System.Data.SQLite
Check-in [c3bb6c2582]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge fix for ticket [8a426d12eb] along with logging and DateTime handling enhancements to trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c3bb6c2582144f1685e852738386b0847f834ff6
User & Date: mistachkin 2012-02-19 13:31:40
Context
2012-02-19
13:42
More doc updates for release 1.0.80.0. check-in: 9a01e7715d user: mistachkin tags: trunk
13:31
Merge fix for ticket [8a426d12eb] along with logging and DateTime handling enhancements to trunk. check-in: c3bb6c2582 user: mistachkin tags: trunk
13:22
When converting a DateTime instance of an 'Unspecified' kind to a string, use the same kind as the connection, if available. Also, cleanup handling of the default formats for UTC and local time. Closed-Leaf check-in: dbdf2561a4 user: mistachkin tags: logBind
2012-02-15
07:51
Version and doc updates in preparation for release 1.0.80.0. check-in: 50276145d8 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to System.Data.SQLite/SQLite3.cs.

     8      8   namespace System.Data.SQLite
     9      9   {
    10     10     using System;
    11     11   #if DEBUG
    12     12     using System.Diagnostics;
    13     13   #endif
    14     14     using System.Runtime.InteropServices;
           15  +  using System.Text;
    15     16   
    16     17   #if !PLATFORM_COMPACTFRAMEWORK
    17     18     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    18     19   #endif
    19     20     internal delegate void SQLiteLogCallback(IntPtr puser, int err_code, IntPtr message);
    20     21   
    21     22     /// <summary>
................................................................................
   207    208       }
   208    209   
   209    210       internal override bool IsOpen()
   210    211       {
   211    212           return (_sql != null);
   212    213       }
   213    214   
   214         -    internal override void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool)
          215  +    internal override void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool)
   215    216       {
   216    217         if (_sql != null) return;
   217    218   
   218    219         _usePool = usePool;
   219    220         if (usePool)
   220    221         {
   221    222           _fileName = strFilename;
................................................................................
   223    224         }
   224    225   
   225    226         if (_sql == null)
   226    227         {
   227    228           IntPtr db;
   228    229   
   229    230   #if !SQLITE_STANDARD
   230         -        int n = UnsafeNativeMethods.sqlite3_open_interop(ToUTF8(strFilename), (int)flags, out db);
          231  +        int n = UnsafeNativeMethods.sqlite3_open_interop(ToUTF8(strFilename), (int)openFlags, out db);
   231    232   #else
   232         -        int n = UnsafeNativeMethods.sqlite3_open_v2(ToUTF8(strFilename), out db, (int)flags, IntPtr.Zero);
          233  +        int n = UnsafeNativeMethods.sqlite3_open_v2(ToUTF8(strFilename), out db, (int)openFlags, IntPtr.Zero);
   233    234   #endif
   234    235   
   235    236   #if DEBUG
   236    237           Trace.WriteLine(String.Format("Open: {0}", db));
   237    238   #endif
   238    239   
   239    240           if (n > 0) throw new SQLiteException(n, null);
   240    241   
   241    242           _sql = db;
   242    243         }
   243    244         // Bind functions to this connection.  If any previous functions of the same name
   244    245         // were already bound, then the new bindings replace the old.
   245         -      _functionsArray = SQLiteFunction.BindFunctions(this);
          246  +      _functionsArray = SQLiteFunction.BindFunctions(this, connectionFlags);
   246    247         SetTimeout(0);
   247    248       }
   248    249   
   249    250       internal override void ClearPool()
   250    251       {
   251    252         SQLiteConnectionPool.ClearPool(_fileName);
   252    253       }
................................................................................
   364    365                 String.Format("[{0}].", baseSchemaName), String.Empty);
   365    366   
   366    367             strSql = strSql.Replace(
   367    368                 String.Format("{0}.", baseSchemaName), String.Empty);
   368    369           }
   369    370         }
   370    371   
   371         -      if ((cnn != null) &&
   372         -          ((cnn.Flags & SQLiteConnectionFlags.LogPrepare) == SQLiteConnectionFlags.LogPrepare))
          372  +      SQLiteConnectionFlags flags =
          373  +          (cnn != null) ? cnn.Flags : SQLiteConnectionFlags.Default;
          374  +
          375  +#if !PLATFORM_COMPACTFRAMEWORK
          376  +      if ((flags & SQLiteConnectionFlags.LogPrepare) == SQLiteConnectionFlags.LogPrepare)
   373    377         {
   374    378             if ((strSql == null) || (strSql.Length == 0) || (strSql.Trim().Length == 0))
   375    379                 SQLiteLog.LogMessage(0, "Preparing {<nothing>}...");
   376    380             else
   377    381                 SQLiteLog.LogMessage(0, String.Format("Preparing {{{0}}}...", strSql));
   378    382         }
          383  +#endif
   379    384   
   380    385         IntPtr stmt = IntPtr.Zero;
   381    386         IntPtr ptr = IntPtr.Zero;
   382    387         int len = 0;
   383    388         int n = 17;
   384    389         int retries = 0;
   385    390         byte[] b = ToUTF8(strSql);
................................................................................
   476    481             }
   477    482           }
   478    483   
   479    484           if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   480    485   
   481    486           strRemain = UTF8ToString(ptr, len);
   482    487   
   483         -        if (stmt != IntPtr.Zero) cmd = new SQLiteStatement(this, stmt, strSql.Substring(0, strSql.Length - strRemain.Length), previous);
          488  +        if (stmt != IntPtr.Zero) cmd = new SQLiteStatement(this, flags, stmt, strSql.Substring(0, strSql.Length - strRemain.Length), previous);
   484    489   
   485    490           return cmd;
   486    491         }
   487    492         finally
   488    493         {
   489    494           handle.Free();
   490    495         }
   491    496       }
   492    497   
   493         -    internal override void Bind_Double(SQLiteStatement stmt, int index, double value)
   494         -    {
   495         -#if !PLATFORM_COMPACTFRAMEWORK
   496         -      int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, value);
   497         -#else
   498         -      int n = UnsafeNativeMethods.sqlite3_bind_double_interop(stmt._sqlite_stmt, index, ref value);
   499         -#endif
   500         -      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   501         -    }
   502         -
   503         -    internal override void Bind_Int32(SQLiteStatement stmt, int index, int value)
   504         -    {
   505         -      int n = UnsafeNativeMethods.sqlite3_bind_int(stmt._sqlite_stmt, index, value);
   506         -      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   507         -    }
   508         -
   509         -    internal override void Bind_UInt32(SQLiteStatement stmt, int index, uint value)
   510         -    {
   511         -      int n = UnsafeNativeMethods.sqlite3_bind_uint(stmt._sqlite_stmt, index, value);
   512         -      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   513         -    }
   514         -
   515         -    internal override void Bind_Int64(SQLiteStatement stmt, int index, long value)
   516         -    {
   517         -#if !PLATFORM_COMPACTFRAMEWORK
   518         -      int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
   519         -#else
   520         -      int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
   521         -#endif
   522         -      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   523         -    }
   524         -
   525         -    internal override void Bind_UInt64(SQLiteStatement stmt, int index, ulong value)
   526         -    {
   527         -#if !PLATFORM_COMPACTFRAMEWORK
   528         -      int n = UnsafeNativeMethods.sqlite3_bind_uint64(stmt._sqlite_stmt, index, value);
   529         -#else
   530         -      int n = UnsafeNativeMethods.sqlite3_bind_uint64_interop(stmt._sqlite_stmt, index, ref value);
   531         -#endif
   532         -      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   533         -    }
   534         -
   535         -    internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
   536         -    {
   537         -      byte[] b = ToUTF8(value);
   538         -      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
   539         -      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   540         -    }
   541         -
   542         -    internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
   543         -    {
          498  +#if !PLATFORM_COMPACTFRAMEWORK
          499  +    protected static void LogBind(SQLiteStatementHandle handle, int index)
          500  +    {
          501  +        IntPtr handleIntPtr = handle;
          502  +
          503  +        SQLiteLog.LogMessage(0, String.Format(
          504  +            "Binding statement {0} paramter #{1} as NULL...",
          505  +            handleIntPtr, index));
          506  +    }
          507  +
          508  +    protected static void LogBind(SQLiteStatementHandle handle, int index, ValueType value)
          509  +    {
          510  +        IntPtr handleIntPtr = handle;
          511  +
          512  +        SQLiteLog.LogMessage(0, String.Format(
          513  +            "Binding statement {0} paramter #{1} as type {2} with value {{{3}}}...",
          514  +            handleIntPtr, index, value.GetType(), value));
          515  +    }
          516  +
          517  +    private static string FormatDateTime(DateTime value)
          518  +    {
          519  +        StringBuilder result = new StringBuilder();
          520  +
          521  +        result.Append(value.ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFFK"));
          522  +        result.Append(' ');
          523  +        result.Append(value.Kind);
          524  +        result.Append(' ');
          525  +        result.Append(value.Ticks);
          526  +
          527  +        return result.ToString();
          528  +    }
          529  +
          530  +    protected static void LogBind(SQLiteStatementHandle handle, int index, DateTime value)
          531  +    {
          532  +        IntPtr handleIntPtr = handle;
          533  +
          534  +        SQLiteLog.LogMessage(0, String.Format(
          535  +            "Binding statement {0} paramter #{1} as type {2} with value {{{3}}}...",
          536  +            handleIntPtr, index, typeof(DateTime), FormatDateTime(value)));
          537  +    }
          538  +
          539  +    protected static void LogBind(SQLiteStatementHandle handle, int index, string value)
          540  +    {
          541  +        IntPtr handleIntPtr = handle;
          542  +
          543  +        SQLiteLog.LogMessage(0, String.Format(
          544  +            "Binding statement {0} paramter #{1} as type {2} with value {{{3}}}...",
          545  +            handleIntPtr, index, typeof(String), (value != null) ? value : "<null>"));
          546  +    }
          547  +
          548  +    private static string ToHexadecimalString(
          549  +        byte[] array
          550  +        )
          551  +    {
          552  +        if (array == null)
          553  +            return null;
          554  +
          555  +        StringBuilder result = new StringBuilder(array.Length * 2);
          556  +
          557  +        int length = array.Length;
          558  +
          559  +        for (int index = 0; index < length; index++)
          560  +            result.Append(array[index].ToString("x2"));
          561  +
          562  +        return result.ToString();
          563  +    }
          564  +
          565  +    protected static void LogBind(SQLiteStatementHandle handle, int index, byte[] value)
          566  +    {
          567  +        IntPtr handleIntPtr = handle;
          568  +
          569  +        SQLiteLog.LogMessage(0, String.Format(
          570  +            "Binding statement {0} paramter #{1} as type {2} with value {{{3}}}...",
          571  +            handleIntPtr, index, typeof(Byte[]), (value != null) ? ToHexadecimalString(value) : "<null>"));
          572  +    }
          573  +#endif
          574  +
          575  +    internal override void Bind_Double(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, double value)
          576  +    {
          577  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          578  +
          579  +#if !PLATFORM_COMPACTFRAMEWORK
          580  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          581  +        {
          582  +            LogBind(handle, index, value);
          583  +        }
          584  +
          585  +        int n = UnsafeNativeMethods.sqlite3_bind_double(handle, index, value);
          586  +#else
          587  +        int n = UnsafeNativeMethods.sqlite3_bind_double_interop(handle, index, ref value);
          588  +#endif
          589  +        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          590  +    }
          591  +
          592  +    internal override void Bind_Int32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, int value)
          593  +    {
          594  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          595  +
          596  +#if !PLATFORM_COMPACTFRAMEWORK
          597  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          598  +        {
          599  +            LogBind(handle, index, value);
          600  +        }
          601  +#endif
          602  +
          603  +        int n = UnsafeNativeMethods.sqlite3_bind_int(handle, index, value);
          604  +        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          605  +    }
          606  +
          607  +    internal override void Bind_UInt32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, uint value)
          608  +    {
          609  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          610  +
          611  +#if !PLATFORM_COMPACTFRAMEWORK
          612  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          613  +        {
          614  +            LogBind(handle, index, value);
          615  +        }
          616  +#endif
          617  +
          618  +        int n = UnsafeNativeMethods.sqlite3_bind_uint(handle, index, value);
          619  +        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          620  +    }
          621  +
          622  +    internal override void Bind_Int64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, long value)
          623  +    {
          624  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          625  +
          626  +#if !PLATFORM_COMPACTFRAMEWORK
          627  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          628  +        {
          629  +            LogBind(handle, index, value);
          630  +        }
          631  +
          632  +        int n = UnsafeNativeMethods.sqlite3_bind_int64(handle, index, value);
          633  +#else
          634  +        int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(handle, index, ref value);
          635  +#endif
          636  +        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          637  +    }
          638  +
          639  +    internal override void Bind_UInt64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, ulong value)
          640  +    {
          641  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          642  +
          643  +#if !PLATFORM_COMPACTFRAMEWORK
          644  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          645  +        {
          646  +            LogBind(handle, index, value);
          647  +        }
          648  +
          649  +        int n = UnsafeNativeMethods.sqlite3_bind_uint64(handle, index, value);
          650  +#else
          651  +        int n = UnsafeNativeMethods.sqlite3_bind_uint64_interop(handle, index, ref value);
          652  +#endif
          653  +        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          654  +    }
          655  +
          656  +    internal override void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value)
          657  +    {
          658  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          659  +
          660  +#if !PLATFORM_COMPACTFRAMEWORK
          661  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          662  +        {
          663  +            LogBind(handle, index, value);
          664  +        }
          665  +#endif
          666  +
          667  +        byte[] b = ToUTF8(value);
          668  +
          669  +#if !PLATFORM_COMPACTFRAMEWORK
          670  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          671  +        {
          672  +            LogBind(handle, index, b);
          673  +        }
          674  +#endif
          675  +
          676  +        int n = UnsafeNativeMethods.sqlite3_bind_text(handle, index, b, b.Length - 1, (IntPtr)(-1));
          677  +        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          678  +    }
          679  +
          680  +    internal override void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt)
          681  +    {
          682  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          683  +
          684  +#if !PLATFORM_COMPACTFRAMEWORK
          685  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          686  +        {
          687  +            LogBind(handle, index, dt);
          688  +        }
          689  +#endif
          690  +
   544    691           switch (_datetimeFormat)
   545    692           {
   546    693               case SQLiteDateFormats.Ticks:
   547    694                   {
   548    695                       long value = dt.Ticks;
   549    696   
   550    697   #if !PLATFORM_COMPACTFRAMEWORK
   551         -                    int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
          698  +                    if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          699  +                    {
          700  +                        LogBind(handle, index, value);
          701  +                    }
          702  +
          703  +                    int n = UnsafeNativeMethods.sqlite3_bind_int64(handle, index, value);
   552    704   #else
   553         -                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
          705  +                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(handle, index, ref value);
   554    706   #endif
   555    707                       if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   556    708                       break;
   557    709                   }
   558    710               case SQLiteDateFormats.JulianDay:
   559    711                   {
   560    712                       double value = ToJulianDay(dt);
   561    713   
   562    714   #if !PLATFORM_COMPACTFRAMEWORK
   563         -                    int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, value);
          715  +                    if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          716  +                    {
          717  +                        LogBind(handle, index, value);
          718  +                    }
          719  +
          720  +                    int n = UnsafeNativeMethods.sqlite3_bind_double(handle, index, value);
   564    721   #else
   565         -                    int n = UnsafeNativeMethods.sqlite3_bind_double_interop(stmt._sqlite_stmt, index, ref value);
          722  +                    int n = UnsafeNativeMethods.sqlite3_bind_double_interop(handle, index, ref value);
   566    723   #endif
   567    724                       if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   568    725                       break;
   569    726                   }
   570    727               case SQLiteDateFormats.UnixEpoch:
   571    728                   {
   572    729                       long value = Convert.ToInt64(dt.Subtract(UnixEpoch).TotalSeconds);
   573    730   
   574    731   #if !PLATFORM_COMPACTFRAMEWORK
   575         -                    int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
          732  +                    if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          733  +                    {
          734  +                        LogBind(handle, index, value);
          735  +                    }
          736  +
          737  +                    int n = UnsafeNativeMethods.sqlite3_bind_int64(handle, index, value);
   576    738   #else
   577         -                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
          739  +                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(handle, index, ref value);
   578    740   #endif
   579    741                       if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   580    742                       break;
   581    743                   }
   582    744               default:
   583    745                   {
   584    746                       byte[] b = ToUTF8(dt);
   585         -                    int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
          747  +
          748  +#if !PLATFORM_COMPACTFRAMEWORK
          749  +                    if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          750  +                    {
          751  +                        LogBind(handle, index, b);
          752  +                    }
          753  +#endif
          754  +
          755  +                    int n = UnsafeNativeMethods.sqlite3_bind_text(handle, index, b, b.Length - 1, (IntPtr)(-1));
   586    756                       if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   587    757                       break;
   588    758                   }
   589    759           }
   590    760       }
   591    761   
   592         -    internal override void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData)
   593         -    {
   594         -      int n = UnsafeNativeMethods.sqlite3_bind_blob(stmt._sqlite_stmt, index, blobData, blobData.Length, (IntPtr)(-1));
   595         -      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   596         -    }
   597         -
   598         -    internal override void Bind_Null(SQLiteStatement stmt, int index)
   599         -    {
   600         -      int n = UnsafeNativeMethods.sqlite3_bind_null(stmt._sqlite_stmt, index);
   601         -      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   602         -    }
   603         -
   604         -    internal override int Bind_ParamCount(SQLiteStatement stmt)
   605         -    {
   606         -      return UnsafeNativeMethods.sqlite3_bind_parameter_count(stmt._sqlite_stmt);
   607         -    }
   608         -
   609         -    internal override string Bind_ParamName(SQLiteStatement stmt, int index)
   610         -    {
   611         -#if !SQLITE_STANDARD
   612         -      int len;
   613         -      return UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(stmt._sqlite_stmt, index, out len), len);
   614         -#else
   615         -      return UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(stmt._sqlite_stmt, index), -1);
   616         -#endif
   617         -    }
   618         -
   619         -    internal override int Bind_ParamIndex(SQLiteStatement stmt, string paramName)
   620         -    {
   621         -      return UnsafeNativeMethods.sqlite3_bind_parameter_index(stmt._sqlite_stmt, ToUTF8(paramName));
          762  +    internal override void Bind_Blob(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, byte[] blobData)
          763  +    {
          764  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          765  +
          766  +#if !PLATFORM_COMPACTFRAMEWORK
          767  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          768  +        {
          769  +            LogBind(handle, index, blobData);
          770  +        }
          771  +#endif
          772  +
          773  +        int n = UnsafeNativeMethods.sqlite3_bind_blob(handle, index, blobData, blobData.Length, (IntPtr)(-1));
          774  +        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          775  +    }
          776  +
          777  +    internal override void Bind_Null(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index)
          778  +    {
          779  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          780  +
          781  +#if !PLATFORM_COMPACTFRAMEWORK
          782  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          783  +        {
          784  +            LogBind(handle, index);
          785  +        }
          786  +#endif
          787  +
          788  +        int n = UnsafeNativeMethods.sqlite3_bind_null(handle, index);
          789  +        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          790  +    }
          791  +
          792  +    internal override int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags)
          793  +    {
          794  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          795  +        int value = UnsafeNativeMethods.sqlite3_bind_parameter_count(handle);
          796  +
          797  +#if !PLATFORM_COMPACTFRAMEWORK
          798  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          799  +        {
          800  +            IntPtr handleIntPtr = handle;
          801  +
          802  +            SQLiteLog.LogMessage(0, String.Format(
          803  +                "Statement {0} paramter count is {1}.",
          804  +                handleIntPtr, value));
          805  +        }
          806  +#endif
          807  +
          808  +        return value;
          809  +    }
          810  +
          811  +    internal override string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index)
          812  +    {
          813  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          814  +        string name;
          815  +
          816  +#if !SQLITE_STANDARD
          817  +        int len;
          818  +        name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(handle, index, out len), len);
          819  +#else
          820  +        name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(handle, index), -1);
          821  +#endif
          822  +
          823  +#if !PLATFORM_COMPACTFRAMEWORK
          824  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          825  +        {
          826  +            IntPtr handleIntPtr = handle;
          827  +
          828  +            SQLiteLog.LogMessage(0, String.Format(
          829  +                "Statement {0} paramter #{1} name is {{{2}}}.",
          830  +                handleIntPtr, index, name));
          831  +        }
          832  +#endif
          833  +
          834  +        return name;
          835  +    }
          836  +
          837  +    internal override int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName)
          838  +    {
          839  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          840  +        int index = UnsafeNativeMethods.sqlite3_bind_parameter_index(handle, ToUTF8(paramName));
          841  +
          842  +#if !PLATFORM_COMPACTFRAMEWORK
          843  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          844  +        {
          845  +            IntPtr handleIntPtr = handle;
          846  +
          847  +            SQLiteLog.LogMessage(0, String.Format(
          848  +                "Statement {0} paramter index of name {{{1}}} is #{2}.",
          849  +                handleIntPtr, paramName, index));
          850  +        }
          851  +#endif
          852  +
          853  +        return index;
   622    854       }
   623    855   
   624    856       internal override int ColumnCount(SQLiteStatement stmt)
   625    857       {
   626    858         return UnsafeNativeMethods.sqlite3_column_count(stmt._sqlite_stmt);
   627    859       }
   628    860   

Changes to System.Data.SQLite/SQLite3_UTF16.cs.

    84     84   
    85     85         if (nbytelen == -1)
    86     86           return Marshal.PtrToStringUni(b);
    87     87         else
    88     88           return Marshal.PtrToStringUni(b, nbytelen / 2);
    89     89       }
    90     90   
    91         -    internal override void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool)
           91  +    internal override void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool)
    92     92       {
    93     93         if (_sql != null) return;
    94     94   
    95     95         _usePool = usePool;
    96     96         if (usePool)
    97     97         {
    98     98           _fileName = strFilename;
................................................................................
   100    100         }
   101    101   
   102    102         if (_sql == null)
   103    103         {
   104    104           IntPtr db;
   105    105   
   106    106   #if !SQLITE_STANDARD
   107         -        int n = UnsafeNativeMethods.sqlite3_open16_interop(ToUTF8(strFilename), (int)flags, out db);
          107  +        int n = UnsafeNativeMethods.sqlite3_open16_interop(ToUTF8(strFilename), (int)openFlags, out db);
   108    108   #else
   109    109           if ((flags & SQLiteOpenFlagsEnum.Create) == 0 && System.IO.File.Exists(strFilename) == false)
   110    110             throw new SQLiteException((int)SQLiteErrorCode.CantOpen, strFilename);
   111    111   
   112    112           int n = UnsafeNativeMethods.sqlite3_open16(strFilename, out db);
   113    113   #endif
   114    114   
................................................................................
   116    116           Trace.WriteLine(String.Format("Open: {0}", db));
   117    117   #endif
   118    118   
   119    119           if (n > 0) throw new SQLiteException(n, null);
   120    120   
   121    121           _sql = db;
   122    122         }
   123         -      _functionsArray = SQLiteFunction.BindFunctions(this);
          123  +      _functionsArray = SQLiteFunction.BindFunctions(this, connectionFlags);
   124    124       }
   125    125   
   126         -    internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
          126  +    internal override void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt)
   127    127       {
   128    128           switch (_datetimeFormat)
   129    129           {
   130    130               case SQLiteDateFormats.Ticks:
   131         -                {
   132         -                    long value = dt.Ticks;
   133         -
   134         -#if !PLATFORM_COMPACTFRAMEWORK
   135         -                    int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
   136         -#else
   137         -                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
   138         -#endif
   139         -                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   140         -                    break;
   141         -                }
   142    131               case SQLiteDateFormats.JulianDay:
   143         -                {
   144         -                    double value = ToJulianDay(dt);
   145         -
   146         -#if !PLATFORM_COMPACTFRAMEWORK
   147         -                    int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, value);
   148         -#else
   149         -                    int n = UnsafeNativeMethods.sqlite3_bind_double_interop(stmt._sqlite_stmt, index, ref value);
   150         -#endif
   151         -                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   152         -                    break;
   153         -                }
   154    132               case SQLiteDateFormats.UnixEpoch:
   155    133                   {
   156         -                    long value = Convert.ToInt64(dt.Subtract(UnixEpoch).TotalSeconds);
   157         -
   158         -#if !PLATFORM_COMPACTFRAMEWORK
   159         -                    int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
   160         -#else
   161         -                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
   162         -#endif
   163         -                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          134  +                    base.Bind_DateTime(stmt, flags, index, dt);
   164    135                       break;
   165    136                   }
   166    137               default:
   167    138                   {
   168         -                    Bind_Text(stmt, index, ToString(dt));
          139  +#if !PLATFORM_COMPACTFRAMEWORK
          140  +                    if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          141  +                    {
          142  +                        SQLiteStatementHandle handle =
          143  +                            (stmt != null) ? stmt._sqlite_stmt : null;
          144  +
          145  +                        LogBind(handle, index, dt);
          146  +                    }
          147  +#endif
          148  +
          149  +                    Bind_Text(stmt, flags, index, ToString(dt));
   169    150                       break;
   170    151                   }
   171    152           }
   172    153       }
   173    154   
   174         -    internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
          155  +    internal override void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value)
   175    156       {
   176         -      int n = UnsafeNativeMethods.sqlite3_bind_text16(stmt._sqlite_stmt, index, value, value.Length * 2, (IntPtr)(-1));
   177         -      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
          157  +        SQLiteStatementHandle handle = stmt._sqlite_stmt;
          158  +
          159  +#if !PLATFORM_COMPACTFRAMEWORK
          160  +        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
          161  +        {
          162  +            LogBind(handle, index, value);
          163  +        }
          164  +#endif
          165  +
          166  +        int n = UnsafeNativeMethods.sqlite3_bind_text16(handle, index, value, value.Length * 2, (IntPtr)(-1));
          167  +        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   178    168       }
   179    169   
   180    170       internal override DateTime GetDateTime(SQLiteStatement stmt, int index)
   181    171       {
   182    172         return ToDateTime(GetText(stmt, index));
   183    173       }
   184    174   

Changes to System.Data.SQLite/SQLiteBase.cs.

    54     54       /// Opens a database.
    55     55       /// </summary>
    56     56       /// <remarks>
    57     57       /// Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection
    58     58       /// to bind all attributed user-defined functions and collating sequences to the new connection.
    59     59       /// </remarks>
    60     60       /// <param name="strFilename">The filename of the database to open.  SQLite automatically creates it if it doesn't exist.</param>
    61         -    /// <param name="flags">The open flags to use when creating the connection</param>
           61  +    /// <param name="connectionFlags">The flags associated with the parent connection object</param>
           62  +    /// <param name="openFlags">The open flags to use when creating the connection</param>
    62     63       /// <param name="maxPoolSize">The maximum size of the pool for the given filename</param>
    63     64       /// <param name="usePool">If true, the connection can be pulled from the connection pool</param>
    64         -    internal abstract void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool);
           65  +    internal abstract void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool);
    65     66       /// <summary>
    66     67       /// Closes the currently-open database.
    67     68       /// </summary>
    68     69       /// <remarks>
    69     70       /// After the database has been closed implemeters should call SQLiteFunction.UnbindFunctions() to deallocate all interop allocated
    70     71       /// memory associated with the user-defined functions and collating sequences tied to the closed connection.
    71     72       /// </remarks>
................................................................................
   109    110       /// transparently attempt to rebuild the SQL statement and throw an error if that was not possible.
   110    111       /// </summary>
   111    112       /// <param name="stmt">The statement to reset</param>
   112    113       /// <returns>Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock</returns>
   113    114       internal abstract int Reset(SQLiteStatement stmt);
   114    115       internal abstract void Cancel();
   115    116   
   116         -    internal abstract void Bind_Double(SQLiteStatement stmt, int index, double value);
   117         -    internal abstract void Bind_Int32(SQLiteStatement stmt, int index, Int32 value);
   118         -    internal abstract void Bind_UInt32(SQLiteStatement stmt, int index, UInt32 value);
   119         -    internal abstract void Bind_Int64(SQLiteStatement stmt, int index, Int64 value);
   120         -    internal abstract void Bind_UInt64(SQLiteStatement stmt, int index, UInt64 value);
   121         -    internal abstract void Bind_Text(SQLiteStatement stmt, int index, string value);
   122         -    internal abstract void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData);
   123         -    internal abstract void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt);
   124         -    internal abstract void Bind_Null(SQLiteStatement stmt, int index);
          117  +    internal abstract void Bind_Double(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, double value);
          118  +    internal abstract void Bind_Int32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, Int32 value);
          119  +    internal abstract void Bind_UInt32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, UInt32 value);
          120  +    internal abstract void Bind_Int64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, Int64 value);
          121  +    internal abstract void Bind_UInt64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, UInt64 value);
          122  +    internal abstract void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value);
          123  +    internal abstract void Bind_Blob(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, byte[] blobData);
          124  +    internal abstract void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt);
          125  +    internal abstract void Bind_Null(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index);
   125    126   
   126         -    internal abstract int Bind_ParamCount(SQLiteStatement stmt);
   127         -    internal abstract string Bind_ParamName(SQLiteStatement stmt, int index);
   128         -    internal abstract int Bind_ParamIndex(SQLiteStatement stmt, string paramName);
          127  +    internal abstract int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags);
          128  +    internal abstract string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index);
          129  +    internal abstract int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName);
   129    130   
   130    131       internal abstract int ColumnCount(SQLiteStatement stmt);
   131    132       internal abstract string ColumnName(SQLiteStatement stmt, int index);
   132    133       internal abstract TypeAffinity ColumnAffinity(SQLiteStatement stmt, int index);
   133    134       internal abstract string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity);
   134    135       internal abstract int ColumnIndex(SQLiteStatement stmt, string columnName);
   135    136       internal abstract string ColumnOriginalName(SQLiteStatement stmt, int index);
................................................................................
   381    382         None = 0x0,
   382    383   
   383    384         /// <summary>
   384    385         /// Enable logging of all SQL statements to be prepared.
   385    386         /// </summary>
   386    387         LogPrepare = 0x1,
   387    388   
          389  +      /// <summary>
          390  +      /// Enable logging of all bound parameter types and raw values.
          391  +      /// </summary>
          392  +      LogPreBind = 0x2,
          393  +
          394  +      /// <summary>
          395  +      /// Enable logging of all bound parameter strongly typed values.
          396  +      /// </summary>
          397  +      LogBind = 0x4,
          398  +
          399  +      /// <summary>
          400  +      /// Enable logging of all exceptions caught from user-provided
          401  +      /// managed code called from native code via delegates.
          402  +      /// </summary>
          403  +      LogCallbackException = 0x8,
          404  +
          405  +      /// <summary>
          406  +      /// Enable all logging.
          407  +      /// </summary>
          408  +      LogAll = LogPrepare | LogPreBind | LogBind | LogCallbackException,
          409  +
   388    410         /// <summary>
   389    411         /// The default extra flags for new connections.
   390    412         /// </summary>
   391    413         Default = None
   392    414     }
   393    415   
   394    416     // These are the options to the internal sqlite3_config call.

Changes to System.Data.SQLite/SQLiteConnection.cs.

   937    937             flags &= ~SQLiteOpenFlagsEnum.Create;
   938    938           }
   939    939           else
   940    940           {
   941    941             flags |= SQLiteOpenFlagsEnum.ReadWrite;
   942    942           }
   943    943   
   944         -        _sql.Open(fileName, flags, maxPoolSize, usePooling);
          944  +        _sql.Open(fileName, _flags, flags, maxPoolSize, usePooling);
   945    945   
   946    946           _binaryGuid = (SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", Boolean.TrueString)) == true);
   947    947   
   948    948           string password = FindKey(opts, "Password", null);
   949    949   
   950    950           if (String.IsNullOrEmpty(password) == false)
   951    951             _sql.SetPassword(System.Text.UTF8Encoding.UTF8.GetBytes(password));

Changes to System.Data.SQLite/SQLiteConvert.cs.

    72     72         "yyyyMMddHHmm",
    73     73         "yyyyMMddTHHmmssFFFFFFF",
    74     74         "yyyy-MM-dd",
    75     75         "yyyyMMdd",
    76     76         "yy-MM-dd"
    77     77       };
    78     78   
           79  +    /// <summary>
           80  +    /// The internal default format for UTC DateTime values when converting
           81  +    /// to a string.
           82  +    /// </summary>
           83  +    private static readonly string _datetimeFormatUtc = _datetimeFormats[5];
           84  +
           85  +    /// <summary>
           86  +    /// The internal default format for local DateTime values when converting
           87  +    /// to a string.
           88  +    /// </summary>
           89  +    private static readonly string _datetimeFormatLocal = _datetimeFormats[19];
           90  +
    79     91       /// <summary>
    80     92       /// An UTF-8 Encoding instance, so we can convert strings to and from UTF-8
    81     93       /// </summary>
    82     94       private static Encoding _utf8 = new UTF8Encoding();
    83     95       /// <summary>
    84     96       /// The default DateTime format for this instance
    85     97       /// </summary>
................................................................................
   345    357       /// </summary>
   346    358       /// <param name="value">The DateTime to convert</param>
   347    359       /// <returns>The JulianDay value the Datetime represents</returns>
   348    360       public static double ToJulianDay(DateTime value)
   349    361       {
   350    362         return value.ToOADate() + OleAutomationEpochAsJulianDay;
   351    363       }
          364  +
          365  +    /// <summary>
          366  +    /// Returns the default DateTime format string to use for the specified
          367  +    /// DateTimeKind.
          368  +    /// </summary>
          369  +    /// <param name="kind">The DateTimeKind to use.</param>
          370  +    /// <returns>
          371  +    /// The default DateTime format string to use for the specified DateTimeKind.
          372  +    /// </returns>
          373  +    private static string GetDateTimeKindFormat(DateTimeKind kind)
          374  +    {
          375  +        return (kind == DateTimeKind.Utc) ? _datetimeFormatUtc : _datetimeFormatLocal;
          376  +    }
   352    377   
   353    378       /// <summary>
   354    379       /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
   355    380       /// </summary>
   356    381       /// <param name="dateValue">The DateTime value to convert</param>
   357    382       /// <returns>Either a string containing the long integer number of 100-nanosecond units since System.DateTime.MinValue, a
   358    383       /// Julian day double, an integer number of seconds since the Unix epoch, a culture-independent formatted date and time
   359    384       /// string, a formatted date and time string in the current culture, or an ISO8601-format date/time string.</returns>
   360    385       public string ToString(DateTime dateValue)
   361    386       {
   362         -      switch (_datetimeFormat)
   363         -      {
   364         -        case SQLiteDateFormats.Ticks:
   365         -          return dateValue.Ticks.ToString(CultureInfo.InvariantCulture);
   366         -        case SQLiteDateFormats.JulianDay:
   367         -          return ToJulianDay(dateValue).ToString(CultureInfo.InvariantCulture);
   368         -        case SQLiteDateFormats.UnixEpoch:
   369         -          return ((long)(dateValue.Subtract(UnixEpoch).Ticks / TimeSpan.TicksPerSecond)).ToString();
   370         -        case SQLiteDateFormats.InvariantCulture:
   371         -          return dateValue.ToString(FullFormat, CultureInfo.InvariantCulture);
   372         -        case SQLiteDateFormats.CurrentCulture:
   373         -          return dateValue.ToString(FullFormat, CultureInfo.CurrentCulture);
   374         -        default:
   375         -          return (dateValue.Kind == DateTimeKind.Utc) ?
   376         -              dateValue.ToString(_datetimeFormats[5], CultureInfo.InvariantCulture) : // include "Z"
   377         -              dateValue.ToString(_datetimeFormats[19], CultureInfo.InvariantCulture);
   378         -      }
          387  +        switch (_datetimeFormat)
          388  +        {
          389  +            case SQLiteDateFormats.Ticks:
          390  +                return dateValue.Ticks.ToString(CultureInfo.InvariantCulture);
          391  +            case SQLiteDateFormats.JulianDay:
          392  +                return ToJulianDay(dateValue).ToString(CultureInfo.InvariantCulture);
          393  +            case SQLiteDateFormats.UnixEpoch:
          394  +                return ((long)(dateValue.Subtract(UnixEpoch).Ticks / TimeSpan.TicksPerSecond)).ToString();
          395  +            case SQLiteDateFormats.InvariantCulture:
          396  +                return dateValue.ToString(FullFormat, CultureInfo.InvariantCulture);
          397  +            case SQLiteDateFormats.CurrentCulture:
          398  +                return dateValue.ToString(FullFormat, CultureInfo.CurrentCulture);
          399  +            default:
          400  +                return (dateValue.Kind == DateTimeKind.Unspecified) ?
          401  +                    DateTime.SpecifyKind(dateValue, _datetimeKind).ToString(
          402  +                        GetDateTimeKindFormat(_datetimeKind), CultureInfo.InvariantCulture) :
          403  +                    dateValue.ToString(GetDateTimeKindFormat(dateValue.Kind), CultureInfo.InvariantCulture);
          404  +        }
   379    405       }
   380    406   
   381    407       /// <summary>
   382    408       /// Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime.
   383    409       /// </summary>
   384    410       /// <remarks>
   385    411       /// This is a convenience function, which first calls ToString() on the IntPtr to convert it to a string, then calls

Changes to System.Data.SQLite/SQLiteFunction.cs.

    32     32     {
    33     33       private class AggregateData
    34     34       {
    35     35         internal int _count = 1;
    36     36         internal object _data;
    37     37       }
    38     38   
           39  +    /////////////////////////////////////////////////////////////////////////
           40  +
           41  +    #region Private Constants
           42  +    /// <summary>
           43  +    /// The error code used for logging exceptions caught in user-provided
           44  +    /// code.
           45  +    /// </summary>
           46  +    private const int COR_E_EXCEPTION = unchecked((int)0x80131500);
           47  +    #endregion
           48  +
           49  +    /////////////////////////////////////////////////////////////////////////
           50  +
    39     51       /// <summary>
    40     52       /// The base connection this function is attached to
    41     53       /// </summary>
    42     54       internal SQLiteBase              _base;
    43     55   
    44     56       /// <summary>
    45     57       /// Internal array used to keep track of aggregate function context data
    46     58       /// </summary>
    47         -    private Dictionary<long, AggregateData> _contextDataList;
           59  +    private Dictionary<IntPtr, AggregateData> _contextDataList;
           60  +
           61  +    /// <summary>
           62  +    /// The connection flags associated with this object (this should be the
           63  +    /// same value as the flags associated with the parent connection object).
           64  +    /// </summary>
           65  +    private SQLiteConnectionFlags _flags;
    48     66   
    49     67       /// <summary>
    50     68       /// Holds a reference to the callback function for user functions
    51     69       /// </summary>
    52     70       private SQLiteCallback  _InvokeFunc;
    53     71       /// <summary>
    54     72       /// Holds a reference to the callbakc function for stepping in an aggregate function
................................................................................
    76     94       private static List<SQLiteFunctionAttribute> _registeredFunctions;
    77     95   
    78     96       /// <summary>
    79     97       /// Internal constructor, initializes the function's internal variables.
    80     98       /// </summary>
    81     99       protected SQLiteFunction()
    82    100       {
    83         -      _contextDataList = new Dictionary<long, AggregateData>();
          101  +      _contextDataList = new Dictionary<IntPtr, AggregateData>();
    84    102       }
    85    103   
    86    104       ///////////////////////////////////////////////////////////////////////////////////////////////
    87    105   
    88    106       #region IDisposable Members
    89    107       /// <summary>
    90    108       /// Disposes of any active contextData variables that were not automatically cleaned up.  Sometimes this can happen if
................................................................................
   123    141               {
   124    142                   ////////////////////////////////////
   125    143                   // dispose managed resources here...
   126    144                   ////////////////////////////////////
   127    145   
   128    146                   IDisposable disp;
   129    147   
   130         -                foreach (KeyValuePair<long, AggregateData> kv in _contextDataList)
          148  +                foreach (KeyValuePair<IntPtr, AggregateData> kv in _contextDataList)
   131    149                   {
   132    150                       disp = kv.Value._data as IDisposable;
   133    151                       if (disp != null)
   134    152                           disp.Dispose();
   135    153                   }
   136    154                   _contextDataList.Clear();
          155  +                _contextDataList = null;
          156  +
          157  +                _flags = SQLiteConnectionFlags.None;
   137    158   
   138    159                   _InvokeFunc = null;
   139    160                   _StepFunc = null;
   140    161                   _FinalFunc = null;
   141    162                   _CompareFunc = null;
   142    163                   _base = null;
   143         -                _contextDataList = null;
   144    164               }
   145    165   
   146    166               //////////////////////////////////////
   147    167               // release unmanaged resources here...
   148    168               //////////////////////////////////////
   149    169   
   150    170               disposed = true;
................................................................................
   346    366             _base.ReturnBlob(context, (byte[])returnValue);
   347    367             return;
   348    368         }
   349    369       }
   350    370   
   351    371       /// <summary>
   352    372       /// Internal scalar callback function, which wraps the raw context pointer and calls the virtual Invoke() method.
          373  +    /// WARNING: Must not throw exceptions.
   353    374       /// </summary>
   354    375       /// <param name="context">A raw context pointer</param>
   355    376       /// <param name="nArgs">Number of arguments passed in</param>
   356    377       /// <param name="argsptr">A pointer to the array of arguments</param>
   357    378       internal void ScalarCallback(IntPtr context, int nArgs, IntPtr argsptr)
   358    379       {
   359         -      _context = context;
   360         -      SetReturnValue(context, Invoke(ConvertParams(nArgs, argsptr)));
          380  +        try
          381  +        {
          382  +            _context = context;
          383  +            SetReturnValue(context,
          384  +                Invoke(ConvertParams(nArgs, argsptr))); /* throw */
          385  +        }
          386  +#if !PLATFORM_COMPACTFRAMEWORK
          387  +        catch (Exception e) /* NOTE: Must catch ALL. */
          388  +        {
          389  +            try
          390  +            {
          391  +                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
          392  +                        SQLiteConnectionFlags.LogCallbackException)
          393  +                {
          394  +                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
          395  +                        "Caught exception in \"Invoke\" method: {0}",
          396  +                        e)); /* throw */
          397  +                }
          398  +            }
          399  +            catch
          400  +            {
          401  +                // do nothing.
          402  +            }
          403  +        }
          404  +#else
          405  +        catch /* NOTE: Must catch ALL. */
          406  +        {
          407  +            // do nothing (Windows CE).
          408  +        }
          409  +#endif
          410  +    }
          411  +
          412  +    /// <summary>
          413  +    /// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function.
          414  +    /// WARNING: Must not throw exceptions.
          415  +    /// </summary>
          416  +    /// <param name="ptr">Not used</param>
          417  +    /// <param name="len1">Length of the string pv1</param>
          418  +    /// <param name="ptr1">Pointer to the first string to compare</param>
          419  +    /// <param name="len2">Length of the string pv2</param>
          420  +    /// <param name="ptr2">Pointer to the second string to compare</param>
          421  +    /// <returns>Returns -1 if the first string is less than the second.  0 if they are equal, or 1 if the first string is greater
          422  +    /// than the second.  Returns 0 if an exception is caught.</returns>
          423  +    internal int CompareCallback(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2)
          424  +    {
          425  +        try
          426  +        {
          427  +            return Compare(SQLiteConvert.UTF8ToString(ptr1, len1),
          428  +                SQLiteConvert.UTF8ToString(ptr2, len2)); /* throw */
          429  +        }
          430  +#if !PLATFORM_COMPACTFRAMEWORK
          431  +        catch (Exception e) /* NOTE: Must catch ALL. */
          432  +        {
          433  +            try
          434  +            {
          435  +                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
          436  +                        SQLiteConnectionFlags.LogCallbackException)
          437  +                {
          438  +                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
          439  +                        "Caught exception in \"Compare\" method: {0}",
          440  +                        e)); /* throw */
          441  +                }
          442  +            }
          443  +            catch
          444  +            {
          445  +                // do nothing.
          446  +            }
          447  +        }
          448  +#else
          449  +        catch /* NOTE: Must catch ALL. */
          450  +        {
          451  +            // do nothing (Windows CE).
          452  +        }
          453  +#endif
          454  +
          455  +        return 0;
   361    456       }
   362    457   
   363    458       /// <summary>
   364    459       /// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function.
          460  +    /// WARNING: Must not throw exceptions.
   365    461       /// </summary>
   366    462       /// <param name="ptr">Not used</param>
   367    463       /// <param name="len1">Length of the string pv1</param>
   368    464       /// <param name="ptr1">Pointer to the first string to compare</param>
   369    465       /// <param name="len2">Length of the string pv2</param>
   370    466       /// <param name="ptr2">Pointer to the second string to compare</param>
   371    467       /// <returns>Returns -1 if the first string is less than the second.  0 if they are equal, or 1 if the first string is greater
   372         -    /// than the second.</returns>
   373         -    internal int CompareCallback(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2)
   374         -    {
   375         -      return Compare(SQLiteConvert.UTF8ToString(ptr1, len1), SQLiteConvert.UTF8ToString(ptr2, len2));
   376         -    }
   377         -
          468  +    /// than the second.  Returns 0 if an exception is caught.</returns>
   378    469       internal int CompareCallback16(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2)
   379    470       {
   380         -      return Compare(SQLite3_UTF16.UTF16ToString(ptr1, len1), SQLite3_UTF16.UTF16ToString(ptr2, len2));
          471  +        try
          472  +        {
          473  +            return Compare(SQLite3_UTF16.UTF16ToString(ptr1, len1),
          474  +                SQLite3_UTF16.UTF16ToString(ptr2, len2)); /* throw */
          475  +        }
          476  +#if !PLATFORM_COMPACTFRAMEWORK
          477  +        catch (Exception e) /* NOTE: Must catch ALL. */
          478  +        {
          479  +            try
          480  +            {
          481  +                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
          482  +                        SQLiteConnectionFlags.LogCallbackException)
          483  +                {
          484  +                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
          485  +                        "Caught exception in \"Compare\" method: {0}",
          486  +                        e)); /* throw */
          487  +                }
          488  +            }
          489  +            catch
          490  +            {
          491  +                // do nothing.
          492  +            }
          493  +        }
          494  +#else
          495  +        catch /* NOTE: Must catch ALL. */
          496  +        {
          497  +            // do nothing (Windows CE).
          498  +        }
          499  +#endif
          500  +
          501  +        return 0;
   381    502       }
   382    503   
   383    504       /// <summary>
   384    505       /// The internal aggregate Step function callback, which wraps the raw context pointer and calls the virtual Step() method.
          506  +    /// WARNING: Must not throw exceptions.
   385    507       /// </summary>
   386    508       /// <remarks>
   387    509       /// This function takes care of doing the lookups and getting the important information put together to call the Step() function.
   388    510       /// That includes pulling out the user's contextData and updating it after the call is made.  We use a sorted list for this so
   389    511       /// binary searches can be done to find the data.
   390    512       /// </remarks>
   391    513       /// <param name="context">A raw context pointer</param>
   392    514       /// <param name="nArgs">Number of arguments passed in</param>
   393    515       /// <param name="argsptr">A pointer to the array of arguments</param>
   394    516       internal void StepCallback(IntPtr context, int nArgs, IntPtr argsptr)
   395    517       {
   396         -      long nAux;
   397         -      AggregateData data;
   398         -
   399         -      nAux = (long)_base.AggregateContext(context);
   400         -      if (_contextDataList.TryGetValue(nAux, out data) == false)
   401         -      {
   402         -        data = new AggregateData();
   403         -        _contextDataList[nAux] = data;
   404         -      }
   405         -
   406         -      try
   407         -      {
   408         -        _context = context;
   409         -        Step(ConvertParams(nArgs, argsptr), data._count, ref data._data);
   410         -      }
   411         -      finally
   412         -      {
   413         -        data._count++;
   414         -      }
          518  +        try
          519  +        {
          520  +            AggregateData data = null;
          521  +
          522  +            if (_base != null)
          523  +            {
          524  +                IntPtr nAux = _base.AggregateContext(context);
          525  +
          526  +                if ((_contextDataList != null) &&
          527  +                    !_contextDataList.TryGetValue(nAux, out data))
          528  +                {
          529  +                    data = new AggregateData();
          530  +                    _contextDataList[nAux] = data;
          531  +                }
          532  +            }
          533  +
          534  +            if (data == null)
          535  +                data = new AggregateData();
          536  +
          537  +            try
          538  +            {
          539  +                _context = context;
          540  +                Step(ConvertParams(nArgs, argsptr),
          541  +                    data._count, ref data._data); /* throw */
          542  +            }
          543  +            finally
          544  +            {
          545  +                data._count++;
          546  +            }
          547  +        }
          548  +#if !PLATFORM_COMPACTFRAMEWORK
          549  +        catch (Exception e) /* NOTE: Must catch ALL. */
          550  +        {
          551  +            try
          552  +            {
          553  +                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
          554  +                        SQLiteConnectionFlags.LogCallbackException)
          555  +                {
          556  +                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
          557  +                        "Caught exception in \"Step\" method: {1}",
          558  +                        e)); /* throw */
          559  +                }
          560  +            }
          561  +            catch
          562  +            {
          563  +                // do nothing.
          564  +            }
          565  +        }
          566  +#else
          567  +        catch /* NOTE: Must catch ALL. */
          568  +        {
          569  +            // do nothing (Windows CE).
          570  +        }
          571  +#endif
   415    572       }
   416    573   
   417    574       /// <summary>
   418    575       /// An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method.
          576  +    /// WARNING: Must not throw exceptions.
   419    577       /// </summary>
   420    578       /// <param name="context">A raw context pointer</param>
   421    579       internal void FinalCallback(IntPtr context)
   422    580       {
   423         -      long n = (long)_base.AggregateContext(context);
   424         -      object obj = null;
   425         -
   426         -      if (_contextDataList.ContainsKey(n))
   427         -      {
   428         -        obj = _contextDataList[n]._data;
   429         -        _contextDataList.Remove(n);
   430         -      }
   431         -
   432         -      _context = context;
   433         -      SetReturnValue(context, Final(obj));
   434         -
   435         -      IDisposable disp = obj as IDisposable;
   436         -      if (disp != null) disp.Dispose();
          581  +        try
          582  +        {
          583  +            object obj = null;
          584  +
          585  +            if (_base != null)
          586  +            {
          587  +                IntPtr n = _base.AggregateContext(context);
          588  +                AggregateData aggData;
          589  +
          590  +                if ((_contextDataList != null) &&
          591  +                    _contextDataList.TryGetValue(n, out aggData))
          592  +                {
          593  +                    obj = aggData._data;
          594  +                    _contextDataList.Remove(n);
          595  +                }
          596  +            }
          597  +
          598  +            try
          599  +            {
          600  +                _context = context;
          601  +                SetReturnValue(context, Final(obj)); /* throw */
          602  +            }
          603  +            finally
          604  +            {
          605  +                IDisposable disp = obj as IDisposable;
          606  +                if (disp != null) disp.Dispose(); /* throw */
          607  +            }
          608  +        }
          609  +#if !PLATFORM_COMPACTFRAMEWORK
          610  +        catch (Exception e) /* NOTE: Must catch ALL. */
          611  +        {
          612  +            try
          613  +            {
          614  +                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
          615  +                        SQLiteConnectionFlags.LogCallbackException)
          616  +                {
          617  +                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
          618  +                        "Caught exception in \"Final\" method: {1}",
          619  +                        e)); /* throw */
          620  +                }
          621  +            }
          622  +            catch
          623  +            {
          624  +                // do nothing.
          625  +            }
          626  +        }
          627  +#else
          628  +        catch /* NOTE: Must catch ALL. */
          629  +        {
          630  +            // do nothing (Windows CE).
          631  +        }
          632  +#endif
   437    633       }
   438    634   
   439    635       /// <summary>
   440    636       /// Using reflection, enumerate all assemblies in the current appdomain looking for classes that
   441    637       /// have a SQLiteFunctionAttribute attribute, and registering them accordingly.
   442    638       /// </summary>
   443    639   #if !PLATFORM_COMPACTFRAMEWORK
................................................................................
   536    732       /// as the connection (UTF-8 or UTF-16).
   537    733       /// </summary>
   538    734       /// <remarks>
   539    735       /// The wrapper functions that interop with SQLite will create a unique cookie value, which internally is a pointer to
   540    736       /// all the wrapped callback functions.  The interop function uses it to map CDecl callbacks to StdCall callbacks.
   541    737       /// </remarks>
   542    738       /// <param name="sqlbase">The base object on which the functions are to bind</param>
          739  +    /// <param name="flags">The flags associated with the parent connection object</param>
   543    740       /// <returns>Returns an array of functions which the connection object should retain until the connection is closed.</returns>
   544         -    internal static SQLiteFunction[] BindFunctions(SQLiteBase sqlbase)
          741  +    internal static SQLiteFunction[] BindFunctions(SQLiteBase sqlbase, SQLiteConnectionFlags flags)
   545    742       {
   546    743         SQLiteFunction f;
   547    744         List<SQLiteFunction> lFunctions = new List<SQLiteFunction>();
   548    745   
   549    746         foreach (SQLiteFunctionAttribute pr in _registeredFunctions)
   550    747         {
   551    748           f = (SQLiteFunction)Activator.CreateInstance(pr._instanceType);
          749  +
   552    750           f._base = sqlbase;
          751  +        f._flags = flags;
   553    752           f._InvokeFunc = (pr.FuncType == FunctionType.Scalar) ? new SQLiteCallback(f.ScalarCallback) : null;
   554    753           f._StepFunc = (pr.FuncType == FunctionType.Aggregate) ? new SQLiteCallback(f.StepCallback) : null;
   555    754           f._FinalFunc = (pr.FuncType == FunctionType.Aggregate) ? new SQLiteFinalCallback(f.FinalCallback) : null;
   556    755           f._CompareFunc = (pr.FuncType == FunctionType.Collation) ? new SQLiteCollation(f.CompareCallback) : null;
   557    756           f._CompareFunc16 = (pr.FuncType == FunctionType.Collation) ? new SQLiteCollation(f.CompareCallback16) : null;
   558    757   
   559    758           if (pr.FuncType != FunctionType.Collation)

Changes to System.Data.SQLite/SQLiteStatement.cs.

    40     40       /// </summary>
    41     41       internal SQLiteParameter[] _paramValues;
    42     42       /// <summary>
    43     43       /// Command this statement belongs to (if any)
    44     44       /// </summary>
    45     45       internal SQLiteCommand     _command;
    46     46   
           47  +    /// <summary>
           48  +    /// The flags associated with the parent connection object.
           49  +    /// </summary>
           50  +    private SQLiteConnectionFlags _flags;
           51  +
    47     52       private string[] _types;
    48     53   
    49     54       /// <summary>
    50     55       /// Initializes the statement and attempts to get all information about parameters in the statement
    51     56       /// </summary>
    52     57       /// <param name="sqlbase">The base SQLite object</param>
           58  +    /// <param name="flags">The flags associated with the parent connection object</param>
    53     59       /// <param name="stmt">The statement</param>
    54     60       /// <param name="strCommand">The command text for this statement</param>
    55     61       /// <param name="previous">The previous command in a multi-statement command</param>
    56         -    internal SQLiteStatement(SQLiteBase sqlbase, SQLiteStatementHandle stmt, string strCommand, SQLiteStatement previous)
           62  +    internal SQLiteStatement(SQLiteBase sqlbase, SQLiteConnectionFlags flags, SQLiteStatementHandle stmt, string strCommand, SQLiteStatement previous)
    57     63       {
    58     64         _sql     = sqlbase;
    59     65         _sqlite_stmt = stmt;
    60     66         _sqlStatement  = strCommand;
           67  +      _flags = flags;
    61     68   
    62     69         // Determine parameters for this statement (if any) and prepare space for them.
    63     70         int nCmdStart = 0;
    64         -      int n = _sql.Bind_ParamCount(this);
           71  +      int n = _sql.Bind_ParamCount(this, _flags);
    65     72         int x;
    66     73         string s;
    67     74   
    68     75         if (n > 0)
    69     76         {
    70     77           if (previous != null)
    71     78             nCmdStart = previous._unnamedParameters;
    72     79   
    73     80           _paramNames = new string[n];
    74     81           _paramValues = new SQLiteParameter[n];
    75     82   
    76     83           for (x = 0; x < n; x++)
    77     84           {
    78         -          s = _sql.Bind_ParamName(this, x + 1);
           85  +          s = _sql.Bind_ParamName(this, _flags, x + 1);
    79     86             if (String.IsNullOrEmpty(s))
    80     87             {
    81     88               s = String.Format(CultureInfo.InvariantCulture, ";{0}", nCmdStart);
    82     89               nCmdStart++;
    83     90               _unnamedParameters++;
    84     91             }
    85     92             _paramNames[x] = s;
................................................................................
   264    271       {
   265    272         if (param == null)
   266    273           throw new SQLiteException((int)SQLiteErrorCode.Error, "Insufficient parameters supplied to the command");
   267    274   
   268    275         object obj = param.Value;
   269    276         DbType objType = param.DbType;
   270    277   
   271         -      if (Convert.IsDBNull(obj) || obj == null)
          278  +      if ((obj != null) && (objType == DbType.Object))
          279  +          objType = SQLiteConvert.TypeToDbType(obj.GetType());
          280  +
          281  +#if !PLATFORM_COMPACTFRAMEWORK
          282  +      if ((_flags & SQLiteConnectionFlags.LogPreBind) == SQLiteConnectionFlags.LogPreBind)
          283  +      {
          284  +          IntPtr handle = _sqlite_stmt;
          285  +
          286  +          SQLiteLog.LogMessage(0, String.Format(
          287  +              "Binding statement {0} paramter #{1} with database type {2} and raw value {{{3}}}...",
          288  +              handle, index, objType, obj));
          289  +      }
          290  +#endif
          291  +
          292  +      if ((obj == null) || Convert.IsDBNull(obj))
   272    293         {
   273         -        _sql.Bind_Null(this, index);
          294  +          _sql.Bind_Null(this, _flags, index);
   274    295           return;
   275    296         }
   276    297   
   277         -      if (objType == DbType.Object)
   278         -        objType = SQLiteConvert.TypeToDbType(obj.GetType());
   279         -
   280    298         switch (objType)
   281    299         {
   282    300           case DbType.Date:
   283    301           case DbType.Time:
   284    302           case DbType.DateTime:
   285    303             //
   286    304             // NOTE: The old method (commented below) does not honor the selected date format
   287    305             //       for the connection.
   288    306             // _sql.Bind_DateTime(this, index, Convert.ToDateTime(obj, CultureInfo.CurrentCulture));
   289         -          _sql.Bind_DateTime(this, index, (obj is string) ?
          307  +            _sql.Bind_DateTime(this, _flags, index, (obj is string) ?
   290    308                 _sql.ToDateTime((string)obj) : Convert.ToDateTime(obj, CultureInfo.CurrentCulture));
   291    309             break;
   292    310           case DbType.Boolean:
   293         -          _sql.Bind_Int32(this, index, ToBoolean(obj, CultureInfo.CurrentCulture) ? 1 : 0);
          311  +          _sql.Bind_Int32(this, _flags, index, ToBoolean(obj, CultureInfo.CurrentCulture) ? 1 : 0);
   294    312             break;
   295    313           case DbType.SByte:
   296         -          _sql.Bind_Int32(this, index, Convert.ToSByte(obj, CultureInfo.CurrentCulture));
          314  +          _sql.Bind_Int32(this, _flags, index, Convert.ToSByte(obj, CultureInfo.CurrentCulture));
   297    315             break;
   298    316           case DbType.Int16:
   299         -          _sql.Bind_Int32(this, index, Convert.ToInt16(obj, CultureInfo.CurrentCulture));
          317  +          _sql.Bind_Int32(this, _flags, index, Convert.ToInt16(obj, CultureInfo.CurrentCulture));
   300    318             break;
   301    319           case DbType.Int32:
   302         -          _sql.Bind_Int32(this, index, Convert.ToInt32(obj, CultureInfo.CurrentCulture));
          320  +          _sql.Bind_Int32(this, _flags, index, Convert.ToInt32(obj, CultureInfo.CurrentCulture));
   303    321             break;
   304    322           case DbType.Int64:
   305         -          _sql.Bind_Int64(this, index, Convert.ToInt64(obj, CultureInfo.CurrentCulture));
          323  +          _sql.Bind_Int64(this, _flags, index, Convert.ToInt64(obj, CultureInfo.CurrentCulture));
   306    324             break;
   307    325           case DbType.Byte:
   308         -          _sql.Bind_UInt32(this, index, Convert.ToByte(obj, CultureInfo.CurrentCulture));
          326  +          _sql.Bind_UInt32(this, _flags, index, Convert.ToByte(obj, CultureInfo.CurrentCulture));
   309    327             break;
   310    328           case DbType.UInt16:
   311         -          _sql.Bind_UInt32(this, index, Convert.ToUInt16(obj, CultureInfo.CurrentCulture));
          329  +          _sql.Bind_UInt32(this, _flags, index, Convert.ToUInt16(obj, CultureInfo.CurrentCulture));
   312    330             break;
   313    331           case DbType.UInt32:
   314         -          _sql.Bind_UInt32(this, index, Convert.ToUInt32(obj, CultureInfo.CurrentCulture));
          332  +          _sql.Bind_UInt32(this, _flags, index, Convert.ToUInt32(obj, CultureInfo.CurrentCulture));
   315    333             break;
   316    334           case DbType.UInt64:
   317         -          _sql.Bind_UInt64(this, index, Convert.ToUInt64(obj, CultureInfo.CurrentCulture));
          335  +          _sql.Bind_UInt64(this, _flags, index, Convert.ToUInt64(obj, CultureInfo.CurrentCulture));
   318    336             break;
   319    337           case DbType.Single:
   320    338           case DbType.Double:
   321    339           case DbType.Currency:
   322    340           //case DbType.Decimal: // Dont store decimal as double ... loses precision
   323         -          _sql.Bind_Double(this, index, Convert.ToDouble(obj, CultureInfo.CurrentCulture));
          341  +          _sql.Bind_Double(this, _flags, index, Convert.ToDouble(obj, CultureInfo.CurrentCulture));
   324    342             break;
   325    343           case DbType.Binary:
   326         -          _sql.Bind_Blob(this, index, (byte[])obj);
          344  +          _sql.Bind_Blob(this, _flags, index, (byte[])obj);
   327    345             break;
   328    346           case DbType.Guid:
   329    347             if (_command.Connection._binaryGuid == true)
   330         -            _sql.Bind_Blob(this, index, ((Guid)obj).ToByteArray());
          348  +            _sql.Bind_Blob(this, _flags, index, ((Guid)obj).ToByteArray());
   331    349             else
   332         -            _sql.Bind_Text(this, index, obj.ToString());
          350  +            _sql.Bind_Text(this, _flags, index, obj.ToString());
   333    351   
   334    352             break;
   335    353           case DbType.Decimal: // Dont store decimal as double ... loses precision
   336         -          _sql.Bind_Text(this, index, Convert.ToDecimal(obj, CultureInfo.CurrentCulture).ToString(CultureInfo.InvariantCulture));
          354  +          _sql.Bind_Text(this, _flags, index, Convert.ToDecimal(obj, CultureInfo.CurrentCulture).ToString(CultureInfo.InvariantCulture));
   337    355             break;
   338    356           default:
   339         -          _sql.Bind_Text(this, index, obj.ToString());
          357  +          _sql.Bind_Text(this, _flags, index, obj.ToString());
   340    358             break;
   341    359         }
   342    360       }
   343    361   
   344    362       internal string[] TypeDefinitions
   345    363       {
   346    364         get { return _types; }

Changes to System.Data.SQLite/UnsafeNativeMethods.cs.

   879    879   #endif
   880    880   
   881    881     // Handles the unmanaged database pointer, and provides finalization support for it.
   882    882     internal class SQLiteConnectionHandle : CriticalHandle
   883    883     {
   884    884       public static implicit operator IntPtr(SQLiteConnectionHandle db)
   885    885       {
   886         -      return db.handle;
          886  +      return (db != null) ? db.handle : IntPtr.Zero;
   887    887       }
   888    888   
   889    889       public static implicit operator SQLiteConnectionHandle(IntPtr db)
   890    890       {
   891    891         return new SQLiteConnectionHandle(db);
   892    892       }
   893    893   
................................................................................
   955    955     }
   956    956   
   957    957     // Provides finalization support for unmanaged SQLite statements.
   958    958     internal class SQLiteStatementHandle : CriticalHandle
   959    959     {
   960    960       public static implicit operator IntPtr(SQLiteStatementHandle stmt)
   961    961       {
   962         -      return stmt.handle;
          962  +      return (stmt != null) ? stmt.handle : IntPtr.Zero;
   963    963       }
   964    964   
   965    965       public static implicit operator SQLiteStatementHandle(IntPtr stmt)
   966    966       {
   967    967         return new SQLiteStatementHandle(stmt);
   968    968       }
   969    969   

Changes to Tests/basic.eagle.

  1000   1000   Source=test\.db\} 0 \{test\.db, Uri=test\.db\} 0 \{60, Default Timeout=60\} 0\
  1001   1001   \{False, Enlist=False\} 0 \{True, FailIfMissing=True\} 0 \{False, Legacy\
  1002   1002   Format=False\} 0 \{True, Read Only=True\} 0 \{secret, Password=secret\} 0\
  1003   1003   \{4096, Page Size=4096\} 0 \{1024, Max Page Count=1024\} 0 \{8192, Cache\
  1004   1004   Size=8192\} 0 \{UnixEpoch, DateTimeFormat=UnixEpoch\} 0 \{Utc,\
  1005   1005   DateTimeKind=Utc\} 0 \{sqlite_schema, BaseSchemaName=sqlite_schema\} 0\
  1006   1006   \{Memory, Journal Mode=Memory\} 0 \{Serializable, Default\
  1007         -IsolationLevel=Serializable\} 0 \{False, Foreign Keys=False\} 0 \{Default,\
  1008         -Flags=Default\}$}}
         1007  +IsolationLevel=Serializable\} 0 \{False, Foreign Keys=False\} 0 \{None,\
         1008  +Flags=None\}$}}
  1009   1009   
  1010   1010   ###############################################################################
  1011   1011   
  1012   1012   runTest {test data-1.17 {SQLiteConvert ToDateTime (Julian Day)} -body {
  1013   1013     set dateTime [object invoke System.Data.SQLite.SQLiteConvert ToDateTime \
  1014   1014         2455928.0 Utc]
  1015   1015