Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the latest trunk changes into the apple-osx branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | apple-osx |
Files: | files | file ages | folders |
SHA1: |
55af80035f0432bbd4c4b3f4dbc9def1 |
User & Date: | drh 2011-08-26 19:18:50.781 |
Context
2011-09-14
| ||
19:05 | Merge in the latest changes from trunk. (check-in: 2456b4d0d2 user: drh tags: apple-osx) | |
2011-08-26
| ||
19:18 | Merge the latest trunk changes into the apple-osx branch. (check-in: 55af80035f user: drh tags: apple-osx) | |
11:25 | Update compiler error message regarding the choice of memory allocator defines. (check-in: 1dada51582 user: mistachkin tags: trunk) | |
2011-08-23
| ||
18:06 | Merge latest trunk changes into the apple-osx branch. (check-in: c5f7977b89 user: dan tags: apple-osx) | |
Changes
Changes to Makefile.msc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # # nmake Makefile for SQLite # # The toplevel directory of the source tree. This is the directory # that contains this "Makefile.msc". # TOP = . # Set this non-0 to create and use the SQLite amalgamation file. # USE_AMALGAMATION = 1 # Version numbers and release number for the SQLite being compiled. # VERSION = 3.7 VERSION_NUMBER = 3007007 RELEASE = 3.7.7 # C Compiler and options for use in building executables that # will run on the platform that is doing the build. # | > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | # # nmake Makefile for SQLite # # The toplevel directory of the source tree. This is the directory # that contains this "Makefile.msc". # TOP = . # Set this non-0 to create and use the SQLite amalgamation file. # USE_AMALGAMATION = 1 # Set this to non-0 to create and use PDBs. # SYMBOLS = 1 # Set this to one of the following values to enable various debugging # features. Each level includes the debugging options from the previous # levels. Currently, the recognized values for DEBUG are: # # 0 == NDEBUG: Disables assert() and other runtime diagnostics. # 1 == Disables NDEBUG and all optimizations and then enables PDBs. # 2 == SQLITE_DEBUG: Enables various diagnostics messages and code. # 3 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call. # 4 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros. # 5 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros. # DEBUG = 0 # Version numbers and release number for the SQLite being compiled. # VERSION = 3.7 VERSION_NUMBER = 3007007 RELEASE = 3.7.7 # C Compiler and options for use in building executables that # will run on the platform that is doing the build. # BCC = cl.exe # C Compile and options for use in building executables that # will run on the target platform. (BCC and TCC are usually the # same unless your are cross-compiling.) # TCC = cl.exe -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise # The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in # any extension header files by default. For non-amalgamation # builds, we need to make sure the compiler can find these. # !IF $(USE_AMALGAMATION)==0 TCC = $(TCC) -I$(TOP)\ext\fts3 TCC = $(TCC) -I$(TOP)\ext\rtree !ENDIF # Define -DNDEBUG to compile without debugging (i.e., for production usage) # Omitting the define will cause extra debugging code to be inserted and # includes extra comments when "EXPLAIN stmt" is used. # !IF $(DEBUG)==0 TCC = $(TCC) -DNDEBUG !ENDIF !IF $(DEBUG)>1 TCC = $(TCC) -DSQLITE_DEBUG !ENDIF !IF $(DEBUG)>3 TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1 !ENDIF !IF $(DEBUG)>4 TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE !ENDIF # # Prevent warnings about "insecure" runtime library functions being used. # TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS # # Use native Win32 heap instead of malloc/free? # # TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1 # # Validate the heap on every call into the native Win32 heap subsystem? # !IF $(DEBUG)>2 TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 !ENDIF # The locations of the Tcl header and library files. Also, the library that # non-stubs enabled programs using Tcl must link against. These variables # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment # prior to running nmake in order to match the actual installed location and # version on this machine. # !if "$(TCLINCDIR)" == "" |
︙ | ︙ | |||
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | # END required Windows option TCC = $(TCC) $(OPT_FEATURE_FLAGS) # Add in any optional parameters specified on the make commane line # ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1". TCC = $(TCC) $(OPTS) # libtool compile/link LTCOMPILE = $(TCC) -Fo$@ LTLIB = lib.exe LTLINK = $(TCC) -Fe$@ # If a platform was set, force the linker to target that. # Note that the vcvars*.bat family of batch files typically # set this for you. Otherwise, the linker will attempt # to deduce the binary type based on the object files. !IF "$(PLATFORM)"!="" LTLINKOPTS = /MACHINE:$(PLATFORM) LTLIBOPTS = /MACHINE:$(PLATFORM) !ENDIF # nawk compatible awk. NAWK = gawk.exe # You should not have to change anything below this line ############################################################################### | > > > > > > > > > > > > > > > > > | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | # END required Windows option TCC = $(TCC) $(OPT_FEATURE_FLAGS) # Add in any optional parameters specified on the make commane line # ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1". TCC = $(TCC) $(OPTS) # If symbols are enabled, enable PDBs. # If debugging is enabled, disable all optimizations and enable PDBs. !IF $(DEBUG)>0 TCC = $(TCC) -Od -D_DEBUG !ELSE TCC = $(TCC) -O2 !ENDIF !IF $(DEBUG)>0 || $(SYMBOLS)!=0 TCC = $(TCC) -Zi !ENDIF # libtool compile/link LTCOMPILE = $(TCC) -Fo$@ LTLIB = lib.exe LTLINK = $(TCC) -Fe$@ # If a platform was set, force the linker to target that. # Note that the vcvars*.bat family of batch files typically # set this for you. Otherwise, the linker will attempt # to deduce the binary type based on the object files. !IF "$(PLATFORM)"!="" LTLINKOPTS = /MACHINE:$(PLATFORM) LTLIBOPTS = /MACHINE:$(PLATFORM) !ENDIF # If debugging is enabled, enable PDBs. !IF $(DEBUG)>0 || $(SYMBOLS)!=0 LTLINKOPTS = $(LTLINKOPTS) /DEBUG !ENDIF # nawk compatible awk. NAWK = gawk.exe # You should not have to change anything below this line ############################################################################### |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
384 385 386 387 388 389 390 | sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl tclsh $(TOP)/tool/mksqlite3c.tcl echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c cat sqlite3.c >>tclsqlite3.c echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c | | | 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 | sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl tclsh $(TOP)/tool/mksqlite3c.tcl echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c cat sqlite3.c >>tclsqlite3.c echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c sqlite3.c-debug: target_source $(TOP)/tool/mksqlite3c.tcl tclsh $(TOP)/tool/mksqlite3c.tcl --linemacros echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c cat sqlite3.c >>tclsqlite3.c echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c echo '#line 1 "tclsqlite.c"' >>tclsqlite3.c cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c |
︙ | ︙ |
Changes to src/backup.c.
︙ | ︙ | |||
406 407 408 409 410 411 412 | } /* Update the schema version field in the destination database. This ** is to make sure that the schema-version really does change in ** the case where the source and destination databases have the ** same schema version. */ | | | < < | | | | < | < < < < | < | | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 406 407 408 409 410 411 412 413 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 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | } /* Update the schema version field in the destination database. This ** is to make sure that the schema-version really does change in ** the case where the source and destination databases have the ** same schema version. */ if( rc==SQLITE_DONE ){ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); if( rc==SQLITE_OK ){ if( p->pDestDb ){ sqlite3ResetInternalSchema(p->pDestDb, -1); } if( destMode==PAGER_JOURNALMODE_WAL ){ rc = sqlite3BtreeSetVersion(p->pDest, 2); } } if( rc==SQLITE_OK ){ int nDestTruncate; /* Set nDestTruncate to the final number of pages in the destination ** database. The complication here is that the destination page ** size may be different to the source page size. ** ** If the source page size is smaller than the destination page size, ** round up. In this case the call to sqlite3OsTruncate() below will ** fix the size of the file. However it is important to call ** sqlite3PagerTruncateImage() here so that any pages in the ** destination file that lie beyond the nDestTruncate page mark are ** journalled by PagerCommitPhaseOne() before they are destroyed ** by the file truncation. */ assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) ); assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) ); if( pgszSrc<pgszDest ){ int ratio = pgszDest/pgszSrc; nDestTruncate = (nSrcPage+ratio-1)/ratio; if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){ nDestTruncate--; } }else{ nDestTruncate = nSrcPage * (pgszSrc/pgszDest); } sqlite3PagerTruncateImage(pDestPager, nDestTruncate); if( pgszSrc<pgszDest ){ /* If the source page-size is smaller than the destination page-size, ** two extra things may need to happen: ** ** * The destination may need to be truncated, and ** ** * Data stored on the pages immediately following the ** pending-byte page in the source database may need to be ** copied into the destination database. */ const i64 iSize = (i64)pgszSrc * (i64)nSrcPage; sqlite3_file * const pFile = sqlite3PagerFile(pDestPager); i64 iOff; i64 iEnd; assert( pFile ); assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || ( nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest )); /* This call ensures that all data required to recreate the original ** database has been stored in the journal for pDestPager and the ** journal synced to disk. So at this point we may safely modify ** the database file in any way, knowing that if a power failure ** occurs, the original database will be reconstructed from the ** journal file. */ rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); /* Write the extra pages and truncate the database file as required */ iEnd = MIN(PENDING_BYTE + pgszDest, iSize); for( iOff=PENDING_BYTE+pgszSrc; rc==SQLITE_OK && iOff<iEnd; iOff+=pgszSrc ){ PgHdr *pSrcPg = 0; const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1); rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); if( rc==SQLITE_OK ){ u8 *zData = sqlite3PagerGetData(pSrcPg); rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff); } sqlite3PagerUnref(pSrcPg); } if( rc==SQLITE_OK ){ rc = backupTruncateFile(pFile, iSize); } /* Sync the database file to disk. */ if( rc==SQLITE_OK ){ rc = sqlite3PagerSync(pDestPager); } }else{ rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); } /* Finish committing the transaction to the destination database. */ if( SQLITE_OK==rc && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0)) ){ rc = SQLITE_DONE; } } } /* If bCloseTrans is true, then this function opened a read transaction ** on the source database. Close the read transaction here. There is ** no need to check the return values of the btree methods here, as ** "committing" a read-only transaction cannot fail. |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 | /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */ assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 ); /* A BTREE_SINGLE database is always a temporary and/or ephemeral */ assert( (flags & BTREE_SINGLE)==0 || isTempDb ); if( db->flags & SQLITE_NoReadlock ){ flags |= BTREE_NO_READLOCK; } if( isMemdb ){ flags |= BTREE_MEMORY; } if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){ vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; } p = sqlite3MallocZero(sizeof(Btree)); if( !p ){ return SQLITE_NOMEM; | > > > > > > > > > > > | 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 | /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */ assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 ); /* A BTREE_SINGLE database is always a temporary and/or ephemeral */ assert( (flags & BTREE_SINGLE)==0 || isTempDb ); /* The BTREE_SORTER flag is only used if SQLITE_OMIT_MERGE_SORT is undef */ #ifdef SQLITE_OMIT_MERGE_SORT assert( (flags & BTREE_SORTER)==0 ); #endif /* BTREE_SORTER is always on a BTREE_SINGLE, BTREE_OMIT_JOURNAL */ assert( (flags & BTREE_SORTER)==0 || (flags & (BTREE_SINGLE|BTREE_OMIT_JOURNAL)) ==(BTREE_SINGLE|BTREE_OMIT_JOURNAL) ); if( db->flags & SQLITE_NoReadlock ){ flags |= BTREE_NO_READLOCK; } if( isMemdb ){ flags |= BTREE_MEMORY; flags &= ~BTREE_SORTER; } if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){ vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; } p = sqlite3MallocZero(sizeof(Btree)); if( !p ){ return SQLITE_NOMEM; |
︙ | ︙ | |||
8197 8198 8199 8200 8201 8202 8203 | } } } pBt->doNotUseWAL = 0; return rc; } | < < | 8208 8209 8210 8211 8212 8213 8214 | } } } pBt->doNotUseWAL = 0; return rc; } |
Changes to src/btree.h.
︙ | ︙ | |||
57 58 59 60 61 62 63 64 65 66 67 68 69 70 | ** pager.h. */ #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ #define BTREE_MEMORY 4 /* This is an in-memory DB */ #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ int sqlite3BtreeClose(Btree*); int sqlite3BtreeSetCacheSize(Btree*,int); int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); int sqlite3BtreeSyncDisabled(Btree*); int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); int sqlite3BtreeGetPageSize(Btree*); | > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | ** pager.h. */ #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ #define BTREE_MEMORY 4 /* This is an in-memory DB */ #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ #define BTREE_SORTER 32 /* Used as accumulator in external merge sort */ int sqlite3BtreeClose(Btree*); int sqlite3BtreeSetCacheSize(Btree*,int); int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); int sqlite3BtreeSyncDisabled(Btree*); int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); int sqlite3BtreeGetPageSize(Btree*); |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
1670 1671 1672 1673 1674 1675 1676 | int noErr /* Suppress error messages if VIEW already exists */ ){ Table *p; int n; const char *z; Token sEnd; DbFixer sFix; | | | 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 | int noErr /* Suppress error messages if VIEW already exists */ ){ Table *p; int n; const char *z; Token sEnd; DbFixer sFix; Token *pName = 0; int iDb; sqlite3 *db = pParse->db; if( pParse->nVar>0 ){ sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); sqlite3SelectDelete(db, pSelect); return; |
︙ | ︙ | |||
2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 | sqlite3VdbeChangeP5(v, 1); } /* Open the sorter cursor if we are to use one. */ if( bUseSorter ){ iSorter = pParse->nTab++; sqlite3VdbeAddOp4(v, OP_OpenSorter, iSorter, 0, 0, (char*)pKey, P4_KEYINFO); } /* Open the table. Loop through all rows of the table, inserting index ** records into the sorter. */ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); regRecord = sqlite3GetTempReg(pParse); | > | 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 | sqlite3VdbeChangeP5(v, 1); } /* Open the sorter cursor if we are to use one. */ if( bUseSorter ){ iSorter = pParse->nTab++; sqlite3VdbeAddOp4(v, OP_OpenSorter, iSorter, 0, 0, (char*)pKey, P4_KEYINFO); sqlite3VdbeChangeP5(v, BTREE_SORTER); } /* Open the table. Loop through all rows of the table, inserting index ** records into the sorter. */ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); regRecord = sqlite3GetTempReg(pParse); |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
232 233 234 235 236 237 238 239 240 241 242 243 244 245 | assert(sizeof(x)==8); assert(sizeof(x)==sizeof(y)); memcpy(&y, &x, 8); assert( sqlite3IsNaN(y) ); } #endif #endif return rc; } /* ** Undo the effects of sqlite3_initialize(). Must not be called while ** there are outstanding database connections or memory allocations or | > > > > > > > > > > | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | assert(sizeof(x)==8); assert(sizeof(x)==sizeof(y)); memcpy(&y, &x, 8); assert( sqlite3IsNaN(y) ); } #endif #endif /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT ** compile-time option. */ #ifdef SQLITE_EXTRA_INIT if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){ int SQLITE_EXTRA_INIT(void); rc = SQLITE_EXTRA_INIT(); } #endif return rc; } /* ** Undo the effects of sqlite3_initialize(). Must not be called while ** there are outstanding database connections or memory allocations or |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
256 257 258 259 260 261 262 | /* ** Allowed values for the unixFile.ctrlFlags bitmask: */ #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ #define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ | > | > > > | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | /* ** Allowed values for the unixFile.ctrlFlags bitmask: */ #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ #define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ #ifndef SQLITE_DISABLE_DIRSYNC # define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */ #else # define UNIXFILE_DIRSYNC 0x00 #endif /* ** Include code that is common to all os_*.c files */ #include "os_common.h" /* |
︙ | ︙ | |||
3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 | if( close(pFile->dirfd) ){ pFile->lastErrno = errno; rc = SQLITE_IOERR_DIR_CLOSE; } #else robust_close(pFile, dirfd, __LINE__); #endif } pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; } return rc; } | > > | 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 | if( close(pFile->dirfd) ){ pFile->lastErrno = errno; rc = SQLITE_IOERR_DIR_CLOSE; } #else robust_close(pFile, dirfd, __LINE__); #endif }else if( rc==SQLITE_CANTOPEN ){ rc = SQLITE_OK; } pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; } return rc; } |
︙ | ︙ | |||
5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 | #if OSCLOSE_CHECK_CLOSE_IOERR if( close(fd)&&!rc ){ rc = SQLITE_IOERR_DIR_CLOSE; } #else robust_close(0, fd, __LINE__); #endif } } #endif return rc; } /* | > > | 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 | #if OSCLOSE_CHECK_CLOSE_IOERR if( close(fd)&&!rc ){ rc = SQLITE_IOERR_DIR_CLOSE; } #else robust_close(0, fd, __LINE__); #endif }else if( rc==SQLITE_CANTOPEN ){ rc = SQLITE_OK; } } #endif return rc; } /* |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
115 116 117 118 119 120 121 122 123 124 125 126 127 128 | HANDLE hMutex; /* Mutex used to control access to shared lock */ HANDLE hShared; /* Shared memory segment used for locking */ winceLock local; /* Locks obtained by this instance of winFile */ winceLock *shared; /* Global shared lock memory for the file */ #endif }; /* ** Forward prototypes. */ static int getSectorSize( sqlite3_vfs *pVfs, const char *zRelative /* UTF-8 file name */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | HANDLE hMutex; /* Mutex used to control access to shared lock */ HANDLE hShared; /* Shared memory segment used for locking */ winceLock local; /* Locks obtained by this instance of winFile */ winceLock *shared; /* Global shared lock memory for the file */ #endif }; /* * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the * various Win32 API heap functions instead of our own. */ #ifdef SQLITE_WIN32_MALLOC /* * The initial size of the Win32-specific heap. This value may be zero. */ #ifndef SQLITE_WIN32_HEAP_INIT_SIZE # define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \ (SQLITE_DEFAULT_PAGE_SIZE) + 4194304) #endif /* * The maximum size of the Win32-specific heap. This value may be zero. */ #ifndef SQLITE_WIN32_HEAP_MAX_SIZE # define SQLITE_WIN32_HEAP_MAX_SIZE (0) #endif /* * The extra flags to use in calls to the Win32 heap APIs. This value may be * zero for the default behavior. */ #ifndef SQLITE_WIN32_HEAP_FLAGS # define SQLITE_WIN32_HEAP_FLAGS (0) #endif /* ** The winMemData structure stores information required by the Win32-specific ** sqlite3_mem_methods implementation. */ typedef struct winMemData winMemData; struct winMemData { #ifndef NDEBUG u32 magic; /* Magic number to detect structure corruption. */ #endif HANDLE hHeap; /* The handle to our heap. */ BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */ }; #ifndef NDEBUG #define WINMEM_MAGIC 0x42b2830b #endif static struct winMemData win_mem_data = { #ifndef NDEBUG WINMEM_MAGIC, #endif NULL, FALSE }; #ifndef NDEBUG #define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC ) #else #define winMemAssertMagic() #endif #define winMemGetHeap() win_mem_data.hHeap static void *winMemMalloc(int nBytes); static void winMemFree(void *pPrior); static void *winMemRealloc(void *pPrior, int nBytes); static int winMemSize(void *p); static int winMemRoundup(int n); static int winMemInit(void *pAppData); static void winMemShutdown(void *pAppData); const sqlite3_mem_methods *sqlite3MemGetWin32(void); #endif /* SQLITE_WIN32_MALLOC */ /* ** Forward prototypes. */ static int getSectorSize( sqlite3_vfs *pVfs, const char *zRelative /* UTF-8 file name */ |
︙ | ︙ | |||
167 168 169 170 171 172 173 174 175 176 177 178 179 180 | GetVersionEx(&sInfo); sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; } return sqlite3_os_type==2; } #endif /* SQLITE_OS_WINCE */ /* ** Convert a UTF-8 string to microsoft unicode (UTF-16?). ** ** Space to hold the returned string is obtained from malloc. */ static WCHAR *utf8ToUnicode(const char *zFilename){ int nChar; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 | GetVersionEx(&sInfo); sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; } return sqlite3_os_type==2; } #endif /* SQLITE_OS_WINCE */ #ifdef SQLITE_WIN32_MALLOC /* ** Allocate nBytes of memory. */ static void *winMemMalloc(int nBytes){ HANDLE hHeap; void *p; winMemAssertMagic(); hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif assert( nBytes>=0 ); p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes); if( !p ){ sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p", nBytes, GetLastError(), (void*)hHeap); } return p; } /* ** Free memory. */ static void winMemFree(void *pPrior){ HANDLE hHeap; winMemAssertMagic(); hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); #endif if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */ if( !HeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){ sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p", pPrior, GetLastError(), (void*)hHeap); } } /* ** Change the size of an existing memory allocation */ static void *winMemRealloc(void *pPrior, int nBytes){ HANDLE hHeap; void *p; winMemAssertMagic(); hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); #endif assert( nBytes>=0 ); if( !pPrior ){ p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes); }else{ p = HeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes); } if( !p ){ sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p", pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, GetLastError(), (void*)hHeap); } return p; } /* ** Return the size of an outstanding allocation, in bytes. */ static int winMemSize(void *p){ HANDLE hHeap; SIZE_T n; winMemAssertMagic(); hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif if( !p ) return 0; n = HeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p); if( n==(SIZE_T)-1 ){ sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p", p, GetLastError(), (void*)hHeap); return 0; } return (int)n; } /* ** Round up a request size to the next valid allocation size. */ static int winMemRoundup(int n){ return n; } /* ** Initialize this module. */ static int winMemInit(void *pAppData){ winMemData *pWinMemData = (winMemData *)pAppData; if( !pWinMemData ) return SQLITE_ERROR; assert( pWinMemData->magic==WINMEM_MAGIC ); if( !pWinMemData->hHeap ){ pWinMemData->hHeap = HeapCreate(SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE); if( !pWinMemData->hHeap ){ sqlite3_log(SQLITE_NOMEM, "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u", GetLastError(), SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE); return SQLITE_NOMEM; } pWinMemData->bOwned = TRUE; } assert( pWinMemData->hHeap!=0 ); assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif return SQLITE_OK; } /* ** Deinitialize this module. */ static void winMemShutdown(void *pAppData){ winMemData *pWinMemData = (winMemData *)pAppData; if( !pWinMemData ) return; if( pWinMemData->hHeap ){ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); #ifdef SQLITE_WIN32_MALLOC_VALIDATE assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif if( pWinMemData->bOwned ){ if( !HeapDestroy(pWinMemData->hHeap) ){ sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p", GetLastError(), (void*)pWinMemData->hHeap); } pWinMemData->bOwned = FALSE; } pWinMemData->hHeap = NULL; } } /* ** Populate the low-level memory allocation function pointers in ** sqlite3GlobalConfig.m with pointers to the routines in this file. The ** arguments specify the block of memory to manage. ** ** This routine is only called by sqlite3_config(), and therefore ** is not required to be threadsafe (it is not). */ const sqlite3_mem_methods *sqlite3MemGetWin32(void){ static const sqlite3_mem_methods winMemMethods = { winMemMalloc, winMemFree, winMemRealloc, winMemSize, winMemRoundup, winMemInit, winMemShutdown, &win_mem_data }; return &winMemMethods; } void sqlite3MemSetDefault(void){ sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32()); } #endif /* SQLITE_WIN32_MALLOC */ /* ** Convert a UTF-8 string to microsoft unicode (UTF-16?). ** ** Space to hold the returned string is obtained from malloc. */ static WCHAR *utf8ToUnicode(const char *zFilename){ int nChar; |
︙ | ︙ | |||
1347 1348 1349 1350 1351 1352 1353 | return SQLITE_OK; } case SQLITE_FCNTL_CHUNK_SIZE: { pFile->szChunk = *(int *)pArg; return SQLITE_OK; } case SQLITE_FCNTL_SIZE_HINT: { | > | > > > > | | | > > | | 1599 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 | return SQLITE_OK; } case SQLITE_FCNTL_CHUNK_SIZE: { pFile->szChunk = *(int *)pArg; return SQLITE_OK; } case SQLITE_FCNTL_SIZE_HINT: { winFile *pFile = (winFile*)id; sqlite3_int64 oldSz; int rc = winFileSize(id, &oldSz); if( rc==SQLITE_OK ){ sqlite3_int64 newSz = *(sqlite3_int64*)pArg; if( newSz>oldSz ){ SimulateIOErrorBenign(1); rc = winTruncate(id, newSz); SimulateIOErrorBenign(0); } } return rc; } case SQLITE_FCNTL_PERSIST_WAL: { int bPersist = *(int*)pArg; if( bPersist<0 ){ *(int*)pArg = pFile->bPersistWal; }else{ pFile->bPersistWal = bPersist!=0; |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
616 617 618 619 620 621 622 623 624 625 626 627 628 629 | u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ u8 memDb; /* True to inhibit all file I/O */ /************************************************************************** ** The following block contains those class members that change during ** routine opertion. Class members not in this block are either fixed ** when the pager is first created or else only change when there is a ** significant mode change (such as changing the page_size, locking_mode, ** or the journal_mode). From another view, these class members describe | > > | 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 | u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ u8 memDb; /* True to inhibit all file I/O */ u8 hasSeenStress; /* pagerStress() called one or more times */ u8 isSorter; /* True for a PAGER_SORTER */ /************************************************************************** ** The following block contains those class members that change during ** routine opertion. Class members not in this block are either fixed ** when the pager is first created or else only change when there is a ** significant mode change (such as changing the page_size, locking_mode, ** or the journal_mode). From another view, these class members describe |
︙ | ︙ | |||
838 839 840 841 842 843 844 845 846 847 848 849 850 851 | assert( p->noSync ); assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_MEMORY ); assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN ); assert( pagerUseWal(p)==0 ); } /* If changeCountDone is set, a RESERVED lock or greater must be held ** on the file. */ assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK ); assert( p->eLock!=PENDING_LOCK ); | > > > > > > > > > | 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 | assert( p->noSync ); assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_MEMORY ); assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN ); assert( pagerUseWal(p)==0 ); } /* A sorter is a temp file that never spills to disk and always has ** the doNotSpill flag set */ if( p->isSorter ){ assert( p->tempFile ); assert( p->doNotSpill ); assert( p->fd->pMethods==0 ); } /* If changeCountDone is set, a RESERVED lock or greater must be held ** on the file. */ assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK ); assert( p->eLock!=PENDING_LOCK ); |
︙ | ︙ | |||
3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 | ** is made to roll it back. If an error occurs during the rollback ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ int sqlite3PagerClose(Pager *pPager){ u8 *pTmp = (u8 *)pPager->pTmpSpace; disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); pPager->pWal = 0; | > | 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 | ** is made to roll it back. If an error occurs during the rollback ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ int sqlite3PagerClose(Pager *pPager){ u8 *pTmp = (u8 *)pPager->pTmpSpace; assert( assert_pager_state(pPager) ); disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); pPager->pWal = 0; |
︙ | ︙ | |||
4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 | ** Spilling is also prohibited when in an error state since that could ** lead to database corruption. In the current implementaton it ** is impossible for sqlite3PCacheFetch() to be called with createFlag==1 ** while in the error state, hence it is impossible for this routine to ** be called in the error state. Nevertheless, we include a NEVER() ** test for the error state as a safeguard against future changes. */ if( NEVER(pPager->errCode) ) return SQLITE_OK; if( pPager->doNotSpill ) return SQLITE_OK; if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){ return SQLITE_OK; } pPg->pDirty = 0; | > | 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 | ** Spilling is also prohibited when in an error state since that could ** lead to database corruption. In the current implementaton it ** is impossible for sqlite3PCacheFetch() to be called with createFlag==1 ** while in the error state, hence it is impossible for this routine to ** be called in the error state. Nevertheless, we include a NEVER() ** test for the error state as a safeguard against future changes. */ pPager->hasSeenStress = 1; if( NEVER(pPager->errCode) ) return SQLITE_OK; if( pPager->doNotSpill ) return SQLITE_OK; if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){ return SQLITE_OK; } pPg->pDirty = 0; |
︙ | ︙ | |||
4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 | }else if( memDb ){ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; return SQLITE_OK; } | > > > > > > | 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 | }else if( memDb ){ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ #ifndef SQLITE_OMIT_MERGE_SORT if( flags & PAGER_SORTER ){ pPager->doNotSpill = 1; pPager->isSorter = 1; } #endif *ppPager = pPager; return SQLITE_OK; } |
︙ | ︙ | |||
6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 | /* ** Return true if this is an in-memory pager. */ int sqlite3PagerIsMemdb(Pager *pPager){ return MEMDB; } /* ** Check that there are at least nSavepoint savepoints open. If there are ** currently less than nSavepoints open, then open one or more savepoints ** to make up the difference. If the number of savepoints is already ** equal to nSavepoint, then this function is a no-op. ** | > > > > > > > > > > > | 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 | /* ** Return true if this is an in-memory pager. */ int sqlite3PagerIsMemdb(Pager *pPager){ return MEMDB; } #ifndef SQLITE_OMIT_MERGE_SORT /* ** Return true if the pager has seen a pagerStress callback. */ int sqlite3PagerUnderStress(Pager *pPager){ assert( pPager->isSorter ); assert( pPager->doNotSpill ); return pPager->hasSeenStress; } #endif /* ** Check that there are at least nSavepoint savepoints open. If there are ** currently less than nSavepoints open, then open one or more savepoints ** to make up the difference. If the number of savepoints is already ** equal to nSavepoint, then this function is a no-op. ** |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
56 57 58 59 60 61 62 63 64 65 66 67 68 69 | ** Allowed values for the flags parameter to sqlite3PagerOpen(). ** ** NOTE: These values must match the corresponding BTREE_ values in btree.h. */ #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ #define PAGER_MEMORY 0x0004 /* In-memory database */ /* ** Valid values for the second argument to sqlite3PagerLockingMode(). */ #define PAGER_LOCKINGMODE_QUERY -1 #define PAGER_LOCKINGMODE_NORMAL 0 #define PAGER_LOCKINGMODE_EXCLUSIVE 1 | > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | ** Allowed values for the flags parameter to sqlite3PagerOpen(). ** ** NOTE: These values must match the corresponding BTREE_ values in btree.h. */ #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ #define PAGER_MEMORY 0x0004 /* In-memory database */ #define PAGER_SORTER 0x0020 /* Accumulator in external merge sort */ /* ** Valid values for the second argument to sqlite3PagerLockingMode(). */ #define PAGER_LOCKINGMODE_QUERY -1 #define PAGER_LOCKINGMODE_NORMAL 0 #define PAGER_LOCKINGMODE_EXCLUSIVE 1 |
︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 160 161 162 163 164 | const char *sqlite3PagerFilename(Pager*); const sqlite3_vfs *sqlite3PagerVfs(Pager*); sqlite3_file *sqlite3PagerFile(Pager*); const char *sqlite3PagerJournalname(Pager*); int sqlite3PagerNosync(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); /* Functions used to truncate the database file. */ void sqlite3PagerTruncateImage(Pager*,Pgno); #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) void *sqlite3PagerCodec(DbPage *); #endif | > > > | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | const char *sqlite3PagerFilename(Pager*); const sqlite3_vfs *sqlite3PagerVfs(Pager*); sqlite3_file *sqlite3PagerFile(Pager*); const char *sqlite3PagerJournalname(Pager*); int sqlite3PagerNosync(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); #ifndef SQLITE_OMIT_MERGE_SORT int sqlite3PagerUnderStress(Pager*); #endif /* Functions used to truncate the database file. */ void sqlite3PagerTruncateImage(Pager*,Pgno); #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) void *sqlite3PagerCodec(DbPage *); #endif |
︙ | ︙ |
Changes to src/pcache1.c.
︙ | ︙ | |||
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | struct PGroup { sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */ int nMaxPage; /* Sum of nMax for purgeable caches */ int nMinPage; /* Sum of nMin for purgeable caches */ int mxPinned; /* nMaxpage + 10 - nMinPage */ int nCurrentPage; /* Number of purgeable pages allocated */ PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */ PGroupBlockList *pBlockList; /* List of block-lists for this group */ }; /* ** If SQLITE_PAGECACHE_BLOCKALLOC is defined when the library is built, ** each PGroup structure has a linked list of the the following starting ** at PGroup.pBlockList. There is one entry for each distinct page-size ** currently used by members of the PGroup (i.e. 1024 bytes, 4096 bytes | > > > | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | struct PGroup { sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */ int nMaxPage; /* Sum of nMax for purgeable caches */ int nMinPage; /* Sum of nMin for purgeable caches */ int mxPinned; /* nMaxpage + 10 - nMinPage */ int nCurrentPage; /* Number of purgeable pages allocated */ PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */ #ifdef SQLITE_PAGECACHE_BLOCKALLOC int isBusy; /* Do not run ReleaseMemory() if true */ PGroupBlockList *pBlockList; /* List of block-lists for this group */ #endif }; /* ** If SQLITE_PAGECACHE_BLOCKALLOC is defined when the library is built, ** each PGroup structure has a linked list of the the following starting ** at PGroup.pBlockList. There is one entry for each distinct page-size ** currently used by members of the PGroup (i.e. 1024 bytes, 4096 bytes |
︙ | ︙ | |||
397 398 399 400 401 402 403 | PGroupBlockList *pList; PGroupBlock *pBlock; int i; nByte += sizeof(PGroupBlockList *); nByte = ROUND8(nByte); | < | | | | | | > > | | | | | | > | | | | < < | | | | | < < > | 400 401 402 403 404 405 406 407 408 409 410 411 412 413 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 439 440 441 442 443 444 445 446 447 | PGroupBlockList *pList; PGroupBlock *pBlock; int i; nByte += sizeof(PGroupBlockList *); nByte = ROUND8(nByte); for(pList=pGroup->pBlockList; pList; pList=pList->pNext){ if( pList->nByte==nByte ) break; } if( pList==0 ){ PGroupBlockList *pNew; assert( pGroup->isBusy==0 ); assert( sqlite3_mutex_held(pGroup->mutex) ); pGroup->isBusy = 1; /* Disable sqlite3PcacheReleaseMemory() */ pNew = (PGroupBlockList *)sqlite3MallocZero(sizeof(PGroupBlockList)); pGroup->isBusy = 0; /* Reenable sqlite3PcacheReleaseMemory() */ if( pNew==0 ){ /* malloc() failure. Return early. */ return 0; } #ifdef SQLITE_DEBUG for(pList=pGroup->pBlockList; pList; pList=pList->pNext){ assert( pList->nByte!=nByte ); } #endif pNew->nByte = nByte; pNew->pNext = pGroup->pBlockList; pGroup->pBlockList = pNew; pList = pNew; } pBlock = pList->pFirst; if( pBlock==0 || pBlock->mUsed==(((Bitmask)1<<pBlock->nEntry)-1) ){ int sz; /* Allocate a new block. Try to allocate enough space for the PGroupBlock ** structure and MINENTRY allocations of nByte bytes each. If the ** allocator returns more memory than requested, then more than MINENTRY ** allocations may fit in it. */ assert( sqlite3_mutex_held(pGroup->mutex) ); pcache1LeaveMutex(pCache->pGroup); sz = sizeof(PGroupBlock) + PAGECACHE_BLOCKALLOC_MINENTRY * nByte; pBlock = (PGroupBlock *)sqlite3Malloc(sz); pcache1EnterMutex(pCache->pGroup); if( !pBlock ){ freeListIfEmpty(pGroup, pList); |
︙ | ︙ | |||
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 | pList->pFirst = pBlock->pNext; pList->pFirst->pPrev = 0; pBlock->pPrev = pList->pLast; pBlock->pNext = 0; pList->pLast->pNext = pBlock; pList->pLast = pBlock; } #else /* The group mutex must be released before pcache1Alloc() is called. This ** is because it may call sqlite3_release_memory(), which assumes that ** this mutex is not held. */ assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); pcache1LeaveMutex(pCache->pGroup); pPg = pcache1Alloc(nByte); pcache1EnterMutex(pCache->pGroup); | > > > > < < > | 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 | pList->pFirst = pBlock->pNext; pList->pFirst->pPrev = 0; pBlock->pPrev = pList->pLast; pBlock->pNext = 0; pList->pLast->pNext = pBlock; pList->pLast = pBlock; } p = PAGE_TO_PGHDR1(pCache, pPg); if( pCache->bPurgeable ){ pCache->pGroup->nCurrentPage++; } #else /* The group mutex must be released before pcache1Alloc() is called. This ** is because it may call sqlite3_release_memory(), which assumes that ** this mutex is not held. */ assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); pcache1LeaveMutex(pCache->pGroup); pPg = pcache1Alloc(nByte); pcache1EnterMutex(pCache->pGroup); if( pPg ){ p = PAGE_TO_PGHDR1(pCache, pPg); if( pCache->bPurgeable ){ pCache->pGroup->nCurrentPage++; } }else{ p = 0; } #endif return p; } /* ** Free a page object allocated by pcache1AllocPage(). ** ** The pointer is allowed to be NULL, which is prudent. But it turns out |
︙ | ︙ | |||
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 | ** ** nReq is the number of bytes of memory required. Once this much has ** been released, the function returns. The return value is the total number ** of bytes of memory released. */ int sqlite3PcacheReleaseMemory(int nReq){ int nFree = 0; assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); assert( sqlite3_mutex_notheld(pcache1.mutex) ); if( pcache1.pStart==0 ){ PgHdr1 *p; pcache1EnterMutex(&pcache1.grp); while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){ nFree += pcache1MemSize(PGHDR1_TO_PAGE(p)); | > > > | 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 | ** ** nReq is the number of bytes of memory required. Once this much has ** been released, the function returns. The return value is the total number ** of bytes of memory released. */ int sqlite3PcacheReleaseMemory(int nReq){ int nFree = 0; #ifdef SQLITE_PAGECACHE_BLOCKALLOC if( pcache1.grp.isBusy ) return 0; #endif assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); assert( sqlite3_mutex_notheld(pcache1.mutex) ); if( pcache1.pStart==0 ){ PgHdr1 *p; pcache1EnterMutex(&pcache1.grp); while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){ nFree += pcache1MemSize(PGHDR1_TO_PAGE(p)); |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
1202 1203 1204 1205 1206 1207 1208 | ** and that this object is only useful to a tiny minority of applications ** with specialized memory allocation requirements. This object is ** also used during testing of SQLite in order to specify an alternative ** memory allocator that simulates memory out-of-memory conditions in ** order to verify that SQLite recovers gracefully from such ** conditions. ** | | | < < < | < < < | 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 | ** and that this object is only useful to a tiny minority of applications ** with specialized memory allocation requirements. This object is ** also used during testing of SQLite in order to specify an alternative ** memory allocator that simulates memory out-of-memory conditions in ** order to verify that SQLite recovers gracefully from such ** conditions. ** ** The xMalloc, xRealloc, and xFree methods must work like the ** malloc(), realloc() and free() functions from the standard C library. ** ^SQLite guarantees that the second argument to ** xRealloc is always a value returned by a prior call to xRoundup. ** ** xSize should return the allocated size of a memory allocation ** previously obtained from xMalloc or xRealloc. The allocated size ** is always at least as big as the requested size but may be larger. ** ** The xRoundup method returns what would be the allocated size of ** a memory allocation given a particular requested size. Most memory |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | #endif /* ** Exactly one of the following macros must be defined in order to ** specify which memory allocation subsystem to use. ** ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() ** SQLITE_MEMDEBUG // Debugging version of system malloc() ** ** (Historical note: There used to be several other options, but we've ** pared it down to just these two.) ** ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as ** the default. */ | > > > > > > | | | | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | #endif /* ** Exactly one of the following macros must be defined in order to ** specify which memory allocation subsystem to use. ** ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() ** SQLITE_WIN32_MALLOC // Use Win32 native heap API ** SQLITE_MEMDEBUG // Debugging version of system malloc() ** ** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the ** assert() macro is enabled, each call into the Win32 native heap subsystem ** will cause HeapValidate to be called. If heap validation should fail, an ** assertion will be triggered. ** ** (Historical note: There used to be several other options, but we've ** pared it down to just these two.) ** ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as ** the default. */ #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1 # error "At most one of the following compile-time configuration options\ is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG" #endif #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0 # define SQLITE_SYSTEM_MALLOC 1 #endif /* ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the ** sizes of memory allocations below this value where possible. */ |
︙ | ︙ | |||
362 363 364 365 366 367 368 369 370 371 372 373 374 375 | ** Provide a default value for SQLITE_TEMP_STORE in case it is not specified ** on the command-line */ #ifndef SQLITE_TEMP_STORE # define SQLITE_TEMP_STORE 1 #endif /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) #endif | > > > > > > > > | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | ** Provide a default value for SQLITE_TEMP_STORE in case it is not specified ** on the command-line */ #ifndef SQLITE_TEMP_STORE # define SQLITE_TEMP_STORE 1 #endif /* ** If all temporary storage is in-memory, then omit the external merge-sort ** logic since it is superfluous. */ #if SQLITE_TEMP_STORE==3 && !defined(SQLITE_OMIT_MERGE_SORT) # define SQLITE_OMIT_MERGE_SORT #endif /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) #endif |
︙ | ︙ |
Changes to src/test6.c.
︙ | ︙ | |||
505 506 507 508 509 510 511 | return sqlite3OsCheckReservedLock(((CrashFile *)pFile)->pRealFile, pResOut); } static int cfFileControl(sqlite3_file *pFile, int op, void *pArg){ if( op==SQLITE_FCNTL_SIZE_HINT ){ CrashFile *pCrash = (CrashFile *)pFile; i64 nByte = *(i64 *)pArg; if( nByte>pCrash->iSize ){ | > | | > > | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | return sqlite3OsCheckReservedLock(((CrashFile *)pFile)->pRealFile, pResOut); } static int cfFileControl(sqlite3_file *pFile, int op, void *pArg){ if( op==SQLITE_FCNTL_SIZE_HINT ){ CrashFile *pCrash = (CrashFile *)pFile; i64 nByte = *(i64 *)pArg; if( nByte>pCrash->iSize ){ if( SQLITE_OK==writeListAppend(pFile, nByte, 0, 0) ){ pCrash->iSize = nByte; } } return SQLITE_OK; } return sqlite3OsFileControl(((CrashFile *)pFile)->pRealFile, op, pArg); } /* ** The xSectorSize() and xDeviceCharacteristics() functions return ** the global values configured by the [sqlite_crashparams] tcl |
︙ | ︙ |
Changes to src/test_malloc.c.
︙ | ︙ | |||
1218 1219 1220 1221 1222 1223 1224 | Tcl_Obj *CONST objv[] ){ if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); return TCL_ERROR; } | | | 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 | Tcl_Obj *CONST objv[] ){ if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); return TCL_ERROR; } switch( SQLITE_PTR_TO_INT(clientData) ){ case 3: { #ifdef SQLITE_ENABLE_MEMSYS3 extern void sqlite3Memsys3Dump(const char*); sqlite3Memsys3Dump(Tcl_GetString(objv[1])); break; #endif } |
︙ | ︙ | |||
1456 1457 1458 1459 1460 1461 1462 | { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 }, { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 }, { "sqlite3_install_memsys3", test_install_memsys3 ,0 }, { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ | | | 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 | { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 }, { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 }, { "sqlite3_install_memsys3", test_install_memsys3 ,0 }, { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData); Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0); } return TCL_OK; } #endif |
Changes to src/test_quota.c.
︙ | ︙ | |||
91 92 93 94 95 96 97 98 99 100 101 102 103 104 | ** to the same file each point to a single instance of this object. */ struct quotaFile { char *zFilename; /* Name of this file */ quotaGroup *pGroup; /* Quota group to which this file belongs */ sqlite3_int64 iSize; /* Current size of this file */ int nRef; /* Number of times this file is open */ quotaFile *pNext, **ppPrev; /* Linked list of files in the same group */ }; /* ** An instance of the following object represents each open connection ** to a file that participates in quota tracking. This object is a ** subclass of sqlite3_file. The sqlite3_file object for the underlying | > | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | ** to the same file each point to a single instance of this object. */ struct quotaFile { char *zFilename; /* Name of this file */ quotaGroup *pGroup; /* Quota group to which this file belongs */ sqlite3_int64 iSize; /* Current size of this file */ int nRef; /* Number of times this file is open */ int deleteOnClose; /* True to delete this file when it closes */ quotaFile *pNext, **ppPrev; /* Linked list of files in the same group */ }; /* ** An instance of the following object represents each open connection ** to a file that participates in quota tracking. This object is a ** subclass of sqlite3_file. The sqlite3_file object for the underlying |
︙ | ︙ | |||
160 161 162 163 164 165 166 167 168 169 170 171 | /* ** Acquire and release the mutex used to serialize access to the ** list of quotaGroups. */ static void quotaEnter(void){ sqlite3_mutex_enter(gQuota.pMutex); } static void quotaLeave(void){ sqlite3_mutex_leave(gQuota.pMutex); } /* If the reference count and threshold for a quotaGroup are both ** zero, then destroy the quotaGroup. */ static void quotaGroupDeref(quotaGroup *pGroup){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | /* ** Acquire and release the mutex used to serialize access to the ** list of quotaGroups. */ static void quotaEnter(void){ sqlite3_mutex_enter(gQuota.pMutex); } static void quotaLeave(void){ sqlite3_mutex_leave(gQuota.pMutex); } /* Count the number of open files in a quotaGroup */ static int quotaGroupOpenFileCount(quotaGroup *pGroup){ int N = 0; quotaFile *pFile = pGroup->pFiles; while( pFile ){ if( pFile->nRef ) N++; pFile = pFile->pNext; } return N; } /* Remove a file from a quota group. */ static void quotaRemoveFile(quotaFile *pFile){ quotaGroup *pGroup = pFile->pGroup; pGroup->iSize -= pFile->iSize; *pFile->ppPrev = pFile->pNext; if( pFile->pNext ) pFile->pNext->ppPrev = pFile->ppPrev; sqlite3_free(pFile); } /* Remove all files from a quota group. It is always the case that ** all files will be closed when this routine is called. */ static void quotaRemoveAllFiles(quotaGroup *pGroup){ while( pGroup->pFiles ){ assert( pGroup->pFiles->nRef==0 ); quotaRemoveFile(pGroup->pFiles); } } /* If the reference count and threshold for a quotaGroup are both ** zero, then destroy the quotaGroup. */ static void quotaGroupDeref(quotaGroup *pGroup){ if( pGroup->iLimit==0 && quotaGroupOpenFileCount(pGroup)==0 ){ quotaRemoveAllFiles(pGroup); *pGroup->ppPrev = pGroup->pNext; if( pGroup->pNext ) pGroup->pNext->ppPrev = pGroup->ppPrev; if( pGroup->xDestroy ) pGroup->xDestroy(pGroup->pArg); sqlite3_free(pGroup); } } |
︙ | ︙ | |||
271 272 273 274 275 276 277 278 279 280 281 282 283 284 | /* Translate an sqlite3_file* that is really a quotaConn* into ** the sqlite3_file* for the underlying original VFS. */ static sqlite3_file *quotaSubOpen(sqlite3_file *pConn){ quotaConn *p = (quotaConn*)pConn; return (sqlite3_file*)&p[1]; } /************************* VFS Method Wrappers *****************************/ /* ** This is the xOpen method used for the "quota" VFS. ** ** Most of the work is done by the underlying original VFS. This method ** simply links the new file into the appropriate quota group if it is a | > > > > > > > > > > > | 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | /* Translate an sqlite3_file* that is really a quotaConn* into ** the sqlite3_file* for the underlying original VFS. */ static sqlite3_file *quotaSubOpen(sqlite3_file *pConn){ quotaConn *p = (quotaConn*)pConn; return (sqlite3_file*)&p[1]; } /* Find a file in a quota group and return a pointer to that file. ** Return NULL if the file is not in the group. */ static quotaFile *quotaFindFile(quotaGroup *pGroup, const char *zName){ quotaFile *pFile = pGroup->pFiles; while( pFile && strcmp(pFile->zFilename, zName)!=0 ){ pFile = pFile->pNext; } return pFile; } /************************* VFS Method Wrappers *****************************/ /* ** This is the xOpen method used for the "quota" VFS. ** ** Most of the work is done by the underlying original VFS. This method ** simply links the new file into the appropriate quota group if it is a |
︙ | ︙ | |||
315 316 317 318 319 320 321 | }else{ /* If we get to this point, it means the file needs to be quota tracked. */ pQuotaOpen = (quotaConn*)pConn; pSubOpen = quotaSubOpen(pConn); rc = pOrigVfs->xOpen(pOrigVfs, zName, pSubOpen, flags, pOutFlags); if( rc==SQLITE_OK ){ | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | < < | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 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 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | }else{ /* If we get to this point, it means the file needs to be quota tracked. */ pQuotaOpen = (quotaConn*)pConn; pSubOpen = quotaSubOpen(pConn); rc = pOrigVfs->xOpen(pOrigVfs, zName, pSubOpen, flags, pOutFlags); if( rc==SQLITE_OK ){ pFile = quotaFindFile(pGroup, zName); if( pFile==0 ){ int nName = strlen(zName); pFile = (quotaFile *)sqlite3_malloc( sizeof(*pFile) + nName + 1 ); if( pFile==0 ){ quotaLeave(); pSubOpen->pMethods->xClose(pSubOpen); return SQLITE_NOMEM; } memset(pFile, 0, sizeof(*pFile)); pFile->zFilename = (char*)&pFile[1]; memcpy(pFile->zFilename, zName, nName+1); pFile->pNext = pGroup->pFiles; if( pGroup->pFiles ) pGroup->pFiles->ppPrev = &pFile->pNext; pFile->ppPrev = &pGroup->pFiles; pGroup->pFiles = pFile; pFile->pGroup = pGroup; pFile->deleteOnClose = (flags & SQLITE_OPEN_DELETEONCLOSE)!=0; } pFile->nRef++; pQuotaOpen->pFile = pFile; if( pSubOpen->pMethods->iVersion==1 ){ pQuotaOpen->base.pMethods = &gQuota.sIoMethodsV1; }else{ pQuotaOpen->base.pMethods = &gQuota.sIoMethodsV2; } } } quotaLeave(); return rc; } /* ** This is the xDelete method used for the "quota" VFS. ** ** If the file being deleted is part of the quota group, then reduce ** the size of the quota group accordingly. And remove the file from ** the set of files in the quota group. */ static int quotaDelete( sqlite3_vfs *pVfs, /* The quota VFS */ const char *zName, /* Name of file to be deleted */ int syncDir /* Do a directory sync after deleting */ ){ int rc; /* Result code */ quotaFile *pFile; /* Files in the quota */ quotaGroup *pGroup; /* The group file belongs to */ sqlite3_vfs *pOrigVfs = gQuota.pOrigVfs; /* Real VFS */ /* Do the actual file delete */ rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir); /* If the file just deleted is a member of a quota group, then remove ** it from that quota group. */ if( rc==SQLITE_OK ){ quotaEnter(); pGroup = quotaGroupFind(zName); if( pGroup ){ pFile = quotaFindFile(pGroup, zName); if( pFile ){ if( pFile->nRef ){ pFile->deleteOnClose = 1; }else{ quotaRemoveFile(pFile); quotaGroupDeref(pGroup); } } } quotaLeave(); } return rc; } /************************ I/O Method Wrappers *******************************/ /* xClose requests get passed through to the original VFS. But we ** also have to unlink the quotaConn from the quotaFile and quotaGroup. ** The quotaFile and/or quotaGroup are freed if they are no longer in use. */ static int quotaClose(sqlite3_file *pConn){ quotaConn *p = (quotaConn*)pConn; quotaFile *pFile = p->pFile; sqlite3_file *pSubOpen = quotaSubOpen(pConn); int rc; rc = pSubOpen->pMethods->xClose(pSubOpen); quotaEnter(); pFile->nRef--; if( pFile->nRef==0 ){ quotaGroup *pGroup = pFile->pGroup; if( pFile->deleteOnClose ) quotaRemoveFile(pFile); quotaGroupDeref(pGroup); } quotaLeave(); return rc; } /* Pass xRead requests directory thru to the original VFS without ** further processing. |
︙ | ︙ | |||
582 583 584 585 586 587 588 589 590 591 592 593 594 595 | if( !gQuota.pMutex ){ return SQLITE_NOMEM; } gQuota.isInitialized = 1; gQuota.pOrigVfs = pOrigVfs; gQuota.sThisVfs = *pOrigVfs; gQuota.sThisVfs.xOpen = quotaOpen; gQuota.sThisVfs.szOsFile += sizeof(quotaConn); gQuota.sThisVfs.zName = "quota"; gQuota.sIoMethodsV1.iVersion = 1; gQuota.sIoMethodsV1.xClose = quotaClose; gQuota.sIoMethodsV1.xRead = quotaRead; gQuota.sIoMethodsV1.xWrite = quotaWrite; gQuota.sIoMethodsV1.xTruncate = quotaTruncate; | > | 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 | if( !gQuota.pMutex ){ return SQLITE_NOMEM; } gQuota.isInitialized = 1; gQuota.pOrigVfs = pOrigVfs; gQuota.sThisVfs = *pOrigVfs; gQuota.sThisVfs.xOpen = quotaOpen; gQuota.sThisVfs.xDelete = quotaDelete; gQuota.sThisVfs.szOsFile += sizeof(quotaConn); gQuota.sThisVfs.zName = "quota"; gQuota.sIoMethodsV1.iVersion = 1; gQuota.sIoMethodsV1.xClose = quotaClose; gQuota.sIoMethodsV1.xRead = quotaRead; gQuota.sIoMethodsV1.xWrite = quotaWrite; gQuota.sIoMethodsV1.xTruncate = quotaTruncate; |
︙ | ︙ | |||
613 614 615 616 617 618 619 | /* ** Shutdown the quota system. ** ** All SQLite database connections must be closed before calling this ** routine. ** | | | > | 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 | /* ** Shutdown the quota system. ** ** All SQLite database connections must be closed before calling this ** routine. ** ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining quota groups. */ int sqlite3_quota_shutdown(void){ quotaGroup *pGroup; if( gQuota.isInitialized==0 ) return SQLITE_MISUSE; for(pGroup=gQuota.pGroup; pGroup; pGroup=pGroup->pNext){ if( quotaGroupOpenFileCount(pGroup)>0 ) return SQLITE_MISUSE; } while( gQuota.pGroup ){ pGroup = gQuota.pGroup; gQuota.pGroup = pGroup->pNext; pGroup->iLimit = 0; assert( quotaGroupOpenFileCount(pGroup)==0 ); quotaGroupDeref(pGroup); } gQuota.isInitialized = 0; sqlite3_mutex_free(gQuota.pMutex); sqlite3_vfs_unregister(&gQuota.sThisVfs); memset(&gQuota, 0, sizeof(gQuota)); return SQLITE_OK; |
︙ | ︙ | |||
703 704 705 706 707 708 709 710 711 712 713 714 715 716 | } pGroup->pArg = pArg; pGroup->xDestroy = xDestroy; quotaGroupDeref(pGroup); quotaLeave(); return SQLITE_OK; } /***************************** Test Code ***********************************/ #ifdef SQLITE_TEST #include <tcl.h> /* | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 | } pGroup->pArg = pArg; pGroup->xDestroy = xDestroy; quotaGroupDeref(pGroup); quotaLeave(); return SQLITE_OK; } /* ** Bring the named file under quota management. Or if it is already under ** management, update its size. */ int sqlite3_quota_file(const char *zFilename){ char *zFull; sqlite3_file *fd; int rc; int outFlags = 0; sqlite3_int64 iSize; fd = sqlite3_malloc(gQuota.sThisVfs.szOsFile + gQuota.sThisVfs.mxPathname+1); if( fd==0 ) return SQLITE_NOMEM; zFull = gQuota.sThisVfs.szOsFile + (char*)fd; rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename, gQuota.sThisVfs.mxPathname+1, zFull); if( rc==SQLITE_OK ){ rc = quotaOpen(&gQuota.sThisVfs, zFull, fd, SQLITE_OPEN_READONLY | SQLITE_OPEN_MAIN_DB, &outFlags); } if( rc==SQLITE_OK ){ fd->pMethods->xFileSize(fd, &iSize); fd->pMethods->xClose(fd); }else if( rc==SQLITE_CANTOPEN ){ quotaGroup *pGroup; quotaFile *pFile; quotaEnter(); pGroup = quotaGroupFind(zFull); if( pGroup ){ pFile = quotaFindFile(pGroup, zFull); if( pFile ) quotaRemoveFile(pFile); } quotaLeave(); } sqlite3_free(fd); return rc; } /***************************** Test Code ***********************************/ #ifdef SQLITE_TEST #include <tcl.h> /* |
︙ | ︙ | |||
879 880 881 882 883 884 885 886 887 888 889 890 891 892 | /* Invoke sqlite3_quota_set() */ rc = sqlite3_quota_set(zPattern, iLimit, xCallback, (void*)p, xDestroy); Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); return TCL_OK; } /* ** tclcmd: sqlite3_quota_dump */ static int test_quota_dump( void * clientData, Tcl_Interp *interp, | > > > > > > > > > > > > > > > > > > > > > > > > > > | 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 | /* Invoke sqlite3_quota_set() */ rc = sqlite3_quota_set(zPattern, iLimit, xCallback, (void*)p, xDestroy); Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); return TCL_OK; } /* ** tclcmd: sqlite3_quota_file FILENAME */ static int test_quota_file( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ const char *zFilename; /* File pattern to configure */ int rc; /* Value returned by quota_file() */ /* Process arguments */ if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); return TCL_ERROR; } zFilename = Tcl_GetString(objv[1]); /* Invoke sqlite3_quota_file() */ rc = sqlite3_quota_file(zFilename); Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); return TCL_OK; } /* ** tclcmd: sqlite3_quota_dump */ static int test_quota_dump( void * clientData, Tcl_Interp *interp, |
︙ | ︙ | |||
913 914 915 916 917 918 919 920 921 922 923 924 925 926 | pFileTerm = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, pFileTerm, Tcl_NewStringObj(pFile->zFilename, -1)); Tcl_ListObjAppendElement(interp, pFileTerm, Tcl_NewWideIntObj(pFile->iSize)); Tcl_ListObjAppendElement(interp, pFileTerm, Tcl_NewWideIntObj(pFile->nRef)); Tcl_ListObjAppendElement(interp, pGroupTerm, pFileTerm); } Tcl_ListObjAppendElement(interp, pResult, pGroupTerm); } quotaLeave(); Tcl_SetObjResult(interp, pResult); return TCL_OK; | > > | 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 | pFileTerm = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, pFileTerm, Tcl_NewStringObj(pFile->zFilename, -1)); Tcl_ListObjAppendElement(interp, pFileTerm, Tcl_NewWideIntObj(pFile->iSize)); Tcl_ListObjAppendElement(interp, pFileTerm, Tcl_NewWideIntObj(pFile->nRef)); Tcl_ListObjAppendElement(interp, pFileTerm, Tcl_NewWideIntObj(pFile->deleteOnClose)); Tcl_ListObjAppendElement(interp, pGroupTerm, pFileTerm); } Tcl_ListObjAppendElement(interp, pResult, pGroupTerm); } quotaLeave(); Tcl_SetObjResult(interp, pResult); return TCL_OK; |
︙ | ︙ | |||
935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 | static struct { char *zName; Tcl_ObjCmdProc *xProc; } aCmd[] = { { "sqlite3_quota_initialize", test_quota_initialize }, { "sqlite3_quota_shutdown", test_quota_shutdown }, { "sqlite3_quota_set", test_quota_set }, { "sqlite3_quota_dump", test_quota_dump }, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } return TCL_OK; } #endif | > | 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 | static struct { char *zName; Tcl_ObjCmdProc *xProc; } aCmd[] = { { "sqlite3_quota_initialize", test_quota_initialize }, { "sqlite3_quota_shutdown", test_quota_shutdown }, { "sqlite3_quota_set", test_quota_set }, { "sqlite3_quota_file", test_quota_file }, { "sqlite3_quota_dump", test_quota_dump }, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } return TCL_OK; } #endif |
Changes to src/test_rtree.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | */ #include "sqlite3.h" /* Solely for the UNUSED_PARAMETER() macro. */ #include "sqliteInt.h" /* ** Type used to cache parameter information for the "circle" r-tree geometry ** callback. */ typedef struct Circle Circle; struct Circle { struct Box { | > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | */ #include "sqlite3.h" /* Solely for the UNUSED_PARAMETER() macro. */ #include "sqliteInt.h" #ifdef SQLITE_ENABLE_RTREE /* ** Type used to cache parameter information for the "circle" r-tree geometry ** callback. */ typedef struct Circle Circle; struct Circle { struct Box { |
︙ | ︙ | |||
226 227 228 229 230 231 232 233 234 235 236 237 238 239 | && aCoord[5]>=pCube->z ){ *piRes = 1; } return SQLITE_OK; } static int register_cube_geom( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ | > | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | && aCoord[5]>=pCube->z ){ *piRes = 1; } return SQLITE_OK; } #endif /* SQLITE_ENABLE_RTREE */ static int register_cube_geom( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ |
︙ | ︙ |
Changes to src/test_thread.c.
︙ | ︙ | |||
301 302 303 304 305 306 307 | static int sqlthread_id( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ Tcl_ThreadId id = Tcl_GetCurrentThread(); | | | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | static int sqlthread_id( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ Tcl_ThreadId id = Tcl_GetCurrentThread(); Tcl_SetObjResult(interp, Tcl_NewIntObj(SQLITE_PTR_TO_INT(id))); UNUSED_PARAMETER(clientData); UNUSED_PARAMETER(objc); UNUSED_PARAMETER(objv); return TCL_OK; } |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
3127 3128 3129 3130 3131 3132 3133 | ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; pCur->isIndex = !pCur->isTable; break; } | | > > > > > > > > > > > > | 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 | ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; pCur->isIndex = !pCur->isTable; break; } /* Opcode: OpenEphemeral P1 P2 * P4 P5 ** ** Open a new cursor P1 to a transient table. ** The cursor is always opened read/write even if ** the main database is read-only. The ephemeral ** table is deleted automatically when the cursor is closed. ** ** P2 is the number of columns in the ephemeral table. ** The cursor points to a BTree table if P4==0 and to a BTree index ** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure ** that defines the format of keys in the index. ** ** This opcode was once called OpenTemp. But that created ** confusion because the term "temp table", might refer either ** to a TEMP table at the SQL level, or to a table opened by ** this opcode. Then this opcode was call OpenVirtual. But ** that created confusion with the whole virtual-table idea. ** ** The P5 parameter can be a mask of the BTREE_* flags defined ** in btree.h. These flags control aspects of the operation of ** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are ** added automatically. */ /* Opcode: OpenAutoindex P1 P2 * P4 * ** ** This opcode works the same as OP_OpenEphemeral. It has a ** different name to distinguish its use. Tables created using ** by this opcode will be used for automatically created transient ** indices in joins. */ /* Opcode: OpenSorter P1 P2 * P4 * ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large ** tables using an external merge-sort algorithm. */ case OP_OpenSorter: case OP_OpenAutoindex: case OP_OpenEphemeral: { VdbeCursor *pCx; static const int vfsFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TRANSIENT_DB; assert( pOp->p1>=0 ); assert( (pOp->opcode==OP_OpenSorter)==((pOp->p5 & BTREE_SORTER)!=0) ); pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
169 170 171 172 173 174 175 | int sqlite3VdbeAddOp1(Vdbe*,int,int); int sqlite3VdbeAddOp2(Vdbe*,int,int,int); int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); | | | | | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | int sqlite3VdbeAddOp1(Vdbe*,int,int); int sqlite3VdbeAddOp2(Vdbe*,int,int,int); int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); void sqlite3VdbeChangeP5(Vdbe*, u8 P5); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); void sqlite3VdbeUsesBtree(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
520 521 522 523 524 525 526 | /* ** Change the value of the P1 operand for a specific instruction. ** This routine is useful when a large program is loaded from a ** static array using sqlite3VdbeAddOpList but we want to make a ** few minor changes to the program. */ | | < | | < | | < | | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | /* ** Change the value of the P1 operand for a specific instruction. ** This routine is useful when a large program is loaded from a ** static array using sqlite3VdbeAddOpList but we want to make a ** few minor changes to the program. */ void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){ assert( p!=0 ); if( ((u32)p->nOp)>addr ){ p->aOp[addr].p1 = val; } } /* ** Change the value of the P2 operand for a specific instruction. ** This routine is useful for setting a jump destination. */ void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){ assert( p!=0 ); if( ((u32)p->nOp)>addr ){ p->aOp[addr].p2 = val; } } /* ** Change the value of the P3 operand for a specific instruction. */ void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ assert( p!=0 ); if( ((u32)p->nOp)>addr ){ p->aOp[addr].p3 = val; } } /* ** Change the value of the P5 operand for the most recently ** added operation. |
︙ | ︙ |
Changes to src/vdbesort.c.
︙ | ︙ | |||
384 385 386 387 388 389 390 391 | ** key). The varint is the number of bytes in the blob of data. */ static int vdbeSorterBtreeToPMA(sqlite3 *db, VdbeCursor *pCsr){ int rc = SQLITE_OK; /* Return code */ VdbeSorter *pSorter = pCsr->pSorter; int res = 0; rc = sqlite3BtreeFirst(pCsr->pCursor, &res); | > > | | 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 | ** key). The varint is the number of bytes in the blob of data. */ static int vdbeSorterBtreeToPMA(sqlite3 *db, VdbeCursor *pCsr){ int rc = SQLITE_OK; /* Return code */ VdbeSorter *pSorter = pCsr->pSorter; int res = 0; /* sqlite3BtreeFirst() cannot fail because sorter btrees are always held ** in memory and so an I/O error is not possible. */ rc = sqlite3BtreeFirst(pCsr->pCursor, &res); if( NEVER(rc!=SQLITE_OK) || res ) return rc; assert( pSorter->nBtree>0 ); /* If the first temporary PMA file has not been opened, open it now. */ if( pSorter->pTemp1==0 ){ rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1); assert( rc!=SQLITE_OK || pSorter->pTemp1 ); assert( pSorter->iWriteOff==0 ); |
︙ | ︙ | |||
425 426 427 428 429 430 431 432 | }else{ nMalloc = nKey; } } /* Write the record itself to the output file */ if( rc==SQLITE_OK ){ rc = sqlite3BtreeKey(pCsr->pCursor, 0, nKey, aMalloc); | > | | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | }else{ nMalloc = nKey; } } /* Write the record itself to the output file */ if( rc==SQLITE_OK ){ /* sqlite3BtreeKey() cannot fail because sorter btrees held in memory */ rc = sqlite3BtreeKey(pCsr->pCursor, 0, nKey, aMalloc); if( ALWAYS(rc==SQLITE_OK) ){ rc = sqlite3OsWrite(pSorter->pTemp1, aMalloc, nKey, iWriteOff); iWriteOff += nKey; } } if( rc!=SQLITE_OK ) break; } |
︙ | ︙ | |||
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | int sqlite3VdbeSorterWrite(sqlite3 *db, VdbeCursor *pCsr, int nKey){ int rc = SQLITE_OK; /* Return code */ VdbeSorter *pSorter = pCsr->pSorter; if( pSorter ){ Pager *pPager = sqlite3BtreePager(pCsr->pBt); int nPage; /* Current size of temporary file in pages */ /* Determine how many pages the temporary b-tree has grown to */ sqlite3PagerPagecount(pPager, &nPage); /* If pSorter->nWorking is still zero, but the temporary file has been ** created in the file-system, then the most recent insert into the ** current b-tree segment probably caused the cache to overflow (it is ** also possible that sqlite3_release_memory() was called). So set the ** size of the working set to a little less than the current size of the ** file in pages. */ | > > > | | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | int sqlite3VdbeSorterWrite(sqlite3 *db, VdbeCursor *pCsr, int nKey){ int rc = SQLITE_OK; /* Return code */ VdbeSorter *pSorter = pCsr->pSorter; if( pSorter ){ Pager *pPager = sqlite3BtreePager(pCsr->pBt); int nPage; /* Current size of temporary file in pages */ /* Sorters never spill to disk */ assert( sqlite3PagerFile(pPager)->pMethods==0 ); /* Determine how many pages the temporary b-tree has grown to */ sqlite3PagerPagecount(pPager, &nPage); /* If pSorter->nWorking is still zero, but the temporary file has been ** created in the file-system, then the most recent insert into the ** current b-tree segment probably caused the cache to overflow (it is ** also possible that sqlite3_release_memory() was called). So set the ** size of the working set to a little less than the current size of the ** file in pages. */ if( pSorter->nWorking==0 && sqlite3PagerUnderStress(pPager) ){ pSorter->nWorking = nPage-5; if( pSorter->nWorking<SORTER_MIN_WORKING ){ pSorter->nWorking = SORTER_MIN_WORKING; } } /* If the number of pages used by the current b-tree segment is greater |
︙ | ︙ | |||
622 623 624 625 626 627 628 | if( rc==SQLITE_OK ){ rc = vdbeSorterWriteVarint(pTemp2, nWrite, &iWrite2); } if( rc==SQLITE_OK ){ int bEof = 0; while( rc==SQLITE_OK && bEof==0 ){ | | | | | | 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 | if( rc==SQLITE_OK ){ rc = vdbeSorterWriteVarint(pTemp2, nWrite, &iWrite2); } if( rc==SQLITE_OK ){ int bEof = 0; while( rc==SQLITE_OK && bEof==0 ){ int nToWrite; VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ]; assert( pIter->pFile ); nToWrite = pIter->nKey + sqlite3VarintLen(pIter->nKey); rc = sqlite3OsWrite(pTemp2, pIter->aAlloc, nToWrite, iWrite2); iWrite2 += nToWrite; if( rc==SQLITE_OK ){ rc = sqlite3VdbeSorterNext(db, pCsr, &bEof); } } } } |
︙ | ︙ |
Changes to test/pager1.test.
︙ | ︙ | |||
2422 2423 2424 2425 2426 2427 2428 2429 2430 | hexio_write test.db2-journal 24 00000000 sqlite3 db2 test.db2 execsql { PRAGMA integrity_check } db2 } {ok} } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 | hexio_write test.db2-journal 24 00000000 sqlite3 db2 test.db2 execsql { PRAGMA integrity_check } db2 } {ok} } #------------------------------------------------------------------------- # Test that a database file can be "pre-hinted" to a certain size and that # subsequent spilling of the pager cache does not result in the database # file being shrunk. # catch {db close} forcedelete test.db do_test pager1-32.1 { sqlite3 db test.db execsql { CREATE TABLE t1(x, y); } db close sqlite3 db test.db execsql { BEGIN; INSERT INTO t1 VALUES(1, randomblob(10000)); } file_control_sizehint_test db main 20971520; # 20MB execsql { PRAGMA cache_size = 10; INSERT INTO t1 VALUES(1, randomblob(10000)); INSERT INTO t1 VALUES(2, randomblob(10000)); INSERT INTO t1 SELECT x+2, randomblob(10000) from t1; INSERT INTO t1 SELECT x+4, randomblob(10000) from t1; INSERT INTO t1 SELECT x+8, randomblob(10000) from t1; INSERT INTO t1 SELECT x+16, randomblob(10000) from t1; SELECT count(*) FROM t1; COMMIT; } db close file size test.db } {20971520} # Cleanup 20MB file left by the previous test. forcedelete test.db finish_test |
Changes to test/quota.test.
︙ | ︙ | |||
219 220 221 222 223 224 225 | do_test quota-3.2.X { foreach db {db1a db2a db2b db1b} { catch { $db close } } sqlite3_quota_set * 0 {} } {SQLITE_OK} #------------------------------------------------------------------------- | | > > > > > > > | 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | do_test quota-3.2.X { foreach db {db1a db2a db2b db1b} { catch { $db close } } sqlite3_quota_set * 0 {} } {SQLITE_OK} #------------------------------------------------------------------------- # Quotas are deleted when unused and when their limit is set to zero # # Return a list of all currently defined quotas. Each quota is identified # by its pattern. proc quota_list {} { set allq {} foreach q [sqlite3_quota_dump] { lappend allq [lindex $q 0] } return [lsort $allq] } proc quota_size {name} { set allq {} foreach q [sqlite3_quota_dump] { if {[lindex $q 0]==$name} {return [lindex $q 2]} } return 0 } do_test quota-4.1.1 { sqlite3_quota_set *test.db 0 {} quota_list } {} do_test quota-4.1.2 { |
︙ | ︙ | |||
325 326 327 328 329 330 331 332 333 334 335 | sqlite3_quota_set A 1000 quota_callback sqlite3 db A sqlite3_quota_set A 0 quota_callback db close quota_list } {} do_test quota-4.4.1 { sqlite3_quota_set A 1000 quota_callback sqlite3_quota_shutdown } {SQLITE_OK} | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 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 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | sqlite3_quota_set A 1000 quota_callback sqlite3 db A sqlite3_quota_set A 0 quota_callback db close quota_list } {} unset -nocomplain quotagroup if {$tcl_platform(platform)=="windows"} { set quotagroup *\\quota-test-A?.db } else { set quotagroup */quota-test-A?.db } foreach file [glob -nocomplain quota-test-A*] { forcedelete $file } do_test quota-4.4.1 { set ::quota {} sqlite3_quota_set $::quotagroup 10000 quota_callback file delete -force ./quota-test-A1.db ./quota-test-A2.db sqlite3 db ./quota-test-A1.db db eval { CREATE TABLE t1(x); INSERT INTO t1 VALUES(randomblob(5000)); } quota_list } [list $quotagroup] do_test quota-4.4.2 { expr {$::quota==""} } {1} do_test quota-4.4.3 { db close sqlite3 db ./quota-test-A2.db db eval { CREATE TABLE t1(x); INSERT INTO t1 VALUES(randomblob(5000)); } quota_list } [list $quotagroup] do_test quota-4.4.4 { expr {$::quota!=""} } {1} do_test quota-4.4.5 { db close sqlite3_quota_set $::quotagroup 0 {} sqlite3_quota_dump } {} do_test quota-4.4.6 { sqlite3_quota_set $quotagroup 10000 quota_callback sqlite3 db quota-test-A1.db db eval {SELECT count(*) FROM sqlite_master} quota_size $quotagroup } [file size quota-test-A1.db] do_test quota-4.4.7 { sqlite3_quota_file quota-test-A2.db quota_size $::quotagroup } [expr {[file size quota-test-A1.db]+[file size quota-test-A2.db]}] unset -nocomplain quotagroup if {$tcl_platform(platform)=="windows"} { set quotagroup *\\quota-test-B* } else { set quotagroup */quota-test-B* } foreach file [glob -nocomplain quota-test-B*] { forcedelete $file } do_test quota-4.5.1 { sqlite3_quota_set $::quotagroup 100000 quota_callback quota_size $::quotagroup } {0} do_test quota-4.5.2 { sqlite3_quota_file quota-test-B1.txt quota_size $::quotagroup } {0} proc add_to_file {name n} { set out [open $name a] fconfigure $out -translation binary puts -nonewline $out [string repeat x $n] close $out } do_test quota-4.5.3 { add_to_file quota-test-B1.txt 123 sqlite3_quota_file quota-test-B1.txt quota_size $::quotagroup } {123} do_test quota-4.5.4 { add_to_file quota-test-B2.txt 234 sqlite3_quota_file quota-test-B2.txt quota_size $::quotagroup } {357} do_test quota-4.5.5 { add_to_file quota-test-B1.txt 2000 sqlite3_quota_file quota-test-B1.txt quota_size $::quotagroup } {2357} do_test quota-4.5.6 { forcedelete quota-test-B1.txt sqlite3_quota_file quota-test-B1.txt quota_size $::quotagroup } {234} do_test quota-4.5.7 { forcedelete quota-test-B2.txt sqlite3_quota_file quota-test-B2.txt quota_size $::quotagroup } {0} do_test quota-4.5.8 { add_to_file quota-test-B3.txt 1234 sqlite3_quota_file quota-test-B3.txt quota_size $::quotagroup } {1234} do_test quota-4.5.9 { sqlite3_quota_set $quotagroup 0 {} quota_size $::quotagroup } {0} do_test quota-4.9.1 { db close sqlite3_quota_set A 1000 quota_callback sqlite3_quota_shutdown } {SQLITE_OK} do_test quota-4.9.2 { quota_list } {} #------------------------------------------------------------------------- # The following tests test that the quota VFS handles malloc and IO # errors. # |
︙ | ︙ |
Changes to test/win32lock.test.
︙ | ︙ | |||
65 66 67 68 69 70 71 72 73 74 75 76 77 78 | regsub {\d+} $::log # x set x } {{delayed #ms for lock/sharing conflict}} } } if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break incr delay1 25 sqlite3_sleep 10 } do_test win32lock-2.0 { file_control_win32_av_retry db -1 -1 } {0 10 25} do_test win32lock-2.1 { | > > > > | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | regsub {\d+} $::log # x set x } {{delayed #ms for lock/sharing conflict}} } } if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break incr delay1 25 if {$delay1 > 12500} { puts "Timed out waiting for \"ok\" and \"error\" results." break } sqlite3_sleep 10 } do_test win32lock-2.0 { file_control_win32_av_retry db -1 -1 } {0 10 25} do_test win32lock-2.1 { |
︙ | ︙ | |||
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | regsub {\d+} $::log # x set x } {{delayed #ms for lock/sharing conflict}} } } if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break incr delay1 1 sqlite3_sleep 10 } file_control_win32_av_retry db 10 25 sqlite3_test_control_pending_byte $old_pending_byte sqlite3_shutdown test_sqlite3_log sqlite3_initialize finish_test | > > > > > | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | regsub {\d+} $::log # x set x } {{delayed #ms for lock/sharing conflict}} } } if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break incr delay1 1 if {$delay1 > 500} { puts "Timed out waiting for \"ok\" and \"error\" results." break } sqlite3_sleep 10 } file_control_win32_av_retry db 10 25 sqlite3_test_control_pending_byte $old_pending_byte db close sqlite3_shutdown test_sqlite3_log sqlite3_initialize finish_test |
Changes to tool/warnings.sh.
1 2 3 4 5 | #/bin/sh # # Run this script in a directory with a working makefile to check for # compiler warnings in SQLite. # | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #/bin/sh # # Run this script in a directory with a working makefile to check for # compiler warnings in SQLite. # rm -f sqlite3.c make sqlite3.c-debug echo '********** No optimizations. Includes FTS4 and RTREE *********' gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \ sqlite3.c echo '********** No optimizations. ENABLE_STAT2. THREADSAFE=0 *******' gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \ -ansi -DSQLITE_ENABLE_STAT2 -DSQLITE_THREADSAFE=0 \ |
︙ | ︙ |