Index: SQLite.Interop/src/win/interop.c
==================================================================
--- SQLite.Interop/src/win/interop.c
+++ SQLite.Interop/src/win/interop.c
@@ -389,18 +389,18 @@
}
SQLITE_API const unsigned char * WINAPI sqlite3_column_text_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
const unsigned char *pval = sqlite3_column_text(stmt, iCol);
- *plen = (pval != 0) ? strlen((char *)pval) : 0;
+ *plen = sqlite3_column_bytes(stmt, iCol);
return pval;
}
SQLITE_API const void * WINAPI sqlite3_column_text16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
const void *pval = sqlite3_column_text16(stmt, iCol);
- *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
+ *plen = sqlite3_column_bytes16(stmt, iCol);
return pval;
}
SQLITE_API int WINAPI sqlite3_finalize_interop(sqlite3_stmt *stmt)
{
@@ -525,18 +525,18 @@
}
SQLITE_API const unsigned char * WINAPI sqlite3_value_text_interop(sqlite3_value *val, int *plen)
{
const unsigned char *pval = sqlite3_value_text(val);
- *plen = (pval != 0) ? strlen((char *)pval) : 0;
+ *plen = sqlite3_value_bytes(val);
return pval;
}
SQLITE_API const void * WINAPI sqlite3_value_text16_interop(sqlite3_value *val, int *plen)
{
const void *pval = sqlite3_value_text16(val);
- *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
+ *plen = sqlite3_value_bytes16(val);
return pval;
}
SQLITE_API void WINAPI sqlite3_result_double_interop(sqlite3_context *pctx, double *val)
{
Index: System.Data.SQLite/SQLite3.cs
==================================================================
--- System.Data.SQLite/SQLite3.cs
+++ System.Data.SQLite/SQLite3.cs
@@ -1202,21 +1202,23 @@
{
#if !SQLITE_STANDARD
int len;
return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len);
#else
- return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), -1);
+ return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index),
+ UnsafeNativeMethods.sqlite3_column_bytes(stmt._sqlite_stmt, index));
#endif
}
internal override DateTime GetDateTime(SQLiteStatement stmt, int index)
{
#if !SQLITE_STANDARD
int len;
return ToDateTime(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len);
#else
- return ToDateTime(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), -1);
+ return ToDateTime(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index),
+ UnsafeNativeMethods.sqlite3_column_bytes(stmt._sqlite_stmt, index));
#endif
}
internal override long GetBytes(SQLiteStatement stmt, int index, int nDataOffset, byte[] bDest, int nStart, int nLength)
{
@@ -1430,11 +1432,12 @@
{
#if !SQLITE_STANDARD
int len;
return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text_interop(ptr, out len), len);
#else
- return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text(ptr), -1);
+ return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text(ptr),
+ UnsafeNativeMethods.sqlite3_value_bytes(ptr));
#endif
}
internal override TypeAffinity GetParamValueType(IntPtr ptr)
{
Index: System.Data.SQLite/SQLite3_UTF16.cs
==================================================================
--- System.Data.SQLite/SQLite3_UTF16.cs
+++ System.Data.SQLite/SQLite3_UTF16.cs
@@ -1,115 +1,115 @@
-/********************************************************
- * ADO.NET 2.0 Data Provider for SQLite Version 3.X
- * Written by Robert Simpson (robert@blackcastlesoft.com)
- *
- * Released to the public domain, use at your own risk!
- ********************************************************/
-
-namespace System.Data.SQLite
-{
- using System;
-
-#if !NET_COMPACT_20 && TRACE_CONNECTION
- using System.Diagnostics;
-#endif
-
- using System.IO;
- using System.Runtime.InteropServices;
-
- ///
- /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode)
- ///
- internal class SQLite3_UTF16 : SQLite3
- {
- internal SQLite3_UTF16(SQLiteDateFormats fmt, DateTimeKind kind)
- : base(fmt, kind)
- {
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////
-
- #region IDisposable "Pattern" Members
- private bool disposed;
- private void CheckDisposed() /* throw */
- {
-#if THROW_ON_DISPOSED
- if (disposed)
- throw new ObjectDisposedException(typeof(SQLite3_UTF16).Name);
-#endif
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////
-
- protected override void Dispose(bool disposing)
- {
- try
- {
- if (!disposed)
- {
- //if (disposing)
- //{
- // ////////////////////////////////////
- // // dispose managed resources here...
- // ////////////////////////////////////
- //}
-
- //////////////////////////////////////
- // release unmanaged resources here...
- //////////////////////////////////////
-
- disposed = true;
- }
- }
- finally
- {
- base.Dispose(disposing);
- }
- }
- #endregion
-
- ///////////////////////////////////////////////////////////////////////////////////////////////
-
- ///
- /// Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8
- ///
- /// A pointer to a UTF-16 string
- /// The length (IN BYTES) of the string
- /// A .NET string
- public override string ToString(IntPtr b, int nbytelen)
- {
- CheckDisposed();
- return UTF16ToString(b, nbytelen);
- }
-
- public static string UTF16ToString(IntPtr b, int nbytelen)
- {
- if (nbytelen == 0 || b == IntPtr.Zero) return "";
-
- if (nbytelen == -1)
- return Marshal.PtrToStringUni(b);
- else
- return Marshal.PtrToStringUni(b, nbytelen / 2);
- }
-
- internal override void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool)
- {
- if (_sql != null) return;
-
- _usePool = usePool;
- _fileName = strFilename;
-
- if (usePool)
- {
- _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);
-
-#if !NET_COMPACT_20 && TRACE_CONNECTION
- Trace.WriteLine(String.Format("Open16 (Pool): {0}", (_sql != null) ? _sql.ToString() : ""));
-#endif
- }
-
- if (_sql == null)
+/********************************************************
+ * ADO.NET 2.0 Data Provider for SQLite Version 3.X
+ * Written by Robert Simpson (robert@blackcastlesoft.com)
+ *
+ * Released to the public domain, use at your own risk!
+ ********************************************************/
+
+namespace System.Data.SQLite
+{
+ using System;
+
+#if !NET_COMPACT_20 && TRACE_CONNECTION
+ using System.Diagnostics;
+#endif
+
+ using System.IO;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode)
+ ///
+ internal class SQLite3_UTF16 : SQLite3
+ {
+ internal SQLite3_UTF16(SQLiteDateFormats fmt, DateTimeKind kind)
+ : base(fmt, kind)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ #region IDisposable "Pattern" Members
+ private bool disposed;
+ private void CheckDisposed() /* throw */
+ {
+#if THROW_ON_DISPOSED
+ if (disposed)
+ throw new ObjectDisposedException(typeof(SQLite3_UTF16).Name);
+#endif
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ protected override void Dispose(bool disposing)
+ {
+ try
+ {
+ if (!disposed)
+ {
+ //if (disposing)
+ //{
+ // ////////////////////////////////////
+ // // dispose managed resources here...
+ // ////////////////////////////////////
+ //}
+
+ //////////////////////////////////////
+ // release unmanaged resources here...
+ //////////////////////////////////////
+
+ disposed = true;
+ }
+ }
+ finally
+ {
+ base.Dispose(disposing);
+ }
+ }
+ #endregion
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ ///
+ /// Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8
+ ///
+ /// A pointer to a UTF-16 string
+ /// The length (IN BYTES) of the string
+ /// A .NET string
+ public override string ToString(IntPtr b, int nbytelen)
+ {
+ CheckDisposed();
+ return UTF16ToString(b, nbytelen);
+ }
+
+ public static string UTF16ToString(IntPtr b, int nbytelen)
+ {
+ if (nbytelen == 0 || b == IntPtr.Zero) return "";
+
+ if (nbytelen == -1)
+ return Marshal.PtrToStringUni(b);
+ else
+ return Marshal.PtrToStringUni(b, nbytelen / 2);
+ }
+
+ internal override void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool)
+ {
+ if (_sql != null) return;
+
+ _usePool = usePool;
+ _fileName = strFilename;
+
+ if (usePool)
+ {
+ _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);
+
+#if !NET_COMPACT_20 && TRACE_CONNECTION
+ Trace.WriteLine(String.Format("Open16 (Pool): {0}", (_sql != null) ? _sql.ToString() : ""));
+#endif
+ }
+
+ if (_sql == null)
{
try
{
// do nothing.
}
@@ -136,139 +136,141 @@
throw new SQLiteException(SQLiteErrorCode.CantOpen, strFilename);
n = UnsafeNativeMethods.sqlite3_open16(strFilename, out db);
}
-#if !NET_COMPACT_20 && TRACE_CONNECTION
- Trace.WriteLine(String.Format("Open16: {0}", db));
+#if !NET_COMPACT_20 && TRACE_CONNECTION
+ Trace.WriteLine(String.Format("Open16: {0}", db));
#endif
if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, null);
_sql = new SQLiteConnectionHandle(db);
- }
- lock (_sql) { /* HACK: Force the SyncBlock to be "created" now. */ }
- }
- _functionsArray = SQLiteFunction.BindFunctions(this, connectionFlags);
- SetTimeout(0);
- GC.KeepAlive(_sql);
- }
-
- internal override void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt)
- {
- switch (_datetimeFormat)
- {
- case SQLiteDateFormats.Ticks:
- case SQLiteDateFormats.JulianDay:
- case SQLiteDateFormats.UnixEpoch:
- {
- base.Bind_DateTime(stmt, flags, index, dt);
- break;
- }
- default:
- {
-#if !PLATFORM_COMPACTFRAMEWORK
- if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
- {
- SQLiteStatementHandle handle =
- (stmt != null) ? stmt._sqlite_stmt : null;
-
- LogBind(handle, index, dt);
- }
-#endif
-
- Bind_Text(stmt, flags, index, ToString(dt));
- break;
- }
- }
- }
-
- internal override void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value)
- {
- SQLiteStatementHandle handle = stmt._sqlite_stmt;
-
-#if !PLATFORM_COMPACTFRAMEWORK
- if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
- {
- LogBind(handle, index, value);
- }
-#endif
-
- SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_text16(handle, index, value, value.Length * 2, (IntPtr)(-1));
- if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError());
- }
-
- internal override DateTime GetDateTime(SQLiteStatement stmt, int index)
- {
- return ToDateTime(GetText(stmt, index));
- }
-
- internal override string ColumnName(SQLiteStatement stmt, int index)
- {
-#if !SQLITE_STANDARD
- int len;
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_name16_interop(stmt._sqlite_stmt, index, out len), len);
-#else
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_name16(stmt._sqlite_stmt, index), -1);
-#endif
- }
-
- internal override string GetText(SQLiteStatement stmt, int index)
- {
-#if !SQLITE_STANDARD
- int len;
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_text16_interop(stmt._sqlite_stmt, index, out len), len);
-#else
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_text16(stmt._sqlite_stmt, index), -1);
-#endif
- }
-
- internal override string ColumnOriginalName(SQLiteStatement stmt, int index)
- {
-#if !SQLITE_STANDARD
- int len;
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_origin_name16_interop(stmt._sqlite_stmt, index, out len), len);
-#else
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_origin_name16(stmt._sqlite_stmt, index), -1);
-#endif
- }
-
- internal override string ColumnDatabaseName(SQLiteStatement stmt, int index)
- {
-#if !SQLITE_STANDARD
- int len;
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_database_name16_interop(stmt._sqlite_stmt, index, out len), len);
-#else
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_database_name16(stmt._sqlite_stmt, index), -1);
-#endif
- }
-
- internal override string ColumnTableName(SQLiteStatement stmt, int index)
- {
-#if !SQLITE_STANDARD
- int len;
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_table_name16_interop(stmt._sqlite_stmt, index, out len), len);
-#else
- return UTF16ToString(UnsafeNativeMethods.sqlite3_column_table_name16(stmt._sqlite_stmt, index), -1);
-#endif
- }
-
- internal override string GetParamValueText(IntPtr ptr)
- {
-#if !SQLITE_STANDARD
- int len;
- return UTF16ToString(UnsafeNativeMethods.sqlite3_value_text16_interop(ptr, out len), len);
-#else
- return UTF16ToString(UnsafeNativeMethods.sqlite3_value_text16(ptr), -1);
-#endif
- }
-
- internal override void ReturnError(IntPtr context, string value)
- {
- UnsafeNativeMethods.sqlite3_result_error16(context, value, value.Length * 2);
- }
-
- internal override void ReturnText(IntPtr context, string value)
- {
- UnsafeNativeMethods.sqlite3_result_text16(context, value, value.Length * 2, (IntPtr)(-1));
- }
- }
-}
+ }
+ lock (_sql) { /* HACK: Force the SyncBlock to be "created" now. */ }
+ }
+ _functionsArray = SQLiteFunction.BindFunctions(this, connectionFlags);
+ SetTimeout(0);
+ GC.KeepAlive(_sql);
+ }
+
+ internal override void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt)
+ {
+ switch (_datetimeFormat)
+ {
+ case SQLiteDateFormats.Ticks:
+ case SQLiteDateFormats.JulianDay:
+ case SQLiteDateFormats.UnixEpoch:
+ {
+ base.Bind_DateTime(stmt, flags, index, dt);
+ break;
+ }
+ default:
+ {
+#if !PLATFORM_COMPACTFRAMEWORK
+ if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
+ {
+ SQLiteStatementHandle handle =
+ (stmt != null) ? stmt._sqlite_stmt : null;
+
+ LogBind(handle, index, dt);
+ }
+#endif
+
+ Bind_Text(stmt, flags, index, ToString(dt));
+ break;
+ }
+ }
+ }
+
+ internal override void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value)
+ {
+ SQLiteStatementHandle handle = stmt._sqlite_stmt;
+
+#if !PLATFORM_COMPACTFRAMEWORK
+ if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
+ {
+ LogBind(handle, index, value);
+ }
+#endif
+
+ SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_text16(handle, index, value, value.Length * 2, (IntPtr)(-1));
+ if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError());
+ }
+
+ internal override DateTime GetDateTime(SQLiteStatement stmt, int index)
+ {
+ return ToDateTime(GetText(stmt, index));
+ }
+
+ internal override string ColumnName(SQLiteStatement stmt, int index)
+ {
+#if !SQLITE_STANDARD
+ int len;
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_name16_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_name16(stmt._sqlite_stmt, index), -1);
+#endif
+ }
+
+ internal override string GetText(SQLiteStatement stmt, int index)
+ {
+#if !SQLITE_STANDARD
+ int len;
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_text16_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_text16(stmt._sqlite_stmt, index),
+ UnsafeNativeMethods.sqlite3_column_bytes16(stmt._sqlite_stmt, index));
+#endif
+ }
+
+ internal override string ColumnOriginalName(SQLiteStatement stmt, int index)
+ {
+#if !SQLITE_STANDARD
+ int len;
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_origin_name16_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_origin_name16(stmt._sqlite_stmt, index), -1);
+#endif
+ }
+
+ internal override string ColumnDatabaseName(SQLiteStatement stmt, int index)
+ {
+#if !SQLITE_STANDARD
+ int len;
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_database_name16_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_database_name16(stmt._sqlite_stmt, index), -1);
+#endif
+ }
+
+ internal override string ColumnTableName(SQLiteStatement stmt, int index)
+ {
+#if !SQLITE_STANDARD
+ int len;
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_table_name16_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_column_table_name16(stmt._sqlite_stmt, index), -1);
+#endif
+ }
+
+ internal override string GetParamValueText(IntPtr ptr)
+ {
+#if !SQLITE_STANDARD
+ int len;
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_value_text16_interop(ptr, out len), len);
+#else
+ return UTF16ToString(UnsafeNativeMethods.sqlite3_value_text16(ptr),
+ UnsafeNativeMethods.sqlite3_value_bytes16(ptr));
+#endif
+ }
+
+ internal override void ReturnError(IntPtr context, string value)
+ {
+ UnsafeNativeMethods.sqlite3_result_error16(context, value, value.Length * 2);
+ }
+
+ internal override void ReturnText(IntPtr context, string value)
+ {
+ UnsafeNativeMethods.sqlite3_result_text16(context, value, value.Length * 2, (IntPtr)(-1));
+ }
+ }
+}
Index: System.Data.SQLite/SQLiteConvert.cs
==================================================================
--- System.Data.SQLite/SQLiteConvert.cs
+++ System.Data.SQLite/SQLiteConvert.cs
@@ -160,17 +160,19 @@
/// The pointer to the memory where the UTF-8 string is encoded
/// The number of bytes to decode
/// A string containing the translated character(s)
public static string UTF8ToString(IntPtr nativestring, int nativestringlen)
{
- if (nativestringlen == 0 || nativestring == IntPtr.Zero) return "";
- if (nativestringlen == -1)
+ if (nativestring == IntPtr.Zero || nativestringlen == 0) return String.Empty;
+ if (nativestringlen < 0)
{
- do
- {
+ nativestringlen = 0;
+
+ while (Marshal.ReadByte(nativestring, nativestringlen) != 0)
nativestringlen++;
- } while (Marshal.ReadByte(nativestring, nativestringlen) != 0);
+
+ if (nativestringlen == 0) return String.Empty;
}
byte[] byteArray = new byte[nativestringlen];
Marshal.Copy(nativestring, byteArray, 0, nativestringlen);
Index: System.Data.SQLite/UnsafeNativeMethods.cs
==================================================================
--- System.Data.SQLite/UnsafeNativeMethods.cs
+++ System.Data.SQLite/UnsafeNativeMethods.cs
@@ -1128,10 +1128,17 @@
internal static extern int sqlite3_column_bytes(IntPtr stmt, int index);
#if !PLATFORM_COMPACTFRAMEWORK
[DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
+ [DllImport(SQLITE_DLL)]
+#endif
+ internal static extern int sqlite3_column_bytes16(IntPtr stmt, int index);
+
+#if !PLATFORM_COMPACTFRAMEWORK
+ [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
+#else
[DllImport(SQLITE_DLL)]
#endif
internal static extern TypeAffinity sqlite3_column_type(IntPtr stmt, int index);
#if !PLATFORM_COMPACTFRAMEWORK
@@ -1160,10 +1167,17 @@
#else
[DllImport(SQLITE_DLL)]
#endif
internal static extern int sqlite3_value_bytes(IntPtr p);
+#if !PLATFORM_COMPACTFRAMEWORK
+ [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
+#else
+ [DllImport(SQLITE_DLL)]
+#endif
+ internal static extern int sqlite3_value_bytes16(IntPtr p);
+
#if !PLATFORM_COMPACTFRAMEWORK
[DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
internal static extern double sqlite3_value_double(IntPtr p);
#else
[DllImport(SQLITE_DLL)]
ADDED Tests/tkt-3567020edf.eagle
Index: Tests/tkt-3567020edf.eagle
==================================================================
--- /dev/null
+++ Tests/tkt-3567020edf.eagle
@@ -0,0 +1,63 @@
+###############################################################################
+#
+# tkt-3567020edf.eagle --
+#
+# Written by Joe Mistachkin.
+# Released to the public domain, use at your own risk!
+#
+###############################################################################
+
+package require Eagle
+package require Eagle.Library
+package require Eagle.Test
+
+runTestPrologue
+
+###############################################################################
+
+package require System.Data.SQLite.Test
+runSQLiteTestPrologue
+
+###############################################################################
+
+runTest {test tkt-3567020edf-1.1 {embedded NUL characters (UTF-8)} -setup {
+ setupDb [set fileName tkt-3567020edf-1.1.db]
+} -body {
+ sql execute $db "CREATE TABLE t1(x);"
+
+ sql execute $db "INSERT INTO t1 (x) VALUES(?);" \
+ [list param1 String one\x00two]
+
+ sql execute -execute reader -format list $db "SELECT x FROM t1;"
+} -cleanup {
+ cleanupDb $fileName
+
+ unset -nocomplain db fileName
+} -constraints \
+{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
+"one\x00two"}
+
+###############################################################################
+
+runTest {test tkt-3567020edf-1.2 {embedded NUL characters (UTF-16)} -setup {
+ setupDb [set fileName tkt-3567020edf-1.2.db] "" "" "" "" \
+ UseUTF16Encoding=True
+} -body {
+ sql execute $db "CREATE TABLE t1(x);"
+
+ sql execute $db "INSERT INTO t1 (x) VALUES(?);" \
+ [list param1 String one\x00two]
+
+ sql execute -execute reader -format list $db "SELECT x FROM t1;"
+} -cleanup {
+ cleanupDb $fileName
+
+ unset -nocomplain db fileName
+} -constraints \
+{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
+"one\x00two"}
+
+###############################################################################
+
+runSQLiteTestEpilogue
+runTestEpilogue