diff --git a/sqlite3.go b/sqlite3.go index a967cab..d69f649 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -1958,6 +1958,8 @@ func (s *SQLiteStmt) bind(args []driver.NamedValue) error { return s.c.lastError() } + C.sqlite3_clear_bindings(s.s) + bindIndices := make([][3]int, len(args)) prefixes := []string{":", "@", "$"} for i, v := range args { diff --git a/sqlite3_test.go b/sqlite3_test.go index ed8fa64..852aa10 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -2023,6 +2023,48 @@ func TestNamedParam(t *testing.T) { } } +func TestNamedParamClearBindings(t *testing.T) { + tempFilename := TempFilename(t) + defer os.Remove(tempFilename) + db, err := sql.Open("sqlite3", tempFilename) + if err != nil { + t.Fatal("Failed to open database:", err) + } + defer db.Close() + + _, err = db.Exec("create table foo (x integer, y integer, z text)") + if err != nil { + t.Fatal("Failed to create table:", err) + } + + // First insert with all named params specified + _, err = db.Exec("insert into foo(x, y, z) values($x, $y, $z)", + sql.Named("x", 1), sql.Named("y", 2), sql.Named("z", "three")) + if err != nil { + t.Fatal("Failed to insert:", err) + } + + // Second insert: $y should be NULL since we pass nil explicitly + _, err = db.Exec("insert into foo(x, y, z) values($x, $y, $z)", + sql.Named("x", 10), sql.Named("y", nil), sql.Named("z", nil)) + if err != nil { + t.Fatal("Failed to insert:", err) + } + + var x int + var y, z sql.NullInt64 + err = db.QueryRow("select x, y, z from foo where x = 10").Scan(&x, &y, &z) + if err != nil { + t.Fatal("Failed to query:", err) + } + if y.Valid { + t.Errorf("Expected y to be NULL, got %d", y.Int64) + } + if z.Valid { + t.Errorf("Expected z to be NULL, got %d", z.Int64) + } +} + var customFunctionOnce sync.Once func BenchmarkCustomFunctions(b *testing.B) {