With Bob v0.50.0, an UPDATE containing bound SET values and a parameterized FROM source generates incorrect PostgreSQL placeholder numbers.
bob.Build returns no error, but the generated SQL references arguments beyond the returned argument slice.
Reproduction
No database, generated models, or explicit scan calls are required.
mkdir bob-update-from-repro
cd bob-update-from-repro
go mod init example.com/bob-update-from-repro
go get github.com/stephenafamo/bob@v0.50.0
Save as main.go:
package main
import (
"context"
"fmt"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/um"
"github.com/stephenafamo/bob/dialect/psql/vm"
)
func main() {
q := psql.Update(
um.Table("widgets"),
um.SetCol("changed_by").ToArg("tester"),
um.SetCol("changed_by_id").ToArg(int64(42)),
um.From(psql.Values(
vm.RowValue(psql.Arg(int64(17), "first")),
vm.RowValue(psql.Arg(int64(29), "second")),
)).As("requested", "id", "value"),
um.Where(
psql.Quote("widgets", "id").
EQ(psql.Quote("requested", "id")),
),
)
query, args, err := bob.Build(context.Background(), q)
fmt.Printf("SQL:\n%s\nARGS(%d): %#v\nERROR: %v\n",
query, len(args), args, err)
}
Run:
Actual result
SQL:
UPDATE widgets SET
"changed_by" = $1,
"changed_by_id" = $2
FROM (VALUES ($5, $6), ($7, $8)
) AS "requested"("id", "value")
WHERE ("widgets"."id" = "requested"."id")
ARGS(6): []interface {}{"tester", 42, 17, "first", 29, "second"}
ERROR: <nil>
The SQL skips $3 and $4, then references $7 and $8, although only six arguments exist.
Expected result
The FROM source should continue numbering immediately after the two SET arguments:
UPDATE widgets SET
"changed_by" = $1,
"changed_by_id" = $2
FROM (VALUES ($3, $4), ($5, $6))
AS "requested"("id", "value")
WHERE ("widgets"."id" = "requested"."id")
The returned argument slice should remain unchanged.
Suspected cause
UpdateQuery.WriteSQL passes both start+len(args) and the accumulated args into writeFromItemList.
writeFromItemList then adds len(args) again when rendering each item. Consequently, the preceding arguments are counted twice.
A likely correction is to pass the original start into the helper, which already accounts for accumulated arguments. Other callers should be checked before changing the shared convention.
With Bob
v0.50.0, an UPDATE containing bound SET values and a parameterized FROM source generates incorrect PostgreSQL placeholder numbers.bob.Buildreturns no error, but the generated SQL references arguments beyond the returned argument slice.Reproduction
No database, generated models, or explicit scan calls are required.
Save as main.go:
Run:
Actual result
SQL:
The SQL skips $3 and $4, then references $7 and $8, although only six arguments exist.
Expected result
The FROM source should continue numbering immediately after the two SET arguments:
The returned argument slice should remain unchanged.
Suspected cause
UpdateQuery.WriteSQL passes both start+len(args) and the accumulated args into writeFromItemList.
writeFromItemList then adds len(args) again when rendering each item. Consequently, the preceding arguments are counted twice.
A likely correction is to pass the original start into the helper, which already accounts for accumulated arguments. Other callers should be checked before changing the shared convention.