@@ -12,15 +12,32 @@ import (
1212 "github.com/sqlc-dev/sqlc/internal/source"
1313 "github.com/sqlc-dev/sqlc/internal/sql/ast"
1414 "github.com/sqlc-dev/sqlc/internal/sql/astutils"
15+ "github.com/sqlc-dev/sqlc/internal/sql/preprocess"
1516 "github.com/sqlc-dev/sqlc/internal/sql/validate"
1617 "github.com/sqlc-dev/sqlc/internal/sqlcdebug"
1718)
1819
1920var debugDumpAST = sqlcdebug .New ("dumpast" )
2021
21- func (c * Compiler ) parseQuery (stmt ast.Node , src string , o opts.Parser ) (* Query , error ) {
22+ func (c * Compiler ) parseQuery (stmt ast.Node , pp * preprocess.Result , o opts.Parser ) (* Query , error ) {
23+ raw , ok := stmt .(* ast.RawStmt )
24+ if ! ok {
25+ return nil , errors .New ("node is not a statement" )
26+ }
27+
28+ // The preprocessor already replaced every sqlc.* construct with native SQL
29+ // and recorded what it replaced.
30+ pre := pp .Statement (raw .StmtLocation )
31+ if pre .Err != nil {
32+ return nil , pre .Err
33+ }
34+
35+ // Engines number bind parameters in whatever order they convert the AST.
36+ // Restore the numbering the preprocessor assigned in source order.
37+ renumberParams (raw , pre .Numbers )
38+
2239 if c .coreCatalog != nil {
23- return c .parseQueryCore (stmt , src )
40+ return c .parseQueryCore (raw , pp . Text , pre )
2441 }
2542
2643 ctx := context .Background ()
@@ -29,18 +46,7 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
2946 debug .Dump (stmt )
3047 }
3148
32- // validate sqlc-specific syntax
33- if err := validate .SqlcFunctions (stmt ); err != nil {
34- return nil , err
35- }
36-
37- // rewrite queries to remove sqlc.* functions
38-
39- raw , ok := stmt .(* ast.RawStmt )
40- if ! ok {
41- return nil , errors .New ("node is not a statement" )
42- }
43- rawSQL , err := source .Pluck (src , raw .StmtLocation , raw .StmtLen )
49+ rawSQL , err := source .Pluck (pp .Text , raw .StmtLocation , raw .StmtLen )
4450 if err != nil {
4551 return nil , err
4652 }
@@ -128,7 +134,7 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
128134 Query : expandedQuery ,
129135 }
130136 } else if c .analyzer != nil {
131- inference , _ := c .inferQuery (raw , rawSQL )
137+ inference , _ := c .inferQuery (raw , rawSQL , pre )
132138 if inference == nil {
133139 inference = & analysis {}
134140 }
@@ -156,7 +162,7 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
156162 // FOOTGUN: combineAnalysis mutates inference
157163 anlys = combineAnalysis (inference , result )
158164 } else {
159- anlys , err = c .analyzeQuery (raw , rawSQL )
165+ anlys , err = c .analyzeQuery (raw , rawSQL , pre )
160166 if err != nil {
161167 return nil , err
162168 }
@@ -188,6 +194,23 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
188194 }, nil
189195}
190196
197+ // renumberParams applies the parameter numbers the preprocessor assigned,
198+ // matching each node by the location of its placeholder in the query text.
199+ func renumberParams (raw * ast.RawStmt , numbers map [int ]int ) {
200+ if len (numbers ) == 0 {
201+ return
202+ }
203+ astutils .Walk (astutils .VisitorFunc (func (node ast.Node ) {
204+ ref , ok := node .(* ast.ParamRef )
205+ if ! ok {
206+ return
207+ }
208+ if n , ok := numbers [ref .Location ]; ok {
209+ ref .Number = n
210+ }
211+ }), raw )
212+ }
213+
191214func rangeVars (root ast.Node ) []* ast.RangeVar {
192215 var vars []* ast.RangeVar
193216 find := astutils .VisitorFunc (func (node ast.Node ) {
0 commit comments