From eec37da61cc2476448dcd56232f740d43f6c5a77 Mon Sep 17 00:00:00 2001 From: Pickle Rick Date: Sat, 7 Mar 2026 18:08:03 +0000 Subject: [PATCH 1/2] feat(sqlite): disable positional indexing when sqlc.slice is present --- .../testdata/issue_4213_reuse/sqlite/go/db.go | 31 ++++++++++ .../issue_4213_reuse/sqlite/go/models.go | 11 ++++ .../issue_4213_reuse/sqlite/go/query.sql.go | 58 +++++++++++++++++++ .../issue_4213_reuse/sqlite/query.sql | 3 + .../issue_4213_reuse/sqlite/schema.sql | 5 ++ .../issue_4213_reuse/sqlite/sqlc.json | 16 +++++ .../sqlc_slice/sqlite/go/query.sql.go | 6 +- .../sqlite/go/query.sql.go | 2 +- internal/sql/rewrite/parameters.go | 27 ++++++++- 9 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 internal/endtoend/testdata/issue_4213_reuse/sqlite/go/db.go create mode 100644 internal/endtoend/testdata/issue_4213_reuse/sqlite/go/models.go create mode 100644 internal/endtoend/testdata/issue_4213_reuse/sqlite/go/query.sql.go create mode 100644 internal/endtoend/testdata/issue_4213_reuse/sqlite/query.sql create mode 100644 internal/endtoend/testdata/issue_4213_reuse/sqlite/schema.sql create mode 100644 internal/endtoend/testdata/issue_4213_reuse/sqlite/sqlc.json diff --git a/internal/endtoend/testdata/issue_4213_reuse/sqlite/go/db.go b/internal/endtoend/testdata/issue_4213_reuse/sqlite/go/db.go new file mode 100644 index 0000000000..3b320aa168 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_reuse/sqlite/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/issue_4213_reuse/sqlite/go/models.go b/internal/endtoend/testdata/issue_4213_reuse/sqlite/go/models.go new file mode 100644 index 0000000000..caf7eaf1e8 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_reuse/sqlite/go/models.go @@ -0,0 +1,11 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +type Mytable struct { + ID int64 + Typ int64 + Name string +} diff --git a/internal/endtoend/testdata/issue_4213_reuse/sqlite/go/query.sql.go b/internal/endtoend/testdata/issue_4213_reuse/sqlite/go/query.sql.go new file mode 100644 index 0000000000..7db8c2cf95 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_reuse/sqlite/go/query.sql.go @@ -0,0 +1,58 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: query.sql + +package querytest + +import ( + "context" + "strings" +) + +const reuseWithSlice = `-- name: ReuseWithSlice :many +SELECT id, typ, name FROM mytable +WHERE typ IN (/*SLICE:types*/?) AND (name = ? OR id = ? OR name = ?) +` + +type ReuseWithSliceParams struct { + Types []int64 + Name string + ID int64 +} + +func (q *Queries) ReuseWithSlice(ctx context.Context, arg ReuseWithSliceParams) ([]Mytable, error) { + query := reuseWithSlice + var queryParams []interface{} + if len(arg.Types) > 0 { + for _, v := range arg.Types { + queryParams = append(queryParams, v) + } + query = strings.Replace(query, "/*SLICE:types*/?", strings.Repeat(",?", len(arg.Types))[1:], 1) + } else { + query = strings.Replace(query, "/*SLICE:types*/?", "NULL", 1) + } + queryParams = append(queryParams, arg.Name) + queryParams = append(queryParams, arg.ID) + queryParams = append(queryParams, arg.Name) + rows, err := q.db.QueryContext(ctx, query, queryParams...) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Mytable + for rows.Next() { + var i Mytable + if err := rows.Scan(&i.ID, &i.Typ, &i.Name); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/issue_4213_reuse/sqlite/query.sql b/internal/endtoend/testdata/issue_4213_reuse/sqlite/query.sql new file mode 100644 index 0000000000..ee46192822 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_reuse/sqlite/query.sql @@ -0,0 +1,3 @@ +-- name: ReuseWithSlice :many +SELECT * FROM mytable +WHERE typ IN (sqlc.slice(types)) AND (name = @name OR id = @id OR name = @name); diff --git a/internal/endtoend/testdata/issue_4213_reuse/sqlite/schema.sql b/internal/endtoend/testdata/issue_4213_reuse/sqlite/schema.sql new file mode 100644 index 0000000000..93d6b31f89 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_reuse/sqlite/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE mytable ( + id INTEGER PRIMARY KEY, + typ INTEGER NOT NULL, + name TEXT NOT NULL +); diff --git a/internal/endtoend/testdata/issue_4213_reuse/sqlite/sqlc.json b/internal/endtoend/testdata/issue_4213_reuse/sqlite/sqlc.json new file mode 100644 index 0000000000..bb0de89ce2 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_reuse/sqlite/sqlc.json @@ -0,0 +1,16 @@ +{ + "version": "2", + "sql": [ + { + "engine": "sqlite", + "queries": "query.sql", + "schema": "schema.sql", + "gen": { + "go": { + "package": "querytest", + "out": "go" + } + } + } + ] +} diff --git a/internal/endtoend/testdata/sqlc_slice/sqlite/go/query.sql.go b/internal/endtoend/testdata/sqlc_slice/sqlite/go/query.sql.go index ff3ae7f5ff..7b7ec9822f 100644 --- a/internal/endtoend/testdata/sqlc_slice/sqlite/go/query.sql.go +++ b/internal/endtoend/testdata/sqlc_slice/sqlite/go/query.sql.go @@ -89,7 +89,7 @@ func (q *Queries) FuncNullableNot(ctx context.Context, favourites []int64) ([]sq const funcParamIdent = `-- name: FuncParamIdent :many SELECT name FROM foo -WHERE name = ?1 +WHERE name = ? AND id IN (/*SLICE:favourites*/?) ` @@ -172,7 +172,7 @@ func (q *Queries) FuncParamSoloArg(ctx context.Context, favourites []int64) ([]s const funcParamString = `-- name: FuncParamString :many SELECT name FROM foo -WHERE name = ?1 +WHERE name = ? AND id IN (/*SLICE:favourites*/?) ` @@ -216,7 +216,7 @@ func (q *Queries) FuncParamString(ctx context.Context, arg FuncParamStringParams } const sliceExec = `-- name: SliceExec :exec -UPDATE foo SET name = ?1 +UPDATE foo SET name = ? WHERE id IN (/*SLICE:favourites*/?) ` diff --git a/internal/endtoend/testdata/sqlc_slice_prepared/sqlite/go/query.sql.go b/internal/endtoend/testdata/sqlc_slice_prepared/sqlite/go/query.sql.go index af519ba1e8..35fdb20aa7 100644 --- a/internal/endtoend/testdata/sqlc_slice_prepared/sqlite/go/query.sql.go +++ b/internal/endtoend/testdata/sqlc_slice_prepared/sqlite/go/query.sql.go @@ -12,7 +12,7 @@ import ( const funcParamIdent = `-- name: FuncParamIdent :many SELECT name FROM foo -WHERE name = ?1 +WHERE name = ? AND id IN (/*SLICE:favourites*/?) ` diff --git a/internal/sql/rewrite/parameters.go b/internal/sql/rewrite/parameters.go index d1ea1a22cc..c33fa09237 100644 --- a/internal/sql/rewrite/parameters.go +++ b/internal/sql/rewrite/parameters.go @@ -81,7 +81,20 @@ func paramFromFuncCall(call *ast.FuncCall) (named.Param, string) { func NamedParameters(engine config.Engine, raw *ast.RawStmt, numbs map[int]bool, dollar bool) (*ast.RawStmt, *named.ParamSet, []source.Edit) { foundFunc := astutils.Search(raw, named.IsParamFunc) foundSign := astutils.Search(raw, named.IsParamSign) + + hasSlice := false + for _, item := range foundFunc.Items { + if call, ok := item.(*ast.FuncCall); ok && call.Func.Name == "slice" { + hasSlice = true + break + } + } + hasNamedParameterSupport := engine != config.EngineMySQL + if engine == config.EngineSQLite && hasSlice { + hasNamedParameterSupport = false + } + allParams := named.NewParamSet(numbs, hasNamedParameterSupport) if len(foundFunc.Items)+len(foundSign.Items) == 0 { @@ -108,7 +121,7 @@ func NamedParameters(engine config.Engine, raw *ast.RawStmt, numbs map[int]bool, // since it's needed during template generation for replacement replace = fmt.Sprintf(`/*SLICE:%s*/?`, param.Name()) } else { - if engine == config.EngineSQLite { + if engine == config.EngineSQLite && hasNamedParameterSupport { replace = fmt.Sprintf("?%d", argn) } else { replace = "?" @@ -143,7 +156,11 @@ func NamedParameters(engine config.Engine, raw *ast.RawStmt, numbs map[int]bool, if engine == config.EngineMySQL || !dollar { replace = "?" } else if engine == config.EngineSQLite { - replace = fmt.Sprintf("?%d", argn) + if hasNamedParameterSupport { + replace = fmt.Sprintf("?%d", argn) + } else { + replace = "?" + } } else { replace = fmt.Sprintf("$%d", argn) } @@ -171,7 +188,11 @@ func NamedParameters(engine config.Engine, raw *ast.RawStmt, numbs map[int]bool, if engine == config.EngineMySQL || !dollar { replace = "?" } else if engine == config.EngineSQLite { - replace = fmt.Sprintf("?%d", argn) + if hasNamedParameterSupport { + replace = fmt.Sprintf("?%d", argn) + } else { + replace = "?" + } } else { replace = fmt.Sprintf("$%d", argn) } From 953e0e33b840a2cd1418de26b3f7d0f235556579 Mon Sep 17 00:00:00 2001 From: Pickle Rick Date: Sat, 7 Mar 2026 18:13:53 +0000 Subject: [PATCH 2/2] test(sqlite): add repro and reuse cases for sqlc.slice positional indexing --- .../testdata/issue_4213_repro/sqlite/go/db.go | 31 ++++++++ .../issue_4213_repro/sqlite/go/models.go | 12 ++++ .../issue_4213_repro/sqlite/go/query.sql.go | 72 +++++++++++++++++++ .../issue_4213_repro/sqlite/query.sql | 6 ++ .../issue_4213_repro/sqlite/schema.sql | 6 ++ .../issue_4213_repro/sqlite/sqlc.json | 16 +++++ .../testdata/mysql_reuse_test/mysql/go/db.go | 31 ++++++++ .../mysql_reuse_test/mysql/go/models.go | 10 +++ .../mysql_reuse_test/mysql/go/query.sql.go | 24 +++++++ .../testdata/mysql_reuse_test/mysql/query.sql | 2 + .../mysql_reuse_test/mysql/schema.sql | 4 ++ .../testdata/mysql_reuse_test/mysql/sqlc.json | 16 +++++ .../sqlite_reuse_test/sqlite/go/db.go | 31 ++++++++ .../sqlite_reuse_test/sqlite/go/models.go | 10 +++ .../sqlite_reuse_test/sqlite/go/query.sql.go | 24 +++++++ .../sqlite_reuse_test/sqlite/query.sql | 2 + .../sqlite_reuse_test/sqlite/schema.sql | 4 ++ .../sqlite_reuse_test/sqlite/sqlc.json | 16 +++++ 18 files changed, 317 insertions(+) create mode 100644 internal/endtoend/testdata/issue_4213_repro/sqlite/go/db.go create mode 100644 internal/endtoend/testdata/issue_4213_repro/sqlite/go/models.go create mode 100644 internal/endtoend/testdata/issue_4213_repro/sqlite/go/query.sql.go create mode 100644 internal/endtoend/testdata/issue_4213_repro/sqlite/query.sql create mode 100644 internal/endtoend/testdata/issue_4213_repro/sqlite/schema.sql create mode 100644 internal/endtoend/testdata/issue_4213_repro/sqlite/sqlc.json create mode 100644 internal/endtoend/testdata/mysql_reuse_test/mysql/go/db.go create mode 100644 internal/endtoend/testdata/mysql_reuse_test/mysql/go/models.go create mode 100644 internal/endtoend/testdata/mysql_reuse_test/mysql/go/query.sql.go create mode 100644 internal/endtoend/testdata/mysql_reuse_test/mysql/query.sql create mode 100644 internal/endtoend/testdata/mysql_reuse_test/mysql/schema.sql create mode 100644 internal/endtoend/testdata/mysql_reuse_test/mysql/sqlc.json create mode 100644 internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/db.go create mode 100644 internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/models.go create mode 100644 internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/query.sql.go create mode 100644 internal/endtoend/testdata/sqlite_reuse_test/sqlite/query.sql create mode 100644 internal/endtoend/testdata/sqlite_reuse_test/sqlite/schema.sql create mode 100644 internal/endtoend/testdata/sqlite_reuse_test/sqlite/sqlc.json diff --git a/internal/endtoend/testdata/issue_4213_repro/sqlite/go/db.go b/internal/endtoend/testdata/issue_4213_repro/sqlite/go/db.go new file mode 100644 index 0000000000..3b320aa168 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_repro/sqlite/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/issue_4213_repro/sqlite/go/models.go b/internal/endtoend/testdata/issue_4213_repro/sqlite/go/models.go new file mode 100644 index 0000000000..6ace3159b6 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_repro/sqlite/go/models.go @@ -0,0 +1,12 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +type Mytable struct { + ID int64 + Typ int64 + Name string + Val string +} diff --git a/internal/endtoend/testdata/issue_4213_repro/sqlite/go/query.sql.go b/internal/endtoend/testdata/issue_4213_repro/sqlite/go/query.sql.go new file mode 100644 index 0000000000..9a3caf6703 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_repro/sqlite/go/query.sql.go @@ -0,0 +1,72 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: query.sql + +package querytest + +import ( + "context" + "strings" +) + +const brokenQuery = `-- name: BrokenQuery :many +SELECT id, typ, name, val +FROM mytable +WHERE + typ IN (/*SLICE:types*/?) + AND (? OR (name IN (/*SLICE:names*/?))) +` + +type BrokenQueryParams struct { + Types []int64 + Allnames interface{} + Names []string +} + +func (q *Queries) BrokenQuery(ctx context.Context, arg BrokenQueryParams) ([]Mytable, error) { + query := brokenQuery + var queryParams []interface{} + if len(arg.Types) > 0 { + for _, v := range arg.Types { + queryParams = append(queryParams, v) + } + query = strings.Replace(query, "/*SLICE:types*/?", strings.Repeat(",?", len(arg.Types))[1:], 1) + } else { + query = strings.Replace(query, "/*SLICE:types*/?", "NULL", 1) + } + queryParams = append(queryParams, arg.Allnames) + if len(arg.Names) > 0 { + for _, v := range arg.Names { + queryParams = append(queryParams, v) + } + query = strings.Replace(query, "/*SLICE:names*/?", strings.Repeat(",?", len(arg.Names))[1:], 1) + } else { + query = strings.Replace(query, "/*SLICE:names*/?", "NULL", 1) + } + rows, err := q.db.QueryContext(ctx, query, queryParams...) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Mytable + for rows.Next() { + var i Mytable + if err := rows.Scan( + &i.ID, + &i.Typ, + &i.Name, + &i.Val, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/issue_4213_repro/sqlite/query.sql b/internal/endtoend/testdata/issue_4213_repro/sqlite/query.sql new file mode 100644 index 0000000000..104379fed0 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_repro/sqlite/query.sql @@ -0,0 +1,6 @@ +-- name: BrokenQuery :many +SELECT * +FROM mytable +WHERE + typ IN (sqlc.slice(types)) + AND (sqlc.arg(allnames) OR (name IN (sqlc.slice(names)))); diff --git a/internal/endtoend/testdata/issue_4213_repro/sqlite/schema.sql b/internal/endtoend/testdata/issue_4213_repro/sqlite/schema.sql new file mode 100644 index 0000000000..60e58a1a72 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_repro/sqlite/schema.sql @@ -0,0 +1,6 @@ +CREATE TABLE mytable ( + id INTEGER PRIMARY KEY, + typ INTEGER NOT NULL, + name TEXT NOT NULL, + val TEXT NOT NULL +); diff --git a/internal/endtoend/testdata/issue_4213_repro/sqlite/sqlc.json b/internal/endtoend/testdata/issue_4213_repro/sqlite/sqlc.json new file mode 100644 index 0000000000..bb0de89ce2 --- /dev/null +++ b/internal/endtoend/testdata/issue_4213_repro/sqlite/sqlc.json @@ -0,0 +1,16 @@ +{ + "version": "2", + "sql": [ + { + "engine": "sqlite", + "queries": "query.sql", + "schema": "schema.sql", + "gen": { + "go": { + "package": "querytest", + "out": "go" + } + } + } + ] +} diff --git a/internal/endtoend/testdata/mysql_reuse_test/mysql/go/db.go b/internal/endtoend/testdata/mysql_reuse_test/mysql/go/db.go new file mode 100644 index 0000000000..3b320aa168 --- /dev/null +++ b/internal/endtoend/testdata/mysql_reuse_test/mysql/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/mysql_reuse_test/mysql/go/models.go b/internal/endtoend/testdata/mysql_reuse_test/mysql/go/models.go new file mode 100644 index 0000000000..7b23258bf0 --- /dev/null +++ b/internal/endtoend/testdata/mysql_reuse_test/mysql/go/models.go @@ -0,0 +1,10 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +type Foo struct { + ID uint64 + Name string +} diff --git a/internal/endtoend/testdata/mysql_reuse_test/mysql/go/query.sql.go b/internal/endtoend/testdata/mysql_reuse_test/mysql/go/query.sql.go new file mode 100644 index 0000000000..99ac5a6c9a --- /dev/null +++ b/internal/endtoend/testdata/mysql_reuse_test/mysql/go/query.sql.go @@ -0,0 +1,24 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const reuseParam = `-- name: ReuseParam :exec +UPDATE foo SET name = ? WHERE id = ? OR name = ? +` + +type ReuseParamParams struct { + Name string + ID uint64 +} + +func (q *Queries) ReuseParam(ctx context.Context, arg ReuseParamParams) error { + _, err := q.db.ExecContext(ctx, reuseParam, arg.Name, arg.ID, arg.Name) + return err +} diff --git a/internal/endtoend/testdata/mysql_reuse_test/mysql/query.sql b/internal/endtoend/testdata/mysql_reuse_test/mysql/query.sql new file mode 100644 index 0000000000..466653fa7b --- /dev/null +++ b/internal/endtoend/testdata/mysql_reuse_test/mysql/query.sql @@ -0,0 +1,2 @@ +-- name: ReuseParam :exec +UPDATE foo SET name = sqlc.arg(name) WHERE id = sqlc.arg(id) OR name = sqlc.arg(name); diff --git a/internal/endtoend/testdata/mysql_reuse_test/mysql/schema.sql b/internal/endtoend/testdata/mysql_reuse_test/mysql/schema.sql new file mode 100644 index 0000000000..f746d54206 --- /dev/null +++ b/internal/endtoend/testdata/mysql_reuse_test/mysql/schema.sql @@ -0,0 +1,4 @@ +CREATE TABLE foo ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL +); diff --git a/internal/endtoend/testdata/mysql_reuse_test/mysql/sqlc.json b/internal/endtoend/testdata/mysql_reuse_test/mysql/sqlc.json new file mode 100644 index 0000000000..21c1a3b035 --- /dev/null +++ b/internal/endtoend/testdata/mysql_reuse_test/mysql/sqlc.json @@ -0,0 +1,16 @@ +{ + "version": "2", + "sql": [ + { + "engine": "mysql", + "queries": "query.sql", + "schema": "schema.sql", + "gen": { + "go": { + "package": "querytest", + "out": "go" + } + } + } + ] +} diff --git a/internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/db.go b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/db.go new file mode 100644 index 0000000000..3b320aa168 --- /dev/null +++ b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/models.go b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/models.go new file mode 100644 index 0000000000..7fb6912595 --- /dev/null +++ b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/models.go @@ -0,0 +1,10 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +type Foo struct { + ID int64 + Name string +} diff --git a/internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/query.sql.go b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/query.sql.go new file mode 100644 index 0000000000..b2b3fcf3d9 --- /dev/null +++ b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/go/query.sql.go @@ -0,0 +1,24 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const reuseParam = `-- name: ReuseParam :exec +UPDATE foo SET name = ?1 WHERE id = ?2 OR name = ?1 +` + +type ReuseParamParams struct { + Name string + ID int64 +} + +func (q *Queries) ReuseParam(ctx context.Context, arg ReuseParamParams) error { + _, err := q.db.ExecContext(ctx, reuseParam, arg.Name, arg.ID) + return err +} diff --git a/internal/endtoend/testdata/sqlite_reuse_test/sqlite/query.sql b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/query.sql new file mode 100644 index 0000000000..d858d4c054 --- /dev/null +++ b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/query.sql @@ -0,0 +1,2 @@ +-- name: ReuseParam :exec +UPDATE foo SET name = @name WHERE id = @id OR name = @name; diff --git a/internal/endtoend/testdata/sqlite_reuse_test/sqlite/schema.sql b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/schema.sql new file mode 100644 index 0000000000..d3af2150f1 --- /dev/null +++ b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/schema.sql @@ -0,0 +1,4 @@ +CREATE TABLE foo ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL +); diff --git a/internal/endtoend/testdata/sqlite_reuse_test/sqlite/sqlc.json b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/sqlc.json new file mode 100644 index 0000000000..bb0de89ce2 --- /dev/null +++ b/internal/endtoend/testdata/sqlite_reuse_test/sqlite/sqlc.json @@ -0,0 +1,16 @@ +{ + "version": "2", + "sql": [ + { + "engine": "sqlite", + "queries": "query.sql", + "schema": "schema.sql", + "gen": { + "go": { + "package": "querytest", + "out": "go" + } + } + } + ] +}