/********************************************************
* 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 DEBUG
using System.Diagnostics;
#endif
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, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool)
{
if (_sql != null) return;
_usePool = usePool;
if (usePool)
{
_fileName = strFilename;
_sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);
}
if (_sql == null)
{
IntPtr db;
#if !SQLITE_STANDARD
int n = UnsafeNativeMethods.sqlite3_open16_interop(ToUTF8(strFilename), (int)flags, out db);
#else
if ((flags & SQLiteOpenFlagsEnum.Create) == 0 && System.IO.File.Exists(strFilename) == false)
throw new SQLiteException((int)SQLiteErrorCode.CantOpen, strFilename);
int n = UnsafeNativeMethods.sqlite3_open16(strFilename, out db);
#endif
#if DEBUG
Trace.WriteLine(String.Format("Open: {0}", db));
#endif
if (n > 0) throw new SQLiteException(n, null);
_sql = db;
}
_functionsArray = SQLiteFunction.BindFunctions(this);
}
internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
{
switch (_datetimeFormat)
{
case SQLiteDateFormats.Ticks:
{
long value = dt.Ticks;
#if !PLATFORM_COMPACTFRAMEWORK
int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
#else
int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
#endif
if (n > 0) throw new SQLiteException(n, SQLiteLastError());
break;
}
case SQLiteDateFormats.JulianDay:
{
double value = ToJulianDay(dt);
#if !PLATFORM_COMPACTFRAMEWORK
int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, value);
#else
int n = UnsafeNativeMethods.sqlite3_bind_double_interop(stmt._sqlite_stmt, index, ref value);
#endif
if (n > 0) throw new SQLiteException(n, SQLiteLastError());
break;
}
case SQLiteDateFormats.UnixEpoch:
{
long value = Convert.ToInt64(dt.Subtract(UnixEpoch).TotalSeconds);
#if !PLATFORM_COMPACTFRAMEWORK
int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
#else
int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
#endif
if (n > 0) throw new SQLiteException(n, SQLiteLastError());
break;
}
default:
{
Bind_Text(stmt, index, ToString(dt));
break;
}
}
}
internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
{
int n = UnsafeNativeMethods.sqlite3_bind_text16(stmt._sqlite_stmt, index, value, value.Length * 2, (IntPtr)(-1));
if (n > 0) throw new SQLiteException(n, SQLiteLastError());
}
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));
}
}
}