@@ -11,6 +11,7 @@ import (
1111 "os"
1212 "path/filepath"
1313 "runtime/trace"
14+ "slices"
1415 "strings"
1516 "time"
1617
@@ -538,11 +539,23 @@ func (c *checker) checkSQL(ctx context.Context, s config.SQL) error {
538539 req := codeGenRequest (result , combo )
539540 cfg := vetConfig (req )
540541 for i , query := range req .Queries {
541- if result .Queries [i ].Metadata .Flags [QueryFlagSqlcVetDisable ] {
542- if debug .Active {
543- log .Printf ("Skipping vet rules for query: %s\n " , query .Name )
542+ md := result .Queries [i ].Metadata
543+ if md .Flags [QueryFlagSqlcVetDisable ] {
544+ // If the vet disable flag is specified without any rules listed, all rules are ignored.
545+ if len (md .RuleSkiplist ) == 0 {
546+ if debug .Active {
547+ log .Printf ("Skipping all vet rules for query: %s\n " , query .Name )
548+ }
549+ continue
550+ }
551+
552+ // Rules which are listed to be disabled but not declared in the config file are rejected.
553+ for r := range md .RuleSkiplist {
554+ if ! slices .Contains (s .Rules , r ) {
555+ fmt .Fprintf (c .Stderr , "%s: %s: rule-check error: rule %q does not exist in the config file\n " , query .Filename , query .Name , r )
556+ errored = true
557+ }
544558 }
545- continue
546559 }
547560
548561 evalMap := map [string ]any {
@@ -551,74 +564,81 @@ func (c *checker) checkSQL(ctx context.Context, s config.SQL) error {
551564 }
552565
553566 for _ , name := range s .Rules {
554- rule , ok := c .Rules [name ]
555- if ! ok {
556- return fmt .Errorf ("type-check error: a rule with the name '%s' does not exist" , name )
557- }
558-
559- if rule .NeedsPrepare {
560- if prep == nil {
561- fmt .Fprintf (c .Stderr , "%s: %s: %s: error preparing query: database connection required\n " , query .Filename , query .Name , name )
562- errored = true
563- continue
567+ if _ , skip := md .RuleSkiplist [name ]; skip {
568+ if debug .Active {
569+ log .Printf ("Skipping vet rule %q for query: %s\n " , name , query .Name )
564570 }
565- prepName := fmt .Sprintf ("sqlc_vet_%d_%d" , time .Now ().Unix (), i )
566- if err := prep .Prepare (ctx , prepName , query .Text ); err != nil {
567- fmt .Fprintf (c .Stderr , "%s: %s: %s: error preparing query: %s\n " , query .Filename , query .Name , name , err )
568- errored = true
569- continue
571+ } else {
572+ rule , ok := c .Rules [name ]
573+ if ! ok {
574+ return fmt .Errorf ("type-check error: a rule with the name '%s' does not exist" , name )
570575 }
571- }
572576
573- // short-circuit for "sqlc/db-prepare" rule which doesn't have a CEL program
574- if rule .Program == nil {
575- continue
576- }
577-
578- // Get explain output for this query if we need it
579- _ , pgsqlOK := evalMap ["postgresql" ]
580- _ , mysqlOK := evalMap ["mysql" ]
581- if rule .NeedsExplain && ! (pgsqlOK || mysqlOK ) {
582- if expl == nil {
583- fmt .Fprintf (c .Stderr , "%s: %s: %s: error explaining query: database connection required\n " , query .Filename , query .Name , name )
584- errored = true
585- continue
577+ if rule .NeedsPrepare {
578+ if prep == nil {
579+ fmt .Fprintf (c .Stderr , "%s: %s: %s: error preparing query: database connection required\n " , query .Filename , query .Name , name )
580+ errored = true
581+ continue
582+ }
583+ prepName := fmt .Sprintf ("sqlc_vet_%d_%d" , time .Now ().Unix (), i )
584+ if err := prep .Prepare (ctx , prepName , query .Text ); err != nil {
585+ fmt .Fprintf (c .Stderr , "%s: %s: %s: error preparing query: %s\n " , query .Filename , query .Name , name , err )
586+ errored = true
587+ continue
588+ }
586589 }
587- engineOutput , err := expl .Explain (ctx , query .Text , query .Params ... )
588- if err != nil {
589- fmt .Fprintf (c .Stderr , "%s: %s: %s: error explaining query: %s\n " , query .Filename , query .Name , name , err )
590- errored = true
590+
591+ // short-circuit for "sqlc/db-prepare" rule which doesn't have a CEL program
592+ if rule .Program == nil {
591593 continue
592594 }
593595
594- evalMap ["postgresql" ] = engineOutput .PostgreSQL
595- evalMap ["mysql" ] = engineOutput .MySQL
596- }
596+ // Get explain output for this query if we need it
597+ _ , pgsqlOK := evalMap ["postgresql" ]
598+ _ , mysqlOK := evalMap ["mysql" ]
599+ if rule .NeedsExplain && ! (pgsqlOK || mysqlOK ) {
600+ if expl == nil {
601+ fmt .Fprintf (c .Stderr , "%s: %s: %s: error explaining query: database connection required\n " , query .Filename , query .Name , name )
602+ errored = true
603+ continue
604+ }
605+ engineOutput , err := expl .Explain (ctx , query .Text , query .Params ... )
606+ if err != nil {
607+ fmt .Fprintf (c .Stderr , "%s: %s: %s: error explaining query: %s\n " , query .Filename , query .Name , name , err )
608+ errored = true
609+ continue
610+ }
611+
612+ evalMap ["postgresql" ] = engineOutput .PostgreSQL
613+ evalMap ["mysql" ] = engineOutput .MySQL
614+ }
597615
598- if debug .Debug .DumpVetEnv {
599- fmt .Printf ("vars for rule '%s' evaluating against query '%s':\n " , name , query .Name )
600- debug .DumpAsJSON (evalMap )
601- }
616+ if debug .Debug .DumpVetEnv {
617+ fmt .Printf ("vars for rule '%s' evaluating against query '%s':\n " , name , query .Name )
618+ debug .DumpAsJSON (evalMap )
619+ }
602620
603- out , _ , err := (* rule .Program ).Eval (evalMap )
604- if err != nil {
605- return err
606- }
607- tripped , ok := out .Value ().(bool )
608- if ! ok {
609- return fmt .Errorf ("expression returned non-bool value: %v" , out .Value ())
610- }
611- if tripped {
612- // TODO: Get line numbers in the output
613- if rule .Message == "" {
614- fmt .Fprintf (c .Stderr , "%s: %s: %s\n " , query .Filename , query .Name , name )
615- } else {
616- fmt .Fprintf (c .Stderr , "%s: %s: %s: %s\n " , query .Filename , query .Name , name , rule .Message )
621+ out , _ , err := (* rule .Program ).Eval (evalMap )
622+ if err != nil {
623+ return err
624+ }
625+ tripped , ok := out .Value ().(bool )
626+ if ! ok {
627+ return fmt .Errorf ("expression returned non-bool value: %v" , out .Value ())
628+ }
629+ if tripped {
630+ // TODO: Get line numbers in the output
631+ if rule .Message == "" {
632+ fmt .Fprintf (c .Stderr , "%s: %s: %s\n " , query .Filename , query .Name , name )
633+ } else {
634+ fmt .Fprintf (c .Stderr , "%s: %s: %s: %s\n " , query .Filename , query .Name , name , rule .Message )
635+ }
636+ errored = true
617637 }
618- errored = true
619638 }
620639 }
621640 }
641+
622642 if errored {
623643 return ErrFailedChecks
624644 }
0 commit comments