diff --git a/sqlite-ffi.lisp b/sqlite-ffi.lisp index 09964f7..82f6017 100644 --- a/sqlite-ffi.lisp +++ b/sqlite-ffi.lisp @@ -127,10 +127,17 @@ (statement p-sqlite3-stmt) (column-number :int)) -(defcfun sqlite3-column-text :string +(defcfun ("sqlite3_column_text" sqlite3-column-text-pointer) :pointer (statement p-sqlite3-stmt) (column-number :int)) +(defun sqlite3-column-text (statement column-number) + "Wraper around sqlite3-column-text-pointer to deal with strings + containing embedded NULs." + (cffi:foreign-string-to-lisp + (sqlite3-column-text-pointer statement column-number) + :count (sqlite3-column-bytes statement column-number))) + (defcfun sqlite3-column-int64 :int64 (statement p-sqlite3-stmt) (column-number :int)) diff --git a/sqlite-tests.lisp b/sqlite-tests.lisp index a401219..55bc582 100644 --- a/sqlite-tests.lisp +++ b/sqlite-tests.lisp @@ -107,6 +107,14 @@ (is (equalp (fetch-all) '())))) (finalize-statement statement))))) +(test test-text-containing-null-bytes + (let ((string-with-nulls (concatenate 'string "foo" '(#\null) "bar" '(#\null) "baz"))) + (with-open-database (db ":memory:") + (execute-non-query db "create table test (str text)") + (execute-non-query db "insert into test (str) values (?)" string-with-nulls) + (is (string= (execute-single db "select str from test") + string-with-nulls))))) + #+thread-support (defparameter *db-file* "/tmp/test.sqlite") diff --git a/sqlite.asd b/sqlite.asd index 0e292f2..f4408f1 100644 --- a/sqlite.asd +++ b/sqlite.asd @@ -13,7 +13,7 @@ (:file "cache") (:file "sqlite" :depends-on ("sqlite-ffi" "cache"))) - :depends-on (:iterate :cffi) + :depends-on (:iterate :cffi :babel) :in-order-to ((test-op (load-op sqlite-tests)))) diff --git a/sqlite.lisp b/sqlite.lisp index de0f97d..d875ff1 100644 --- a/sqlite.lisp +++ b/sqlite.lisp @@ -385,7 +385,9 @@ Supported types: (integer (sqlite-ffi:sqlite3-bind-int64 (handle statement) index value)) (double-float (sqlite-ffi:sqlite3-bind-double (handle statement) index value)) (real (sqlite-ffi:sqlite3-bind-double (handle statement) index (coerce value 'double-float))) - (string (sqlite-ffi:sqlite3-bind-text (handle statement) index value -1 (sqlite-ffi:destructor-transient))) + (string (sqlite-ffi:sqlite3-bind-text (handle statement) index value + (babel:string-size-in-octets value) + (sqlite-ffi:destructor-transient))) ((vector (unsigned-byte 8)) (cffi:with-pointer-to-vector-data (ptr value) (sqlite-ffi:sqlite3-bind-blob (handle statement) index ptr (length value) (sqlite-ffi:destructor-transient)))) (vector (cffi:with-foreign-object (array :unsigned-char (length value))