diff --git a/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/base.txt b/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/base.txt index c74f98d2c2..9582e34e62 100644 --- a/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/base.txt +++ b/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/base.txt @@ -2,4 +2,4 @@ query.sql:1:1: could not determine data type of parameter $1 query.sql:5:1: could not determine data type of parameter $2 query.sql:8:8: column "foo" does not exist -query.sql:11:1: could not determine data type of parameter $2 +query.sql:11:1: could not determine data type of parameter $3 diff --git a/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/base.txt b/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/base.txt index c74f98d2c2..9582e34e62 100644 --- a/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/base.txt +++ b/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/base.txt @@ -2,4 +2,4 @@ query.sql:1:1: could not determine data type of parameter $1 query.sql:5:1: could not determine data type of parameter $2 query.sql:8:8: column "foo" does not exist -query.sql:11:1: could not determine data type of parameter $2 +query.sql:11:1: could not determine data type of parameter $3 diff --git a/internal/endtoend/testdata/invalid_params/stdlib/stderr/base.txt b/internal/endtoend/testdata/invalid_params/stdlib/stderr/base.txt index c74f98d2c2..9582e34e62 100644 --- a/internal/endtoend/testdata/invalid_params/stdlib/stderr/base.txt +++ b/internal/endtoend/testdata/invalid_params/stdlib/stderr/base.txt @@ -2,4 +2,4 @@ query.sql:1:1: could not determine data type of parameter $1 query.sql:5:1: could not determine data type of parameter $2 query.sql:8:8: column "foo" does not exist -query.sql:11:1: could not determine data type of parameter $2 +query.sql:11:1: could not determine data type of parameter $3 diff --git a/internal/sql/preprocess/preprocess.go b/internal/sql/preprocess/preprocess.go index ad25bc9b2f..587fd67e38 100644 --- a/internal/sql/preprocess/preprocess.go +++ b/internal/sql/preprocess/preprocess.go @@ -215,8 +215,8 @@ func Dialected(d Dialect, src string) *Result { continue } - stmt.Dollar, stmt.ParamErr = validatePlaceholders(occs) stmt.Params = number(d, occs) + stmt.Dollar, stmt.ParamErr = validatePlaceholders(occs) stmt.Numbers = map[int]int{} prev := start @@ -301,6 +301,17 @@ func validatePlaceholders(occs []occurrence) (dollar bool, err error) { unnumbered = true } } + + // sqlc.arg/narg/slice fill gaps in numbered dialects; include them so + // the gap check does not fire for positions they occupy. + if numbered && !unnumbered { + for _, occ := range occs { + if occ.kind == kindArg || occ.kind == kindNarg || occ.kind == kindSlice { + seen[occ.number] = true + } + } + } + if numbered && unnumbered { return false, errors.New("can not mix $1 format with ? format") } diff --git a/internal/sql/preprocess/testdata/postgresql/arg_fills_gap_at_start/input.sql b/internal/sql/preprocess/testdata/postgresql/arg_fills_gap_at_start/input.sql new file mode 100644 index 0000000000..e9e38b2b80 --- /dev/null +++ b/internal/sql/preprocess/testdata/postgresql/arg_fills_gap_at_start/input.sql @@ -0,0 +1 @@ +INSERT INTO users (a, b, c) VALUES (sqlc.arg(a), @b, $3); diff --git a/internal/sql/preprocess/testdata/postgresql/arg_fills_gap_at_start/output.sql b/internal/sql/preprocess/testdata/postgresql/arg_fills_gap_at_start/output.sql new file mode 100644 index 0000000000..2c9b08d355 --- /dev/null +++ b/internal/sql/preprocess/testdata/postgresql/arg_fills_gap_at_start/output.sql @@ -0,0 +1 @@ +INSERT INTO users (a, b, c) VALUES ($1, $2, $3); diff --git a/internal/sql/preprocess/testdata/postgresql/arg_fills_gap_at_start/side_table.json b/internal/sql/preprocess/testdata/postgresql/arg_fills_gap_at_start/side_table.json new file mode 100644 index 0000000000..a206cc05b2 --- /dev/null +++ b/internal/sql/preprocess/testdata/postgresql/arg_fills_gap_at_start/side_table.json @@ -0,0 +1,29 @@ +[ + { + "start": 0, + "end": 48, + "dollar": true, + "params": [ + { + "number": 1, + "location": 36, + "origin": 36, + "name": "a", + "named": true + }, + { + "number": 2, + "location": 40, + "origin": 49, + "name": "b", + "named": true + }, + { + "number": 3, + "location": 44, + "origin": 53, + "named": false + } + ] + } +]