Index: SQLite.Interop/interop.h
==================================================================
--- SQLite.Interop/interop.h
+++ SQLite.Interop/interop.h
@@ -250,25 +250,29 @@
const char *pval = sqlite3_errmsg(db);
*plen = (pval != 0) ? strlen(pval) : 0;
return pval;
}
-__declspec(dllexport) const void * __stdcall sqlite3_errmsg16_interop(sqlite3 *db)
+__declspec(dllexport) const void * __stdcall sqlite3_errmsg16_interop(sqlite3 *db, int *plen)
{
- return sqlite3_errmsg16(db);
+ const void *pval = sqlite3_errmsg16(db);
+ *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
+ return pval;
}
__declspec(dllexport) int __stdcall sqlite3_prepare_interop(sqlite3 *db, const char *sql, int nbytes, sqlite3_stmt **ppstmt, const char **pztail, int *plen)
{
int n = sqlite3_prepare(db, sql, nbytes, ppstmt, pztail);
*plen = (*pztail != 0) ? strlen(*pztail) : 0;
return n;
}
-__declspec(dllexport) int __stdcall sqlite3_prepare16_interop(sqlite3 *db, const void *sql, int nbytes, sqlite3_stmt **ppstmt, const void **pztail)
+__declspec(dllexport) int __stdcall sqlite3_prepare16_interop(sqlite3 *db, const void *sql, int nbytes, sqlite3_stmt **ppstmt, const void **pztail, int *plen)
{
- return sqlite3_prepare16(db, sql, nbytes, ppstmt, pztail);
+ int n = sqlite3_prepare16(db, sql, nbytes, ppstmt, pztail);
+ *plen = (*pztail != 0) ? wcslen((wchar_t *)*pztail) * sizeof(wchar_t) : 0;
+ return n;
}
__declspec(dllexport) int __stdcall sqlite3_bind_blob_interop(sqlite3_stmt *stmt, int iCol, const void *pv, int n, void(*cb)(void*))
{
return sqlite3_bind_blob(stmt, iCol, pv, n, cb);
@@ -331,25 +335,29 @@
const char *pval = sqlite3_column_name(stmt, iCol);
*plen = (pval != 0) ? strlen(pval) : 0;
return pval;
}
-__declspec(dllexport) const void * __stdcall sqlite3_column_name16_interop(sqlite3_stmt *stmt, int iCol)
+__declspec(dllexport) const void * __stdcall sqlite3_column_name16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
- return sqlite3_column_name16(stmt, iCol);
+ const void *pval = sqlite3_column_name16(stmt, iCol);
+ *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
+ return pval;
}
__declspec(dllexport) const char * __stdcall sqlite3_column_decltype_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
const char *pval = sqlite3_column_decltype(stmt, iCol);
*plen = (pval != 0) ? strlen(pval) : 0;
return pval;
}
-__declspec(dllexport) const void * __stdcall sqlite3_column_decltype16_interop(sqlite3_stmt *stmt, int iCol)
+__declspec(dllexport) const void * __stdcall sqlite3_column_decltype16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
- return sqlite3_column_decltype16(stmt, iCol);
+ const void *pval = sqlite3_column_decltype16(stmt, iCol);
+ *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
+ return pval;
}
__declspec(dllexport) int __stdcall sqlite3_step_interop(sqlite3_stmt *stmt)
{
return sqlite3_step(stmt);
@@ -395,13 +403,15 @@
const unsigned char *pval = sqlite3_column_text(stmt, iCol);
*plen = (pval != 0) ? strlen((char *)pval) : 0;
return pval;
}
-__declspec(dllexport) const void * __stdcall sqlite3_column_text16_interop(sqlite3_stmt *stmt, int iCol)
+__declspec(dllexport) const void * __stdcall sqlite3_column_text16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
- return sqlite3_column_text16(stmt, iCol);
+ const void *pval = sqlite3_column_text16(stmt, iCol);
+ *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
+ return pval;
}
__declspec(dllexport) int __stdcall sqlite3_column_type_interop(sqlite3_stmt *stmt, int iCol)
{
return sqlite3_column_type(stmt, iCol);
@@ -533,13 +543,15 @@
const unsigned char *pval = sqlite3_value_text(val);
*plen = (pval != 0) ? strlen((char *)pval) : 0;
return pval;
}
-__declspec(dllexport) const void * __stdcall sqlite3_value_text16_interop(sqlite3_value *val)
+__declspec(dllexport) const void * __stdcall sqlite3_value_text16_interop(sqlite3_value *val, int *plen)
{
- return sqlite3_value_text16(val);
+ const void *pval = sqlite3_value_text16(val);
+ *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
+ return pval;
}
__declspec(dllexport) int __stdcall sqlite3_value_type_interop(sqlite3_value *val)
{
return sqlite3_value_type(val);
Index: System.Data.SQLite/SQLite3_UTF16.cs
==================================================================
--- System.Data.SQLite/SQLite3_UTF16.cs
+++ System.Data.SQLite/SQLite3_UTF16.cs
@@ -30,19 +30,17 @@
{
if (nbytelen == 0) return "";
return Marshal.PtrToStringUni(b, nbytelen / 2);
}
- ///
- /// Another custom string marshaling function
- ///
- /// A pointer to a zero-terminated UTF-16 string
- /// A .NET string
- internal static string ToString(IntPtr b)
- {
- if (b == IntPtr.Zero) return "";
- return Marshal.PtrToStringUni(b);
+ internal override string Version
+ {
+ get
+ {
+ int len;
+ return base.ToString(UnsafeNativeMethods.sqlite3_libversion_interop(out len), len);
+ }
}
internal override void Open(string strFilename)
{
if (_sql != 0) return;
@@ -52,22 +50,24 @@
_functionsArray = SQLiteFunction.BindFunctions(this);
}
internal override string SQLiteLastError()
{
- return ToString(UnsafeNativeMethods.sqlite3_errmsg16_interop(_sql));
+ int len;
+ return ToString(UnsafeNativeMethods.sqlite3_errmsg16_interop(_sql, out len), len);
}
internal override SQLiteStatement Prepare(string strSql, ref int nParamStart, out string strRemain)
{
int stmt;
IntPtr ptr;
+ int len;
- int n = UnsafeNativeMethods.sqlite3_prepare16_interop(_sql, strSql, strSql.Length, out stmt, out ptr);
+ int n = UnsafeNativeMethods.sqlite3_prepare16_interop(_sql, strSql, strSql.Length, out stmt, out ptr, out len);
if (n > 0) throw new SQLiteException(n, SQLiteLastError());
- strRemain = ToString(ptr);
+ strRemain = ToString(ptr, len);
SQLiteStatement cmd = new SQLiteStatement(this, stmt, strSql.Substring(0, strSql.Length - strRemain.Length), ref nParamStart);
return cmd;
}
@@ -74,37 +74,47 @@
internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
{
Bind_Text(stmt, index, ToString(dt));
}
+
+ internal override string Bind_ParamName(SQLiteStatement stmt, int index)
+ {
+ int len;
+ return base.ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(stmt._sqlite_stmt, index, out len), len);
+ }
internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
{
int n = UnsafeNativeMethods.sqlite3_bind_text16_interop(stmt._sqlite_stmt, index, value, value.Length * 2, -1);
if (n > 0) throw new SQLiteException(n, SQLiteLastError());
}
internal override string ColumnName(SQLiteStatement stmt, int index)
{
- return ToString(UnsafeNativeMethods.sqlite3_column_name16_interop(stmt._sqlite_stmt, index));
+ int len;
+ return ToString(UnsafeNativeMethods.sqlite3_column_name16_interop(stmt._sqlite_stmt, index, out len), len);
}
internal override DateTime GetDateTime(SQLiteStatement stmt, int index)
{
return ToDateTime(GetText(stmt, index));
}
internal override string GetText(SQLiteStatement stmt, int index)
{
- return ToString(UnsafeNativeMethods.sqlite3_column_text16_interop(stmt._sqlite_stmt, index));
+ int len;
+ return ToString(UnsafeNativeMethods.sqlite3_column_text16_interop(stmt._sqlite_stmt, index, out len), len);
}
internal override string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity)
{
nAffinity = TypeAffinity.None;
+
+ int len;
+ IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype16_interop(stmt._sqlite_stmt, index, out len);
- IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype16_interop(stmt._sqlite_stmt, index);
- if (p != IntPtr.Zero) return ToString(p);
+ if (p != IntPtr.Zero) return ToString(p, len);
else
{
nAffinity = UnsafeNativeMethods.sqlite3_column_type_interop(stmt._sqlite_stmt, index);
switch (nAffinity)
{
@@ -140,11 +150,12 @@
return nCookie;
}
internal override string GetParamValueText(int ptr)
{
- return ToString(UnsafeNativeMethods.sqlite3_value_text16_interop(ptr));
+ int len;
+ return ToString(UnsafeNativeMethods.sqlite3_value_text16_interop(ptr, out len), len);
}
internal override void ReturnError(int context, string value)
{
UnsafeNativeMethods.sqlite3_result_error16_interop(context, value, value.Length);
Index: System.Data.SQLite/SQLiteConvert.cs
==================================================================
--- System.Data.SQLite/SQLiteConvert.cs
+++ System.Data.SQLite/SQLiteConvert.cs
@@ -210,38 +210,10 @@
default:
return DateTime.ParseExact(dateText, _datetimeFormats, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None);
}
}
- /////
- ///// Attempt to convert the specified string to a datetime value.
- /////
- ///// The string to parse into a datetime
- ///// If successful, a valid datetime structure
- ///// Returns true if the string was a valid ISO8601 datetime, false otherwise.
- //public bool TryToDateTime(string strSrc, out DateTime result)
- //{
- // switch (_datetimeFormat)
- // {
- // case DateTimeFormat.ISO8601:
- // return DateTime.TryParseExact(strSrc, _datetimeFormats, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None, out result);
- // case DateTimeFormat.Ticks:
- // {
- // long n;
- // if (long.TryParse(strSrc, out n) == true)
- // {
- // result = new DateTime(n);
- // return true;
- // }
- // }
- // break;
- // }
-
- // result = DateTime.Now;
- // return false;
- //}
-
///
/// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
///
/// The DateTime value to convert
/// Either a string consisting of the tick count for DateTimeFormat.Ticks, or a date/time in ISO8601 format.
@@ -359,149 +331,144 @@
internal static Type SQLiteTypeToType(SQLiteType t)
{
if (t.Type != DbType.Object)
return SQLiteConvert.DbTypeToType(t.Type);
- switch (t.Affinity)
- {
- case TypeAffinity.Null:
- return typeof(DBNull);
- case TypeAffinity.Int64:
- return typeof(Int64);
- case TypeAffinity.Double:
- return typeof(Double);
- case TypeAffinity.Blob:
- return typeof(byte[]);
- default:
- return typeof(string);
- }
- }
+ return _typeaffinities[(int)t.Affinity];
+ }
+
+ static Type[] _typeaffinities = {
+ null,
+ typeof(Int64),
+ typeof(Double),
+ typeof(string),
+ typeof(byte[]),
+ typeof(DBNull),
+ null,
+ null,
+ null,
+ null,
+ typeof(DateTime),
+ };
///
/// For a given intrinsic type, return a DbType
///
/// The native type to convert
/// The corresponding (closest match) DbType
internal static DbType TypeToDbType(Type typ)
{
- switch (Type.GetTypeCode(typ))
- {
- case TypeCode.Int16:
- return DbType.Int16;
- case TypeCode.Int32:
- return DbType.Int32;
- case TypeCode.Int64:
- return DbType.Int64;
- case TypeCode.UInt16:
- return DbType.UInt16;
- case TypeCode.UInt32:
- return DbType.UInt32;
- case TypeCode.UInt64:
- return DbType.UInt64;
- case TypeCode.Double:
- return DbType.Double;
- case TypeCode.Single:
- return DbType.Single;
- case TypeCode.Decimal:
- return DbType.Decimal;
- case TypeCode.Boolean:
- return DbType.Boolean;
- case TypeCode.SByte:
- case TypeCode.Char:
- return DbType.SByte;
- case TypeCode.DateTime:
- return DbType.DateTime;
- case TypeCode.String:
- return DbType.String;
- case TypeCode.Object:
- if (typ == typeof(byte[])) return DbType.Binary;
- if (typ == typeof(Guid)) return DbType.Guid;
- return DbType.String;
- }
-
- return DbType.String;
- }
+ TypeCode tc = Type.GetTypeCode(typ);
+ if (tc == TypeCode.Object)
+ {
+ if (typ == typeof(byte[])) return DbType.Binary;
+ if (typ == typeof(Guid)) return DbType.Guid;
+ return DbType.String;
+ }
+ return _typetodbtype[(int)tc];
+ }
+
+ private static DbType[] _typetodbtype = {
+ DbType.Object,
+ DbType.Binary,
+ DbType.Object,
+ DbType.Boolean,
+ DbType.SByte,
+ DbType.SByte,
+ DbType.Byte,
+ DbType.Int16, // 7
+ DbType.UInt16,
+ DbType.Int32,
+ DbType.UInt32,
+ DbType.Int64, // 11
+ DbType.UInt64,
+ DbType.Single,
+ DbType.Double,
+ DbType.Decimal,
+ DbType.DateTime,
+ DbType.Object,
+ DbType.String,
+ };
///
/// Convert a DbType to a Type
///
/// The DbType to convert from
/// The closest-match .NET type
internal static Type DbTypeToType(DbType typ)
{
- switch (typ)
- {
- case DbType.Binary:
- return typeof(byte[]);
- case DbType.Boolean:
- return typeof(bool);
- case DbType.Byte:
- return typeof(byte);
- case DbType.Currency:
- case DbType.Decimal:
- return typeof(decimal);
- case DbType.DateTime:
- return typeof(DateTime);
- case DbType.Double:
- return typeof(double);
- case DbType.Guid:
- return typeof(Guid);
- case DbType.Int16:
- case DbType.UInt16:
- return typeof(Int16);
- case DbType.Int32:
- case DbType.UInt32:
- return typeof(Int32);
- case DbType.Int64:
- case DbType.UInt64:
- return typeof(Int64);
- case DbType.String:
- return typeof(string);
- case DbType.SByte:
- return typeof(char);
- case DbType.Single:
- return typeof(float);
- }
- return typeof(string);
- }
+ return _dbtypeToType[(int)typ];
+ }
+
+ private static Type[] _dbtypeToType = {
+ typeof(string), // 0
+ typeof(byte[]), // 1
+ typeof(byte), // 2
+ typeof(bool), // 3
+ typeof(decimal), // 4
+ typeof(DateTime), // 5
+ typeof(DateTime), // 6
+ typeof(decimal), // 7
+ typeof(double), // 8
+ typeof(Guid), // 9
+ typeof(Int16),
+ typeof(Int32),
+ typeof(Int64),
+ typeof(object),
+ typeof(sbyte),
+ typeof(float),
+ typeof(string),
+ typeof(DateTime),
+ typeof(UInt16),
+ typeof(UInt32),
+ typeof(UInt64),
+ typeof(double),
+ typeof(string),
+ typeof(string),
+ typeof(string),
+ typeof(string), // 25 (Xml)
+ };
///
/// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types.
///
/// The type to evaluate
/// The SQLite type affinity for that type.
internal static TypeAffinity TypeToAffinity(Type typ)
{
- switch (Type.GetTypeCode(typ))
- {
- case TypeCode.DBNull:
- return TypeAffinity.Null;
- case TypeCode.String:
- return TypeAffinity.Text;
- case TypeCode.DateTime:
- return TypeAffinity.DateTime;
- case TypeCode.Int16:
- case TypeCode.Int32:
- case TypeCode.Int64:
- case TypeCode.UInt16:
- case TypeCode.UInt32:
- case TypeCode.UInt64:
- case TypeCode.Char:
- case TypeCode.SByte:
- case TypeCode.Byte:
- case TypeCode.Boolean:
- return TypeAffinity.Int64;
- case TypeCode.Double:
- case TypeCode.Single:
- case TypeCode.Decimal:
- return TypeAffinity.Double;
- case TypeCode.Object:
- if (typ == typeof(byte[])) return TypeAffinity.Blob;
- else return TypeAffinity.Text;
- }
- return TypeAffinity.Text;
- }
+ TypeCode tc = Type.GetTypeCode(typ);
+ if (tc == TypeCode.Object)
+ {
+ if (typ == typeof(byte[]))
+ return TypeAffinity.Blob;
+ else
+ return TypeAffinity.Text;
+ }
+ return _typecodeAffinities[(int)tc];
+ }
+
+ private static TypeAffinity[] _typecodeAffinities = {
+ TypeAffinity.Null,
+ TypeAffinity.Blob,
+ TypeAffinity.Null,
+ TypeAffinity.Int64,
+ TypeAffinity.Int64,
+ TypeAffinity.Int64,
+ TypeAffinity.Int64,
+ TypeAffinity.Int64, // 7
+ TypeAffinity.Int64,
+ TypeAffinity.Int64,
+ TypeAffinity.Int64,
+ TypeAffinity.Int64, // 11
+ TypeAffinity.Int64,
+ TypeAffinity.Double,
+ TypeAffinity.Double,
+ TypeAffinity.Double,
+ TypeAffinity.DateTime,
+ TypeAffinity.Null,
+ TypeAffinity.Text,
+ };
///
/// For a given type name, return a closest-match .NET type
///
/// The name of the type to match
Index: System.Data.SQLite/UnsafeNativeMethods.cs
==================================================================
--- System.Data.SQLite/UnsafeNativeMethods.cs
+++ System.Data.SQLite/UnsafeNativeMethods.cs
@@ -184,38 +184,38 @@
[DllImport(SQLITE_DLL)]
internal static extern void sqlite3_realcolnames(int db, int bset);
[DllImport(SQLITE_DLL)]
- internal static extern IntPtr sqlite3_column_text16_interop(int stmt, int index);
+ internal static extern IntPtr sqlite3_column_text16_interop(int stmt, int index, out int len);
[DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)]
internal static extern int sqlite3_open16_interop(string utf16Filename, out int db);
[DllImport(SQLITE_DLL)]
- internal static extern IntPtr sqlite3_errmsg16_interop(int db);
+ internal static extern IntPtr sqlite3_errmsg16_interop(int db, out int len);
[DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)]
- internal static extern int sqlite3_prepare16_interop(int db, string strSql, int sqlLen, out int stmt, out IntPtr ptrRemain);
+ internal static extern int sqlite3_prepare16_interop(int db, string strSql, int sqlLen, out int stmt, out IntPtr ptrRemain, out int len);
[DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)]
internal static extern int sqlite3_bind_text16_interop(int stmt, int index, string value, int nlen, int nTransient);
[DllImport(SQLITE_DLL)]
- internal static extern IntPtr sqlite3_column_name16_interop(int stmt, int index);
+ internal static extern IntPtr sqlite3_column_name16_interop(int stmt, int index, out int len);
[DllImport(SQLITE_DLL)]
- internal static extern IntPtr sqlite3_column_decltype16_interop(int stmt, int index);
+ internal static extern IntPtr sqlite3_column_decltype16_interop(int stmt, int index, out int len);
[DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)]
internal static extern int sqlite3_create_collation16_interop(int db, string strName, int nType, int nArgs, SQLiteCollation func, out int nCookie);
[DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)]
internal static extern int sqlite3_create_function16_interop(int db, string strName, int nArgs, int nType, SQLiteCallback func, SQLiteCallback funcstep, SQLiteCallback funcfinal, out int nCookie);
[DllImport(SQLITE_DLL)]
- internal static extern IntPtr sqlite3_value_text16_interop(int p);
+ internal static extern IntPtr sqlite3_value_text16_interop(int p, out int len);
[DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)]
internal static extern void sqlite3_result_error16_interop(int context, string strName, int nLen);
[DllImport(SQLITE_DLL, CharSet = CharSet.Unicode)]