Index: System.Data.SQLite/SQLiteSession.cs ================================================================== --- System.Data.SQLite/SQLiteSession.cs +++ System.Data.SQLite/SQLiteSession.cs @@ -150,10 +150,15 @@ #region SQLiteConnectionLock Class internal abstract class SQLiteConnectionLock : IDisposable { #region Private Constants private const string LockNopSql = "SELECT 1;"; + + /////////////////////////////////////////////////////////////////////// + + private const string StatementMessageFormat = + "Connection lock object was {0} with statement {1}"; #endregion /////////////////////////////////////////////////////////////////////// #region Private Data @@ -180,12 +185,26 @@ } #endregion /////////////////////////////////////////////////////////////////////// - #region Private Methods - private IntPtr GetHandle() + #region Protected Methods + protected SQLiteConnectionHandle GetHandle() + { + return handle; + } + + /////////////////////////////////////////////////////////////////////// + + protected SQLiteConnectionFlags GetFlags() + { + return flags; + } + + /////////////////////////////////////////////////////////////////////// + + protected IntPtr GetIntPtr() { if (handle == null) { throw new InvalidOperationException( "Connection lock object has an invalid handle."); @@ -223,11 +242,11 @@ IntPtr pRemain = IntPtr.Zero; int nRemain = 0; SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_prepare_interop( - GetHandle(), pSql, nSql, ref statement, ref pRemain, + GetIntPtr(), pSql, nSql, ref statement, ref pRemain, ref nRemain); if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "sqlite3_prepare_interop"); } @@ -311,18 +330,20 @@ // disposed (or finalized) without the Unlock // method being called first. // try { - if ((flags & SQLiteConnectionFlags.LogPrepare) == - SQLiteConnectionFlags.LogPrepare) + if (HelperMethods.LogPrepare(GetFlags())) { /* throw */ - SQLiteLog.LogMessage(SQLiteErrorCode.Misuse, - HelperMethods.StringFormat(CultureInfo.CurrentCulture, - "Connection lock object was {0} with statement {1}", - disposing ? "disposed" : "finalized", statement)); + SQLiteLog.LogMessage( + SQLiteErrorCode.Misuse, + HelperMethods.StringFormat( + CultureInfo.CurrentCulture, + StatementMessageFormat, disposing ? + "disposed" : "finalized", + statement)); } } catch { // do nothing. @@ -384,11 +405,11 @@ throw new InvalidOperationException("iterator is not open"); } /////////////////////////////////////////////////////////////////////// - internal IntPtr GetHandle() + internal IntPtr GetIntPtr() { return iterator; } #endregion @@ -769,10 +790,19 @@ } #endregion /////////////////////////////////////////////////////////////////////// + #region Private Methods + private SQLiteConnectionFlags GetFlags() + { + return flags; + } + #endregion + + /////////////////////////////////////////////////////////////////////// + #region Native Callback Methods public SQLiteErrorCode xInput( IntPtr context, IntPtr pData, ref int nData @@ -797,17 +827,18 @@ } catch (Exception e) { try { - if ((flags & SQLiteConnectionFlags.LogCallbackException) == - SQLiteConnectionFlags.LogCallbackException) + if (HelperMethods.LogCallbackExceptions(GetFlags())) { - SQLiteLog.LogMessage(SQLiteBase.COR_E_EXCEPTION, - HelperMethods.StringFormat(CultureInfo.CurrentCulture, - "Caught exception in \"xInput\" method: {0}", - e)); /* throw */ + SQLiteLog.LogMessage( + SQLiteBase.COR_E_EXCEPTION, + HelperMethods.StringFormat( + CultureInfo.CurrentCulture, + UnsafeNativeMethods.ExceptionMessageFormat, + "xInput", e)); /* throw */ } } catch { // do nothing. @@ -844,17 +875,18 @@ } catch (Exception e) { try { - if ((flags & SQLiteConnectionFlags.LogCallbackException) == - SQLiteConnectionFlags.LogCallbackException) + if (HelperMethods.LogCallbackExceptions(GetFlags())) { - SQLiteLog.LogMessage(SQLiteBase.COR_E_EXCEPTION, - HelperMethods.StringFormat(CultureInfo.CurrentCulture, - "Caught exception in \"xOutput\" method: {0}", - e)); /* throw */ + SQLiteLog.LogMessage( + SQLiteBase.COR_E_EXCEPTION, + HelperMethods.StringFormat( + CultureInfo.CurrentCulture, + UnsafeNativeMethods.ExceptionMessageFormat, + "xOutput", e)); /* throw */ } } catch { // do nothing. @@ -1567,18 +1599,189 @@ } #endregion /////////////////////////////////////////////////////////////////////////// + #region SQLiteChangeSetBase Class + internal class SQLiteChangeSetBase : SQLiteConnectionLock + { + #region Private Constants + private const string ExceptionMessageFormat = + "Caught exception in \"{0}\" method: {1}"; + #endregion + + /////////////////////////////////////////////////////////////////////// + + #region Private Constructors + internal SQLiteChangeSetBase( + SQLiteConnectionHandle handle, + SQLiteConnectionFlags flags + ) + : base(handle, flags) + { + // do nothing. + } + #endregion + + /////////////////////////////////////////////////////////////////////// + + #region Protected Methods + protected UnsafeNativeMethods.xSessionFilter GetDelegate( + SessionTableFilterCallback tableFilterCallback, + object clientData + ) + { + if (tableFilterCallback == null) + return null; + + UnsafeNativeMethods.xSessionFilter xFilter; + + xFilter = new UnsafeNativeMethods.xSessionFilter( + delegate(IntPtr context, byte[] tblName) + { + try + { + string name = SQLiteString.GetStringFromUtf8Bytes( + tblName); + + return tableFilterCallback(clientData, name) ? 1 : 0; + } + catch (Exception e) + { + try + { + if (HelperMethods.LogCallbackExceptions(GetFlags())) + { + SQLiteLog.LogMessage( /* throw */ + SQLiteBase.COR_E_EXCEPTION, + HelperMethods.StringFormat( + CultureInfo.CurrentCulture, + UnsafeNativeMethods.ExceptionMessageFormat, + "xFilter", e)); + } + } + catch + { + // do nothing. + } + } + + return 0; + }); + + return xFilter; + } + + /////////////////////////////////////////////////////////////////////// + + protected UnsafeNativeMethods.xSessionConflict GetDelegate( + SessionConflictCallback conflictCallback, + object clientData + ) + { + if (conflictCallback == null) + return null; + + UnsafeNativeMethods.xSessionConflict xConflict; + + xConflict = new UnsafeNativeMethods.xSessionConflict( + delegate(IntPtr context, + SQLiteChangeSetConflictType type, + IntPtr iterator) + { + ISQLiteChangeSetMetadataItem item = null; + + try + { + return conflictCallback(clientData, type, item); + } + catch (Exception e) + { + try + { + if (HelperMethods.LogCallbackExceptions(GetFlags())) + { + SQLiteLog.LogMessage( /* throw */ + SQLiteBase.COR_E_EXCEPTION, + HelperMethods.StringFormat( + CultureInfo.CurrentCulture, + UnsafeNativeMethods.ExceptionMessageFormat, + "xConflict", e)); + } + } + catch + { + // do nothing. + } + } + + return SQLiteChangeSetConflictResult.Abort; + }); + + return xConflict; + } + #endregion + + /////////////////////////////////////////////////////////////////////// + + #region IDisposable "Pattern" Members + private bool disposed; + private void CheckDisposed() /* throw */ + { +#if THROW_ON_DISPOSED + if (disposed) + { + throw new ObjectDisposedException( + typeof(SQLiteChangeSetBase).Name); + } +#endif + } + + /////////////////////////////////////////////////////////////////////// + + protected override void Dispose(bool disposing) + { + try + { + if (!disposed) + { + if (disposing) + { + //////////////////////////////////// + // dispose managed resources here... + //////////////////////////////////// + } + + ////////////////////////////////////// + // release unmanaged resources here... + ////////////////////////////////////// + + Unlock(); + } + } + finally + { + base.Dispose(disposing); + + // + // NOTE: Everything should be fully disposed at this point. + // + disposed = true; + } + } + #endregion + } + #endregion + + /////////////////////////////////////////////////////////////////////////// + #region SQLiteMemoryChangeSet Class internal sealed class SQLiteMemoryChangeSet : - SQLiteConnectionLock, ISQLiteChangeSet + SQLiteChangeSetBase, ISQLiteChangeSet { #region Private Data private byte[] rawData; - private SQLiteConnectionHandle handle; - private SQLiteConnectionFlags flags; #endregion /////////////////////////////////////////////////////////////////////// #region Private Constructors @@ -1588,12 +1791,10 @@ SQLiteConnectionFlags flags ) : base(handle, flags) { this.rawData = rawData; - this.handle= handle; - this.flags = flags; } #endregion /////////////////////////////////////////////////////////////////////// @@ -1630,11 +1831,12 @@ if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "sqlite3changeset_invert"); byte[] newData = SQLiteBytes.FromIntPtr(pOutData, nOutData); - return new SQLiteMemoryChangeSet(newData, handle, flags); + return new SQLiteMemoryChangeSet( + newData, GetHandle(), GetFlags()); } finally { if (pOutData != IntPtr.Zero) { @@ -1694,11 +1896,12 @@ if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "sqlite3changeset_concat"); byte[] newData = SQLiteBytes.FromIntPtr(pOutData, nOutData); - return new SQLiteMemoryChangeSet(newData, handle, flags); + return new SQLiteMemoryChangeSet( + newData, GetHandle(), GetFlags()); } finally { if (pOutData != IntPtr.Zero) { @@ -1744,89 +1947,15 @@ CheckRawData(); if (conflictCallback == null) throw new ArgumentNullException("conflictCallback"); - /////////////////////////////////////////////////////////////////// - - #region Native Callback Methods - UnsafeNativeMethods.xSessionFilter xFilter = null; - - if (tableFilterCallback != null) - { - xFilter = new UnsafeNativeMethods.xSessionFilter( - delegate(IntPtr context, byte[] tblName) - { - try - { - string name = SQLiteString.GetStringFromUtf8Bytes( - tblName); - - return tableFilterCallback(clientData, name) ? 1 : 0; - } - catch (Exception e) - { - try - { - if ((flags & SQLiteConnectionFlags.LogCallbackException) == - SQLiteConnectionFlags.LogCallbackException) - { - SQLiteLog.LogMessage(SQLiteBase.COR_E_EXCEPTION, - HelperMethods.StringFormat(CultureInfo.CurrentCulture, - "Caught exception in \"xFilter\" method: {0}", - e)); /* throw */ - } - } - catch - { - // do nothing. - } - } - - return 0; - }); - } - - /////////////////////////////////////////////////////////////////// - - UnsafeNativeMethods.xSessionConflict xConflict; - - xConflict = new UnsafeNativeMethods.xSessionConflict( - delegate(IntPtr context, - SQLiteChangeSetConflictType type, - IntPtr iterator) - { - ISQLiteChangeSetMetadataItem item = null; - - try - { - return conflictCallback(clientData, type, item); - } - catch (Exception e) - { - try - { - if ((flags & SQLiteConnectionFlags.LogCallbackException) == - SQLiteConnectionFlags.LogCallbackException) - { - SQLiteLog.LogMessage(SQLiteBase.COR_E_EXCEPTION, - HelperMethods.StringFormat(CultureInfo.CurrentCulture, - "Caught exception in \"xConflict\" method: {0}", - e)); /* throw */ - } - } - catch - { - // do nothing. - } - } - - return SQLiteChangeSetConflictResult.Abort; - }); - #endregion - - /////////////////////////////////////////////////////////////////// + UnsafeNativeMethods.xSessionFilter xFilter = GetDelegate( + tableFilterCallback, clientData); + + UnsafeNativeMethods.xSessionConflict xConflict = GetDelegate( + conflictCallback, clientData); IntPtr pData = IntPtr.Zero; try { @@ -1833,11 +1962,11 @@ int nData = 0; pData = SQLiteBytes.ToIntPtr(rawData, ref nData); SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_apply( - handle, nData, pData, xFilter, xConflict, IntPtr.Zero); + GetIntPtr(), nData, pData, xFilter, xConflict, IntPtr.Zero); if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "sqlite3changeset_apply"); } finally @@ -1925,17 +2054,15 @@ /////////////////////////////////////////////////////////////////////////// #region SQLiteStreamChangeSet Class internal sealed class SQLiteStreamChangeSet : - SQLiteConnectionLock, ISQLiteChangeSet + SQLiteChangeSetBase, ISQLiteChangeSet { #region Private Data private Stream inputStream; private Stream outputStream; - private SQLiteConnectionHandle handle; - private SQLiteConnectionFlags flags; #endregion /////////////////////////////////////////////////////////////////////// #region Private Constructors @@ -1947,12 +2074,10 @@ ) : base(handle, flags) { this.inputStream = inputStream; this.outputStream = outputStream; - this.handle = handle; - this.flags = flags; } #endregion /////////////////////////////////////////////////////////////////////// @@ -1984,10 +2109,12 @@ public ISQLiteChangeSet Invert() { CheckDisposed(); CheckInputStream(); CheckOutputStream(); + + SQLiteConnectionFlags flags = GetFlags(); SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_invert_strm( new SQLiteStreamAdapter(inputStream, flags).xInput, IntPtr.Zero, new SQLiteStreamAdapter(outputStream, flags).xOutput, IntPtr.Zero); @@ -2015,16 +2142,19 @@ throw new ArgumentException( "not a stream based change set", "changeSet"); } streamChangeSet.CheckInputStream(); + + SQLiteConnectionFlags otherFlags = streamChangeSet.GetFlags(); + SQLiteConnectionFlags flags = GetFlags(); SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_concat_strm( - new SQLiteStreamAdapter(inputStream, flags).xInput, IntPtr.Zero, - new SQLiteStreamAdapter(streamChangeSet.inputStream, - streamChangeSet.flags).xInput, IntPtr.Zero, - new SQLiteStreamAdapter(outputStream, flags).xOutput, IntPtr.Zero); + new SQLiteStreamAdapter(inputStream, flags).xInput, + IntPtr.Zero, new SQLiteStreamAdapter(streamChangeSet.inputStream, + otherFlags).xInput, IntPtr.Zero, new SQLiteStreamAdapter( + outputStream, flags).xOutput, IntPtr.Zero); if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "sqlite3changeset_concat_strm"); return null; @@ -2054,89 +2184,20 @@ CheckInputStream(); if (conflictCallback == null) throw new ArgumentNullException("conflictCallback"); - /////////////////////////////////////////////////////////////////// - - #region Native Callback Methods - UnsafeNativeMethods.xSessionFilter xFilter; - - xFilter = new UnsafeNativeMethods.xSessionFilter( - delegate(IntPtr context, byte[] tblName) - { - try - { - string name = SQLiteString.GetStringFromUtf8Bytes( - tblName); - - return tableFilterCallback(clientData, name) ? 1 : 0; - } - catch (Exception e) - { - try - { - if ((flags & SQLiteConnectionFlags.LogCallbackException) == - SQLiteConnectionFlags.LogCallbackException) - { - SQLiteLog.LogMessage(SQLiteBase.COR_E_EXCEPTION, - HelperMethods.StringFormat(CultureInfo.CurrentCulture, - "Caught exception in \"xFilter\" method: {0}", - e)); /* throw */ - } - } - catch - { - // do nothing. - } - } - - return 0; - }); - - /////////////////////////////////////////////////////////////////// - - UnsafeNativeMethods.xSessionConflict xConflict; - - xConflict = new UnsafeNativeMethods.xSessionConflict( - delegate(IntPtr context, - SQLiteChangeSetConflictType type, - IntPtr iterator) - { - ISQLiteChangeSetMetadataItem item = null; - - try - { - return conflictCallback(clientData, type, item); - } - catch (Exception e) - { - try - { - if ((flags & SQLiteConnectionFlags.LogCallbackException) == - SQLiteConnectionFlags.LogCallbackException) - { - SQLiteLog.LogMessage(SQLiteBase.COR_E_EXCEPTION, - HelperMethods.StringFormat(CultureInfo.CurrentCulture, - "Caught exception in \"xConflict\" method: {0}", - e)); /* throw */ - } - } - catch - { - // do nothing. - } - } - - return SQLiteChangeSetConflictResult.Abort; - }); - #endregion - - /////////////////////////////////////////////////////////////////// + UnsafeNativeMethods.xSessionFilter xFilter = GetDelegate( + tableFilterCallback, clientData); + + UnsafeNativeMethods.xSessionConflict xConflict = GetDelegate( + conflictCallback, clientData); + + SQLiteConnectionFlags flags = GetFlags(); SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_apply_strm( - handle, new SQLiteStreamAdapter(inputStream, flags).xInput, + GetIntPtr(), new SQLiteStreamAdapter(inputStream, flags).xInput, IntPtr.Zero, xFilter, xConflict, IntPtr.Zero); if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "sqlite3changeset_apply_strm"); } @@ -2145,10 +2206,11 @@ /////////////////////////////////////////////////////////////////////// #region IEnumerable Members public IEnumerator GetEnumerator() { + SQLiteConnectionFlags flags = GetFlags(); return new SQLiteStreamChangeSetEnumerator(inputStream, flags); } #endregion /////////////////////////////////////////////////////////////////////// @@ -2590,11 +2652,11 @@ SQLiteAuthorizerActionCode op = SQLiteAuthorizerActionCode.None; int bIndirect = 0; int nColumns = 0; SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_op( - iterator.GetHandle(), ref pTblName, ref nColumns, ref op, + iterator.GetIntPtr(), ref pTblName, ref nColumns, ref op, ref bIndirect); if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "sqlite3changeset_op"); @@ -2615,11 +2677,11 @@ IntPtr pPrimaryKeys = IntPtr.Zero; int nColumns = 0; SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_pk( - iterator.GetHandle(), ref pPrimaryKeys, ref nColumns); + iterator.GetIntPtr(), ref pPrimaryKeys, ref nColumns); if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "sqlite3changeset_pk"); byte[] bytes = SQLiteBytes.FromIntPtr(pPrimaryKeys, nColumns); @@ -2644,11 +2706,11 @@ int conflicts = 0; SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_fk_conflicts( - iterator.GetHandle(), ref conflicts); + iterator.GetIntPtr(), ref conflicts); if (rc != SQLiteErrorCode.Ok) { throw new SQLiteException(rc, "sqlite3changeset_fk_conflicts"); @@ -2754,11 +2816,11 @@ CheckIterator(); IntPtr pValue = IntPtr.Zero; SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_old( - iterator.GetHandle(), columnIndex, ref pValue); + iterator.GetIntPtr(), columnIndex, ref pValue); return SQLiteValue.FromIntPtr(pValue); } /////////////////////////////////////////////////////////////////////// @@ -2771,11 +2833,11 @@ CheckIterator(); IntPtr pValue = IntPtr.Zero; SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_new( - iterator.GetHandle(), columnIndex, ref pValue); + iterator.GetIntPtr(), columnIndex, ref pValue); return SQLiteValue.FromIntPtr(pValue); } /////////////////////////////////////////////////////////////////////// @@ -2788,11 +2850,11 @@ CheckIterator(); IntPtr pValue = IntPtr.Zero; SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_conflict( - iterator.GetHandle(), columnIndex, ref pValue); + iterator.GetIntPtr(), columnIndex, ref pValue); return SQLiteValue.FromIntPtr(pValue); } #endregion