System.Data.SQLite

Login
This project makes use of Eagle, provided by Mistachkin Systems.
Eagle: Secure Software Automation

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

Overview
Comment:Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post 25cafb35e5.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9e98945ce3a03e195938742bbf6602e469fb1cf5
User & Date: mistachkin 2024-05-24 19:16:41
Context
2024-05-24
20:53
Update SQLite core library to the 3.46.0 release. Pickup the latest SQLite 3.46.0 core library docs from upstream. check-in: 2ec4618e22 user: mistachkin tags: trunk
19:16
Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post 25cafb35e5. check-in: 9e98945ce3 user: mistachkin tags: trunk
19:15
Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post 76cb35b58d. check-in: ded053d6c2 user: mistachkin tags: trunk
19:12
Add tests for the fix on this branch. Closed-Leaf check-in: 59ad1a9be9 user: mistachkin tags: pst-25cafb35e5
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Doc/Extra/Provider/version.html.

44
45
46
47
48
49
50

51
52
53
54
55
56
57
    <div id="mainBody">
    <h1 class="heading">Version History</h1>
    <p><b>1.0.119.0 - May XX, 2024 <font color="red">(release scheduled)</font></b></p>
    <ul>
      <li>Updated to <a href="https://www.sqlite.org/releaselog/3_45_3.html">SQLite 3.45.3</a>.</li>
      <li>Update internal resource list of reserved SQL words.</li>
      <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/66a0d2716a">[66a0d2716a]</a>.</li>

      <li>Add the VfsName connection string property.</li>
      <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
      <li>Revise the calculation used to bind DateTime values. Fix for <a href="https://system.data.sqlite.org/index.html/info/bbddfeb773">[bbddfeb773]</a>.</li>
      <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/76cb35b58d">[76cb35b58d]</a>.</li>
    </ul>
    <p><b>1.0.118.0 - June 10, 2023</b></p>
    <ul>







>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    <div id="mainBody">
    <h1 class="heading">Version History</h1>
    <p><b>1.0.119.0 - May XX, 2024 <font color="red">(release scheduled)</font></b></p>
    <ul>
      <li>Updated to <a href="https://www.sqlite.org/releaselog/3_45_3.html">SQLite 3.45.3</a>.</li>
      <li>Update internal resource list of reserved SQL words.</li>
      <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/66a0d2716a">[66a0d2716a]</a>.</li>
      <li>Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/25cafb35e5">[25cafb35e5]</a>.</li>
      <li>Add the VfsName connection string property.</li>
      <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
      <li>Revise the calculation used to bind DateTime values. Fix for <a href="https://system.data.sqlite.org/index.html/info/bbddfeb773">[bbddfeb773]</a>.</li>
      <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/76cb35b58d">[76cb35b58d]</a>.</li>
    </ul>
    <p><b>1.0.118.0 - June 10, 2023</b></p>
    <ul>

Changes to Setup/data/verify.lst.

841
842
843
844
845
846
847

848
849
850
851
852
853
854
  Tests/data/wal.db
  Tests/function.eagle
  Tests/installer.eagle
  Tests/linq.eagle
  Tests/memory.eagle
  Tests/pool.eagle
  Tests/progress.eagle

  Tests/pst-4db2934c2e.eagle
  Tests/pst-76cb35b58d.eagle
  Tests/pst-eeaefb84ec.eagle
  Tests/pst-f4e718891d.eagle
  Tests/session.eagle
  Tests/speed.eagle
  Tests/stress.eagle







>







841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
  Tests/data/wal.db
  Tests/function.eagle
  Tests/installer.eagle
  Tests/linq.eagle
  Tests/memory.eagle
  Tests/pool.eagle
  Tests/progress.eagle
  Tests/pst-25cafb35e5.eagle
  Tests/pst-4db2934c2e.eagle
  Tests/pst-76cb35b58d.eagle
  Tests/pst-eeaefb84ec.eagle
  Tests/pst-f4e718891d.eagle
  Tests/session.eagle
  Tests/speed.eagle
  Tests/stress.eagle

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

186
187
188
189
190
191
192


193
194
195
196
197

198
199
200
201
202
203
204

        if (db != IntPtr.Zero)
        {
            _sql = new SQLiteConnectionHandle(db, ownHandle);
            _fileName = fileName;
            _returnToFileName = fileName;



            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                SQLiteConnectionEventType.NewCriticalHandle, null,
                null, null, null, _sql, fileName, new object[] {
                typeof(SQLite3), fmt, kind, fmtString, db, fileName,
                ownHandle }));

        }
    }

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

    #region Query Diagnostics Support
    /// <summary>







>
>
|
|
|
|
|
>







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207

        if (db != IntPtr.Zero)
        {
            _sql = new SQLiteConnectionHandle(db, ownHandle);
            _fileName = fileName;
            _returnToFileName = fileName;

            if (SQLiteConnection.CanOnChanged(null))
            {
                SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                    SQLiteConnectionEventType.NewCriticalHandle, null,
                    null, null, null, _sql, fileName, new object[] {
                    typeof(SQLite3), fmt, kind, fmtString, db, fileName,
                    ownHandle }));
            }
        }
    }

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

    #region Query Diagnostics Support
    /// <summary>
399
400
401
402
403
404
405


406
407
408
409

410
411
412
413
414
415
416

#if INTEROP_VIRTUAL_TABLE
                  DisposeModules();
#endif

                  SQLiteConnectionPool.Add(_returnToFileName, _sql, _poolVersion);



                  SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                      SQLiteConnectionEventType.ClosedToPool, null, null,
                      null, null, _sql, _returnToFileName, new object[] {
                      typeof(SQLite3), !disposing, _returnToFileName, _poolVersion }));


#if !NET_COMPACT_20 && TRACE_CONNECTION
                  Trace.WriteLine(HelperMethods.StringFormat(
                      CultureInfo.CurrentCulture,
                      "Close (Pool) Success: {0}",
                      HandleToString()));
#endif







>
>
|
|
|
|
>







402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

#if INTEROP_VIRTUAL_TABLE
                  DisposeModules();
#endif

                  SQLiteConnectionPool.Add(_returnToFileName, _sql, _poolVersion);

                  if (SQLiteConnection.CanOnChanged(null))
                  {
                      SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                          SQLiteConnectionEventType.ClosedToPool, null, null,
                          null, null, _sql, _returnToFileName, new object[] {
                          typeof(SQLite3), !disposing, _returnToFileName, _poolVersion }));
                  }

#if !NET_COMPACT_20 && TRACE_CONNECTION
                  Trace.WriteLine(HelperMethods.StringFormat(
                      CultureInfo.CurrentCulture,
                      "Close (Pool) Success: {0}",
                      HandleToString()));
#endif
1197
1198
1199
1200
1201
1202
1203


1204
1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
      _returnToFileName = strFilename;
      _flags = connectionFlags;

      if (usePool)
      {
        _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);



        SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
            SQLiteConnectionEventType.OpenedFromPool, null, null,
            null, null, _sql, strFilename, new object[] {
            typeof(SQLite3), strFilename, vfsName, connectionFlags,
            openFlags, maxPoolSize, usePool, _poolVersion }));


#if !NET_COMPACT_20 && TRACE_CONNECTION
        Trace.WriteLine(HelperMethods.StringFormat(
            CultureInfo.CurrentCulture,
            "Open (Pool): {0}", HandleToString()));
#endif
      }







>
>
|
|
|
|
|
>







1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
      _returnToFileName = strFilename;
      _flags = connectionFlags;

      if (usePool)
      {
        _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);

        if (SQLiteConnection.CanOnChanged(null))
        {
            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                SQLiteConnectionEventType.OpenedFromPool, null, null,
                null, null, _sql, strFilename, new object[] {
                typeof(SQLite3), strFilename, vfsName, connectionFlags,
                openFlags, maxPoolSize, usePool, _poolVersion }));
        }

#if !NET_COMPACT_20 && TRACE_CONNECTION
        Trace.WriteLine(HelperMethods.StringFormat(
            CultureInfo.CurrentCulture,
            "Open (Pool): {0}", HandleToString()));
#endif
      }
1247
1248
1249
1250
1251
1252
1253


1254
1255
1256
1257
1258

1259
1260
1261
1262
1263
1264
1265

          if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, null);
          _sql = new SQLiteConnectionHandle(db, true);
          BumpCreateCount();
        }
        lock (_sql) { /* HACK: Force the SyncBlock to be "created" now. */ }



        SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
            SQLiteConnectionEventType.NewCriticalHandle, null,
            null, null, null, _sql, strFilename, new object[] {
            typeof(SQLite3), strFilename, vfsName, connectionFlags,
            openFlags, maxPoolSize, usePool }));

      }

      // Bind functions to this connection.  If any previous functions of the same name
      // were already bound, then the new bindings replace the old.
      if (!HelperMethods.HasFlags(connectionFlags, SQLiteConnectionFlags.NoBindFunctions))
      {
          if (_functions == null)







>
>
|
|
|
|
|
>







1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277

          if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, null);
          _sql = new SQLiteConnectionHandle(db, true);
          BumpCreateCount();
        }
        lock (_sql) { /* HACK: Force the SyncBlock to be "created" now. */ }

        if (SQLiteConnection.CanOnChanged(null))
        {
            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                SQLiteConnectionEventType.NewCriticalHandle, null,
                null, null, null, _sql, strFilename, new object[] {
                typeof(SQLite3), strFilename, vfsName, connectionFlags,
                openFlags, maxPoolSize, usePool }));
        }
      }

      // Bind functions to this connection.  If any previous functions of the same name
      // were already bound, then the new bindings replace the old.
      if (!HelperMethods.HasFlags(connectionFlags, SQLiteConnectionFlags.NoBindFunctions))
      {
          if (_functions == null)
1699
1700
1701
1702
1703
1704
1705


1706
1707
1708
1709

1710
1711
1712
1713
1714
1715
1716
              if (statementHandle != null) statementHandle.Dispose();
              statementHandle = new SQLiteStatementHandle(_sql, stmt);
            }
          }

          if (statementHandle != null)
          {


            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
              SQLiteConnectionEventType.NewCriticalHandle, null, null,
              null, null, statementHandle, strSql, new object[] {
              typeof(SQLite3), cnn, strSql, previous, timeoutMS }));

          }

          if (ShouldThrowForCancel())
          {
              if ((n == SQLiteErrorCode.Ok) ||
                  (n == SQLiteErrorCode.Row) ||
                  (n == SQLiteErrorCode.Done))







>
>
|
|
|
|
>







1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
              if (statementHandle != null) statementHandle.Dispose();
              statementHandle = new SQLiteStatementHandle(_sql, stmt);
            }
          }

          if (statementHandle != null)
          {
              if (SQLiteConnection.CanOnChanged(null))
              {
                  SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                      SQLiteConnectionEventType.NewCriticalHandle, null, null,
                      null, null, statementHandle, strSql, new object[] {
                      typeof(SQLite3), cnn, strSql, previous, timeoutMS }));
              }
          }

          if (ShouldThrowForCancel())
          {
              if ((n == SQLiteErrorCode.Ok) ||
                  (n == SQLiteErrorCode.Row) ||
                  (n == SQLiteErrorCode.Done))
4308
4309
4310
4311
4312
4313
4314


4315
4316
4317
4318

4319
4320
4321
4322
4323
4324
4325
                else
                    throw new SQLiteException("failed to initialize backup");
            }

            backupHandle = new SQLiteBackupHandle(destHandle, backup);
        }



        SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
            SQLiteConnectionEventType.NewCriticalHandle, null,
            null, null, null, backupHandle, null, new object[] {
            typeof(SQLite3), destCnn, destName, sourceName }));


        return new SQLiteBackup(
            this, backupHandle, destHandle, zDestName, sourceHandle,
            zSourceName);
    }

    /// <summary>







>
>
|
|
|
|
>







4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
                else
                    throw new SQLiteException("failed to initialize backup");
            }

            backupHandle = new SQLiteBackupHandle(destHandle, backup);
        }

        if (SQLiteConnection.CanOnChanged(null))
        {
            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                SQLiteConnectionEventType.NewCriticalHandle, null,
                null, null, null, backupHandle, null, new object[] {
                typeof(SQLite3), destCnn, destName, sourceName }));
        }

        return new SQLiteBackup(
            this, backupHandle, destHandle, zDestName, sourceHandle,
            zSourceName);
    }

    /// <summary>

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

165
166
167
168
169
170
171


172
173
174
175
176
177

178
179
180
181
182
183
184
      _returnToFileName = strFilename;
      _flags = connectionFlags;

      if (usePool)
      {
        _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);



        SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
            SQLiteConnectionEventType.OpenedFromPool, null, null,
            null, null, _sql, strFilename, new object[] {
            typeof(SQLite3_UTF16), strFilename, vfsName,
            connectionFlags, openFlags, maxPoolSize, usePool,
            _poolVersion }));


#if !NET_COMPACT_20 && TRACE_CONNECTION
        Trace.WriteLine(HelperMethods.StringFormat(
            CultureInfo.CurrentCulture,
            "Open16 (Pool): {0}",
            HandleToString()));
#endif







>
>
|
|
|
|
|
|
>







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
      _returnToFileName = strFilename;
      _flags = connectionFlags;

      if (usePool)
      {
        _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);

        if (SQLiteConnection.CanOnChanged(null))
        {
            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                SQLiteConnectionEventType.OpenedFromPool, null, null,
                null, null, _sql, strFilename, new object[] {
                typeof(SQLite3_UTF16), strFilename, vfsName,
                connectionFlags, openFlags, maxPoolSize, usePool,
                _poolVersion }));
        }

#if !NET_COMPACT_20 && TRACE_CONNECTION
        Trace.WriteLine(HelperMethods.StringFormat(
            CultureInfo.CurrentCulture,
            "Open16 (Pool): {0}",
            HandleToString()));
#endif
233
234
235
236
237
238
239


240
241
242
243
244

245
246
247
248
249
250
251

          if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, null);
          _sql = new SQLiteConnectionHandle(db, true);
          BumpCreateCount();
        }
        lock (_sql) { /* HACK: Force the SyncBlock to be "created" now. */ }



        SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
            SQLiteConnectionEventType.NewCriticalHandle, null,
            null, null, null, _sql, strFilename, new object[] {
            typeof(SQLite3_UTF16), strFilename, vfsName,
            connectionFlags, openFlags, maxPoolSize, usePool }));

      }

      // Bind functions to this connection.  If any previous functions of the same name
      // were already bound, then the new bindings replace the old.
      if (!HelperMethods.HasFlags(connectionFlags, SQLiteConnectionFlags.NoBindFunctions))
      {
          if (_functions == null)







>
>
|
|
|
|
|
>







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

          if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, null);
          _sql = new SQLiteConnectionHandle(db, true);
          BumpCreateCount();
        }
        lock (_sql) { /* HACK: Force the SyncBlock to be "created" now. */ }

        if (SQLiteConnection.CanOnChanged(null))
        {
            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                SQLiteConnectionEventType.NewCriticalHandle, null,
                null, null, null, _sql, strFilename, new object[] {
                typeof(SQLite3_UTF16), strFilename, vfsName,
                connectionFlags, openFlags, maxPoolSize, usePool }));
        }
      }

      // Bind functions to this connection.  If any previous functions of the same name
      // were already bound, then the new bindings replace the old.
      if (!HelperMethods.HasFlags(connectionFlags, SQLiteConnectionFlags.NoBindFunctions))
      {
          if (_functions == null)

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

156
157
158
159
160
161
162


163
164
165
166

167
168
169
170
171
172
173

                if (rc != SQLiteErrorCode.Ok)
                    throw new SQLiteException(rc, null);

                blob = new SQLiteBlobHandle(handle, ptrBlob);
            }



            SQLiteConnection.OnChanged(connection, new ConnectionEventArgs(
                SQLiteConnectionEventType.NewCriticalHandle, null, null,
                null, null, blob, null, new object[] { typeof(SQLiteBlob),
                databaseName, tableName, columnName, rowId, readOnly }));


            return new SQLiteBlob(sqlite3, blob);
        }
        #endregion

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








>
>
|
|
|
|
>







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176

                if (rc != SQLiteErrorCode.Ok)
                    throw new SQLiteException(rc, null);

                blob = new SQLiteBlobHandle(handle, ptrBlob);
            }

            if (SQLiteConnection.CanOnChanged(connection))
            {
                SQLiteConnection.OnChanged(connection, new ConnectionEventArgs(
                    SQLiteConnectionEventType.NewCriticalHandle, null, null,
                    null, null, blob, null, new object[] { typeof(SQLiteBlob),
                    databaseName, tableName, columnName, rowId, readOnly }));
            }

            return new SQLiteBlob(sqlite3, blob);
        }
        #endregion

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

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

168
169
170
171
172
173
174


175
176
177

178
179
180
181
182
183
184
        _commandTimeout = connection.DefaultTimeout;
        _maximumSleepTime = connection.DefaultMaximumSleepTime;
      }

      if (transaction != null)
        Transaction = transaction;



      SQLiteConnection.OnChanged(connection, new ConnectionEventArgs(
          SQLiteConnectionEventType.NewCommand, null, transaction, this,
          null, null, null, null));

    }

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

    [Conditional("CHECK_STATE")]
    internal static void Check(SQLiteCommand command)
    {







>
>
|
|
|
>







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
        _commandTimeout = connection.DefaultTimeout;
        _maximumSleepTime = connection.DefaultMaximumSleepTime;
      }

      if (transaction != null)
        Transaction = transaction;

      if (SQLiteConnection.CanOnChanged(connection))
      {
          SQLiteConnection.OnChanged(connection, new ConnectionEventArgs(
              SQLiteConnectionEventType.NewCommand, null, transaction, this,
              null, null, null, null));
      }
    }

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

    [Conditional("CHECK_STATE")]
    internal static void Check(SQLiteCommand command)
    {
205
206
207
208
209
210
211


212
213
214

215
216
217
218
219
220
221

    /// <summary>
    /// Disposes of the command and clears all member variables
    /// </summary>
    /// <param name="disposing">Whether or not the class is being explicitly or implicitly disposed</param>
    protected override void Dispose(bool disposing)
    {


        SQLiteConnection.OnChanged(_cnn, new ConnectionEventArgs(
            SQLiteConnectionEventType.DisposingCommand, null, _transaction, this,
            null, null, null, new object[] { disposing, disposed }));


        bool skippedDispose = false;

        try
        {
            if (!disposed)
            {







>
>
|
|
|
>







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

    /// <summary>
    /// Disposes of the command and clears all member variables
    /// </summary>
    /// <param name="disposing">Whether or not the class is being explicitly or implicitly disposed</param>
    protected override void Dispose(bool disposing)
    {
        if (SQLiteConnection.CanOnChanged(_cnn))
        {
            SQLiteConnection.OnChanged(_cnn, new ConnectionEventArgs(
                SQLiteConnectionEventType.DisposingCommand, null, _transaction, this,
                null, null, null, new object[] { disposing, disposed }));
        }

        bool skippedDispose = false;

        try
        {
            if (!disposed)
            {
565
566
567
568
569
570
571


572
573
574
575
576
577
578

579
580
581
582
583
584
585
      }
      set
      {
        CheckDisposed();

        string newCommandText = value;



        ConnectionEventArgs previewEventArgs = new ConnectionEventArgs(
            SQLiteConnectionEventType.SqlStringPreview,
            null, null, null, null, null, null, null, null);

        previewEventArgs.Result = newCommandText;
        SQLiteConnection.OnChanged(_cnn, previewEventArgs);
        newCommandText = previewEventArgs.Result;


        if (_commandText == newCommandText) return;

        if (_activeReader != null && _activeReader.IsAlive)
        {
          throw new InvalidOperationException("Cannot set CommandText while a DataReader is active");
        }







>
>
|
|
|

|
|
|
>







571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
      }
      set
      {
        CheckDisposed();

        string newCommandText = value;

        if (SQLiteConnection.CanOnChanged(_cnn))
        {
            ConnectionEventArgs previewEventArgs = new ConnectionEventArgs(
                SQLiteConnectionEventType.SqlStringPreview,
                null, null, null, null, null, null, null, null);

            previewEventArgs.Result = newCommandText;
            SQLiteConnection.OnChanged(_cnn, previewEventArgs);
            newCommandText = previewEventArgs.Result;
        }

        if (_commandText == newCommandText) return;

        if (_activeReader != null && _activeReader.IsAlive)
        {
          throw new InvalidOperationException("Cannot set CommandText while a DataReader is active");
        }

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

811
812
813
814
815
816
817












818
819
820
821
822
823
824
  /////////////////////////////////////////////////////////////////////////////////////////////////

  /// <summary>
  /// Event data for connection event handlers.
  /// </summary>
  public class ConnectionEventArgs : EventArgs
  {












      /// <summary>
      /// The type of event being raised.
      /// </summary>
      public readonly SQLiteConnectionEventType EventType;

      /// <summary>
      /// The <see cref="StateChangeEventArgs" /> associated with this event, if any.







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







811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
  /////////////////////////////////////////////////////////////////////////////////////////////////

  /// <summary>
  /// Event data for connection event handlers.
  /// </summary>
  public class ConnectionEventArgs : EventArgs
  {
      /// <summary>
      /// Returns the number of instances of this class that have been created
      /// within this application domain.
      /// </summary>
      private static long createCount;
      public static long CreateCount
      {
          get { return createCount; }
      }

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

      /// <summary>
      /// The type of event being raised.
      /// </summary>
      public readonly SQLiteConnectionEventType EventType;

      /// <summary>
      /// The <see cref="StateChangeEventArgs" /> associated with this event, if any.
919
920
921
922
923
924
925


926
927
928
929
930
931
932
          object criticalHandle,
#endif
          string text,
          object data,
          string result
          )
      {


          EventType = eventType;
          EventArgs = eventArgs;
          Transaction = transaction;
          Command = command;
          DataReader = dataReader;
          CriticalHandle = criticalHandle;
          Text = text;







>
>







931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
          object criticalHandle,
#endif
          string text,
          object data,
          string result
          )
      {
          Interlocked.Increment(ref createCount);

          EventType = eventType;
          EventArgs = eventArgs;
          Transaction = transaction;
          Command = command;
          DataReader = dataReader;
          CriticalHandle = criticalHandle;
          Text = text;
1532
1533
1534
1535
1536
1537
1538












1539
1540
1541
1542
1543
1544
1545

#if SQLITE_STANDARD && !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// Used to hold the active library version number of SQLite.
    /// </summary>
    private static int _versionNumber;
#endif












    #endregion

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

    #region Private Data
    /// <summary>
    /// State of the current connection







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







1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571

#if SQLITE_STANDARD && !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// Used to hold the active library version number of SQLite.
    /// </summary>
    private static int _versionNumber;
#endif

    /// <summary>
    /// Used to hold the number of times the <see cref="Changed" /> event
    /// should have been fired.
    /// </summary>
    private static long _onChangedHit;

    /// <summary>
    /// Used to hold the number of times the <see cref="Changed" /> event
    /// should have been skipped.
    /// </summary>
    private static long _onChangedMiss;
    #endregion

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

    #region Private Data
    /// <summary>
    /// State of the current connection
2149
2150
2151
2152
2153
2154
2155























































2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
                    throw new NotImplementedException();
                }
        }
    }

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
























































    /// <summary>
    /// Raises the <see cref="Changed" /> event.
    /// </summary>
    /// <param name="connection">
    /// The connection associated with this event.  If this parameter is not
    /// null and the specified connection cannot raise events, then the
    /// registered event handlers will not be invoked.
    /// </param>
    /// <param name="e">
    /// A <see cref="ConnectionEventArgs" /> that contains the event data.
    /// </param>
    internal static void OnChanged(
        SQLiteConnection connection,
        ConnectionEventArgs e
        )
    {
#if !PLATFORM_COMPACTFRAMEWORK
        if ((connection != null) &&
            !connection.disposed && !connection.CanRaiseEvents)
        {
            return;
        }
#endif

        SQLiteConnectionEventHandler handlers;

        lock (_syncRoot)
        {
            if (_handlers != null)
                handlers = _handlers.Clone() as SQLiteConnectionEventHandler;
            else







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
















<
<
<
<
<
<
<
<







2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252








2253
2254
2255
2256
2257
2258
2259
                    throw new NotImplementedException();
                }
        }
    }

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

    /// <summary>
    /// Attempts to determine if <see cref="Changed" /> events can be
    /// raised.
    /// </summary>
    /// <param name="connection">
    /// The connection associated with this event, if any.
    /// </param>
    /// <returns>
    /// Non-zero if <see cref="Changed" /> events are currently enabled
    /// for the specified connection; otherwise, zero.
    /// </returns>
    internal static bool CanOnChanged(
        SQLiteConnection connection
        )
    {
        if (connection != null)
        {
            if (connection.disposed)
            {
                Interlocked.Increment(ref _onChangedMiss);
                return false;
            }

#if !PLATFORM_COMPACTFRAMEWORK
            if (!connection.CanRaiseEvents)
            {
                Interlocked.Increment(ref _onChangedMiss);
                return false;
            }
#endif
        }

        //
        // BUGFIX: *PERF* If there are no event handlers, we do not
        //         attempt to handle any events -AND- skip creating
        //         data for event arguments.  This should minimize
        //         "wasted" heap allocations.
        //
        lock (_syncRoot)
        {
            if (_handlers != null)
            {
                Interlocked.Increment(ref _onChangedHit);
                return true;
            }
            else
            {
                Interlocked.Increment(ref _onChangedMiss);
                return false;
            }
        }
    }

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

    /// <summary>
    /// Raises the <see cref="Changed" /> event.
    /// </summary>
    /// <param name="connection">
    /// The connection associated with this event.  If this parameter is not
    /// null and the specified connection cannot raise events, then the
    /// registered event handlers will not be invoked.
    /// </param>
    /// <param name="e">
    /// A <see cref="ConnectionEventArgs" /> that contains the event data.
    /// </param>
    internal static void OnChanged(
        SQLiteConnection connection,
        ConnectionEventArgs e
        )
    {








        SQLiteConnectionEventHandler handlers;

        lock (_syncRoot)
        {
            if (_handlers != null)
                handlers = _handlers.Clone() as SQLiteConnectionEventHandler;
            else
2264
2265
2266
2267
2268
2269
2270


2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
        {
            result = (nativeHandle != IntPtr.Zero) ?
                new SQLiteConnectionHandle(nativeHandle, true) : null;
        }

        if (result != null)
        {


            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                SQLiteConnectionEventType.NewCriticalHandle, null,
                null, null, null, result, null, new object[] {
                typeof(SQLiteConnection), nativeHandle }));

        }

        return result;
    }

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








>
>
|
|
|
|
>







2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
        {
            result = (nativeHandle != IntPtr.Zero) ?
                new SQLiteConnectionHandle(nativeHandle, true) : null;
        }

        if (result != null)
        {
            if (CanOnChanged(null))
            {
                OnChanged(null, new ConnectionEventArgs(
                    SQLiteConnectionEventType.NewCriticalHandle, null,
                    null, null, null, result, null, new object[] {
                    typeof(SQLiteConnection), nativeHandle }));
            }
        }

        return result;
    }

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

3122
3123
3124
3125
3126
3127
3128


3129
3130
3131
3132
3133

3134
3135
3136
3137
3138
3139
3140
    /// Cleans up resources (native and managed) associated with the current instance.
    /// </summary>
    /// <param name="disposing">
    /// Zero when being disposed via garbage collection; otherwise, non-zero.
    /// </param>
    protected override void Dispose(bool disposing)
    {


        OnChanged(this, new ConnectionEventArgs(
            disposing ?
                SQLiteConnectionEventType.DisposingConnection :
                SQLiteConnectionEventType.FinalizingConnection,
            null, null, null, null, null, null, null));


#if !NET_COMPACT_20 && TRACE_WARNING
        if (HelperMethods.HasFlags(_flags, SQLiteConnectionFlags.TraceWarning))
        {
            if (_noDispose)
            {
                System.Diagnostics.Trace.WriteLine(HelperMethods.StringFormat(







>
>
|
|
|
|
|
>







3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
    /// Cleans up resources (native and managed) associated with the current instance.
    /// </summary>
    /// <param name="disposing">
    /// Zero when being disposed via garbage collection; otherwise, non-zero.
    /// </param>
    protected override void Dispose(bool disposing)
    {
        if (CanOnChanged(this))
        {
            OnChanged(this, new ConnectionEventArgs(
                disposing ?
                    SQLiteConnectionEventType.DisposingConnection :
                    SQLiteConnectionEventType.FinalizingConnection,
                null, null, null, null, null, null, null));
        }

#if !NET_COMPACT_20 && TRACE_WARNING
        if (HelperMethods.HasFlags(_flags, SQLiteConnectionFlags.TraceWarning))
        {
            if (_noDispose)
            {
                System.Diagnostics.Trace.WriteLine(HelperMethods.StringFormat(
3170
3171
3172
3173
3174
3175
3176


3177
3178
3179
3180
3181

3182
3183
3184
3185
3186
3187
3188
            base.Dispose(disposing);

            //
            // NOTE: Everything should be fully disposed at this point.
            //
            disposed = true;



            OnChanged(this, new ConnectionEventArgs(
                disposing ?
                    SQLiteConnectionEventType.DisposedConnection :
                    SQLiteConnectionEventType.FinalizedConnection,
                null, null, null, null, null, null, null));

        }
    }
    #endregion

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

#if PLATFORM_COMPACTFRAMEWORK







>
>
|
|
|
|
|
>







3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
            base.Dispose(disposing);

            //
            // NOTE: Everything should be fully disposed at this point.
            //
            disposed = true;

            if (CanOnChanged(this))
            {
                OnChanged(this, new ConnectionEventArgs(
                    disposing ?
                        SQLiteConnectionEventType.DisposedConnection :
                        SQLiteConnectionEventType.FinalizedConnection,
                    null, null, null, null, null, null, null));
            }
        }
    }
    #endregion

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

#if PLATFORM_COMPACTFRAMEWORK
3359
3360
3361
3362
3363
3364
3365


3366
3367
3368

3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381


3382
3383
3384

3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398


3399
3400
3401

3402
3403
3404
3405
3406
3407
3408
      }
      else
      {
          transaction = new SQLiteTransaction(
              this, isolationLevel != ImmediateIsolationLevel);
      }



      OnChanged(this, new ConnectionEventArgs(
          SQLiteConnectionEventType.NewTransaction, null, transaction,
          null, null, null, null, null));


      return transaction;
    }

    /// <summary>
    /// This method is not implemented; however, the <see cref="Changed" />
    /// event will still be raised.
    /// </summary>
    /// <param name="databaseName"></param>
    public override void ChangeDatabase(string databaseName)
    {
      CheckDisposed();



      OnChanged(this, new ConnectionEventArgs(
          SQLiteConnectionEventType.ChangeDatabase, null, null, null, null,
          null, databaseName, null));


      throw new NotImplementedException(); // NOTE: For legacy compatibility.
    }

    /// <summary>
    /// When the database connection is closed, all commands linked to this connection are automatically reset.
    /// </summary>
    public override void Close()
    {
      CheckDisposed();

      if (Object.ReferenceEquals(_lastConnectionInOpen, this))
          _lastConnectionInOpen = null; /* THREAD-SAFE: per-thread datum. */



      OnChanged(this, new ConnectionEventArgs(
          SQLiteConnectionEventType.Closing, null, null, null, null, null,
          null, null));


      if (_sql != null)
      {
#if !PLATFORM_COMPACTFRAMEWORK
        lock (_enlistmentSyncRoot) /* TRANSACTIONAL */
        {
          SQLiteEnlistment enlistment = _enlistment;







>
>
|
|
|
>













>
>
|
|
|
>














>
>
|
|
|
>







3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
      }
      else
      {
          transaction = new SQLiteTransaction(
              this, isolationLevel != ImmediateIsolationLevel);
      }

      if (CanOnChanged(this))
      {
          OnChanged(this, new ConnectionEventArgs(
              SQLiteConnectionEventType.NewTransaction, null, transaction,
              null, null, null, null, null));
      }

      return transaction;
    }

    /// <summary>
    /// This method is not implemented; however, the <see cref="Changed" />
    /// event will still be raised.
    /// </summary>
    /// <param name="databaseName"></param>
    public override void ChangeDatabase(string databaseName)
    {
      CheckDisposed();

      if (CanOnChanged(this))
      {
          OnChanged(this, new ConnectionEventArgs(
              SQLiteConnectionEventType.ChangeDatabase, null, null, null, null,
              null, databaseName, null));
      }

      throw new NotImplementedException(); // NOTE: For legacy compatibility.
    }

    /// <summary>
    /// When the database connection is closed, all commands linked to this connection are automatically reset.
    /// </summary>
    public override void Close()
    {
      CheckDisposed();

      if (Object.ReferenceEquals(_lastConnectionInOpen, this))
          _lastConnectionInOpen = null; /* THREAD-SAFE: per-thread datum. */

      if (CanOnChanged(this))
      {
          OnChanged(this, new ConnectionEventArgs(
              SQLiteConnectionEventType.Closing, null, null, null, null, null,
              null, null));
      }

      if (_sql != null)
      {
#if !PLATFORM_COMPACTFRAMEWORK
        lock (_enlistmentSyncRoot) /* TRANSACTIONAL */
        {
          SQLiteEnlistment enlistment = _enlistment;
3447
3448
3449
3450
3451
3452
3453


3454
3455
3456

3457
3458
3459
3460
3461


3462
3463
3464

3465
3466
3467
3468
3469
3470
3471
          _sql = null;
        }
        _transactionLevel = 0;
        _transactionSequence = 0;
      }
      else
      {


          OnChanged(this, new ConnectionEventArgs(
              SQLiteConnectionEventType.NothingToDo,
              null, null, null, null, null, null, null));

      }

      StateChangeEventArgs eventArgs = null;
      OnStateChange(ConnectionState.Closed, ref eventArgs);



      OnChanged(this, new ConnectionEventArgs(
          SQLiteConnectionEventType.Closed, eventArgs, null, null, null,
          null, null, null));

    }

    /// <summary>
    /// Returns the number of pool entries for the file name associated with this connection.
    /// </summary>
    public int PoolCount
    {







>
>
|
|
|
>





>
>
|
|
|
>







3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
          _sql = null;
        }
        _transactionLevel = 0;
        _transactionSequence = 0;
      }
      else
      {
          if (CanOnChanged(this))
          {
              OnChanged(this, new ConnectionEventArgs(
                  SQLiteConnectionEventType.NothingToDo,
                  null, null, null, null, null, null, null));
          }
      }

      StateChangeEventArgs eventArgs = null;
      OnStateChange(ConnectionState.Closed, ref eventArgs);

      if (CanOnChanged(this))
      {
          OnChanged(this, new ConnectionEventArgs(
              SQLiteConnectionEventType.Closed, eventArgs, null, null, null,
              null, null, null));
      }
    }

    /// <summary>
    /// Returns the number of pool entries for the file name associated with this connection.
    /// </summary>
    public int PoolCount
    {
4012
4013
4014
4015
4016
4017
4018


4019
4020
4021

4022
4023
4024
4025
4026
4027
4028
            bool strictEnlistment = HelperMethods.HasFlags(
                _flags, SQLiteConnectionFlags.StrictEnlistment);

            _enlistment = new SQLiteEnlistment(this, transaction,
                GetFallbackDefaultIsolationLevel(), strictEnlistment,
                strictEnlistment);



            OnChanged(this, new ConnectionEventArgs(
                SQLiteConnectionEventType.EnlistTransaction, null, null, null, null,
                null, null, new object[] { _enlistment }));

        }
    }
#endif

#if !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// <b>EXPERIMENTAL</b> --







>
>
|
|
|
>







4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
            bool strictEnlistment = HelperMethods.HasFlags(
                _flags, SQLiteConnectionFlags.StrictEnlistment);

            _enlistment = new SQLiteEnlistment(this, transaction,
                GetFallbackDefaultIsolationLevel(), strictEnlistment,
                strictEnlistment);

            if (CanOnChanged(this))
            {
                OnChanged(this, new ConnectionEventArgs(
                    SQLiteConnectionEventType.EnlistTransaction, null, null, null, null,
                    null, null, new object[] { _enlistment }));
            }
        }
    }
#endif

#if !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// <b>EXPERIMENTAL</b> --
4635
4636
4637
4638
4639
4640
4641


4642
4643
4644

4645
4646
4647
4648
4649
4650


4651
4652
4653
4654
4655
4656
4657

4658
4659
4660
4661
4662
4663
4664
    /// </summary>
    public override void Open()
    {
      CheckDisposed();

      _lastConnectionInOpen = this; /* THREAD-SAFE: per-thread datum. */



      OnChanged(this, new ConnectionEventArgs(
          SQLiteConnectionEventType.Opening, null, null, null, null, null,
          null, null));


      if (_connectionState != ConnectionState.Closed)
        throw new InvalidOperationException();

      Close();



      ConnectionEventArgs previewEventArgs = new ConnectionEventArgs(
          SQLiteConnectionEventType.ConnectionStringPreview,
          null, null, null, null, null, null, null, null);

      previewEventArgs.Result = _connectionString;
      OnChanged(this, previewEventArgs);
      _connectionString = previewEventArgs.Result;


      SortedList<string, string> opts = ParseConnectionString(
          this, _connectionString, _parseViaFramework, false, false);

      string stringValue;
      object enumValue;








>
>
|
|
|
>






>
>
|
|
|

|
|
|
>







4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
    /// </summary>
    public override void Open()
    {
      CheckDisposed();

      _lastConnectionInOpen = this; /* THREAD-SAFE: per-thread datum. */

      if (CanOnChanged(this))
      {
          OnChanged(this, new ConnectionEventArgs(
              SQLiteConnectionEventType.Opening, null, null, null, null, null,
              null, null));
      }

      if (_connectionState != ConnectionState.Closed)
        throw new InvalidOperationException();

      Close();

      if (CanOnChanged(this))
      {
          ConnectionEventArgs previewEventArgs = new ConnectionEventArgs(
              SQLiteConnectionEventType.ConnectionStringPreview,
              null, null, null, null, null, null, null, null);

          previewEventArgs.Result = _connectionString;
          OnChanged(this, previewEventArgs);
          _connectionString = previewEventArgs.Result;
      }

      SortedList<string, string> opts = ParseConnectionString(
          this, _connectionString, _parseViaFramework, false, false);

      string stringValue;
      object enumValue;

4738
4739
4740
4741
4742
4743
4744


4745
4746
4747

4748
4749
4750
4751
4752
4753
4754
          }

          eventArgConnectionString = BuildConnectionString(
              eventArgOpts);
      }
#endif



      OnChanged(this, new ConnectionEventArgs(
          SQLiteConnectionEventType.ConnectionString, null, null, null, null,
          null, eventArgConnectionString, new object[] { eventArgOpts }));


      stringValue = FindKey(opts, "DefaultDbType", null);

      if (stringValue != null)
      {
          enumValue = TryParseEnum(typeof(DbType), stringValue, true);
          _defaultDbType = (enumValue is DbType) ? (DbType)enumValue : (DbType?)null;







>
>
|
|
|
>







4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
          }

          eventArgConnectionString = BuildConnectionString(
              eventArgOpts);
      }
#endif

      if (CanOnChanged(this))
      {
          OnChanged(this, new ConnectionEventArgs(
              SQLiteConnectionEventType.ConnectionString, null, null, null, null,
              null, eventArgConnectionString, new object[] { eventArgOpts }));
      }

      stringValue = FindKey(opts, "DefaultDbType", null);

      if (stringValue != null)
      {
          enumValue = TryParseEnum(typeof(DbType), stringValue, true);
          _defaultDbType = (enumValue is DbType) ? (DbType)enumValue : (DbType?)null;
5261
5262
5263
5264
5265
5266
5267


5268
5269
5270

5271
5272
5273
5274
5275
5276
5277
#endif

          _connectionState = oldstate;

          StateChangeEventArgs eventArgs = null;
          OnStateChange(ConnectionState.Open, ref eventArgs);



          OnChanged(this, new ConnectionEventArgs(
              SQLiteConnectionEventType.Opened, eventArgs, null, null, null,
              null, eventArgConnectionString, new object[] { eventArgOpts }));


#if DEBUG
          _debugString = HelperMethods.StringFormat(
              CultureInfo.InvariantCulture,
              "openThreadId = {0}, connectionString = {1}",
              HelperMethods.GetThreadId(),
              eventArgConnectionString);







>
>
|
|
|
>







5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
#endif

          _connectionState = oldstate;

          StateChangeEventArgs eventArgs = null;
          OnStateChange(ConnectionState.Open, ref eventArgs);

          if (CanOnChanged(this))
          {
              OnChanged(this, new ConnectionEventArgs(
                  SQLiteConnectionEventType.Opened, eventArgs, null, null, null,
                  null, eventArgConnectionString, new object[] { eventArgOpts }));
          }

#if DEBUG
          _debugString = HelperMethods.StringFormat(
              CultureInfo.InvariantCulture,
              "openThreadId = {0}, connectionString = {1}",
              HelperMethods.GetThreadId(),
              eventArgConnectionString);
5500
5501
5502
5503
5504
5505
5506


5507
5508
5509

5510
5511
5512
5513
5514
5515
5516
        CheckDisposed();

        if (_sql == null)
            throw new InvalidOperationException("Database connection not valid for query cancellation.");

        _sql.Cancel(); /* throw */



        OnChanged(this, new ConnectionEventArgs(
            SQLiteConnectionEventType.Canceled,
            null, null, null, null, null, null, null));

    }

    /// <summary>
    /// This method checks if the database operation for this connection has been
    /// interrupted.
    /// </summary>
    /// <returns>







>
>
|
|
|
>







5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
        CheckDisposed();

        if (_sql == null)
            throw new InvalidOperationException("Database connection not valid for query cancellation.");

        _sql.Cancel(); /* throw */

        if (CanOnChanged(this))
        {
            OnChanged(this, new ConnectionEventArgs(
                SQLiteConnectionEventType.Canceled,
                null, null, null, null, null, null, null));
        }
    }

    /// <summary>
    /// This method checks if the database operation for this connection has been
    /// interrupted.
    /// </summary>
    /// <returns>

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

111
112
113
114
115
116
117




118
119
120

121
122
123
124
125
126
127

      _commandBehavior = behave;
      _activeStatementIndex = -1;
      _rowsAffected = -1;

      RefreshFlags();





      SQLiteConnection.OnChanged(GetConnection(this),
          new ConnectionEventArgs(SQLiteConnectionEventType.NewDataReader,
          null, null, _command, this, null, null, new object[] { behave }));


      if (_command != null)
          NextResult();
    }

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








>
>
>
>
|
|
|
>







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

      _commandBehavior = behave;
      _activeStatementIndex = -1;
      _rowsAffected = -1;

      RefreshFlags();

      SQLiteConnection connection = GetConnection(this);

      if (SQLiteConnection.CanOnChanged(connection))
      {
          SQLiteConnection.OnChanged(connection,
              new ConnectionEventArgs(SQLiteConnectionEventType.NewDataReader,
              null, null, _command, this, null, null, new object[] { behave }));
      }

      if (_command != null)
          NextResult();
    }

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

139
140
141
142
143
144
145




146
147
148
149
150

151
152
153
154
155
156
157

    /// <summary>
    /// Dispose of all resources used by this datareader.
    /// </summary>
    /// <param name="disposing"></param>
    protected override void Dispose(bool disposing)
    {




        SQLiteConnection.OnChanged(GetConnection(this),
            new ConnectionEventArgs(SQLiteConnectionEventType.DisposingDataReader,
            null, null, _command, this, null, null, new object[] { disposing,
            disposed, _commandBehavior, _readingState, _rowsAffected, _stepCount,
            _fieldCount, _disposeCommand, _throwOnDisposed }));


        try
        {
            if (!disposed)
            {
                //if (disposing)
                //{







>
>
>
>
|
|
|
|
|
>







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

    /// <summary>
    /// Dispose of all resources used by this datareader.
    /// </summary>
    /// <param name="disposing"></param>
    protected override void Dispose(bool disposing)
    {
        SQLiteConnection connection = GetConnection(this);

        if (SQLiteConnection.CanOnChanged(connection))
        {
            SQLiteConnection.OnChanged(connection,
                new ConnectionEventArgs(SQLiteConnectionEventType.DisposingDataReader,
                null, null, _command, this, null, null, new object[] { disposing,
                disposed, _commandBehavior, _readingState, _rowsAffected, _stepCount,
                _fieldCount, _disposeCommand, _throwOnDisposed }));
        }

        try
        {
            if (!disposed)
            {
                //if (disposing)
                //{
193
194
195
196
197
198
199




200
201
202
203
204

205
206
207
208
209
210
211
    /// <summary>
    /// Closes the datareader, potentially closing the connection as well if CommandBehavior.CloseConnection was specified.
    /// </summary>
    public override void Close()
    {
      CheckDisposed();





      SQLiteConnection.OnChanged(GetConnection(this),
          new ConnectionEventArgs(SQLiteConnectionEventType.ClosingDataReader,
          null, null, _command, this, null, null, new object[] { _commandBehavior,
          _readingState, _rowsAffected, _stepCount, _fieldCount, _disposeCommand,
          _throwOnDisposed }));


      try
      {
        if (_command != null)
        {
          try
          {







>
>
>
>
|
|
|
|
|
>







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
    /// <summary>
    /// Closes the datareader, potentially closing the connection as well if CommandBehavior.CloseConnection was specified.
    /// </summary>
    public override void Close()
    {
      CheckDisposed();

      SQLiteConnection connection = GetConnection(this);

      if (SQLiteConnection.CanOnChanged(connection))
      {
          SQLiteConnection.OnChanged(connection,
              new ConnectionEventArgs(SQLiteConnectionEventType.ClosingDataReader,
              null, null, _command, this, null, null, new object[] { _commandBehavior,
              _readingState, _rowsAffected, _stepCount, _fieldCount, _disposeCommand,
              _throwOnDisposed }));
      }

      try
      {
        if (_command != null)
        {
          try
          {

Added Tests/pst-25cafb35e5.eagle.



































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
###############################################################################
#
# pst-25cafb35e5.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

proc getChangedCounts {} {
  return [list \
      hit [object invoke -flags +NonPublic \
          System.Data.SQLite.SQLiteConnection \
          _onChangedHit] \
      miss [object invoke -flags +NonPublic \
          System.Data.SQLite.SQLiteConnection \
          _onChangedMiss] \
      data [object invoke \
          System.Data.SQLite.ConnectionEventArgs \
          CreateCount]]
}

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

proc subtractChangedCounts { dict1 dict2 } {
  set result [list]

  foreach name [list hit miss data] {
    set count1 [getDictionaryValue $dict1 $name]
    set count2 [getDictionaryValue $dict2 $name]

    lappend result $name [expr {$count2 - $count1}]
  }

  return $result
}

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

runTest {test pst-25cafb35e5-1.1 {without Changed events} -body {
  set result [list]
  set counts(before) [getChangedCounts]

  setupDb [set fileName pst-25cafb35e5-1.1.db]

  sql execute $db {
    CREATE TABLE t1(x TEXT);
    INSERT INTO t1 (x) VALUES('1');
    INSERT INTO t1 (x) VALUES('2');
    INSERT INTO t1 (x) VALUES('3');
  }

  lappend result [sql execute -execute reader -format list -- \
      $db {SELECT x FROM t1 ORDER BY x;}]

  cleanupDb $fileName

  set counts(after) [getChangedCounts]

  list $result [subtractChangedCounts $counts(before) $counts(after)]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result counts fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -result {{{1 2 3}} {hit 0 miss 35 data 0}}}

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

runTest {test pst-25cafb35e5-1.2 {with Changed events} -setup {
  proc onChanged { sender e } {
    #
    # NOTE: For the purposes of this issue, there isn't a pressing
    #       need to do anything specific here; however, keep track
    #       of the event type for additional verification that the
    #       correct set of events is still being fired.
    #
    lappend ::result [$e EventType]
  }

  set callback onChanged
  object invoke System.Data.SQLite.SQLiteConnection add_Changed $callback
} -body {
  set result [list]
  set counts(before) [getChangedCounts]

  setupDb [set fileName pst-25cafb35e5-1.2.db]

  sql execute $db {
    CREATE TABLE t1(x TEXT);
    INSERT INTO t1 (x) VALUES('1');
    INSERT INTO t1 (x) VALUES('2');
    INSERT INTO t1 (x) VALUES('3');
  }

  lappend result [sql execute -execute reader -format list -- \
      $db {SELECT x FROM t1 ORDER BY x;}]

  cleanupDb $fileName

  set counts(after) [getChangedCounts]

  list $result [subtractChangedCounts $counts(before) $counts(after)]
} -cleanup {
  object invoke System.Data.SQLite.SQLiteConnection remove_Changed $callback
  catch {object removecallback $callback}

  cleanupDb $fileName

  unset -nocomplain callback result counts fileName

  rename onChanged ""
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -result {{Opening Closing NothingToDo Closed\
ConnectionStringPreview ConnectionString NewCriticalHandle NewCommand\
DisposingCommand Opened NewCommand SqlStringPreview NewDataReader\
NewCriticalHandle DisposingDataReader ClosingDataReader DisposingCommand\
NewCommand SqlStringPreview NewDataReader NewCriticalHandle NewCriticalHandle\
NewCriticalHandle NewCriticalHandle DisposingDataReader ClosingDataReader\
DisposingCommand NewCommand SqlStringPreview NewDataReader NewCriticalHandle\
ClosingDataReader DisposingCommand {1 2 3} Closing Closed} {hit 35 miss 0 data\
35}}}

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

rename subtractChangedCounts ""
rename getChangedCounts ""

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

runSQLiteTestEpilogue
runTestEpilogue

Changes to readme.htm.

210
211
212
213
214
215
216

217
218
219
220
221
222
223
<p>
    <b>1.0.119.0 - May XX, 2024 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to <a href="https://www.sqlite.org/releaselog/3_45_3.html">SQLite 3.45.3</a>.</li>
    <li>Update internal resource list of reserved SQL words.</li>
    <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post [66a0d2716a].</li>

    <li>Add the VfsName connection string property.</li>
    <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
    <li>Revise the calculation used to bind DateTime values. Fix for [bbddfeb773].</li>
    <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post [76cb35b58d].</li>
</ul>
<p>
    <b>1.0.118.0 - June 10, 2023</b>







>







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
<p>
    <b>1.0.119.0 - May XX, 2024 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to <a href="https://www.sqlite.org/releaselog/3_45_3.html">SQLite 3.45.3</a>.</li>
    <li>Update internal resource list of reserved SQL words.</li>
    <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post [66a0d2716a].</li>
    <li>Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post [25cafb35e5].</li>
    <li>Add the VfsName connection string property.</li>
    <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
    <li>Revise the calculation used to bind DateTime values. Fix for [bbddfeb773].</li>
    <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post [76cb35b58d].</li>
</ul>
<p>
    <b>1.0.118.0 - June 10, 2023</b>

Changes to www/news.wiki.

57
58
59
60
61
62
63

64
65
66
67
68
69
70
<p>
    <b>1.0.119.0 - May XX, 2024 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to [https://www.sqlite.org/releaselog/3_45_3.html|SQLite 3.45.3].</li>
    <li>Update internal resource list of reserved SQL words.</li>
    <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/66a0d2716a|66a0d2716a].</li>

    <li>Add the VfsName connection string property.</li>
    <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
    <li>Revise the calculation used to bind DateTime values. Fix for [bbddfeb773].</li>
    <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/76cb35b58d|76cb35b58d].</li>
</ul>
<p>
    <b>1.0.118.0 - June 10, 2023</b>







>







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<p>
    <b>1.0.119.0 - May XX, 2024 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to [https://www.sqlite.org/releaselog/3_45_3.html|SQLite 3.45.3].</li>
    <li>Update internal resource list of reserved SQL words.</li>
    <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/66a0d2716a|66a0d2716a].</li>
    <li>Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/25cafb35e5|25cafb35e5]</a>.</li>
    <li>Add the VfsName connection string property.</li>
    <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
    <li>Revise the calculation used to bind DateTime values. Fix for [bbddfeb773].</li>
    <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/76cb35b58d|76cb35b58d].</li>
</ul>
<p>
    <b>1.0.118.0 - June 10, 2023</b>