Skip to content

Commit 144deb6

Browse files
authored
Merge pull request #454 from gholt/master
Fix to better handle NULL values in TEXT and BLOB columns.
2 parents 6654e41 + b1c8062 commit 144deb6

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

sqlite3.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -867,10 +867,11 @@ func (s *SQLiteStmt) bind(args []namedValue) error {
867867
case float64:
868868
rv = C.sqlite3_bind_double(s.s, n, C.double(v))
869869
case []byte:
870-
if len(v) == 0 {
870+
ln := len(v)
871+
if ln == 0 {
871872
v = placeHolder
872873
}
873-
rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(len(v)))
874+
rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(ln))
874875
case time.Time:
875876
b := []byte(v.Format(SQLiteTimestampFormats[0]))
876877
rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))

sqlite3_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package sqlite3
77

88
import (
9+
"bytes"
910
"database/sql"
1011
"database/sql/driver"
1112
"errors"
@@ -1343,6 +1344,61 @@ func TestUpdateAndTransactionHooks(t *testing.T) {
13431344
}
13441345
}
13451346

1347+
func TestNilAndEmptyBytes(t *testing.T) {
1348+
db, err := sql.Open("sqlite3", ":memory:")
1349+
if err != nil {
1350+
t.Fatal(err)
1351+
}
1352+
defer db.Close()
1353+
actualNil := []byte("use this to use an actual nil not a reference to nil")
1354+
emptyBytes := []byte{}
1355+
for tsti, tst := range []struct {
1356+
name string
1357+
columnType string
1358+
insertBytes []byte
1359+
expectedBytes []byte
1360+
}{
1361+
{"actual nil blob", "blob", actualNil, nil},
1362+
{"referenced nil blob", "blob", nil, nil},
1363+
{"empty blob", "blob", emptyBytes, emptyBytes},
1364+
{"actual nil text", "text", actualNil, nil},
1365+
{"referenced nil text", "text", nil, nil},
1366+
{"empty text", "text", emptyBytes, emptyBytes},
1367+
} {
1368+
if _, err = db.Exec(fmt.Sprintf("create table tbl%d (txt %s)", tsti, tst.columnType)); err != nil {
1369+
t.Fatal(tst.name, err)
1370+
}
1371+
if bytes.Equal(tst.insertBytes, actualNil) {
1372+
if _, err = db.Exec(fmt.Sprintf("insert into tbl%d (txt) values (?)", tsti), nil); err != nil {
1373+
t.Fatal(tst.name, err)
1374+
}
1375+
} else {
1376+
if _, err = db.Exec(fmt.Sprintf("insert into tbl%d (txt) values (?)", tsti), &tst.insertBytes); err != nil {
1377+
t.Fatal(tst.name, err)
1378+
}
1379+
}
1380+
rows, err := db.Query(fmt.Sprintf("select txt from tbl%d", tsti))
1381+
if err != nil {
1382+
t.Fatal(tst.name, err)
1383+
}
1384+
if !rows.Next() {
1385+
t.Fatal(tst.name, "no rows")
1386+
}
1387+
var scanBytes []byte
1388+
if err = rows.Scan(&scanBytes); err != nil {
1389+
t.Fatal(tst.name, err)
1390+
}
1391+
if err = rows.Err(); err != nil {
1392+
t.Fatal(tst.name, err)
1393+
}
1394+
if tst.expectedBytes == nil && scanBytes != nil {
1395+
t.Errorf("%s: %#v != %#v", tst.name, scanBytes, tst.expectedBytes)
1396+
} else if !bytes.Equal(scanBytes, tst.expectedBytes) {
1397+
t.Errorf("%s: %#v != %#v", tst.name, scanBytes, tst.expectedBytes)
1398+
}
1399+
}
1400+
}
1401+
13461402
var customFunctionOnce sync.Once
13471403

13481404
func BenchmarkCustomFunctions(b *testing.B) {

0 commit comments

Comments
 (0)