Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge updates from trunk. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | configReadOnly |
Files: | files | file ages | folders |
SHA1: |
f021559d8a23934e3bdccad5b55fc7a9 |
User & Date: | mistachkin 2012-10-16 23:08:28.778 |
Context
2012-12-08
| ||
06:46 | Merge updates from trunk. (check-in: e65db42c9f user: mistachkin tags: configReadOnly) | |
2012-10-16
| ||
23:08 | Merge updates from trunk. (check-in: f021559d8a user: mistachkin tags: configReadOnly) | |
2012-10-15
| ||
20:28 | Correct comments and enhance readability of the mkvsix tool. (check-in: 2c3af657fe user: mistachkin tags: trunk) | |
2012-10-07
| ||
14:14 | Merge updates from trunk. (check-in: bbb0d189b7 user: mistachkin tags: configReadOnly) | |
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 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 | # # 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 non-0 to use the International Components for Unicode (ICU). # USE_ICU = 0 # Set this non-0 to dynamically link to the MSVC runtime library. # USE_CRT_DLL = 0 # Set this non-0 to attempt setting the native compiler automatically # for cross-compiling the command line tools needed during the compilation # process. # XCOMPILE = 0 # Set this non-0 to use the native libraries paths for cross-compiling # the command line tools needed during the compilation process. # USE_NATIVE_LIBPATHS = 0 # Set this 0 to skip the compiling and embedding of version resources. # USE_RC = 1 # Set this non-0 to compile binaries suitable for the WinRT environment. # This setting does not apply to any binaries that require Tcl to operate # properly (i.e. the text fixture, etc). # FOR_WINRT = 0 # Set this non-0 to skip attempting to look for and/or link with the Tcl # runtime library. # NO_TCL = 0 # Set this to non-0 to create and use PDBs. # SYMBOLS = 1 # Set this to non-0 to use the SQLite debugging heap subsystem. # MEMDEBUG = 0 # Set this to non-0 to use the Win32 native heap subsystem. # WIN32HEAP = 0 # 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 # Check for the predefined command macro CC. This should point to the compiler # binary for the target platform. If it is not defined, simply define it to # the legacy default value 'cl.exe'. # !IFNDEF CC CC = cl.exe | > > > > > > > > > > > > > > > > > > > > > > > > | 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 101 102 | # # 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. # !IFNDEF USE_AMALGAMATION USE_AMALGAMATION = 1 !ENDIF # Set this non-0 to use the International Components for Unicode (ICU). # !IFNDEF USE_ICU USE_ICU = 0 !ENDIF # Set this non-0 to dynamically link to the MSVC runtime library. # !IFNDEF USE_CRT_DLL USE_CRT_DLL = 0 !ENDIF # Set this non-0 to attempt setting the native compiler automatically # for cross-compiling the command line tools needed during the compilation # process. # !IFNDEF XCOMPILE XCOMPILE = 0 !ENDIF # Set this non-0 to use the native libraries paths for cross-compiling # the command line tools needed during the compilation process. # !IFNDEF USE_NATIVE_LIBPATHS USE_NATIVE_LIBPATHS = 0 !ENDIF # Set this 0 to skip the compiling and embedding of version resources. # !IFNDEF USE_RC USE_RC = 1 !ENDIF # Set this non-0 to compile binaries suitable for the WinRT environment. # This setting does not apply to any binaries that require Tcl to operate # properly (i.e. the text fixture, etc). # !IFNDEF FOR_WINRT FOR_WINRT = 0 !ENDIF # Set this non-0 to skip attempting to look for and/or link with the Tcl # runtime library. # !IFNDEF NO_TCL NO_TCL = 0 !ENDIF # Set this to non-0 to create and use PDBs. # !IFNDEF SYMBOLS SYMBOLS = 1 !ENDIF # Set this to non-0 to use the SQLite debugging heap subsystem. # !IFNDEF MEMDEBUG MEMDEBUG = 0 !ENDIF # Set this to non-0 to use the Win32 native heap subsystem. # !IFNDEF WIN32HEAP WIN32HEAP = 0 !ENDIF # 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. # !IFNDEF DEBUG DEBUG = 0 !ENDIF # Check for the predefined command macro CC. This should point to the compiler # binary for the target platform. If it is not defined, simply define it to # the legacy default value 'cl.exe'. # !IFNDEF CC CC = cl.exe |
︙ | ︙ |
Changes to src/backup.c.
︙ | ︙ | |||
409 410 411 412 413 414 415 | /* 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 ){ | > > > > > | > | 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | /* 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 ){ if( nSrcPage==0 ){ rc = sqlite3BtreeNewDb(p->pDest); nSrcPage = 1; } if( rc==SQLITE_OK || rc==SQLITE_DONE ){ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); } if( rc==SQLITE_OK ){ if( p->pDestDb ){ sqlite3ResetAllSchemasOfConnection(p->pDestDb); } if( destMode==PAGER_JOURNALMODE_WAL ){ rc = sqlite3BtreeSetVersion(p->pDest, 2); } |
︙ | ︙ | |||
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 | 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 ); | > > | | 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 | nDestTruncate = (nSrcPage+ratio-1)/ratio; if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){ nDestTruncate--; } }else{ nDestTruncate = nSrcPage * (pgszSrc/pgszDest); } assert( nDestTruncate>0 ); 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( nDestTruncate==0 || (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 |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 | put4byte(&data[36 + 4*4], pBt->autoVacuum); put4byte(&data[36 + 7*4], pBt->incrVacuum); #endif pBt->nPage = 1; data[31] = 1; return SQLITE_OK; } /* ** Attempt to start a new transaction. A write-transaction ** is started if the second argument is nonzero, otherwise a read- ** transaction. If the second argument is 2 or more and exclusive ** transaction is started, meaning that no other process is allowed ** to access the database. A preexisting transaction may not be | > > > > > > > > > > > > > > | 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 | put4byte(&data[36 + 4*4], pBt->autoVacuum); put4byte(&data[36 + 7*4], pBt->incrVacuum); #endif pBt->nPage = 1; data[31] = 1; return SQLITE_OK; } /* ** Initialize the first page of the database file (creating a database ** consisting of a single page and no schema objects). Return SQLITE_OK ** if successful, or an SQLite error code otherwise. */ int sqlite3BtreeNewDb(Btree *p){ int rc; sqlite3BtreeEnter(p); p->pBt->nPage = 0; rc = newDatabase(p->pBt); sqlite3BtreeLeave(p); return rc; } /* ** Attempt to start a new transaction. A write-transaction ** is started if the second argument is nonzero, otherwise a read- ** transaction. If the second argument is 2 or more and exclusive ** transaction is started, meaning that no other process is allowed ** to access the database. A preexisting transaction may not be |
︙ | ︙ |
Changes to src/btree.h.
︙ | ︙ | |||
112 113 114 115 116 117 118 119 120 121 122 123 124 125 | int sqlite3BtreeDropTable(Btree*, int, int*); int sqlite3BtreeClearTable(Btree*, int, int*); void sqlite3BtreeTripAllCursors(Btree*, int); void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); /* ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta ** should be one of the following values. The integer values are assigned ** to constants so that the offset of the corresponding field in an ** SQLite database header may be found using the following formula: ** | > > | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | int sqlite3BtreeDropTable(Btree*, int, int*); int sqlite3BtreeClearTable(Btree*, int, int*); void sqlite3BtreeTripAllCursors(Btree*, int); void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); int sqlite3BtreeNewDb(Btree *p); /* ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta ** should be one of the following values. The integer values are assigned ** to constants so that the offset of the corresponding field in an ** SQLite database header may be found using the following formula: ** |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 | iLargest = iIdx; } } if( iLargest==0 ){ return; }else{ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); destroyRootPage(pParse, iLargest, iDb); iDestroyed = iLargest; } } #endif } | > | 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 | iLargest = iIdx; } } if( iLargest==0 ){ return; }else{ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); assert( iDb>=0 && iDb<pParse->db->nDb ); destroyRootPage(pParse, iLargest, iDb); iDestroyed = iLargest; } } #endif } |
︙ | ︙ | |||
2573 2574 2575 2576 2577 2578 2579 | sqlite3FixSrcList(&sFix, pTblName) ){ /* Because the parser constructs pTblName from a single identifier, ** sqlite3FixSrcList can never fail. */ assert(0); } pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]); | > | | 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 | sqlite3FixSrcList(&sFix, pTblName) ){ /* Because the parser constructs pTblName from a single identifier, ** sqlite3FixSrcList can never fail. */ assert(0); } pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]); assert( db->mallocFailed==0 || pTab==0 ); if( pTab==0 ) goto exit_create_index; assert( db->aDb[iDb].pSchema==pTab->pSchema ); }else{ assert( pName==0 ); assert( pStart==0 ); pTab = pParse->pNewTable; if( !pTab ) goto exit_create_index; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
1271 1272 1273 1274 1275 1276 1277 | if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; pParse->ckBase = regData; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; i<pCheck->nExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0); | > | | | | | | | | | | | | | | | > | 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 | if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; pParse->ckBase = regData; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; i<pCheck->nExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0); if( !db->mallocFailed ){ assert( pDup!=0 ); sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); }else{ char *zConsName = pCheck->a[i].zName; if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ if( zConsName ){ zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); }else{ zConsName = 0; } sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); } sqlite3VdbeResolveLabel(v, allOk); } sqlite3ExprDelete(db, pDup); } } #endif /* !defined(SQLITE_OMIT_CHECK) */ /* If we have an INTEGER PRIMARY KEY, make sure the primary key ** of the new record does not previously exist. Except, if this |
︙ | ︙ |
Changes to src/lempar.c.
︙ | ︙ | |||
604 605 606 607 608 609 610 611 612 613 614 615 616 617 | ** #line <lineno> <grammarfile> ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ %% }; yygoto = yyRuleInfo[yyruleno].lhs; yysize = yyRuleInfo[yyruleno].nrhs; yypParser->yyidx -= yysize; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); if( yyact < YYNSTATE ){ #ifdef NDEBUG /* If we are not debugging and the reduce action popped at least | > | 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 | ** #line <lineno> <grammarfile> ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ %% }; assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) ); yygoto = yyRuleInfo[yyruleno].lhs; yysize = yyRuleInfo[yyruleno].nrhs; yypParser->yyidx -= yysize; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); if( yyact < YYNSTATE ){ #ifdef NDEBUG /* If we are not debugging and the reduce action popped at least |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
2082 2083 2084 2085 2086 2087 2088 | return SQLITE_OK; } /* ** Close a file. Make sure the lock has been released before closing. */ static int dotlockClose(sqlite3_file *id) { | | < | > | 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 | return SQLITE_OK; } /* ** Close a file. Make sure the lock has been released before closing. */ static int dotlockClose(sqlite3_file *id) { int rc = SQLITE_OK; if( id ){ unixFile *pFile = (unixFile*)id; dotlockUnlock(id, NO_LOCK); sqlite3_free(pFile->lockingContext); rc = closeUnixFile(id); } return rc; } /****************** End of the dot-file lock implementation ******************* ******************************************************************************/ /****************************************************************************** ************************** Begin flock Locking ******************************** |
︙ | ︙ | |||
2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 | } } /* ** Close a file. */ static int flockClose(sqlite3_file *id) { if( id ){ flockUnlock(id, NO_LOCK); } | > > | | 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 | } } /* ** Close a file. */ static int flockClose(sqlite3_file *id) { int rc = SQLITE_OK; if( id ){ flockUnlock(id, NO_LOCK); rc = closeUnixFile(id); } return rc; } #endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */ /******************* End of the flock lock implementation ********************* ******************************************************************************/ |
︙ | ︙ | |||
4094 4095 4096 4097 4098 4099 4100 | } pShmNode->apRegion = apNew; while(pShmNode->nRegion<=iRegion){ void *pMem; if( pShmNode->h>=0 ){ pMem = mmap(0, szRegion, pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, | | | 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 | } pShmNode->apRegion = apNew; while(pShmNode->nRegion<=iRegion){ void *pMem; if( pShmNode->h>=0 ){ pMem = mmap(0, szRegion, pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion ); if( pMem==MAP_FAILED ){ rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename); goto shmpage_out; } }else{ pMem = sqlite3_malloc(szRegion); |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 | ** available in Windows platforms based on the NT kernel. */ #if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) # error "WAL mode requires support from the Windows NT kernel, compile\ with SQLITE_OMIT_WAL." #endif /* ** Macro to find the minimum of two numeric values. */ #ifndef MIN # define MIN(x,y) ((x)<(y)?(x):(y)) #endif | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | ** available in Windows platforms based on the NT kernel. */ #if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) # error "WAL mode requires support from the Windows NT kernel, compile\ with SQLITE_OMIT_WAL." #endif /* ** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions ** based on the sub-platform)? */ #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT # define SQLITE_WIN32_HAS_ANSI #endif /* ** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions ** based on the sub-platform)? */ #if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT # define SQLITE_WIN32_HAS_WIDE #endif /* ** Do we need to manually define the Win32 file mapping APIs for use with WAL ** mode (e.g. these APIs are available in the Windows CE SDK; however, they ** are not present in the header file)? */ #if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) /* ** Two of the file mapping APIs are different under WinRT. Figure out which ** set we need. */ #if SQLITE_OS_WINRT WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \ LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR); WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T); #else #if defined(SQLITE_WIN32_HAS_ANSI) WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \ DWORD, DWORD, DWORD, LPCSTR); #endif /* defined(SQLITE_WIN32_HAS_ANSI) */ #if defined(SQLITE_WIN32_HAS_WIDE) WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \ DWORD, DWORD, DWORD, LPCWSTR); #endif /* defined(SQLITE_WIN32_HAS_WIDE) */ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif /* SQLITE_OS_WINRT */ /* ** This file mapping API is common to both Win32 and WinRT. */ WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID); #endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */ /* ** Macro to find the minimum of two numeric values. */ #ifndef MIN # define MIN(x,y) ((x)<(y)?(x):(y)) #endif |
︙ | ︙ | |||
234 235 236 237 238 239 240 | */ #ifdef SQLITE_TEST int sqlite3_os_type = 0; #else static int sqlite3_os_type = 0; #endif | < < < < < < < < | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | */ #ifdef SQLITE_TEST int sqlite3_os_type = 0; #else static int sqlite3_os_type = 0; #endif #ifndef SYSCALL # define SYSCALL sqlite3_syscall_ptr #endif /* ** This function is not available on Windows CE or WinRT. */ |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
5661 5662 5663 5664 5665 5666 5667 | # define DIRECT_MODE 0 assert( isDirectMode==0 ); UNUSED_PARAMETER(isDirectMode); #else # define DIRECT_MODE isDirectMode #endif | | | 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 | # define DIRECT_MODE 0 assert( isDirectMode==0 ); UNUSED_PARAMETER(isDirectMode); #else # define DIRECT_MODE isDirectMode #endif if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){ PgHdr *pPgHdr; /* Reference to page 1 */ assert( !pPager->tempFile && isOpen(pPager->fd) ); /* Open page 1 of the file for writing. */ rc = sqlite3PagerGet(pPager, 1, &pPgHdr); assert( pPgHdr==0 || rc==SQLITE_OK ); |
︙ | ︙ | |||
6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 | pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; } } return rc; } #ifdef SQLITE_ENABLE_ZIPVFS /* ** A read-lock must be held on the pager when this function is called. If ** the pager is in WAL mode and the WAL file currently contains one or more ** frames, return the size in bytes of the page images stored within the ** WAL frames. Otherwise, if this is not a WAL database or the WAL file ** is empty, return 0. | > > | 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 | pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; } } return rc; } #endif /* !SQLITE_OMIT_WAL */ #ifdef SQLITE_ENABLE_ZIPVFS /* ** A read-lock must be held on the pager when this function is called. If ** the pager is in WAL mode and the WAL file currently contains one or more ** frames, return the size in bytes of the page images stored within the ** WAL frames. Otherwise, if this is not a WAL database or the WAL file ** is empty, return 0. |
︙ | ︙ | |||
6941 6942 6943 6944 6945 6946 6947 | void *sqlite3PagerCodec(PgHdr *pPg){ void *aData = 0; CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData); return aData; } #endif /* SQLITE_HAS_CODEC */ | < < | 6943 6944 6945 6946 6947 6948 6949 6950 | void *sqlite3PagerCodec(PgHdr *pPg){ void *aData = 0; CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData); return aData; } #endif /* SQLITE_HAS_CODEC */ #endif /* SQLITE_OMIT_DISKIO */ |
Changes to src/pager.h.
︙ | ︙ | |||
134 135 136 137 138 139 140 | int sqlite3PagerSync(Pager *pPager); int sqlite3PagerCommitPhaseTwo(Pager*); int sqlite3PagerRollback(Pager*); int sqlite3PagerOpenSavepoint(Pager *pPager, int n); int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); int sqlite3PagerSharedLock(Pager *pPager); | > | | | | | > > | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | int sqlite3PagerSync(Pager *pPager); int sqlite3PagerCommitPhaseTwo(Pager*); int sqlite3PagerRollback(Pager*); int sqlite3PagerOpenSavepoint(Pager *pPager, int n); int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); int sqlite3PagerSharedLock(Pager *pPager); #ifndef SQLITE_OMIT_WAL int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); int sqlite3PagerWalSupported(Pager *pPager); int sqlite3PagerWalCallback(Pager *pPager); int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); int sqlite3PagerCloseWal(Pager *pPager); #endif #ifdef SQLITE_ENABLE_ZIPVFS int sqlite3PagerWalFramesize(Pager *pPager); #endif /* Functions used to query pager state and configuration. */ u8 sqlite3PagerIsreadonly(Pager*); int sqlite3PagerRefcount(Pager*); |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
1565 1566 1567 1568 1569 1570 1571 | int i; sqlite3VdbeSetNumCols(v, 2); pParse->nMem = 2; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC); for(i=0; i<db->nDb; i++){ Btree *pBt; | < | | 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 | int i; sqlite3VdbeSetNumCols(v, 2); pParse->nMem = 2; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC); for(i=0; i<db->nDb; i++){ Btree *pBt; const char *zState = "unknown"; int j; if( db->aDb[i].zName==0 ) continue; sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC); pBt = db->aDb[i].pBt; if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ zState = "closed"; }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ zState = azLockName[j]; } sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
191 192 193 194 195 196 197 | struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int isTrigger = 0; assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ | | | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int isTrigger = 0; assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; pExpr->pTab = 0; ExprSetIrreducible(pExpr); /* Start at the inner-most context and move outward until a match is found */ |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
3094 3095 3096 3097 3098 3099 3100 | ** ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ pList = pParent->pEList; for(i=0; i<pList->nExpr; i++){ if( pList->a[i].zName==0 ){ | | | | < | 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 | ** ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ pList = pParent->pEList; for(i=0; i<pList->nExpr; i++){ if( pList->a[i].zName==0 ){ char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan); sqlite3Dequote(zName); pList->a[i].zName = zName; } } substExprList(db, pParent->pEList, iParent, pSub->pEList); if( isAgg ){ substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); } |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
3181 3182 3183 3184 3185 3186 3187 | int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); int sqlite3Reprepare(Vdbe*); void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); int sqlite3TempInMemory(const sqlite3*); const char *sqlite3JournalModename(int); | > | | > | 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 | int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); int sqlite3Reprepare(Vdbe*); void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); int sqlite3TempInMemory(const sqlite3*); const char *sqlite3JournalModename(int); #ifndef SQLITE_OMIT_WAL int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif /* Declarations for functions in fkey.c. All of these are replaced by ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). |
︙ | ︙ |
Changes to src/vacuum.c.
︙ | ︙ | |||
81 82 83 84 85 86 87 88 89 90 91 92 93 94 | ** with 2.0.0, SQLite no longer uses GDBM so this command has ** become a no-op. */ void sqlite3Vacuum(Parse *pParse){ Vdbe *v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); } return; } /* ** This routine implements the OP_Vacuum opcode of the VDBE. */ | > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | ** with 2.0.0, SQLite no longer uses GDBM so this command has ** become a no-op. */ void sqlite3Vacuum(Parse *pParse){ Vdbe *v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); sqlite3VdbeUsesBtree(v, 0); } return; } /* ** This routine implements the OP_Vacuum opcode of the VDBE. */ |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
259 260 261 262 263 264 265 | ** in the list are moved to the sqlite3.pDisconnect list of the associated ** database connection. */ void sqlite3VtabClear(sqlite3 *db, Table *p){ if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); if( p->azModuleArg ){ int i; | < | | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | ** in the list are moved to the sqlite3.pDisconnect list of the associated ** database connection. */ void sqlite3VtabClear(sqlite3 *db, Table *p){ if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); if( p->azModuleArg ){ int i; for(i=0; i<p->nModuleArg; i++){ if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]); } sqlite3DbFree(db, p->azModuleArg); } } /* ** Add a new module argument to pTable->azModuleArg[]. |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
2514 2515 2516 2517 2518 2519 2520 | ** are no outstanding references to any page other than page 1. And ** page 1 is never written to the log until the transaction is ** committed. As a result, the call to xUndo may not fail. */ assert( walFramePgno(pWal, iFrame)!=1 ); rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); } | | | 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 | ** are no outstanding references to any page other than page 1. And ** page 1 is never written to the log until the transaction is ** committed. As a result, the call to xUndo may not fail. */ assert( walFramePgno(pWal, iFrame)!=1 ); rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); } if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } assert( rc==SQLITE_OK ); return rc; } /* ** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
1438 1439 1440 1441 1442 1443 1444 | /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ pTerm->prereqRight |= extraRight; } | < < < < < < < < < < < < < < < < | 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 | /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ pTerm->prereqRight |= extraRight; } /* ** This function searches the expression list passed as the second argument ** for an expression of type TK_COLUMN that refers to the same column and ** uses the same collation sequence as the iCol'th column of index pIdx. ** Argument iBase is the cursor number used for the table that pIdx refers ** to. ** |
︙ | ︙ | |||
2722 2723 2724 2725 2726 2727 2728 | } return rc; } #endif /* defined(SQLITE_ENABLE_STAT3) */ /* ** Check to see if column iCol of the table with cursor iTab will appear | | | > < | | > > | > > > > | < < | 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 | } return rc; } #endif /* defined(SQLITE_ENABLE_STAT3) */ /* ** Check to see if column iCol of the table with cursor iTab will appear ** in sorted order according to the current query plan. ** ** Return values: ** ** 0 iCol is not ordered ** 1 iCol has only a single value ** 2 iCol is in ASC order ** 3 iCol is in DESC order */ static int isOrderedColumn( WhereBestIdx *p, int iTab, int iCol ){ int i, j; WhereLevel *pLevel = &p->aLevel[p->i-1]; Index *pIdx; u8 sortOrder; for(i=p->i-1; i>=0; i--, pLevel--){ if( pLevel->iTabCur!=iTab ) continue; if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){ return 1; } assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 ); if( (pIdx = pLevel->plan.u.pIdx)!=0 ){ if( iCol<0 ){ sortOrder = 0; testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ); }else{ int n = pIdx->nColumn; for(j=0; j<n; j++){ |
︙ | ︙ | |||
2765 2766 2767 2768 2769 2770 2771 | testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ); } if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){ assert( sortOrder==0 || sortOrder==1 ); testcase( sortOrder==1 ); sortOrder = 1 - sortOrder; } | < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > | > > > | | | < > > < < < < < < < | > > > > > > | | | | | | > > | > > | > | | < < < < < | > > > | | > | > > | > > > > > > > > > | > > | > > > | > > > > | > | > > | | | < < < > > > > > > > > > > > | > > > > > > > | > > | < < < < > | | < < > > | > | > > | > | > > > > > > > > > > > | | < < < < < | 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 | testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ); } if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){ assert( sortOrder==0 || sortOrder==1 ); testcase( sortOrder==1 ); sortOrder = 1 - sortOrder; } return sortOrder+2; } return 0; } /* ** This routine decides if pIdx can be used to satisfy the ORDER BY ** clause, either in whole or in part. The return value is the ** cumulative number of terms in the ORDER BY clause that are satisfied ** by the index pIdx and other indices in outer loops. ** ** The table being queried has a cursor number of "base". pIdx is the ** index that is postulated for use to access the table. ** ** The *pbRev value is set to 0 order 1 depending on whether or not ** pIdx should be run in the forward order or in reverse order. */ static int isSortingIndex( WhereBestIdx *p, /* Best index search context */ Index *pIdx, /* The index we are testing */ int base, /* Cursor number for the table to be sorted */ int *pbRev /* Set to 1 for reverse-order scan of pIdx */ ){ int i; /* Number of pIdx terms used */ int j; /* Number of ORDER BY terms satisfied */ int sortOrder = 2; /* 0: forward. 1: backward. 2: unknown */ int nTerm; /* Number of ORDER BY terms */ struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */ Table *pTab = pIdx->pTable; /* Table that owns index pIdx */ ExprList *pOrderBy; /* The ORDER BY clause */ Parse *pParse = p->pParse; /* Parser context */ sqlite3 *db = pParse->db; /* Database connection */ int nPriorSat; /* ORDER BY terms satisfied by outer loops */ int seenRowid = 0; /* True if an ORDER BY rowid term is seen */ int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */ if( p->i==0 ){ nPriorSat = 0; }else{ nPriorSat = p->aLevel[p->i-1].plan.nOBSat; if( (p->aLevel[p->i-1].plan.wsFlags & WHERE_ORDERED)==0 ){ /* This loop cannot be ordered unless the next outer loop is ** also ordered */ return nPriorSat; } if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){ /* Only look at the outer-most loop if the OrderByIdxJoin ** optimization is disabled */ return nPriorSat; } } pOrderBy = p->pOrderBy; assert( pOrderBy!=0 ); if( pIdx->bUnordered ){ /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot ** be used for sorting */ return nPriorSat; } nTerm = pOrderBy->nExpr; uniqueNotNull = pIdx->onError!=OE_None; assert( nTerm>0 ); /* Argument pIdx must either point to a 'real' named index structure, ** or an index structure allocated on the stack by bestBtreeIndex() to ** represent the rowid index that is part of every table. */ assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) ); /* Match terms of the ORDER BY clause against columns of ** the index. ** ** Note that indices have pIdx->nColumn regular columns plus ** one additional column containing the rowid. The rowid column ** of the index is also allowed to match against the ORDER BY ** clause. */ j = nPriorSat; for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){ Expr *pOBExpr; /* The expression of the ORDER BY pOBItem */ CollSeq *pColl; /* The collating sequence of pOBExpr */ int termSortOrder; /* Sort order for this term */ int iColumn; /* The i-th column of the index. -1 for rowid */ int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */ int isEq; /* Subject to an == or IS NULL constraint */ int isMatch; /* ORDER BY term matches the index term */ const char *zColl; /* Name of collating sequence for i-th index term */ WhereTerm *pConstraint; /* A constraint in the WHERE clause */ /* If the next term of the ORDER BY clause refers to anything other than ** a column in the "base" table, then this index will not be of any ** further use in handling the ORDER BY. */ pOBExpr = pOBItem->pExpr; if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ break; } /* Find column number and collating sequence for the next entry ** in the index */ if( pIdx->zName && i<pIdx->nColumn ){ iColumn = pIdx->aiColumn[i]; if( iColumn==pIdx->pTable->iPKey ){ iColumn = -1; } iSortOrder = pIdx->aSortOrder[i]; zColl = pIdx->azColl[i]; assert( zColl!=0 ); }else{ iColumn = -1; iSortOrder = 0; zColl = 0; } /* Check to see if the column number and collating sequence of the ** index match the column number and collating sequence of the ORDER BY ** clause entry. Set isMatch to 1 if they both match. */ if( pOBExpr->iColumn==iColumn ){ if( zColl ){ pColl = sqlite3ExprCollSeq(pParse, pOBExpr); if( !pColl ) pColl = db->pDfltColl; isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; }else{ isMatch = 1; } }else{ isMatch = 0; } /* termSortOrder is 0 or 1 for whether or not the access loop should ** run forward or backwards (respectively) in order to satisfy this ** term of the ORDER BY clause. */ assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 ); assert( iSortOrder==0 || iSortOrder==1 ); termSortOrder = iSortOrder ^ pOBItem->sortOrder; /* If X is the column in the index and ORDER BY clause, check to see ** if there are any X= or X IS NULL constraints in the WHERE clause. */ pConstraint = findTerm(p->pWC, base, iColumn, p->notReady, WO_EQ|WO_ISNULL|WO_IN, pIdx); if( pConstraint==0 ){ isEq = 0; }else if( pConstraint->eOperator==WO_IN ){ /* Constraints of the form: "X IN ..." cannot be used with an ORDER BY ** because we do not know in what order the values on the RHS of the IN ** operator will occur. */ break; }else if( pConstraint->eOperator==WO_ISNULL ){ uniqueNotNull = 0; isEq = 1; /* "X IS NULL" means X has only a single value */ }else if( pConstraint->prereqRight==0 ){ isEq = 1; /* Constraint "X=constant" means X has only a single value */ }else{ Expr *pRight = pConstraint->pExpr->pRight; if( pRight->op==TK_COLUMN ){ WHERETRACE((" .. isOrderedColumn(tab=%d,col=%d)", pRight->iTable, pRight->iColumn)); isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn); WHERETRACE((" -> isEq=%d\n", isEq)); /* If the constraint is of the form X=Y where Y is an ordered value ** in an outer loop, then make sure the sort order of Y matches the ** sort order required for X. */ if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){ testcase( isEq==2 ); testcase( isEq==3 ); break; } }else{ isEq = 0; /* "X=expr" places no ordering constraints on X */ } } if( !isMatch ){ if( isEq==0 ){ break; }else{ continue; } }else if( isEq!=1 ){ if( sortOrder==2 ){ sortOrder = termSortOrder; }else if( termSortOrder!=sortOrder ){ break; } } j++; pOBItem++; if( iColumn<0 ){ seenRowid = 1; break; }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){ testcase( isEq==0 ); testcase( isEq==2 ); testcase( isEq==3 ); uniqueNotNull = 0; } } /* If we have not found at least one ORDER BY term that matches the ** index, then show no progress. */ if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat; /* Return the necessary scan order back to the caller */ *pbRev = sortOrder & 1; /* If there was an "ORDER BY rowid" term that matched, or it is only ** possible for a single row from this table to match, then skip over ** any additional ORDER BY terms dealing with this table. */ if( seenRowid || (uniqueNotNull && i>=pIdx->nColumn) ){ /* Advance j over additional ORDER BY terms associated with base */ WhereMaskSet *pMS = p->pWC->pMaskSet; Bitmask m = ~getMask(pMS, base); while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){ j++; } } |
︙ | ︙ | |||
3060 3061 3062 3063 3064 3065 3066 | /* Loop over all indices looking for the best one to use */ for(; pProbe; pIdx=pProbe=pProbe->pNext){ const tRowcnt * const aiRowEst = pProbe->aiRowEst; WhereCost pc; /* Cost of using pProbe */ double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */ | < | 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 | /* Loop over all indices looking for the best one to use */ for(; pProbe; pIdx=pProbe=pProbe->pNext){ const tRowcnt * const aiRowEst = pProbe->aiRowEst; WhereCost pc; /* Cost of using pProbe */ double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */ /* The following variables are populated based on the properties of ** index being evaluated. They are then used to determine the expected ** cost and number of rows returned. ** ** pc.plan.nEq: ** Number of equality terms that can be implemented using the index. |
︙ | ︙ | |||
3091 3092 3093 3094 3095 3096 3097 | ** ** nInMul is set to 1. ** ** If there exists a WHERE term of the form "x IN (SELECT ...)", then ** the sub-select is assumed to return 25 rows for the purposes of ** determining nInMul. ** | < < < < | 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 | ** ** nInMul is set to 1. ** ** If there exists a WHERE term of the form "x IN (SELECT ...)", then ** the sub-select is assumed to return 25 rows for the purposes of ** determining nInMul. ** ** bInEst: ** Set to true if there was at least one "x IN (SELECT ...)" term used ** in determining the value of nInMul. Note that the RHS of the ** IN operator must be a SELECT, not a value list, for this variable ** to be true. ** ** rangeDiv: |
︙ | ︙ | |||
3132 3133 3134 3135 3136 3137 3138 | ** two queries requires table b-tree lookups in order to find the value ** of column c, but the first does not because columns a and b are ** both available in the index. ** ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ | < > > > > | < < < < | 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 3190 3191 3192 3193 3194 3195 | ** two queries requires table b-tree lookups in order to find the value ** of column c, but the first does not because columns a and b are ** both available in the index. ** ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ int bInEst = 0; /* True if "x IN (SELECT...)" seen */ int nInMul = 1; /* Number of distinct equalities to lookup */ double rangeDiv = (double)1; /* Estimated reduction in search space */ int nBound = 0; /* Number of range constraints seen */ int bSort; /* True if external sort required */ int bDist; /* True if index cannot help with DISTINCT */ int bLookup = 0; /* True if not a covering index */ int nPriorSat; /* ORDER BY terms satisfied by outer loops */ int nOrderBy; /* Number of ORDER BY terms */ WhereTerm *pTerm; /* A single term of the WHERE clause */ #ifdef SQLITE_ENABLE_STAT3 WhereTerm *pFirstTerm = 0; /* First term matching the index */ #endif WHERETRACE(( " %s(%s):\n", pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") )); memset(&pc, 0, sizeof(pc)); nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; if( p->i ){ nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat; bSort = nPriorSat<nOrderBy; bDist = 0; }else{ nPriorSat = pc.plan.nOBSat = 0; bSort = nOrderBy>0; bDist = p->pDistinct!=0; } /* Determine the values of pc.plan.nEq and nInMul */ for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){ int j = pProbe->aiColumn[pc.plan.nEq]; pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); if( pTerm==0 ) break; pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ); testcase( pTerm->pWC!=pWC ); if( pTerm->eOperator & WO_IN ){ Expr *pExpr = pTerm->pExpr; pc.plan.wsFlags |= WHERE_COLUMN_IN; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */ nInMul *= 25; bInEst = 1; }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nInMul *= pExpr->x.pList->nExpr; } }else if( pTerm->eOperator & WO_ISNULL ){ pc.plan.wsFlags |= WHERE_COLUMN_NULL; } #ifdef SQLITE_ENABLE_STAT3 if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm; #endif pc.used |= pTerm->prereqRight; } |
︙ | ︙ | |||
3237 3238 3239 3240 3241 3242 3243 | } /* If there is an ORDER BY clause and the index being considered will ** naturally scan rows in the required order, set the appropriate flags ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but ** the index will scan rows in a different order, set the bSort ** variable. */ | < | | < < > | > | | 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 | } /* If there is an ORDER BY clause and the index being considered will ** naturally scan rows in the required order, set the appropriate flags ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but ** the index will scan rows in a different order, set the bSort ** variable. */ if( bSort && (pSrc->jointype & JT_LEFT)==0 ){ int bRev = 2; WHERETRACE((" --> before isSortingIndex: nPriorSat=%d\n",nPriorSat)); pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev); WHERETRACE((" --> after isSortingIndex: bRev=%d nOBSat=%d\n", bRev, pc.plan.nOBSat)); if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_UNIQUE)!=0 ){ pc.plan.wsFlags |= WHERE_ORDERED; } if( nOrderBy==pc.plan.nOBSat ){ bSort = 0; pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE; } |
︙ | ︙ | |||
3361 3362 3363 3364 3365 3366 3367 | ** the cost function to err on the side of choosing an index over ** choosing a full scan. This 4x full-scan penalty is an arguable ** decision and one which we expect to revisit in the future. But ** it seems to be working well enough at the moment. */ pc.rCost = aiRowEst[0]*4; pc.plan.wsFlags &= ~WHERE_IDX_ONLY; | > | > > | 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 | ** the cost function to err on the side of choosing an index over ** choosing a full scan. This 4x full-scan penalty is an arguable ** decision and one which we expect to revisit in the future. But ** it seems to be working well enough at the moment. */ pc.rCost = aiRowEst[0]*4; pc.plan.wsFlags &= ~WHERE_IDX_ONLY; if( pIdx ){ pc.plan.wsFlags &= ~WHERE_ORDERED; pc.plan.nOBSat = nPriorSat; } }else{ log10N = estLog(aiRowEst[0]); pc.rCost = pc.plan.nRow; if( pIdx ){ if( bLookup ){ /* For an index lookup followed by a table lookup: ** nInMul index searches to find the start of each index range |
︙ | ︙ | |||
3466 3467 3468 3469 3470 3471 3472 | } } if( pc.plan.nRow<2 ) pc.plan.nRow = 2; } WHERETRACE(( | < | | | < | | 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 | } } if( pc.plan.nRow<2 ) pc.plan.nRow = 2; } WHERETRACE(( " nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n" " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n" " used=0x%llx nOBSat=%d\n", pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags, p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used, pc.plan.nOBSat )); /* If this index is the best we have seen so far, then record this ** index and its cost in the p->cost structure. */ if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){ |
︙ | ︙ | |||
3510 3511 3512 3513 3514 3515 3516 | assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 ); assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 ); assert( pSrc->pIndex==0 || p->cost.plan.u.pIdx==0 || p->cost.plan.u.pIdx==pSrc->pIndex ); | | | 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 | assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 ); assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 ); assert( pSrc->pIndex==0 || p->cost.plan.u.pIdx==0 || p->cost.plan.u.pIdx==pSrc->pIndex ); WHERETRACE((" best index is: %s\n", p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk")); bestOrClauseIndex(p); bestAutomaticIndex(p); p->cost.plan.wsFlags |= eqTermMask; } |
︙ | ︙ | |||
4602 4603 4604 4605 4606 4607 4608 | /* Finish the loop through table entries that match term pOrTerm. */ sqlite3WhereEnd(pSubWInfo); } } } pLevel->u.pCovidx = pCov; | | | 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 | /* Finish the loop through table entries that match term pOrTerm. */ sqlite3WhereEnd(pSubWInfo); } } } pLevel->u.pCovidx = pCov; if( pCov ) pLevel->iIdxCur = iCovCur; if( pAndExpr ){ pAndExpr->pLeft = 0; sqlite3ExprDelete(pParse->db, pAndExpr); } sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); sqlite3VdbeResolveLabel(v, iLoopBody); |
︙ | ︙ | |||
5060 5061 5062 5063 5064 5065 5066 | if( (m & sWBI.notValid)==0 ){ if( j==iFrom ) iFrom++; continue; } sWBI.notReady = (isOptimal ? m : sWBI.notValid); if( sWBI.pSrc->pIndex==0 ) nUnconstrained++; | | | 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 | if( (m & sWBI.notValid)==0 ){ if( j==iFrom ) iFrom++; continue; } sWBI.notReady = (isOptimal ? m : sWBI.notValid); if( sWBI.pSrc->pIndex==0 ) nUnconstrained++; WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n", j, sWBI.pSrc->pTab->zName, isOptimal)); assert( sWBI.pSrc->pTab ); #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(sWBI.pSrc->pTab) ){ sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo; bestVirtualIndex(&sWBI); }else |
︙ | ︙ | |||
5113 5114 5115 5116 5117 5118 5119 | && (bestJ<0 || (notIndexed&m)!=0 /* (2) */ || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0) && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */ || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */ ){ | | | | 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 | && (bestJ<0 || (notIndexed&m)!=0 /* (2) */ || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0) && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */ || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */ ){ WHERETRACE((" === table %d (%s) is best so far\n" " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n", j, sWBI.pSrc->pTab->zName, sWBI.cost.rCost, sWBI.cost.plan.nRow, sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags)); bestPlan = sWBI.cost; bestJ = j; } if( doNotReorder ) break; |
︙ | ︙ |
Added test/backup4.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 101 102 103 104 105 106 | # 2012 October 13 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # The tests in this file verify that if an empty database (zero bytes in # size) is used as the source of a backup operation, the final destination # database is one page in size. # # The destination must consist of at least one page as truncating a # database file to zero bytes is equivalent to resetting the database # schema cookie and change counter. Doing that could cause other clients # to become confused and continue using out-of-date cache data. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix backup4 #------------------------------------------------------------------------- # At one point this test was failing because [db] was using an out of # date schema in test case 1.2. # do_execsql_test 1.0 { CREATE TABLE t1(x, y, UNIQUE(x, y)); INSERT INTO t1 VALUES('one', 'two'); SELECT * FROM t1 WHERE x='one'; PRAGMA integrity_check; } {one two ok} do_test 1.1 { sqlite3 db1 :memory: db1 backup test.db sqlite3 db1 test.db db1 eval { CREATE TABLE t1(x, y); INSERT INTO t1 VALUES('one', 'two'); } db1 close } {} do_execsql_test 1.2 { SELECT * FROM t1 WHERE x='one'; PRAGMA integrity_check; } {one two ok} db close forcedelete test.db forcedelete test.db2 sqlite3 db test.db #------------------------------------------------------------------------- # Test that if the source is zero bytes, the destination database # consists of a single page only. # do_execsql_test 2.1 { CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); } do_test 2.2 { file size test.db } 3072 do_test 2.3 { sqlite3 db1 test.db2 db1 backup test.db db1 close file size test.db } {1024} do_test 2.4 { file size test.db2 } 0 db close forcedelete test.db forcedelete test.db2 sqlite3 db test.db #------------------------------------------------------------------------- # Test that if the destination has a page-size larger than the implicit # page-size of the source, the final destination database still consists # of a single page. # do_execsql_test 3.1 { PRAGMA page_size = 4096; CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); } do_test 3.2 { file size test.db } 12288 do_test 3.3 { sqlite3 db1 test.db2 db1 backup test.db db1 close file size test.db } {1024} do_test 3.4 { file size test.db2 } 0 finish_test |
Changes to test/orderby1.test.
︙ | ︙ | |||
110 111 112 113 114 115 116 | } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 1.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } | | | | 110 111 112 113 114 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 | } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 1.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } } {~/ORDER BY/} ;# optimized out do_test 1.5a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} do_test 1.5b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC } } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting do_test 1.5c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {~/ORDER BY/} ;# optimized out do_test 1.6a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {three-c three-a two-b two-a one-c one-a} do_test 1.6b { |
︙ | ︙ | |||
257 258 259 260 261 262 263 | } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 2.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } | | | | 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 | } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 2.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } } {~/ORDER BY/} ;# optimized out do_test 2.5a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} do_test 2.5b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC } } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting do_test 2.5c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC } } {~/ORDER BY/} ;# optimized out do_test 2.6a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {three-c three-a two-b two-a one-c one-a} do_test 2.6b { |
︙ | ︙ | |||
392 393 394 395 396 397 398 | } } {one-a one-c two-a two-b three-a three-c} ;# verify same order after sorting do_test 3.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } | | | | 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 | } } {one-a one-c two-a two-b three-a three-c} ;# verify same order after sorting do_test 3.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn } } {~/ORDER BY/} ;# optimized out do_test 3.5a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {three-c three-a two-b two-a one-c one-a} do_test 3.5b { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn DESC } } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting do_test 3.5c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {~/ORDER BY/} ;# optimzed out do_test 3.6a { db eval { SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn } } {three-a three-c two-a two-b one-a one-c} |
︙ | ︙ |
Changes to test/pager1.test.
︙ | ︙ | |||
1361 1362 1363 1364 1365 1366 1367 | CREATE TABLE t2(a, b); } db2 sqlite3_backup B db2 main db main list [B step 10000] [B finish] } {SQLITE_DONE SQLITE_OK} do_test pager1-9.4.2 { list [file size test.db2] [file size test.db] | | | 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 | CREATE TABLE t2(a, b); } db2 sqlite3_backup B db2 main db main list [B step 10000] [B finish] } {SQLITE_DONE SQLITE_OK} do_test pager1-9.4.2 { list [file size test.db2] [file size test.db] } {1024 0} db2 close #------------------------------------------------------------------------- # Test that regardless of the value returned by xSectorSize(), the # minimum effective sector-size is 512 and the maximum 65536 bytes. # testvfs tv -default 1 |
︙ | ︙ |
Added test/wal9.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | # 2012 October 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # This test case tests that a problem causing a failing assert() has # been fixed. The problem occurred if a writer process with a subset # of the *shm file mapped rolled back a transaction begun after the # entire WAL file was checkpointed into the db file (i.e. a transaction # that would have restarted the WAL file from the beginning). # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix wal9 sqlite3 db2 test.db do_execsql_test 1.0 { PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0; CREATE TABLE t(x); } {wal 0} do_test 1.1 { execsql "SELECT * FROM t" db2 } {} do_execsql_test 1.2 { BEGIN; INSERT INTO t VALUES(randomblob(100)); INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; COMMIT; } {} # Check file sizes are as expected. The real requirement here is that # the *shm file is now more than one chunk (>32KiB). do_test 1.3 { file size test.db } {1024} do_test 1.4 { file size test.db-wal } {15421352} do_test 1.5 { file size test.db-shm } {131072} do_execsql_test 1.6 { PRAGMA wal_checkpoint } {0 14715 14715} # At this point connection [db2] has mapped the first 32KB of the *shm file # only. Because the entire WAL file has been checkpointed, it is not # necessary to map any more of the *-shm file to read or write the database # (since all data will be read directly from the db file). # # However, at one point if a transaction that had not yet written to the # WAL file was rolled back an assert() attempting to verify that the entire # *-shm file was mapped would fail. If NDEBUG was defined (and the assert() # disabled) this bug caused SQLite to ignore the return code of a mmap() # call. # do_test 1.7 { execsql { BEGIN; INSERT INTO t VALUES('hello'); ROLLBACK; } db2 } {} db2 close finish_test |
Changes to test/whereD.test.
︙ | ︙ | |||
156 157 158 159 160 161 162 163 164 | do_searchcount_test 3.5.1 { SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR rowid=4 } {1 one 2 two search 2} do_searchcount_test 3.5.2 { SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR rowid=4 } {1 i 2 ii search 2} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | do_searchcount_test 3.5.1 { SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR rowid=4 } {1 one 2 two search 2} do_searchcount_test 3.5.2 { SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR rowid=4 } {1 i 2 ii search 2} # Ticket [d02e1406a58ea02d] (2012-10-04) # LEFT JOIN with an OR in the ON clause causes segfault # do_test 4.1 { db eval { CREATE TABLE t41(a,b,c); INSERT INTO t41 VALUES(1,2,3), (4,5,6); CREATE TABLE t42(d,e,f); INSERT INTO t42 VALUES(3,6,9), (4,8,12); SELECT * FROM t41 AS x LEFT JOIN t42 AS y ON (y.d=x.c) OR (y.e=x.b); } } {1 2 3 3 6 9 4 5 6 {} {} {}} do_test 4.2 { db eval { CREATE INDEX t42d ON t42(d); CREATE INDEX t42e ON t42(e); SELECT * FROM t41 AS x LEFT JOIN t42 AS y ON (y.d=x.c) OR (y.e=x.b); } } {1 2 3 3 6 9 4 5 6 {} {} {}} do_test 4.3 { db eval { SELECT * FROM t41 AS x LEFT JOIN t42 AS y ON (y.d=x.c) OR (y.d=x.b); } } {1 2 3 3 6 9 4 5 6 {} {} {}} finish_test |
Changes to tool/build-all-msvc.bat.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @ECHO OFF :: :: build-all-msvc.bat -- :: :: Multi-Platform Build Tool for MSVC :: SETLOCAL REM SET __ECHO=ECHO REM SET __ECHO2=ECHO IF NOT DEFINED _AECHO (SET _AECHO=REM) IF NOT DEFINED _CECHO (SET _CECHO=REM) IF NOT DEFINED _VECHO (SET _VECHO=REM) %_AECHO% Running %0 %* REM SET DFLAGS=/L | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @ECHO OFF :: :: build-all-msvc.bat -- :: :: Multi-Platform Build Tool for MSVC :: SETLOCAL REM SET __ECHO=ECHO REM SET __ECHO2=ECHO REM SET __ECHO3=ECHO IF NOT DEFINED _AECHO (SET _AECHO=REM) IF NOT DEFINED _CECHO (SET _CECHO=REM) IF NOT DEFINED _VECHO (SET _VECHO=REM) %_AECHO% Running %0 %* REM SET DFLAGS=/L |
︙ | ︙ | |||
177 178 179 180 181 182 183 | CALL :fn_UnsetVariable WindowsSdkDir_old REM REM NOTE: Reset the PATH here to the absolute bare minimum required. REM SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot% | > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | CALL :fn_UnsetVariable WindowsSdkDir_old REM REM NOTE: Reset the PATH here to the absolute bare minimum required. REM SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot% FOR %%B IN (Debug Retail) DO ( REM REM NOTE: When preparing the debug build, set the DEBUG and MEMDEBUG REM environment variables to be picked up by the MSVC makefile REM itself. REM IF /I "%%B" == "Debug" ( SET DEBUG=2 SET MEMDEBUG=1 ) ELSE ( CALL :fn_UnsetVariable DEBUG CALL :fn_UnsetVariable MEMDEBUG ) REM REM NOTE: Launch a nested command shell to perform the following steps: REM REM 1. Setup the MSVC environment for this platform using the REM official batch file. REM REM 2. Make sure that no stale build output files are present. REM REM 3. Build the "sqlite3.dll" and "sqlite3.lib" binaries for this REM platform. REM REM 4. Copy the "sqlite3.dll" and "sqlite3.lib" binaries for this REM platform to the platform-specific directory beneath the REM binary directory. REM "%ComSpec%" /C ( REM REM NOTE: Attempt to setup the MSVC environment for this platform. REM %__ECHO3% CALL "%VCINSTALLDIR%\vcvarsall.bat" %%P IF ERRORLEVEL 1 ( ECHO Failed to call "%VCINSTALLDIR%\vcvarsall.bat" for platform %%P. GOTO errors ) REM REM NOTE: If this batch file is not running in "what-if" mode, check to REM be sure we were actually able to setup the MSVC environment REM as current versions of their official batch file do not set REM the exit code upon failure. REM IF NOT DEFINED __ECHO ( IF NOT DEFINED WindowsSdkDir ( ECHO Cannot build, Windows SDK not found for platform %%P. GOTO errors ) ) REM REM NOTE: When using MSVC 2012, the native SDK path cannot simply use REM the "lib" sub-directory beneath the location specified in the REM WindowsSdkDir environment variable because that location does REM not actually contain the necessary library files for x86. REM This must be done for each iteration because it relies upon REM the WindowsSdkDir environment variable being set by the batch REM file used to setup the MSVC environment. REM IF DEFINED SET_NSDKLIBPATH ( CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86 ) REM REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC REM makefile to clean any stale build output from previous REM iterations of this loop and/or previous runs of this batch REM file, etc. REM IF NOT DEFINED NOCLEAN ( %__ECHO% nmake -f Makefile.msc clean IF ERRORLEVEL 1 ( ECHO Failed to clean for platform %%P. GOTO errors ) ) ELSE ( REM REM NOTE: Even when the cleaning step has been disabled, we still REM need to remove the build output for the files we are REM specifically wanting to build for each platform. REM %__ECHO% DEL /Q sqlite3.dll sqlite3.lib sqlite3.pdb ) REM REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.dll" REM binary. The x86 compiler will be used to compile the native REM command line tools needed during the build process itself. REM Also, disable looking for and/or linking to the native Tcl REM runtime library. REM %__ECHO% nmake -f Makefile.msc sqlite3.dll XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% IF ERRORLEVEL 1 ( ECHO Failed to build %%B "sqlite3.dll" for platform %%P. GOTO errors ) REM REM NOTE: Copy the "sqlite3.dll" file to the appropriate directory for REM the build and platform beneath the binary directory. REM %__ECHO% XCOPY sqlite3.dll "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( ECHO Failed to copy "sqlite3.dll" to "%BINARYDIRECTORY%\%%B\%%D\". GOTO errors ) REM REM NOTE: Copy the "sqlite3.lib" file to the appropriate directory for REM the build and platform beneath the binary directory. REM %__ECHO% XCOPY sqlite3.lib "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( ECHO Failed to copy "sqlite3.lib" to "%BINARYDIRECTORY%\%%B\%%D\". GOTO errors ) REM REM NOTE: Copy the "sqlite3.pdb" file to the appropriate directory for REM the build and platform beneath the binary directory unless we REM are prevented from doing so. REM IF NOT DEFINED NOSYMBOLS ( %__ECHO% XCOPY sqlite3.pdb "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% IF ERRORLEVEL 1 ( ECHO Failed to copy "sqlite3.pdb" to "%BINARYDIRECTORY%\%%B\%%D\". GOTO errors ) ) ) ) ) REM REM NOTE: Handle any errors generated during the nested command shell. |
︙ | ︙ |
Changes to tool/mkvsix.tcl.
︙ | ︙ | |||
86 87 88 89 90 91 92 | # NOTE: Performs all Tcl command, variable, and backslash substitutions in # the specified file and then re-writes the contents of that same file # with the substituted data. # return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]] } | | | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | # NOTE: Performs all Tcl command, variable, and backslash substitutions in # the specified file and then re-writes the contents of that same file # with the substituted data. # return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]] } proc replaceBuildAndPlatform { fileName buildName platformName } { # # NOTE: Returns the specified file name containing the platform name instead # of platform placeholder tokens. # return [string map [list <build> $buildName <platform> $platformName] \ $fileName] } set script [file normalize [info script]] if {[string length $script] == 0} then { fail "script file currently being evaluated is unknown" true } |
︙ | ︙ | |||
245 246 247 248 249 250 251 | # # NOTE: Setup the master file list data, including the necessary flags. # if {![info exists fileNames(source)]} then { set fileNames(source) [list "" "" "" \ [file join $sourceDirectory sqlite3.h] \ | | | | | | | < | < | < | > > | > > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | # # NOTE: Setup the master file list data, including the necessary flags. # if {![info exists fileNames(source)]} then { set fileNames(source) [list "" "" "" \ [file join $sourceDirectory sqlite3.h] \ [file join $binaryDirectory <build> <platform> sqlite3.lib] \ [file join $binaryDirectory <build> <platform> sqlite3.dll]] if {![info exists no(symbols)]} then { lappend fileNames(source) \ [file join $binaryDirectory <build> <platform> sqlite3.pdb] } } if {![info exists fileNames(destination)]} then { set fileNames(destination) [list \ [file join $stagingDirectory extension.vsixmanifest] \ [file join $stagingDirectory SDKManifest.xml] \ [file join $stagingDirectory DesignTime <build> <platform> \ SQLite.WinRT.props] \ [file join $stagingDirectory DesignTime <build> <platform> sqlite3.h] \ [file join $stagingDirectory DesignTime <build> <platform> sqlite3.lib] \ [file join $stagingDirectory Redist <build> <platform> sqlite3.dll]] if {![info exists no(symbols)]} then { lappend fileNames(destination) \ [file join $stagingDirectory Redist <build> <platform> sqlite3.pdb] } } if {![info exists fileNames(buildNeutral)]} then { set fileNames(buildNeutral) [list 1 1 1 1 0 0] if {![info exists no(symbols)]} then { lappend fileNames(buildNeutral) 0 } } if {![info exists fileNames(platformNeutral)]} then { set fileNames(platformNeutral) [list 1 1 1 1 0 0] if {![info exists no(symbols)]} then { lappend fileNames(platformNeutral) 0 } } if {![info exists fileNames(subst)]} then { set fileNames(subst) [list 1 1 1 0 0 0] if {![info exists no(symbols)]} then { lappend fileNames(subst) 0 } } if {![info exists fileNames(noDebug)]} then { set fileNames(noDebug) [list 0 0 0 0 0 0] if {![info exists no(symbols)]} then { lappend fileNames(noDebug) 0 } } if {![info exists fileNames(noRetail)]} then { set fileNames(noRetail) [list 0 0 0 0 0 0] if {![info exists no(symbols)]} then { lappend fileNames(noRetail) 1 } } ############################################################################### # # NOTE: Setup the list of builds supported by this script. # if {![info exists buildNames]} then { set buildNames [list Debug Retail] } ############################################################################### # # NOTE: Setup the list of platforms supported by this script. # if {![info exists platformNames]} then { |
︙ | ︙ | |||
320 321 322 323 324 325 326 | # NOTE: Extract the template package to the staging directory. # eval $extractCommand ############################################################################### # | | | | > > | | | > > > | | | | | | > > | > > > > > > > > > > > > > > > > | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # NOTE: Extract the template package to the staging directory. # eval $extractCommand ############################################################################### # # NOTE: Process each file in the master file list. There are actually seven # parallel lists that contain the source file names, the destination file # names, the build-neutral flags, the platform-neutral flags, the # use-subst flags, the no-debug flags, and the no-retail flags. If the # platform-neutral flag is non-zero, the file is not platform-specific. # If the build-neutral flag is non-zero, the file is not build-specific. # If the use-subst flag is non-zero, the file is considered to be a text # file that may contain Tcl variable and/or command replacements, to be # dynamically replaced during processing. If the no-debug flag is # non-zero, the file will be skipped when processing for the debug build. # If the no-retail flag is non-zero, the file will be skipped when # processing for the retail build. If the source file name is an empty # string, then the destination file name will be assumed to already exist # in the staging directory and will not be copied; however, dynamic # replacements may still be performed on the destination file prior to # the package being re-zipped. # foreach sourceFileName $fileNames(source) \ destinationFileName $fileNames(destination) \ buildNeutral $fileNames(buildNeutral) \ platformNeutral $fileNames(platformNeutral) \ useSubst $fileNames(subst) \ noDebug $fileNames(noDebug) \ noRetail $fileNames(noRetail) { # # NOTE: If the current file is build-neutral, then only one build will # be processed for it, namely "CommonConfiguration"; otherwise, each # supported build will be processed for it individually. # foreach buildName \ [expr {$buildNeutral ? [list CommonConfiguration] : $buildNames}] { # # NOTE: Should the current file be skipped for this build? # if {[info exists no${buildName}] && [set no${buildName}]} then { continue } # # NOTE: If the current file is platform-neutral, then only one platform # will be processed for it, namely "neutral"; otherwise, each # supported platform will be processed for it individually. # foreach platformName \ [expr {$platformNeutral ? [list neutral] : $platformNames}] { # # NOTE: Use the actual platform name in the destination file name. # set newDestinationFileName [replaceBuildAndPlatform \ $destinationFileName $buildName $platformName] # # NOTE: Does the source file need to be copied to the destination file? # if {[string length $sourceFileName] > 0} then { # # NOTE: First, make sure the destination directory exists. # file mkdir [file dirname $newDestinationFileName] # # NOTE: Then, copy the source file to the destination file verbatim. # file copy [replaceBuildAndPlatform $sourceFileName $buildName \ $platformName] $newDestinationFileName } # # NOTE: Does the destination file contain dynamic replacements that must # be processed now? # if {$useSubst} then { # # NOTE: Perform any dynamic replacements contained in the destination # file and then re-write it in-place. # substFile $newDestinationFileName } } } } ############################################################################### # |
︙ | ︙ |
Changes to tool/showdb.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /* ** A utility for printing all or part of an SQLite database file. */ #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" static int pagesize = 1024; /* Size of a database page */ static int db = -1; /* File descriptor for reading the DB */ | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* ** A utility for printing all or part of an SQLite database file. */ #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #if !defined(_MSC_VER) #include <unistd.h> #endif #include <stdlib.h> #include <string.h> #include "sqlite3.h" static int pagesize = 1024; /* Size of a database page */ static int db = -1; /* File descriptor for reading the DB */ |
︙ | ︙ |
Changes to tool/spaceanal.tcl.
︙ | ︙ | |||
26 27 28 29 30 31 32 | } elseif {$file_to_analyze!=""} { usage } else { set file_to_analyze $arg } } if {$file_to_analyze==""} usage | > > | | | | | | | | | | > > > | 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 | } elseif {$file_to_analyze!=""} { usage } else { set file_to_analyze $arg } } if {$file_to_analyze==""} usage set root_filename $file_to_analyze regexp {^file:(//)?([^?]*)} $file_to_analyze all x1 root_filename if {![file exists $root_filename]} { puts stderr "No such file: $root_filename" exit 1 } if {![file readable $root_filename]} { puts stderr "File is not readable: $root_filename" exit 1 } set true_file_size [file size $root_filename] if {$true_file_size<512} { puts stderr "Empty or malformed database: $root_filename" exit 1 } # Compute the total file size assuming test_multiplexor is being used. # Assume that SQLITE_ENABLE_8_3_NAMES might be enabled # set extension [file extension $root_filename] set pattern $root_filename append pattern {[0-3][0-9][0-9]} foreach f [glob -nocomplain $pattern] { incr true_file_size [file size $f] set extension {} } if {[string length $extension]>=2 && [string length $extension]<=4} { set pattern [file rootname $root_filename] append pattern {.[0-3][0-9][0-9]} foreach f [glob -nocomplain $pattern] { incr true_file_size [file size $f] } } # Open the database # if {[catch {sqlite3 db $file_to_analyze -uri 1} msg]} { puts stderr "error trying to open $file_to_analyze: $msg" exit 1 } register_dbstat_vtab db db eval {SELECT count(*) FROM sqlite_master} set pageSize [expr {wide([db one {PRAGMA page_size}])}] if {$flags(-pageinfo)} { db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat} |
︙ | ︙ | |||
480 481 482 483 484 485 486 | # set total_payload [mem eval "SELECT sum(payload) FROM space_used"] set user_payload [mem one {SELECT int(sum(payload)) FROM space_used WHERE NOT is_index AND name NOT LIKE 'sqlite_master'}] set user_percent [percent $user_payload $file_bytes] # Output the summary statistics calculated above. # | | | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | # set total_payload [mem eval "SELECT sum(payload) FROM space_used"] set user_payload [mem one {SELECT int(sum(payload)) FROM space_used WHERE NOT is_index AND name NOT LIKE 'sqlite_master'}] set user_percent [percent $user_payload $file_bytes] # Output the summary statistics calculated above. # puts "/** Disk-Space Utilization Report For $root_filename" catch { puts "*** As of [clock format [clock seconds] -format {%Y-%b-%d %H:%M:%S}]" } puts "" statline {Page size in bytes} $pageSize statline {Pages in the whole file (measured)} $file_pgcnt statline {Pages in the whole file (calculated)} $file_pgcnt2 |
︙ | ︙ |