Index: System.Data.SQLite/SQLiteSessions.cs ================================================================== --- System.Data.SQLite/SQLiteSessions.cs +++ System.Data.SQLite/SQLiteSessions.cs @@ -35,18 +35,18 @@ /////////////////////////////////////////////////////////////////////////// #region Session Extension Delegates public delegate bool SessionTableFilterCallback( - object context, + object clientData, string name ); /////////////////////////////////////////////////////////////////////////// public delegate SQLiteChangeSetConflictResult SessionConflictCallback( - object context, + object clientData, SQLiteChangeSetConflictType type, ISQLiteChangeSetMetadataItem item ); #endregion @@ -67,11 +67,11 @@ { void AddChangeSet(byte[] rawData); void AddChangeSet(Stream stream); void CreateChangeSet(ref byte[] rawData); - void CreateChangeSet(Stream stream, SQLiteConnectionFlags flags); + void CreateChangeSet(Stream stream); } /////////////////////////////////////////////////////////////////////////// public interface ISQLiteChangeSetMetadataItem @@ -106,35 +106,35 @@ void AttachTable(string name); void SetTableFilter( SessionTableFilterCallback callback, - object context + object clientData ); void CreateChangeSet(ref byte[] rawData); - void CreateChangeSet(Stream stream, SQLiteConnectionFlags flags); + void CreateChangeSet(Stream stream); void CreatePatchSet(ref byte[] rawData); - void CreatePatchSet(Stream stream, SQLiteConnectionFlags flags); + void CreatePatchSet(Stream stream); void LoadDifferencesFromTable( string fromDatabaseName, string tableName ); void ApplyChangeSet( byte[] rawData, SessionConflictCallback conflictCallback, - object context + object clientData ); void ApplyChangeSet( Stream stream, SessionConflictCallback conflictCallback, SessionTableFilterCallback tableFilterCallback, - object context + object clientData ); } #endregion /////////////////////////////////////////////////////////////////////////// @@ -558,11 +558,11 @@ private IntPtr session; /////////////////////////////////////////////////////////////////////// private SessionTableFilterCallback tableFilterCallback; - private object tableFilterContext; + private object tableFilterClientData; #endregion /////////////////////////////////////////////////////////////////////// #region Public Constructors @@ -589,17 +589,24 @@ throw new InvalidOperationException("session is not open"); } /////////////////////////////////////////////////////////////////////// + private SQLiteConnectionFlags GetConnectionFlags() + { + return SQLiteConnectionFlags.None; + } + + /////////////////////////////////////////////////////////////////////// + #region Native Callback Methods private int xFilter( IntPtr context, /* NOT USED */ byte[] tblName ) { - return tableFilterCallback(tableFilterContext, + return tableFilterCallback(tableFilterClientData, SQLiteString.GetStringFromUtf8Bytes(tblName)) ? 1 : 0; } #endregion #endregion @@ -690,18 +697,18 @@ /////////////////////////////////////////////////////////////////////// public void SetTableFilter( SessionTableFilterCallback callback, - object context + object clientData ) { CheckDisposed(); CheckHandle(); this.tableFilterCallback = callback; - this.tableFilterContext = context; + this.tableFilterClientData = clientData; UnsafeNativeMethods.sqlite3session_table_filter( session, xFilter, IntPtr.Zero); } @@ -739,16 +746,17 @@ } /////////////////////////////////////////////////////////////////////// public void CreateChangeSet( - Stream stream, - SQLiteConnectionFlags flags + Stream stream ) { CheckDisposed(); CheckHandle(); + + SQLiteConnectionFlags flags = GetConnectionFlags(); SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3session_changeset_strm( session, new SQLiteStreamAdapter(stream, flags).xOutput, IntPtr.Zero); @@ -790,16 +798,17 @@ } /////////////////////////////////////////////////////////////////////// public void CreatePatchSet( - Stream stream, - SQLiteConnectionFlags flags + Stream stream ) { CheckDisposed(); CheckHandle(); + + SQLiteConnectionFlags flags = GetConnectionFlags(); SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3session_patchset_strm( session, new SQLiteStreamAdapter(stream, flags).xOutput, IntPtr.Zero); @@ -863,15 +872,110 @@ object clientData ) { CheckDisposed(); + SQLiteConnectionFlags flags = GetConnectionFlags(); + int nData = 0; IntPtr pData = IntPtr.Zero; - SQLiteConnectionFlags flags = connection.Flags; - UnsafeNativeMethods.xSessionConflict xConflict = new UnsafeNativeMethods.xSessionConflict(delegate(IntPtr context, SQLiteChangeSetConflictType type, IntPtr iterator) + UnsafeNativeMethods.xSessionConflict 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; + }); + + SQLiteConnectionHandle handle = SQLiteConnection.GetNativeHandle( + connection); + + SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_apply( + handle, nData, pData, null, xConflict, IntPtr.Zero); + + if (rc != SQLiteErrorCode.Ok) + throw new SQLiteException(rc, "sqlite3changeset_apply"); + } + + /////////////////////////////////////////////////////////////////////// + + public void ApplyChangeSet( + Stream stream, + SessionConflictCallback conflictCallback, + SessionTableFilterCallback tableFilterCallback, + object clientData + ) + { + CheckDisposed(); + + SQLiteConnectionFlags flags = GetConnectionFlags(); + + UnsafeNativeMethods.xSessionFilter 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 = + new UnsafeNativeMethods.xSessionConflict( + delegate(IntPtr context, + SQLiteChangeSetConflictType type, + IntPtr iterator) { ISQLiteChangeSetMetadataItem item = null; try { @@ -897,27 +1001,19 @@ } return SQLiteChangeSetConflictResult.Abort; }); - SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_apply( - SQLiteConnection.GetNativeHandle(connection), nData, pData, - null, xConflict, IntPtr.Zero); - } - - /////////////////////////////////////////////////////////////////////// - - public void ApplyChangeSet( - Stream stream, - SessionConflictCallback conflictCallback, - SessionTableFilterCallback tableFilterCallback, - object context - ) - { - CheckDisposed(); - - throw new NotImplementedException(); + SQLiteConnectionHandle handle = SQLiteConnection.GetNativeHandle( + connection); + + SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_apply_strm( + handle, new SQLiteStreamAdapter(stream, flags).xInput, + IntPtr.Zero, xFilter, xConflict, IntPtr.Zero); + + if (rc != SQLiteErrorCode.Ok) + throw new SQLiteException(rc, "sqlite3changeset_apply_strm"); } #endregion ///////////////////////////////////////////////////////////////////////