System.Data.SQLite

Check-in [937230cef0]
Login

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

Overview
Comment:Experimental changes to permit the unit test suite to pass with the debug version of SQLite.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | debugInteropFix
Files: files | file ages | folders
SHA1: 937230cef025187422b69e4d7bed7aa26bfa2b1a
User & Date: mistachkin 2011-07-22 23:13:38.445
Context
2011-07-23
00:57
Update SQLite core to latest. Closed-Leaf check-in: ecfb121b6e user: mistachkin tags: debugInteropFix
2011-07-22
23:13
Experimental changes to permit the unit test suite to pass with the debug version of SQLite. check-in: 937230cef0 user: mistachkin tags: debugInteropFix
21:21
Fix issue with building in a Visual Studio Command Prompt window. Support building and testing the VS2010 projects using the .NET Framework 3.5. check-in: a912d7f434 user: mistachkin tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to SQLite.Interop/src/win/crypt.c.
335
336
337
338
339
340
341


342
343
344
345
346
347
348
    //db->aDb[0].xFreeAux = DestroyCryptBlock;
  }
  else // Change the writekey for an already-encrypted database
  {
    pBlock->hWriteKey = hKey;
  }



  // Start a transaction
  rc = sqlite3BtreeBeginTrans(pbt, 1);

  if (!rc)
  {
    // Rewrite all the pages in the database using the new encryption key
    Pgno nPage;







>
>







335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
    //db->aDb[0].xFreeAux = DestroyCryptBlock;
  }
  else // Change the writekey for an already-encrypted database
  {
    pBlock->hWriteKey = hKey;
  }

  sqlite3_mutex_enter(db->mutex);

  // Start a transaction
  rc = sqlite3BtreeBeginTrans(pbt, 1);

  if (!rc)
  {
    // Rewrite all the pages in the database using the new encryption key
    Pgno nPage;
401
402
403
404
405
406
407


408
409
410
411
412
413
414

  // If the readkey and writekey are both empty, there's no need for a codec on this
  // pager anymore.  Destroy the crypt block and remove the codec from the pager.
  if (!pBlock->hReadKey && !pBlock->hWriteKey)
  {
    sqlite3PagerSetCodec(p, NULL, NULL, NULL, NULL);
  }



  return rc;
}

#endif // SQLITE_HAS_CODEC

#endif // SQLITE_OMIT_DISKIO







>
>







403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418

  // If the readkey and writekey are both empty, there's no need for a codec on this
  // pager anymore.  Destroy the crypt block and remove the codec from the pager.
  if (!pBlock->hReadKey && !pBlock->hWriteKey)
  {
    sqlite3PagerSetCodec(p, NULL, NULL, NULL, NULL);
  }

  sqlite3_mutex_leave(db->mutex);

  return rc;
}

#endif // SQLITE_HAS_CODEC

#endif // SQLITE_OMIT_DISKIO
Changes to SQLite.Interop/src/win/interop.c.
8
9
10
11
12
13
14



























15
16
17
18
19
20
21
#ifdef SQLITE_OS_WIN

// Additional open flags, we use this one privately
//#define SQLITE_OPEN_SHAREDCACHE      0x01000000

typedef void (*SQLITEUSERFUNC)(sqlite3_context *, int, sqlite3_value **);
typedef void (*SQLITEFUNCFINAL)(sqlite3_context *);




























/*
    The goal of this version of close is different than that of sqlite3_close(), and is designed to lend itself better to .NET's non-deterministic finalizers and
    the GC thread.  SQLite will not close a database if statements are open on it -- but for our purposes, we'd rather finalize all active statements
    and forcibly close the database.  The reason is simple -- a lot of people don't Dispose() of their objects correctly and let the garbage collector
    do it.  This leads to unexpected behavior when a user thinks they've closed a database, but it's still open because not all the statements have
    hit the GC yet.







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







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
#ifdef SQLITE_OS_WIN

// Additional open flags, we use this one privately
//#define SQLITE_OPEN_SHAREDCACHE      0x01000000

typedef void (*SQLITEUSERFUNC)(sqlite3_context *, int, sqlite3_value **);
typedef void (*SQLITEFUNCFINAL)(sqlite3_context *);

__declspec(dllexport) void * WINAPI sqlite3DbMallocZero_interop(sqlite3 *db, int n)
{
  void *p;
  if (db) {
    sqlite3_mutex_enter(db->mutex);
  }
  p = sqlite3DbMallocZero(db,n);
  if (db) {
    sqlite3_mutex_leave(db->mutex);
  }
  return p;
}

__declspec(dllexport) void sqlite3DbFree_interop(sqlite3 *db, void *p)
{
  if (db) {
    sqlite3_mutex_enter(db->mutex);
  }
  if (p) {
    sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
  }
  sqlite3DbFree(db,p);
  if (db) {
    sqlite3_mutex_leave(db->mutex);
  }
}

/*
    The goal of this version of close is different than that of sqlite3_close(), and is designed to lend itself better to .NET's non-deterministic finalizers and
    the GC thread.  SQLite will not close a database if statements are open on it -- but for our purposes, we'd rather finalize all active statements
    and forcibly close the database.  The reason is simple -- a lot of people don't Dispose() of their objects correctly and let the garbage collector
    do it.  This leads to unexpected behavior when a user thinks they've closed a database, but it's still open because not all the statements have
    hit the GC yet.
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  ret = sqlite3_close(db);

  if (ret == SQLITE_BUSY && db->pVdbe)
  {
    while (db->pVdbe)
    {
      // Make a copy of the first prepared statement
      Vdbe *p = (Vdbe *)sqlite3_malloc(sizeof(Vdbe));
      Vdbe *po = db->pVdbe;

      if (!p) 
      {
        ret = SQLITE_NOMEM;
        break;
      }







|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  ret = sqlite3_close(db);

  if (ret == SQLITE_BUSY && db->pVdbe)
  {
    while (db->pVdbe)
    {
      // Make a copy of the first prepared statement
      Vdbe *p = (Vdbe *)sqlite3DbMallocZero_interop(db, sizeof(Vdbe));
      Vdbe *po = db->pVdbe;

      if (!p) 
      {
        ret = SQLITE_NOMEM;
        break;
      }
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

  p = (Vdbe *)stmt;
  if (p && p->magic == VDBE_MAGIC_DEAD)
  {
    db = p->db;
    if (db == NULL)
    {
      sqlite3_free(p);
      ret = SQLITE_OK;
    }
  }
  else
    ret = sqlite3_finalize(stmt);

  return ret;







|







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

  p = (Vdbe *)stmt;
  if (p && p->magic == VDBE_MAGIC_DEAD)
  {
    db = p->db;
    if (db == NULL)
    {
      sqlite3DbFree_interop(db, p);
      ret = SQLITE_OK;
    }
  }
  else
    ret = sqlite3_finalize(stmt);

  return ret;
361
362
363
364
365
366
367




368




369
370
371
372
373
374
375
}

__declspec(dllexport) int WINAPI sqlite3_index_column_info_interop(sqlite3 *db, const char *zDb, const char *zIndexName, const char *zColumnName, int *sortOrder, int *onError, char **pzColl, int *plen)
{
  Index *pIdx;
  Table *pTab;
  int n;




  pIdx = sqlite3FindIndex(db, zIndexName, zDb);




  if (!pIdx) return SQLITE_ERROR;

  pTab = pIdx->pTable;
  for (n = 0; n < pIdx->nColumn; n++)
  {
    int cnum = pIdx->aiColumn[n];
    if (sqlite3StrICmp(pTab->aCol[cnum].zName, zColumnName) == 0)







>
>
>
>

>
>
>
>







388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
}

__declspec(dllexport) int WINAPI sqlite3_index_column_info_interop(sqlite3 *db, const char *zDb, const char *zIndexName, const char *zColumnName, int *sortOrder, int *onError, char **pzColl, int *plen)
{
  Index *pIdx;
  Table *pTab;
  int n;

  sqlite3_mutex_enter(db->mutex);
  sqlite3BtreeEnterAll(db);

  pIdx = sqlite3FindIndex(db, zIndexName, zDb);

  sqlite3BtreeLeaveAll(db);
  sqlite3_mutex_leave(db->mutex);

  if (!pIdx) return SQLITE_ERROR;

  pTab = pIdx->pTable;
  for (n = 0; n < pIdx->nColumn; n++)
  {
    int cnum = pIdx->aiColumn[n];
    if (sqlite3StrICmp(pTab->aCol[cnum].zName, zColumnName) == 0)