@@ -3,11 +3,12 @@ package expander
33import (
44 "context"
55 "database/sql"
6+ "database/sql/driver"
67 "fmt"
78 "os"
89 "testing"
910
10- _ "github.com/go-sql-driver/mysql"
11+ "github.com/go-sql-driver/mysql"
1112 "github.com/jackc/pgx/v5/pgxpool"
1213 "github.com/ncruces/go-sqlite3"
1314 _ "github.com/ncruces/go-sqlite3/embed"
@@ -42,28 +43,46 @@ func (g *PostgreSQLColumnGetter) GetColumnNames(ctx context.Context, query strin
4243 return columns , nil
4344}
4445
45- // MySQLColumnGetter implements ColumnGetter for MySQL using database/sql .
46+ // MySQLColumnGetter implements ColumnGetter for MySQL using the forked driver's StmtMetadata .
4647type MySQLColumnGetter struct {
4748 db * sql.DB
4849}
4950
5051func (g * MySQLColumnGetter ) GetColumnNames (ctx context.Context , query string ) ([]string , error ) {
51- // Prepare the statement to validate the query and get column metadata
52- stmt , err := g .db .PrepareContext (ctx , query )
52+ conn , err := g .db .Conn (ctx )
5353 if err != nil {
5454 return nil , err
5555 }
56- defer stmt .Close ()
56+ defer conn .Close ()
5757
58- // Execute to get column metadata from database/sql.
59- // database/sql doesn't expose column names from prepared statements directly.
60- rows , err := stmt .QueryContext (ctx )
58+ var columns []string
59+ err = conn .Raw (func (driverConn any ) error {
60+ preparer , ok := driverConn .(driver.ConnPrepareContext )
61+ if ! ok {
62+ return fmt .Errorf ("driver connection does not support PrepareContext" )
63+ }
64+
65+ stmt , err := preparer .PrepareContext (ctx , query )
66+ if err != nil {
67+ return err
68+ }
69+ defer stmt .Close ()
70+
71+ meta , ok := stmt .(mysql.StmtMetadata )
72+ if ! ok {
73+ return fmt .Errorf ("prepared statement does not implement StmtMetadata" )
74+ }
75+
76+ for _ , col := range meta .ColumnMetadata () {
77+ columns = append (columns , col .Name )
78+ }
79+ return nil
80+ })
6181 if err != nil {
6282 return nil , err
6383 }
64- defer rows .Close ()
6584
66- return rows . Columns ()
85+ return columns , nil
6786}
6887
6988// SQLiteColumnGetter implements ColumnGetter for SQLite using the native ncruces/go-sqlite3 API.
@@ -133,7 +152,7 @@ func TestExpandPostgreSQL(t *testing.T) {
133152 {
134153 name : "simple select star" ,
135154 query : "SELECT * FROM authors" ,
136- expected : "SELECT id,name,bio FROM authors;" ,
155+ expected : "SELECT id, name, bio FROM authors;" ,
137156 },
138157 {
139158 name : "select with no star" ,
@@ -143,52 +162,52 @@ func TestExpandPostgreSQL(t *testing.T) {
143162 {
144163 name : "select star with where clause" ,
145164 query : "SELECT * FROM authors WHERE id = 1" ,
146- expected : "SELECT id,name,bio FROM authors WHERE id = 1;" ,
165+ expected : "SELECT id, name, bio FROM authors WHERE id = 1;" ,
147166 },
148167 {
149168 name : "double star" ,
150169 query : "SELECT *, * FROM authors" ,
151- expected : "SELECT id,name,bio,id,name,bio FROM authors;" ,
170+ expected : "SELECT id, name, bio, id, name, bio FROM authors;" ,
152171 },
153172 {
154173 name : "table qualified star" ,
155174 query : "SELECT authors.* FROM authors" ,
156- expected : "SELECT authors.id,authors.name,authors.bio FROM authors;" ,
175+ expected : "SELECT authors.id, authors.name, authors.bio FROM authors;" ,
157176 },
158177 {
159178 name : "star in middle of columns" ,
160179 query : "SELECT id, *, name FROM authors" ,
161- expected : "SELECT id,id,name,bio,name FROM authors;" ,
180+ expected : "SELECT id, id, name, bio, name FROM authors;" ,
162181 },
163182 {
164183 name : "insert returning star" ,
165184 query : "INSERT INTO authors (name, bio) VALUES ('John', 'A writer') RETURNING *" ,
166- expected : "INSERT INTO authors (name,bio) VALUES ('John','A writer') RETURNING id,name,bio;" ,
185+ expected : "INSERT INTO authors (name, bio) VALUES ('John', 'A writer') RETURNING id, name, bio;" ,
167186 },
168187 {
169188 name : "insert returning mixed" ,
170189 query : "INSERT INTO authors (name, bio) VALUES ('John', 'A writer') RETURNING id, *" ,
171- expected : "INSERT INTO authors (name,bio) VALUES ('John','A writer') RETURNING id,id,name,bio;" ,
190+ expected : "INSERT INTO authors (name, bio) VALUES ('John', 'A writer') RETURNING id, id, name, bio;" ,
172191 },
173192 {
174193 name : "update returning star" ,
175194 query : "UPDATE authors SET name = 'Jane' WHERE id = 1 RETURNING *" ,
176- expected : "UPDATE authors SET name = 'Jane' WHERE id = 1 RETURNING id,name,bio;" ,
195+ expected : "UPDATE authors SET name = 'Jane' WHERE id = 1 RETURNING id, name, bio;" ,
177196 },
178197 {
179198 name : "delete returning star" ,
180199 query : "DELETE FROM authors WHERE id = 1 RETURNING *" ,
181- expected : "DELETE FROM authors WHERE id = 1 RETURNING id,name,bio;" ,
200+ expected : "DELETE FROM authors WHERE id = 1 RETURNING id, name, bio;" ,
182201 },
183202 {
184203 name : "cte with select star" ,
185204 query : "WITH a AS (SELECT * FROM authors) SELECT * FROM a" ,
186- expected : "WITH a AS (SELECT id,name,bio FROM authors) SELECT id,name,bio FROM a;" ,
205+ expected : "WITH a AS (SELECT id, name, bio FROM authors) SELECT id, name, bio FROM a;" ,
187206 },
188207 {
189208 name : "multiple ctes with dependency" ,
190209 query : "WITH a AS (SELECT * FROM authors), b AS (SELECT * FROM a) SELECT * FROM b" ,
191- expected : "WITH a AS (SELECT id,name,bio FROM authors), b AS (SELECT id,name,bio FROM a) SELECT id,name,bio FROM b;" ,
210+ expected : "WITH a AS (SELECT id, name, bio FROM authors), b AS (SELECT id, name, bio FROM a) SELECT id, name, bio FROM b;" ,
192211 },
193212 {
194213 name : "count star not expanded" ,
@@ -285,7 +304,7 @@ func TestExpandMySQL(t *testing.T) {
285304 {
286305 name : "simple select star" ,
287306 query : "SELECT * FROM authors" ,
288- expected : "SELECT id,name,bio FROM authors;" ,
307+ expected : "SELECT id, name, bio FROM authors;" ,
289308 },
290309 {
291310 name : "select with no star" ,
@@ -295,22 +314,22 @@ func TestExpandMySQL(t *testing.T) {
295314 {
296315 name : "select star with where clause" ,
297316 query : "SELECT * FROM authors WHERE id = 1" ,
298- expected : "SELECT id,name,bio FROM authors WHERE id = 1;" ,
317+ expected : "SELECT id, name, bio FROM authors WHERE id = 1;" ,
299318 },
300319 {
301320 name : "table qualified star" ,
302321 query : "SELECT authors.* FROM authors" ,
303- expected : "SELECT authors.id,authors.name,authors.bio FROM authors;" ,
322+ expected : "SELECT authors.id, authors.name, authors.bio FROM authors;" ,
304323 },
305324 {
306325 name : "double table qualified star" ,
307326 query : "SELECT authors.*, authors.* FROM authors" ,
308- expected : "SELECT authors.id,authors.name,authors.bio,authors.id,authors.name,authors.bio FROM authors;" ,
327+ expected : "SELECT authors.id, authors.name, authors.bio, authors.id, authors.name, authors.bio FROM authors;" ,
309328 },
310329 {
311330 name : "star in middle of columns table qualified" ,
312331 query : "SELECT id, authors.*, name FROM authors" ,
313- expected : "SELECT id,authors.id,authors.name,authors.bio,name FROM authors;" ,
332+ expected : "SELECT id, authors.id, authors.name, authors.bio, name FROM authors;" ,
314333 },
315334 {
316335 name : "count star not expanded" ,
@@ -374,7 +393,7 @@ func TestExpandSQLite(t *testing.T) {
374393 {
375394 name : "simple select star" ,
376395 query : "SELECT * FROM authors" ,
377- expected : "SELECT id,name,bio FROM authors;" ,
396+ expected : "SELECT id, name, bio FROM authors;" ,
378397 },
379398 {
380399 name : "select with no star" ,
@@ -384,22 +403,22 @@ func TestExpandSQLite(t *testing.T) {
384403 {
385404 name : "select star with where clause" ,
386405 query : "SELECT * FROM authors WHERE id = 1" ,
387- expected : "SELECT id,name,bio FROM authors WHERE id = 1;" ,
406+ expected : "SELECT id, name, bio FROM authors WHERE id = 1;" ,
388407 },
389408 {
390409 name : "double star" ,
391410 query : "SELECT *, * FROM authors" ,
392- expected : "SELECT id,name,bio,id,name,bio FROM authors;" ,
411+ expected : "SELECT id, name, bio, id, name, bio FROM authors;" ,
393412 },
394413 {
395414 name : "table qualified star" ,
396415 query : "SELECT authors.* FROM authors" ,
397- expected : "SELECT authors.id,authors.name,authors.bio FROM authors;" ,
416+ expected : "SELECT authors.id, authors.name, authors.bio FROM authors;" ,
398417 },
399418 {
400419 name : "star in middle of columns" ,
401420 query : "SELECT id, *, name FROM authors" ,
402- expected : "SELECT id,id,name,bio,name FROM authors;" ,
421+ expected : "SELECT id, id, name, bio, name FROM authors;" ,
403422 },
404423 {
405424 name : "count star not expanded" ,
0 commit comments