aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattn <mattn.jp@gmail.com>2017-08-22 13:32:16 +0900
committerGitHub <noreply@github.com>2017-08-22 13:32:16 +0900
commit144deb6596cd6dbb49158b3d6f6a0e742715f9a5 (patch)
treecbc91e77b2908af25c7d2456488c586fdfdbf753
parentfix test (diff)
parentImproved TestNilAndEmptyBytes (diff)
downloadgolite-144deb6596cd6dbb49158b3d6f6a0e742715f9a5.tar.gz
golite-144deb6596cd6dbb49158b3d6f6a0e742715f9a5.tar.xz
Merge pull request #454 from gholt/master
Fix to better handle NULL values in TEXT and BLOB columns.
-rw-r--r--sqlite3.go5
-rw-r--r--sqlite3_test.go56
2 files changed, 59 insertions, 2 deletions
diff --git a/sqlite3.go b/sqlite3.go
index d0327b8..bff6b7c 100644
--- a/sqlite3.go
+++ b/sqlite3.go
@@ -867,10 +867,11 @@ func (s *SQLiteStmt) bind(args []namedValue) error {
case float64:
rv = C.sqlite3_bind_double(s.s, n, C.double(v))
case []byte:
- if len(v) == 0 {
+ ln := len(v)
+ if ln == 0 {
v = placeHolder
}
- rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(len(v)))
+ rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(ln))
case time.Time:
b := []byte(v.Format(SQLiteTimestampFormats[0]))
rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
diff --git a/sqlite3_test.go b/sqlite3_test.go
index 7c545e1..09e6727 100644
--- a/sqlite3_test.go
+++ b/sqlite3_test.go
@@ -6,6 +6,7 @@
package sqlite3
import (
+ "bytes"
"database/sql"
"database/sql/driver"
"errors"
@@ -1343,6 +1344,61 @@ func TestUpdateAndTransactionHooks(t *testing.T) {
}
}
+func TestNilAndEmptyBytes(t *testing.T) {
+ db, err := sql.Open("sqlite3", ":memory:")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer db.Close()
+ actualNil := []byte("use this to use an actual nil not a reference to nil")
+ emptyBytes := []byte{}
+ for tsti, tst := range []struct {
+ name string
+ columnType string
+ insertBytes []byte
+ expectedBytes []byte
+ }{
+ {"actual nil blob", "blob", actualNil, nil},
+ {"referenced nil blob", "blob", nil, nil},
+ {"empty blob", "blob", emptyBytes, emptyBytes},
+ {"actual nil text", "text", actualNil, nil},
+ {"referenced nil text", "text", nil, nil},
+ {"empty text", "text", emptyBytes, emptyBytes},
+ } {
+ if _, err = db.Exec(fmt.Sprintf("create table tbl%d (txt %s)", tsti, tst.columnType)); err != nil {
+ t.Fatal(tst.name, err)
+ }
+ if bytes.Equal(tst.insertBytes, actualNil) {
+ if _, err = db.Exec(fmt.Sprintf("insert into tbl%d (txt) values (?)", tsti), nil); err != nil {
+ t.Fatal(tst.name, err)
+ }
+ } else {
+ if _, err = db.Exec(fmt.Sprintf("insert into tbl%d (txt) values (?)", tsti), &tst.insertBytes); err != nil {
+ t.Fatal(tst.name, err)
+ }
+ }
+ rows, err := db.Query(fmt.Sprintf("select txt from tbl%d", tsti))
+ if err != nil {
+ t.Fatal(tst.name, err)
+ }
+ if !rows.Next() {
+ t.Fatal(tst.name, "no rows")
+ }
+ var scanBytes []byte
+ if err = rows.Scan(&scanBytes); err != nil {
+ t.Fatal(tst.name, err)
+ }
+ if err = rows.Err(); err != nil {
+ t.Fatal(tst.name, err)
+ }
+ if tst.expectedBytes == nil && scanBytes != nil {
+ t.Errorf("%s: %#v != %#v", tst.name, scanBytes, tst.expectedBytes)
+ } else if !bytes.Equal(scanBytes, tst.expectedBytes) {
+ t.Errorf("%s: %#v != %#v", tst.name, scanBytes, tst.expectedBytes)
+ }
+ }
+}
+
var customFunctionOnce sync.Once
func BenchmarkCustomFunctions(b *testing.B) {