System.Data.SQLite
Check-in [7da399e402]
Not logged in

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

Overview
Comment:Add generic variants of the SQLiteModuleEnumerable and SQLiteVirtualTableCursorEnumerator classes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7da399e4025afc2d9b85a1efbd9180b8850de8c1
User & Date: mistachkin 2013-06-26 04:23:21
Context
2013-06-26
04:27
Minor addition to doc comments. check-in: 7d123e6752 user: mistachkin tags: trunk
04:23
Add generic variants of the SQLiteModuleEnumerable and SQLiteVirtualTableCursorEnumerator classes. check-in: 7da399e402 user: mistachkin tags: trunk
03:18
Rename the SQLiteVirtualTableCursorEnumerable class to SQLiteVirtualTableCursorEnumerator. check-in: 4e38ea39a3 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

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

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    /// The format string to be used when parsing and formatting DateTime
    /// values.
    /// </param>
    /// <param name="db">
    /// The native handle to be associated with the database connection.
    /// </param>
    /// <param name="fileName">
    /// The fully qualified file name associated with <paramref name="db "/>.
    /// </param>
    /// <param name="ownHandle">
    /// Non-zero if the newly created object instance will need to dispose
    /// of <paramref name="db" /> when it is no longer needed.
    /// </param>
    internal SQLite3_UTF16(
        SQLiteDateFormats fmt,







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    /// The format string to be used when parsing and formatting DateTime
    /// values.
    /// </param>
    /// <param name="db">
    /// The native handle to be associated with the database connection.
    /// </param>
    /// <param name="fileName">
    /// The fully qualified file name associated with <paramref name="db" />.
    /// </param>
    /// <param name="ownHandle">
    /// Non-zero if the newly created object instance will need to dispose
    /// of <paramref name="db" /> when it is no longer needed.
    /// </param>
    internal SQLite3_UTF16(
        SQLiteDateFormats fmt,

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

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
....
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
    public static long ToUnixEpoch(DateTime value)
    {
        return (value.Subtract(UnixEpoch).Ticks / TimeSpan.TicksPerSecond);
    }

    /// <summary>
    /// Returns the DateTime format string to use for the specified DateTimeKind.
    /// If <paramref name="formatString"/> is not null, it will be returned verbatim.
    /// </summary>
    /// <param name="kind">The DateTimeKind to use.</param>
    /// <param name="formatString">The DateTime format string to use.</param>
    /// <returns>
    /// The DateTime format string to use for the specified DateTimeKind.
    /// </returns>
    private static string GetDateTimeKindFormat(
................................................................................
      /// The command is expected to return a scalar result -OR- the result should
      /// be limited to a scalar result.  The <see cref="SQLiteCommand.ExecuteScalar" />
      /// method will be called.
      /// </summary>
      Scalar = 2,

      /// <summary>
      /// The command is expected to return <see cref="SQLiteDataReader"/> result.
      /// The <see cref="SQLiteCommand.ExecuteReader()" /> method will be called.
      /// </summary>
      Reader = 3,

      /// <summary>
      /// Use the default command execution type.  Using this value is the same
      /// as using the <see cref="SQLiteExecuteType.NonQuery" /> value.







|







 







|







422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
....
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
    public static long ToUnixEpoch(DateTime value)
    {
        return (value.Subtract(UnixEpoch).Ticks / TimeSpan.TicksPerSecond);
    }

    /// <summary>
    /// Returns the DateTime format string to use for the specified DateTimeKind.
    /// If <paramref name="formatString" /> is not null, it will be returned verbatim.
    /// </summary>
    /// <param name="kind">The DateTimeKind to use.</param>
    /// <param name="formatString">The DateTime format string to use.</param>
    /// <returns>
    /// The DateTime format string to use for the specified DateTimeKind.
    /// </returns>
    private static string GetDateTimeKindFormat(
................................................................................
      /// The command is expected to return a scalar result -OR- the result should
      /// be limited to a scalar result.  The <see cref="SQLiteCommand.ExecuteScalar" />
      /// method will be called.
      /// </summary>
      Scalar = 2,

      /// <summary>
      /// The command is expected to return <see cref="SQLiteDataReader" /> result.
      /// The <see cref="SQLiteCommand.ExecuteReader()" /> method will be called.
      /// </summary>
      Reader = 3,

      /// <summary>
      /// Use the default command execution type.  Using this value is the same
      /// as using the <see cref="SQLiteExecuteType.NonQuery" /> value.

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

357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
....
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
....
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
....
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
....
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
....
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
....
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
....
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
....
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
....
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
....
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
        }

        ///////////////////////////////////////////////////////////////////////

        private object value;
        /// <summary>
        /// If the managed value for this object instance is available (i.e. it
        /// has been previously persisted via the <see cref="Persist"/>) method,
        /// that value is returned; otherwise, an exception is thrown.  The
        /// returned value may be null.
        /// </summary>
        public object Value
        {
            get
            {
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException"/> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException"/> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
................................................................................
            /// Sets the table error message to one that indicates the native
            /// module implementation is not available.
            /// </summary>
            /// <param name="pVtab">
            /// The native pointer to the sqlite3_vtab derived structure.
            /// </param>
            /// <returns>
            /// The value of <see cref="SQLiteErrorCode.Error"/>.
            /// </returns>
            private static SQLiteErrorCode ModuleNotAvailableTableError(
                IntPtr pVtab
                )
            {
                SetTableError(null, pVtab, DefaultLogErrors,
                    ModuleNotAvailableErrorMessage);
................................................................................
            /// module implementation is not available.
            /// </summary>
            /// <param name="pCursor">
            /// The native pointer to the sqlite3_vtab_cursor derived
            /// structure.
            /// </param>
            /// <returns>
            /// The value of <see cref="SQLiteErrorCode.Error"/>.
            /// </returns>
            private static SQLiteErrorCode ModuleNotAvailableCursorError(
                IntPtr pCursor
                )
            {
                SetCursorError(null, pCursor, DefaultLogErrors,
                    ModuleNotAvailableErrorMessage);
................................................................................
            #endregion

            ///////////////////////////////////////////////////////////////////

            #region IDisposable "Pattern" Members
            private bool disposed;
            /// <summary>
            /// Throws an <see cref="ObjectDisposedException"/> if this object
            /// instance has been disposed.
            /// </summary>
            private void CheckDisposed() /* throw */
            {
#if THROW_ON_DISPOSED
                if (disposed)
                {
................................................................................
        /// <param name="pCursor">
        /// The native pointer to the sqlite3_vtab_cursor derived structure
        /// from which to read the native pointer to the sqlite3_vtab derived
        /// structure.
        /// </param>
        /// <returns>
        /// The native pointer to the sqlite3_vtab derived structure -OR-
        /// <see cref="IntPtr.Zero"/> if it cannot be determined.
        /// </returns>
        private static IntPtr TableFromCursor(
            SQLiteModule module,
            IntPtr pCursor
            )
        {
            if (pCursor == IntPtr.Zero)
................................................................................
        /// <param name="pCursor">
        /// The native pointer to the sqlite3_vtab_cursor derived structure
        /// from which to read the native pointer to the sqlite3_vtab derived
        /// structure.
        /// </param>
        /// <returns>
        /// The native pointer to the sqlite3_vtab derived structure -OR-
        /// <see cref="IntPtr.Zero"/> if it cannot be determined.
        /// </returns>
        protected virtual IntPtr TableFromCursor(
            IntPtr pCursor
            )
        {
            return TableFromCursor(this, pCursor);
        }
................................................................................
        /// </summary>
        /// <param name="table">
        /// The <see cref="SQLiteVirtualTable" /> object instance to be used
        /// when creating the association.
        /// </param>
        /// <returns>
        /// The native pointer to a sqlite3_vtab derived structure or
        /// <see cref="IntPtr.Zero"/> if the method fails for any reason.
        /// </returns>
        protected virtual IntPtr TableToIntPtr(
            SQLiteVirtualTable table
            )
        {
            if ((table == null) || (tables == null))
                return IntPtr.Zero;
................................................................................
        /// </summary>
        /// <param name="cursor">
        /// The <see cref="SQLiteVirtualTableCursor" /> object instance to be
        /// used when creating the association.
        /// </param>
        /// <returns>
        /// The native pointer to a sqlite3_vtab_cursor derived structure or
        /// <see cref="IntPtr.Zero"/> if the method fails for any reason.
        /// </returns>
        protected virtual IntPtr CursorToIntPtr(
            SQLiteVirtualTableCursor cursor
            )
        {
            if ((cursor == null) || (cursors == null))
                return IntPtr.Zero;
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException"/> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
....
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
....
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
....
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
....
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
....
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
....
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
....
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
....
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
....
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
....
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
        }

        ///////////////////////////////////////////////////////////////////////

        private object value;
        /// <summary>
        /// If the managed value for this object instance is available (i.e. it
        /// has been previously persisted via the <see cref="Persist" />) method,
        /// that value is returned; otherwise, an exception is thrown.  The
        /// returned value may be null.
        /// </summary>
        public object Value
        {
            get
            {
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException" /> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException" /> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
................................................................................
            /// Sets the table error message to one that indicates the native
            /// module implementation is not available.
            /// </summary>
            /// <param name="pVtab">
            /// The native pointer to the sqlite3_vtab derived structure.
            /// </param>
            /// <returns>
            /// The value of <see cref="SQLiteErrorCode.Error" />.
            /// </returns>
            private static SQLiteErrorCode ModuleNotAvailableTableError(
                IntPtr pVtab
                )
            {
                SetTableError(null, pVtab, DefaultLogErrors,
                    ModuleNotAvailableErrorMessage);
................................................................................
            /// module implementation is not available.
            /// </summary>
            /// <param name="pCursor">
            /// The native pointer to the sqlite3_vtab_cursor derived
            /// structure.
            /// </param>
            /// <returns>
            /// The value of <see cref="SQLiteErrorCode.Error" />.
            /// </returns>
            private static SQLiteErrorCode ModuleNotAvailableCursorError(
                IntPtr pCursor
                )
            {
                SetCursorError(null, pCursor, DefaultLogErrors,
                    ModuleNotAvailableErrorMessage);
................................................................................
            #endregion

            ///////////////////////////////////////////////////////////////////

            #region IDisposable "Pattern" Members
            private bool disposed;
            /// <summary>
            /// Throws an <see cref="ObjectDisposedException" /> if this object
            /// instance has been disposed.
            /// </summary>
            private void CheckDisposed() /* throw */
            {
#if THROW_ON_DISPOSED
                if (disposed)
                {
................................................................................
        /// <param name="pCursor">
        /// The native pointer to the sqlite3_vtab_cursor derived structure
        /// from which to read the native pointer to the sqlite3_vtab derived
        /// structure.
        /// </param>
        /// <returns>
        /// The native pointer to the sqlite3_vtab derived structure -OR-
        /// <see cref="IntPtr.Zero" /> if it cannot be determined.
        /// </returns>
        private static IntPtr TableFromCursor(
            SQLiteModule module,
            IntPtr pCursor
            )
        {
            if (pCursor == IntPtr.Zero)
................................................................................
        /// <param name="pCursor">
        /// The native pointer to the sqlite3_vtab_cursor derived structure
        /// from which to read the native pointer to the sqlite3_vtab derived
        /// structure.
        /// </param>
        /// <returns>
        /// The native pointer to the sqlite3_vtab derived structure -OR-
        /// <see cref="IntPtr.Zero" /> if it cannot be determined.
        /// </returns>
        protected virtual IntPtr TableFromCursor(
            IntPtr pCursor
            )
        {
            return TableFromCursor(this, pCursor);
        }
................................................................................
        /// </summary>
        /// <param name="table">
        /// The <see cref="SQLiteVirtualTable" /> object instance to be used
        /// when creating the association.
        /// </param>
        /// <returns>
        /// The native pointer to a sqlite3_vtab derived structure or
        /// <see cref="IntPtr.Zero" /> if the method fails for any reason.
        /// </returns>
        protected virtual IntPtr TableToIntPtr(
            SQLiteVirtualTable table
            )
        {
            if ((table == null) || (tables == null))
                return IntPtr.Zero;
................................................................................
        /// </summary>
        /// <param name="cursor">
        /// The <see cref="SQLiteVirtualTableCursor" /> object instance to be
        /// used when creating the association.
        /// </param>
        /// <returns>
        /// The native pointer to a sqlite3_vtab_cursor derived structure or
        /// <see cref="IntPtr.Zero" /> if the method fails for any reason.
        /// </returns>
        protected virtual IntPtr CursorToIntPtr(
            SQLiteVirtualTableCursor cursor
            )
        {
            if ((cursor == null) || (cursors == null))
                return IntPtr.Zero;
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException" /> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {

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

2
3
4
5
6
7
8

9
10

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
321
322
323
324
325
326
327



328
329
330
331
332
333
334
...
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825

































































































































































































































































































































826
827
828
829
830
831
832
...
862
863
864
865
866
867
868

 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Joe Mistachkin (joe@mistachkin.com)
 *
 * Released to the public domain, use at your own risk!
 ********************************************************/

using System.Collections;

using System.Globalization;


namespace System.Data.SQLite
{
    #region SQLiteVirtualTableCursorEnumerator Class
    /// <summary>
    /// This class represents a virtual table cursor to be used with the
    /// <see cref="SQLiteModuleEnumerable" /> class.  It is not sealed and may
    /// be used as the base class for any user-defined virtual table cursor
    /// class that wraps an <see cref="IEnumerator" /> object instance.
    /// </summary>
    public class SQLiteVirtualTableCursorEnumerator :
            SQLiteVirtualTableCursor /* NOT SEALED */
    {
        #region Private Data
        /// <summary>
        /// The <see cref="IEnumerator" /> instance provided when this cursor
        /// was created.
        /// </summary>
        private IEnumerator enumerator;

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// This value will be non-zero if false has been returned from the
        /// <see cref="IEnumerator.MoveNext"/> method.
        /// </summary>
        private bool endOfEnumerator;
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Public Constructors
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException"/> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
................................................................................
        /// Sets the table error message to one that indicates the virtual
        /// table cursor is of the wrong type.
        /// </summary>
        /// <param name="cursor">
        /// The <see cref="SQLiteVirtualTableCursor" /> object instance.
        /// </param>
        /// <returns>
        /// The value of <see cref="SQLiteErrorCode.Error"/>.
        /// </returns>
        protected virtual SQLiteErrorCode CursorTypeMismatchError(
            SQLiteVirtualTableCursor cursor
            )
        {
            SetCursorError(cursor, "not an \"enumerator\" cursor");
            return SQLiteErrorCode.Error;
................................................................................
        /// Sets the table error message to one that indicates the virtual
        /// table cursor has no current row.
        /// </summary>
        /// <param name="cursor">
        /// The <see cref="SQLiteVirtualTableCursor" /> object instance.
        /// </param>
        /// <returns>
        /// The value of <see cref="SQLiteErrorCode.Error"/>.
        /// </returns>
        protected virtual SQLiteErrorCode CursorEndOfEnumeratorError(
            SQLiteVirtualTableCursor cursor
            )
        {
            SetCursorError(cursor, "already hit end of enumerator");
            return SQLiteErrorCode.Error; 
................................................................................
        protected virtual string GetStringFromObject(
            object value
            )
        {
            if (value == null)
                return null;




            return value.ToString();
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Determines the unique row identifier for the object instance value.
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException"/> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
                throw new ObjectDisposedException(
                    typeof(SQLiteModuleNoop).Name);

































































































































































































































































































































            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
................................................................................
                base.Dispose(disposing);
            }
        }
        #endregion
    }
    #endregion
}








>


>










|












|







 







|







 







|







 







|







 







>
>
>







 







|








|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
...
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
...
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
....
1188
1189
1190
1191
1192
1193
1194
1195
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Joe Mistachkin (joe@mistachkin.com)
 *
 * Released to the public domain, use at your own risk!
 ********************************************************/

using System.Collections;
using System.Collections.Generic;
using System.Globalization;

#region Non-Generic Classes
namespace System.Data.SQLite
{
    #region SQLiteVirtualTableCursorEnumerator Class
    /// <summary>
    /// This class represents a virtual table cursor to be used with the
    /// <see cref="SQLiteModuleEnumerable" /> class.  It is not sealed and may
    /// be used as the base class for any user-defined virtual table cursor
    /// class that wraps an <see cref="IEnumerator" /> object instance.
    /// </summary>
    public class SQLiteVirtualTableCursorEnumerator :
            SQLiteVirtualTableCursor, IEnumerator /* NOT SEALED */
    {
        #region Private Data
        /// <summary>
        /// The <see cref="IEnumerator" /> instance provided when this cursor
        /// was created.
        /// </summary>
        private IEnumerator enumerator;

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// This value will be non-zero if false has been returned from the
        /// <see cref="IEnumerator.MoveNext" /> method.
        /// </summary>
        private bool endOfEnumerator;
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Public Constructors
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException" /> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
................................................................................
        /// Sets the table error message to one that indicates the virtual
        /// table cursor is of the wrong type.
        /// </summary>
        /// <param name="cursor">
        /// The <see cref="SQLiteVirtualTableCursor" /> object instance.
        /// </param>
        /// <returns>
        /// The value of <see cref="SQLiteErrorCode.Error" />.
        /// </returns>
        protected virtual SQLiteErrorCode CursorTypeMismatchError(
            SQLiteVirtualTableCursor cursor
            )
        {
            SetCursorError(cursor, "not an \"enumerator\" cursor");
            return SQLiteErrorCode.Error;
................................................................................
        /// Sets the table error message to one that indicates the virtual
        /// table cursor has no current row.
        /// </summary>
        /// <param name="cursor">
        /// The <see cref="SQLiteVirtualTableCursor" /> object instance.
        /// </param>
        /// <returns>
        /// The value of <see cref="SQLiteErrorCode.Error" />.
        /// </returns>
        protected virtual SQLiteErrorCode CursorEndOfEnumeratorError(
            SQLiteVirtualTableCursor cursor
            )
        {
            SetCursorError(cursor, "already hit end of enumerator");
            return SQLiteErrorCode.Error; 
................................................................................
        protected virtual string GetStringFromObject(
            object value
            )
        {
            if (value == null)
                return null;

            if (value is string)
                return (string)value;

            return value.ToString();
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Determines the unique row identifier for the object instance value.
................................................................................
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException" /> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
                throw new ObjectDisposedException(
                    typeof(SQLiteModuleEnumerable).Name);
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Disposes of this object instance.
        /// </summary>
        /// <param name="disposing">
        /// Non-zero if this method is being called from the
        /// <see cref="IDisposable.Dispose" /> method.  Zero if this method is
        /// being called from the finalizer.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            try
            {
                if (!disposed)
                {
                    //if (disposing)
                    //{
                    //    ////////////////////////////////////
                    //    // dispose managed resources here...
                    //    ////////////////////////////////////
                    //}

                    //////////////////////////////////////
                    // release unmanaged resources here...
                    //////////////////////////////////////

                    disposed = true;
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
        }
        #endregion
    }
    #endregion
}
#endregion

///////////////////////////////////////////////////////////////////////////////

#region Generic Classes
namespace System.Data.SQLite.Generic
{
    #region SQLiteVirtualTableCursorEnumerator<T> Class
    /// <summary>
    /// This class represents a virtual table cursor to be used with the
    /// <see cref="SQLiteModuleEnumerable" /> class.  It is not sealed and may
    /// be used as the base class for any user-defined virtual table cursor
    /// class that wraps an <see cref="IEnumerator{T}" /> object instance.
    /// </summary>
    public class SQLiteVirtualTableCursorEnumerator<T> :
            SQLiteVirtualTableCursorEnumerator, IEnumerator<T> /* NOT SEALED */
    {
        #region Private Data
        /// <summary>
        /// The <see cref="IEnumerator{T}" /> instance provided when this
        /// cursor was created.
        /// </summary>
        private IEnumerator<T> enumerator;
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Public Constructors
        /// <summary>
        /// Constructs an instance of this class.
        /// </summary>
        /// <param name="table">
        /// The <see cref="SQLiteVirtualTable" /> object instance associated
        /// with this object instance.
        /// </param>
        /// <param name="enumerator">
        /// The <see cref="IEnumerator{T}" /> instance to expose as a virtual
        /// table cursor.
        /// </param>
        public SQLiteVirtualTableCursorEnumerator(
            SQLiteVirtualTable table,
            IEnumerator<T> enumerator
            )
            : base(table, enumerator as IEnumerator)
        {
            this.enumerator = enumerator;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Public Members
        /// <summary>
        /// Returns the value for the current row of the virtual table cursor
        /// using the <see cref="IEnumerator{T}.Current" /> property of the
        /// <see cref="IEnumerator{T}" /> object instance.
        /// </summary>
        T IEnumerator<T>.Current
        {
            get
            {
                CheckDisposed();

                if (enumerator == null)
                    return default(T);

                return enumerator.Current;
            }
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Closes the virtual table cursor.
        /// </summary>
        public override void Close()
        {
            // CheckDisposed();

            if (enumerator != null)
                enumerator = null;

            base.Close();
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException" /> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
                throw new ObjectDisposedException(
                    typeof(SQLiteVirtualTableCursorEnumerator<T>).Name);
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Disposes of this object instance.
        /// </summary>
        /// <param name="disposing">
        /// Non-zero if this method is being called from the
        /// <see cref="IDisposable.Dispose" /> method.  Zero if this method is
        /// being called from the finalizer.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            try
            {
                if (!disposed)
                {
                    //if (disposing)
                    //{
                    //    ////////////////////////////////////
                    //    // dispose managed resources here...
                    //    ////////////////////////////////////
                    //}

                    //////////////////////////////////////
                    // release unmanaged resources here...
                    //////////////////////////////////////

                    Close();

                    disposed = true;
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
        }
        #endregion
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////

    #region SQLiteModuleEnumerable<T> Class
    /// <summary>
    /// This class implements a virtual table module that exposes an
    /// <see cref="IEnumerable{T}" /> object instance as a read-only virtual
    /// table.  It is not sealed and may be used as the base class for any
    /// user-defined virtual table class that wraps an
    /// <see cref="IEnumerable{T}" /> object instance.
    /// </summary>
    public class SQLiteModuleEnumerable<T> :
            SQLiteModuleEnumerable /* NOT SEALED */
    {
        #region Private Data
        /// <summary>
        /// The <see cref="IEnumerable{T}" /> instance containing the backing
        /// data for the virtual table.
        /// </summary>
        private IEnumerable<T> enumerable;
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Public Constructors
        /// <summary>
        /// Constructs an instance of this class.
        /// </summary>
        /// <param name="name">
        /// The name of the module.  This parameter cannot be null.
        /// </param>
        /// <param name="enumerable">
        /// The <see cref="IEnumerable{T}" /> instance to expose as a virtual
        /// table.  This parameter cannot be null.
        /// </param>
        public SQLiteModuleEnumerable(
            string name,
            IEnumerable<T> enumerable
            )
            : base(name, enumerable as IEnumerable)
        {
            this.enumerable = enumerable;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region ISQLiteManagedModule Members
        /// <summary>
        /// See the <see cref="ISQLiteManagedModule.Open" /> method.
        /// </summary>
        /// <param name="table">
        /// See the <see cref="ISQLiteManagedModule.Open" /> method.
        /// </param>
        /// <param name="cursor">
        /// See the <see cref="ISQLiteManagedModule.Open" /> method.
        /// </param>
        /// <returns>
        /// See the <see cref="ISQLiteManagedModule.Open" /> method.
        /// </returns>
        public override SQLiteErrorCode Open(
            SQLiteVirtualTable table,
            ref SQLiteVirtualTableCursor cursor
            )
        {
            CheckDisposed();

            cursor = new SQLiteVirtualTableCursorEnumerator<T>(
                table, enumerable.GetEnumerator());

            return SQLiteErrorCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// See the <see cref="ISQLiteManagedModule.Column" /> method.
        /// </summary>
        /// <param name="cursor">
        /// See the <see cref="ISQLiteManagedModule.Column" /> method.
        /// </param>
        /// <param name="context">
        /// See the <see cref="ISQLiteManagedModule.Column" /> method.
        /// </param>
        /// <param name="index">
        /// See the <see cref="ISQLiteManagedModule.Column" /> method.
        /// </param>
        /// <returns>
        /// See the <see cref="ISQLiteManagedModule.Column" /> method.
        /// </returns>
        public override SQLiteErrorCode Column(
            SQLiteVirtualTableCursor cursor,
            SQLiteContext context,
            int index
            )
        {
            CheckDisposed();

            SQLiteVirtualTableCursorEnumerator<T> enumeratorCursor =
                cursor as SQLiteVirtualTableCursorEnumerator<T>;

            if (enumeratorCursor == null)
                return CursorTypeMismatchError(cursor);

            if (enumeratorCursor.EndOfEnumerator)
                return CursorEndOfEnumeratorError(cursor);

            T current = ((IEnumerator<T>)enumeratorCursor).Current;

            if (current != null)
                context.SetString(GetStringFromObject(current));
            else
                context.SetNull();

            return SQLiteErrorCode.Ok;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException" /> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {
                throw new ObjectDisposedException(
                    typeof(SQLiteModuleEnumerable<T>).Name);
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
................................................................................
                base.Dispose(disposing);
            }
        }
        #endregion
    }
    #endregion
}
#endregion

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

716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException"/> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {







|







716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        /// <summary>
        /// Throws an <see cref="ObjectDisposedException" /> if this object
        /// instance has been disposed.
        /// </summary>
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
            {

Changes to Tests/vtab.eagle.

208
209
210
211
212
213
214
215
216
217












































































































218
219
  unset -nocomplain result code results errors sql dataSource id db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite\
defineConstant.System.Data.SQLite.INTEROP_VIRTUAL_TABLE} -match regexp -result \
[string map [list \n \r\n] {^Ok System#CodeDom#Compiler#CompilerResults#\d+\
\{\} 0 \{one two three 4 5.0 Error \{SQL logic error or missing database
virtual table "t\d+" is read-only\}\}$}]}

###############################################################################













































































































runSQLiteTestEpilogue
runTestEpilogue










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  unset -nocomplain result code results errors sql dataSource id db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite\
defineConstant.System.Data.SQLite.INTEROP_VIRTUAL_TABLE} -match regexp -result \
[string map [list \n \r\n] {^Ok System#CodeDom#Compiler#CompilerResults#\d+\
\{\} 0 \{one two three 4 5.0 Error \{SQL logic error or missing database
virtual table "t\d+" is read-only\}\}$}]}

###############################################################################

runTest {test vtab-1.3 {IEnumerable<T> virtual table} -setup {
  setupDb [set fileName vtab-1.3.db]
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  set sql(1) { \
    CREATE VIRTUAL TABLE t${id} USING mod${id}; \
  }

  set sql(2) { \
    SELECT * FROM t${id}; \
  }

  set sql(3) { \
    UPDATE t${id} SET x = 1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System;
    using System.Data.SQLite;
    using System.Data.SQLite.Generic;
    using Eagle._Containers.Public;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static StringList GetList(params int\[\] integers)
        {
          StringList result = new StringList();

          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            connection.CreateModule(new SQLiteModuleEnumerable<int>(
              "mod${id}", integers));

            using (SQLiteCommand command = connection.CreateCommand())
            {
              command.CommandText = "[subst ${sql(1)}]";
              command.ExecuteNonQuery();
            }

            using (SQLiteCommand command = connection.CreateCommand())
            {
              command.CommandText = "[subst ${sql(2)}]";

              using (SQLiteDataReader dataReader = command.ExecuteReader())
              {
                while (dataReader.Read())
                  result.Add(dataReader\[0\].ToString());
              }
            }

            using (SQLiteCommand command = connection.CreateCommand())
            {
              command.CommandText = "[subst ${sql(3)}]";

              try
              {
                command.ExecuteNonQuery();
              }
              catch (SQLiteException e)
              {
                result.Add(e.ResultCode.ToString());
                result.Add(e.Message);
              }
            }

            connection.Close();
          }

          return result;
        }

        ///////////////////////////////////////////////////////////////////////

        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] true true true results errors [list System.Data.SQLite.dll Eagle.dll]]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} GetList 1 2 3 4 5
      } result] : [set result ""]}] $result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors sql dataSource id db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite\
defineConstant.System.Data.SQLite.INTEROP_VIRTUAL_TABLE} -match regexp -result \
[string map [list \n \r\n] {^Ok System#CodeDom#Compiler#CompilerResults#\d+\
\{\} 0 \{1 2 3 4 5 Error \{SQL logic error or missing database
virtual table "t\d+" is read-only\}\}$}]}

###############################################################################

runSQLiteTestEpilogue
runTestEpilogue