System.Data.SQLite
Check-in [8f18f2c045]
Not logged in

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

Overview
Comment:Final work on the initial draft of the doc comments.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: 8f18f2c04582b36bc695788a3e8d19e8894b810e
User & Date: mistachkin 2017-10-14 06:37:21
Context
2017-10-14
07:20
Update the master release archive manifest. Closed-Leaf check-in: 71327c1dd6 user: mistachkin tags: sessions
06:37
Final work on the initial draft of the doc comments. check-in: 8f18f2c045 user: mistachkin tags: sessions
04:38
More progress on doc comments. check-in: dfc53a02a6 user: mistachkin tags: sessions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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

   199    199       /// <summary>
   200    200       /// This interface contains methods used to manipulate a set of changes for
   201    201       /// a database.
   202    202       /// </summary>
   203    203       public interface ISQLiteChangeSet :
   204    204           IEnumerable<ISQLiteChangeSetMetadataItem>, IDisposable
   205    205       {
          206  +        /// <summary>
          207  +        /// This method "inverts" the set of changes within this instance.
          208  +        /// Applying an inverted set of changes to a database reverses the
          209  +        /// effects of applying the uninverted changes.  Specifically:
          210  +        /// <![CDATA[<ul>]]><![CDATA[<li>]]>
          211  +        /// Each DELETE change is changed to an INSERT, and
          212  +        /// <![CDATA[</li>]]><![CDATA[<li>]]>
          213  +        /// Each INSERT change is changed to a DELETE, and
          214  +        /// <![CDATA[</li>]]><![CDATA[<li>]]>
          215  +        /// For each UPDATE change, the old.* and new.* values are exchanged.
          216  +        /// <![CDATA[</li>]]><![CDATA[</ul>]]>
          217  +        /// This method does not change the order in which changes appear
          218  +        /// within the set of changes. It merely reverses the sense of each
          219  +        /// individual change.
          220  +        /// </summary>
          221  +        /// <returns>
          222  +        /// The new <see cref="ISQLiteChangeSet" /> instance that represents
          223  +        /// the resulting set of changes -OR- null if it is not available.
          224  +        /// </returns>
   206    225           ISQLiteChangeSet Invert();
          226  +
          227  +        /// <summary>
          228  +        /// This method combines the specified set of changes with the ones
          229  +        /// contained in this instance.
          230  +        /// </summary>
          231  +        /// <param name="changeSet">
          232  +        /// The changes to be combined with those in this instance.
          233  +        /// </param>
          234  +        /// <returns>
          235  +        /// The new <see cref="ISQLiteChangeSet" /> instance that represents
          236  +        /// the resulting set of changes -OR- null if it is not available.
          237  +        /// </returns>
   207    238           ISQLiteChangeSet CombineWith(ISQLiteChangeSet changeSet);
   208    239   
          240  +        /// <summary>
          241  +        /// Attempts to apply the set of changes in this instance to the
          242  +        /// associated database.
          243  +        /// </summary>
          244  +        /// <param name="conflictCallback">
          245  +        /// The <see cref="SessionConflictCallback" /> delegate that will need
          246  +        /// to handle any conflicting changes that may arise.
          247  +        /// </param>
          248  +        /// <param name="clientData">
          249  +        /// The optional application-defined context data.  This value may be
          250  +        /// null.
          251  +        /// </param>
   209    252           void Apply(
   210    253               SessionConflictCallback conflictCallback,
   211    254               object clientData
   212    255           );
   213    256   
          257  +        /// <summary>
          258  +        /// Attempts to apply the set of changes in this instance to the
          259  +        /// associated database.
          260  +        /// </summary>
          261  +        /// <param name="conflictCallback">
          262  +        /// The <see cref="SessionConflictCallback" /> delegate that will need
          263  +        /// to handle any conflicting changes that may arise.
          264  +        /// </param>
          265  +        /// <param name="tableFilterCallback">
          266  +        /// The optional <see cref="SessionTableFilterCallback" /> delegate
          267  +        /// that can be used to filter the list of tables impacted by the set
          268  +        /// of changes.
          269  +        /// </param>
          270  +        /// <param name="clientData">
          271  +        /// The optional application-defined context data.  This value may be
          272  +        /// null.
          273  +        /// </param>
   214    274           void Apply(
   215    275               SessionConflictCallback conflictCallback,
   216    276               SessionTableFilterCallback tableFilterCallback,
   217    277               object clientData
   218    278           );
   219    279       }
   220    280       #endregion
................................................................................
  3163   3223           #endregion
  3164   3224       }
  3165   3225       #endregion
  3166   3226   
  3167   3227       ///////////////////////////////////////////////////////////////////////////
  3168   3228   
  3169   3229       #region SQLiteChangeSetBase Class
         3230  +    /// <summary>
         3231  +    /// This class represents the abstract concept of a set of changes.  It
         3232  +    /// acts as the base class for the <see cref="SQLiteMemoryChangeSet" />
         3233  +    /// and <see cref="SQLiteStreamChangeSet" /> classes.  It derives from
         3234  +    /// the <see cref="SQLiteConnectionLock" /> class, which is used to hold
         3235  +    /// the underlying native connection handle open until the instances of
         3236  +    /// this class are disposed or finalized.  It also provides the ability
         3237  +    /// to construct wrapped native delegates of the
         3238  +    /// <see cref="UnsafeNativeMethods.xSessionFilter" /> and
         3239  +    /// <see cref="UnsafeNativeMethods.xSessionConflict" /> types.
         3240  +    /// </summary>
  3170   3241       internal class SQLiteChangeSetBase : SQLiteConnectionLock
  3171   3242       {
  3172   3243           #region Private Constructors
         3244  +        /// <summary>
         3245  +        /// Constructs an instance of this class using the specified wrapped
         3246  +        /// native connection handle.
         3247  +        /// </summary>
         3248  +        /// <param name="handle">
         3249  +        /// The wrapped native connection handle to be associated with this
         3250  +        /// change set.
         3251  +        /// </param>
         3252  +        /// <param name="flags">
         3253  +        /// The flags associated with the connection represented by the
         3254  +        /// <paramref name="handle" /> value.
         3255  +        /// </param>
  3173   3256           internal SQLiteChangeSetBase(
  3174   3257               SQLiteConnectionHandle handle,
  3175   3258               SQLiteConnectionFlags flags
  3176   3259               )
  3177   3260               : base(handle, flags, true)
  3178   3261           {
  3179   3262               // do nothing.
  3180   3263           }
  3181   3264           #endregion
  3182   3265   
  3183   3266           ///////////////////////////////////////////////////////////////////////
  3184   3267   
  3185   3268           #region Private Methods
         3269  +        /// <summary>
         3270  +        /// Creates and returns a concrete implementation of the
         3271  +        /// <see cref="ISQLiteChangeSetMetadataItem" /> interface.
         3272  +        /// </summary>
         3273  +        /// <param name="iterator">
         3274  +        /// The native iterator handle to use.
         3275  +        /// </param>
         3276  +        /// <returns>
         3277  +        /// An instance of the <see cref="ISQLiteChangeSetMetadataItem"/>
         3278  +        /// interface, which can be used to fetch metadata associated with
         3279  +        /// the current item in this set of changes.
         3280  +        /// </returns>
  3186   3281           private ISQLiteChangeSetMetadataItem CreateMetadataItem(
  3187   3282               IntPtr iterator
  3188   3283               )
  3189   3284           {
  3190   3285               return new SQLiteChangeSetMetadataItem(
  3191   3286                   SQLiteChangeSetIterator.Attach(iterator));
  3192   3287           }
  3193   3288           #endregion
  3194   3289   
  3195   3290           ///////////////////////////////////////////////////////////////////////
  3196   3291   
  3197   3292           #region Protected Methods
         3293  +        /// <summary>
         3294  +        /// Attempts to create a
         3295  +        /// <see cref="UnsafeNativeMethods.xSessionFilter" /> native delegate
         3296  +        /// that invokes the specified
         3297  +        /// <see cref="SessionTableFilterCallback" /> delegate.
         3298  +        /// </summary>
         3299  +        /// <param name="tableFilterCallback">
         3300  +        /// The <see cref="SessionTableFilterCallback" /> to invoke when the
         3301  +        /// <see cref="UnsafeNativeMethods.xSessionFilter" /> native delegate
         3302  +        /// is called.  If this value is null then null is returned.
         3303  +        /// </param>
         3304  +        /// <param name="clientData">
         3305  +        /// The optional application-defined context data.  This value may be
         3306  +        /// null.
         3307  +        /// </param>
         3308  +        /// <returns>
         3309  +        /// The created <see cref="UnsafeNativeMethods.xSessionFilter" />
         3310  +        /// native delegate -OR- null if it cannot be created.
         3311  +        /// </returns>
  3198   3312           protected UnsafeNativeMethods.xSessionFilter GetDelegate(
  3199   3313               SessionTableFilterCallback tableFilterCallback,
  3200   3314               object clientData
  3201   3315               )
  3202   3316           {
  3203   3317               if (tableFilterCallback == null)
  3204   3318                   return null;
................................................................................
  3239   3353               });
  3240   3354   
  3241   3355               return xFilter;
  3242   3356           }
  3243   3357   
  3244   3358           ///////////////////////////////////////////////////////////////////////
  3245   3359   
         3360  +        /// <summary>
         3361  +        /// Attempts to create a
         3362  +        /// <see cref="UnsafeNativeMethods.xSessionConflict" /> native delegate
         3363  +        /// that invokes the specified
         3364  +        /// <see cref="SessionConflictCallback" /> delegate.
         3365  +        /// </summary>
         3366  +        /// <param name="conflictCallback">
         3367  +        /// The <see cref="SessionConflictCallback" /> to invoke when the
         3368  +        /// <see cref="UnsafeNativeMethods.xSessionConflict" /> native delegate
         3369  +        /// is called.  If this value is null then null is returned.
         3370  +        /// </param>
         3371  +        /// <param name="clientData">
         3372  +        /// The optional application-defined context data.  This value may be
         3373  +        /// null.
         3374  +        /// </param>
         3375  +        /// <returns>
         3376  +        /// The created <see cref="UnsafeNativeMethods.xSessionConflict" />
         3377  +        /// native delegate -OR- null if it cannot be created.
         3378  +        /// </returns>
  3246   3379           protected UnsafeNativeMethods.xSessionConflict GetDelegate(
  3247   3380               SessionConflictCallback conflictCallback,
  3248   3381               object clientData
  3249   3382               )
  3250   3383           {
  3251   3384               if (conflictCallback == null)
  3252   3385                   return null;
................................................................................
  3362   3495           #endregion
  3363   3496       }
  3364   3497       #endregion
  3365   3498   
  3366   3499       ///////////////////////////////////////////////////////////////////////////
  3367   3500   
  3368   3501       #region SQLiteMemoryChangeSet Class
         3502  +    /// <summary>
         3503  +    /// This class represents a set of changes contained entirely in memory.
         3504  +    /// </summary>
  3369   3505       internal sealed class SQLiteMemoryChangeSet :
  3370   3506           SQLiteChangeSetBase, ISQLiteChangeSet
  3371   3507       {
  3372   3508           #region Private Data
         3509  +        /// <summary>
         3510  +        /// The raw byte data for this set of changes.  Since this data must
         3511  +        /// be marshalled to a native memory buffer before being used, there
         3512  +        /// must be enough memory available to store at least two times the
         3513  +        /// amount of data contained within it.
         3514  +        /// </summary>
  3373   3515           private byte[] rawData;
  3374   3516           #endregion
  3375   3517   
  3376   3518           ///////////////////////////////////////////////////////////////////////
  3377   3519   
  3378   3520           #region Private Constructors
         3521  +        /// <summary>
         3522  +        /// Constructs an instance of this class using the specified raw byte
         3523  +        /// data and wrapped native connection handle.
         3524  +        /// </summary>
         3525  +        /// <param name="rawData">
         3526  +        /// The raw byte data for the specified change set (or patch set).
         3527  +        /// </param>
         3528  +        /// <param name="handle">
         3529  +        /// The wrapped native connection handle to be associated with this
         3530  +        /// set of changes.
         3531  +        /// </param>
         3532  +        /// <param name="flags">
         3533  +        /// The flags associated with the connection represented by the
         3534  +        /// <paramref name="handle" /> value.
         3535  +        /// </param>
  3379   3536           internal SQLiteMemoryChangeSet(
  3380   3537               byte[] rawData,
  3381   3538               SQLiteConnectionHandle handle,
  3382   3539               SQLiteConnectionFlags flags
  3383   3540               )
  3384   3541               : base(handle, flags)
  3385   3542           {
................................................................................
  3386   3543               this.rawData = rawData;
  3387   3544           }
  3388   3545           #endregion
  3389   3546   
  3390   3547           ///////////////////////////////////////////////////////////////////////
  3391   3548   
  3392   3549           #region ISQLiteChangeSet Members
         3550  +        /// <summary>
         3551  +        /// This method "inverts" the set of changes within this instance.
         3552  +        /// Applying an inverted set of changes to a database reverses the
         3553  +        /// effects of applying the uninverted changes.  Specifically:
         3554  +        /// <![CDATA[<ul>]]><![CDATA[<li>]]>
         3555  +        /// Each DELETE change is changed to an INSERT, and
         3556  +        /// <![CDATA[</li>]]><![CDATA[<li>]]>
         3557  +        /// Each INSERT change is changed to a DELETE, and
         3558  +        /// <![CDATA[</li>]]><![CDATA[<li>]]>
         3559  +        /// For each UPDATE change, the old.* and new.* values are exchanged.
         3560  +        /// <![CDATA[</li>]]><![CDATA[</ul>]]>
         3561  +        /// This method does not change the order in which changes appear
         3562  +        /// within the set of changes. It merely reverses the sense of each
         3563  +        /// individual change.
         3564  +        /// </summary>
         3565  +        /// <returns>
         3566  +        /// The new <see cref="ISQLiteChangeSet" /> instance that represents
         3567  +        /// the resulting set of changes.
         3568  +        /// </returns>
  3393   3569           public ISQLiteChangeSet Invert()
  3394   3570           {
  3395   3571               CheckDisposed();
  3396   3572   
  3397   3573               SQLiteSessionHelpers.CheckRawData(rawData);
  3398   3574   
  3399   3575               IntPtr pInData = IntPtr.Zero;
................................................................................
  3432   3608                       pInData = IntPtr.Zero;
  3433   3609                   }
  3434   3610               }
  3435   3611           }
  3436   3612   
  3437   3613           ///////////////////////////////////////////////////////////////////////
  3438   3614   
         3615  +        /// <summary>
         3616  +        /// This method combines the specified set of changes with the ones
         3617  +        /// contained in this instance.
         3618  +        /// </summary>
         3619  +        /// <param name="changeSet">
         3620  +        /// The changes to be combined with those in this instance.
         3621  +        /// </param>
         3622  +        /// <returns>
         3623  +        /// The new <see cref="ISQLiteChangeSet" /> instance that represents
         3624  +        /// the resulting set of changes.
         3625  +        /// </returns>
  3439   3626           public ISQLiteChangeSet CombineWith(
  3440   3627               ISQLiteChangeSet changeSet
  3441   3628               )
  3442   3629           {
  3443   3630               CheckDisposed();
  3444   3631   
  3445   3632               SQLiteSessionHelpers.CheckRawData(rawData);
................................................................................
  3504   3691                       pInData1 = IntPtr.Zero;
  3505   3692                   }
  3506   3693               }
  3507   3694           }
  3508   3695   
  3509   3696           ///////////////////////////////////////////////////////////////////////
  3510   3697   
         3698  +        /// <summary>
         3699  +        /// Attempts to apply the set of changes in this instance to the
         3700  +        /// associated database.
         3701  +        /// </summary>
         3702  +        /// <param name="conflictCallback">
         3703  +        /// The <see cref="SessionConflictCallback" /> delegate that will need
         3704  +        /// to handle any conflicting changes that may arise.
         3705  +        /// </param>
         3706  +        /// <param name="clientData">
         3707  +        /// The optional application-defined context data.  This value may be
         3708  +        /// null.
         3709  +        /// </param>
  3511   3710           public void Apply(
  3512   3711               SessionConflictCallback conflictCallback,
  3513   3712               object clientData
  3514   3713               )
  3515   3714           {
  3516   3715               CheckDisposed();
  3517   3716   
  3518   3717               Apply(conflictCallback, null, clientData);
  3519   3718           }
  3520   3719   
  3521   3720           ///////////////////////////////////////////////////////////////////////
  3522   3721   
         3722  +        /// <summary>
         3723  +        /// Attempts to apply the set of changes in this instance to the
         3724  +        /// associated database.
         3725  +        /// </summary>
         3726  +        /// <param name="conflictCallback">
         3727  +        /// The <see cref="SessionConflictCallback" /> delegate that will need
         3728  +        /// to handle any conflicting changes that may arise.
         3729  +        /// </param>
         3730  +        /// <param name="tableFilterCallback">
         3731  +        /// The optional <see cref="SessionTableFilterCallback" /> delegate
         3732  +        /// that can be used to filter the list of tables impacted by the set
         3733  +        /// of changes.
         3734  +        /// </param>
         3735  +        /// <param name="clientData">
         3736  +        /// The optional application-defined context data.  This value may be
         3737  +        /// null.
         3738  +        /// </param>
  3523   3739           public void Apply(
  3524   3740               SessionConflictCallback conflictCallback,
  3525   3741               SessionTableFilterCallback tableFilterCallback,
  3526   3742               object clientData
  3527   3743               )
  3528   3744           {
  3529   3745               CheckDisposed();
................................................................................
  3563   3779               }
  3564   3780           }
  3565   3781           #endregion
  3566   3782   
  3567   3783           ///////////////////////////////////////////////////////////////////////
  3568   3784   
  3569   3785           #region IEnumerable<ISQLiteChangeSetMetadataItem> Members
         3786  +        /// <summary>
         3787  +        /// Creates an <see cref="IEnumerator" /> capable of iterating over the
         3788  +        /// items within this set of changes.
         3789  +        /// </summary>
         3790  +        /// <returns>
         3791  +        /// The new <see cref="IEnumerator{ISQLiteChangeSetMetadataItem}" />
         3792  +        /// instance.
         3793  +        /// </returns>
  3570   3794           public IEnumerator<ISQLiteChangeSetMetadataItem> GetEnumerator()
  3571   3795           {
  3572   3796               return new SQLiteMemoryChangeSetEnumerator(rawData);
  3573   3797           }
  3574   3798           #endregion
  3575   3799   
  3576   3800           ///////////////////////////////////////////////////////////////////////
  3577   3801   
  3578   3802           #region IEnumerable Members
         3803  +        /// <summary>
         3804  +        /// Creates an <see cref="IEnumerator" /> capable of iterating over the
         3805  +        /// items within this set of changes.
         3806  +        /// </summary>
         3807  +        /// <returns>
         3808  +        /// The new <see cref="IEnumerator" /> instance.
         3809  +        /// </returns>
  3579   3810           IEnumerator System.Collections.IEnumerable.GetEnumerator()
  3580   3811           {
  3581   3812               return GetEnumerator();
  3582   3813           }
  3583   3814           #endregion
  3584   3815   
  3585   3816           ///////////////////////////////////////////////////////////////////////
................................................................................
  3628   3859                           if (rawData != null)
  3629   3860                               rawData = null;
  3630   3861                       }
  3631   3862   
  3632   3863                       //////////////////////////////////////
  3633   3864                       // release unmanaged resources here...
  3634   3865                       //////////////////////////////////////
  3635         -
  3636         -                    Unlock();
  3637   3866                   }
  3638   3867               }
  3639   3868               finally
  3640   3869               {
  3641   3870                   base.Dispose(disposing);
  3642   3871   
  3643   3872                   //
................................................................................
  3649   3878           #endregion
  3650   3879       }
  3651   3880       #endregion
  3652   3881   
  3653   3882       ///////////////////////////////////////////////////////////////////////////
  3654   3883   
  3655   3884       #region SQLiteStreamChangeSet Class
         3885  +    /// <summary>
         3886  +    /// This class represents a set of changes that are backed by a
         3887  +    /// <see cref="Stream" /> instance.
         3888  +    /// </summary>
  3656   3889       internal sealed class SQLiteStreamChangeSet :
  3657   3890           SQLiteChangeSetBase, ISQLiteChangeSet
  3658   3891       {
  3659   3892           #region Private Data
         3893  +        /// <summary>
         3894  +        /// The <see cref="SQLiteStreamAdapter" /> instance that is managing
         3895  +        /// the underlying input <see cref="Stream" /> used as the backing
         3896  +        /// store for the set of changes associated with this instance.
         3897  +        /// </summary>
  3660   3898           private SQLiteStreamAdapter inputStreamAdapter;
         3899  +
         3900  +        /// <summary>
         3901  +        /// The <see cref="SQLiteStreamAdapter" /> instance that is managing
         3902  +        /// the underlying output <see cref="Stream" /> used as the backing
         3903  +        /// store for the set of changes generated by the <see cref="Invert" />
         3904  +        /// or <see cref="CombineWith" /> methods.
         3905  +        /// </summary>
  3661   3906           private SQLiteStreamAdapter outputStreamAdapter;
         3907  +
         3908  +        /// <summary>
         3909  +        /// The <see cref="Stream" /> instance used as the backing store for
         3910  +        /// the set of changes associated with this instance.
         3911  +        /// </summary>
  3662   3912           private Stream inputStream;
         3913  +
         3914  +        /// <summary>
         3915  +        /// The <see cref="Stream" /> instance used as the backing store for
         3916  +        /// the set of changes generated by the <see cref="Invert" /> or
         3917  +        /// <see cref="CombineWith" /> methods.
         3918  +        /// </summary>
  3663   3919           private Stream outputStream;
  3664   3920           #endregion
  3665   3921   
  3666   3922           ///////////////////////////////////////////////////////////////////////
  3667   3923   
  3668   3924           #region Private Constructors
         3925  +        /// <summary>
         3926  +        /// Constructs an instance of this class using the specified streams
         3927  +        /// and wrapped native connection handle.
         3928  +        /// </summary>
         3929  +        /// <param name="inputStream">
         3930  +        /// The <see cref="Stream" /> where the raw byte data for the set of
         3931  +        /// changes may be read.
         3932  +        /// </param>
         3933  +        /// <param name="outputStream">
         3934  +        /// The <see cref="Stream" /> where the raw byte data for resulting
         3935  +        /// sets of changes may be written.
         3936  +        /// </param>
         3937  +        /// <param name="handle">
         3938  +        /// The wrapped native connection handle to be associated with this
         3939  +        /// set of changes.
         3940  +        /// </param>
         3941  +        /// <param name="flags">
         3942  +        /// The flags associated with the connection represented by the
         3943  +        /// <paramref name="handle" /> value.
         3944  +        /// </param>
  3669   3945           internal SQLiteStreamChangeSet(
  3670   3946               Stream inputStream,
  3671   3947               Stream outputStream,
  3672   3948               SQLiteConnectionHandle handle,
  3673   3949               SQLiteConnectionFlags flags
  3674   3950               )
  3675   3951               : base(handle, flags)
................................................................................
  3678   3954               this.outputStream = outputStream;
  3679   3955           }
  3680   3956           #endregion
  3681   3957   
  3682   3958           ///////////////////////////////////////////////////////////////////////
  3683   3959   
  3684   3960           #region Private Methods
         3961  +        /// <summary>
         3962  +        /// Throws an exception if the input stream or its associated stream
         3963  +        /// adapter are invalid.
         3964  +        /// </summary>
  3685   3965           private void CheckInputStream()
  3686   3966           {
  3687   3967               if (inputStream == null)
  3688   3968               {
  3689   3969                   throw new InvalidOperationException(
  3690   3970                       "input stream unavailable");
  3691   3971               }
................................................................................
  3695   3975                   inputStreamAdapter = new SQLiteStreamAdapter(
  3696   3976                       inputStream, GetFlags());
  3697   3977               }
  3698   3978           }
  3699   3979   
  3700   3980           ///////////////////////////////////////////////////////////////////////
  3701   3981   
         3982  +        /// <summary>
         3983  +        /// Throws an exception if the output stream or its associated stream
         3984  +        /// adapter are invalid.
         3985  +        /// </summary>
  3702   3986           private void CheckOutputStream()
  3703   3987           {
  3704   3988               if (outputStream == null)
  3705   3989               {
  3706   3990                   throw new InvalidOperationException(
  3707   3991                       "output stream unavailable");
  3708   3992               }
................................................................................
  3714   3998               }
  3715   3999           }
  3716   4000           #endregion
  3717   4001   
  3718   4002           ///////////////////////////////////////////////////////////////////////
  3719   4003   
  3720   4004           #region ISQLiteChangeSet Members
         4005  +        /// <summary>
         4006  +        /// This method "inverts" the set of changes within this instance.
         4007  +        /// Applying an inverted set of changes to a database reverses the
         4008  +        /// effects of applying the uninverted changes.  Specifically:
         4009  +        /// <![CDATA[<ul>]]><![CDATA[<li>]]>
         4010  +        /// Each DELETE change is changed to an INSERT, and
         4011  +        /// <![CDATA[</li>]]><![CDATA[<li>]]>
         4012  +        /// Each INSERT change is changed to a DELETE, and
         4013  +        /// <![CDATA[</li>]]><![CDATA[<li>]]>
         4014  +        /// For each UPDATE change, the old.* and new.* values are exchanged.
         4015  +        /// <![CDATA[</li>]]><![CDATA[</ul>]]>
         4016  +        /// This method does not change the order in which changes appear
         4017  +        /// within the set of changes. It merely reverses the sense of each
         4018  +        /// individual change.
         4019  +        /// </summary>
         4020  +        /// <returns>
         4021  +        /// Since the resulting set of changes is written to the output stream,
         4022  +        /// this method always returns null.
         4023  +        /// </returns>
  3721   4024           public ISQLiteChangeSet Invert()
  3722   4025           {
  3723   4026               CheckDisposed();
  3724   4027               CheckInputStream();
  3725   4028               CheckOutputStream();
  3726   4029   
  3727   4030               SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3changeset_invert_strm(
................................................................................
  3732   4035                   throw new SQLiteException(rc, "sqlite3changeset_invert_strm");
  3733   4036   
  3734   4037               return null;
  3735   4038           }
  3736   4039   
  3737   4040           ///////////////////////////////////////////////////////////////////////
  3738   4041   
         4042  +        /// <summary>
         4043  +        /// This method combines the specified set of changes with the ones
         4044  +        /// contained in this instance.
         4045  +        /// </summary>
         4046  +        /// <param name="changeSet">
         4047  +        /// The changes to be combined with those in this instance.
         4048  +        /// </param>
         4049  +        /// <returns>
         4050  +        /// Since the resulting set of changes is written to the output stream,
         4051  +        /// this method always returns null.
         4052  +        /// </returns>
  3739   4053           public ISQLiteChangeSet CombineWith(
  3740   4054               ISQLiteChangeSet changeSet
  3741   4055               )
  3742   4056           {
  3743   4057               CheckDisposed();
  3744   4058               CheckInputStream();
  3745   4059               CheckOutputStream();
................................................................................
  3765   4079                   throw new SQLiteException(rc, "sqlite3changeset_concat_strm");
  3766   4080   
  3767   4081               return null;
  3768   4082           }
  3769   4083   
  3770   4084           ///////////////////////////////////////////////////////////////////////
  3771   4085   
         4086  +        /// <summary>
         4087  +        /// Attempts to apply the set of changes in this instance to the
         4088  +        /// associated database.
         4089  +        /// </summary>
         4090  +        /// <param name="conflictCallback">
         4091  +        /// The <see cref="SessionConflictCallback" /> delegate that will need
         4092  +        /// to handle any conflicting changes that may arise.
         4093  +        /// </param>
         4094  +        /// <param name="clientData">
         4095  +        /// The optional application-defined context data.  This value may be
         4096  +        /// null.
         4097  +        /// </param>
  3772   4098           public void Apply(
  3773   4099               SessionConflictCallback conflictCallback,
  3774   4100               object clientData
  3775   4101               )
  3776   4102           {
  3777   4103               CheckDisposed();
  3778   4104   
  3779   4105               Apply(conflictCallback, null, clientData);
  3780   4106           }
  3781   4107   
  3782   4108           ///////////////////////////////////////////////////////////////////////
  3783   4109   
         4110  +        /// <summary>
         4111  +        /// Attempts to apply the set of changes in this instance to the
         4112  +        /// associated database.
         4113  +        /// </summary>
         4114  +        /// <param name="conflictCallback">
         4115  +        /// The <see cref="SessionConflictCallback" /> delegate that will need
         4116  +        /// to handle any conflicting changes that may arise.
         4117  +        /// </param>
         4118  +        /// <param name="tableFilterCallback">
         4119  +        /// The optional <see cref="SessionTableFilterCallback" /> delegate
         4120  +        /// that can be used to filter the list of tables impacted by the set
         4121  +        /// of changes.
         4122  +        /// </param>
         4123  +        /// <param name="clientData">
         4124  +        /// The optional application-defined context data.  This value may be
         4125  +        /// null.
         4126  +        /// </param>
  3784   4127           public void Apply(
  3785   4128               SessionConflictCallback conflictCallback,
  3786   4129               SessionTableFilterCallback tableFilterCallback,
  3787   4130               object clientData
  3788   4131               )
  3789   4132           {
  3790   4133               CheckDisposed();
................................................................................
  3807   4150                   throw new SQLiteException(rc, "sqlite3changeset_apply_strm");
  3808   4151           }
  3809   4152           #endregion
  3810   4153   
  3811   4154           ///////////////////////////////////////////////////////////////////////
  3812   4155   
  3813   4156           #region IEnumerable<ISQLiteChangeSetMetadataItem> Members
         4157  +        /// <summary>
         4158  +        /// Creates an <see cref="IEnumerator" /> capable of iterating over the
         4159  +        /// items within this set of changes.
         4160  +        /// </summary>
         4161  +        /// <returns>
         4162  +        /// The new <see cref="IEnumerator{ISQLiteChangeSetMetadataItem}" />
         4163  +        /// instance.
         4164  +        /// </returns>
  3814   4165           public IEnumerator<ISQLiteChangeSetMetadataItem> GetEnumerator()
  3815   4166           {
  3816   4167               return new SQLiteStreamChangeSetEnumerator(
  3817   4168                   inputStream, GetFlags());
  3818   4169           }
  3819   4170           #endregion
  3820   4171   
  3821   4172           ///////////////////////////////////////////////////////////////////////
  3822   4173   
  3823   4174           #region IEnumerable Members
         4175  +        /// <summary>
         4176  +        /// Creates an <see cref="IEnumerator" /> capable of iterating over the
         4177  +        /// items within this set of changes.
         4178  +        /// </summary>
         4179  +        /// <returns>
         4180  +        /// The new <see cref="IEnumerator" /> instance.
         4181  +        /// </returns>
  3824   4182           IEnumerator System.Collections.IEnumerable.GetEnumerator()
  3825   4183           {
  3826   4184               return GetEnumerator();
  3827   4185           }
  3828   4186           #endregion
  3829   4187   
  3830   4188           ///////////////////////////////////////////////////////////////////////
................................................................................
  3865   4223                   if (!disposed)
  3866   4224                   {
  3867   4225                       if (disposing)
  3868   4226                       {
  3869   4227                           ////////////////////////////////////
  3870   4228                           // dispose managed resources here...
  3871   4229                           ////////////////////////////////////
         4230  +
         4231  +                        if (outputStreamAdapter != null)
         4232  +                        {
         4233  +                            outputStreamAdapter.Dispose();
         4234  +                            outputStreamAdapter = null;
         4235  +                        }
         4236  +
         4237  +                        if (inputStreamAdapter != null)
         4238  +                        {
         4239  +                            inputStreamAdapter.Dispose();
         4240  +                            inputStreamAdapter = null;
         4241  +                        }
  3872   4242   
  3873   4243                           if (outputStream != null)
  3874   4244                               outputStream = null; /* NOT OWNED */
  3875   4245   
  3876   4246                           if (inputStream != null)
  3877   4247                               inputStream = null; /* NOT OWNED */
  3878   4248                       }
  3879   4249   
  3880   4250                       //////////////////////////////////////
  3881   4251                       // release unmanaged resources here...
  3882   4252                       //////////////////////////////////////
  3883         -
  3884         -                    Unlock();
  3885   4253                   }
  3886   4254               }
  3887   4255               finally
  3888   4256               {
  3889   4257                   base.Dispose(disposing);
  3890   4258   
  3891   4259                   //
................................................................................
  3897   4265           #endregion
  3898   4266       }
  3899   4267       #endregion
  3900   4268   
  3901   4269       ///////////////////////////////////////////////////////////////////////////
  3902   4270   
  3903   4271       #region SQLiteChangeSetEnumerator Class
         4272  +    /// <summary>
         4273  +    /// This class represents an <see cref="IEnumerator" /> that is capable of
         4274  +    /// enumerating over a set of changes.  It serves as the base class for the
         4275  +    /// <see cref="SQLiteMemoryChangeSetEnumerator" /> and
         4276  +    /// <see cref="SQLiteStreamChangeSetEnumerator" /> classes.  It manages and
         4277  +    /// owns an instance of the <see cref="SQLiteChangeSetIterator" /> class.
         4278  +    /// </summary>
  3904   4279       internal abstract class SQLiteChangeSetEnumerator :
  3905   4280           IEnumerator<ISQLiteChangeSetMetadataItem>
  3906   4281       {
  3907   4282           #region Private Data
         4283  +        /// <summary>
         4284  +        /// This managed change set iterator is managed and owned by this
         4285  +        /// class.  It will be disposed when this class is disposed.
         4286  +        /// </summary>
  3908   4287           private SQLiteChangeSetIterator iterator;
  3909   4288           #endregion
  3910   4289   
  3911   4290           ///////////////////////////////////////////////////////////////////////
  3912   4291   
  3913   4292           #region Public Constructors
         4293  +        /// <summary>
         4294  +        /// Constructs an instance of this class using the specified managed
         4295  +        /// change set iterator.
         4296  +        /// </summary>
         4297  +        /// <param name="iterator">
         4298  +        /// The managed iterator instance to use.
         4299  +        /// </param>
  3914   4300           public SQLiteChangeSetEnumerator(
  3915   4301               SQLiteChangeSetIterator iterator
  3916   4302               )
  3917   4303           {
  3918   4304               SetIterator(iterator);
  3919   4305           }
  3920   4306           #endregion
  3921   4307   
  3922   4308           ///////////////////////////////////////////////////////////////////////
  3923   4309   
  3924   4310           #region Private Methods
         4311  +        /// <summary>
         4312  +        /// Throws an exception if the managed iterator instance is invalid.
         4313  +        /// </summary>
  3925   4314           private void CheckIterator()
  3926   4315           {
  3927   4316               if (iterator == null)
  3928   4317                   throw new InvalidOperationException("iterator unavailable");
  3929   4318   
  3930   4319               iterator.CheckHandle();
  3931   4320           }
  3932   4321   
  3933   4322           ///////////////////////////////////////////////////////////////////////
  3934   4323   
         4324  +        /// <summary>
         4325  +        /// Sets the managed iterator instance to a new value.
         4326  +        /// </summary>
         4327  +        /// <param name="iterator">
         4328  +        /// The new managed iterator instance to use.
         4329  +        /// </param>
  3935   4330           private void SetIterator(
  3936   4331               SQLiteChangeSetIterator iterator
  3937   4332               )
  3938   4333           {
  3939   4334               this.iterator = iterator;
  3940   4335           }
  3941   4336   
  3942   4337           ///////////////////////////////////////////////////////////////////////
  3943   4338   
         4339  +        /// <summary>
         4340  +        /// Disposes of the managed iterator instance and sets its value to
         4341  +        /// null.
         4342  +        /// </summary>
  3944   4343           private void CloseIterator()
  3945   4344           {
  3946   4345               if (iterator != null)
  3947   4346               {
  3948   4347                   iterator.Dispose();
  3949   4348                   iterator = null;
  3950   4349               }
  3951   4350           }
  3952   4351           #endregion
  3953   4352   
  3954   4353           ///////////////////////////////////////////////////////////////////////
  3955   4354   
  3956   4355           #region Protected Methods
         4356  +        /// <summary>
         4357  +        /// Disposes of the existing managed iterator instance and then sets it
         4358  +        /// to a new value.
         4359  +        /// </summary>
         4360  +        /// <param name="iterator">
         4361  +        /// The new managed iterator instance to use.
         4362  +        /// </param>
  3957   4363           protected void ResetIterator(
  3958   4364               SQLiteChangeSetIterator iterator
  3959   4365               )
  3960   4366           {
  3961   4367               CloseIterator();
  3962   4368               SetIterator(iterator);
  3963   4369           }
  3964   4370           #endregion
  3965   4371   
  3966   4372           ///////////////////////////////////////////////////////////////////////
  3967   4373   
  3968   4374           #region IEnumerator<ISQLiteChangeSetMetadataItem> Members
         4375  +        /// <summary>
         4376  +        /// Returns the current change within the set of changes, represented
         4377  +        /// by a <see cref="ISQLiteChangeSetMetadataItem" /> instance.
         4378  +        /// </summary>
  3969   4379           public ISQLiteChangeSetMetadataItem Current
  3970   4380           {
  3971   4381               get
  3972   4382               {
  3973   4383                   CheckDisposed();
  3974   4384   
  3975   4385                   return new SQLiteChangeSetMetadataItem(iterator);
................................................................................
  3976   4386               }
  3977   4387           }
  3978   4388           #endregion
  3979   4389   
  3980   4390           ///////////////////////////////////////////////////////////////////////
  3981   4391   
  3982   4392           #region IEnumerator Members
         4393  +        /// <summary>
         4394  +        /// Returns the current change within the set of changes, represented
         4395  +        /// by a <see cref="ISQLiteChangeSetMetadataItem" /> instance.
         4396  +        /// </summary>
  3983   4397           object Collections.IEnumerator.Current
  3984   4398           {
  3985   4399               get
  3986   4400               {
  3987   4401                   CheckDisposed();
  3988   4402   
  3989   4403                   return Current;
  3990   4404               }
  3991   4405           }
  3992   4406   
  3993   4407           ///////////////////////////////////////////////////////////////////////
  3994   4408   
         4409  +        /// <summary>
         4410  +        /// Attempts to advance to the next item in the set of changes.
         4411  +        /// </summary>
         4412  +        /// <returns>
         4413  +        /// Non-zero if more items are available; otherwise, zero.
         4414  +        /// </returns>
  3995   4415           public bool MoveNext()
  3996   4416           {
  3997   4417               CheckDisposed();
  3998   4418               CheckIterator();
  3999   4419   
  4000   4420               return iterator.Next();
  4001   4421           }
  4002   4422   
  4003   4423           ///////////////////////////////////////////////////////////////////////
  4004   4424   
         4425  +        /// <summary>
         4426  +        /// Throws <see cref="NotImplementedException" /> because not all the
         4427  +        /// derived classes are able to support reset functionality.
         4428  +        /// </summary>
  4005   4429           public virtual void Reset()
  4006   4430           {
  4007   4431               CheckDisposed();
  4008   4432   
  4009   4433               throw new NotImplementedException();
  4010   4434           }
  4011   4435           #endregion
................................................................................
  4097   4521           #endregion
  4098   4522       }
  4099   4523       #endregion
  4100   4524   
  4101   4525       ///////////////////////////////////////////////////////////////////////////
  4102   4526   
  4103   4527       #region SQLiteMemoryChangeSetEnumerator Class
         4528  +    /// <summary>
         4529  +    /// This class represents an <see cref="IEnumerator" /> that is capable of
         4530  +    /// enumerating over a set of changes contained entirely in memory.
         4531  +    /// </summary>
  4104   4532       internal sealed class SQLiteMemoryChangeSetEnumerator :
  4105   4533           SQLiteChangeSetEnumerator
  4106   4534       {
  4107   4535           #region Private Data
         4536  +        /// <summary>
         4537  +        /// The raw byte data for this set of changes.  Since this data must
         4538  +        /// be marshalled to a native memory buffer before being used, there
         4539  +        /// must be enough memory available to store at least two times the
         4540  +        /// amount of data contained within it.
         4541  +        /// </summary>
  4108   4542           private byte[] rawData;
  4109   4543           #endregion
  4110   4544   
  4111   4545           ///////////////////////////////////////////////////////////////////////
  4112   4546   
  4113   4547           #region Public Constructors
         4548  +        /// <summary>
         4549  +        /// Constructs an instance of this class using the specified raw byte
         4550  +        /// data.
         4551  +        /// </summary>
         4552  +        /// <param name="rawData">
         4553  +        /// The raw byte data containing the set of changes for this
         4554  +        /// enumerator.
         4555  +        /// </param>
  4114   4556           public SQLiteMemoryChangeSetEnumerator(
  4115   4557               byte[] rawData
  4116   4558               )
  4117   4559               : base(SQLiteMemoryChangeSetIterator.Create(rawData))
  4118   4560           {
  4119   4561               this.rawData = rawData;
  4120   4562           }
  4121   4563           #endregion
  4122   4564   
  4123   4565           ///////////////////////////////////////////////////////////////////////
  4124   4566   
  4125   4567           #region IEnumerator Overrides
         4568  +        /// <summary>
         4569  +        /// Resets the enumerator to its initial position.
         4570  +        /// </summary>
  4126   4571           public override void Reset()
  4127   4572           {
  4128   4573               CheckDisposed();
  4129   4574   
  4130   4575               ResetIterator(SQLiteMemoryChangeSetIterator.Create(rawData));
  4131   4576           }
  4132   4577           #endregion
................................................................................
  4193   4638           #endregion
  4194   4639       }
  4195   4640       #endregion
  4196   4641   
  4197   4642       ///////////////////////////////////////////////////////////////////////////
  4198   4643   
  4199   4644       #region SQLiteStreamChangeSetEnumerator Class
         4645  +    /// <summary>
         4646  +    /// This class represents an <see cref="IEnumerator" /> that is capable of
         4647  +    /// enumerating over a set of changes backed by a <see cref="Stream" />
         4648  +    /// instance.
         4649  +    /// </summary>
  4200   4650       internal sealed class SQLiteStreamChangeSetEnumerator :
  4201   4651           SQLiteChangeSetEnumerator
  4202   4652       {
  4203   4653           #region Public Constructors
         4654  +        /// <summary>
         4655  +        /// Constructs an instance of this class using the specified stream.
         4656  +        /// </summary>
         4657  +        /// <param name="stream">
         4658  +        /// The <see cref="Stream" /> where the raw byte data for the set of
         4659  +        /// changes may be read.
         4660  +        /// </param>
         4661  +        /// <param name="flags">
         4662  +        /// The flags associated with the parent connection.
         4663  +        /// </param>
  4204   4664           public SQLiteStreamChangeSetEnumerator(
  4205   4665               Stream stream,
  4206   4666               SQLiteConnectionFlags flags
  4207   4667               )
  4208   4668               : base(SQLiteStreamChangeSetIterator.Create(stream, flags))
  4209   4669           {
  4210   4670               // do nothing.
................................................................................
  4297   4757   
  4298   4758           #region Public Constructors
  4299   4759           /// <summary>
  4300   4760           /// Constructs an instance of this class using the specified iterator
  4301   4761           /// instance.
  4302   4762           /// </summary>
  4303   4763           /// <param name="iterator">
  4304         -        /// The native iterator handle to use.
         4764  +        /// The managed iterator instance to use.
  4305   4765           /// </param>
  4306   4766           public SQLiteChangeSetMetadataItem(
  4307   4767               SQLiteChangeSetIterator iterator
  4308   4768               )
  4309   4769           {
  4310   4770               this.iterator = iterator;
  4311   4771           }