Commit 21e6557
feat(expander): Add star expander for SELECT * and RETURNING * (PostgreSQL, MySQL, SQLite) (#4203)
* feat(postgresql): Add star expander for SELECT * and RETURNING *
Adds a new expander package that expands * expressions in SQL queries
to explicit column names by preparing the query against a PostgreSQL
database.
Features:
- Expands SELECT * to explicit column list
- Preserves table prefix for qualified stars (e.g., table.*)
- Handles RETURNING * in INSERT/UPDATE/DELETE statements
- Recursively expands CTEs, including dependent CTEs
- Supports subqueries in FROM clause
- Works with both cgo (pganalyze/pg_query_go) and non-cgo
(wasilibs/go-pgquery) builds
Example:
SELECT * FROM authors
→ SELECT id, name, bio FROM authors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(expander): port expander to use internal AST types
Move expander from internal/engine/postgresql/expander to internal/x/expander
and port it to use the internal AST types instead of pg_query nodes.
Key changes:
- Use internal AST types (*ast.SelectStmt, *ast.InsertStmt, etc.)
- Use astutils.Search for star detection
- Use ast.Format instead of pg_query deparse
- Add Parser interface for dependency injection
- Add test cases for COUNT(*) (should not be expanded)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(expander): add MySQL support and use ColumnGetter interface
- Rename TestExpand to TestExpandPostgreSQL
- Add TestExpandMySQL for MySQL database support
- Replace pgxpool.Pool with ColumnGetter interface for database-agnostic column resolution
- Add PostgreSQLColumnGetter and MySQLColumnGetter implementations
- MySQL tests skip edge cases (double star, star in middle) due to intermediate query formatting issues
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(expander): use valid MySQL syntax for edge case tests
MySQL doesn't support unqualified `*` mixed with other columns (e.g.,
`SELECT *, *` or `SELECT id, *, name`). These are valid PostgreSQL
but invalid MySQL syntax.
Update MySQL tests to use table-qualified stars which are valid:
- `SELECT authors.*, authors.*` instead of `SELECT *, *`
- `SELECT id, authors.*, name` instead of `SELECT id, *, name`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(expander): add SQLite support
- Add TestExpandSQLite with 8 test cases using in-memory SQLite database
- Rename MySQLColumnGetter to SQLColumnGetter since both MySQL and SQLite
use the same database/sql-based implementation
- SQLite supports the same star syntax as PostgreSQL (including `SELECT *, *`
and `SELECT id, *, name`)
Test results:
- PostgreSQL: 14 tests
- MySQL: 8 tests
- SQLite: 8 tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(expander): use PrepareContext in SQLColumnGetter
Use PrepareContext to validate the query before executing it to get
column metadata. While database/sql doesn't expose column names from
prepared statements directly (unlike pgx), this at least validates
the SQL syntax before execution.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(expander): use native ncruces/go-sqlite3 API for column names
Use the native sqlite3.Conn.Prepare and stmt.ColumnName/ColumnCount APIs
to get column names without executing the query. This is more efficient
and consistent with how PostgreSQL handles it.
Changes:
- Add SQLiteColumnGetter using native sqlite3.Conn
- Rename SQLColumnGetter to MySQLColumnGetter (MySQL still needs to execute)
- SQLite test now uses sqlite3.Open instead of sql.Open
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(expander): use forked MySQL driver and fix list formatting
- Update MySQLColumnGetter to use github.com/sqlc-dev/mysql fork with
StmtMetadata interface for getting column names via prepare
- Add replace directive to go.mod for the forked MySQL driver
- Fix list formatting to use ", " separator instead of "," for proper
SQL spacing (e.g., "SELECT id, name, bio" instead of "SELECT id,name,bio")
- Update test expectations to reflect proper spacing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent ebd32cf commit 21e6557
File tree
5 files changed
+958
-3
lines changed- internal
- sql/ast
- x/expander
5 files changed
+958
-3
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
64 | 64 | | |
65 | 65 | | |
66 | 66 | | |
| 67 | + | |
| 68 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
30 | | - | |
31 | 29 | | |
32 | 30 | | |
33 | 31 | | |
| |||
159 | 157 | | |
160 | 158 | | |
161 | 159 | | |
| 160 | + | |
| 161 | + | |
162 | 162 | | |
163 | 163 | | |
164 | 164 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
| 17 | + | |
18 | 18 | | |
0 commit comments