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

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

Overview
Comment:Virtual table marshalling fixes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | marshalFixes
Files: files | file ages | folders
SHA1: e7b11da35f706621866212909471ee9792c41edd
User & Date: mistachkin 2013-07-15 03:57:46
Context
2013-07-15
05:16
Modify classes implementing the IDisposable pattern to set the disposed flag after their base classes have been disposed. check-in: db3a299625 user: mistachkin tags: marshalFixes
03:57
Virtual table marshalling fixes. check-in: e7b11da35f user: mistachkin tags: marshalFixes
2013-07-11
15:49
Add GetSqlForDeclareTable method to the SQLiteModuleEnumerable class to allow derived classes to override the SQL statement used to declare the virtual table schema. check-in: a3798d45f4 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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

   387    387     pModule->xFindFunction = xFindFunction;
   388    388     pModule->xRename = xRename;
   389    389     pModule->xSavepoint = xSavepoint;
   390    390     pModule->xRelease = xRelease;
   391    391     pModule->xRollbackTo = xRollbackTo;
   392    392     return sqlite3_create_disposable_module(db, zName, pModule, pClientData, xDestroyModule);
   393    393   }
   394         -
   395         -SQLITE_API void WINAPI sqlite3_dispose_module_interop(void *pModule)
   396         -{
   397         -  sqlite3_dispose_module(pModule);
   398         -}
   399    394   #endif
   400    395   
   401    396   SQLITE_API int WINAPI sqlite3_bind_double_interop(sqlite3_stmt *stmt, int iCol, double *val)
   402    397   {
   403    398   	return sqlite3_bind_double(stmt,iCol,*val);
   404    399   }
   405    400   

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

   157    157                   //}
   158    158   
   159    159                   //////////////////////////////////////
   160    160                   // release unmanaged resources here...
   161    161                   //////////////////////////////////////
   162    162   
   163    163   #if INTEROP_VIRTUAL_TABLE
   164         -                //
   165         -                // NOTE: If any modules were created, attempt to dispose of
   166         -                //       them now.  This code is designed to avoid throwing
   167         -                //       exceptions unless the Dispose method of the module
   168         -                //       itself throws an exception.
   169         -                //
   170         -                if (_modules != null)
   171         -                {
   172         -                    foreach (KeyValuePair<string, SQLiteModule> pair in _modules)
   173         -                    {
   174         -                        SQLiteModule module = pair.Value;
   175         -
   176         -                        if (module == null)
   177         -                            continue;
   178         -
   179         -                        module.Dispose();
   180         -                    }
   181         -                }
          164  +                DisposeModules();
   182    165   #endif
   183    166   
   184    167                   Close(false); /* Disposing, cannot throw. */
   185    168   
   186    169                   disposed = true;
   187    170               }
   188    171           }
   189    172           finally
   190    173           {
   191    174               base.Dispose(disposing);
   192    175           }
   193    176       }
   194    177       #endregion
          178  +
          179  +    ///////////////////////////////////////////////////////////////////////////////////////////////
          180  +
          181  +#if INTEROP_VIRTUAL_TABLE
          182  +    /// <summary>
          183  +    /// This method attempts to dispose of all the <see cref="SQLiteModule" /> derived
          184  +    /// object instances currently associated with the native database connection.
          185  +    /// </summary>
          186  +    private void DisposeModules()
          187  +    {
          188  +        //
          189  +        // NOTE: If any modules were created, attempt to dispose of
          190  +        //       them now.  This code is designed to avoid throwing
          191  +        //       exceptions unless the Dispose method of the module
          192  +        //       itself throws an exception.
          193  +        //
          194  +        if (_modules != null)
          195  +        {
          196  +            foreach (KeyValuePair<string, SQLiteModule> pair in _modules)
          197  +            {
          198  +                SQLiteModule module = pair.Value;
          199  +
          200  +                if (module == null)
          201  +                    continue;
          202  +
          203  +                module.Dispose();
          204  +            }
          205  +        }
          206  +    }
          207  +#endif
   195    208   
   196    209       ///////////////////////////////////////////////////////////////////////////////////////////////
   197    210   
   198    211       // It isn't necessary to cleanup any functions we've registered.  If the connection
   199    212       // goes to the pool and is resurrected later, re-registered functions will overwrite the
   200    213       // previous functions.  The SQLiteFunctionCookieHandle will take care of freeing unmanaged
   201    214       // resources belonging to the previously-registered functions.
................................................................................
   209    222                 return;
   210    223             }
   211    224   
   212    225             if (_usePool)
   213    226             {
   214    227                 if (SQLiteBase.ResetConnection(_sql, _sql, canThrow))
   215    228                 {
          229  +#if INTEROP_VIRTUAL_TABLE
          230  +                  DisposeModules();
          231  +#endif
          232  +
   216    233                     SQLiteConnectionPool.Add(_fileName, _sql, _poolVersion);
   217    234   
   218    235   #if !NET_COMPACT_20 && TRACE_CONNECTION
   219    236                     Trace.WriteLine(String.Format("Close (Pool) Success: {0}", _sql));
   220    237   #endif
   221    238                 }
   222    239   #if !NET_COMPACT_20 && TRACE_CONNECTION
................................................................................
  1707   1724   
  1708   1725           if (_sql == null)
  1709   1726               throw new SQLiteException("connection has an invalid handle");
  1710   1727   
  1711   1728           SetLoadExtension(true);
  1712   1729           LoadExtension(UnsafeNativeMethods.SQLITE_DLL, "sqlite3_vtshim_init");
  1713   1730   
  1714         -        IntPtr pName = IntPtr.Zero;
  1715         -
  1716         -        try
  1717         -        {
  1718         -            pName = SQLiteString.Utf8IntPtrFromString(module.Name);
  1719         -
  1720         -            UnsafeNativeMethods.sqlite3_module nativeModule =
  1721         -                module.CreateNativeModule();
  1722         -
  1723         -#if !PLATFORM_COMPACTFRAMEWORK
  1724         -            if (UnsafeNativeMethods.sqlite3_create_disposable_module(
  1725         -                    _sql, pName, ref nativeModule, IntPtr.Zero,
  1726         -                    null) != IntPtr.Zero)
  1727         -#elif !SQLITE_STANDARD
  1728         -            if (UnsafeNativeMethods.sqlite3_create_disposable_module_interop(
  1729         -                    _sql, pName, module.CreateNativeModuleInterop(),
  1730         -                    nativeModule.iVersion, nativeModule.xCreate,
  1731         -                    nativeModule.xConnect, nativeModule.xBestIndex,
  1732         -                    nativeModule.xDisconnect, nativeModule.xDestroy,
  1733         -                    nativeModule.xOpen, nativeModule.xClose,
  1734         -                    nativeModule.xFilter, nativeModule.xNext,
  1735         -                    nativeModule.xEof, nativeModule.xColumn,
  1736         -                    nativeModule.xRowId, nativeModule.xUpdate,
  1737         -                    nativeModule.xBegin, nativeModule.xSync,
  1738         -                    nativeModule.xCommit, nativeModule.xRollback,
  1739         -                    nativeModule.xFindFunction, nativeModule.xRename,
  1740         -                    nativeModule.xSavepoint, nativeModule.xRelease,
  1741         -                    nativeModule.xRollbackTo, IntPtr.Zero, null) != IntPtr.Zero)
  1742         -#else
  1743         -            throw new NotImplementedException();
  1744         -#endif
  1745         -#if !PLATFORM_COMPACTFRAMEWORK || !SQLITE_STANDARD
  1746         -            {
  1747         -                if (_modules == null)
  1748         -                    _modules = new Dictionary<string, SQLiteModule>();
  1749         -
  1750         -                _modules.Add(module.Name, module);
  1751         -            }
  1752         -            else
  1753         -            {
  1754         -                throw new SQLiteException(GetLastError());
  1755         -            }
  1756         -#endif
  1757         -        }
  1758         -        finally
  1759         -        {
  1760         -            if (pName != IntPtr.Zero)
  1761         -            {
  1762         -                SQLiteMemory.Free(pName);
  1763         -                pName = IntPtr.Zero;
  1764         -            }
         1731  +        if (module.CreateDisposableModule(_sql))
         1732  +        {
         1733  +            if (_modules == null)
         1734  +                _modules = new Dictionary<string, SQLiteModule>();
         1735  +
         1736  +            _modules.Add(module.Name, module);
         1737  +        }
         1738  +        else
         1739  +        {
         1740  +            throw new SQLiteException(GetLastError());
  1765   1741           }
  1766   1742       }
  1767   1743   
  1768   1744       /// <summary>
  1769   1745       /// Calls the native SQLite core library in order to cleanup the resources
  1770   1746       /// associated with a module containing the implementation of a virtual table.
  1771   1747       /// </summary>

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

  1100   1100               if (pIndex == IntPtr.Zero)
  1101   1101                   return;
  1102   1102   
  1103   1103               int offset = 0;
  1104   1104   
  1105   1105               int nConstraint = SQLiteMarshal.ReadInt32(pIndex, offset);
  1106   1106   
  1107         -            offset += sizeof(int);
         1107  +            offset += SQLiteMarshal.SizeOfStructInt();
  1108   1108   
  1109   1109               IntPtr pConstraint = SQLiteMarshal.ReadIntPtr(pIndex, offset);
  1110   1110   
  1111   1111               offset += IntPtr.Size;
  1112   1112   
  1113   1113               int nOrderBy = SQLiteMarshal.ReadInt32(pIndex, offset);
  1114   1114   
  1115         -            offset += sizeof(int);
         1115  +            offset += SQLiteMarshal.SizeOfStructInt();
  1116   1116   
  1117   1117               IntPtr pOrderBy = SQLiteMarshal.ReadIntPtr(pIndex, offset);
  1118   1118   
  1119   1119               index = new SQLiteIndex(nConstraint, nOrderBy);
  1120   1120   
  1121         -            int sizeOfConstraintType = Marshal.SizeOf(typeof(
  1122         -                UnsafeNativeMethods.sqlite3_index_constraint));
         1121  +            Type indexConstraintType = typeof(
         1122  +                UnsafeNativeMethods.sqlite3_index_constraint);
         1123  +
         1124  +            int sizeOfConstraintType = Marshal.SizeOf(indexConstraintType);
  1123   1125   
  1124   1126               for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++)
  1125   1127               {
         1128  +                IntPtr pOffset = SQLiteMarshal.IntPtrForOffset(
         1129  +                    pConstraint, iConstraint * sizeOfConstraintType);
         1130  +
  1126   1131                   UnsafeNativeMethods.sqlite3_index_constraint constraint =
  1127         -                    new UnsafeNativeMethods.sqlite3_index_constraint();
  1128         -
  1129         -                Marshal.PtrToStructure(SQLiteMarshal.IntPtrForOffset(
  1130         -                    pConstraint, iConstraint * sizeOfConstraintType),
  1131         -                    constraint);
         1132  +                    (UnsafeNativeMethods.sqlite3_index_constraint)
         1133  +                        Marshal.PtrToStructure(pOffset, indexConstraintType);
  1132   1134   
  1133   1135                   index.Inputs.Constraints[iConstraint] =
  1134   1136                       new SQLiteIndexConstraint(constraint);
  1135   1137               }
  1136   1138   
  1137         -            int sizeOfOrderByType = Marshal.SizeOf(typeof(
  1138         -                UnsafeNativeMethods.sqlite3_index_orderby));
         1139  +            Type indexOrderByType = typeof(
         1140  +                UnsafeNativeMethods.sqlite3_index_orderby);
         1141  +
         1142  +            int sizeOfOrderByType = Marshal.SizeOf(indexOrderByType);
  1139   1143   
  1140   1144               for (int iOrderBy = 0; iOrderBy < nOrderBy; iOrderBy++)
  1141   1145               {
         1146  +                IntPtr pOffset = SQLiteMarshal.IntPtrForOffset(
         1147  +                    pOrderBy, iOrderBy * sizeOfOrderByType);
         1148  +
  1142   1149                   UnsafeNativeMethods.sqlite3_index_orderby orderBy =
  1143         -                    new UnsafeNativeMethods.sqlite3_index_orderby();
  1144         -
  1145         -                Marshal.PtrToStructure(SQLiteMarshal.IntPtrForOffset(
  1146         -                    pOrderBy, iOrderBy * sizeOfOrderByType), orderBy);
         1150  +                    (UnsafeNativeMethods.sqlite3_index_orderby)
         1151  +                        Marshal.PtrToStructure(pOffset, indexOrderByType);
  1147   1152   
  1148   1153                   index.Inputs.OrderBys[iOrderBy] =
  1149   1154                       new SQLiteIndexOrderBy(orderBy);
  1150   1155               }
  1151   1156           }
  1152   1157   
  1153   1158           ///////////////////////////////////////////////////////////////////////
................................................................................
  1187   1192   
  1188   1193               if (nConstraint != index.Inputs.Constraints.Length)
  1189   1194                   return;
  1190   1195   
  1191   1196               if (nConstraint != index.Outputs.ConstraintUsages.Length)
  1192   1197                   return;
  1193   1198   
  1194         -            offset += sizeof(int) + IntPtr.Size + sizeof(int) + IntPtr.Size;
         1199  +            offset += SQLiteMarshal.SizeOfStructInt() + IntPtr.Size +
         1200  +                SQLiteMarshal.SizeOfStructInt() + IntPtr.Size;
  1195   1201   
  1196   1202               IntPtr pConstraintUsage = SQLiteMarshal.ReadIntPtr(pIndex, offset);
  1197   1203   
  1198   1204               int sizeOfConstraintUsageType = Marshal.SizeOf(typeof(
  1199   1205                   UnsafeNativeMethods.sqlite3_index_constraint_usage));
  1200   1206   
  1201   1207               for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++)
................................................................................
  1204   1210                       new UnsafeNativeMethods.sqlite3_index_constraint_usage(
  1205   1211                           index.Outputs.ConstraintUsages[iConstraint]);
  1206   1212   
  1207   1213                   Marshal.StructureToPtr(
  1208   1214                       constraintUsage, SQLiteMarshal.IntPtrForOffset(
  1209   1215                       pConstraintUsage, iConstraint * sizeOfConstraintUsageType),
  1210   1216                       false);
  1211         -
  1212         -                index.Outputs.ConstraintUsages[iConstraint] =
  1213         -                    new SQLiteIndexConstraintUsage(constraintUsage);
  1214   1217               }
  1215   1218   
  1216   1219               offset += IntPtr.Size;
  1217   1220   
  1218   1221               SQLiteMarshal.WriteInt32(pIndex, offset,
  1219   1222                   index.Outputs.IndexNumber);
  1220   1223   
  1221         -            offset += sizeof(int);
         1224  +            offset += SQLiteMarshal.SizeOfStructInt();
  1222   1225   
  1223   1226               SQLiteMarshal.WriteIntPtr(pIndex, offset,
  1224   1227                   SQLiteString.Utf8IntPtrFromString(index.Outputs.IndexString));
  1225   1228   
  1226   1229               offset += IntPtr.Size;
  1227   1230   
  1228   1231               //
  1229   1232               // NOTE: We just allocated the IndexString field; therefore, we
  1230   1233               //       need to set the NeedToFreeIndexString field to non-zero.
  1231   1234               //
  1232   1235               SQLiteMarshal.WriteInt32(pIndex, offset, 1);
  1233   1236   
  1234         -            offset += sizeof(int);
         1237  +            offset += SQLiteMarshal.SizeOfStructInt();
  1235   1238   
  1236   1239               SQLiteMarshal.WriteInt32(pIndex, offset,
  1237   1240                   index.Outputs.OrderByConsumed);
  1238   1241   
  1239         -            offset += sizeof(int);
         1242  +            offset += SQLiteMarshal.SizeOfStructInt();
  1240   1243   
  1241   1244               SQLiteMarshal.WriteDouble(pIndex, offset,
  1242   1245                   index.Outputs.EstimatedCost);
  1243   1246           }
  1244   1247           #endregion
  1245   1248   
  1246   1249           ///////////////////////////////////////////////////////////////////////
................................................................................
  4103   4106           public static IntPtr IntPtrForOffset(
  4104   4107               IntPtr pointer,
  4105   4108               int offset
  4106   4109               )
  4107   4110           {
  4108   4111               return new IntPtr(pointer.ToInt64() + offset);
  4109   4112           }
         4113  +
         4114  +        ///////////////////////////////////////////////////////////////////////
         4115  +
         4116  +        /// <summary>
         4117  +        /// Determines the size of a <see cref="Int32" /> when it resides
         4118  +        /// inside of a native structure.
         4119  +        /// </summary>
         4120  +        /// <returns>
         4121  +        /// The size of the <see cref="Int32" /> type, in bytes, when it
         4122  +        /// resides inside a native structure.
         4123  +        /// </returns>
         4124  +        public static int SizeOfStructInt()
         4125  +        {
         4126  +            return IntPtr.Size;
         4127  +        }
  4110   4128           #endregion
  4111   4129   
  4112   4130           ///////////////////////////////////////////////////////////////////////
  4113   4131   
  4114   4132           #region Marshal Read Helper Methods
  4115   4133           /// <summary>
  4116   4134           /// Reads a <see cref="Int32" /> value from the specified memory
................................................................................
  5162   5180           /// This field is used to store the native sqlite3_module structure
  5163   5181           /// associated with this object instance.
  5164   5182           /// </summary>
  5165   5183           private UnsafeNativeMethods.sqlite3_module nativeModule;
  5166   5184   
  5167   5185           ///////////////////////////////////////////////////////////////////////
  5168   5186   
         5187  +        /// <summary>
         5188  +        /// This field is used to store a pointer to the native sqlite3_module
         5189  +        /// structure returned by the sqlite3_create_disposable_module
         5190  +        /// function.
         5191  +        /// </summary>
         5192  +        private IntPtr disposableModule;
         5193  +
         5194  +        ///////////////////////////////////////////////////////////////////////
         5195  +
  5169   5196   #if PLATFORM_COMPACTFRAMEWORK
  5170   5197           /// <summary>
  5171   5198           /// This field is used to hold the block of native memory that contains
  5172   5199           /// the native sqlite3_module structure associated with this object
  5173   5200           /// instance when running on the .NET Compact Framework.
  5174   5201           /// </summary>
  5175   5202           private IntPtr pNativeModule;
................................................................................
  5225   5252               this.functions = new Dictionary<string, SQLiteFunction>();
  5226   5253           }
  5227   5254           #endregion
  5228   5255   
  5229   5256           ///////////////////////////////////////////////////////////////////////
  5230   5257   
  5231   5258           #region Internal Methods
         5259  +        /// <summary>
         5260  +        /// Calls the native SQLite core library in order to create a new
         5261  +        /// disposable module containing the implementation of a virtual table.
         5262  +        /// </summary>
         5263  +        /// <param name="pDb">
         5264  +        /// The native database connection pointer to use.
         5265  +        /// </param>
         5266  +        /// <returns>
         5267  +        /// Non-zero upon success.
         5268  +        /// </returns>
         5269  +        internal bool CreateDisposableModule(
         5270  +            IntPtr pDb
         5271  +            )
         5272  +        {
         5273  +            if (disposableModule != IntPtr.Zero)
         5274  +                return true;
         5275  +
         5276  +            IntPtr pName = IntPtr.Zero;
         5277  +
         5278  +            try
         5279  +            {
         5280  +                pName = SQLiteString.Utf8IntPtrFromString(name);
         5281  +
         5282  +                UnsafeNativeMethods.sqlite3_module nativeModule =
         5283  +                    AllocateNativeModule();
         5284  +
         5285  +#if !PLATFORM_COMPACTFRAMEWORK
         5286  +                disposableModule =
         5287  +                    UnsafeNativeMethods.sqlite3_create_disposable_module(
         5288  +                        pDb, pName, ref nativeModule, IntPtr.Zero, null);
         5289  +
         5290  +                return (disposableModule != IntPtr.Zero);
         5291  +#elif !SQLITE_STANDARD
         5292  +
         5293  +
         5294  +                disposableModule =
         5295  +                    UnsafeNativeMethods.sqlite3_create_disposable_module_interop(
         5296  +                       pDb, pName, AllocateNativeModuleInterop(),
         5297  +                       nativeModule.iVersion, nativeModule.xCreate,
         5298  +                       nativeModule.xConnect, nativeModule.xBestIndex,
         5299  +                       nativeModule.xDisconnect, nativeModule.xDestroy,
         5300  +                       nativeModule.xOpen, nativeModule.xClose,
         5301  +                       nativeModule.xFilter, nativeModule.xNext,
         5302  +                       nativeModule.xEof, nativeModule.xColumn,
         5303  +                       nativeModule.xRowId, nativeModule.xUpdate,
         5304  +                       nativeModule.xBegin, nativeModule.xSync,
         5305  +                       nativeModule.xCommit, nativeModule.xRollback,
         5306  +                       nativeModule.xFindFunction, nativeModule.xRename,
         5307  +                       nativeModule.xSavepoint, nativeModule.xRelease,
         5308  +                       nativeModule.xRollbackTo, IntPtr.Zero, null);
         5309  +
         5310  +                return (disposableModule != IntPtr.Zero);
         5311  +#else
         5312  +                throw new NotImplementedException();
         5313  +#endif
         5314  +            }
         5315  +            finally
         5316  +            {
         5317  +                if (pName != IntPtr.Zero)
         5318  +                {
         5319  +                    SQLiteMemory.Free(pName);
         5320  +                    pName = IntPtr.Zero;
         5321  +                }
         5322  +            }
         5323  +        }
         5324  +        #endregion
         5325  +
         5326  +        ///////////////////////////////////////////////////////////////////////
         5327  +
         5328  +        #region Private Methods
  5232   5329           /// <summary>
  5233   5330           /// Creates and returns the native sqlite_module structure using the
  5234   5331           /// configured (or default) <see cref="ISQLiteNativeModule" />
  5235   5332           /// interface implementation.
  5236   5333           /// </summary>
  5237   5334           /// <returns>
  5238   5335           /// The native sqlite_module structure using the configured (or
  5239   5336           /// default) <see cref="ISQLiteNativeModule" /> interface
  5240   5337           /// implementation.
  5241   5338           /// </returns>
  5242         -        internal UnsafeNativeMethods.sqlite3_module CreateNativeModule()
         5339  +        private UnsafeNativeMethods.sqlite3_module AllocateNativeModule()
  5243   5340           {
  5244         -            return CreateNativeModule(GetNativeModuleImpl());
         5341  +            return AllocateNativeModule(GetNativeModuleImpl());
  5245   5342           }
  5246   5343   
  5247   5344           ///////////////////////////////////////////////////////////////////////
  5248   5345   
  5249   5346   #if PLATFORM_COMPACTFRAMEWORK
  5250   5347           /// <summary>
  5251   5348           /// Creates and returns a memory block obtained from the SQLite core
  5252   5349           /// library used to store the native sqlite3_module structure for this
  5253   5350           /// object instance when running on the .NET Compact Framework.
  5254   5351           /// </summary>
  5255   5352           /// <returns>
  5256   5353           /// The native pointer to the native sqlite3_module structure.
  5257   5354           /// </returns>
  5258         -        internal IntPtr CreateNativeModuleInterop()
         5355  +        private IntPtr AllocateNativeModuleInterop()
  5259   5356           {
  5260   5357               if (pNativeModule == IntPtr.Zero)
  5261   5358               {
  5262   5359                   //
  5263   5360                   // HACK: No easy way to determine the size of the native
  5264   5361                   //       sqlite_module structure when running on the .NET
  5265   5362                   //       Compact Framework; therefore, just base the size
  5266   5363                   //       on what we know:
  5267   5364                   //
  5268   5365                   //       There is one integer member.
  5269   5366                   //       There are 22 function pointer members.
  5270   5367                   //
  5271   5368                   pNativeModule = SQLiteMemory.Allocate(
  5272         -                    sizeof(int) + (22 * IntPtr.Size));
         5369  +                    SQLiteMarshal.SizeOfStructInt() + (22 * IntPtr.Size));
  5273   5370   
  5274   5371                   if (pNativeModule == IntPtr.Zero)
  5275   5372                       throw new OutOfMemoryException("sqlite3_module");
  5276   5373               }
  5277   5374   
  5278   5375               return pNativeModule;
  5279   5376           }
  5280   5377   #endif
  5281         -        #endregion
  5282   5378   
  5283   5379           ///////////////////////////////////////////////////////////////////////
  5284   5380   
  5285         -        #region Private Methods
  5286   5381           /// <summary>
  5287   5382           /// Creates and returns the native sqlite_module structure using the
  5288   5383           /// specified <see cref="ISQLiteNativeModule" /> interface
  5289   5384           /// implementation.
  5290   5385           /// </summary>
  5291   5386           /// <param name="module">
  5292   5387           /// The <see cref="ISQLiteNativeModule" /> interface implementation to
  5293   5388           /// use.
  5294   5389           /// </param>
  5295   5390           /// <returns>
  5296   5391           /// The native sqlite_module structure using the specified
  5297   5392           /// <see cref="ISQLiteNativeModule" /> interface implementation.
  5298   5393           /// </returns>
  5299         -        private UnsafeNativeMethods.sqlite3_module CreateNativeModule(
         5394  +        private UnsafeNativeMethods.sqlite3_module AllocateNativeModule(
  5300   5395               ISQLiteNativeModule module
  5301   5396               )
  5302   5397           {
  5303   5398               nativeModule = new UnsafeNativeMethods.sqlite3_module();
  5304   5399               nativeModule.iVersion = DefaultModuleVersion;
  5305   5400   
  5306   5401               if (module != null)
................................................................................
  5662   5757                   //
  5663   5758                   // NOTE: At this point, there is no way to report the error
  5664   5759                   //       condition back to the caller; therefore, use the
  5665   5760                   //       logging facility instead.
  5666   5761                   //
  5667   5762                   try
  5668   5763                   {
  5669         -                    if (LogExceptions)
         5764  +                    if (LogExceptionsNoThrow)
  5670   5765                       {
  5671   5766                           /* throw */
  5672   5767                           SQLiteLog.LogMessage(SQLiteBase.COR_E_EXCEPTION,
  5673   5768                               String.Format(CultureInfo.CurrentCulture,
  5674   5769                               "Caught exception in \"{0}\" method: {1}",
  5675   5770                               destroy ? "xDestroy" : "xDisconnect", e));
  5676   5771                       }
................................................................................
  5732   5827               {
  5733   5828                   // do nothing.
  5734   5829               }
  5735   5830   
  5736   5831               if (pVtab == IntPtr.Zero)
  5737   5832                   return false;
  5738   5833   
  5739         -            int offset = IntPtr.Size + sizeof(int);
         5834  +            int offset = IntPtr.Size + SQLiteMarshal.SizeOfStructInt();
  5740   5835               IntPtr pError = SQLiteMarshal.ReadIntPtr(pVtab, offset);
  5741   5836   
  5742   5837               if (pError != IntPtr.Zero)
  5743   5838               {
  5744   5839                   SQLiteMemory.Free(pError); pError = IntPtr.Zero;
  5745   5840                   SQLiteMarshal.WriteIntPtr(pVtab, offset, pError);
  5746   5841               }
................................................................................
  5977   6072   
  5978   6073               SQLiteMarshal.WriteIntPtr(pVtab, offset, IntPtr.Zero);
  5979   6074   
  5980   6075               offset += IntPtr.Size;
  5981   6076   
  5982   6077               SQLiteMarshal.WriteInt32(pVtab, offset, 0);
  5983   6078   
  5984         -            offset += sizeof(int);
         6079  +            offset += SQLiteMarshal.SizeOfStructInt();
  5985   6080   
  5986   6081               SQLiteMarshal.WriteIntPtr(pVtab, offset, IntPtr.Zero);
  5987   6082           }
  5988   6083   
  5989   6084           ///////////////////////////////////////////////////////////////////////
  5990   6085   
  5991   6086           /// <summary>
................................................................................
  6416   6511               return sqliteBase.DeclareVirtualFunction(
  6417   6512                   this, argumentCount, name, ref error);
  6418   6513           }
  6419   6514           #endregion
  6420   6515   
  6421   6516           ///////////////////////////////////////////////////////////////////////
  6422   6517   
         6518  +        #region Error Handling Properties
         6519  +        private bool logErrors;
         6520  +        /// <summary>
         6521  +        /// Returns or sets a boolean value indicating whether virtual table
         6522  +        /// errors should be logged using the <see cref="SQLiteLog" /> class.
         6523  +        /// </summary>
         6524  +        protected virtual bool LogErrorsNoThrow
         6525  +        {
         6526  +            get { return logErrors; }
         6527  +            set { logErrors = value; }
         6528  +        }
         6529  +
         6530  +        ///////////////////////////////////////////////////////////////////////
         6531  +
         6532  +        private bool logExceptions;
         6533  +        /// <summary>
         6534  +        /// Returns or sets a boolean value indicating whether exceptions
         6535  +        /// caught in the
         6536  +        /// <see cref="ISQLiteNativeModule.xDisconnect" /> method,
         6537  +        /// <see cref="ISQLiteNativeModule.xDestroy" /> method, and the
         6538  +        /// <see cref="Dispose()" /> method should be logged using the
         6539  +        /// <see cref="SQLiteLog" /> class.
         6540  +        /// </summary>
         6541  +        protected virtual bool LogExceptionsNoThrow
         6542  +        {
         6543  +            get { return logExceptions; }
         6544  +            set { logExceptions = value; }
         6545  +        }
         6546  +        #endregion
         6547  +
         6548  +        ///////////////////////////////////////////////////////////////////////
         6549  +
  6423   6550           #region Error Handling Helper Methods
  6424   6551           /// <summary>
  6425   6552           /// Arranges for the specified error message to be placed into the
  6426   6553           /// zErrMsg field of a sqlite3_vtab derived structure, freeing the
  6427   6554           /// existing error message, if any.
  6428   6555           /// </summary>
  6429   6556           /// <param name="pVtab">
................................................................................
  6436   6563           /// Non-zero upon success.
  6437   6564           /// </returns>
  6438   6565           protected virtual bool SetTableError(
  6439   6566               IntPtr pVtab,
  6440   6567               string error
  6441   6568               )
  6442   6569           {
  6443         -            return SetTableError(this, pVtab, LogErrors, error);
         6570  +            return SetTableError(this, pVtab, LogErrorsNoThrow, error);
  6444   6571           }
  6445   6572   
  6446   6573           ///////////////////////////////////////////////////////////////////////
  6447   6574   
  6448   6575           /// <summary>
  6449   6576           /// Arranges for the specified error message to be placed into the
  6450   6577           /// zErrMsg field of a sqlite3_vtab derived structure, freeing the
................................................................................
  6461   6588           /// Non-zero upon success.
  6462   6589           /// </returns>
  6463   6590           protected virtual bool SetTableError(
  6464   6591               SQLiteVirtualTable table,
  6465   6592               string error
  6466   6593               )
  6467   6594           {
  6468         -            return SetTableError(this, table, LogErrors, error);
         6595  +            return SetTableError(this, table, LogErrorsNoThrow, error);
  6469   6596           }
  6470   6597   
  6471   6598           ///////////////////////////////////////////////////////////////////////
  6472   6599   
  6473   6600           /// <summary>
  6474   6601           /// Arranges for the specified error message to be placed into the
  6475   6602           /// zErrMsg field of a sqlite3_vtab derived structure, freeing the
................................................................................
  6486   6613           /// Non-zero upon success.
  6487   6614           /// </returns>
  6488   6615           protected virtual bool SetCursorError(
  6489   6616               SQLiteVirtualTableCursor cursor,
  6490   6617               string error
  6491   6618               )
  6492   6619           {
  6493         -            return SetCursorError(this, cursor, LogErrors, error);
         6620  +            return SetCursorError(this, cursor, LogErrorsNoThrow, error);
  6494   6621           }
  6495   6622           #endregion
  6496   6623   
  6497   6624           ///////////////////////////////////////////////////////////////////////
  6498   6625   
  6499   6626           #region Index Handling Helper Methods
  6500   6627           /// <summary>
................................................................................
  6542   6669           }
  6543   6670           #endregion
  6544   6671           #endregion
  6545   6672   
  6546   6673           ///////////////////////////////////////////////////////////////////////
  6547   6674   
  6548   6675           #region Public Properties
  6549         -        private bool logErrors;
  6550   6676           /// <summary>
  6551   6677           /// Returns or sets a boolean value indicating whether virtual table
  6552   6678           /// errors should be logged using the <see cref="SQLiteLog" /> class.
  6553   6679           /// </summary>
  6554   6680           public virtual bool LogErrors
  6555   6681           {
  6556         -            get { CheckDisposed(); return logErrors; }
  6557         -            set { CheckDisposed(); logErrors = value; }
         6682  +            get { CheckDisposed(); return LogErrorsNoThrow; }
         6683  +            set { CheckDisposed(); LogErrorsNoThrow = value; }
  6558   6684           }
  6559   6685   
  6560   6686           ///////////////////////////////////////////////////////////////////////
  6561   6687   
  6562         -        private bool logExceptions;
  6563   6688           /// <summary>
  6564   6689           /// Returns or sets a boolean value indicating whether exceptions
  6565   6690           /// caught in the
  6566   6691           /// <see cref="ISQLiteNativeModule.xDisconnect" /> method,
  6567   6692           /// <see cref="ISQLiteNativeModule.xDestroy" /> method, and the
  6568   6693           /// <see cref="Dispose()" /> method should be logged using the
  6569   6694           /// <see cref="SQLiteLog" /> class.
  6570   6695           /// </summary>
  6571   6696           public virtual bool LogExceptions
  6572   6697           {
  6573         -            get { CheckDisposed(); return logExceptions; }
  6574         -            set { CheckDisposed(); logExceptions = value; }
         6698  +            get { CheckDisposed(); return LogExceptionsNoThrow; }
         6699  +            set { CheckDisposed(); LogExceptionsNoThrow = value; }
  6575   6700           }
  6576   6701           #endregion
  6577   6702   
  6578   6703           ///////////////////////////////////////////////////////////////////////
  6579   6704   
  6580   6705           #region ISQLiteNativeModule Members
  6581   6706           /// <summary>
................................................................................
  8030   8155   
  8031   8156                   //////////////////////////////////////
  8032   8157                   // release unmanaged resources here...
  8033   8158                   //////////////////////////////////////
  8034   8159   
  8035   8160                   try
  8036   8161                   {
  8037         -#if !PLATFORM_COMPACTFRAMEWORK
  8038         -                    UnsafeNativeMethods.sqlite3_dispose_module(
  8039         -                        ref nativeModule);
  8040         -#elif !SQLITE_STANDARD
  8041         -                    if (pNativeModule != IntPtr.Zero)
  8042         -                    {
  8043         -                        try
  8044         -                        {
  8045         -                            UnsafeNativeMethods.sqlite3_dispose_module_interop(
  8046         -                                pNativeModule);
  8047         -                        }
  8048         -                        finally
  8049         -                        {
  8050         -                            SQLiteMemory.Free(pNativeModule);
  8051         -                        }
  8052         -                    }
  8053         -#else
  8054         -                    throw new NotImplementedException();
  8055         -#endif
         8162  +                    UnsafeNativeMethods.sqlite3_dispose_module(disposableModule);
         8163  +                    disposableModule = IntPtr.Zero;
  8056   8164                   }
  8057   8165                   catch (Exception e)
  8058   8166                   {
  8059   8167                       try
  8060   8168                       {
  8061         -                        if (LogExceptions)
         8169  +                        if (LogExceptionsNoThrow)
  8062   8170                           {
  8063   8171                               SQLiteLog.LogMessage(SQLiteBase.COR_E_EXCEPTION,
  8064   8172                                   String.Format(CultureInfo.CurrentCulture,
  8065   8173                                   "Caught exception in \"Dispose\" method: {0}",
  8066   8174                                   e)); /* throw */
  8067   8175                           }
  8068   8176                       }
  8069   8177                       catch
  8070   8178                       {
  8071   8179                           // do nothing.
  8072   8180                       }
  8073   8181                   }
         8182  +#if PLATFORM_COMPACTFRAMEWORK
         8183  +                finally
         8184  +                {
         8185  +                    if (pNativeModule == IntPtr.Zero)
         8186  +                    {
         8187  +                        SQLiteMemory.Free(pNativeModule);
         8188  +                        pNativeModule = IntPtr.Zero;
         8189  +                    }
         8190  +                }
         8191  +#endif
  8074   8192   
  8075   8193                   disposed = true;
  8076   8194               }
  8077   8195           }
  8078   8196           #endregion
  8079   8197   
  8080   8198           ///////////////////////////////////////////////////////////////////////

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

  1603   1603       internal static extern IntPtr sqlite3_create_disposable_module(IntPtr db, IntPtr name, ref sqlite3_module module, IntPtr pClientData, xDestroyModule xDestroy);
  1604   1604   
  1605   1605   #if !PLATFORM_COMPACTFRAMEWORK
  1606   1606       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
  1607   1607   #else
  1608   1608       [DllImport(SQLITE_DLL)]
  1609   1609   #endif
  1610         -    internal static extern void sqlite3_dispose_module(ref sqlite3_module pModule);
         1610  +    internal static extern void sqlite3_dispose_module(IntPtr pModule);
  1611   1611   #endif
  1612   1612       #endregion
  1613   1613   
  1614   1614       ///////////////////////////////////////////////////////////////////////////
  1615   1615   
  1616   1616       #region sqlite interop api calls (.NET Compact Framework only)
  1617   1617   #if PLATFORM_COMPACTFRAMEWORK && !SQLITE_STANDARD
................................................................................
  1657   1657           xConnect xConnect, xBestIndex xBestIndex, xDisconnect xDisconnect,
  1658   1658           xDestroy xDestroy, xOpen xOpen, xClose xClose, xFilter xFilter,
  1659   1659           xNext xNext, xEof xEof, xColumn xColumn, xRowId xRowId, xUpdate xUpdate,
  1660   1660           xBegin xBegin, xSync xSync, xCommit xCommit, xRollback xRollback,
  1661   1661           xFindFunction xFindFunction, xRename xRename, xSavepoint xSavepoint,
  1662   1662           xRelease xRelease, xRollbackTo xRollbackTo, IntPtr pClientData,
  1663   1663           xDestroyModule xDestroyModule);
  1664         -
  1665         -    [DllImport(SQLITE_DLL)]
  1666         -    internal static extern void sqlite3_dispose_module_interop(IntPtr pModule);
  1667   1664   #endif
  1668   1665       // PLATFORM_COMPACTFRAMEWORK && !SQLITE_STANDARD
  1669   1666       #endregion
  1670   1667   
  1671   1668       ///////////////////////////////////////////////////////////////////////////
  1672   1669   
  1673   1670       #region Native Delegates