Skip to content

Expose source_tables on the plugin Query message#4472

Closed
Prateeks16 wants to merge 1 commit into
sqlc-dev:mainfrom
Prateeks16:claude/expose-query-source-tables
Closed

Expose source_tables on the plugin Query message#4472
Prateeks16 wants to merge 1 commit into
sqlc-dev:mainfrom
Prateeks16:claude/expose-query-source-tables

Conversation

@Prateeks16
Copy link
Copy Markdown

What

Adds a source_tables field to the plugin Query message: the list of base tables a query reads from, deduplicated and sorted ascending.

Why

Plugins currently learn a query's tables only through Query.columns[].table, which covers only tables that contribute a column to the output. A table referenced solely in a JOIN, a subquery, or a common table expression body is invisible to plugins even though the query depends on it. Plugins that build reactive/refetch logic (for example keyed off SQLite's update_hook) need a query's full read set, not just its output columns.

What's included

  • source_tables field on the Query proto (and regenerated codegen.pb.go).
  • The compiler resolves the read set from the statement AST: every base table in a FROM, a JOIN, or a subquery in any clause, including CTE bodies. Common table expression names and the target relations of INSERT/UPDATE/DELETE/TRUNCATE are excluded.
  • A unit test (internal/compiler) covering the example below plus deduplication, write-target exclusion, and the no-tables case. The existing JSON codegen goldens are regenerated to include the new field.

For this query:

WITH filtered_accounts AS (
    SELECT account_id FROM accounts WHERE accounts.space_id = $1
    AND NOT EXISTS (SELECT 1 FROM account_tags t WHERE t.account_id = accounts.account_id)
)
SELECT acc.* FROM accounts acc
JOIN filtered_accounts fa ON acc.account_id = fa.account_id
LEFT JOIN transactions t ON t.debit_account_id = acc.account_id;

source_tables is ["account_tags", "accounts", "transactions"]: accounts appears once (read in the CTE body and the outer query), account_tags appears though it is read only inside a NOT EXISTS subquery, transactions appears though it projects no column, and filtered_accounts is excluded as a CTE name.

🤖 Generated with Claude Code

Plugins receive Query.columns[].table, which only covers tables that
contribute a column to a query's output. Tables referenced only in a
JOIN, a subquery, or a common table expression body are invisible to
plugins, even though the query depends on them (issue sqlc-dev#4434).

Add a source_tables field to the plugin Query message listing every base
table a query reads from, deduplicated and sorted. Common table
expression names and the target relations of INSERT, UPDATE, DELETE, and
TRUNCATE statements are excluded.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 7, 2026 10:50
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds “source tables” metadata to compiled queries and exposes it through the plugin/codegen JSON output.

Changes:

  • Extends plugin.Query proto + JSON fixtures with a new source_tables field.
  • Implements sourceTableNames in the compiler to extract read-dependencies (CTEs included, write targets excluded).
  • Adds unit tests covering key dependency patterns (CTEs, joins, dedup across aliases, INSERT read vs write target).

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
protos/plugin/codegen.proto Adds source_tables to Query message for plugin consumers
internal/compiler/source_tables.go Implements dependency extraction for base tables read by a statement
internal/compiler/source_tables_test.go Adds unit tests for sourceTableNames behavior
internal/compiler/query.go Adds SourceTables field to compiler Query model
internal/compiler/parse.go Populates SourceTables when parsing queries
internal/cmd/shim.go Plumbs compiler SourceTables into plugin Query
internal/endtoend/testdata/process_plugin_sqlc_gen_json/gen/codegen.json Updates golden JSON outputs to include source_tables
internal/endtoend/testdata/codegen_json/gen/codegen.json Updates golden JSON outputs to include source_tables
Files not reviewed (1)
  • internal/plugin/codegen.pb.go: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +10 to +12
// sourceTableNames returns the sorted, deduplicated names of the base tables a
// statement reads from. It covers every table referenced in a FROM, a JOIN, or
// a subquery in any clause, including the bodies of common table expressions.
Comment on lines +55 to +62
if _, ok := cteNames[table.Name]; ok {
continue
}
if _, ok := seen[table.Name]; ok {
continue
}
seen[table.Name] = struct{}{}
names = append(names, table.Name)
Comment on lines +11 to +44
func TestSourceTableNames(t *testing.T) {
for _, tc := range []struct {
name string
sql string
want []string
}{
{
name: "cte, join and subquery dependencies",
sql: `WITH filtered_accounts AS (
SELECT account_id FROM accounts WHERE accounts.space_id = $1
AND NOT EXISTS (
SELECT 1 FROM account_tags t WHERE t.account_id = accounts.account_id
)
)
SELECT acc.* FROM accounts acc
JOIN filtered_accounts fa ON acc.account_id = fa.account_id
LEFT JOIN transactions t ON t.debit_account_id = acc.account_id`,
want: []string{"account_tags", "accounts", "transactions"},
},
{
name: "deduplicated across aliases",
sql: `SELECT a1.account_id FROM accounts a1 JOIN accounts a2 ON a1.space_id = a2.space_id`,
want: []string{"accounts"},
},
{
name: "insert excludes write target, includes read",
sql: `INSERT INTO audit_log (account_id) SELECT account_id FROM accounts`,
want: []string{"accounts"},
},
{
name: "no base tables",
sql: `SELECT 1`,
want: nil,
},
@Prateeks16
Copy link
Copy Markdown
Author

Replaced by a clean branch.

@Prateeks16 Prateeks16 closed this Jun 7, 2026
@Prateeks16 Prateeks16 deleted the claude/expose-query-source-tables branch June 7, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants