From ec26aceecd4b6571e2b84baf555bf0634d9b9d05 Mon Sep 17 00:00:00 2001 From: Svetlin Ralchev Date: Mon, 8 Jun 2026 08:06:03 +0400 Subject: [PATCH 1/2] feat: add options.tables.include allow-list Add an include allow-list alongside the existing exclude deny-list. When include is non-empty, only the listed tables are generated; an empty include matches all tables. Exclude always takes precedence over include. Both lists match unqualified and schema-qualified table names. Selection is unified in a single tableSelected predicate. --- README.md | 13 +++++++--- internal/sqlc/config.go | 34 +++++++++++++++++++++++--- internal/sqlc/config_test.go | 43 +++++++++++++++++++++++++++++++++ internal/sqlc/generator.go | 3 ++- internal/sqlc/generator_test.go | 43 +++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 162d9d0..385bed9 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,9 @@ sql: out: "ent/query" options: tables: + include: + - "users" + - "auth.accounts" exclude: - "audit_logs" - "auth.sessions" @@ -68,9 +71,13 @@ sql: - "GetUserWithPost" ``` -Use `options.tables.exclude` to skip generating query files for tables that -should not be managed by sqlc. Entries may be table names (`audit_logs`) or -schema-qualified table names (`auth.sessions`). +Use `options.tables` to control which tables get query files. Entries may be +table names (`audit_logs`) or schema-qualified table names (`auth.sessions`). + +- `include` is an allow-list: when non-empty, only the listed tables are + generated. When omitted or empty, every table is generated. +- `exclude` is a deny-list that always takes precedence over `include`, so a + table present in both lists is skipped. ### Default queries (always generated) diff --git a/internal/sqlc/config.go b/internal/sqlc/config.go index 2b4e417..518cc10 100644 --- a/internal/sqlc/config.go +++ b/internal/sqlc/config.go @@ -76,7 +76,10 @@ type CodegenOptions struct { } // TableOptions holds table-level filtering options for the gen-queries plugin. +// Include is an allow-list: when non-empty, only the listed tables are +// generated. Exclude is a deny-list that always takes precedence over Include. type TableOptions struct { + Include []string `yaml:"include,omitempty"` Exclude []string `yaml:"exclude,omitempty"` } @@ -102,8 +105,20 @@ func (s *SQL) GetQueriesSet() map[string]bool { return querySet } -// GetExcludeSet returns a set of table names to skip during query generation. -// Entries may be unqualified table names or schema-qualified names. +// GetIncludeSet returns the allow-list of table names for query generation. +// Entries may be unqualified table names or schema-qualified names. An empty +// set means every table is included. +func (s *SQL) GetIncludeSet() map[string]bool { + opts := s.GetOptions() + includeSet := make(map[string]bool, len(opts.Tables.Include)) + for _, name := range opts.Tables.Include { + includeSet[name] = true + } + return includeSet +} + +// GetExcludeSet returns the deny-list of table names to skip during query +// generation. Entries may be unqualified table names or schema-qualified names. func (s *SQL) GetExcludeSet() map[string]bool { opts := s.GetOptions() excludeSet := make(map[string]bool, len(opts.Tables.Exclude)) @@ -113,6 +128,17 @@ func (s *SQL) GetExcludeSet() map[string]bool { return excludeSet } -func tableExcluded(excludeSet map[string]bool, schema, table string) bool { - return excludeSet[table] || excludeSet[schema+"."+table] +// tableSelected reports whether a table should have query files generated. +// Exclude always takes precedence over include; an empty include set matches +// every table. Both sets are checked against the unqualified table name and +// the schema-qualified name (schema.table). +func tableSelected(includeSet, excludeSet map[string]bool, schema, table string) bool { + qualified := schema + "." + table + if excludeSet[table] || excludeSet[qualified] { + return false + } + if len(includeSet) == 0 { + return true + } + return includeSet[table] || includeSet[qualified] } diff --git a/internal/sqlc/config_test.go b/internal/sqlc/config_test.go index b612225..d4a21b4 100644 --- a/internal/sqlc/config_test.go +++ b/internal/sqlc/config_test.go @@ -190,4 +190,47 @@ var _ = Describe("Config", func() { Expect(excludeSet["posts"]).To(BeFalse()) }) }) + + Describe("SQL.GetIncludeSet", func() { + It("returns an empty map when codegen is nil", func() { + sql := sqlc.SQL{} + includeSet := sql.GetIncludeSet() + Expect(includeSet).NotTo(BeNil()) + Expect(includeSet).To(BeEmpty()) + }) + + It("returns an empty map when include is empty", func() { + sql := sqlc.SQL{ + Codegen: []sqlc.Codegen{ + { + Plugin: "gen-queries", + Out: "out", + Options: sqlc.CodegenOptions{Tables: sqlc.TableOptions{Include: []string{}}}, + }, + }, + } + includeSet := sql.GetIncludeSet() + Expect(includeSet).NotTo(BeNil()) + Expect(includeSet).To(BeEmpty()) + }) + + It("returns a map with included table names", func() { + sql := sqlc.SQL{ + Codegen: []sqlc.Codegen{ + { + Plugin: "gen-queries", + Out: "out", + Options: sqlc.CodegenOptions{ + Tables: sqlc.TableOptions{Include: []string{"users", "analytics.events"}}, + }, + }, + }, + } + includeSet := sql.GetIncludeSet() + Expect(includeSet).To(HaveLen(2)) + Expect(includeSet["users"]).To(BeTrue()) + Expect(includeSet["analytics.events"]).To(BeTrue()) + Expect(includeSet["posts"]).To(BeFalse()) + }) + }) }) diff --git a/internal/sqlc/generator.go b/internal/sqlc/generator.go index 3a3437c..86dedec 100644 --- a/internal/sqlc/generator.go +++ b/internal/sqlc/generator.go @@ -162,11 +162,12 @@ func (x *Generator) Generate() error { } queries := config.GetQueriesSet() + include := config.GetIncludeSet() exclude := config.GetExcludeSet() for _, schema := range x.Catalog.Schemas { for _, table := range schema.Tables { - if tableExcluded(exclude, schema.Name, table.Name) { + if !tableSelected(include, exclude, schema.Name, table.Name) { continue } diff --git a/internal/sqlc/generator_test.go b/internal/sqlc/generator_test.go index 0f4c465..82feded 100644 --- a/internal/sqlc/generator_test.go +++ b/internal/sqlc/generator_test.go @@ -70,6 +70,49 @@ var _ = Describe("Generator", func() { } }) + It("generates only included tables", func() { + dir := generator.Config.SQL[0].Queries + generator.Config.SQL[0].Codegen = []sqlc.Codegen{ + { + Plugin: "gen-queries", + Out: dir, + Options: sqlc.CodegenOptions{ + Tables: sqlc.TableOptions{Include: []string{"public.users"}}, + }, + }, + } + + Expect(generator.Generate()).NotTo(HaveOccurred()) + + for _, config := range generator.Config.SQL { + Expect(filepath.Join(config.Queries, "users.sql")).To(BeAnExistingFile()) + Expect(filepath.Join(config.Queries, "posts.sql")).NotTo(BeAnExistingFile()) + } + }) + + It("excludes tables even when they are included", func() { + dir := generator.Config.SQL[0].Queries + generator.Config.SQL[0].Codegen = []sqlc.Codegen{ + { + Plugin: "gen-queries", + Out: dir, + Options: sqlc.CodegenOptions{ + Tables: sqlc.TableOptions{ + Include: []string{"users", "posts"}, + Exclude: []string{"posts"}, + }, + }, + }, + } + + Expect(generator.Generate()).NotTo(HaveOccurred()) + + for _, config := range generator.Config.SQL { + Expect(filepath.Join(config.Queries, "users.sql")).To(BeAnExistingFile()) + Expect(filepath.Join(config.Queries, "posts.sql")).NotTo(BeAnExistingFile()) + } + }) + It("generates valid SQL content with default PK queries", func() { err := generator.Generate() Expect(err).NotTo(HaveOccurred()) From 8f512983f5ebbe68df3d6c100a97f97c9644da23 Mon Sep 17 00:00:00 2001 From: Svetlin Ralchev Date: Mon, 8 Jun 2026 08:17:06 +0400 Subject: [PATCH 2/2] fix(flake): refresh vendorHash after gomod bumps go.mod was bumped (inflect, ginkgo, gomega, urfave/cli) without regenerating the Nix vendorHash, causing buildGoModule to build against a stale vendor dir and fail with inconsistent vendoring. --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 5e4da07..95824eb 100644 --- a/flake.nix +++ b/flake.nix @@ -20,7 +20,7 @@ inherit version; src = pkgs.lib.cleanSource ./.; subPackages = [ "cmd/sqlc-gen-queries" ]; - vendorHash = "sha256-+p3CtZbFv2NQV8d2HI1wFBW2jbn4a9kc3+6qtjoLl8c="; + vendorHash = "sha256-DJWhLrSOSAy1VjJS9BjVYqws8nQShWr7Y89vjWDO8VQ="; doInstallCheck = true; installCheckPhase = '' $out/bin/sqlc-gen-queries --help