System.Data.SQLite

Check-in [54ebb78b16]
Login

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
Timelines: family | ancestors | descendants | both | preRelease
Files: files | file ages | folders
SHA1: 54ebb78b1681dcf0cb8ab02c9a556fad5a059a37
User & Date: mistachkin 2018-08-07 00:06:36.823
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
Side-by-Side Diff 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
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
3410
3411
3412
3413
3414
3415
3416


3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432







-
-
+
+



+


+








        #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.
        /// 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

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

3590
3591
3592
3593
3594
3595
3596

3597







3598
3599
3600
3601
3602
3603
3604
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614







+

+
+
+
+
+
+
+







        /// </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
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
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



-
+














-
+







/********************************************************
 * 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 
  /// 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)
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
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







-
+



-
+



-
+



-
+



-
+



-
+


-
-
+
+



-
+



-
+



-
+



-
+







-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+




-
+




-
+



-
+



-
+








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

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

      total++;
      try { DataTypeTest(cnn); frm.WriteLine("SUCCESS - DataType Test"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - DataType Test"); failed++; }
      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) { frm.WriteLine("FAIL - Full Text Search"); failed++; }
      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) { frm.WriteLine("FAIL - KeyInfo Fetch"); failed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - KeyInfo Fetch: {0}", e)); failed++; }

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

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

      total++;
      try { CoersionTest(cnn); frm.WriteLine("FAIL - CoersionTest"); failed++; }
      catch (Exception) { frm.WriteLine("SUCCESS - CoersionTest"); passed++; }
      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) { frm.WriteLine("FAIL - ParameterizedInsert"); failed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - ParameterizedInsert: {0}", e)); failed++; }

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

      total++;
      try { VerifyBinaryData(cnn); frm.WriteLine("SUCCESS - VerifyBinaryData"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - VerifyBinaryData"); failed++; }
      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) { frm.WriteLine("FAIL - LockTest"); failed++; }
      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) { frm.WriteLine("FAIL - InsertMany"); failed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - InsertMany: {0}", e)); failed++; }

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

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

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

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

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

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

      total++;
      try { Int64Properties(cnn); frm.WriteLine("SUCCESS - Int64Properties"); passed++; }
      catch (Exception) { frm.WriteLine("FAIL - Int64Properties"); failed++; }
      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) { frm.WriteLine("FAIL - ManagedVirtualTable"); failed++; }
      catch (Exception e) { frm.WriteLine(String.Format("FAIL - ManagedVirtualTable: {0}", e)); failed++; }
#endif

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

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

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

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

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

      WriteMemoryStatistics(true);
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
584
585
586
587
588
589
590

591
592
593
594
595
596
597
598







-
+







            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)
    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())
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1022







-
+








    // 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 
        // 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");
      }
    }