From 8e88a000fef547950875c7cb8d197ba8fee25f04 Mon Sep 17 00:00:00 2001 From: Artyom Pervukhin Date: Wed, 18 May 2022 23:48:36 +0300 Subject: [PATCH] Fix handling of nil []byte as NULL values This fixes a regression introduced in 87412bbfa9b5b979ca4d4e8ba69c347819b9c4da, which changed nil []byte values by storing them as zero-sized blobs, instead of NULLs. Closes #100 --- all_test.go | 34 ++++++++++++++++++++++++++++++++++ sqlite.go | 6 ++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/all_test.go b/all_test.go index 154350d..8f5d704 100644 --- a/all_test.go +++ b/all_test.go @@ -149,6 +149,40 @@ func tempDB(t testing.TB) (string, *sql.DB) { return dir, db } +// https://gitlab.com/cznic/sqlite/issues/100 +func TestIssue100(t *testing.T) { + db, err := sql.Open("sqlite", ":memory:") + if err != nil { + t.Fatal(err) + } + defer db.Close() + if _, err := db.Exec(`CREATE TABLE t1(v TEXT)`); err != nil { + t.Fatal(err) + } + var val []byte + if _, err := db.Exec(`INSERT INTO t1(v) VALUES(?)`, val); err != nil { + t.Fatal(err) + } + var res sql.NullByte + if err = db.QueryRow(`SELECT v FROM t1 LIMIT 1`).Scan(&res); err != nil { + t.Fatal(err) + } + if res.Valid { + t.Fatalf("got non-NULL result: %+v", res) + } + + if _, err := db.Exec(`CREATE TABLE t2( + v TEXT check(v is NULL OR(json_valid(v) AND json_type(v)='array')) + )`); err != nil { + t.Fatal(err) + } + for _, val := range [...][]byte{nil, []byte(`["a"]`)} { + if _, err := db.Exec(`INSERT INTO t2(v) VALUES(?)`, val); err != nil { + t.Fatalf("inserting value %v (%[1]q): %v", val, err) + } + } +} + // https://gitlab.com/cznic/sqlite/issues/98 func TestIssue98(t *testing.T) { dir, db := tempDB(t) diff --git a/sqlite.go b/sqlite.go index 70d4007..109a11f 100644 --- a/sqlite.go +++ b/sqlite.go @@ -1147,7 +1147,7 @@ func (c *conn) bindText(pstmt uintptr, idx1 int, value string) (uintptr, error) // int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); func (c *conn) bindBlob(pstmt uintptr, idx1 int, value []byte) (uintptr, error) { - if len(value) == 0 { + if value != nil && len(value) == 0 { if rc := sqlite3.Xsqlite3_bind_zeroblob(c.tls, pstmt, int32(idx1), 0); rc != sqlite3.SQLITE_OK { return 0, c.errstr(rc) } @@ -1158,7 +1158,9 @@ func (c *conn) bindBlob(pstmt uintptr, idx1 int, value []byte) (uintptr, error) if err != nil { return 0, err } - copy((*libc.RawMem)(unsafe.Pointer(p))[:len(value):len(value)], value) + if len(value) != 0 { + copy((*libc.RawMem)(unsafe.Pointer(p))[:len(value):len(value)], value) + } if rc := sqlite3.Xsqlite3_bind_blob(c.tls, pstmt, int32(idx1), p, int32(len(value)), 0); rc != sqlite3.SQLITE_OK { c.free(p) return 0, c.errstr(rc)