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

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

Overview
Comment:Initial implementation of SQLITE_CONFIG_LOG interface.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: fc3e41ac858848624097eacec25c8c1a9b4df7c0
User & Date: shaneh 2011-04-22 18:08:43
Context
2011-04-22
18:54
Revert path setting again, still fails on 64-bit systems. check-in: ef25334cf7 user: shaneh tags: trunk
18:08
Initial implementation of SQLITE_CONFIG_LOG interface. check-in: fc3e41ac85 user: shaneh tags: trunk
2011-04-15
17:33
Added support for sqlite3_extended_result_codes(), sqlite3_errcode(), and sqlite3_extended_errcode(). check-in: 41ad3433f5 user: shaneh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to SQLite.Interop/src/win/interop.c.

    92     92     {
    93     93       if(!DbHasProperty(*ppdb, 0, DB_SchemaLoaded))
    94     94         ENC(*ppdb) = SQLITE_UTF16NATIVE;
    95     95     }
    96     96     return ret;
    97     97   }
    98     98   
    99         -__declspec(dllexport) int WINAPI sqlite3_extended_result_codes_interop(sqlite3 *db, int onoff)
   100         -{
   101         -  int rc = sqlite3_extended_result_codes(db, onoff);
   102         -  return rc;
   103         -}
   104         -
   105         -__declspec(dllexport) int WINAPI sqlite3_errcode_interop(sqlite3 *db)
   106         -{
   107         -  int rc = sqlite3_errcode(db);
   108         -  return rc;
   109         -}
   110         -
   111         -__declspec(dllexport) int WINAPI sqlite3_extended_errcode_interop(sqlite3 *db)
   112         -{
   113         -  int rc = sqlite3_extended_errcode(db);
   114         -  return rc;
   115         -}
   116         -
   117     99   __declspec(dllexport) const char * WINAPI sqlite3_errmsg_interop(sqlite3 *db, int *plen)
   118    100   {
   119    101     const char *pval = sqlite3_errmsg(db);
   120    102     *plen = (pval != 0) ? strlen(pval) : 0;
   121    103     return pval;
   122    104   }
   123    105   

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

    96     96       internal override int Changes
    97     97       {
    98     98         get
    99     99         {
   100    100           return UnsafeNativeMethods.sqlite3_changes(_sql);
   101    101         }
   102    102       }
          103  +
          104  +    /// <summary>
          105  +    /// Shutdown the SQLite engine so that it can be restarted with different config options.
          106  +    /// We depend on auto initialization to recover.
          107  +    /// </summary>
          108  +    /// <returns>Returns a result code</returns>
          109  +    internal override int Shutdown()
          110  +    {
          111  +        int rc = UnsafeNativeMethods.sqlite3_shutdown();
          112  +        return rc;
          113  +    }
   103    114   
   104    115       internal override void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool)
   105    116       {
   106    117         if (_sql != null) return;
   107    118   
   108    119         _usePool = usePool;
   109    120         if (usePool)
................................................................................
   849    860       {
   850    861         return UnsafeNativeMethods.sqlite3_aggregate_context(context, 1);
   851    862       }
   852    863   
   853    864       /// Enables or disabled extended result codes returned by SQLite
   854    865       internal override void SetExtendedResultCodes(bool bOnOff)
   855    866       {
   856         -#if !SQLITE_STANDARD
   857         -      UnsafeNativeMethods.sqlite3_extended_result_codes_interop(_sql, (bOnOff ? -1 : 0));
   858         -#else
   859    867         UnsafeNativeMethods.sqlite3_extended_result_codes(_sql, (bOnOff ? -1 : 0));
   860         -#endif
   861    868       }
   862    869       /// Gets the last SQLite error code
   863    870       internal override int ResultCode()
   864    871       {
   865         -#if !SQLITE_STANDARD
   866         -      return UnsafeNativeMethods.sqlite3_errcode_interop(_sql);
   867         -#else
   868    872         return UnsafeNativeMethods.sqlite3_errcode(_sql);
   869         -#endif
   870    873       }
   871    874       /// Gets the last SQLite extended error code
   872    875       internal override int ExtendedResultCode()
   873    876       {
   874         -#if !SQLITE_STANDARD
   875         -      return UnsafeNativeMethods.sqlite3_extended_errcode_interop(_sql);
   876         -#else
   877    877         return UnsafeNativeMethods.sqlite3_extended_errcode(_sql);
   878         -#endif
   879    878       }
   880    879   
   881    880       internal override void SetPassword(byte[] passwordBytes)
   882    881       {
   883    882         int n = UnsafeNativeMethods.sqlite3_key(_sql, passwordBytes, passwordBytes.Length);
   884    883         if (n > 0) throw new SQLiteException(n, SQLiteLastError());
   885    884       }
................................................................................
   905    904         UnsafeNativeMethods.sqlite3_trace(_sql, func, IntPtr.Zero);
   906    905       }
   907    906   
   908    907       internal override void SetRollbackHook(SQLiteRollbackCallback func)
   909    908       {
   910    909         UnsafeNativeMethods.sqlite3_rollback_hook(_sql, func, IntPtr.Zero);
   911    910       }
          911  +
          912  +    /// <summary>
          913  +    /// Allows the setting of a logging callback invoked by SQLite when a
          914  +    /// log event occurs.  Only one callback may be set.  If NULL is passed,
          915  +    /// the logging callback is unregistered.
          916  +    /// </summary>
          917  +    /// <param name="func">The callback function to invoke.</param>
          918  +    /// <returns>Returns a result code</returns>
          919  +    internal override int SetLogCallback(SQLiteLogCallback func)
          920  +    {
          921  +        int rc = UnsafeNativeMethods.sqlite3_config((int)SQLiteConfigOpsEnum.SQLITE_CONFIG_LOG, func, (IntPtr)0);
          922  +        return rc;
          923  +    }
   912    924   
   913    925       /// <summary>
   914    926       /// Helper function to retrieve a column of data from an active statement.
   915    927       /// </summary>
   916    928       /// <param name="stmt">The statement being step()'d through</param>
   917    929       /// <param name="index">The column index to retrieve</param>
   918    930       /// <param name="typ">The type of data contained in the column.  If Uninitialized, this function will retrieve the datatype information.</param>

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

    28     28       /// </summary>
    29     29       internal abstract string Version { get; }
    30     30       /// <summary>
    31     31       /// Returns the number of changes the last executing insert/update caused.
    32     32       /// </summary>
    33     33       internal abstract int Changes { get; }
    34     34       /// <summary>
           35  +    /// Shutdown the SQLite engine so that it can be restarted with different config options.
           36  +    /// We depend on auto initialization to recover.
           37  +    /// </summary>
           38  +    internal abstract int Shutdown();
           39  +    /// <summary>
    35     40       /// Opens a database.
    36     41       /// </summary>
    37     42       /// <remarks>
    38     43       /// Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection
    39     44       /// to bind all attributed user-defined functions and collating sequences to the new connection.
    40     45       /// </remarks>
    41     46       /// <param name="strFilename">The filename of the database to open.  SQLite automatically creates it if it doesn't exist.</param>
................................................................................
   172    177       internal abstract void SetPassword(byte[] passwordBytes);
   173    178       internal abstract void ChangePassword(byte[] newPasswordBytes);
   174    179   
   175    180       internal abstract void SetUpdateHook(SQLiteUpdateCallback func);
   176    181       internal abstract void SetCommitHook(SQLiteCommitCallback func);
   177    182       internal abstract void SetTraceCallback(SQLiteTraceCallback func);
   178    183       internal abstract void SetRollbackHook(SQLiteRollbackCallback func);
          184  +    internal abstract int SetLogCallback(SQLiteLogCallback func);
   179    185   
   180    186       internal abstract int GetCursorForTable(SQLiteStatement stmt, int database, int rootPage);
   181    187       internal abstract long GetRowIdForCursor(SQLiteStatement stmt, int cursor);
   182    188   
   183    189       internal abstract object GetValue(SQLiteStatement stmt, int index, SQLiteType typ);
   184    190   
   185    191       internal abstract bool AutoCommit
................................................................................
   284    290       None = 0,
   285    291       ReadOnly = 0x01,
   286    292       ReadWrite = 0x02,
   287    293       Create = 0x04,
   288    294       SharedCache = 0x01000000,
   289    295       Default = 0x06,
   290    296     }
          297  +
          298  +  // These are the options to the internal sqlite3_config call.
          299  +  internal enum SQLiteConfigOpsEnum
          300  +  {
          301  +    SQLITE_CONFIG_SINGLETHREAD = 1, // nil 
          302  +    SQLITE_CONFIG_MULTITHREAD = 2, // nil 
          303  +    SQLITE_CONFIG_SERIALIZED = 3, // nil 
          304  +    SQLITE_CONFIG_MALLOC = 4, // sqlite3_mem_methods* 
          305  +    SQLITE_CONFIG_GETMALLOC = 5, // sqlite3_mem_methods* 
          306  +    SQLITE_CONFIG_SCRATCH = 6, // void*, int sz, int N 
          307  +    SQLITE_CONFIG_PAGECACHE = 7, // void*, int sz, int N 
          308  +    SQLITE_CONFIG_HEAP = 8, // void*, int nByte, int min 
          309  +    SQLITE_CONFIG_MEMSTATUS = 9, // boolean 
          310  +    SQLITE_CONFIG_MUTEX = 10, // sqlite3_mutex_methods* 
          311  +    SQLITE_CONFIG_GETMUTEX = 11, // sqlite3_mutex_methods* 
          312  +    // previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused
          313  +    SQLITE_CONFIG_LOOKASIDE = 13, // int int 
          314  +    SQLITE_CONFIG_PCACHE = 14, // sqlite3_pcache_methods* 
          315  +    SQLITE_CONFIG_GETPCACHE = 15, // sqlite3_pcache_methods* 
          316  +    SQLITE_CONFIG_LOG = 16, // xFunc, void* 
          317  +  }
          318  +
   291    319   }

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

   203    203   
   204    204       internal long _version;
   205    205   
   206    206       private event SQLiteUpdateEventHandler _updateHandler;
   207    207       private event SQLiteCommitHandler _commitHandler;
   208    208       private event SQLiteTraceEventHandler _traceHandler;
   209    209       private event EventHandler _rollbackHandler;
          210  +    private event SQLiteLogEventHandler _logHandler;
   210    211   
   211    212       private SQLiteUpdateCallback _updateCallback;
   212    213       private SQLiteCommitCallback _commitCallback;
   213    214       private SQLiteTraceCallback _traceCallback;
   214    215       private SQLiteRollbackCallback _rollbackCallback;
          216  +    private SQLiteLogCallback _logCallback;
   215    217   
   216    218       /// <summary>
   217    219       /// This event is raised whenever the database is opened or closed.
   218    220       /// </summary>
   219    221       public override event StateChangeEventHandler StateChange;
   220    222   
   221    223       ///<overloads>
................................................................................
   440    442             cnn._transactionLevel = _transactionLevel;
   441    443             cnn._enlistment = _enlistment;
   442    444             cnn._connectionState = _connectionState;
   443    445             cnn._version = _version;
   444    446   
   445    447             cnn._enlistment._transaction._cnn = cnn;
   446    448             cnn._enlistment._disposeConnection = true;
          449  +
   447    450             _sql = null;
   448    451             _enlistment = null;
   449    452           }
   450    453   #endif
   451    454           if (_sql != null)
   452    455           {
   453    456             _sql.Close();
................................................................................
   785    788            fileName = Path.GetDirectoryName(System.Reflection.Assembly.GetCallingAssembly().GetName().CodeBase) + fileName.Substring(1);
   786    789   #endif
   787    790          fileName = ExpandFileName(fileName);
   788    791         }
   789    792         try
   790    793         {
   791    794           bool usePooling = (SQLiteConvert.ToBoolean(FindKey(opts, "Pooling", Boolean.FalseString)) == true);
   792         -        bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true);
   793    795           int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", "100"), CultureInfo.InvariantCulture);
   794    796   
   795    797           _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", "30"), CultureInfo.CurrentCulture);
   796    798   
   797    799           _defaultIsolation = (IsolationLevel)Enum.Parse(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", "Serializable"), true);
   798    800           if (_defaultIsolation != IsolationLevel.Serializable && _defaultIsolation != IsolationLevel.ReadCommitted)
   799    801             throw new NotSupportedException("Invalid Default IsolationLevel specified");
   800    802   
   801         -        SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats), FindKey(opts, "DateTimeFormat", "ISO8601"), true);
   802    803           //string temp = FindKey(opts, "DateTimeFormat", "ISO8601");
   803    804           //if (String.Compare(temp, "ticks", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.Ticks;
   804    805           //else if (String.Compare(temp, "julianday", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.JulianDay;
   805    806   
   806         -        if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16()
   807         -          _sql = new SQLite3_UTF16(dateFormat);
   808         -        else
   809         -          _sql = new SQLite3(dateFormat);
          807  +        if (_sql == null)
          808  +        {
          809  +          bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true);
          810  +          SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats),
          811  +                                                                       FindKey(opts, "DateTimeFormat", "ISO8601"),
          812  +                                                                       true);
          813  +
          814  +          if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16()
          815  +            _sql = new SQLite3_UTF16(dateFormat);
          816  +          else
          817  +            _sql = new SQLite3(dateFormat);
          818  +
          819  +          if (_sql != null && _logHandler != null)
          820  +          {
          821  +              if (_logCallback == null) _logCallback = new SQLiteLogCallback(LogCallback);
          822  +              if (_logCallback != null) _sql.SetLogCallback(_logCallback);
          823  +          }
          824  +        }
   810    825   
   811    826           SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None;
   812    827   
   813    828           if (SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", Boolean.FalseString)) == false)
   814    829             flags |= SQLiteOpenFlagsEnum.Create;
   815    830   
   816    831           if (SQLiteConvert.ToBoolean(FindKey(opts, "Read Only", Boolean.FalseString)) == true)
................................................................................
   971    986       public override ConnectionState State
   972    987       {
   973    988         get
   974    989         {
   975    990           return _connectionState;
   976    991         }
   977    992       }
          993  +
          994  +    /// Passes a shutdown request off to SQLite.
          995  +    public int Shutdown()
          996  +    {
          997  +        // make sure we have an instance of the base class
          998  +        if (_sql == null)
          999  +        {
         1000  +            SortedList<string, string> opts = ParseConnectionString(_connectionString);
         1001  +
         1002  +            bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true);
         1003  +            SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats),
         1004  +                                                                         FindKey(opts, "DateTimeFormat", "ISO8601"),
         1005  +                                                                         true);
         1006  +
         1007  +            if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16()
         1008  +                _sql = new SQLite3_UTF16(dateFormat);
         1009  +            else
         1010  +                _sql = new SQLite3(dateFormat);
         1011  +        }
         1012  +        if (_sql != null) return _sql.Shutdown();
         1013  +        throw new InvalidOperationException("Database connection not active.");
         1014  +    }
   978   1015   
   979   1016       /// Enables or disabled extended result codes returned by SQLite
   980   1017       public void SetExtendedResultCodes(bool bOnOff)
   981   1018       {
   982   1019         if (_sql != null) _sql.SetExtendedResultCodes(bOnOff);
   983   1020       }
   984   1021       /// Enables or disabled extended result codes returned by SQLite
................................................................................
  2303   2340         return (e.AbortTransaction == true) ? 1 : 0;
  2304   2341       }
  2305   2342   
  2306   2343       private void RollbackCallback(IntPtr parg)
  2307   2344       {
  2308   2345         _rollbackHandler(this, EventArgs.Empty);
  2309   2346       }
         2347  +
         2348  +    /// <summary>
         2349  +    /// This event is raised whenever SQLite raises a logging event.
         2350  +    /// </summary>
         2351  +    public event SQLiteLogEventHandler Log
         2352  +    {
         2353  +        add
         2354  +        {
         2355  +            _logHandler += value;
         2356  +            // callback handler will be set/removed at open/close
         2357  +        }
         2358  +        remove
         2359  +        {
         2360  +            _logHandler -= value;
         2361  +            if (_logHandler==null)
         2362  +            {
         2363  +                _sql.SetLogCallback(null);
         2364  +                _logCallback = null;
         2365  +            }
         2366  +
         2367  +        }
         2368  +    }
         2369  +
         2370  +    private void LogCallback(IntPtr puser, int err_code, IntPtr message)
         2371  +    {
         2372  +        if (_logHandler != null) 
         2373  +            _logHandler(this, 
         2374  +                        new LogEventArgs(puser, 
         2375  +                                         err_code,
         2376  +                                         SQLiteBase.UTF8ToString(message, -1)));
         2377  +    }
         2378  +
  2310   2379     }
  2311   2380   
  2312   2381     /// <summary>
  2313   2382     /// The I/O file cache flushing behavior for the connection
  2314   2383     /// </summary>
  2315   2384     public enum SynchronizationModes
  2316   2385     {
................................................................................
  2328   2397       Off = 2,
  2329   2398     }
  2330   2399   
  2331   2400   #if !PLATFORM_COMPACTFRAMEWORK
  2332   2401     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  2333   2402   #endif
  2334   2403     internal delegate void SQLiteUpdateCallback(IntPtr puser, int type, IntPtr database, IntPtr table, Int64 rowid);
         2404  +
  2335   2405   #if !PLATFORM_COMPACTFRAMEWORK
  2336   2406     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  2337   2407   #endif
  2338   2408     internal delegate int SQLiteCommitCallback(IntPtr puser);
         2409  +
  2339   2410   #if !PLATFORM_COMPACTFRAMEWORK
  2340   2411     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  2341   2412   #endif
  2342   2413     internal delegate void SQLiteTraceCallback(IntPtr puser, IntPtr statement);
         2414  +
  2343   2415   #if !PLATFORM_COMPACTFRAMEWORK
  2344   2416     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  2345   2417   #endif
  2346   2418     internal delegate void SQLiteRollbackCallback(IntPtr puser);
  2347   2419   
         2420  +#if !PLATFORM_COMPACTFRAMEWORK
         2421  +  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
         2422  +#endif
         2423  +  internal delegate void SQLiteLogCallback(IntPtr puser, int err_code, IntPtr message);
         2424  +
  2348   2425     /// <summary>
  2349   2426     /// Raised when a transaction is about to be committed.  To roll back a transaction, set the 
  2350   2427     /// rollbackTrans boolean value to true.
  2351   2428     /// </summary>
  2352   2429     /// <param name="sender">The connection committing the transaction</param>
  2353   2430     /// <param name="e">Event arguments on the transaction</param>
  2354   2431     public delegate void SQLiteCommitHandler(object sender, CommitEventArgs e);
................................................................................
  2363   2440     /// <summary>
  2364   2441     /// Raised when a statement first begins executing on a given connection
  2365   2442     /// </summary>
  2366   2443     /// <param name="sender">The connection executing the statement</param>
  2367   2444     /// <param name="e">Event arguments on the trace</param>
  2368   2445     public delegate void SQLiteTraceEventHandler(object sender, TraceEventArgs e);
  2369   2446   
         2447  +  /// <summary>
         2448  +  /// Raised when a log event occurs.
         2449  +  /// </summary>
         2450  +  /// <param name="sender">The current connection</param>
         2451  +  /// <param name="e">Event arguments on the trace</param>
         2452  +  public delegate void SQLiteLogEventHandler(object sender, LogEventArgs e);
         2453  +
  2370   2454     /// <summary>
  2371   2455     /// Whenever an update event is triggered on a connection, this enum will indicate
  2372   2456     /// exactly what type of operation is being performed.
  2373   2457     /// </summary>
  2374   2458     public enum UpdateEventType
  2375   2459     {
  2376   2460       /// <summary>
................................................................................
  2448   2532       public readonly string Statement;
  2449   2533   
  2450   2534       internal TraceEventArgs(string statement)
  2451   2535       {
  2452   2536         Statement = statement;
  2453   2537       }
  2454   2538     }
         2539  +
         2540  +  /// <summary>
         2541  +  /// Passed during an Log callback
         2542  +  /// </summary>
         2543  +  public class LogEventArgs : EventArgs
         2544  +  {
         2545  +      /// <summary>
         2546  +      /// The error code.
         2547  +      /// </summary>
         2548  +      public readonly int ErrorCode;
         2549  +
         2550  +      /// <summary>
         2551  +      /// SQL statement text as the statement first begins executing
         2552  +      /// </summary>
         2553  +      public readonly string Message;
         2554  +
         2555  +      internal LogEventArgs(IntPtr puser, int err_code, string message)
         2556  +      {
         2557  +          // puser should be NULL
         2558  +          ErrorCode = err_code;
         2559  +          Message = message;
         2560  +      }
         2561  +  }
  2455   2562   
  2456   2563   }

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

    31     31   #endif // USE_INTEROP_DLL
    32     32   
    33     33   #else
    34     34       private const string SQLITE_DLL = "sqlite3";
    35     35   #endif
    36     36   
    37     37       // This section uses interop calls that also fetch text length to optimize conversion.  
    38         -    // When using the standard dll, we can replace these calls with normal sqlite calls and do unoptimized conversions instead afterwards
           38  +    // When using the standard dll, we can replace these calls with normal sqlite calls and 
           39  +    // do unoptimized conversions instead afterwards
    39     40       #region interop added textlength calls
    40     41   
    41     42   #if !SQLITE_STANDARD
           43  +
    42     44       [DllImport(SQLITE_DLL)]
    43     45       internal static extern IntPtr sqlite3_bind_parameter_name_interop(IntPtr stmt, int index, out int len);
    44     46   
    45     47       [DllImport(SQLITE_DLL)]
    46     48       internal static extern IntPtr sqlite3_column_database_name_interop(IntPtr stmt, int index, out int len);
    47     49   
    48     50       [DllImport(SQLITE_DLL)]
................................................................................
    74     76   
    75     77       [DllImport(SQLITE_DLL)]
    76     78       internal static extern IntPtr sqlite3_column_text_interop(IntPtr stmt, int index, out int len);
    77     79   
    78     80       [DllImport(SQLITE_DLL)]
    79     81       internal static extern IntPtr sqlite3_column_text16_interop(IntPtr stmt, int index, out int len);
    80     82   
    81         -    [DllImport(SQLITE_DLL)]
    82         -    internal static extern int sqlite3_extended_result_codes_interop(IntPtr db, int onoff);
    83         -
    84         -    [DllImport(SQLITE_DLL)]
    85         -    internal static extern int sqlite3_errcode_interop(IntPtr db);
    86         -
    87         -    [DllImport(SQLITE_DLL)]
    88         -    internal static extern int sqlite3_extended_errcode_interop(IntPtr db);
    89         -
    90     83       [DllImport(SQLITE_DLL)]
    91     84       internal static extern IntPtr sqlite3_errmsg_interop(IntPtr db, out int len);
    92     85   
    93     86       [DllImport(SQLITE_DLL)]
    94     87       internal static extern int sqlite3_prepare_interop(IntPtr db, IntPtr pSql, int nBytes, out IntPtr stmt, out IntPtr ptrRemain, out int nRemain);
    95     88   
    96     89       [DllImport(SQLITE_DLL)]
................................................................................
    97     90       internal static extern int sqlite3_table_column_metadata_interop(IntPtr db, byte[] dbName, byte[] tblName, byte[] colName, out IntPtr ptrDataType, out IntPtr ptrCollSeq, out int notNull, out int primaryKey, out int autoInc, out int dtLen, out int csLen);
    98     91   
    99     92       [DllImport(SQLITE_DLL)]
   100     93       internal static extern IntPtr sqlite3_value_text_interop(IntPtr p, out int len);
   101     94   
   102     95       [DllImport(SQLITE_DLL)]
   103     96       internal static extern IntPtr sqlite3_value_text16_interop(IntPtr p, out int len);
           97  +
   104     98   #endif
           99  +// !SQLITE_STANDARD
   105    100   
   106    101       #endregion
   107    102   
   108    103       // These functions add existing functionality on top of SQLite and require a little effort to
   109    104       // get working when using the standard SQLite library.
   110    105       #region interop added functionality
   111    106   
   112    107   #if !SQLITE_STANDARD
          108  +
   113    109       [DllImport(SQLITE_DLL)]
   114    110       internal static extern int sqlite3_close_interop(IntPtr db);
   115    111   
   116    112       [DllImport(SQLITE_DLL)]
   117    113       internal static extern int sqlite3_create_function_interop(IntPtr db, byte[] strName, int nArgs, int nType, IntPtr pvUser, SQLiteCallback func, SQLiteCallback fstep, SQLiteFinalCallback ffinal, int needCollSeq);
   118    114   
   119    115       [DllImport(SQLITE_DLL)]
................................................................................
   125    121       [DllImport(SQLITE_DLL)]
   126    122       internal static extern int sqlite3_open16_interop(byte[] utf8Filename, int flags, out IntPtr db);
   127    123   
   128    124       [DllImport(SQLITE_DLL)]
   129    125       internal static extern int sqlite3_reset_interop(IntPtr stmt);
   130    126   
   131    127   #endif
          128  +// !SQLITE_STANDARD
   132    129   
   133    130       #endregion
   134    131   
   135    132       // The standard api call equivalents of the above interop calls
   136    133       #region standard versions of interop functions
   137    134   
   138    135   #if SQLITE_STANDARD
          136  +
   139    137   #if !PLATFORM_COMPACTFRAMEWORK
   140    138       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   141    139   #else
   142    140       [DllImport(SQLITE_DLL)]
   143    141   #endif
   144    142       internal static extern int sqlite3_close(IntPtr db);
   145    143   
................................................................................
   268    266       [DllImport(SQLITE_DLL)]
   269    267   #endif
   270    268       internal static extern IntPtr sqlite3_column_text16(IntPtr stmt, int index);
   271    269   
   272    270   #if !PLATFORM_COMPACTFRAMEWORK
   273    271       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   274    272   #else
   275         -    [DllImport(SQLITE_DLL)]
   276         -#endif
   277         -    internal static extern int sqlite3_extended_result_codes(IntPtr db, int onoff);
   278         -
   279         -#if !PLATFORM_COMPACTFRAMEWORK
   280         -    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   281         -#else
   282         -    [DllImport(SQLITE_DLL)]
   283         -#endif
   284         -    internal static extern int sqlite3_errcode(IntPtr db);
   285         -
   286         -#if !PLATFORM_COMPACTFRAMEWORK
   287         -    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   288         -#else
   289         -    [DllImport(SQLITE_DLL)]
   290         -#endif
   291         -    internal static extern int sqlite3_extended_errcode(IntPtr db);
   292         -
   293         -#if !PLATFORM_COMPACTFRAMEWORK
   294         -    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   295         -#else
   296    273       [DllImport(SQLITE_DLL)]
   297    274   #endif
   298    275       internal static extern IntPtr sqlite3_errmsg(IntPtr db);
   299    276   
   300    277   #if !PLATFORM_COMPACTFRAMEWORK
   301    278       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   302    279   #else
................................................................................
   320    297   
   321    298   #if !PLATFORM_COMPACTFRAMEWORK
   322    299       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   323    300   #else
   324    301       [DllImport(SQLITE_DLL)]
   325    302   #endif
   326    303       internal static extern IntPtr sqlite3_value_text16(IntPtr p);
          304  +
   327    305   #endif
          306  +// SQLITE_STANDARD
   328    307   
   329    308       #endregion
   330    309   
   331    310       // These functions are custom and have no equivalent standard library method.
   332    311       // All of them are "nice to haves" and not necessarily "need to haves".
   333    312       #region no equivalent standard method
   334    313   
   335    314   #if !SQLITE_STANDARD
          315  +
   336    316       [DllImport(SQLITE_DLL)]
   337    317       internal static extern IntPtr sqlite3_context_collseq(IntPtr context, out int type, out int enc, out int len);
   338    318   
   339    319       [DllImport(SQLITE_DLL)]
   340    320       internal static extern int sqlite3_context_collcompare(IntPtr context, byte[] p1, int p1len, byte[] p2, int p2len);
   341    321   
   342    322       [DllImport(SQLITE_DLL)]
................................................................................
   346    326       internal static extern int sqlite3_index_column_info_interop(IntPtr db, byte[] catalog, byte[] IndexName, byte[] ColumnName, out int sortOrder, out int onError, out IntPtr Collation, out int colllen);
   347    327   
   348    328       [DllImport(SQLITE_DLL)]
   349    329       internal static extern void sqlite3_resetall_interop(IntPtr db);
   350    330   
   351    331       [DllImport(SQLITE_DLL)]
   352    332       internal static extern int sqlite3_table_cursor(IntPtr stmt, int db, int tableRootPage);
          333  +
   353    334   #endif
          335  +// !SQLITE_STANDARD
   354    336   
   355    337       #endregion
   356    338   
   357    339       // Standard API calls global across versions.  There are a few instances of interop calls
   358    340       // scattered in here, but they are only active when PLATFORM_COMPACTFRAMEWORK is declared.
   359    341       #region standard sqlite api calls
   360    342   
................................................................................
   375    357   #if !PLATFORM_COMPACTFRAMEWORK
   376    358       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   377    359   #else
   378    360       [DllImport(SQLITE_DLL)]
   379    361   #endif
   380    362       internal static extern int sqlite3_changes(IntPtr db);
   381    363   
          364  +#if !PLATFORM_COMPACTFRAMEWORK
          365  +    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
          366  +#else
          367  +    [DllImport(SQLITE_DLL)]
          368  +#endif
          369  +    internal static extern int sqlite3_shutdown();
          370  +
   382    371   #if !PLATFORM_COMPACTFRAMEWORK
   383    372       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   384    373   #else
   385    374       [DllImport(SQLITE_DLL)]
   386    375   #endif
   387    376       internal static extern int sqlite3_busy_timeout(IntPtr db, int ms);
   388    377   
................................................................................
   670    659   #if !PLATFORM_COMPACTFRAMEWORK
   671    660       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   672    661   #else
   673    662       [DllImport(SQLITE_DLL)]
   674    663   #endif
   675    664       internal static extern IntPtr sqlite3_trace(IntPtr db, SQLiteTraceCallback func, IntPtr pvUser);
   676    665   
          666  +    // Since sqlite3_config() takes a variable argument list, we have to overload declarations
          667  +    // for all possible calls.  For now, we are only exposing the SQLITE_CONFIG_LOG call.
          668  +#if !PLATFORM_COMPACTFRAMEWORK
          669  +    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
          670  +#else
          671  +    [DllImport(SQLITE_DLL)]
          672  +#endif
          673  +    internal static extern int sqlite3_config(int op, SQLiteLogCallback func, IntPtr pvUser);
          674  +
   677    675   #if !PLATFORM_COMPACTFRAMEWORK
   678    676       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   679    677   #else
   680    678       [DllImport(SQLITE_DLL)]
   681    679   #endif
   682    680       internal static extern IntPtr sqlite3_rollback_hook(IntPtr db, SQLiteRollbackCallback func, IntPtr pvUser);
   683    681   
................................................................................
   704    702   
   705    703   #if !PLATFORM_COMPACTFRAMEWORK
   706    704       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   707    705   #else
   708    706       [DllImport(SQLITE_DLL)]
   709    707   #endif
   710    708       internal static extern int sqlite3_get_autocommit(IntPtr db);
          709  +
          710  +#if !PLATFORM_COMPACTFRAMEWORK
          711  +    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
          712  +#else
          713  +    [DllImport(SQLITE_DLL)]
          714  +#endif
          715  +    internal static extern int sqlite3_extended_result_codes(IntPtr db, int onoff);
          716  +
          717  +#if !PLATFORM_COMPACTFRAMEWORK
          718  +    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
          719  +#else
          720  +    [DllImport(SQLITE_DLL)]
          721  +#endif
          722  +    internal static extern int sqlite3_errcode(IntPtr db);
          723  +
          724  +#if !PLATFORM_COMPACTFRAMEWORK
          725  +    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
          726  +#else
          727  +    [DllImport(SQLITE_DLL)]
          728  +#endif
          729  +    internal static extern int sqlite3_extended_errcode(IntPtr db);
          730  +
   711    731   
   712    732       #endregion
   713    733     }
   714    734   
   715    735   #if PLATFORM_COMPACTFRAMEWORK
   716    736     internal abstract class CriticalHandle : IDisposable
   717    737     {

Changes to test/TestCases.cs.

  1523   1523   
  1524   1524           int rc = cnn.ResultCode();
  1525   1525           int xrc = cnn.ExtendedResultCode();
  1526   1526   
  1527   1527           cnn.Close();
  1528   1528         }
  1529   1529       }
         1530  +
         1531  +    //Applying EventHandler
         1532  +    public void OnLogEvent(object sender, LogEventArgs logEvent)
         1533  +    {
         1534  +        int err_code = logEvent.ErrorCode;
         1535  +        string err_msg = logEvent.Message;
         1536  +    }
         1537  +
         1538  +    /// <summary>
         1539  +    /// Tests SQLITE_CONFIG_LOG support.
         1540  +    /// </summary>
         1541  +    [Test]
         1542  +    internal void SetLogCallbackTest()
         1543  +    {
         1544  +        if (_factstring.ToLower().Contains("sqlite"))
         1545  +        {
         1546  +            SQLiteConnection cnn = new SQLiteConnection(_cnnstring.ConnectionString);
         1547  +
         1548  +            cnn.Shutdown();  // we need to shutdown so that we can change config options
         1549  +
         1550  +            SQLiteLogEventHandler logHandler = new SQLiteLogEventHandler(OnLogEvent); 
         1551  +            cnn.Log += logHandler;
         1552  +
         1553  +            cnn.Open();
         1554  +
         1555  +            maydroptable.Add("LogCallbackTest");
         1556  +            if (cnn.State != ConnectionState.Open) cnn.Open();
         1557  +            using (DbCommand cmd = cnn.CreateCommand())
         1558  +            {
         1559  +                cmd.CommandText = "CREATE TABLE LogCallbackTest(ID int primary key)";
         1560  +                cmd.ExecuteNonQuery();
         1561  +            }
         1562  +
         1563  +            cnn.Close();
         1564  +
         1565  +            cnn.Shutdown();  // we need to shutdown so that we can change config options
         1566  +
         1567  +            // remove the log handler before the connection is closed.
         1568  +            cnn.Log -= logHandler;
         1569  +
         1570  +        }
         1571  +    }
  1530   1572   
  1531   1573       /// <summary>
  1532   1574       /// Open a reader and then attempt to write to test the writer's command timeout property
  1533   1575       /// SQLite doesn't allow a write when a reader is active.
  1534   1576       /// *** NOTE AS OF 3.3.8 this test no longer blocks because SQLite now allows you to update table(s)
  1535   1577       /// while a reader is active on the same connection.  Therefore the timeout test is invalid
  1536   1578       /// </summary>