System.Data.SQLite
Check-in [54ebb78b16]
Not logged in

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

Overview
Comment:Fix issue with P/Invoke portability to Windows CE by wrapping sqlite3_msize() on that platform. Enhance tests.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | preRelease
Files: files | file ages | folders
SHA1:54ebb78b1681dcf0cb8ab02c9a556fad5a059a37
User & Date: mistachkin 2018-08-07 00:06:36
Context
2018-08-07
00:11
Update SQLite core library docs from upstream. Update version history docs. check-in: 4642ef13b9 user: mistachkin tags: preRelease
00:06
Fix issue with P/Invoke portability to Windows CE by wrapping sqlite3_msize() on that platform. Enhance tests. check-in: 54ebb78b16 user: mistachkin tags: preRelease
2018-08-06
11:16
Update version history docs. check-in: 66c7e0e130 user: mistachkin tags: preRelease
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to SQLite.Interop/src/generic/interop.c.

246
247
248
249
250
251
252






253
254
255
256
257
258
259
  sqlite3InteropDebug("INTEROP_LOG (%d) %s\n", iCode, zMsg);
}
#endif

SQLITE_API int WINAPI sqlite3_malloc_size_interop(void *p){
  return sqlite3MallocSize(p);
}







#if defined(INTEROP_LEGACY_CLOSE) || SQLITE_VERSION_NUMBER < 3007014
SQLITE_PRIVATE void * sqlite3DbMallocZero_interop(sqlite3 *db, int n)
{
  void *p;
  if (db) {
    sqlite3_mutex_enter(db->mutex);







>
>
>
>
>
>







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  sqlite3InteropDebug("INTEROP_LOG (%d) %s\n", iCode, zMsg);
}
#endif

SQLITE_API int WINAPI sqlite3_malloc_size_interop(void *p){
  return sqlite3MallocSize(p);
}

SQLITE_API void WINAPI sqlite3_msize_interop(void *p, sqlite_uint64 *pN)
{
  if (!pN) return;
  *pN = sqlite3_msize(p);
}

#if defined(INTEROP_LEGACY_CLOSE) || SQLITE_VERSION_NUMBER < 3007014
SQLITE_PRIVATE void * sqlite3DbMallocZero_interop(sqlite3 *db, int n)
{
  void *p;
  if (db) {
    sqlite3_mutex_enter(db->mutex);

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

3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421

3422
3423

3424
3425
3426
3427
3428
3429
3430
....
3590
3591
3592
3593
3594
3595
3596

3597







3598
3599
3600
3601
3602
3603
3604

        #region Memory Version Helper Methods
        /// <summary>
        /// Determines if the native sqlite3_msize() API can be used, based on
        /// the available version of the SQLite core library.
        /// </summary>
        /// <returns>
        /// Non-zero if the native sqlite3_msize() API property is supported
        /// by the SQLite core library.
        /// </returns>
        private static bool CanUseSize64()
        {

            if (UnsafeNativeMethods.sqlite3_libversion_number() >= 3008007)
                return true;


            return false;
        }
        #endregion

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

................................................................................
        /// </returns>
        public static ulong Size64(IntPtr pMemory)
        {
#if DEBUG
            SQLiteMarshal.CheckAlignment("Size64", pMemory, 0, IntPtr.Size);
#endif


            return UnsafeNativeMethods.sqlite3_msize(pMemory);







        }

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

        /// <summary>
        /// Frees a memory block previously obtained from the
        /// <see cref="Allocate" /> or <see cref="Allocate64" /> methods.  If







|
|



>


>







 







>

>
>
>
>
>
>
>







3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
....
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614

        #region Memory Version Helper Methods
        /// <summary>
        /// Determines if the native sqlite3_msize() API can be used, based on
        /// the available version of the SQLite core library.
        /// </summary>
        /// <returns>
        /// Non-zero if the native sqlite3_msize() API is supported by the
        /// SQLite core library.
        /// </returns>
        private static bool CanUseSize64()
        {
#if !PLATFORM_COMPACTFRAMEWORK || !SQLITE_STANDARD
            if (UnsafeNativeMethods.sqlite3_libversion_number() >= 3008007)
                return true;
#endif

            return false;
        }
        #endregion

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

................................................................................
        /// </returns>
        public static ulong Size64(IntPtr pMemory)
        {
#if DEBUG
            SQLiteMarshal.CheckAlignment("Size64", pMemory, 0, IntPtr.Size);
#endif

#if !PLATFORM_COMPACTFRAMEWORK
            return UnsafeNativeMethods.sqlite3_msize(pMemory);
#elif !SQLITE_STANDARD
            ulong size = 0;
            UnsafeNativeMethods.sqlite3_msize_interop(pMemory, ref size);
            return size;
#else
            throw new NotImplementedException();
#endif
        }

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

        /// <summary>
        /// Frees a memory block previously obtained from the
        /// <see cref="Allocate" /> or <see cref="Allocate64" /> methods.  If

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

4776
4777
4778
4779
4780
4781
4782



4783
4784
4785
4786
4787
4788
4789

    [DllImport(SQLITE_DLL)]
    internal static extern void sqlite3_result_double_interop(IntPtr context, ref double value);

    [DllImport(SQLITE_DLL)]
    internal static extern void sqlite3_result_int64_interop(IntPtr context, ref Int64 value);




    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_create_disposable_module_interop(
        IntPtr db, IntPtr name, IntPtr pModule, int iVersion, xCreate xCreate,
        xConnect xConnect, xBestIndex xBestIndex, xDisconnect xDisconnect,
        xDestroy xDestroy, xOpen xOpen, xClose xClose, xFilter xFilter,
        xNext xNext, xEof xEof, xColumn xColumn, xRowId xRowId, xUpdate xUpdate,
        xBegin xBegin, xSync xSync, xCommit xCommit, xRollback xRollback,







>
>
>







4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792

    [DllImport(SQLITE_DLL)]
    internal static extern void sqlite3_result_double_interop(IntPtr context, ref double value);

    [DllImport(SQLITE_DLL)]
    internal static extern void sqlite3_result_int64_interop(IntPtr context, ref Int64 value);

    [DllImport(SQLITE_DLL)]
    internal static extern void sqlite3_msize_interop(IntPtr p, ref ulong size);

    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_create_disposable_module_interop(
        IntPtr db, IntPtr name, IntPtr pModule, int iVersion, xCreate xCreate,
        xConnect xConnect, xBestIndex xBestIndex, xDisconnect xDisconnect,
        xDestroy xDestroy, xOpen xOpen, xClose xClose, xFilter xFilter,
        xNext xNext, xEof xEof, xColumn xColumn, xRowId xRowId, xUpdate xUpdate,
        xBegin xBegin, xSync xSync, xCommit xCommit, xRollback xRollback,

Changes to testce/TestCases.cs.

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
...
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
...
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data;
................................................................................
using System.Data.SQLite;
using System.Threading;

namespace test
{

  /// <summary>
  /// Scalar user-defined function.  In this example, the same class is declared twice with 
  /// different function names to demonstrate how to use alias names for user-defined functions.
  /// </summary>
  [SQLiteFunction(Name = "Foo", Arguments = 2, FuncType = FunctionType.Scalar)]
  [SQLiteFunction(Name = "TestFunc", Arguments = 2, FuncType = FunctionType.Scalar)]
  class TestFunc : SQLiteFunction
  {
    public override object Invoke(object[] args)
................................................................................

          WriteMemoryStatistics(false);
          frm.WriteLine(String.Empty);
      }

      total++;
      try { CreateTable(cnn); frm.WriteLine("SUCCESS - CreateTable"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - CreateTable"); failed++; }

      total++;
      try { DataTypeTest(cnn); frm.WriteLine("SUCCESS - DataType Test"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - DataType Test"); failed++; }

      total++;
      try { FullTextTest(cnn); frm.WriteLine("SUCCESS - Full Text Search"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - Full Text Search"); failed++; }

      total++;
      try { KeyInfoTest(cnn); frm.WriteLine("SUCCESS - KeyInfo Fetch"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - KeyInfo Fetch"); failed++; }

      total++;
      try { InsertTable(cnn); frm.WriteLine("SUCCESS - InsertTable"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - InsertTable"); failed++; }

      total++;
      try { VerifyInsert(cnn); frm.WriteLine("SUCCESS - VerifyInsert"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - VerifyInsert"); failed++; }

      total++;
      try { CoersionTest(cnn); frm.WriteLine("FAIL - CoersionTest"); failed++; }
      catch (Exception) { frm.WriteLine("SUCCESS - CoersionTest"); passed++; }

      total++;
      try { ParameterizedInsert(cnn); frm.WriteLine("SUCCESS - ParameterizedInsert"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - ParameterizedInsert"); failed++; }

      total++;
      try { BinaryInsert(cnn); frm.WriteLine("SUCCESS - BinaryInsert"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - BinaryInsert"); failed++; }

      total++;
      try { VerifyBinaryData(cnn); frm.WriteLine("SUCCESS - VerifyBinaryData"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - VerifyBinaryData"); failed++; }

      total++;
      try { LockTest(cnn, sql, isolatedSql); frm.WriteLine("SUCCESS - LockTest"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - LockTest"); failed++; }

      total++;
      try { ParameterizedInsertMissingParams(cnn); frm.WriteLine("FAIL - ParameterizedInsertMissingParams"); failed++; }
      catch (Exception) { frm.WriteLine("SUCCESS - ParameterizedInsertMissingParams"); passed++; }

      total++;
      try { InsertMany(cnn, false); frm.WriteLine("SUCCESS - InsertMany"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - InsertMany"); failed++; }

      total++;
      try { InsertMany(cnn, true); frm.WriteLine("SUCCESS - InsertManyWithIdentityFetch"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - InsertManyWithIdentityFetch"); failed++; }

      total++;
      try { FastInsertMany(cnn); frm.WriteLine("SUCCESS - FastInsertMany"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - FastInsertMany"); failed++; }

      total++;
      try { IterationTest(cnn); frm.WriteLine("SUCCESS - Iteration Test"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - Iteration Test"); failed++; }

      total++;
      try { UserFunction(cnn); frm.WriteLine("SUCCESS - UserFunction"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - UserFunction"); failed++; }

      total++;
      try { UserAggregate(cnn); frm.WriteLine("SUCCESS - UserAggregate"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - UserAggregate"); failed++; }

      total++;
      try { UserCollation(cnn); frm.WriteLine("SUCCESS - UserCollation"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - UserCollation"); failed++; }

      total++;
      try { Int64Properties(cnn); frm.WriteLine("SUCCESS - Int64Properties"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - Int64Properties"); failed++; }

#if INTEROP_VIRTUAL_TABLE
      total++;
      try { ManagedVirtualTable(cnn); frm.WriteLine("SUCCESS - ManagedVirtualTable"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - ManagedVirtualTable"); failed++; }
#endif

      total++;
      try { MultipleThreadStress(cnn); frm.WriteLine("SUCCESS - MultipleThreadStress"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - MultipleThreadStress"); failed++; }

      total++;
      try { SimpleRTree(cnn); frm.WriteLine("SUCCESS - SimpleRTree"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - SimpleRTree"); failed++; }

      total++;
      try { DropTable(cnn); frm.WriteLine("SUCCESS - DropTable"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - DropTable"); failed++; }

      frm.WriteLine("\r\nTests Finished.");

      if (cnn2 != null)
          cnn2.Close();

      WriteMemoryStatistics(true);
................................................................................
            if (Field5.CompareTo(DateTime.Parse("2005-01-01 13:49:00")) != 0) throw new ArgumentOutOfRangeException("Non-Match on Field5");
          }
          else throw new ArgumentOutOfRangeException("No data in table");
        }
      }
    }

    internal void CoersionTest(DbConnection cnn)
    {
      using (DbCommand cmd = cnn.CreateCommand())
      {
        cmd.CommandText = "SELECT Field1, Field2, Field3, Field4, Field5, 'A', 1, 1 + 1, 3.14159 FROM TestCase";
        using (DbDataReader rd = cmd.ExecuteReader())
        {
          if (rd.Read())
................................................................................

    // Causes the user-defined collation sequence to be iterated through
    internal void UserCollation(DbConnection cnn)
    {
      using (DbCommand cmd = cnn.CreateCommand())
      {
        // Using a default collating sequence in descending order, "Param Field3" will appear at the top
        // and "Field3" will be next, followed by a NULL.  Our user-defined collating sequence will 
        // deliberately place them out of order so Field3 is first.
        cmd.CommandText = "SELECT Field3 FROM TestCase ORDER BY Field3 COLLATE MYSEQUENCE DESC";
        string s = (string)cmd.ExecuteScalar();
        if (s != "Field3") throw new ArgumentOutOfRangeException("MySequence didn't sort properly");
      }
    }




|







 







|







 







|



|



|



|



|



|


|
|



|



|



|



|







|



|



|



|



|



|



|



|




|




|



|



|







 







|







 







|







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
...
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
...
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 *
 * Released to the public domain, use at your own risk!
 ********************************************************/

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data;
................................................................................
using System.Data.SQLite;
using System.Threading;

namespace test
{

  /// <summary>
  /// Scalar user-defined function.  In this example, the same class is declared twice with
  /// different function names to demonstrate how to use alias names for user-defined functions.
  /// </summary>
  [SQLiteFunction(Name = "Foo", Arguments = 2, FuncType = FunctionType.Scalar)]
  [SQLiteFunction(Name = "TestFunc", Arguments = 2, FuncType = FunctionType.Scalar)]
  class TestFunc : SQLiteFunction
  {
    public override object Invoke(object[] args)
................................................................................

          WriteMemoryStatistics(false);
          frm.WriteLine(String.Empty);
      }

      total++;
      try { CreateTable(cnn); frm.WriteLine("SUCCESS - CreateTable"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - CreateTable: {0}", e)); failed++; }

      total++;
      try { DataTypeTest(cnn); frm.WriteLine("SUCCESS - DataType Test"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - DataType Test: {0}", e)); failed++; }

      total++;
      try { FullTextTest(cnn); frm.WriteLine("SUCCESS - Full Text Search"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - Full Text Search: {0}", e)); failed++; }

      total++;
      try { KeyInfoTest(cnn); frm.WriteLine("SUCCESS - KeyInfo Fetch"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - KeyInfo Fetch: {0}", e)); failed++; }

      total++;
      try { InsertTable(cnn); frm.WriteLine("SUCCESS - InsertTable"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - InsertTable: {0}", e)); failed++; }

      total++;
      try { VerifyInsert(cnn); frm.WriteLine("SUCCESS - VerifyInsert"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - VerifyInsert: {0}", e)); failed++; }

      total++;
      try { CoercionTest(cnn); frm.WriteLine("FAIL - CoercionTest"); failed++; }
      catch (Exception) { frm.WriteLine("SUCCESS - CoercionTest"); passed++; }

      total++;
      try { ParameterizedInsert(cnn); frm.WriteLine("SUCCESS - ParameterizedInsert"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - ParameterizedInsert: {0}", e)); failed++; }

      total++;
      try { BinaryInsert(cnn); frm.WriteLine("SUCCESS - BinaryInsert"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - BinaryInsert: {0}", e)); failed++; }

      total++;
      try { VerifyBinaryData(cnn); frm.WriteLine("SUCCESS - VerifyBinaryData"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - VerifyBinaryData: {0}", e)); failed++; }

      total++;
      try { LockTest(cnn, sql, isolatedSql); frm.WriteLine("SUCCESS - LockTest"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - LockTest: {0}", e)); failed++; }

      total++;
      try { ParameterizedInsertMissingParams(cnn); frm.WriteLine("FAIL - ParameterizedInsertMissingParams"); failed++; }
      catch (Exception) { frm.WriteLine("SUCCESS - ParameterizedInsertMissingParams"); passed++; }

      total++;
      try { InsertMany(cnn, false); frm.WriteLine("SUCCESS - InsertMany"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - InsertMany: {0}", e)); failed++; }

      total++;
      try { InsertMany(cnn, true); frm.WriteLine("SUCCESS - InsertManyWithIdentityFetch"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - InsertManyWithIdentityFetch: {0}", e)); failed++; }

      total++;
      try { FastInsertMany(cnn); frm.WriteLine("SUCCESS - FastInsertMany"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - FastInsertMany: {0}", e)); failed++; }

      total++;
      try { IterationTest(cnn); frm.WriteLine("SUCCESS - Iteration Test"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - Iteration Test: {0}", e)); failed++; }

      total++;
      try { UserFunction(cnn); frm.WriteLine("SUCCESS - UserFunction"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - UserFunction: {0}", e)); failed++; }

      total++;
      try { UserAggregate(cnn); frm.WriteLine("SUCCESS - UserAggregate"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - UserAggregate: {0}", e)); failed++; }

      total++;
      try { UserCollation(cnn); frm.WriteLine("SUCCESS - UserCollation"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - UserCollation: {0}", e)); failed++; }

      total++;
      try { Int64Properties(cnn); frm.WriteLine("SUCCESS - Int64Properties"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - Int64Properties: {0}", e)); failed++; }

#if INTEROP_VIRTUAL_TABLE
      total++;
      try { ManagedVirtualTable(cnn); frm.WriteLine("SUCCESS - ManagedVirtualTable"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - ManagedVirtualTable: {0}", e)); failed++; }
#endif

      total++;
      try { MultipleThreadStress(cnn); frm.WriteLine("SUCCESS - MultipleThreadStress"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - MultipleThreadStress: {0}", e)); failed++; }

      total++;
      try { SimpleRTree(cnn); frm.WriteLine("SUCCESS - SimpleRTree"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - SimpleRTree: {0}", e)); failed++; }

      total++;
      try { DropTable(cnn); frm.WriteLine("SUCCESS - DropTable"); passed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - DropTable: {0}", e)); failed++; }

      frm.WriteLine("\r\nTests Finished.");

      if (cnn2 != null)
          cnn2.Close();

      WriteMemoryStatistics(true);
................................................................................
            if (Field5.CompareTo(DateTime.Parse("2005-01-01 13:49:00")) != 0) throw new ArgumentOutOfRangeException("Non-Match on Field5");
          }
          else throw new ArgumentOutOfRangeException("No data in table");
        }
      }
    }

    internal void CoercionTest(DbConnection cnn)
    {
      using (DbCommand cmd = cnn.CreateCommand())
      {
        cmd.CommandText = "SELECT Field1, Field2, Field3, Field4, Field5, 'A', 1, 1 + 1, 3.14159 FROM TestCase";
        using (DbDataReader rd = cmd.ExecuteReader())
        {
          if (rd.Read())
................................................................................

    // Causes the user-defined collation sequence to be iterated through
    internal void UserCollation(DbConnection cnn)
    {
      using (DbCommand cmd = cnn.CreateCommand())
      {
        // Using a default collating sequence in descending order, "Param Field3" will appear at the top
        // and "Field3" will be next, followed by a NULL.  Our user-defined collating sequence will
        // deliberately place them out of order so Field3 is first.
        cmd.CommandText = "SELECT Field3 FROM TestCase ORDER BY Field3 COLLATE MYSEQUENCE DESC";
        string s = (string)cmd.ExecuteScalar();
        if (s != "Field3") throw new ArgumentOutOfRangeException("MySequence didn't sort properly");
      }
    }