Skip to content

Commit bca48e6

Browse files
authored
dolphin: Implement named parameters via sqlc.arg() (#632)
* parser: Update to latest version of forked parser * endtoend: Add sqlc_arg test case * internal: Implement named arguments for MySQL * cleanup
1 parent 3731a92 commit bca48e6

File tree

16 files changed

+294
-8
lines changed

16 files changed

+294
-8
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ require (
1616
vitess.io/vitess v0.0.0-20200617014457-5ba6549015c0
1717
)
1818

19-
replace github.com/pingcap/parser => github.com/kyleconroy/parser v0.0.0-20200727200926-0e04da0a60a6
19+
replace github.com/pingcap/parser => github.com/kyleconroy/parser v0.0.0-20200728181224-b006e3bf3ed9

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,8 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
311311
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
312312
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
313313
github.com/krishicks/yaml-patch v0.0.10/go.mod h1:Sm5TchwZS6sm7RJoyg87tzxm2ZcKzdRE4Q7TjNhPrME=
314-
github.com/kyleconroy/parser v0.0.0-20200727200926-0e04da0a60a6 h1:fryw+mWaV81slq8BqQFia2hlVt1HA4v+8d0UM7VOe7E=
315-
github.com/kyleconroy/parser v0.0.0-20200727200926-0e04da0a60a6/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0=
314+
github.com/kyleconroy/parser v0.0.0-20200728181224-b006e3bf3ed9 h1:rSPG/3/wBoiniDxYd/BsAy+mLIi0MVfZMhXJr7TKVPA=
315+
github.com/kyleconroy/parser v0.0.0-20200728181224-b006e3bf3ed9/go.mod h1:vQdbJqobJAgFyiRNNtXahpMoGWwPEuWciVEK5A20NS0=
316316
github.com/lfittl/pg_query_go v1.0.0 h1:rcHZK5DBEUoxtO6dACP+UVCHKtA1ZsELBW0rSjOXMAE=
317317
github.com/lfittl/pg_query_go v1.0.0/go.mod h1:jcikG62RKf+NIWmbLzjjk73m4x6um2pKf3h+TJyINms=
318318
github.com/lib/pq v1.4.0 h1:TmtCFbH+Aw0AixwyttznSMQDgbR5Yed/Gg6S8Funrhc=

internal/compiler/parse.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
7676
return nil, err
7777
}
7878

79-
raw, namedParams, edits := rewrite.NamedParameters(raw)
79+
raw, namedParams, edits := rewrite.NamedParameters(c.conf.Engine, raw)
8080
rvs := rangeVars(raw.Stmt)
8181
refs := findParameters(raw.Stmt)
8282
if o.UsePositionalParameters {

internal/debug/dump.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ func init() {
1212
Active = os.Getenv("SQLCDEBUG") != ""
1313
}
1414

15-
func Dump(n interface{}) {
15+
func Dump(n ...interface{}) {
1616
if Active {
1717
spew.Dump(n)
1818
}

internal/endtoend/testdata/sqlc_arg/mysql/go/db.go

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/sqlc_arg/mysql/go/models.go

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/sqlc_arg/mysql/go/query.sql.go

Lines changed: 62 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE TABLE foo (name text not null);
2+
3+
/* name: FuncParamIdent :many */
4+
SELECT name FROM foo WHERE name = sqlc.arg(slug);
5+
6+
/* name: FuncParamString :many */
7+
SELECT name FROM foo WHERE name = sqlc.arg('slug');
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"engine": "_dolphin",
6+
"path": "go",
7+
"name": "querytest",
8+
"schema": "query.sql",
9+
"queries": "query.sql"
10+
}
11+
]
12+
}

internal/endtoend/testdata/sqlc_arg/postgresql/go/db.go

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/sqlc_arg/postgresql/go/models.go

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/sqlc_arg/postgresql/go/query.sql.go

Lines changed: 62 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE TABLE foo (name text not null);
2+
3+
-- name: FuncParamIdent :many
4+
SELECT name FROM foo WHERE name = sqlc.arg(slug);
5+
6+
-- name: FuncParamString :many
7+
SELECT name FROM foo WHERE name = sqlc.arg('slug');
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"engine": "postgresql",
6+
"path": "go",
7+
"name": "querytest",
8+
"schema": "query.sql",
9+
"queries": "query.sql"
10+
}
11+
]
12+
}

internal/engine/dolphin/convert.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,34 @@ func (c *cc) convertFieldList(n *pcast.FieldList) *ast.List {
193193
return &ast.List{Items: fields}
194194
}
195195

196+
func (c *cc) convertFuncCallExpr(n *pcast.FuncCallExpr) *ast.FuncCall {
197+
schema := n.Schema.String()
198+
name := n.FnName.String()
199+
200+
// TODO: Deprecate the usage of Funcname
201+
items := []ast.Node{}
202+
if schema != "" {
203+
items = append(items, &pg.String{Str: schema})
204+
}
205+
items = append(items, &pg.String{Str: name})
206+
207+
fn := &ast.FuncCall{
208+
Args: &ast.List{},
209+
Func: &ast.FuncName{
210+
Schema: schema,
211+
Name: name,
212+
},
213+
Funcname: &ast.List{
214+
Items: items,
215+
},
216+
Location: n.Offset,
217+
}
218+
for _, arg := range n.Args {
219+
fn.Args.Items = append(fn.Args.Items, c.convert(arg))
220+
}
221+
return fn
222+
}
223+
196224
func (c *cc) convertInsertStmt(n *pcast.InsertStmt) *pg.InsertStmt {
197225
rels := c.convertTableRefsClause(n.Table)
198226
if len(rels.Items) != 1 {
@@ -322,6 +350,14 @@ func (c *cc) convertUpdateStmt(n *pcast.UpdateStmt) *pg.UpdateStmt {
322350
}
323351
}
324352

353+
func (c *cc) convertValueExpr(n *driver.ValueExpr) *pg.A_Const {
354+
return &pg.A_Const{
355+
Val: &pg.String{
356+
Str: n.Datum.GetString(),
357+
},
358+
}
359+
}
360+
325361
func (c *cc) convertWildCardField(n *pcast.WildCardField) *pg.ColumnRef {
326362
items := []ast.Node{}
327363
if t := n.Table.String(); t != "" {
@@ -342,6 +378,9 @@ func (c *cc) convert(node pcast.Node) ast.Node {
342378
case *driver.ParamMarkerExpr:
343379
return c.convertParamMarkerExpr(n)
344380

381+
case *driver.ValueExpr:
382+
return c.convertValueExpr(n)
383+
345384
case *pcast.AlterTableStmt:
346385
return c.convertAlterTableStmt(n)
347386

@@ -363,6 +402,9 @@ func (c *cc) convert(node pcast.Node) ast.Node {
363402
case *pcast.ExistsSubqueryExpr:
364403
return c.convertExistsSubqueryExpr(n)
365404

405+
case *pcast.FuncCallExpr:
406+
return c.convertFuncCallExpr(n)
407+
366408
case *pcast.InsertStmt:
367409
return c.convertInsertStmt(n)
368410

internal/sql/rewrite/parameters.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package rewrite
33
import (
44
"fmt"
55

6+
"github.com/kyleconroy/sqlc/internal/config"
67
"github.com/kyleconroy/sqlc/internal/source"
78
"github.com/kyleconroy/sqlc/internal/sql/ast"
89
"github.com/kyleconroy/sqlc/internal/sql/ast/pg"
@@ -41,7 +42,7 @@ func isNamedParamSignCast(node ast.Node) bool {
4142
return astutils.Join(expr.Name, ".") == "@" && cast
4243
}
4344

44-
func NamedParameters(raw *ast.RawStmt) (*ast.RawStmt, map[int]string, []source.Edit) {
45+
func NamedParameters(engine config.Engine, raw *ast.RawStmt) (*ast.RawStmt, map[int]string, []source.Edit) {
4546
foundFunc := astutils.Search(raw, named.IsParamFunc)
4647
foundSign := astutils.Search(raw, named.IsParamSign)
4748
if len(foundFunc.Items)+len(foundSign.Items) == 0 {
@@ -72,16 +73,21 @@ func NamedParameters(raw *ast.RawStmt) (*ast.RawStmt, map[int]string, []source.E
7273
})
7374
}
7475
// TODO: This code assumes that sqlc.arg(name) is on a single line
75-
var old string
76+
var old, replace string
7677
if isConst {
7778
old = fmt.Sprintf("sqlc.arg('%s')", param)
7879
} else {
7980
old = fmt.Sprintf("sqlc.arg(%s)", param)
8081
}
82+
if engine == config.EngineMySQL || engine == config.EngineXDolphin {
83+
replace = "?"
84+
} else {
85+
replace = fmt.Sprintf("$%d", args[param])
86+
}
8187
edits = append(edits, source.Edit{
8288
Location: fun.Location - raw.StmtLocation,
8389
Old: old,
84-
New: fmt.Sprintf("$%d", args[param]),
90+
New: replace,
8591
})
8692
return false
8793

0 commit comments

Comments
 (0)