/ Check-in [5173b3e8]
Login

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

Overview
Comment:Remove the xGetTempname() method from the vfs structure. Temp files are now opened by passing a NULL pointer as the filename to xOpen(). (CVS 5190)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5173b3e816c7eb711cd21a9068bbafb9ebb7cff1
User & Date: danielk1977 2008-06-06 11:11:26
References
2009-12-08
10:45 Ticket [abe728bb] Crash committing multi-file transaction including temp file status still Open with 3 other changes artifact: 43184db8 user: dan
Context
2008-06-06
15:04
Remove the subroutine return stack from the VDBE. Return addresses for subroutines are now stored in registers. (CVS 5191) check-in: ef1956ee user: drh tags: trunk
11:11
Remove the xGetTempname() method from the vfs structure. Temp files are now opened by passing a NULL pointer as the filename to xOpen(). (CVS 5190) check-in: 5173b3e8 user: danielk1977 tags: trunk
2008-06-05
16:47
Reorganize some of the code that detects expression trees with a depth greater than EXPR_MAX_DEPTH so that they are detected earlier. This further reduces the opportunities for stack overflow. (CVS 5189) check-in: 16d4c53a user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains OS interface code that is common to all
** architectures.
**
** $Id: os.c,v 1.110 2008/06/05 11:39:11 danielk1977 Exp $
*/
#define _SQLITE_OS_C_ 1
#include "sqliteInt.h"
#undef _SQLITE_OS_C_

/*
** The default SQLite sqlite3_vfs implementations do not allocate
................................................................................
  const char *zPath, 
  int flags, 
  int *pResOut
){
  DO_OS_MALLOC_TEST;
  return pVfs->xAccess(pVfs, zPath, flags, pResOut);
}
int sqlite3OsGetTempname(sqlite3_vfs *pVfs, int nBufOut, char *zBufOut){
  return pVfs->xGetTempname(pVfs, nBufOut, zBufOut);
}
int sqlite3OsFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nPathOut, 
  char *zPathOut
){
  return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);







|







 







<
<
<







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
123
124
125
126
127
128
129



130
131
132
133
134
135
136
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains OS interface code that is common to all
** architectures.
**
** $Id: os.c,v 1.111 2008/06/06 11:11:26 danielk1977 Exp $
*/
#define _SQLITE_OS_C_ 1
#include "sqliteInt.h"
#undef _SQLITE_OS_C_

/*
** The default SQLite sqlite3_vfs implementations do not allocate
................................................................................
  const char *zPath, 
  int flags, 
  int *pResOut
){
  DO_OS_MALLOC_TEST;
  return pVfs->xAccess(pVfs, zPath, flags, pResOut);
}



int sqlite3OsFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nPathOut, 
  char *zPathOut
){
  return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);

Changes to src/os_unix.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
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
....
2331
2332
2333
2334
2335
2336
2337

























































2338
2339
2340
2341
2342
2343
2344
....
2379
2380
2381
2382
2383
2384
2385






2386
2387
2388
2389
2390
2391
2392
....
2406
2407
2408
2409
2410
2411
2412










2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
....
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
....
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to Unix systems.
**
** $Id: os_unix.c,v 1.184 2008/06/05 11:39:11 danielk1977 Exp $
*/
#include "sqliteInt.h"
#if OS_UNIX              /* This file is used on unix only */

/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */

/*
................................................................................
*/
static int fillInUnixFile(
  int h,                  /* Open file descriptor of file being opened */
  int dirfd,              /* Directory file descriptor */
  sqlite3_file *pId,      /* Write to the unixFile structure here */
  const char *zFilename   /* Name of the file being opened */
){
  sqlite3LockingStyle lockingStyle;
  unixFile *pNew = (unixFile *)pId;
  int rc;

#ifdef FD_CLOEXEC
  fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC);
#endif









  lockingStyle = sqlite3DetectLockingStyle(zFilename, h);
  if ( lockingStyle==posixLockingStyle ){
    enterMutex();
    rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen);
    leaveMutex();
    if( rc ){
      if( dirfd>=0 ) close(dirfd);
      close(h);
      return rc;
    }
  } else {
    /*  pLock and pOpen are only used for posix advisory locking */
    pNew->pLock = NULL;
    pNew->pOpen = NULL;

  }

  OSTRACE3("OPEN    %-3d %s\n", h, zFilename);    
  pNew->dirfd = -1;
  pNew->h = h;
  pNew->dirfd = dirfd;
  SET_THREADID(pNew);
    
  switch(lockingStyle) {
    case afpLockingStyle: {
      /* afp locking uses the file path so it needs to be included in
................................................................................
#endif
      OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname);
    }
  }
  *pFd = fd;
  return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN);
}


























































/*
** Open the file zPath.
** 
** Previously, the SQLite OS layer used three functions in place of this
** one:
**
................................................................................
  /* If creating a master or main-file journal, this function will open
  ** a file-descriptor on the directory too. The first time unixSync()
  ** is called the directory file descriptor will be fsync()ed and close()d.
  */
  int isOpenDirectory = (isCreate && 
      (eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL)
  );







  /* Check the following statements are true: 
  **
  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
  **   (b) if CREATE is set, then READWRITE must also be set, and
  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
................................................................................

  /* Assert that the upper layer has set one of the "file-type" flags. */
  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
       || eType==SQLITE_OPEN_TRANSIENT_DB
  );











  if( isReadonly )  oflags |= O_RDONLY;
  if( isReadWrite ) oflags |= O_RDWR;
  if( isCreate )    oflags |= O_CREAT;
  if( isExclusive ) oflags |= (O_EXCL|O_NOFOLLOW);
  oflags |= (O_LARGEFILE|O_BINARY);

  memset(pFile, 0, sizeof(unixFile));
  fd = open(zPath, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS);
  if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
    /* Failed to open the file for read/write access. Try read-only. */
    flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
    flags |= SQLITE_OPEN_READONLY;
    return unixOpen(pVfs, zPath, pFile, flags, pOutFlags);
  }
  if( fd<0 ){
    return SQLITE_CANTOPEN;
  }
  if( isDelete ){
    unlink(zPath);
  }
  if( pOutFlags ){
    *pOutFlags = flags;
  }

  assert(fd!=0);
  if( isOpenDirectory ){
................................................................................
    default:
      assert(!"Invalid flags argument");
  }
  *pResOut = (access(zPath, amode)==0);
  return SQLITE_OK;
}

/*
** Create a temporary file name in zBuf.  zBuf must be allocated
** by the calling process and must be big enough to hold at least
** pVfs->mxPathname bytes.
*/
static int unixGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
  static const char *azDirs[] = {
     0,
     "/var/tmp",
     "/usr/tmp",
     "/tmp",
     ".",
  };
  static const unsigned char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;
  struct stat buf;
  const char *zDir = ".";

  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. 
  */
  SimulateIOError( return SQLITE_ERROR );

  azDirs[0] = sqlite3_temp_directory;
  for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
    if( azDirs[i]==0 ) continue;
    if( stat(azDirs[i], &buf) ) continue;
    if( !S_ISDIR(buf.st_mode) ) continue;
    if( access(azDirs[i], 07) ) continue;
    zDir = azDirs[i];
    break;
  }

  /* Check that the output buffer is large enough for the temporary file 
  ** name. If it is not, return SQLITE_ERROR.
  */
  if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){
    return SQLITE_ERROR;
  }

  do{
    assert( pVfs->mxPathname==MAX_PATHNAME );
    sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
    j = strlen(zBuf);
    sqlite3_randomness(15, &zBuf[j]);
    for(i=0; i<15; i++, j++){
      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
    }
    zBuf[j] = 0;
  }while( access(zBuf,0)==0 );
  return SQLITE_OK;
}


/*
** Turn a relative pathname into a full pathname. The relative path
** is stored as a nul-terminated string in the buffer pointed to by
** zPath. 
**
** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes 
................................................................................
    0,                  /* pNext */
    "unix",             /* zName */
    0,                  /* pAppData */
  
    unixOpen,           /* xOpen */
    unixDelete,         /* xDelete */
    unixAccess,         /* xAccess */
    unixGetTempname,    /* xGetTempName */
    unixFullPathname,   /* xFullPathname */
    unixDlOpen,         /* xDlOpen */
    unixDlError,        /* xDlError */
    unixDlSym,          /* xDlSym */
    unixDlClose,        /* xDlClose */
    unixRandomness,     /* xRandomness */
    unixSleep,          /* xSleep */







|







 







|







>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
<
<
<
<
>



<







 







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







 







>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>








|










|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
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
....
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
....
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
....
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
....
2576
2577
2578
2579
2580
2581
2582

























































2583
2584
2585
2586
2587
2588
2589
....
2789
2790
2791
2792
2793
2794
2795

2796
2797
2798
2799
2800
2801
2802
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to Unix systems.
**
** $Id: os_unix.c,v 1.185 2008/06/06 11:11:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#if OS_UNIX              /* This file is used on unix only */

/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */

/*
................................................................................
*/
static int fillInUnixFile(
  int h,                  /* Open file descriptor of file being opened */
  int dirfd,              /* Directory file descriptor */
  sqlite3_file *pId,      /* Write to the unixFile structure here */
  const char *zFilename   /* Name of the file being opened */
){
  sqlite3LockingStyle lockingStyle = noLockingStyle;
  unixFile *pNew = (unixFile *)pId;
  int rc;

#ifdef FD_CLOEXEC
  fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC);
#endif

  assert( pNew->pLock==NULL );
  assert( pNew->pOpen==NULL );
  if( zFilename ){
    /* If zFilename is NULL then this is a temporary file. Temporary files
    ** are never locked or unlocked, so noLockingStyle is used for these.
    ** The locking style used by other files is determined by 
    ** sqlite3DetectLockingStyle().
    */
    lockingStyle = sqlite3DetectLockingStyle(zFilename, h);
    if ( lockingStyle==posixLockingStyle ){
      enterMutex();
      rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen);
      leaveMutex();
      if( rc ){
        if( dirfd>=0 ) close(dirfd);
        close(h);
        return rc;
      }




    }
  }

  OSTRACE3("OPEN    %-3d %s\n", h, zFilename);    

  pNew->h = h;
  pNew->dirfd = dirfd;
  SET_THREADID(pNew);
    
  switch(lockingStyle) {
    case afpLockingStyle: {
      /* afp locking uses the file path so it needs to be included in
................................................................................
#endif
      OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname);
    }
  }
  *pFd = fd;
  return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN);
}

/*
** Create a temporary file name in zBuf.  zBuf must be allocated
** by the calling process and must be big enough to hold at least
** pVfs->mxPathname bytes.
*/
static int getTempname(int nBuf, char *zBuf){
  static const char *azDirs[] = {
     0,
     "/var/tmp",
     "/usr/tmp",
     "/tmp",
     ".",
  };
  static const unsigned char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;
  struct stat buf;
  const char *zDir = ".";

  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. 
  */
  SimulateIOError( return SQLITE_IOERR );

  azDirs[0] = sqlite3_temp_directory;
  for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
    if( azDirs[i]==0 ) continue;
    if( stat(azDirs[i], &buf) ) continue;
    if( !S_ISDIR(buf.st_mode) ) continue;
    if( access(azDirs[i], 07) ) continue;
    zDir = azDirs[i];
    break;
  }

  /* Check that the output buffer is large enough for the temporary file 
  ** name. If it is not, return SQLITE_ERROR.
  */
  if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){
    return SQLITE_ERROR;
  }

  do{
    sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
    j = strlen(zBuf);
    sqlite3_randomness(15, &zBuf[j]);
    for(i=0; i<15; i++, j++){
      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
    }
    zBuf[j] = 0;
  }while( access(zBuf,0)==0 );
  return SQLITE_OK;
}


/*
** Open the file zPath.
** 
** Previously, the SQLite OS layer used three functions in place of this
** one:
**
................................................................................
  /* If creating a master or main-file journal, this function will open
  ** a file-descriptor on the directory too. The first time unixSync()
  ** is called the directory file descriptor will be fsync()ed and close()d.
  */
  int isOpenDirectory = (isCreate && 
      (eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL)
  );

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
  */
  char zTmpname[MAX_PATHNAME+1];
  const char *zName = zPath;

  /* Check the following statements are true: 
  **
  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
  **   (b) if CREATE is set, then READWRITE must also be set, and
  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
................................................................................

  /* Assert that the upper layer has set one of the "file-type" flags. */
  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
       || eType==SQLITE_OPEN_TRANSIENT_DB
  );

  if( !zName ){
    int rc;
    assert(isDelete && !isOpenDirectory);
    rc = getTempname(MAX_PATHNAME+1, zTmpname);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    zName = zTmpname;
  }

  if( isReadonly )  oflags |= O_RDONLY;
  if( isReadWrite ) oflags |= O_RDWR;
  if( isCreate )    oflags |= O_CREAT;
  if( isExclusive ) oflags |= (O_EXCL|O_NOFOLLOW);
  oflags |= (O_LARGEFILE|O_BINARY);

  memset(pFile, 0, sizeof(unixFile));
  fd = open(zName, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS);
  if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
    /* Failed to open the file for read/write access. Try read-only. */
    flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
    flags |= SQLITE_OPEN_READONLY;
    return unixOpen(pVfs, zPath, pFile, flags, pOutFlags);
  }
  if( fd<0 ){
    return SQLITE_CANTOPEN;
  }
  if( isDelete ){
    unlink(zName);
  }
  if( pOutFlags ){
    *pOutFlags = flags;
  }

  assert(fd!=0);
  if( isOpenDirectory ){
................................................................................
    default:
      assert(!"Invalid flags argument");
  }
  *pResOut = (access(zPath, amode)==0);
  return SQLITE_OK;
}



























































/*
** Turn a relative pathname into a full pathname. The relative path
** is stored as a nul-terminated string in the buffer pointed to by
** zPath. 
**
** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes 
................................................................................
    0,                  /* pNext */
    "unix",             /* zName */
    0,                  /* pAppData */
  
    unixOpen,           /* xOpen */
    unixDelete,         /* xDelete */
    unixAccess,         /* xAccess */

    unixFullPathname,   /* xFullPathname */
    unixDlOpen,         /* xDlOpen */
    unixDlError,        /* xDlError */
    unixDlSym,          /* xDlSym */
    unixDlClose,        /* xDlClose */
    unixRandomness,     /* xRandomness */
    unixSleep,          /* xSleep */

Changes to src/os_win.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1069
1070
1071
1072
1073
1074
1075



















































1076
1077
1078
1079
1080
1081
1082
....
1087
1088
1089
1090
1091
1092
1093
















1094
1095
1096
1097
1098
1099
1100
1101
....
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
....
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to windows.
**
** $Id: os_win.c,v 1.124 2008/06/05 11:39:11 danielk1977 Exp $
*/
#include "sqliteInt.h"
#if OS_WIN               /* This file is used for windows only */


/*
** A Note About Memory Allocation:
................................................................................
    zConverted = utf8ToUnicode(zFilename);
  }else{
    zConverted = utf8ToMbcs(zFilename);
  }
  /* caller will handle out of memory */
  return zConverted;
}




















































/*
** Open a file.
*/
static int winOpen(
  sqlite3_vfs *pVfs,        /* Not used */
  const char *zName,        /* Name of the file (UTF-8) */
................................................................................
  HANDLE h;
  DWORD dwDesiredAccess;
  DWORD dwShareMode;
  DWORD dwCreationDisposition;
  DWORD dwFlagsAndAttributes = 0;
  int isTemp;
  winFile *pFile = (winFile*)id;
















  void *zConverted = convertUtf8Filename(zName);
  if( zConverted==0 ){
    return SQLITE_NOMEM;
  }

  if( flags & SQLITE_OPEN_READWRITE ){
    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  }else{
................................................................................
      assert(!"Invalid flags argument");
  }
  *pResOut = rc;
  return SQLITE_OK;
}


/*
** Create a temporary file name in zBuf.  zBuf must be big enough to
** hold at pVfs->mxPathname characters.
*/
static int winGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
  static char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;
  char zTempPath[MAX_PATH+1];
  if( sqlite3_temp_directory ){
    sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
  }else if( isNT() ){
    char *zMulti;
    WCHAR zWidePath[MAX_PATH];
    GetTempPathW(MAX_PATH-30, zWidePath);
    zMulti = unicodeToUtf8(zWidePath);
    if( zMulti ){
      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
      free(zMulti);
    }else{
      return SQLITE_NOMEM;
    }
  }else{
    char *zUtf8;
    char zMbcsPath[MAX_PATH];
    GetTempPathA(MAX_PATH-30, zMbcsPath);
    zUtf8 = mbcsToUtf8(zMbcsPath);
    if( zUtf8 ){
      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
      free(zUtf8);
    }else{
      return SQLITE_NOMEM;
    }
  }
  for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
  zTempPath[i] = 0;
  sqlite3_snprintf(nBuf-30, zBuf,
                   "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
  j = strlen(zBuf);
  sqlite3_randomness(20, &zBuf[j]);
  for(i=0; i<20; i++, j++){
    zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
  }
  zBuf[j] = 0;
  OSTRACE2("TEMP FILENAME: %s\n", zBuf);
  return SQLITE_OK; 
}

/*
** Turn a relative pathname into a full pathname.  Write the full
** pathname into zOut[].  zOut[] will be at least pVfs->mxPathname
** bytes in size.
*/
static int winFullPathname(
  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
................................................................................
    0,                 /* pNext */
    "win32",           /* zName */
    0,                 /* pAppData */
  
    winOpen,           /* xOpen */
    winDelete,         /* xDelete */
    winAccess,         /* xAccess */
    winGetTempname,    /* xGetTempName */
    winFullPathname,   /* xFullPathname */
    winDlOpen,         /* xDlOpen */
    winDlError,        /* xDlError */
    winDlSym,          /* xDlSym */
    winDlClose,        /* xDlClose */
    winRandomness,     /* xRandomness */
    winSleep,          /* xSleep */







|







 







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







 







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







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
....
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
....
1338
1339
1340
1341
1342
1343
1344


















































1345
1346
1347
1348
1349
1350
1351
....
1563
1564
1565
1566
1567
1568
1569

1570
1571
1572
1573
1574
1575
1576
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to windows.
**
** $Id: os_win.c,v 1.125 2008/06/06 11:11:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#if OS_WIN               /* This file is used for windows only */


/*
** A Note About Memory Allocation:
................................................................................
    zConverted = utf8ToUnicode(zFilename);
  }else{
    zConverted = utf8ToMbcs(zFilename);
  }
  /* caller will handle out of memory */
  return zConverted;
}

/*
** Create a temporary file name in zBuf.  zBuf must be big enough to
** hold at pVfs->mxPathname characters.
*/
static int getTempname(int nBuf, char *zBuf){
  static char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;
  char zTempPath[MAX_PATH+1];
  if( sqlite3_temp_directory ){
    sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
  }else if( isNT() ){
    char *zMulti;
    WCHAR zWidePath[MAX_PATH];
    GetTempPathW(MAX_PATH-30, zWidePath);
    zMulti = unicodeToUtf8(zWidePath);
    if( zMulti ){
      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
      free(zMulti);
    }else{
      return SQLITE_NOMEM;
    }
  }else{
    char *zUtf8;
    char zMbcsPath[MAX_PATH];
    GetTempPathA(MAX_PATH-30, zMbcsPath);
    zUtf8 = mbcsToUtf8(zMbcsPath);
    if( zUtf8 ){
      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
      free(zUtf8);
    }else{
      return SQLITE_NOMEM;
    }
  }
  for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
  zTempPath[i] = 0;
  sqlite3_snprintf(nBuf-30, zBuf,
                   "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
  j = strlen(zBuf);
  sqlite3_randomness(20, &zBuf[j]);
  for(i=0; i<20; i++, j++){
    zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
  }
  zBuf[j] = 0;
  OSTRACE2("TEMP FILENAME: %s\n", zBuf);
  return SQLITE_OK; 
}


/*
** Open a file.
*/
static int winOpen(
  sqlite3_vfs *pVfs,        /* Not used */
  const char *zName,        /* Name of the file (UTF-8) */
................................................................................
  HANDLE h;
  DWORD dwDesiredAccess;
  DWORD dwShareMode;
  DWORD dwCreationDisposition;
  DWORD dwFlagsAndAttributes = 0;
  int isTemp;
  winFile *pFile = (winFile*)id;
  void *zConverted;                 /* Filename in OS encoding */
  const char *zUtf8Name = zName;    /* Filename in UTF-8 encoding */
  char zTmpname[MAX_PATH+1];        /* Buffer used to create temp filename */

  /* If the second argument to this function is NULL, generate a 
  ** temporary file name to use 
  */
  if( !zUtf8Name ){
    int rc = getTempname(MAX_PATH+1, zTmpname);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    zUtf8Name = zTmpname;
  }

  /* Convert the filename to the system encoding. */
  zConverted = convertUtf8Filename(zUtf8Name);
  if( zConverted==0 ){
    return SQLITE_NOMEM;
  }

  if( flags & SQLITE_OPEN_READWRITE ){
    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  }else{
................................................................................
      assert(!"Invalid flags argument");
  }
  *pResOut = rc;
  return SQLITE_OK;
}




















































/*
** Turn a relative pathname into a full pathname.  Write the full
** pathname into zOut[].  zOut[] will be at least pVfs->mxPathname
** bytes in size.
*/
static int winFullPathname(
  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
................................................................................
    0,                 /* pNext */
    "win32",           /* zName */
    0,                 /* pAppData */
  
    winOpen,           /* xOpen */
    winDelete,         /* xDelete */
    winAccess,         /* xAccess */

    winFullPathname,   /* xFullPathname */
    winDlOpen,         /* xDlOpen */
    winDlError,        /* xDlError */
    winDlSym,          /* xDlSym */
    winDlClose,        /* xDlClose */
    winRandomness,     /* xRandomness */
    winSleep,          /* xSleep */

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
....
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
....
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
2260
2261
2262
2263
2264
....
2326
2327
2328
2329
2330
2331
2332

2333
2334



2335
2336
2337
2338
2339
2340
2341
....
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
....
4957
4958
4959
4960
4961
4962
4963



4964
4965
4966
4967
4968
4969
4970
....
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.452 2008/06/05 11:39:11 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*
................................................................................
  int mxPage;                 /* Maximum number of pages to hold in cache */
  Pgno mxPgno;                /* Maximum allowed size of the database */
  Bitvec *pInJournal;         /* One bit for each page in the database file */
  Bitvec *pInStmt;            /* One bit for each page in the database */
  char *zFilename;            /* Name of the database file */
  char *zJournal;             /* Name of the journal file */
  char *zDirectory;           /* Directory hold database and journal files */
  char *zStmtJrnl;            /* Name of the statement journal file */
  sqlite3_file *fd, *jfd;     /* File descriptors for database and journal */
  sqlite3_file *stfd;         /* File descriptor for the statement subjournal*/
  BusyHandler *pBusyHandler;  /* Pointer to sqlite.busyHandler */
  PagerLruList lru;           /* LRU list of free pages */
  PgHdr *pAll;                /* List of all pages */
  PgHdr *pStmt;               /* List of pages in the statement subjournal */
  PgHdr *pDirty;              /* List of all dirty pages */
................................................................................
** Open a temporary file. 
**
** Write the file descriptor into *fd.  Return SQLITE_OK on success or some
** other error code if we fail. The OS will automatically delete the temporary
** file when it is closed.
*/
static int sqlite3PagerOpentemp(
  sqlite3_vfs *pVfs,    /* The virtual file system layer */
  sqlite3_file *pFile,  /* Write the file descriptor here */
  char *zFilename,      /* Name of the file.  Might be NULL */
  int vfsFlags          /* Flags passed through to the VFS */
){
  int rc;
  assert( zFilename!=0 );

#ifdef SQLITE_TEST
  sqlite3_opentemp_count++;  /* Used for testing and analysis only */
#endif

  vfsFlags |=  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
            SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
  rc = sqlite3OsOpen(pVfs, zFilename, pFile, vfsFlags, 0);
  assert( rc!=SQLITE_OK || pFile->pMethods );
  return rc;
}

/*
** Create a new page cache and put a pointer to the page cache in *ppPager.
** The file to be cached need not exist.  The file is not locked until
................................................................................
  int tempFile = 0;
  int memDb = 0;
  int readOnly = 0;
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
  int journalFileSize = sqlite3JournalSize(pVfs);
  int nDefaultPage = SQLITE_DEFAULT_PAGE_SIZE;
  char *zPathname;
  int nPathname;
  char *zStmtJrnl;
  int nStmtJrnl;

  /* The default return is a NULL pointer */
  *ppPager = 0;

  /* Compute the full pathname */




  nPathname = pVfs->mxPathname+1;
  zPathname = sqlite3_malloc(nPathname*2);
  if( zPathname==0 ){
    return SQLITE_NOMEM;
  }
  if( zFilename && zFilename[0] ){
#ifndef SQLITE_OMIT_MEMORYDB
    if( strcmp(zFilename,":memory:")==0 ){
      memDb = 1;
      zPathname[0] = 0;
    }else
#endif
    {
      rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
    }
  }else{
    rc = sqlite3OsGetTempname(pVfs, nPathname, zPathname);
  }
  if( rc!=SQLITE_OK ){
    sqlite3_free(zPathname);
    return rc;
  }
  nPathname = strlen(zPathname);

  /* Put the statement journal in temporary disk space since this is
  ** sometimes RAM disk or other optimized storage.  Unlikely the main
  ** main journal file, the statement journal does not need to be 
  ** colocated with the database nor does it need to be persistent.
  */
  zStmtJrnl = &zPathname[nPathname+1];
  rc = sqlite3OsGetTempname(pVfs, pVfs->mxPathname+1, zStmtJrnl);
  if( rc!=SQLITE_OK ){
    sqlite3_free(zPathname);
    return rc;
  }
  nStmtJrnl = strlen(zStmtJrnl);

  /* Allocate memory for the pager structure */
  pPager = sqlite3MallocZero(
    sizeof(*pPager) +           /* Pager structure */
    journalFileSize +           /* The journal file structure */ 
    pVfs->szOsFile * 3 +        /* The main db and two journal files */ 
    3*nPathname + 40 +          /* zFilename, zDirectory, zJournal */
    nStmtJrnl                   /* zStmtJrnl */
  );
  if( !pPager ){
    sqlite3_free(zPathname);
    return SQLITE_NOMEM;
  }
  pPtr = (u8 *)&pPager[1];
  pPager->vfsFlags = vfsFlags;
  pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
  pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
  pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
  pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize];
  pPager->zDirectory = &pPager->zFilename[nPathname+1];
  pPager->zJournal = &pPager->zDirectory[nPathname+1];
  pPager->zStmtJrnl = &pPager->zJournal[nPathname+10];
  pPager->pVfs = pVfs;

  memcpy(pPager->zFilename, zPathname, nPathname+1);
  memcpy(pPager->zStmtJrnl, zStmtJrnl, nStmtJrnl+1);
  sqlite3_free(zPathname);


  /* Open the pager file.
  */
  if( zFilename && zFilename[0] && !memDb ){
    if( nPathname>(pVfs->mxPathname - sizeof("-journal")) ){
      rc = SQLITE_CANTOPEN;
    }else{
................................................................................

  /* Fill in Pager.zDirectory[] */
  memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1);
  for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){}
  if( i>0 ) pPager->zDirectory[i-1] = 0;

  /* Fill in Pager.zJournal[] */

  memcpy(pPager->zJournal, pPager->zFilename, nPathname);
  memcpy(&pPager->zJournal[nPathname], "-journal", 9);




  /* pPager->journalOpen = 0; */
  pPager->useJournal = useJournal && !memDb;
  pPager->noReadlock = noReadlock && readOnly;
  /* pPager->stmtOpen = 0; */
  /* pPager->stmtInUse = 0; */
  /* pPager->nRef = 0; */
................................................................................
    p->dirty = 0;
  }
  while( pList ){

    /* If the file has not yet been opened, open it now. */
    if( !pPager->fd->pMethods ){
      assert(pPager->tempFile);
      rc = sqlite3PagerOpentemp(pPager->pVfs, pPager->fd, pPager->zFilename,
                                pPager->vfsFlags);
      if( rc ) return rc;
    }

    /* If there are dirty pages in the page cache with page numbers greater
    ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to
    ** make the file smaller (presumably by auto-vacuum code). Do not write
    ** any such pages to the file.
................................................................................
  a[6] = pPager->nHit;
  a[7] = pPager->nMiss;
  a[8] = 0;  /* Used to be pPager->nOvfl */
  a[9] = pPager->nRead;
  a[10] = pPager->nWrite;
  return a;
}



#endif

/*
** Set the statement rollback point.
**
** This routine should be called with the transaction journal already
** open.  A new statement journal is created that can be used to rollback
................................................................................
    return SQLITE_NOMEM;
  }
  pPager->stmtJSize = pPager->journalOff;
  pPager->stmtSize = pPager->dbSize;
  pPager->stmtHdrOff = 0;
  pPager->stmtCksum = pPager->cksumInit;
  if( !pPager->stmtOpen ){
    rc = sqlite3PagerOpentemp(pPager->pVfs, pPager->stfd, pPager->zStmtJrnl,
                              SQLITE_OPEN_SUBJOURNAL);
    if( rc ){
      goto stmt_begin_failed;
    }
    pPager->stmtOpen = 1;
    pPager->stmtNRec = 0;
  }
  pPager->stmtInUse = 1;







|







 







<







 







|

<



<







|







 







|
|
<
<




|
>
>
>
>
|
|
|
|
|
<









<
<
<
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<






|
<













<

>
|
<
|
>







 







>
|
|
>
>
>







 







|
<







 







>
>
>







 







<
|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
368
369
370
371
372
373
374

375
376
377
378
379
380
381
....
2127
2128
2129
2130
2131
2132
2133
2134
2135

2136
2137
2138

2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
....
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
....
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
....
3053
3054
3055
3056
3057
3058
3059
3060

3061
3062
3063
3064
3065
3066
3067
....
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
....
4983
4984
4985
4986
4987
4988
4989

4990
4991
4992
4993
4994
4995
4996
4997
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.453 2008/06/06 11:11:26 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*
................................................................................
  int mxPage;                 /* Maximum number of pages to hold in cache */
  Pgno mxPgno;                /* Maximum allowed size of the database */
  Bitvec *pInJournal;         /* One bit for each page in the database file */
  Bitvec *pInStmt;            /* One bit for each page in the database */
  char *zFilename;            /* Name of the database file */
  char *zJournal;             /* Name of the journal file */
  char *zDirectory;           /* Directory hold database and journal files */

  sqlite3_file *fd, *jfd;     /* File descriptors for database and journal */
  sqlite3_file *stfd;         /* File descriptor for the statement subjournal*/
  BusyHandler *pBusyHandler;  /* Pointer to sqlite.busyHandler */
  PagerLruList lru;           /* LRU list of free pages */
  PgHdr *pAll;                /* List of all pages */
  PgHdr *pStmt;               /* List of pages in the statement subjournal */
  PgHdr *pDirty;              /* List of all dirty pages */
................................................................................
** Open a temporary file. 
**
** Write the file descriptor into *fd.  Return SQLITE_OK on success or some
** other error code if we fail. The OS will automatically delete the temporary
** file when it is closed.
*/
static int sqlite3PagerOpentemp(
  Pager *pPager,        /* The pager object */
  sqlite3_file *pFile,  /* Write the file descriptor here */

  int vfsFlags          /* Flags passed through to the VFS */
){
  int rc;


#ifdef SQLITE_TEST
  sqlite3_opentemp_count++;  /* Used for testing and analysis only */
#endif

  vfsFlags |=  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
            SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
  rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
  assert( rc!=SQLITE_OK || pFile->pMethods );
  return rc;
}

/*
** Create a new page cache and put a pointer to the page cache in *ppPager.
** The file to be cached need not exist.  The file is not locked until
................................................................................
  int tempFile = 0;
  int memDb = 0;
  int readOnly = 0;
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
  int journalFileSize = sqlite3JournalSize(pVfs);
  int nDefaultPage = SQLITE_DEFAULT_PAGE_SIZE;
  char *zPathname = 0;
  int nPathname = 0;



  /* The default return is a NULL pointer */
  *ppPager = 0;

  /* Compute and store the full pathname in an allocated buffer pointed
  ** to by zPathname, length nPathname. Or, if this is a temporary file,
  ** leave both nPathname and zPathname set to 0.
  */
  if( zFilename && zFilename[0] ){
    nPathname = pVfs->mxPathname+1;
    zPathname = sqlite3_malloc(nPathname*2);
    if( zPathname==0 ){
      return SQLITE_NOMEM;
    }

#ifndef SQLITE_OMIT_MEMORYDB
    if( strcmp(zFilename,":memory:")==0 ){
      memDb = 1;
      zPathname[0] = 0;
    }else
#endif
    {
      rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
    }



    if( rc!=SQLITE_OK ){
      sqlite3_free(zPathname);
      return rc;
    }
    nPathname = strlen(zPathname);
  }













  /* Allocate memory for the pager structure */
  pPager = sqlite3MallocZero(
    sizeof(*pPager) +           /* Pager structure */
    journalFileSize +           /* The journal file structure */ 
    pVfs->szOsFile * 3 +        /* The main db and two journal files */ 
    3*nPathname + 40            /* zFilename, zDirectory, zJournal */

  );
  if( !pPager ){
    sqlite3_free(zPathname);
    return SQLITE_NOMEM;
  }
  pPtr = (u8 *)&pPager[1];
  pPager->vfsFlags = vfsFlags;
  pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
  pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
  pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
  pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize];
  pPager->zDirectory = &pPager->zFilename[nPathname+1];
  pPager->zJournal = &pPager->zDirectory[nPathname+1];

  pPager->pVfs = pVfs;
  if( zPathname ){
    memcpy(pPager->zFilename, zPathname, nPathname+1);

    sqlite3_free(zPathname);
  }

  /* Open the pager file.
  */
  if( zFilename && zFilename[0] && !memDb ){
    if( nPathname>(pVfs->mxPathname - sizeof("-journal")) ){
      rc = SQLITE_CANTOPEN;
    }else{
................................................................................

  /* Fill in Pager.zDirectory[] */
  memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1);
  for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){}
  if( i>0 ) pPager->zDirectory[i-1] = 0;

  /* Fill in Pager.zJournal[] */
  if( zPathname ){
    memcpy(pPager->zJournal, pPager->zFilename, nPathname);
    memcpy(&pPager->zJournal[nPathname], "-journal", 9);
  }else{
    pPager->zJournal = 0;
  }

  /* pPager->journalOpen = 0; */
  pPager->useJournal = useJournal && !memDb;
  pPager->noReadlock = noReadlock && readOnly;
  /* pPager->stmtOpen = 0; */
  /* pPager->stmtInUse = 0; */
  /* pPager->nRef = 0; */
................................................................................
    p->dirty = 0;
  }
  while( pList ){

    /* If the file has not yet been opened, open it now. */
    if( !pPager->fd->pMethods ){
      assert(pPager->tempFile);
      rc = sqlite3PagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);

      if( rc ) return rc;
    }

    /* If there are dirty pages in the page cache with page numbers greater
    ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to
    ** make the file smaller (presumably by auto-vacuum code). Do not write
    ** any such pages to the file.
................................................................................
  a[6] = pPager->nHit;
  a[7] = pPager->nMiss;
  a[8] = 0;  /* Used to be pPager->nOvfl */
  a[9] = pPager->nRead;
  a[10] = pPager->nWrite;
  return a;
}
int sqlite3PagerIsMemdb(Pager *pPager){
  return MEMDB;
}
#endif

/*
** Set the statement rollback point.
**
** This routine should be called with the transaction journal already
** open.  A new statement journal is created that can be used to rollback
................................................................................
    return SQLITE_NOMEM;
  }
  pPager->stmtJSize = pPager->journalOff;
  pPager->stmtSize = pPager->dbSize;
  pPager->stmtHdrOff = 0;
  pPager->stmtCksum = pPager->cksumInit;
  if( !pPager->stmtOpen ){

    rc = sqlite3PagerOpentemp(pPager, pPager->stfd, SQLITE_OPEN_SUBJOURNAL);
    if( rc ){
      goto stmt_begin_failed;
    }
    pPager->stmtOpen = 1;
    pPager->stmtNRec = 0;
  }
  pPager->stmtInUse = 1;

Changes to src/pager.h.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140
141
142
143
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
** subsystem.  The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.74 2008/06/04 06:45:59 danielk1977 Exp $
*/

#ifndef _PAGER_H_
#define _PAGER_H_

/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
................................................................................
  Pgno sqlite3PagerPagenumber(DbPage*);
  int sqlite3PagerIswriteable(DbPage*);
#endif

#ifdef SQLITE_TEST
  int *sqlite3PagerStats(Pager*);
  void sqlite3PagerRefdump(Pager*);

#endif

#ifdef SQLITE_TEST
void disable_simulated_io_errors(void);
void enable_simulated_io_errors(void);
#else
# define disable_simulated_io_errors()
# define enable_simulated_io_errors()
#endif

#endif /* _PAGER_H_ */







|







 







>











9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
** subsystem.  The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.75 2008/06/06 11:11:26 danielk1977 Exp $
*/

#ifndef _PAGER_H_
#define _PAGER_H_

/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
................................................................................
  Pgno sqlite3PagerPagenumber(DbPage*);
  int sqlite3PagerIswriteable(DbPage*);
#endif

#ifdef SQLITE_TEST
  int *sqlite3PagerStats(Pager*);
  void sqlite3PagerRefdump(Pager*);
  int sqlite3PagerIsMemdb(Pager*);
#endif

#ifdef SQLITE_TEST
void disable_simulated_io_errors(void);
void enable_simulated_io_errors(void);
#else
# define disable_simulated_io_errors()
# define enable_simulated_io_errors()
#endif

#endif /* _PAGER_H_ */

Changes to src/sqlite.h.in.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
...
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.320 2008/06/05 11:39:11 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
** to test for the existence of a file,
** or [SQLITE_ACCESS_READWRITE] to test to see
** if a file is readable and writable, or [SQLITE_ACCESS_READ]
** to test to see if a file is at least readable.  {END} The file can be a 
** directory.
** 
** {F11150} SQLite will always allocate at least mxPathname+1 bytes for
** the output buffers for xGetTempname and xFullPathname. {F11151} The exact
** size of the output buffer is also passed as a parameter to both 
** methods. {END} If the output buffer is not large enough, [SQLITE_CANTOPEN]
** should be returned. As this is handled as a fatal error by SQLite,
** vfs implementations should endeavor to prevent this by setting 
** mxPathname to a sufficiently large value.
** 
** The xRandomness(), xSleep(), and xCurrentTime() interfaces
................................................................................
  sqlite3_vfs *pNext;      /* Next registered VFS */
  const char *zName;       /* Name of this virtual file system */
  void *pAppData;          /* Pointer to application-specific data */
  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
               int flags, int *pOutFlags);
  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
  int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut);
  int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
  void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
  void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
  void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol);
  void (*xDlClose)(sqlite3_vfs*, void*);
  int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
  int (*xSleep)(sqlite3_vfs*, int microseconds);







|







 







|







 







<







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
...
807
808
809
810
811
812
813

814
815
816
817
818
819
820
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.321 2008/06/06 11:11:26 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
** to test for the existence of a file,
** or [SQLITE_ACCESS_READWRITE] to test to see
** if a file is readable and writable, or [SQLITE_ACCESS_READ]
** to test to see if a file is at least readable.  {END} The file can be a 
** directory.
** 
** {F11150} SQLite will always allocate at least mxPathname+1 bytes for
** the output buffer xFullPathname. {F11151} The exact
** size of the output buffer is also passed as a parameter to both 
** methods. {END} If the output buffer is not large enough, [SQLITE_CANTOPEN]
** should be returned. As this is handled as a fatal error by SQLite,
** vfs implementations should endeavor to prevent this by setting 
** mxPathname to a sufficiently large value.
** 
** The xRandomness(), xSleep(), and xCurrentTime() interfaces
................................................................................
  sqlite3_vfs *pNext;      /* Next registered VFS */
  const char *zName;       /* Name of this virtual file system */
  void *pAppData;          /* Pointer to application-specific data */
  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
               int flags, int *pOutFlags);
  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);

  int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
  void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
  void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
  void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol);
  void (*xDlClose)(sqlite3_vfs*, void*);
  int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
  int (*xSleep)(sqlite3_vfs*, int microseconds);

Changes to src/test3.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1600
1601
1602
1603
1604
1605
1606





























1607
1608
1609
1610
1611
1612
1613
....
1650
1651
1652
1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.96 2008/05/27 20:17:01 shane Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  sqlite3BtreeSetCacheSize(pBt, nCache);
  sqlite3BtreeLeave(pBt);
  sqlite3_mutex_leave(pBt->db->mutex);

  return TCL_OK;
}































/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest3_Init(Tcl_Interp *interp){
  extern int sqlite3BtreeTrace;
  static struct {
................................................................................
     { "btree_commit_statement",   (Tcl_CmdProc*)btree_commit_statement   },
     { "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement },
     { "btree_from_db",            (Tcl_CmdProc*)btree_from_db            },
     { "btree_set_cache_size",     (Tcl_CmdProc*)btree_set_cache_size     },
     { "btree_cursor_info",        (Tcl_CmdProc*)btree_cursor_info        },
     { "btree_ovfl_info",          (Tcl_CmdProc*)btree_ovfl_info          },
     { "btree_cursor_list",        (Tcl_CmdProc*)btree_cursor_list        },

  };
  int i;

  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  }
  Tcl_LinkVar(interp, "btree_trace", (char*)&sqlite3BtreeTrace,







|







 







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







 







>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
....
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.97 2008/06/06 11:11:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  sqlite3BtreeSetCacheSize(pBt, nCache);
  sqlite3BtreeLeave(pBt);
  sqlite3_mutex_leave(pBt->db->mutex);

  return TCL_OK;
}

/*
** Usage:   btree_ismemdb ID
**
** Return true if the B-Tree is in-memory.
*/
static int btree_ismemdb(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  const char **argv      /* Text of each argument */
){
  Btree *pBt;
  int res;

  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pBt = sqlite3TextToPtr(argv[1]);
  sqlite3_mutex_enter(pBt->db->mutex);
  sqlite3BtreeEnter(pBt);
  res = sqlite3PagerIsMemdb(sqlite3BtreePager(pBt));
  sqlite3BtreeLeave(pBt);
  sqlite3_mutex_leave(pBt->db->mutex);
  Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));
  return SQLITE_OK;
}


/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest3_Init(Tcl_Interp *interp){
  extern int sqlite3BtreeTrace;
  static struct {
................................................................................
     { "btree_commit_statement",   (Tcl_CmdProc*)btree_commit_statement   },
     { "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement },
     { "btree_from_db",            (Tcl_CmdProc*)btree_from_db            },
     { "btree_set_cache_size",     (Tcl_CmdProc*)btree_set_cache_size     },
     { "btree_cursor_info",        (Tcl_CmdProc*)btree_cursor_info        },
     { "btree_ovfl_info",          (Tcl_CmdProc*)btree_ovfl_info          },
     { "btree_cursor_list",        (Tcl_CmdProc*)btree_cursor_list        },
     { "btree_ismemdb",            (Tcl_CmdProc*)btree_ismemdb            },
  };
  int i;

  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  }
  Tcl_LinkVar(interp, "btree_trace", (char*)&sqlite3BtreeTrace,

Changes to src/test6.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
...
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
**
******************************************************************************
**
** This file contains code that modified the OS layer in order to simulate
** the effect on the database file of an OS crash or power failure.  This
** is used to test the ability of SQLite to recover from those situations.
**
** $Id: test6.c,v 1.38 2008/06/05 11:39:11 danielk1977 Exp $
*/
#if SQLITE_TEST          /* This file is used for testing only */
#include "sqliteInt.h"
#include "tcl.h"

#ifndef SQLITE_OMIT_DISKIO  /* This file is a no-op if disk I/O is disabled */

................................................................................
  const char *zPath, 
  int flags, 
  int *pResOut
){
  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
  return pVfs->xAccess(pVfs, zPath, flags, pResOut);
}
static int cfGetTempname(sqlite3_vfs *pCfVfs, int nBufOut, char *zBufOut){
  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
  return pVfs->xGetTempname(pVfs, nBufOut, zBufOut);
}
static int cfFullPathname(
  sqlite3_vfs *pCfVfs, 
  const char *zPath, 
  int nPathOut,
  char *zPathOut
){
  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
................................................................................
    0,                  /* pNext */
    "crash",            /* zName */
    0,                  /* pAppData */
  
    cfOpen,               /* xOpen */
    cfDelete,             /* xDelete */
    cfAccess,             /* xAccess */
    cfGetTempname,        /* xGetTempName */
    cfFullPathname,       /* xFullPathname */
    cfDlOpen,             /* xDlOpen */
    cfDlError,            /* xDlError */
    cfDlSym,              /* xDlSym */
    cfDlClose,            /* xDlClose */
    cfRandomness,         /* xRandomness */
    cfSleep,              /* xSleep */







|







 







<
<
<
<







 







<







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
585
586
587
588
589
590
591




592
593
594
595
596
597
598
...
739
740
741
742
743
744
745

746
747
748
749
750
751
752
**
******************************************************************************
**
** This file contains code that modified the OS layer in order to simulate
** the effect on the database file of an OS crash or power failure.  This
** is used to test the ability of SQLite to recover from those situations.
**
** $Id: test6.c,v 1.39 2008/06/06 11:11:26 danielk1977 Exp $
*/
#if SQLITE_TEST          /* This file is used for testing only */
#include "sqliteInt.h"
#include "tcl.h"

#ifndef SQLITE_OMIT_DISKIO  /* This file is a no-op if disk I/O is disabled */

................................................................................
  const char *zPath, 
  int flags, 
  int *pResOut
){
  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
  return pVfs->xAccess(pVfs, zPath, flags, pResOut);
}




static int cfFullPathname(
  sqlite3_vfs *pCfVfs, 
  const char *zPath, 
  int nPathOut,
  char *zPathOut
){
  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
................................................................................
    0,                  /* pNext */
    "crash",            /* zName */
    0,                  /* pAppData */
  
    cfOpen,               /* xOpen */
    cfDelete,             /* xDelete */
    cfAccess,             /* xAccess */

    cfFullPathname,       /* xFullPathname */
    cfDlOpen,             /* xDlOpen */
    cfDlError,            /* xDlError */
    cfDlSym,              /* xDlSym */
    cfDlClose,            /* xDlClose */
    cfRandomness,         /* xRandomness */
    cfSleep,              /* xSleep */

Changes to src/test_async.c.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
....
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
....
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** $Id: test_async.c,v 1.43 2008/06/05 11:39:11 danielk1977 Exp $
**
** This file contains an example implementation of an asynchronous IO 
** backend for SQLite.
**
** WHAT IS ASYNCHRONOUS I/O?
**
** With asynchronous I/O, write requests are handled by a separate thread
................................................................................
    , zName, ret)
  );
  pthread_mutex_unlock(&async.queueMutex);
  *pResOut = ret;
  return rc;
}

static int asyncGetTempname(sqlite3_vfs *pAsyncVfs, int nBufOut, char *zBufOut){
  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  return pVfs->xGetTempname(pVfs, nBufOut, zBufOut);
}

/*
** Fill in zPathOut with the full path to the file identified by zPath.
*/
static int asyncFullPathname(
  sqlite3_vfs *pAsyncVfs, 
  const char *zPath, 
  int nPathOut,
................................................................................
  0,                    /* mxPathname */
  0,                    /* pNext */
  "async",              /* zName */
  0,                    /* pAppData */
  asyncOpen,            /* xOpen */
  asyncDelete,          /* xDelete */
  asyncAccess,          /* xAccess */
  asyncGetTempname,     /* xGetTempName */
  asyncFullPathname,    /* xFullPathname */
  asyncDlOpen,          /* xDlOpen */
  asyncDlError,         /* xDlError */
  asyncDlSym,           /* xDlSym */
  asyncDlClose,         /* xDlClose */
  asyncRandomness,      /* xDlError */
  asyncSleep,           /* xDlSym */







|







 







<
<
<
<
<







 







<







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
....
1163
1164
1165
1166
1167
1168
1169





1170
1171
1172
1173
1174
1175
1176
....
1262
1263
1264
1265
1266
1267
1268

1269
1270
1271
1272
1273
1274
1275
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** $Id: test_async.c,v 1.44 2008/06/06 11:11:26 danielk1977 Exp $
**
** This file contains an example implementation of an asynchronous IO 
** backend for SQLite.
**
** WHAT IS ASYNCHRONOUS I/O?
**
** With asynchronous I/O, write requests are handled by a separate thread
................................................................................
    , zName, ret)
  );
  pthread_mutex_unlock(&async.queueMutex);
  *pResOut = ret;
  return rc;
}






/*
** Fill in zPathOut with the full path to the file identified by zPath.
*/
static int asyncFullPathname(
  sqlite3_vfs *pAsyncVfs, 
  const char *zPath, 
  int nPathOut,
................................................................................
  0,                    /* mxPathname */
  0,                    /* pNext */
  "async",              /* zName */
  0,                    /* pAppData */
  asyncOpen,            /* xOpen */
  asyncDelete,          /* xDelete */
  asyncAccess,          /* xAccess */

  asyncFullPathname,    /* xFullPathname */
  asyncDlOpen,          /* xDlOpen */
  asyncDlError,         /* xDlError */
  asyncDlSym,           /* xDlSym */
  asyncDlClose,         /* xDlClose */
  asyncRandomness,      /* xDlError */
  asyncSleep,           /* xDlSym */

Changes to src/test_devsym.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
**
******************************************************************************
**
** This file contains code that modified the OS layer in order to simulate
** different device types (by overriding the return values of the 
** xDeviceCharacteristics() and xSectorSize() methods).
**
** $Id: test_devsym.c,v 1.6 2008/06/05 11:39:11 danielk1977 Exp $
*/
#if SQLITE_TEST          /* This file is used for testing only */

#include "sqlite3.h"
#include "sqliteInt.h"

/*
................................................................................

/*
** Method declarations for devsym_vfs.
*/
static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int devsymGetTempName(sqlite3_vfs*, int nOut, char *zOut);
static int devsymFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
#ifndef SQLITE_OMIT_LOAD_EXTENSION
static void *devsymDlOpen(sqlite3_vfs*, const char *zFilename);
static void devsymDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void *devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol);
static void devsymDlClose(sqlite3_vfs*, void*);
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
................................................................................
  DEVSYM_MAX_PATHNAME,      /* mxPathname */
  0,                     /* pNext */
  DEVSYM_VFS_NAME,          /* zName */
  0,                     /* pAppData */
  devsymOpen,               /* xOpen */
  devsymDelete,             /* xDelete */
  devsymAccess,             /* xAccess */
  devsymGetTempName,        /* xGetTempName */
  devsymFullPathname,       /* xFullPathname */
#ifndef SQLITE_OMIT_LOAD_EXTENSION
  devsymDlOpen,             /* xDlOpen */
  devsymDlError,            /* xDlError */
  devsymDlSym,              /* xDlSym */
  devsymDlClose,            /* xDlClose */
#else
................................................................................
  const char *zPath, 
  int flags, 
  int *pResOut
){
  return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut);
}

/*
** Populate buffer zBufOut with a pathname suitable for use as a 
** temporary file. zBufOut is guaranteed to point to a buffer of 
** at least (DEVSYM_MAX_PATHNAME+1) bytes.
*/
static int devsymGetTempName(sqlite3_vfs *pVfs, int nOut, char *zBufOut){
  return sqlite3OsGetTempname(g.pVfs, nOut, zBufOut);
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
*/
static int devsymFullPathname(
  sqlite3_vfs *pVfs, 







|







 







<







 







<







 







<
<
<
<
<
<
<
<
<







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
55
56
57
58
59
60
61

62
63
64
65
66
67
68
..
76
77
78
79
80
81
82

83
84
85
86
87
88
89
...
258
259
260
261
262
263
264









265
266
267
268
269
270
271
**
******************************************************************************
**
** This file contains code that modified the OS layer in order to simulate
** different device types (by overriding the return values of the 
** xDeviceCharacteristics() and xSectorSize() methods).
**
** $Id: test_devsym.c,v 1.7 2008/06/06 11:11:26 danielk1977 Exp $
*/
#if SQLITE_TEST          /* This file is used for testing only */

#include "sqlite3.h"
#include "sqliteInt.h"

/*
................................................................................

/*
** Method declarations for devsym_vfs.
*/
static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *);

static int devsymFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
#ifndef SQLITE_OMIT_LOAD_EXTENSION
static void *devsymDlOpen(sqlite3_vfs*, const char *zFilename);
static void devsymDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void *devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol);
static void devsymDlClose(sqlite3_vfs*, void*);
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
................................................................................
  DEVSYM_MAX_PATHNAME,      /* mxPathname */
  0,                     /* pNext */
  DEVSYM_VFS_NAME,          /* zName */
  0,                     /* pAppData */
  devsymOpen,               /* xOpen */
  devsymDelete,             /* xDelete */
  devsymAccess,             /* xAccess */

  devsymFullPathname,       /* xFullPathname */
#ifndef SQLITE_OMIT_LOAD_EXTENSION
  devsymDlOpen,             /* xDlOpen */
  devsymDlError,            /* xDlError */
  devsymDlSym,              /* xDlSym */
  devsymDlClose,            /* xDlClose */
#else
................................................................................
  const char *zPath, 
  int flags, 
  int *pResOut
){
  return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut);
}










/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
*/
static int devsymFullPathname(
  sqlite3_vfs *pVfs, 

Changes to src/test_onefile.c.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** $Id: test_onefile.c,v 1.7 2008/06/05 11:39:11 danielk1977 Exp $
**
** OVERVIEW:
**
**   This file contains some example code demonstrating how the SQLite 
**   vfs feature can be used to have SQLite operate directly on an 
**   embedded media, without using an intermediate file system.
**
................................................................................

/*
** Method declarations for fs_vfs.
*/
static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int fsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int fsGetTempname(sqlite3_vfs*, int nOut, char *zOut);
static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);
static void *fsDlOpen(sqlite3_vfs*, const char *zFilename);
static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void *fsDlSym(sqlite3_vfs*,void*, const char *zSymbol);
static void fsDlClose(sqlite3_vfs*, void*);
static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int fsSleep(sqlite3_vfs*, int microseconds);
................................................................................
    0,                                          /* mxPathname */
    0,                                          /* pNext */
    FS_VFS_NAME,                                /* zName */
    0,                                          /* pAppData */
    fsOpen,                                     /* xOpen */
    fsDelete,                                   /* xDelete */
    fsAccess,                                   /* xAccess */
    fsGetTempname,                              /* xGetTempName */
    fsFullPathname,                             /* xFullPathname */
    fsDlOpen,                                   /* xDlOpen */
    fsDlError,                                  /* xDlError */
    fsDlSym,                                    /* xDlSym */
    fsDlClose,                                  /* xDlClose */
    fsRandomness,                               /* xRandomness */
    fsSleep,                                    /* xSleep */
................................................................................
  pReal = pFsVfs->pFileList; 
  for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);

  *pResOut = (pReal && (!isJournal || pReal->nJournal>0));
  return SQLITE_OK;
}

/*
** Populate buffer zBufOut with a pathname suitable for use as a 
** temporary file. zBufOut is guaranteed to point to a buffer of 
** at least (FS_MAX_PATHNAME+1) bytes.
*/
static int fsGetTempname(sqlite3_vfs *pVfs, int nBufOut, char *zBufOut){
  sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  return pParent->xGetTempname(pParent, nBufOut, zBufOut);
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (FS_MAX_PATHNAME+1) bytes.
*/
static int fsFullPathname(
  sqlite3_vfs *pVfs,            /* Pointer to vfs object */







|







 







<







 







<







 







<
<
<
<
<
<
<
<
<
<







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
161
162
163
164
165
166
167

168
169
170
171
172
173
174
...
189
190
191
192
193
194
195

196
197
198
199
200
201
202
...
725
726
727
728
729
730
731










732
733
734
735
736
737
738
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** $Id: test_onefile.c,v 1.8 2008/06/06 11:11:26 danielk1977 Exp $
**
** OVERVIEW:
**
**   This file contains some example code demonstrating how the SQLite 
**   vfs feature can be used to have SQLite operate directly on an 
**   embedded media, without using an intermediate file system.
**
................................................................................

/*
** Method declarations for fs_vfs.
*/
static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int fsAccess(sqlite3_vfs*, const char *zName, int flags, int *);

static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);
static void *fsDlOpen(sqlite3_vfs*, const char *zFilename);
static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void *fsDlSym(sqlite3_vfs*,void*, const char *zSymbol);
static void fsDlClose(sqlite3_vfs*, void*);
static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int fsSleep(sqlite3_vfs*, int microseconds);
................................................................................
    0,                                          /* mxPathname */
    0,                                          /* pNext */
    FS_VFS_NAME,                                /* zName */
    0,                                          /* pAppData */
    fsOpen,                                     /* xOpen */
    fsDelete,                                   /* xDelete */
    fsAccess,                                   /* xAccess */

    fsFullPathname,                             /* xFullPathname */
    fsDlOpen,                                   /* xDlOpen */
    fsDlError,                                  /* xDlError */
    fsDlSym,                                    /* xDlSym */
    fsDlClose,                                  /* xDlClose */
    fsRandomness,                               /* xRandomness */
    fsSleep,                                    /* xSleep */
................................................................................
  pReal = pFsVfs->pFileList; 
  for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);

  *pResOut = (pReal && (!isJournal || pReal->nJournal>0));
  return SQLITE_OK;
}











/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (FS_MAX_PATHNAME+1) bytes.
*/
static int fsFullPathname(
  sqlite3_vfs *pVfs,            /* Pointer to vfs object */

Changes to src/test_osinst.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
...
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
**
******************************************************************************
**
** This file contains the implementation of an SQLite vfs wrapper that
** adds instrumentation to all vfs and file methods. C and Tcl interfaces
** are provided to control the instrumentation.
**
** $Id: test_osinst.c,v 1.13 2008/06/05 11:39:11 danielk1977 Exp $
*/

/*
** C interface:
**
**   sqlite3_instvfs_create()
**   sqlite3_instvfs_destroy()
................................................................................

/*
** Method declarations for inst_vfs.
*/
static int instOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int instDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int instAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int instGetTempName(sqlite3_vfs*, int nOut, char *zOut);
static int instFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
static void *instDlOpen(sqlite3_vfs*, const char *zFilename);
static void instDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void *instDlSym(sqlite3_vfs*,void*, const char *zSymbol);
static void instDlClose(sqlite3_vfs*, void*);
static int instRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int instSleep(sqlite3_vfs*, int microseconds);
................................................................................
  INST_MAX_PATHNAME,      /* mxPathname */
  0,                      /* pNext */
  0,                      /* zName */
  0,                      /* pAppData */
  instOpen,               /* xOpen */
  instDelete,             /* xDelete */
  instAccess,             /* xAccess */
  instGetTempName,        /* xGetTempName */
  instFullPathname,       /* xFullPathname */
  instDlOpen,             /* xDlOpen */
  instDlError,            /* xDlError */
  instDlSym,              /* xDlSym */
  instDlClose,            /* xDlClose */
  instRandomness,         /* xRandomness */
  instSleep,              /* xSleep */
................................................................................
){
  binarylog_blob(pVfs, zPath, -1, 0);
  OS_TIME_VFS(OS_ACCESS, zPath, 0, flags, *pResOut, 
    REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut) 
  );
}

/*
** Populate buffer zBufOut with a pathname suitable for use as a 
** temporary file. zBufOut is guaranteed to point to a buffer of 
** at least (INST_MAX_PATHNAME+1) bytes.
*/
static int instGetTempName(sqlite3_vfs *pVfs, int nOut, char *zBufOut){
  OS_TIME_VFS( OS_GETTEMPNAME, 0, 0, 0, 0,
    REALVFS(pVfs)->xGetTempname(REALVFS(pVfs), nOut, zBufOut);
  );
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
*/
static int instFullPathname(
  sqlite3_vfs *pVfs, 







|







 







<







 







<







 







<
<
<
<
<
<
<
<
<
<
<







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
169
170
171
172
173
174
175

176
177
178
179
180
181
182
...
190
191
192
193
194
195
196

197
198
199
200
201
202
203
...
412
413
414
415
416
417
418











419
420
421
422
423
424
425
**
******************************************************************************
**
** This file contains the implementation of an SQLite vfs wrapper that
** adds instrumentation to all vfs and file methods. C and Tcl interfaces
** are provided to control the instrumentation.
**
** $Id: test_osinst.c,v 1.14 2008/06/06 11:11:26 danielk1977 Exp $
*/

/*
** C interface:
**
**   sqlite3_instvfs_create()
**   sqlite3_instvfs_destroy()
................................................................................

/*
** Method declarations for inst_vfs.
*/
static int instOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int instDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int instAccess(sqlite3_vfs*, const char *zName, int flags, int *);

static int instFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
static void *instDlOpen(sqlite3_vfs*, const char *zFilename);
static void instDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void *instDlSym(sqlite3_vfs*,void*, const char *zSymbol);
static void instDlClose(sqlite3_vfs*, void*);
static int instRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int instSleep(sqlite3_vfs*, int microseconds);
................................................................................
  INST_MAX_PATHNAME,      /* mxPathname */
  0,                      /* pNext */
  0,                      /* zName */
  0,                      /* pAppData */
  instOpen,               /* xOpen */
  instDelete,             /* xDelete */
  instAccess,             /* xAccess */

  instFullPathname,       /* xFullPathname */
  instDlOpen,             /* xDlOpen */
  instDlError,            /* xDlError */
  instDlSym,              /* xDlSym */
  instDlClose,            /* xDlClose */
  instRandomness,         /* xRandomness */
  instSleep,              /* xSleep */
................................................................................
){
  binarylog_blob(pVfs, zPath, -1, 0);
  OS_TIME_VFS(OS_ACCESS, zPath, 0, flags, *pResOut, 
    REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut) 
  );
}












/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
*/
static int instFullPathname(
  sqlite3_vfs *pVfs, 

Changes to src/vdbeaux.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
....
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
**
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
** $Id: vdbeaux.c,v 1.384 2008/06/05 11:39:11 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"



................................................................................
  }

  /* The simple case - no more than one database file (not counting the
  ** TEMP database) has a transaction active.   There is no need for the
  ** master-journal.
  **
  ** If the return value of sqlite3BtreeGetFilename() is a zero length
  ** string, it means the main database is :memory:.  In that case we do
  ** not support atomic multi-file commits, so use the simple case then
  ** too.
  */
  if( 0==strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt)) || nTrans<=1 ){
    for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ 
      Btree *pBt = db->aDb[i].pBt;
      if( pBt ){
        rc = sqlite3BtreeCommitPhaseOne(pBt, 0);
      }







|







 







|
|
|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
....
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
**
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
** $Id: vdbeaux.c,v 1.385 2008/06/06 11:11:27 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"



................................................................................
  }

  /* The simple case - no more than one database file (not counting the
  ** TEMP database) has a transaction active.   There is no need for the
  ** master-journal.
  **
  ** If the return value of sqlite3BtreeGetFilename() is a zero length
  ** string, it means the main database is :memory: or a temp file.  In 
  ** that case we do not support atomic multi-file commits, so use the 
  ** simple case then too.
  */
  if( 0==strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt)) || nTrans<=1 ){
    for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ 
      Btree *pBt = db->aDb[i].pBt;
      if( pBt ){
        rc = sqlite3BtreeCommitPhaseOne(pBt, 0);
      }

Changes to test/pragma.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
818
819
820
821
822
823
824
825

826
827
828
829

830
831
832
833
834
835
836
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the PRAGMA command.
#
# $Id: pragma.test,v 1.60 2008/05/15 17:48:20 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Test organization:
#
# pragma-1.*: Test cache_size, default_cache_size and synchronous on main db.
................................................................................
# Check to see if TEMP_STORE is memory or disk.  Return strings
# "memory" or "disk" as appropriate.
#
proc check_temp_store {} {
  db eval {CREATE TEMP TABLE IF NOT EXISTS a(b)}
  db eval {PRAGMA database_list} {
    if {$name=="temp"} {
      if {$file==""} {

        return "memory"
      } else {
        return "disk"
      }

    }
  }
  return "unknown"
}


# Test temp_store and temp_store_directory pragmas







|







 







|
>

<
<

>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
818
819
820
821
822
823
824
825
826
827


828
829
830
831
832
833
834
835
836
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the PRAGMA command.
#
# $Id: pragma.test,v 1.61 2008/06/06 11:11:27 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Test organization:
#
# pragma-1.*: Test cache_size, default_cache_size and synchronous on main db.
................................................................................
# Check to see if TEMP_STORE is memory or disk.  Return strings
# "memory" or "disk" as appropriate.
#
proc check_temp_store {} {
  db eval {CREATE TEMP TABLE IF NOT EXISTS a(b)}
  db eval {PRAGMA database_list} {
    if {$name=="temp"} {
      set bt [btree_from_db db 1]
      if {[btree_ismemdb $bt]} {
        return "memory"


      }
      return "disk"
    }
  }
  return "unknown"
}


# Test temp_store and temp_store_directory pragmas