Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge recent trunk enhancements. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | apple-osx |
Files: | files | file ages | folders |
SHA1: |
ccb601f6dffba68a57d82db2d046aa27 |
User & Date: | drh 2014-11-18 21:27:48.468 |
Context
2014-12-02
| ||
16:38 | Merge all recent enhancements and bug fixes from trunk into the apple-osx branch. (check-in: 43c4ba26a2 user: drh tags: apple-osx) | |
2014-11-18
| ||
21:27 | Merge recent trunk enhancements. (check-in: ccb601f6df user: drh tags: apple-osx) | |
20:49 | Merge in all the other ROLLBACK fixes from the branch-3.8.7 branch. I don't know why I was doing them one-by-one. (check-in: 296b0c7397 user: drh tags: trunk) | |
2014-10-31
| ||
15:20 | Merge all recent trunk enhancements into the apple-osx branch. (check-in: fef8430f12 user: drh tags: apple-osx) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
393 394 395 396 397 398 399 400 401 402 403 404 405 406 | $(TOP)/ext/fts3/fts3_test.c # Statically linked extensions # TESTSRC += \ $(TOP)/ext/misc/amatch.c \ $(TOP)/ext/misc/closure.c \ $(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fuzzer.c \ $(TOP)/ext/misc/ieee754.c \ $(TOP)/ext/misc/nextchar.c \ $(TOP)/ext/misc/percentile.c \ $(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/spellfix.c \ | > | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | $(TOP)/ext/fts3/fts3_test.c # Statically linked extensions # TESTSRC += \ $(TOP)/ext/misc/amatch.c \ $(TOP)/ext/misc/closure.c \ $(TOP)/ext/misc/eval.c \ $(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fuzzer.c \ $(TOP)/ext/misc/ieee754.c \ $(TOP)/ext/misc/nextchar.c \ $(TOP)/ext/misc/percentile.c \ $(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/spellfix.c \ |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
859 860 861 862 863 864 865 866 867 868 869 870 871 872 | $(TOP)\ext\fts3\fts3_test.c # Statically linked extensions # TESTEXT = \ $(TOP)\ext\misc\amatch.c \ $(TOP)\ext\misc\closure.c \ $(TOP)\ext\misc\fileio.c \ $(TOP)\ext\misc\fuzzer.c \ $(TOP)\ext\misc\ieee754.c \ $(TOP)\ext\misc\nextchar.c \ $(TOP)\ext\misc\percentile.c \ $(TOP)\ext\misc\regexp.c \ $(TOP)\ext\misc\spellfix.c \ | > | 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 | $(TOP)\ext\fts3\fts3_test.c # Statically linked extensions # TESTEXT = \ $(TOP)\ext\misc\amatch.c \ $(TOP)\ext\misc\closure.c \ $(TOP)\ext\misc\eval.c \ $(TOP)\ext\misc\fileio.c \ $(TOP)\ext\misc\fuzzer.c \ $(TOP)\ext\misc\ieee754.c \ $(TOP)\ext\misc\nextchar.c \ $(TOP)\ext\misc\percentile.c \ $(TOP)\ext\misc\regexp.c \ $(TOP)\ext\misc\spellfix.c \ |
︙ | ︙ |
Added ext/misc/eval.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 | /* ** 2014-11-10 ** ** 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 SQLite extension implements SQL function eval() which runs ** SQL statements recursively. */ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <string.h> /* ** Structure used to accumulate the output */ struct EvalResult { char *z; /* Accumulated output */ const char *zSep; /* Separator */ int szSep; /* Size of the separator string */ int nAlloc; /* Number of bytes allocated for z[] */ int nUsed; /* Number of bytes of z[] actually used */ }; /* ** Callback from sqlite_exec() for the eval() function. */ static int callback(void *pCtx, int argc, char **argv, char **colnames){ struct EvalResult *p = (struct EvalResult*)pCtx; int i; for(i=0; i<argc; i++){ const char *z = argv[i] ? argv[i] : ""; size_t sz = strlen(z); if( sz+p->nUsed+p->szSep+1 > p->nAlloc ){ char *zNew; p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1; zNew = sqlite3_realloc(p->z, p->nAlloc); if( zNew==0 ){ sqlite3_free(p->z); memset(p, 0, sizeof(*p)); return 1; } p->z = zNew; } if( p->nUsed>0 ){ memcpy(&p->z[p->nUsed], p->zSep, p->szSep); p->nUsed += p->szSep; } memcpy(&p->z[p->nUsed], z, sz); p->nUsed += sz; } return 0; } /* ** Implementation of the eval(X) and eval(X,Y) SQL functions. ** ** Evaluate the SQL text in X. Return the results, using string ** Y as the separator. If Y is omitted, use a single space character. */ static void sqlEvalFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zSql; sqlite3 *db; char *zErr = 0; int rc; struct EvalResult x; memset(&x, 0, sizeof(x)); x.zSep = " "; zSql = (const char*)sqlite3_value_text(argv[0]); if( zSql==0 ) return; if( argc>1 ){ x.zSep = (const char*)sqlite3_value_text(argv[1]); if( x.zSep==0 ) return; } x.szSep = (int)strlen(x.zSep); db = sqlite3_context_db_handle(context); rc = sqlite3_exec(db, zSql, callback, &x, &zErr); if( rc!=SQLITE_OK ){ sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr); }else if( x.zSep==0 ){ sqlite3_result_error_nomem(context); sqlite3_free(x.z); }else{ sqlite3_result_text(context, x.z, x.nUsed, sqlite3_free); } } #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_eval_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0); } return rc; } |
Changes to main.mk.
︙ | ︙ | |||
244 245 246 247 248 249 250 251 252 253 254 255 256 257 | $(TOP)/src/test6.c \ $(TOP)/src/test7.c \ $(TOP)/src/test8.c \ $(TOP)/src/test9.c \ $(TOP)/src/test_autoext.c \ $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_fs.c \ $(TOP)/src/test_func.c \ $(TOP)/src/test_hexio.c \ | > | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | $(TOP)/src/test6.c \ $(TOP)/src/test7.c \ $(TOP)/src/test8.c \ $(TOP)/src/test9.c \ $(TOP)/src/test_autoext.c \ $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ $(TOP)/src/test_blob.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_fs.c \ $(TOP)/src/test_func.c \ $(TOP)/src/test_hexio.c \ |
︙ | ︙ | |||
278 279 280 281 282 283 284 285 286 287 288 289 290 291 | $(TOP)/src/test_wsd.c # Extensions to be statically loaded. # TESTSRC += \ $(TOP)/ext/misc/amatch.c \ $(TOP)/ext/misc/closure.c \ $(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fuzzer.c \ $(TOP)/ext/misc/ieee754.c \ $(TOP)/ext/misc/nextchar.c \ $(TOP)/ext/misc/percentile.c \ $(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/spellfix.c \ | > | 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | $(TOP)/src/test_wsd.c # Extensions to be statically loaded. # TESTSRC += \ $(TOP)/ext/misc/amatch.c \ $(TOP)/ext/misc/closure.c \ $(TOP)/ext/misc/eval.c \ $(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fuzzer.c \ $(TOP)/ext/misc/ieee754.c \ $(TOP)/ext/misc/nextchar.c \ $(TOP)/ext/misc/percentile.c \ $(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/spellfix.c \ |
︙ | ︙ |
Changes to src/backup.c.
︙ | ︙ | |||
117 118 119 120 121 122 123 124 125 126 127 128 129 130 | ** of the source. */ static int setDestPgsz(sqlite3_backup *p){ int rc; rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0); return rc; } /* ** Create an sqlite3_backup process to copy the contents of zSrcDb from ** connection handle pSrcDb to zDestDb in pDestDb. If successful, return ** a pointer to the new sqlite3_backup object. ** ** If an error occurs, NULL is returned and an error code and error message | > > > > > > > > > > > > > > | 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 | ** of the source. */ static int setDestPgsz(sqlite3_backup *p){ int rc; rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0); return rc; } /* ** Check that there is no open read-transaction on the b-tree passed as the ** second argument. If there is not, return SQLITE_OK. Otherwise, if there ** is an open read-transaction, return SQLITE_ERROR and leave an error ** message in database handle db. */ static int checkReadTransaction(sqlite3 *db, Btree *p){ if( sqlite3BtreeIsInReadTrans(p) ){ sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use"); return SQLITE_ERROR; } return SQLITE_OK; } /* ** Create an sqlite3_backup process to copy the contents of zSrcDb from ** connection handle pSrcDb to zDestDb in pDestDb. If successful, return ** a pointer to the new sqlite3_backup object. ** ** If an error occurs, NULL is returned and an error code and error message |
︙ | ︙ | |||
177 178 179 180 181 182 183 | p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); p->pDest = findBtree(pDestDb, pDestDb, zDestDb); p->pDestDb = pDestDb; p->pSrcDb = pSrcDb; p->iNext = 1; p->isAttached = 0; | | > > > > | | | < | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); p->pDest = findBtree(pDestDb, pDestDb, zDestDb); p->pDestDb = pDestDb; p->pSrcDb = pSrcDb; p->iNext = 1; p->isAttached = 0; if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK ){ /* One (or both) of the named databases did not exist or an OOM ** error was hit. Or there is a transaction open on the destination ** database. The error has already been written into the pDestDb ** handle. All that is left to do here is free the sqlite3_backup ** structure. */ sqlite3_free(p); p = 0; } } if( p ){ p->pSrc->nBackup++; } |
︙ | ︙ | |||
603 604 605 606 607 608 609 | while( *pp!=p ){ pp = &(*pp)->pNext; } *pp = p->pNext; } /* If a transaction is still open on the Btree, roll it back. */ | | | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 | while( *pp!=p ){ pp = &(*pp)->pNext; } *pp = p->pNext; } /* If a transaction is still open on the Btree, roll it back. */ sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0); /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; if( p->pDestDb ){ sqlite3Error(p->pDestDb, rc); /* Exit the mutexes and free the backup context structure. */ |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
1299 1300 1301 1302 1303 1304 1305 1306 | ** allocation is being made in order to insert a new cell, so we will ** also end up needing a new cell pointer. */ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */ u8 * const data = pPage->aData; /* Local cache of pPage->aData */ int top; /* First byte of cell content area */ int gap; /* First byte of gap between cell pointers and cell content */ | > < | 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 | ** allocation is being made in order to insert a new cell, so we will ** also end up needing a new cell pointer. */ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */ u8 * const data = pPage->aData; /* Local cache of pPage->aData */ int top; /* First byte of cell content area */ int rc = SQLITE_OK; /* Integer return code */ int gap; /* First byte of gap between cell pointers and cell content */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( nByte>=0 ); /* Minimum cell size is 4 */ assert( pPage->nFree>=nByte ); assert( pPage->nOverflow==0 ); |
︙ | ︙ | |||
1330 1331 1332 1333 1334 1335 1336 | ** array entry offset, and if the freelist is not empty, then search the ** freelist looking for a free slot big enough to satisfy the request. */ testcase( gap+2==top ); testcase( gap+1==top ); testcase( gap==top ); if( gap+2<=top && (data[hdr+1] || data[hdr+2]) ){ | < > | | 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 | ** array entry offset, and if the freelist is not empty, then search the ** freelist looking for a free slot big enough to satisfy the request. */ testcase( gap+2==top ); testcase( gap+1==top ); testcase( gap==top ); if( gap+2<=top && (data[hdr+1] || data[hdr+2]) ){ int bDefrag = 0; u8 *pSpace = pageFindSlot(pPage, nByte, &rc, &bDefrag); if( rc ) return rc; if( bDefrag ) goto defragment_page; if( pSpace ){ assert( pSpace>=data && (pSpace - data)<65536 ); *pIdx = (int)(pSpace - data); return SQLITE_OK; } } /* The request could not be fulfilled using a freelist slot. Check ** to see if defragmentation is necessary. */ |
︙ | ︙ | |||
2215 2216 2217 2218 2219 2220 2221 | } } /* Rollback any active transaction and free the handle structure. ** The call to sqlite3BtreeRollback() drops any table-locks held by ** this handle. */ | | | 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 | } } /* Rollback any active transaction and free the handle structure. ** The call to sqlite3BtreeRollback() drops any table-locks held by ** this handle. */ sqlite3BtreeRollback(p, SQLITE_OK, 0); sqlite3BtreeLeave(p); /* If there are still other outstanding references to the shared-btree ** structure, return now. The remainder of this procedure cleans ** up the shared-btree. */ assert( p->wantToLock==0 && p->locked==0 ); |
︙ | ︙ | |||
3529 3530 3531 3532 3533 3534 3535 | } sqlite3BtreeLeave(p); return rc; } /* ** This routine sets the state to CURSOR_FAULT and the error | | | > | | | | | < > | > > | | | > > > > > > | > > > | | | | > > > > > > > > > | | | > | | | | | | | > | > | > > > | < | | > > > | > > | 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 | } sqlite3BtreeLeave(p); return rc; } /* ** This routine sets the state to CURSOR_FAULT and the error ** code to errCode for every cursor on any BtShared that pBtree ** references. Or if the writeOnly flag is set to 1, then only ** trip write cursors and leave read cursors unchanged. ** ** Every cursor is a candidate to be tripped, including cursors ** that belong to other database connections that happen to be ** sharing the cache with pBtree. ** ** This routine gets called when a rollback occurs. If the writeOnly ** flag is true, then only write-cursors need be tripped - read-only ** cursors save their current positions so that they may continue ** following the rollback. Or, if writeOnly is false, all cursors are ** tripped. In general, writeOnly is false if the transaction being ** rolled back modified the database schema. In this case b-tree root ** pages may be moved or deleted from the database altogether, making ** it unsafe for read cursors to continue. ** ** If the writeOnly flag is true and an error is encountered while ** saving the current position of a read-only cursor, all cursors, ** including all read-cursors are tripped. ** ** SQLITE_OK is returned if successful, or if an error occurs while ** saving a cursor position, an SQLite error code. */ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){ BtCursor *p; int rc = SQLITE_OK; assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 ); if( pBtree ){ sqlite3BtreeEnter(pBtree); for(p=pBtree->pBt->pCursor; p; p=p->pNext){ int i; if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ if( p->eState==CURSOR_VALID ){ rc = saveCursorPosition(p); if( rc!=SQLITE_OK ){ (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0); break; } } }else{ sqlite3BtreeClearCursor(p); p->eState = CURSOR_FAULT; p->skipNext = errCode; } for(i=0; i<=p->iPage; i++){ releasePage(p->apPage[i]); p->apPage[i] = 0; } } sqlite3BtreeLeave(pBtree); } return rc; } /* ** Rollback the transaction in progress. ** ** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped). ** Only write cursors are tripped if writeOnly is true but all cursors are ** tripped if writeOnly is false. Any attempt to use ** a tripped cursor will result in an error. ** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){ int rc; BtShared *pBt = p->pBt; MemPage *pPage1; assert( writeOnly==1 || writeOnly==0 ); assert( tripCode==SQLITE_ABORT_ROLLBACK || tripCode==SQLITE_OK ); sqlite3BtreeEnter(p); if( tripCode==SQLITE_OK ){ rc = tripCode = saveAllCursors(pBt, 0, 0); if( rc ) writeOnly = 0; }else{ rc = SQLITE_OK; } if( tripCode ){ int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly); assert( rc==SQLITE_OK || (writeOnly==0 && rc2==SQLITE_OK) ); if( rc2!=SQLITE_OK ) rc = rc2; } btreeIntegrity(p); if( p->inTrans==TRANS_WRITE ){ int rc2; assert( TRANS_WRITE==pBt->inTransaction ); |
︙ | ︙ | |||
3917 3918 3919 3920 3921 3922 3923 | ** ** The caller must position the cursor prior to invoking this routine. ** ** This routine cannot fail. It always returns SQLITE_OK. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ assert( cursorHoldsMutex(pCur) ); | | < < < | | < | 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 | ** ** The caller must position the cursor prior to invoking this routine. ** ** This routine cannot fail. It always returns SQLITE_OK. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); getCellInfo(pCur); *pSize = pCur->info.nKey; return SQLITE_OK; } /* ** Set *pSize to the number of bytes of data in the entry the ** cursor currently points to. ** |
︙ | ︙ | |||
6140 6141 6142 6143 6144 6145 6146 | int szFree = 0; for(i=0; i<nCell; i++){ u8 *pCell = apCell[i]; if( pCell>=pStart && pCell<pEnd ){ int sz = szCell[i]; if( pFree!=(pCell + sz) ){ | | > > > | > > > | 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 | int szFree = 0; for(i=0; i<nCell; i++){ u8 *pCell = apCell[i]; if( pCell>=pStart && pCell<pEnd ){ int sz = szCell[i]; if( pFree!=(pCell + sz) ){ if( pFree ){ assert( pFree>aData && (pFree - aData)<65536 ); freeSpace(pPg, (u16)(pFree - aData), szFree); } pFree = pCell; szFree = sz; if( pFree+sz>pEnd ) return 0; }else{ pFree = pCell; szFree += sz; } nRet++; } } if( pFree ){ assert( pFree>aData && (pFree - aData)<65536 ); freeSpace(pPg, (u16)(pFree - aData), szFree); } return nRet; } /* ** The pPg->nFree field is invalid when this function returns. It is the ** responsibility of the caller to set it correctly. */ |
︙ | ︙ | |||
6215 6216 6217 6218 6219 6220 6221 | nCell += nAdd; } /* Add any overflow cells */ for(i=0; i<pPg->nOverflow; i++){ int iCell = (iOld + pPg->aiOvfl[i]) - iNew; if( iCell>=0 && iCell<nNew ){ | | | 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 | nCell += nAdd; } /* Add any overflow cells */ for(i=0; i<pPg->nOverflow; i++){ int iCell = (iOld + pPg->aiOvfl[i]) - iNew; if( iCell>=0 && iCell<nNew ){ pCellptr = &pPg->aCellIdx[iCell * 2]; memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); nCell++; if( pageInsertArray( pPg, pBegin, &pData, pCellptr, 1, &apCell[iCell + iNew], &szCell[iCell + iNew] ) ) goto editpage_fail; } |
︙ | ︙ | |||
6672 6673 6674 6675 6676 6677 6678 | /* ** Allocate space for memory structures */ szScratch = nMaxCells*sizeof(u8*) /* apCell */ + nMaxCells*sizeof(u16) /* szCell */ + pBt->pageSize; /* aSpace1 */ | > > > | | 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 | /* ** Allocate space for memory structures */ szScratch = nMaxCells*sizeof(u8*) /* apCell */ + nMaxCells*sizeof(u16) /* szCell */ + pBt->pageSize; /* aSpace1 */ /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer ** that is more than 6 times the database page size. */ assert( szScratch<=6*pBt->pageSize ); apCell = sqlite3ScratchMalloc( szScratch ); if( apCell==0 ){ rc = SQLITE_NOMEM; goto balance_cleanup; } szCell = (u16*)&apCell[nMaxCells]; aSpace1 = (u8*)&szCell[nMaxCells]; |
︙ | ︙ | |||
6901 6902 6903 6904 6905 6906 6907 | rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } } } for(i=0; i<nNew; i++){ int iBest = 0; /* aPgno[] index of page number to use */ | < | 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 | rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } } } for(i=0; i<nNew; i++){ int iBest = 0; /* aPgno[] index of page number to use */ for(j=1; j<nNew; j++){ if( aPgOrder[j]<aPgOrder[iBest] ) iBest = j; } pgno = aPgOrder[iBest]; aPgOrder[iBest] = 0xffffffff; if( iBest!=i ){ if( iBest>i ){ |
︙ | ︙ | |||
8988 8989 8990 8991 8992 8993 8994 | /* ** Return true if the given Btree is read-only. */ int sqlite3BtreeIsReadonly(Btree *p){ return (p->pBt->btsFlags & BTS_READ_ONLY)!=0; } | > > > > > | 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 | /* ** Return true if the given Btree is read-only. */ int sqlite3BtreeIsReadonly(Btree *p){ return (p->pBt->btsFlags & BTS_READ_ONLY)!=0; } /* ** Return the size of the header added to each page by this module. */ int sqlite3HeaderSizeBtree(void){ return sizeof(MemPage); } |
Changes to src/btree.h.
︙ | ︙ | |||
79 80 81 82 83 84 85 | #endif int sqlite3BtreeSetAutoVacuum(Btree *, int); int sqlite3BtreeGetAutoVacuum(Btree *); int sqlite3BtreeBeginTrans(Btree*,int); int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); int sqlite3BtreeCommitPhaseTwo(Btree*, int); int sqlite3BtreeCommit(Btree*); | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | #endif int sqlite3BtreeSetAutoVacuum(Btree *, int); int sqlite3BtreeGetAutoVacuum(Btree *); int sqlite3BtreeBeginTrans(Btree*,int); int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); int sqlite3BtreeCommitPhaseTwo(Btree*, int); int sqlite3BtreeCommit(Btree*); int sqlite3BtreeRollback(Btree*,int,int); int sqlite3BtreeBeginStmt(Btree*,int); int sqlite3BtreeCreateTable(Btree*, int*, int flags); int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInReadTrans(Btree*); int sqlite3BtreeIsInBackup(Btree*); void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); int sqlite3BtreeSchemaLocked(Btree *pBtree); |
︙ | ︙ | |||
112 113 114 115 116 117 118 | */ #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ #define BTREE_BLOBKEY 2 /* Table has keys only - no data */ int sqlite3BtreeDropTable(Btree*, int, int*); int sqlite3BtreeClearTable(Btree*, int, int*); int sqlite3BtreeClearTableOfCursor(BtCursor*); | | | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | */ #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ #define BTREE_BLOBKEY 2 /* Table has keys only - no data */ int sqlite3BtreeDropTable(Btree*, int, int*); int sqlite3BtreeClearTable(Btree*, int, int*); int sqlite3BtreeClearTableOfCursor(BtCursor*); int sqlite3BtreeTripAllCursors(Btree*, int, int); void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); int sqlite3BtreeNewDb(Btree *p); /* |
︙ | ︙ | |||
192 193 194 195 196 197 198 199 200 201 202 203 204 205 | int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeIncrblobCursor(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); int sqlite3BtreeIsReadonly(Btree *pBt); #ifndef NDEBUG int sqlite3BtreeCursorIsValid(BtCursor*); #endif #ifndef SQLITE_OMIT_BTREECOUNT int sqlite3BtreeCount(BtCursor *, i64 *); | > | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeIncrblobCursor(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); int sqlite3BtreeIsReadonly(Btree *pBt); int sqlite3HeaderSizeBtree(void); #ifndef NDEBUG int sqlite3BtreeCursorIsValid(BtCursor*); #endif #ifndef SQLITE_OMIT_BTREECOUNT int sqlite3BtreeCount(BtCursor *, i64 *); |
︙ | ︙ |
Changes to src/btreeInt.h.
︙ | ︙ | |||
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 | ** ** A single database file can be shared by two more database connections, ** but cursors cannot be shared. Each cursor is associated with a ** particular database connection identified BtCursor.pBtree.db. ** ** Fields in this structure are accessed under the BtShared.mutex ** found at self->pBt->mutex. */ struct BtCursor { Btree *pBtree; /* The Btree to which this cursor belongs */ BtShared *pBt; /* The BtShared this cursor points to */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ Pgno *aOverflow; /* Cache of overflow page locations */ CellInfo info; /* A parse of the cell we are pointing at */ i64 nKey; /* Size of pKey, or last integer key */ void *pKey; /* Saved key that was cursor last known position */ Pgno pgnoRoot; /* The root page of this tree */ int nOvflAlloc; /* Allocated size of aOverflow[] array */ | > > > > > | > | 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 | ** ** A single database file can be shared by two more database connections, ** but cursors cannot be shared. Each cursor is associated with a ** particular database connection identified BtCursor.pBtree.db. ** ** Fields in this structure are accessed under the BtShared.mutex ** found at self->pBt->mutex. ** ** skipNext meaning: ** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op. ** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op. ** eState==FAULT: Cursor fault with skipNext as error code. */ struct BtCursor { Btree *pBtree; /* The Btree to which this cursor belongs */ BtShared *pBt; /* The BtShared this cursor points to */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ Pgno *aOverflow; /* Cache of overflow page locations */ CellInfo info; /* A parse of the cell we are pointing at */ i64 nKey; /* Size of pKey, or last integer key */ void *pKey; /* Saved key that was cursor last known position */ Pgno pgnoRoot; /* The root page of this tree */ int nOvflAlloc; /* Allocated size of aOverflow[] array */ int skipNext; /* Prev() is noop if negative. Next() is noop if positive. ** Error code if eState==CURSOR_FAULT */ u8 curFlags; /* zero or more BTCF_* flags defined below */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ u8 hints; /* As configured by CursorSetHints() */ i16 iPage; /* Index of current page in apPage */ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ }; |
︙ | ︙ | |||
543 544 545 546 547 548 549 | ** seek the cursor to the saved position. ** ** CURSOR_FAULT: ** An unrecoverable error (an I/O error or a malloc failure) has occurred ** on a different connection that shares the BtShared cache with this ** cursor. The error has left the cache in an inconsistent state. ** Do nothing else with this cursor. Any attempt to use the cursor | | | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | ** seek the cursor to the saved position. ** ** CURSOR_FAULT: ** An unrecoverable error (an I/O error or a malloc failure) has occurred ** on a different connection that shares the BtShared cache with this ** cursor. The error has left the cache in an inconsistent state. ** Do nothing else with this cursor. Any attempt to use the cursor ** should return the error code stored in BtCursor.skipNext */ #define CURSOR_INVALID 0 #define CURSOR_VALID 1 #define CURSOR_SKIPNEXT 2 #define CURSOR_REQUIRESEEK 3 #define CURSOR_FAULT 4 |
︙ | ︙ |
Changes to src/date.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement date and time ** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | | 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 | ** This file contains the C functions that implement date and time ** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** ** SQLite processes all times and dates as julian day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian ** calendar system. ** ** 1970-01-01 00:00:00 is JD 2440587.5 ** 2000-01-01 00:00:00 is JD 2451544.5 ** ** This implementation requires years to be expressed as a 4-digit number ** which means that only dates between 0000-01-01 and 9999-12-31 can ** be represented, even though julian day numbers allow a much wider ** range of dates. ** ** The Gregorian calendar system is used for all dates and times, ** even those that predate the Gregorian calendar. Historians usually ** use the julian calendar for dates prior to 1582-10-15 and for some ** dates afterwards, depending on locale. Beware of this difference. ** ** The conversion algorithms are implemented based on descriptions ** in the following text: ** ** Jean Meeus ** Astronomical Algorithms, 2nd Edition, 1998 |
︙ | ︙ | |||
300 301 302 303 304 305 306 | return 0; }else{ return 1; } } /* | | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | return 0; }else{ return 1; } } /* ** Attempt to parse the given string into a julian day number. Return ** the number of errors. ** ** The following are acceptable forms for the input string: ** ** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM ** DDDD.DD ** now |
︙ | ︙ | |||
871 872 873 874 875 876 877 | ** ** Return a string described by FORMAT. Conversions as follows: ** ** %d day of month ** %f ** fractional seconds SS.SSS ** %H hour 00-24 ** %j day of year 000-366 | | | 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 | ** ** Return a string described by FORMAT. Conversions as follows: ** ** %d day of month ** %f ** fractional seconds SS.SSS ** %H hour 00-24 ** %j day of year 000-366 ** %J ** julian day number ** %m month 01-12 ** %M minute 00-59 ** %s seconds since 1970-01-01 ** %S seconds 00-59 ** %w day of week 0-6 sunday==0 ** %W week of year 00-53 ** %Y year 0000-9999 |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1853 1854 1855 1856 1857 1858 1859 | assert( !isRowid ); sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); dest.affSdst = (u8)affinity; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); pSelect->iLimit = 0; testcase( pSelect->selFlags & SF_Distinct ); | < | 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 | assert( !isRowid ); sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); dest.affSdst = (u8)affinity; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); pSelect->iLimit = 0; testcase( pSelect->selFlags & SF_Distinct ); testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ if( sqlite3Select(pParse, pSelect, &dest) ){ sqlite3KeyInfoUnref(pKeyInfo); return 0; } pEList = pSelect->pEList; assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ |
︙ | ︙ |
Changes to src/global.c.
︙ | ︙ | |||
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | /* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards ** compatibility for legacy applications, the URI filename capability is ** disabled by default. ** ** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled ** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options. */ #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 0 #endif #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 #endif /* ** The following singleton contains the global configuration for ** the SQLite library. | > > > > > > > > | 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 | /* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards ** compatibility for legacy applications, the URI filename capability is ** disabled by default. ** ** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled ** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options. ** ** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** SQLITE_USE_URI symbol defined. */ #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 0 #endif /* EVIDENCE-OF: R-38720-18127 The default setting is determined by the ** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if ** that compile-time option is omitted. */ #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 #endif /* ** The following singleton contains the global configuration for ** the SQLite library. |
︙ | ︙ | |||
225 226 227 228 229 230 231 | ** a different position in the file. This allows code that has to ** deal with the pending byte to run on files that are much smaller ** than 1 GiB. The sqlite3_test_control() interface can be used to ** move the pending byte. ** ** IMPORTANT: Changing the pending byte to any value other than ** 0x40000000 results in an incompatible database file format! | | | | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | ** a different position in the file. This allows code that has to ** deal with the pending byte to run on files that are much smaller ** than 1 GiB. The sqlite3_test_control() interface can be used to ** move the pending byte. ** ** IMPORTANT: Changing the pending byte to any value other than ** 0x40000000 results in an incompatible database file format! ** Changing the pending byte during operation will result in undefined ** and incorrect behavior. */ #ifndef SQLITE_OMIT_WSD int sqlite3PendingByte = 0x40000000; #endif #include "opcodes.h" /* ** Properties of opcodes. The OPFLG_INITIALIZER macro is ** created by mkopcodeh.awk during compilation. Data is obtained ** from the comments following the "case OP_xxxx:" statements in ** the vdbe.c file. */ const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; |
Changes to src/main.c.
︙ | ︙ | |||
328 329 330 331 332 333 334 | ** the SQLite library is in use. */ if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT; va_start(ap, op); switch( op ){ /* Mutex configuration options are only available in a threadsafe | | | > > > > > > > > < > > > > | > > > | > > | > > | > > > | > > > > > > > > > > > > > > | > > > > > > > > | > > | > > > | | < | > | < < | 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 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 | ** the SQLite library is in use. */ if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT; va_start(ap, op); switch( op ){ /* Mutex configuration options are only available in a threadsafe ** compile. */ #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */ case SQLITE_CONFIG_SINGLETHREAD: { /* Disable all mutexing */ sqlite3GlobalConfig.bCoreMutex = 0; sqlite3GlobalConfig.bFullMutex = 0; break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */ case SQLITE_CONFIG_MULTITHREAD: { /* Disable mutexing of database connections */ /* Enable mutexing of core data structures */ sqlite3GlobalConfig.bCoreMutex = 1; sqlite3GlobalConfig.bFullMutex = 0; break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */ case SQLITE_CONFIG_SERIALIZED: { /* Enable all mutexing */ sqlite3GlobalConfig.bCoreMutex = 1; sqlite3GlobalConfig.bFullMutex = 1; break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */ case SQLITE_CONFIG_MUTEX: { /* Specify an alternative mutex implementation */ sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*); break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-14450-37597 */ case SQLITE_CONFIG_GETMUTEX: { /* Retrieve the current mutex implementation */ *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex; break; } #endif case SQLITE_CONFIG_MALLOC: { /* EVIDENCE-OF: R-55594-21030 The SQLITE_CONFIG_MALLOC option takes a ** single argument which is a pointer to an instance of the ** sqlite3_mem_methods structure. The argument specifies alternative ** low-level memory allocation routines to be used in place of the memory ** allocation routines built into SQLite. */ sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*); break; } case SQLITE_CONFIG_GETMALLOC: { /* EVIDENCE-OF: R-51213-46414 The SQLITE_CONFIG_GETMALLOC option takes a ** single argument which is a pointer to an instance of the ** sqlite3_mem_methods structure. The sqlite3_mem_methods structure is ** filled with the currently defined memory allocation routines. */ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; break; } case SQLITE_CONFIG_MEMSTATUS: { /* EVIDENCE-OF: R-61275-35157 The SQLITE_CONFIG_MEMSTATUS option takes ** single argument of type int, interpreted as a boolean, which enables ** or disables the collection of memory allocation statistics. */ sqlite3GlobalConfig.bMemstat = va_arg(ap, int); break; } case SQLITE_CONFIG_SCRATCH: { /* EVIDENCE-OF: R-08404-60887 There are three arguments to ** SQLITE_CONFIG_SCRATCH: A pointer an 8-byte aligned memory buffer from ** which the scratch allocations will be drawn, the size of each scratch ** allocation (sz), and the maximum number of scratch allocations (N). */ sqlite3GlobalConfig.pScratch = va_arg(ap, void*); sqlite3GlobalConfig.szScratch = va_arg(ap, int); sqlite3GlobalConfig.nScratch = va_arg(ap, int); break; } case SQLITE_CONFIG_PAGECACHE: { /* EVIDENCE-OF: R-31408-40510 There are three arguments to ** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory, the size ** of each page buffer (sz), and the number of pages (N). */ sqlite3GlobalConfig.pPage = va_arg(ap, void*); sqlite3GlobalConfig.szPage = va_arg(ap, int); sqlite3GlobalConfig.nPage = va_arg(ap, int); break; } case SQLITE_CONFIG_PCACHE_HDRSZ: { /* EVIDENCE-OF: R-39100-27317 The SQLITE_CONFIG_PCACHE_HDRSZ option takes ** a single parameter which is a pointer to an integer and writes into ** that integer the number of extra bytes per page required for each page ** in SQLITE_CONFIG_PAGECACHE. */ *va_arg(ap, int*) = sqlite3HeaderSizeBtree() + sqlite3HeaderSizePcache() + sqlite3HeaderSizePcache1(); break; } case SQLITE_CONFIG_PCACHE: { /* no-op */ break; } case SQLITE_CONFIG_GETPCACHE: { /* now an error */ rc = SQLITE_ERROR; break; } case SQLITE_CONFIG_PCACHE2: { /* EVIDENCE-OF: R-63325-48378 The SQLITE_CONFIG_PCACHE2 option takes a ** single argument which is a pointer to an sqlite3_pcache_methods2 ** object. This object specifies the interface to a custom page cache ** implementation. */ sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*); break; } case SQLITE_CONFIG_GETPCACHE2: { /* EVIDENCE-OF: R-22035-46182 The SQLITE_CONFIG_GETPCACHE2 option takes a ** single argument which is a pointer to an sqlite3_pcache_methods2 ** object. SQLite copies of the current page cache implementation into ** that object. */ if( sqlite3GlobalConfig.pcache2.xInit==0 ){ sqlite3PCacheSetDefault(); } *va_arg(ap, sqlite3_pcache_methods2*) = sqlite3GlobalConfig.pcache2; break; } /* EVIDENCE-OF: R-06626-12911 The SQLITE_CONFIG_HEAP option is only ** available if SQLite is compiled with either SQLITE_ENABLE_MEMSYS3 or ** SQLITE_ENABLE_MEMSYS5 and returns SQLITE_ERROR if invoked otherwise. */ #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) case SQLITE_CONFIG_HEAP: { /* EVIDENCE-OF: R-19854-42126 There are three arguments to ** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the ** number of bytes in the memory buffer, and the minimum allocation size. */ sqlite3GlobalConfig.pHeap = va_arg(ap, void*); sqlite3GlobalConfig.nHeap = va_arg(ap, int); sqlite3GlobalConfig.mnReq = va_arg(ap, int); if( sqlite3GlobalConfig.mnReq<1 ){ sqlite3GlobalConfig.mnReq = 1; }else if( sqlite3GlobalConfig.mnReq>(1<<12) ){ /* cap min request size at 2^12 */ sqlite3GlobalConfig.mnReq = (1<<12); } if( sqlite3GlobalConfig.pHeap==0 ){ /* EVIDENCE-OF: R-49920-60189 If the first pointer (the memory pointer) ** is NULL, then SQLite reverts to using its default memory allocator ** (the system malloc() implementation), undoing any prior invocation of ** SQLITE_CONFIG_MALLOC. ** ** Setting sqlite3GlobalConfig.m to all zeros will cause malloc to ** revert to its default implementation when sqlite3_initialize() is run */ memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m)); }else{ /* EVIDENCE-OF: R-61006-08918 If the memory pointer is not NULL then the ** alternative memory allocator is engaged to handle all of SQLites ** memory allocation needs. */ #ifdef SQLITE_ENABLE_MEMSYS3 sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3(); #endif #ifdef SQLITE_ENABLE_MEMSYS5 sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5(); #endif } |
︙ | ︙ | |||
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 | /* EVIDENCE-OF: R-55548-33817 The compile-time setting for URI filenames ** can be changed at start-time using the ** sqlite3_config(SQLITE_CONFIG_URI,1) or ** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls. */ case SQLITE_CONFIG_URI: { sqlite3GlobalConfig.bOpenUri = va_arg(ap, int); break; } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { sqlite3GlobalConfig.bUseCis = va_arg(ap, int); break; } #ifdef SQLITE_ENABLE_SQLLOG case SQLITE_CONFIG_SQLLOG: { typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int); sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t); sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *); break; } #endif case SQLITE_CONFIG_MMAP_SIZE: { sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64); sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64); | > > > > > > > > > > > > > > > > > > > > | < < < > | > > > | 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 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | /* EVIDENCE-OF: R-55548-33817 The compile-time setting for URI filenames ** can be changed at start-time using the ** sqlite3_config(SQLITE_CONFIG_URI,1) or ** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls. */ case SQLITE_CONFIG_URI: { /* EVIDENCE-OF: R-25451-61125 The SQLITE_CONFIG_URI option takes a single ** argument of type int. If non-zero, then URI handling is globally ** enabled. If the parameter is zero, then URI handling is globally ** disabled. */ sqlite3GlobalConfig.bOpenUri = va_arg(ap, int); break; } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { /* EVIDENCE-OF: R-36592-02772 The SQLITE_CONFIG_COVERING_INDEX_SCAN ** option takes a single integer argument which is interpreted as a ** boolean in order to enable or disable the use of covering indices for ** full table scans in the query optimizer. */ sqlite3GlobalConfig.bUseCis = va_arg(ap, int); break; } #ifdef SQLITE_ENABLE_SQLLOG case SQLITE_CONFIG_SQLLOG: { typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int); sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t); sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *); break; } #endif case SQLITE_CONFIG_MMAP_SIZE: { /* EVIDENCE-OF: R-58063-38258 SQLITE_CONFIG_MMAP_SIZE takes two 64-bit ** integer (sqlite3_int64) values that are the default mmap size limit ** (the default setting for PRAGMA mmap_size) and the maximum allowed ** mmap size limit. */ sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64); sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64); /* EVIDENCE-OF: R-53367-43190 If either argument to this option is ** negative, then that argument is changed to its compile-time default. ** ** EVIDENCE-OF: R-34993-45031 The maximum allowed mmap size will be ** silently truncated if necessary so that it does not exceed the ** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE ** compile-time option. */ if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ) mxMmap = SQLITE_MAX_MMAP_SIZE; if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE; if( szMmap>mxMmap) szMmap = mxMmap; sqlite3GlobalConfig.mxMmap = mxMmap; sqlite3GlobalConfig.szMmap = szMmap; break; } #if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC) /* IMP: R-04780-55815 */ case SQLITE_CONFIG_WIN32_HEAPSIZE: { /* EVIDENCE-OF: R-34926-03360 SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit ** unsigned integer value that specifies the maximum size of the created ** heap. */ sqlite3GlobalConfig.nHeap = va_arg(ap, int); break; } #endif default: { rc = SQLITE_ERROR; |
︙ | ︙ | |||
1047 1048 1049 1050 1051 1052 1053 | #endif sqlite3_free(db); } /* ** Rollback all database files. If tripCode is not SQLITE_OK, then | | | > > > | | 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 | #endif sqlite3_free(db); } /* ** Rollback all database files. If tripCode is not SQLITE_OK, then ** any write cursors are invalidated ("tripped" - as in "tripping a circuit ** breaker") and made to return tripCode if there are any further ** attempts to use that cursor. Read cursors remain open and valid ** but are "saved" in case the table pages are moved around. */ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ int i; int inTrans = 0; int schemaChange; assert( sqlite3_mutex_held(db->mutex) ); sqlite3BeginBenignMalloc(); /* Obtain all b-tree mutexes before making any calls to BtreeRollback(). ** This is important in case the transaction being rolled back has ** modified the database schema. If the b-tree mutexes are not taken ** here, then another shared-cache connection might sneak in between ** the database rollback and schema reset, which can cause false ** corruption reports in some cases. */ sqlite3BtreeEnterAll(db); schemaChange = (db->flags & SQLITE_InternChanges)!=0 && db->init.busy==0; for(i=0; i<db->nDb; i++){ Btree *p = db->aDb[i].pBt; if( p ){ if( sqlite3BtreeIsInTrans(p) ){ inTrans = 1; } sqlite3BtreeRollback(p, tripCode, !schemaChange); } } sqlite3VtabRollback(db); sqlite3EndBenignMalloc(); if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){ sqlite3ExpirePreparedStatements(db); |
︙ | ︙ | |||
2374 2375 2376 2377 2378 2379 2380 | const char *zVfs = zDefaultVfs; char *zFile; char c; int nUri = sqlite3Strlen30(zUri); assert( *pzErrMsg==0 ); | > | | 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 | const char *zVfs = zDefaultVfs; char *zFile; char c; int nUri = sqlite3Strlen30(zUri); assert( *pzErrMsg==0 ); if( ((flags & SQLITE_OPEN_URI) /* IMP: R-48725-32206 */ || sqlite3GlobalConfig.bOpenUri) /* IMP: R-51689-46548 */ && nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */ ){ char *zOpt; int eState; /* Parser state when parsing URI */ int iIn; /* Input character index */ int iOut = 0; /* Output character index */ int nByte = nUri+2; /* Bytes of space to allocate */ |
︙ | ︙ |
Changes to src/malloc.c.
︙ | ︙ | |||
373 374 375 376 377 378 379 | } sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); } assert( sqlite3_mutex_notheld(mem0.mutex) ); #if SQLITE_THREADSAFE==0 && !defined(NDEBUG) | > | < > | < > | | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 | } sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); } assert( sqlite3_mutex_notheld(mem0.mutex) ); #if SQLITE_THREADSAFE==0 && !defined(NDEBUG) /* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch ** buffers per thread. ** ** This can only be checked in single-threaded mode. */ assert( scratchAllocOut==0 ); if( p ) scratchAllocOut++; #endif return p; } void sqlite3ScratchFree(void *p){ if( p ){ |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
30 31 32 33 34 35 36 37 38 39 40 41 42 43 | ** 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 && !defined(SQLITE_WIN32_NO_ANSI) # define SQLITE_WIN32_HAS_ANSI #endif | > > > > > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | ** 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 #if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0 # error "Memory mapped files require support from the Windows NT kernel,\ compile with SQLITE_MAX_MMAP_SIZE=0." #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 && !defined(SQLITE_WIN32_NO_ANSI) # define SQLITE_WIN32_HAS_ANSI #endif |
︙ | ︙ | |||
159 160 161 162 163 164 165 | */ #ifndef winGetDirSep # define winGetDirSep() '\\' #endif /* ** Do we need to manually define the Win32 file mapping APIs for use with WAL | | | | > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | */ #ifndef winGetDirSep # define winGetDirSep() '\\' #endif /* ** Do we need to manually define the Win32 file mapping APIs for use with WAL ** mode or memory mapped files (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) || SQLITE_MAX_MMAP_SIZE>0) /* ** 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); |
︙ | ︙ | |||
190 191 192 193 194 195 196 | 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); | | | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | 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 */ /* ** Some Microsoft compilers lack this definition. */ #ifndef INVALID_FILE_ATTRIBUTES # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) #endif |
︙ | ︙ | |||
483 484 485 486 487 488 489 | { "CreateFileW", (SYSCALL)0, 0 }, #endif #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) #if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ | | | | 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 | { "CreateFileW", (SYSCALL)0, 0 }, #endif #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) #if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, #else { "CreateFileMappingA", (SYSCALL)0, 0 }, #endif #define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent) #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, #else { "CreateFileMappingW", (SYSCALL)0, 0 }, #endif #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent) |
︙ | ︙ | |||
833 834 835 836 837 838 839 | #endif #ifndef osLockFileEx #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[48].pCurrent) #endif | | > | 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | #endif #ifndef osLockFileEx #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[48].pCurrent) #endif #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \ (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, #else { "MapViewOfFile", (SYSCALL)0, 0 }, #endif #define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ SIZE_T))aSyscall[49].pCurrent) |
︙ | ︙ | |||
903 904 905 906 907 908 909 | #else { "UnlockFileEx", (SYSCALL)0, 0 }, #endif #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[58].pCurrent) | | | 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 | #else { "UnlockFileEx", (SYSCALL)0, 0 }, #endif #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[58].pCurrent) #if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 }, #else { "UnmapViewOfFile", (SYSCALL)0, 0 }, #endif #define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[59].pCurrent) |
︙ | ︙ | |||
966 967 968 969 970 971 972 | #else { "GetFileInformationByHandleEx", (SYSCALL)0, 0 }, #endif #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) | | | 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 | #else { "GetFileInformationByHandleEx", (SYSCALL)0, 0 }, #endif #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) #if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, #else { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, #endif #define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \ SIZE_T))aSyscall[67].pCurrent) |
︙ | ︙ | |||
1030 1031 1032 1033 1034 1035 1036 | #define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent) { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) | | | 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 | #define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent) { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) #if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, #else { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, #endif #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \ LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent) |
︙ | ︙ |
Changes to src/pcache.c.
︙ | ︙ | |||
646 647 648 649 650 651 652 653 654 655 656 657 658 659 | /* ** Free up as much memory as possible from the page cache. */ void sqlite3PcacheShrink(PCache *pCache){ assert( pCache->pCache!=0 ); sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache); } #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* ** For all dirty pages currently in the cache, invoke the specified ** callback. This is only used if the SQLITE_CHECK_PAGES macro is ** defined. */ | > > > > > > > | 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 | /* ** Free up as much memory as possible from the page cache. */ void sqlite3PcacheShrink(PCache *pCache){ assert( pCache->pCache!=0 ); sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache); } /* ** Return the size of the header added by this middleware layer ** in the page-cache hierarchy. */ int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); } #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* ** For all dirty pages currently in the cache, invoke the specified ** callback. This is only used if the SQLITE_CHECK_PAGES macro is ** defined. */ |
︙ | ︙ |
Changes to src/pcache.h.
︙ | ︙ | |||
156 157 158 159 160 161 162 163 | #ifdef SQLITE_TEST void sqlite3PcacheStats(int*,int*,int*,int*); #endif void sqlite3PCacheSetDefault(void); #endif /* _PCACHE_H_ */ | > > > > | 156 157 158 159 160 161 162 163 164 165 166 167 | #ifdef SQLITE_TEST void sqlite3PcacheStats(int*,int*,int*,int*); #endif void sqlite3PCacheSetDefault(void); /* Return the header size */ int sqlite3HeaderSizePcache(void); int sqlite3HeaderSizePcache1(void); #endif /* _PCACHE_H_ */ |
Changes to src/pcache1.c.
︙ | ︙ | |||
977 978 979 980 981 982 983 984 985 986 987 988 989 990 | pcache1Truncate, /* xTruncate */ pcache1Destroy, /* xDestroy */ pcache1Shrink /* xShrink */ }; sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods); } #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* ** This function is called to free superfluous dynamically allocated memory ** held by the pager system. Memory in use by any SQLite pager allocated ** by the current thread may be sqlite3_free()ed. ** ** nReq is the number of bytes of memory required. Once this much has | > > > > > | 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 | pcache1Truncate, /* xTruncate */ pcache1Destroy, /* xDestroy */ pcache1Shrink /* xShrink */ }; sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods); } /* ** Return the size of the header on each page of this PCACHE implementation. */ int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); } #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* ** This function is called to free superfluous dynamically allocated memory ** held by the pager system. Memory in use by any SQLite pager allocated ** by the current thread may be sqlite3_free()ed. ** ** nReq is the number of bytes of memory required. Once this much has |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 | N = p->nAlloc - p->nChar - 1; setStrAccumError(p, STRACCUM_TOOBIG); return N; }else{ char *zOld = (p->zText==p->zBase ? 0 : p->zText); i64 szNew = p->nChar; szNew += N + 1; if( szNew > p->mxAlloc ){ sqlite3StrAccumReset(p); setStrAccumError(p, STRACCUM_TOOBIG); return 0; }else{ p->nAlloc = (int)szNew; } if( p->useMalloc==1 ){ zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); }else{ zNew = sqlite3_realloc(zOld, p->nAlloc); } if( zNew ){ assert( p->zText!=0 || p->nChar==0 ); if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); p->zText = zNew; }else{ sqlite3StrAccumReset(p); setStrAccumError(p, STRACCUM_NOMEM); return 0; } } return N; | > > > > > > | 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 | N = p->nAlloc - p->nChar - 1; setStrAccumError(p, STRACCUM_TOOBIG); return N; }else{ char *zOld = (p->zText==p->zBase ? 0 : p->zText); i64 szNew = p->nChar; szNew += N + 1; if( szNew+p->nChar<=p->mxAlloc ){ /* Force exponential buffer size growth as long as it does not overflow, ** to avoid having to call this routine too often */ szNew += p->nChar; } if( szNew > p->mxAlloc ){ sqlite3StrAccumReset(p); setStrAccumError(p, STRACCUM_TOOBIG); return 0; }else{ p->nAlloc = (int)szNew; } if( p->useMalloc==1 ){ zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); }else{ zNew = sqlite3_realloc(zOld, p->nAlloc); } if( zNew ){ assert( p->zText!=0 || p->nChar==0 ); if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); p->zText = zNew; p->nAlloc = sqlite3DbMallocSize(p->db, zNew); }else{ sqlite3StrAccumReset(p); setStrAccumError(p, STRACCUM_NOMEM); return 0; } } return N; |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
168 169 170 171 172 173 174 | #include <windows.h> /* Saved resource information for the beginning of an operation */ static HANDLE hProcess; static FILETIME ftKernelBegin; static FILETIME ftUserBegin; static sqlite3_int64 ftWallBegin; | | > | | | > | | > | | 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 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 | #include <windows.h> /* Saved resource information for the beginning of an operation */ static HANDLE hProcess; static FILETIME ftKernelBegin; static FILETIME ftUserBegin; static sqlite3_int64 ftWallBegin; typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME); static GETPROCTIMES getProcessTimesAddr = NULL; /* ** Check to see if we have timer support. Return 1 if necessary ** support found (or found previously). */ static int hasTimer(void){ if( getProcessTimesAddr ){ return 1; } else { /* GetProcessTimes() isn't supported in WIN95 and some other Windows ** versions. See if the version we are running on has it, and if it ** does, save off a pointer to it and the current process handle. */ hProcess = GetCurrentProcess(); if( hProcess ){ HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); if( NULL != hinstLib ){ getProcessTimesAddr = (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); if( NULL != getProcessTimesAddr ){ return 1; } FreeLibrary(hinstLib); } } } return 0; } /* ** Begin timing an operation */ static void beginTimer(void){ if( enableTimer && getProcessTimesAddr ){ FILETIME ftCreation, ftExit; getProcessTimesAddr(hProcess,&ftCreation,&ftExit, &ftKernelBegin,&ftUserBegin); ftWallBegin = timeOfDay(); } } /* Return the difference of two FILETIME structs in seconds */ static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ sqlite_int64 i64Start = *((sqlite_int64 *) pStart); sqlite_int64 i64End = *((sqlite_int64 *) pEnd); return (double) ((i64End - i64Start) / 10000000.0); } /* ** Print the timing results. */ static void endTimer(void){ if( enableTimer && getProcessTimesAddr){ FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; sqlite3_int64 ftWallEnd = timeOfDay(); getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); printf("Run Time: real %.3f user %f sys %f\n", (ftWallEnd - ftWallBegin)*0.001, timeDiff(&ftUserBegin, &ftUserEnd), timeDiff(&ftKernelBegin, &ftKernelEnd)); } } |
︙ | ︙ | |||
453 454 455 456 457 458 459 460 461 462 463 464 465 466 | */ typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ int statsOn; /* True to display memory stats before each finalize */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int writableSchema; /* True if PRAGMA writable_schema=ON */ | > | 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | */ typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ int statsOn; /* True to display memory stats before each finalize */ int scanstatsOn; /* True to display scan stats before each finalize */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int writableSchema; /* True if PRAGMA writable_schema=ON */ |
︙ | ︙ | |||
721 722 723 724 725 726 727 | } #endif /* ** This is the callback routine that the shell ** invokes for each row of a query result. */ | | > > > > > > | 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 | } #endif /* ** This is the callback routine that the shell ** invokes for each row of a query result. */ static int shell_callback( void *pArg, int nArg, /* Number of result columns */ char **azArg, /* Text of each result column */ char **azCol, /* Column names */ int *aiType /* Column types */ ){ int i; ShellState *p = (ShellState*)pArg; switch( p->mode ){ case MODE_Line: { int w = 5; if( azArg==0 ) break; |
︙ | ︙ | |||
1100 1101 1102 1103 1104 1105 1106 | int iCur; int iHiwtr; if( pArg && pArg->out ){ iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); | > | > | > > | > > | > | > > | > | > | > | > | > | > | > | > | > | > | > | | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 | int iCur; int iHiwtr; if( pArg && pArg->out ){ iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Memory Used: %d (max %d) bytes\n", iCur, iHiwtr); iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", iCur, iHiwtr); if( pArg->shellFlgs & SHFLG_Pagecache ){ iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr); } iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); if( pArg->shellFlgs & SHFLG_Scratch ){ iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr); } iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Largest Allocation: %d bytes\n", iHiwtr); iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n", iHiwtr); iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n", iHiwtr); #ifdef YYTRACKMAXSTACKDEPTH iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", iCur, iHiwtr); #endif } if( pArg && pArg->out && db ){ if( pArg->shellFlgs & SHFLG_Lookaside ){ iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr); sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr); sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr); sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr); } iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Pager Heap Usage: %d bytes\n",iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); fprintf(pArg->out, "Page cache hits: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); fprintf(pArg->out, "Page cache misses: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); fprintf(pArg->out, "Page cache writes: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Schema Heap Usage: %d bytes\n",iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",iCur); } if( pArg && pArg->out && db && pArg->pStmt ){ iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset); fprintf(pArg->out, "Fullscan Steps: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); fprintf(pArg->out, "Sort Operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur); } return 0; } /* ** Display scan stats. */ static void display_scanstats( sqlite3 *db, /* Database to query */ ShellState *pArg /* Pointer to ShellState */ ){ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS int i, k, n, mx; fprintf(pArg->out, "-------- scanstats --------\n"); mx = 0; for(k=0; k<=mx; k++){ double rEstLoop = 1.0; for(i=n=0; 1; i++){ sqlite3_stmt *p = pArg->pStmt; sqlite3_int64 nLoop, nVisit; double rEst; int iSid; const char *zExplain; if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){ break; } sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid); if( iSid>mx ) mx = iSid; if( iSid!=k ) continue; if( n==0 ){ rEstLoop = (double)nLoop; if( k>0 ) fprintf(pArg->out, "-------- subquery %d -------\n", k); } n++; sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst); sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); fprintf(pArg->out, "Loop %2d: %s\n", n, zExplain); rEstLoop *= rEst; fprintf(pArg->out, " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n", nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst ); } } fprintf(pArg->out, "---------------------------\n"); #endif } /* ** Parameter azArray points to a zero-terminated array of strings. zStr ** points to a single nul-terminated string. Return non-zero if zStr ** is equal, according to strcmp(), to any of the strings in the array. ** Otherwise, return zero. */ |
︙ | ︙ | |||
1222 1223 1224 1225 1226 1227 1228 | const char *z; /* Used to check if this is an EXPLAIN */ int *abYield = 0; /* True if op is an OP_Yield */ int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ int iOp; /* Index of operation in p->aiIndent[] */ const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", "NextIfOpen", "PrevIfOpen", 0 }; | | > | 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 | const char *z; /* Used to check if this is an EXPLAIN */ int *abYield = 0; /* True if op is an OP_Yield */ int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ int iOp; /* Index of operation in p->aiIndent[] */ const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", "NextIfOpen", "PrevIfOpen", 0 }; const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", "Rewind", 0 }; const char *azGoto[] = { "Goto", 0 }; /* Try to figure out if this is really an EXPLAIN statement. If this ** cannot be verified, return early. */ zSql = sqlite3_sql(pSql); if( zSql==0 ) return; for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); |
︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 | const char *zStmtSql = sqlite3_sql(pStmt); fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); } /* Show the EXPLAIN QUERY PLAN if .eqp is on */ if( pArg && pArg->autoEQP ){ sqlite3_stmt *pExplain; | | > | 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 | const char *zStmtSql = sqlite3_sql(pStmt); fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); } /* Show the EXPLAIN QUERY PLAN if .eqp is on */ if( pArg && pArg->autoEQP ){ sqlite3_stmt *pExplain; char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", sqlite3_sql(pStmt)); rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); if( rc==SQLITE_OK ){ while( sqlite3_step(pExplain)==SQLITE_ROW ){ fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0)); fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1)); fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2)); fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3)); |
︙ | ︙ | |||
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 | explain_data_delete(pArg); /* print usage stats if stats on */ if( pArg && pArg->statsOn ){ display_stats(db, pArg, 0); } /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ rc2 = sqlite3_finalize(pStmt); if( rc!=SQLITE_NOMEM ) rc = rc2; if( rc==SQLITE_OK ){ | > > > > > | 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 | explain_data_delete(pArg); /* print usage stats if stats on */ if( pArg && pArg->statsOn ){ display_stats(db, pArg, 0); } /* print loop-counters if required */ if( pArg && pArg->scanstatsOn ){ display_scanstats(db, pArg); } /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ rc2 = sqlite3_finalize(pStmt); if( rc!=SQLITE_NOMEM ) rc = rc2; if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 | ".output ?FILENAME? Send output to FILENAME or stdout\n" ".print STRING... Print literal STRING\n" ".prompt MAIN CONTINUE Replace the standard prompts\n" ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" ".save FILE Write in-memory database into FILE\n" ".schema ?TABLE? Show the CREATE statements\n" " If TABLE specified, only show tables matching\n" " LIKE pattern TABLE.\n" ".separator STRING ?NL? Change separator used by output mode and .import\n" " NL is the end-of-line mark for CSV\n" ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" ".show Show the current values for various settings\n" | > | 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 | ".output ?FILENAME? Send output to FILENAME or stdout\n" ".print STRING... Print literal STRING\n" ".prompt MAIN CONTINUE Replace the standard prompts\n" ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" ".save FILE Write in-memory database into FILE\n" ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" ".schema ?TABLE? Show the CREATE statements\n" " If TABLE specified, only show tables matching\n" " LIKE pattern TABLE.\n" ".separator STRING ?NL? Change separator used by output mode and .import\n" " NL is the end-of-line mark for CSV\n" ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" ".show Show the current values for various settings\n" |
︙ | ︙ | |||
3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 | }else{ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); rc = 1; } sqlite3_close(pSrc); }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ ShellState data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_Semi; | > > > > > > > > > > > > > | 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 | }else{ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); rc = 1; } sqlite3_close(pSrc); }else if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){ if( nArg==2 ){ p->scanstatsOn = booleanValue(azArg[1]); #ifndef SQLITE_ENABLE_STMT_SCANSTATUS fprintf(stderr, "Warning: .scanstats not available in this build.\n"); #endif }else{ fprintf(stderr, "Usage: .scanstats on|off\n"); rc = 1; } }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ ShellState data; char *zErrMsg = 0; open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_Semi; |
︙ | ︙ | |||
3267 3268 3269 3270 3271 3272 3273 | } nPrintCol = 80/(maxlen+2); if( nPrintCol<1 ) nPrintCol = 1; nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; for(i=0; i<nPrintRow; i++){ for(j=i; j<nRow; j+=nPrintRow){ char *zSp = j<nPrintRow ? "" : " "; | | | 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 | } nPrintCol = 80/(maxlen+2); if( nPrintCol<1 ) nPrintCol = 1; nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; for(i=0; i<nPrintRow; i++){ for(j=i; j<nRow; j+=nPrintRow){ char *zSp = j<nPrintRow ? "" : " "; fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:""); } fprintf(p->out, "\n"); } } for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); sqlite3_free(azResult); }else |
︙ | ︙ | |||
3737 3738 3739 3740 3741 3742 3743 | ** Return a pathname which is the user's home directory. A ** 0 return indicates an error of some kind. */ static char *find_home_dir(void){ static char *home_dir = NULL; if( home_dir ) return home_dir; | | > | 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 | ** Return a pathname which is the user's home directory. A ** 0 return indicates an error of some kind. */ static char *find_home_dir(void){ static char *home_dir = NULL; if( home_dir ) return home_dir; #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \ && !defined(__RTP__) && !defined(_WRS_KERNEL) { struct passwd *pwent; uid_t uid = getuid(); if( (pwent=getpwuid(uid)) != NULL) { home_dir = pwent->pw_dir; } } |
︙ | ︙ | |||
4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 | data.showHeader = 0; }else if( strcmp(z,"-echo")==0 ){ data.echoOn = 1; }else if( strcmp(z,"-eqp")==0 ){ data.autoEQP = 1; }else if( strcmp(z,"-stats")==0 ){ data.statsOn = 1; }else if( strcmp(z,"-bail")==0 ){ bail_on_error = 1; }else if( strcmp(z,"-version")==0 ){ printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); return 0; }else if( strcmp(z,"-interactive")==0 ){ stdin_is_interactive = 1; | > > | 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 | data.showHeader = 0; }else if( strcmp(z,"-echo")==0 ){ data.echoOn = 1; }else if( strcmp(z,"-eqp")==0 ){ data.autoEQP = 1; }else if( strcmp(z,"-stats")==0 ){ data.statsOn = 1; }else if( strcmp(z,"-scanstats")==0 ){ data.scanstatsOn = 1; }else if( strcmp(z,"-bail")==0 ){ bail_on_error = 1; }else if( strcmp(z,"-version")==0 ){ printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); return 0; }else if( strcmp(z,"-interactive")==0 ){ stdin_is_interactive = 1; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
48 49 50 51 52 53 54 | #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif /* ** These no-op macros are used in front of interfaces to mark those ** interfaces as either deprecated or experimental. New applications | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif /* ** These no-op macros are used in front of interfaces to mark those ** interfaces as either deprecated or experimental. New applications ** should not use deprecated interfaces - they are supported for backwards ** compatibility only. Application writers should be aware that ** experimental interfaces are subject to change in point releases. ** ** These macros used to resolve to various kinds of compiler magic that ** would generate warning messages when they were used. But that ** compiler magic ended up generating such a flurry of bug reports ** that we have taken it all out and gone back to using simple |
︙ | ︙ | |||
1500 1501 1502 1503 1504 1505 1506 | ** ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** it is not possible to set the Serialized [threading mode] and ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the ** SQLITE_CONFIG_SERIALIZED configuration option.</dd> ** ** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt> | | | > | | > | | | | > | | < | < < | < < | > > > > > > | | > | > | | | > > | | > | > | < < < | | | > > > > | | < | | | | | | | | | | | | | | | | | | 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 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 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 | ** ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** it is not possible to set the Serialized [threading mode] and ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the ** SQLITE_CONFIG_SERIALIZED configuration option.</dd> ** ** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt> ** <dd> ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is ** a pointer to an instance of the [sqlite3_mem_methods] structure. ** The argument specifies ** alternative low-level memory allocation routines to be used in place of ** the memory allocation routines built into SQLite.)^ ^SQLite makes ** its own private copy of the content of the [sqlite3_mem_methods] structure ** before the [sqlite3_config()] call returns.</dd> ** ** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt> ** <dd> ^(The SQLITE_CONFIG_GETMALLOC option takes a single argument which ** is a pointer to an instance of the [sqlite3_mem_methods] structure. ** The [sqlite3_mem_methods] ** structure is filled with the currently defined memory allocation routines.)^ ** This option can be used to overload the default memory allocation ** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example. </dd> ** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of ** memory allocation statistics. ^(When memory allocation statistics are disabled, the ** following SQLite interfaces become non-operational: ** <ul> ** <li> [sqlite3_memory_used()] ** <li> [sqlite3_memory_highwater()] ** <li> [sqlite3_soft_heap_limit64()] ** <li> [sqlite3_status()] ** </ul>)^ ** ^Memory allocation statistics are enabled by default unless SQLite is ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory ** allocation statistics are disabled by default. ** </dd> ** ** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt> ** <dd> ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer ** that SQLite can use for scratch memory. ^(There are three arguments ** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte ** aligned memory buffer from which the scratch allocations will be ** drawn, the size of each scratch allocation (sz), ** and the maximum number of scratch allocations (N).)^ ** The first argument must be a pointer to an 8-byte aligned buffer ** of at least sz*N bytes of memory. ** ^SQLite will not use more than one scratch buffers per thread. ** ^SQLite will never request a scratch buffer that is more than 6 ** times the database page size. ** ^If SQLite needs needs additional ** scratch memory beyond what is provided by this configuration option, then ** [sqlite3_malloc()] will be used to obtain the memory needed.<p> ** ^When the application provides any amount of scratch memory using ** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large ** [sqlite3_malloc|heap allocations]. ** This can help [Robson proof|prevent memory allocation failures] due to heap ** fragmentation in low-memory embedded systems. ** </dd> ** ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt> ** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer ** that SQLite can use for the database page cache with the default page ** cache implementation. ** This configuration should not be used if an application-define page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] ** configuration option. ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned ** memory, the size of each page buffer (sz), and the number of pages (N). ** The sz argument should be the size of the largest database page ** (a power of two between 512 and 32768) plus some extra bytes for each ** page header. ^The number of extra bytes needed by the page header ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option ** to [sqlite3_config()]. ** ^It is harmless, apart from the wasted memory, ** for the sz parameter to be larger than necessary. The first ** argument should pointer to an 8-byte aligned block of memory that ** is at least sz*N bytes of memory, otherwise subsequent behavior is ** undefined. ** ^SQLite will use the memory provided by the first argument to satisfy its ** memory needs for the first N pages that it adds to cache. ^If additional ** page cache memory is needed beyond what is provided by this option, then ** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd> ** ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer ** that SQLite will use for all of its dynamic memory allocation needs ** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns ** [SQLITE_ERROR] if invoked otherwise. ** ^There are three arguments to SQLITE_CONFIG_HEAP: ** An 8-byte aligned pointer to the memory, ** the number of bytes in the memory buffer, and the minimum allocation size. ** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts ** to using its default memory allocator (the system malloc() implementation), ** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the ** memory pointer is not NULL then the alternative memory ** allocator is engaged to handle all of SQLites memory allocation needs. ** The first pointer (the memory pointer) must be aligned to an 8-byte ** boundary or subsequent behavior of SQLite will be undefined. ** The minimum allocation size is capped at 2**12. Reasonable values ** for the minimum allocation size are 2**5 through 2**8.</dd> ** ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a ** pointer to an instance of the [sqlite3_mutex_methods] structure. ** The argument specifies alternative low-level mutex routines to be used in place ** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the ** content of the [sqlite3_mutex_methods] structure before the call to ** [sqlite3_config()] returns. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** the entire mutexing subsystem is omitted from the build and hence calls to ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will ** return [SQLITE_ERROR].</dd> ** ** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt> ** <dd> ^(The SQLITE_CONFIG_GETMUTEX option takes a single argument which ** is a pointer to an instance of the [sqlite3_mutex_methods] structure. The ** [sqlite3_mutex_methods] ** structure is filled with the currently defined mutex routines.)^ ** This option can be used to overload the default mutex allocation ** routines with a wrapper used to track mutex usage for performance ** profiling or testing, for example. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** the entire mutexing subsystem is omitted from the build and hence calls to ** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will ** return [SQLITE_ERROR].</dd> ** ** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt> ** <dd> ^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine ** the default size of lookaside memory on each [database connection]. ** The first argument is the ** size of each lookaside buffer slot and the second is the number of ** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE ** sets the <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] ** option to [sqlite3_db_config()] can be used to change the lookaside ** configuration on individual connections.)^ </dd> ** ** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is ** a pointer to an [sqlite3_pcache_methods2] object. This object specifies ** the interface to a custom page cache implementation.)^ ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which ** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of the current ** page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite ** global [error log]. ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a ** function with a call signature of void(*)(void*,int,const char*), |
︙ | ︙ | |||
1656 1657 1658 1659 1660 1661 1662 | ** log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI | | | | | | | > | | 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 | ** log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. ** If non-zero, then URI handling is globally enabled. If the parameter is zero, ** then URI handling is globally disabled.)^ ^If URI handling is globally enabled, ** all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. ^If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. ^(By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined.)^ ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN ** <dd>^The SQLITE_CONFIG_COVERING_INDEX_SCAN option takes a single integer ** argument which is interpreted as a boolean in order to enable or disable ** the use of covering indices for full table scans in the query optimizer. ** ^The default setting is determined ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. |
︙ | ︙ | |||
1711 1712 1713 1714 1715 1716 1717 | ** <dt>SQLITE_CONFIG_MMAP_SIZE ** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values ** that are the default mmap size limit (the default setting for ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. ** ^The default setting can be overridden by each database connection using ** either the [PRAGMA mmap_size] command, or by using the ** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size | | | | | | > > > > > > > > > | 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 | ** <dt>SQLITE_CONFIG_MMAP_SIZE ** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values ** that are the default mmap size limit (the default setting for ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. ** ^The default setting can be overridden by each database connection using ** either the [PRAGMA mmap_size] command, or by using the ** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size ** will be silently truncated if necessary so that it does not exceed the ** compile-time maximum mmap size set by the ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ ** ^If either argument to this option is negative, then that argument is ** changed to its compile-time default. ** ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro defined. ** ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value ** that specifies the maximum size of the created heap. ** </dl> ** ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which ** is a pointer to an integer and writes into that integer the number of extra ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. The amount of ** extra space required can change depending on the compiler, ** target platform, and SQLite version. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ |
︙ | ︙ | |||
1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 | #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** | > | 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 | #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** |
︙ | ︙ | |||
5641 5642 5643 5644 5645 5646 5647 5648 | ** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located ** in row iRow, column zColumn, table zTable in database zDb; ** in other words, the same BLOB that would be selected by: ** ** <pre> ** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow; ** </pre>)^ ** | < < < < < < | | | | | > > > > | | > > > > > | > > > > > > > > > > > > > > > | | < < < > < < < | | < | 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 | ** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located ** in row iRow, column zColumn, table zTable in database zDb; ** in other words, the same BLOB that would be selected by: ** ** <pre> ** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow; ** </pre>)^ ** ** ^(Parameter zDb is not the filename that contains the database, but ** rather the symbolic name of the database. For attached databases, this is ** the name that appears after the AS keyword in the [ATTACH] statement. ** For the main database file, the database name is "main". For TEMP ** tables, the database name is "temp".)^ ** ** ^If the flags parameter is non-zero, then the BLOB is opened for read ** and write access. ^If the flags parameter is zero, the BLOB is opened for ** read-only access. ** ** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored ** in *ppBlob. Otherwise an [error code] is returned and, unless the error ** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided ** the API is not misused, it is always safe to call [sqlite3_blob_close()] ** on *ppBlob after this function it returns. ** ** This function fails with SQLITE_ERROR if any of the following are true: ** <ul> ** <li> ^(Database zDb does not exist)^, ** <li> ^(Table zTable does not exist within database zDb)^, ** <li> ^(Table zTable is a WITHOUT ROWID table)^, ** <li> ^(Column zColumn does not exist)^, ** <li> ^(Row iRow is not present in the table)^, ** <li> ^(The specified column of row iRow contains a value that is not ** a TEXT or BLOB value)^, ** <li> ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE ** constraint and the blob is being opened for read/write access)^, ** <li> ^([foreign key constraints | Foreign key constraints] are enabled, ** column zColumn is part of a [child key] definition and the blob is ** being opened for read/write access)^. ** </ul> ** ** ^Unless it returns SQLITE_MISUSE, this function sets the ** [database connection] error code and message accessible via ** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. ** ** ** ^(If the row that a BLOB handle points to is modified by an ** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects ** then the BLOB handle is marked as "expired". ** This is true if any column of the row is changed, even a column ** other than the one the BLOB handle is open on.)^ ** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for ** an expired BLOB handle fail with a return code of [SQLITE_ABORT]. ** ^(Changes written into a BLOB prior to the BLOB expiring are not ** rolled back by the expiration of the BLOB. Such changes will eventually ** commit if the transaction continues to completion.)^ ** ** ^Use the [sqlite3_blob_bytes()] interface to determine the size of ** the opened blob. ^The size of a blob may not be changed by this ** interface. Use the [UPDATE] SQL command to change the size of a ** blob. ** ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces ** and the built-in [zeroblob] SQL function may be used to create a ** zero-filled blob to read or write using the incremental-blob interface. ** ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. */ int sqlite3_blob_open( sqlite3*, const char *zDb, |
︙ | ︙ | |||
5727 5728 5729 5730 5731 5732 5733 | ** ^This function sets the database handle error code and message. */ SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle ** | | > > > > | > | < < < | < < | < < < < | | > > | 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 | ** ^This function sets the database handle error code and message. */ SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle ** ** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed ** unconditionally. Even if this routine returns an error code, the ** handle is still closed.)^ ** ** ^If the blob handle being closed was opened for read-write access, and if ** the database is in auto-commit mode and there are no other open read-write ** blob handles or active write statements, the current transaction is ** committed. ^If an error occurs while committing the transaction, an error ** code is returned and the transaction rolled back. ** ** Calling this function with an argument that is not a NULL pointer or an ** open blob handle results in undefined behaviour. ^Calling this routine ** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function ** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB ** ** ^Returns the size in bytes of the BLOB accessible via the |
︙ | ︙ | |||
5794 5795 5796 5797 5798 5799 5800 | ** See also: [sqlite3_blob_write()]. */ int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally ** | | | | > > > > > > | | < | | > < < < | 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 | ** See also: [sqlite3_blob_write()]. */ int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally ** ** ^(This function is used to write data into an open [BLOB handle] from a ** caller-supplied buffer. N bytes of data are copied from the buffer Z ** into the open BLOB, starting at offset iOffset.)^ ** ** ^(On success, sqlite3_blob_write() returns SQLITE_OK. ** Otherwise, an [error code] or an [extended error code] is returned.)^ ** ^Unless SQLITE_MISUSE is returned, this function sets the ** [database connection] error code and message accessible via ** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. ** ** ^If the [BLOB handle] passed as the first argument was not opened for ** writing (the flags parameter to [sqlite3_blob_open()] was zero), ** this function returns [SQLITE_READONLY]. ** ** This function may only modify the contents of the BLOB; it is ** not possible to increase the size of a BLOB using this API. ** ^If offset iOffset is less than N bytes from the end of the BLOB, ** [SQLITE_ERROR] is returned and no data is written. The size of the ** BLOB (and hence the maximum value of N+iOffset) can be determined ** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less ** than zero [SQLITE_ERROR] is returned and no data is written. ** ** ^An attempt to write to an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred ** before the [BLOB handle] expired are not rolled back by the ** expiration of the handle, though of course those changes might ** have been overwritten by the statement that expired the BLOB handle ** or by other independent statements. ** ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. ** ** See also: [sqlite3_blob_read()]. */ |
︙ | ︙ | |||
6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 | ** an [ATTACH] statement for an attached database. ** ^The S and M arguments passed to ** sqlite3_backup_init(D,N,S,M) identify the [database connection] ** and database name of the source database, respectively. ** ^The source and destination [database connections] (parameters S and D) ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** ** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is ** returned and an error code and error message are stored in the ** destination [database connection] D. ** ^The error code and message for the failed call to sqlite3_backup_init() ** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or ** [sqlite3_errmsg16()] functions. | > > > > | 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 | ** an [ATTACH] statement for an attached database. ** ^The S and M arguments passed to ** sqlite3_backup_init(D,N,S,M) identify the [database connection] ** and database name of the source database, respectively. ** ^The source and destination [database connections] (parameters S and D) ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** ** ^A call to sqlite3_backup_init() will fail, returning SQLITE_ERROR, if ** there is already a read or read-write transaction open on the ** destination database. ** ** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is ** returned and an error code and error message are stored in the ** destination [database connection] D. ** ^The error code and message for the failed call to sqlite3_backup_init() ** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or ** [sqlite3_errmsg16()] functions. |
︙ | ︙ | |||
7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 | */ #define SQLITE_ROLLBACK 1 /* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ #define SQLITE_FAIL 3 /* #define SQLITE_ABORT 4 // Also an error code */ #define SQLITE_REPLACE 5 /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 | */ #define SQLITE_ROLLBACK 1 /* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ #define SQLITE_FAIL 3 /* #define SQLITE_ABORT 4 // Also an error code */ #define SQLITE_REPLACE 5 /* ** CAPI3REF: Prepared Statement Scan Status Opcodes ** KEYWORDS: {scanstatus options} ** ** The following constants can be used for the T parameter to the ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a ** different metric for sqlite3_stmt_scanstatus() to return. ** ** <dl> ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the ** total number of times that the X-th loop has run.</dd> ** ** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt> ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the ** total number of rows examined by all iterations of the X-th loop.</dd> ** ** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt> ** <dd>^The "double" variable pointed to by the T parameter will be set to the ** query planner's estimate for the average number of rows output from each ** iteration of the X-th loop. If the query planner's estimates was accurate, ** then this value will approximate the quotient NVISIT/NLOOP and the ** product of this value for all prior loops with the same SELECTID will ** be the NLOOP value for the current loop. ** ** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt> ** <dd>^The "const char *" variable pointed to by the T parameter will be set to ** a zero-terminated UTF-8 string containing the name of the index or table used ** for the X-th loop. ** ** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt> ** <dd>^The "const char *" variable pointed to by the T parameter will be set to ** a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] description ** for the X-th loop. ** ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt> ** <dd>^The "int" variable pointed to by the T parameter will be set to the ** "select-id" for the X-th loop. The select-id identifies which query or ** subquery the loop is part of. The main query has a select-id of zero. ** The select-id is the same value as is output in the first column ** of an [EXPLAIN QUERY PLAN] query. ** </dl> */ #define SQLITE_SCANSTAT_NLOOP 0 #define SQLITE_SCANSTAT_NVISIT 1 #define SQLITE_SCANSTAT_EST 2 #define SQLITE_SCANSTAT_NAME 3 #define SQLITE_SCANSTAT_EXPLAIN 4 #define SQLITE_SCANSTAT_SELECTID 5 /* ** CAPI3REF: Prepared Statement Scan Status ** ** Return status data for a single loop within query pStmt. ** ** The "iScanStatusOp" parameter determines which status information to return. ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior of ** this interface is undefined. ** ^The requested measurement is written into a variable pointed to by ** the "pOut" parameter. ** Parameter "idx" identifies the specific loop to retrieve statistics for. ** Loops are numbered starting from zero. ^If idx is out of range - less than ** zero or greater than or equal to the total number of loops used to implement ** the statement - a non-zero value is returned and the variable that pOut ** points to is unchanged. ** ** ^Statistics might not be available for all loops in all statements. ^In cases ** where there exist loops with no available statistics, this function behaves ** as if the loop did not exist - it returns non-zero and leave the variable ** that pOut points to unchanged. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ void *pOut /* Result written here */ ); /* ** CAPI3REF: Zero Scan-Status Counters ** ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
189 190 191 192 193 194 195 | ** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. */ #ifndef SQLITE_POWERSAFE_OVERWRITE # define SQLITE_POWERSAFE_OVERWRITE 1 #endif /* | > | < | < | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | ** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. */ #ifndef SQLITE_POWERSAFE_OVERWRITE # define SQLITE_POWERSAFE_OVERWRITE 1 #endif /* ** EVIDENCE-OF: R-25715-37072 Memory allocation statistics are enabled by ** default unless SQLite is compiled with SQLITE_DEFAULT_MEMSTATUS=0 in ** which case memory allocation statistics are disabled by default. */ #if !defined(SQLITE_DEFAULT_MEMSTATUS) # define SQLITE_DEFAULT_MEMSTATUS 1 #endif /* ** Exactly one of the following macros must be defined in order to |
︙ | ︙ | |||
559 560 561 562 563 564 565 | /* ** Estimated quantities used for query planning are stored as 16-bit ** logarithms. For quantity X, the value stored is 10*log2(X). This ** gives a possible range of values of approximately 1.0e986 to 1e-986. ** But the allowed values are "grainy". Not every value is representable. ** For example, quantities 16 and 17 are both represented by a LogEst | | | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 | /* ** Estimated quantities used for query planning are stored as 16-bit ** logarithms. For quantity X, the value stored is 10*log2(X). This ** gives a possible range of values of approximately 1.0e986 to 1e-986. ** But the allowed values are "grainy". Not every value is representable. ** For example, quantities 16 and 17 are both represented by a LogEst ** of 40. However, since LogEst quantities are suppose to be estimates, ** not exact values, this imprecision is not a problem. ** ** "LogEst" is short for "Logarithmic Estimate". ** ** Examples: ** 1 -> 0 20 -> 43 10000 -> 132 ** 2 -> 10 25 -> 46 25000 -> 146 |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 | } pDb->bLegacyPrepare = bPrepare; Tcl_ResetResult(interp); return TCL_OK; } #endif /* ** Configure the interpreter passed as the first argument to have access ** to the commands and linked variables that make up: ** ** * the [sqlite3] extension itself, | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 | } pDb->bLegacyPrepare = bPrepare; Tcl_ResetResult(interp); return TCL_OK; } /* ** Tclcmd: db_last_stmt_ptr DB ** ** If the statement cache associated with database DB is not empty, ** return the text representation of the most recently used statement ** handle. */ static int db_last_stmt_ptr( ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); Tcl_CmdInfo cmdInfo; SqliteDb *pDb; sqlite3_stmt *pStmt = 0; char zBuf[100]; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0); return TCL_ERROR; } pDb = (SqliteDb*)cmdInfo.objClientData; if( pDb->stmtList ) pStmt = pDb->stmtList->pStmt; if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ){ return TCL_ERROR; } Tcl_SetResult(interp, zBuf, TCL_VOLATILE); return TCL_OK; } #endif /* ** Configure the interpreter passed as the first argument to have access ** to the commands and linked variables that make up: ** ** * the [sqlite3] extension itself, |
︙ | ︙ | |||
3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 | extern int Sqlitetest5_Init(Tcl_Interp*); extern int Sqlitetest6_Init(Tcl_Interp*); extern int Sqlitetest7_Init(Tcl_Interp*); extern int Sqlitetest8_Init(Tcl_Interp*); extern int Sqlitetest9_Init(Tcl_Interp*); extern int Sqlitetestasync_Init(Tcl_Interp*); extern int Sqlitetest_autoext_Init(Tcl_Interp*); extern int Sqlitetest_demovfs_Init(Tcl_Interp *); extern int Sqlitetest_func_Init(Tcl_Interp*); extern int Sqlitetest_hexio_Init(Tcl_Interp*); extern int Sqlitetest_init_Init(Tcl_Interp*); extern int Sqlitetest_malloc_Init(Tcl_Interp*); extern int Sqlitetest_mutex_Init(Tcl_Interp*); extern int Sqlitetestschema_Init(Tcl_Interp*); | > | 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 | extern int Sqlitetest5_Init(Tcl_Interp*); extern int Sqlitetest6_Init(Tcl_Interp*); extern int Sqlitetest7_Init(Tcl_Interp*); extern int Sqlitetest8_Init(Tcl_Interp*); extern int Sqlitetest9_Init(Tcl_Interp*); extern int Sqlitetestasync_Init(Tcl_Interp*); extern int Sqlitetest_autoext_Init(Tcl_Interp*); extern int Sqlitetest_blob_Init(Tcl_Interp*); extern int Sqlitetest_demovfs_Init(Tcl_Interp *); extern int Sqlitetest_func_Init(Tcl_Interp*); extern int Sqlitetest_hexio_Init(Tcl_Interp*); extern int Sqlitetest_init_Init(Tcl_Interp*); extern int Sqlitetest_malloc_Init(Tcl_Interp*); extern int Sqlitetest_mutex_Init(Tcl_Interp*); extern int Sqlitetestschema_Init(Tcl_Interp*); |
︙ | ︙ | |||
3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 | Sqlitetest5_Init(interp); Sqlitetest6_Init(interp); Sqlitetest7_Init(interp); Sqlitetest8_Init(interp); Sqlitetest9_Init(interp); Sqlitetestasync_Init(interp); Sqlitetest_autoext_Init(interp); Sqlitetest_demovfs_Init(interp); Sqlitetest_func_Init(interp); Sqlitetest_hexio_Init(interp); Sqlitetest_init_Init(interp); Sqlitetest_malloc_Init(interp); Sqlitetest_mutex_Init(interp); Sqlitetestschema_Init(interp); | > | 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 | Sqlitetest5_Init(interp); Sqlitetest6_Init(interp); Sqlitetest7_Init(interp); Sqlitetest8_Init(interp); Sqlitetest9_Init(interp); Sqlitetestasync_Init(interp); Sqlitetest_autoext_Init(interp); Sqlitetest_blob_Init(interp); Sqlitetest_demovfs_Init(interp); Sqlitetest_func_Init(interp); Sqlitetest_hexio_Init(interp); Sqlitetest_init_Init(interp); Sqlitetest_malloc_Init(interp); Sqlitetest_mutex_Init(interp); Sqlitetestschema_Init(interp); |
︙ | ︙ | |||
3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 | Tcl_CreateObjCommand( interp, "load_testfixture_extensions", init_all_cmd, 0, 0 ); Tcl_CreateObjCommand( interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0 ); #ifdef SQLITE_SSE Sqlitetestsse_Init(interp); #endif } #endif } | > > > | 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 | Tcl_CreateObjCommand( interp, "load_testfixture_extensions", init_all_cmd, 0, 0 ); Tcl_CreateObjCommand( interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0 ); Tcl_CreateObjCommand( interp, "db_last_stmt_ptr", db_last_stmt_ptr, 0, 0 ); #ifdef SQLITE_SSE Sqlitetestsse_Init(interp); #endif } #endif } |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
1647 1648 1649 1650 1651 1652 1653 | instanceData = Tcl_GetChannelInstanceData(channel); *ppBlob = *((sqlite3_blob **)instanceData); } return TCL_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 | instanceData = Tcl_GetChannelInstanceData(channel); *ppBlob = *((sqlite3_blob **)instanceData); } return TCL_OK; } static int test_blob_reopen( ClientData clientData, /* Not used */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ Tcl_WideInt iRowid; |
︙ | ︙ | |||
2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 | if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; } if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; iValue = sqlite3_stmt_status(pStmt, op, resetFlag); Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue)); return TCL_OK; } /* ** Usage: sqlite3_next_stmt DB STMT ** ** Return the next statment in sequence after STMT. */ static int test_next_stmt( | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 | if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; } if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; iValue = sqlite3_stmt_status(pStmt, op, resetFlag); Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue)); return TCL_OK; } #ifdef SQLITE_ENABLE_STMT_SCANSTATUS /* ** Usage: sqlite3_stmt_scanstatus STMT IDX */ static int test_stmt_scanstatus( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ sqlite3_stmt *pStmt; /* First argument */ int idx; /* Second argument */ const char *zName; const char *zExplain; sqlite3_int64 nLoop; sqlite3_int64 nVisit; double rEst; int res; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX"); return TCL_ERROR; } if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop); if( res==0 ){ Tcl_Obj *pRet = Tcl_NewObj(); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop)); sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit)); sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst)); sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1)); sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1)); Tcl_SetObjResult(interp, pRet); }else{ Tcl_ResetResult(interp); } return TCL_OK; } /* ** Usage: sqlite3_stmt_scanstatus_reset STMT */ static int test_stmt_scanstatus_reset( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ sqlite3_stmt *pStmt; /* First argument */ if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "STMT"); return TCL_ERROR; } if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; sqlite3_stmt_scanstatus_reset(pStmt); return TCL_OK; } #endif /* ** Usage: sqlite3_next_stmt DB STMT ** ** Return the next statment in sequence after STMT. */ static int test_next_stmt( |
︙ | ︙ | |||
6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 | void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*); static const struct { const char *zExtName; int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*); } aExtension[] = { { "amatch", sqlite3_amatch_init }, { "closure", sqlite3_closure_init }, { "fileio", sqlite3_fileio_init }, { "fuzzer", sqlite3_fuzzer_init }, { "ieee754", sqlite3_ieee_init }, { "nextchar", sqlite3_nextchar_init }, { "percentile", sqlite3_percentile_init }, { "regexp", sqlite3_regexp_init }, { "spellfix", sqlite3_spellfix_init }, | > > | 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 | void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*); static const struct { const char *zExtName; int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*); } aExtension[] = { { "amatch", sqlite3_amatch_init }, { "closure", sqlite3_closure_init }, { "eval", sqlite3_eval_init }, { "fileio", sqlite3_fileio_init }, { "fuzzer", sqlite3_fuzzer_init }, { "ieee754", sqlite3_ieee_init }, { "nextchar", sqlite3_nextchar_init }, { "percentile", sqlite3_percentile_init }, { "regexp", sqlite3_regexp_init }, { "spellfix", sqlite3_spellfix_init }, |
︙ | ︙ | |||
7034 7035 7036 7037 7038 7039 7040 | { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0}, #endif { "sqlite3_libversion_number", test_libversion_number, 0 }, #ifdef SQLITE_ENABLE_COLUMN_METADATA { "sqlite3_table_column_metadata", test_table_column_metadata, 0 }, #endif #ifndef SQLITE_OMIT_INCRBLOB | < < < < | 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 | { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0}, #endif { "sqlite3_libversion_number", test_libversion_number, 0 }, #ifdef SQLITE_ENABLE_COLUMN_METADATA { "sqlite3_table_column_metadata", test_table_column_metadata, 0 }, #endif #ifndef SQLITE_OMIT_INCRBLOB { "sqlite3_blob_reopen", test_blob_reopen, 0 }, #endif { "pcache_stats", test_pcache_stats, 0 }, #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY { "sqlite3_unlock_notify", test_unlock_notify, 0 }, #endif { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 }, { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 }, |
︙ | ︙ | |||
7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 | { "sorter_test_sort4_helper", sorter_test_sort4_helper }, #ifdef SQLITE_USER_AUTHENTICATION { "sqlite3_user_authenticate", test_user_authenticate, 0 }, { "sqlite3_user_add", test_user_add, 0 }, { "sqlite3_user_change", test_user_change, 0 }, { "sqlite3_user_delete", test_user_delete, 0 }, #endif }; static int bitmask_size = sizeof(Bitmask)*8; int i; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_like_count; | > > > > | 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 | { "sorter_test_sort4_helper", sorter_test_sort4_helper }, #ifdef SQLITE_USER_AUTHENTICATION { "sqlite3_user_authenticate", test_user_authenticate, 0 }, { "sqlite3_user_add", test_user_add, 0 }, { "sqlite3_user_change", test_user_change, 0 }, { "sqlite3_user_delete", test_user_delete, 0 }, #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS { "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 }, { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 }, #endif }; static int bitmask_size = sizeof(Bitmask)*8; int i; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_like_count; |
︙ | ︙ |
Added src/test_blob.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 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 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 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 | /* ** 2014 October 30 ** ** 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. ** ************************************************************************* ** */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> #include <assert.h> /* These functions are implemented in main.c. */ extern const char *sqlite3ErrName(int); /* From test1.c: */ extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); extern void *sqlite3TestTextToPtr(const char *z); /* ** Return a pointer to a buffer containing a text representation of the ** pointer passed as the only argument. The original pointer may be extracted ** from the text using sqlite3TestTextToPtr(). */ static char *ptrToText(void *p){ static char buf[100]; sqlite3_snprintf(sizeof(buf)-1, buf, "%p", p); return buf; } /* ** Attempt to extract a blob handle (type sqlite3_blob*) from the Tcl ** object passed as the second argument. If successful, set *ppBlob to ** point to the blob handle and return TCL_OK. Otherwise, store an error ** message in the tcl interpreter and return TCL_ERROR. The final value ** of *ppBlob is undefined in this case. ** ** If the object contains a string that begins with "incrblob_", then it ** is assumed to be the name of a Tcl channel opened using the [db incrblob] ** command (see tclsqlite.c). Otherwise, it is assumed to be a pointer ** encoded using the ptrToText() routine or similar. */ static int blobHandleFromObj( Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3_blob **ppBlob ){ char *z; int n; z = Tcl_GetStringFromObj(pObj, &n); if( n==0 ){ *ppBlob = 0; }else if( n>9 && 0==memcmp("incrblob_", z, 9) ){ int notUsed; Tcl_Channel channel; ClientData instanceData; channel = Tcl_GetChannel(interp, z, ¬Used); if( !channel ) return TCL_ERROR; Tcl_Flush(channel); Tcl_Seek(channel, 0, SEEK_SET); instanceData = Tcl_GetChannelInstanceData(channel); *ppBlob = *((sqlite3_blob **)instanceData); }else{ *ppBlob = (sqlite3_blob*)sqlite3TestTextToPtr(z); } return TCL_OK; } /* ** Like Tcl_GetString(), except that if the string is 0 bytes in size, a ** NULL Pointer is returned. */ static char *blobStringFromObj(Tcl_Obj *pObj){ int n; char *z; z = Tcl_GetStringFromObj(pObj, &n); return (n ? z : 0); } /* ** sqlite3_blob_open DB DATABASE TABLE COLUMN ROWID FLAGS VARNAME ** ** Tcl test harness for the sqlite3_blob_open() function. */ static int test_blob_open( ClientData clientData, /* Not used */ Tcl_Interp *interp, /* Calling TCL interpreter */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3 *db; const char *zDb; const char *zTable; const char *zColumn; sqlite_int64 iRowid; int flags; const char *zVarname; int nVarname; sqlite3_blob *pBlob = (sqlite3_blob*)0xFFFFFFFF; int rc; if( objc!=8 ){ const char *zUsage = "DB DATABASE TABLE COLUMN ROWID FLAGS VARNAME"; Tcl_WrongNumArgs(interp, 1, objv, zUsage); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zDb = Tcl_GetString(objv[2]); zTable = blobStringFromObj(objv[3]); zColumn = Tcl_GetString(objv[4]); if( Tcl_GetWideIntFromObj(interp, objv[5], &iRowid) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[6], &flags) ) return TCL_ERROR; zVarname = Tcl_GetStringFromObj(objv[7], &nVarname); if( nVarname>0 ){ rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRowid, flags, &pBlob); Tcl_SetVar(interp, zVarname, ptrToText(pBlob), 0); }else{ rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRowid, flags, 0); } if( rc==SQLITE_OK ){ Tcl_ResetResult(interp); }else{ Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); return TCL_ERROR; } return TCL_OK; } /* ** sqlite3_blob_close HANDLE */ static int test_blob_close( ClientData clientData, /* Not used */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3_blob *pBlob; int rc; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); return TCL_ERROR; } if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; rc = sqlite3_blob_close(pBlob); if( rc ){ Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); }else{ Tcl_ResetResult(interp); } return TCL_OK; } /* ** sqlite3_blob_bytes HANDLE */ static int test_blob_bytes( ClientData clientData, /* Not used */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3_blob *pBlob; int nByte; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); return TCL_ERROR; } if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; nByte = sqlite3_blob_bytes(pBlob); Tcl_SetObjResult(interp, Tcl_NewIntObj(nByte)); return TCL_OK; } /* ** sqlite3_blob_read CHANNEL OFFSET N ** ** This command is used to test the sqlite3_blob_read() in ways that ** the Tcl channel interface does not. The first argument should ** be the name of a valid channel created by the [incrblob] method ** of a database handle. This function calls sqlite3_blob_read() ** to read N bytes from offset OFFSET from the underlying SQLite ** blob handle. ** ** On success, a byte-array object containing the read data is ** returned. On failure, the interpreter result is set to the ** text representation of the returned error code (i.e. "SQLITE_NOMEM") ** and a Tcl exception is thrown. */ static int test_blob_read( ClientData clientData, /* Not used */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3_blob *pBlob; int nByte; int iOffset; unsigned char *zBuf = 0; int rc; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N"); return TCL_ERROR; } if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) || TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte) ){ return TCL_ERROR; } if( nByte>0 ){ zBuf = (unsigned char *)Tcl_Alloc(nByte); } rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset); if( rc==SQLITE_OK ){ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte)); }else{ Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); } Tcl_Free((char *)zBuf); return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); } /* ** sqlite3_blob_write HANDLE OFFSET DATA ?NDATA? ** ** This command is used to test the sqlite3_blob_write() in ways that ** the Tcl channel interface does not. The first argument should ** be the name of a valid channel created by the [incrblob] method ** of a database handle. This function calls sqlite3_blob_write() ** to write the DATA byte-array to the underlying SQLite blob handle. ** at offset OFFSET. ** ** On success, an empty string is returned. On failure, the interpreter ** result is set to the text representation of the returned error code ** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown. */ static int test_blob_write( ClientData clientData, /* Not used */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3_blob *pBlob; int iOffset; int rc; unsigned char *zBuf; int nBuf; if( objc!=4 && objc!=5 ){ Tcl_WrongNumArgs(interp, 1, objv, "HANDLE OFFSET DATA ?NDATA?"); return TCL_ERROR; } if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){ return TCL_ERROR; } zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf); if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){ return TCL_ERROR; } rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); } return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); } /* ** Register commands with the TCL interpreter. */ int Sqlitetest_blob_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; } aObjCmd[] = { { "sqlite3_blob_open", test_blob_open }, { "sqlite3_blob_close", test_blob_close }, { "sqlite3_blob_bytes", test_blob_bytes }, { "sqlite3_blob_read", test_blob_read }, { "sqlite3_blob_write", test_blob_write }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); } return TCL_OK; } |
Changes to src/test_config.c.
︙ | ︙ | |||
150 151 152 153 154 155 156 157 158 159 160 161 162 163 | #endif #ifdef SQLITE_OMIT_ANALYZE Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_ATOMIC_WRITE Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY); #endif | > > > > > > | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | #endif #ifdef SQLITE_OMIT_ANALYZE Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_API_ARMOR Tcl_SetVar2(interp, "sqlite_options", "api_armor", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "api_armor", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_ATOMIC_WRITE Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY); #endif |
︙ | ︙ | |||
479 480 481 482 483 484 485 486 487 488 489 490 491 492 | Tcl_SetVar2(interp, "sqlite_options", "stat4", "0", TCL_GLOBAL_ONLY); #endif #if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY); #endif #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__APPLE__) # define SQLITE_ENABLE_LOCKING_STYLE 1 # else # define SQLITE_ENABLE_LOCKING_STYLE 0 # endif | > > > > > > | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 | Tcl_SetVar2(interp, "sqlite_options", "stat4", "0", TCL_GLOBAL_ONLY); #endif #if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS Tcl_SetVar2(interp, "sqlite_options", "scanstatus", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "scanstatus", "0", TCL_GLOBAL_ONLY); #endif #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__APPLE__) # define SQLITE_ENABLE_LOCKING_STYLE 1 # else # define SQLITE_ENABLE_LOCKING_STYLE 0 # endif |
︙ | ︙ |
Changes to src/vacuum.c.
︙ | ︙ | |||
90 91 92 93 94 95 96 | ** original database is required. Every page of the database is written ** approximately 3 times: Once for step (2) and twice for step (3). ** Two writes per page are required in step (3) because the original ** database content must be written into the rollback journal prior to ** overwriting the database with the vacuumed content. ** ** Only 1x temporary space and only 1x writes would be required if | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | ** original database is required. Every page of the database is written ** approximately 3 times: Once for step (2) and twice for step (3). ** Two writes per page are required in step (3) because the original ** database content must be written into the rollback journal prior to ** overwriting the database with the vacuumed content. ** ** Only 1x temporary space and only 1x writes would be required if ** the copy of step (3) were replaced by deleting the original database ** and renaming the transient database as the original. But that will ** not work if other processes are attached to the original database. ** And a power loss in between deleting the original and renaming the ** transient would cause the database file to appear to be deleted ** following reboot. */ void sqlite3Vacuum(Parse *pParse){ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
604 605 606 607 608 609 610 611 612 613 614 615 616 617 | assert( pc>=0 && pc<p->nOp ); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE start = sqlite3Hwtime(); #endif nVmStep++; pOp = &aOp[pc]; /* Only allow tracing if SQLITE_DEBUG is defined. */ #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ sqlite3VdbePrintOp(stdout, pc, pOp); } | > > > | 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 | assert( pc>=0 && pc<p->nOp ); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE start = sqlite3Hwtime(); #endif nVmStep++; pOp = &aOp[pc]; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS if( p->anExec ) p->anExec[pc]++; #endif /* Only allow tracing if SQLITE_DEBUG is defined. */ #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ sqlite3VdbePrintOp(stdout, pc, pOp); } |
︙ | ︙ | |||
2294 2295 2296 2297 2298 2299 2300 | assert( pC->pseudoTableReg>0 ); pReg = &aMem[pC->pseudoTableReg]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); pC->payloadSize = pC->szRow = avail = pReg->n; pC->aRow = (u8*)pReg->z; }else{ | | | 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 | assert( pC->pseudoTableReg>0 ); pReg = &aMem[pC->pseudoTableReg]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); pC->payloadSize = pC->szRow = avail = pReg->n; pC->aRow = (u8*)pReg->z; }else{ sqlite3VdbeMemSetNull(pDest); goto op_column_out; } }else{ assert( pCrsr ); if( pC->isTable==0 ){ assert( sqlite3BtreeCursorIsValid(pCrsr) ); VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64); |
︙ | ︙ | |||
2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 | db->autoCommit = 0; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } db->isTransactionSavepoint = 0; rc = p->rc; }else{ iSavepoint = db->nSavepoint - iSavepoint - 1; if( p1==SAVEPOINT_ROLLBACK ){ for(ii=0; ii<db->nDb; ii++){ | > > | > > > > > | | 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 | db->autoCommit = 0; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } db->isTransactionSavepoint = 0; rc = p->rc; }else{ int isSchemaChange; iSavepoint = db->nSavepoint - iSavepoint - 1; if( p1==SAVEPOINT_ROLLBACK ){ isSchemaChange = (db->flags & SQLITE_InternChanges)!=0; for(ii=0; ii<db->nDb; ii++){ rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT_ROLLBACK, isSchemaChange==0); if( rc!=SQLITE_OK ) goto abort_due_to_error; } }else{ isSchemaChange = 0; } for(ii=0; ii<db->nDb; ii++){ rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } } if( isSchemaChange ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); db->flags = (db->flags | SQLITE_InternChanges); } } /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all |
︙ | ︙ | |||
3227 3228 3229 3230 3231 3232 3233 | assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); assert( p->bIsReader ); assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx || p->readOnly==0 ); if( p->expired ){ | | | 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 | assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); assert( p->bIsReader ); assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx || p->readOnly==0 ); if( p->expired ){ rc = SQLITE_ABORT_ROLLBACK; break; } nField = 0; pKeyInfo = 0; p2 = pOp->p2; iDb = pOp->p3; |
︙ | ︙ | |||
3791 3792 3793 3794 3795 3796 3797 | if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]); #endif } pIdxKey = &r; }else{ pIdxKey = sqlite3VdbeAllocUnpackedRecord( pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree | | | > | 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 | if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]); #endif } pIdxKey = &r; }else{ pIdxKey = sqlite3VdbeAllocUnpackedRecord( pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree ); if( pIdxKey==0 ) goto no_mem; assert( pIn3->flags & MEM_Blob ); /* assert( (pIn3->flags & MEM_Zero)==0 ); // zeroblobs already expanded */ ExpandBlob(pIn3); sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); } pIdxKey->default_rc = 0; if( pOp->opcode==OP_NoConflict ){ /* For the OP_NoConflict opcode, take the jump if any of the ** input fields are NULL, since any key with a NULL will not ** conflict */ |
︙ | ︙ | |||
4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 | rc = pModule->xRowid(pC->pVtabCursor, &v); sqlite3VtabImportErrmsg(p, pVtab); #endif /* SQLITE_OMIT_VIRTUALTABLE */ }else{ assert( pC->pCursor!=0 ); rc = sqlite3VdbeCursorRestore(pC); if( rc ) goto abort_due_to_error; rc = sqlite3BtreeKeySize(pC->pCursor, &v); assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */ } pOut->u.i = v; break; } | > > > > | 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 | rc = pModule->xRowid(pC->pVtabCursor, &v); sqlite3VtabImportErrmsg(p, pVtab); #endif /* SQLITE_OMIT_VIRTUALTABLE */ }else{ assert( pC->pCursor!=0 ); rc = sqlite3VdbeCursorRestore(pC); if( rc ) goto abort_due_to_error; if( pC->nullRow ){ pOut->flags = MEM_Null; break; } rc = sqlite3BtreeKeySize(pC->pCursor, &v); assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */ } pOut->u.i = v; break; } |
︙ | ︙ | |||
4484 4485 4486 4487 4488 4489 4490 | p->aCounter[SQLITE_STMTSTATUS_SORT]++; /* Fall through into OP_Rewind */ } /* Opcode: Rewind P1 P2 * * * ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. | | | | | 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 | p->aCounter[SQLITE_STMTSTATUS_SORT]++; /* Fall through into OP_Rewind */ } /* Opcode: Rewind P1 P2 * * * ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. ** If the table or index is empty, jump immediately to P2. ** If the table or index is not empty, fall through to the following ** instruction. ** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. */ case OP_Rewind: { /* jump */ VdbeCursor *pC; |
︙ | ︙ | |||
5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 | pFrame->apCsr = p->apCsr; pFrame->nCursor = p->nCursor; pFrame->aOp = p->aOp; pFrame->nOp = p->nOp; pFrame->token = pProgram->token; pFrame->aOnceFlag = p->aOnceFlag; pFrame->nOnceFlag = p->nOnceFlag; pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ pMem->flags = MEM_Undefined; pMem->db = db; } }else{ | > > > | 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 | pFrame->apCsr = p->apCsr; pFrame->nCursor = p->nCursor; pFrame->aOp = p->aOp; pFrame->nOp = p->nOp; pFrame->token = pProgram->token; pFrame->aOnceFlag = p->aOnceFlag; pFrame->nOnceFlag = p->nOnceFlag; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS pFrame->anExec = p->anExec; #endif pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ pMem->flags = MEM_Undefined; pMem->db = db; } }else{ |
︙ | ︙ | |||
5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 | p->nMem = pFrame->nChildMem; p->nCursor = (u16)pFrame->nChildCsr; p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; p->aOp = aOp = pProgram->aOp; p->nOp = pProgram->nOp; p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; p->nOnceFlag = pProgram->nOnce; pc = -1; memset(p->aOnceFlag, 0, p->nOnceFlag); break; } /* Opcode: Param P1 P2 * * * | > > > | 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 | p->nMem = pFrame->nChildMem; p->nCursor = (u16)pFrame->nChildCsr; p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; p->aOp = aOp = pProgram->aOp; p->nOp = pProgram->nOp; p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; p->nOnceFlag = pProgram->nOnce; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = 0; #endif pc = -1; memset(p->aOnceFlag, 0, p->nOnceFlag); break; } /* Opcode: Param P1 P2 * * * |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
277 278 279 280 281 282 283 284 285 | #else # define VdbeCoverage(v) # define VdbeCoverageIf(v,x) # define VdbeCoverageAlwaysTaken(v) # define VdbeCoverageNeverTaken(v) # define VDBE_OFFSET_LINENO(x) 0 #endif #endif | > > > > > > | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | #else # define VdbeCoverage(v) # define VdbeCoverageIf(v,x) # define VdbeCoverageAlwaysTaken(v) # define VdbeCoverageNeverTaken(v) # define VDBE_OFFSET_LINENO(x) 0 #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*); #else # define sqlite3VdbeScanStatus(a,b,c,d,e) #endif #endif |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
128 129 130 131 132 133 134 135 136 137 138 139 140 141 | ** set to NULL if the currently executing frame is the main program. */ typedef struct VdbeFrame VdbeFrame; struct VdbeFrame { Vdbe *v; /* VM this frame belongs to */ VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ | > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | ** set to NULL if the currently executing frame is the main program. */ typedef struct VdbeFrame VdbeFrame; struct VdbeFrame { Vdbe *v; /* VM this frame belongs to */ VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ i64 *anExec; /* Event counters from parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ |
︙ | ︙ | |||
292 293 294 295 296 297 298 299 300 301 302 303 304 305 | }; /* A bitfield type for use inside of structures. Always follow with :N where ** N is the number of bits. */ typedef unsigned bft; /* Bit Field Type */ /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() ** is really a pointer to an instance of this structure. ** | > > > > > > > > > > | 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | }; /* A bitfield type for use inside of structures. Always follow with :N where ** N is the number of bits. */ typedef unsigned bft; /* Bit Field Type */ typedef struct ScanStatus ScanStatus; struct ScanStatus { int addrExplain; /* OP_Explain for loop */ int addrLoop; /* Address of "loops" counter */ int addrVisit; /* Address of "rows visited" counter */ int iSelectID; /* The "Select-ID" for this loop */ LogEst nEst; /* Estimated output rows per loop */ char *zName; /* Name of table or index */ }; /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() ** is really a pointer to an instance of this structure. ** |
︙ | ︙ | |||
364 365 366 367 368 369 370 371 372 373 374 375 376 377 | VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ int nFrame; /* Number of frames in pFrame list */ u32 expmask; /* Binding to these vars invalidates VM */ SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ int nOnceFlag; /* Size of array aOnceFlag[] */ u8 *aOnceFlag; /* Flags for OP_Once */ AuxData *pAuxData; /* Linked list of auxdata allocations */ }; /* ** The following are allowed values for Vdbe.magic */ #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ | > > > > > | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 | VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ int nFrame; /* Number of frames in pFrame list */ u32 expmask; /* Binding to these vars invalidates VM */ SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ int nOnceFlag; /* Size of array aOnceFlag[] */ u8 *aOnceFlag; /* Flags for OP_Once */ AuxData *pAuxData; /* Linked list of auxdata allocations */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS i64 *anExec; /* Number of times each op has been executed */ int nScan; /* Entries in aScan[] */ ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ #endif }; /* ** The following are allowed values for Vdbe.magic */ #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
1514 1515 1516 1517 1518 1519 1520 | return 0; } #endif v = pVdbe->aCounter[op]; if( resetFlag ) pVdbe->aCounter[op] = 0; return (int)v; } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 | return 0; } #endif v = pVdbe->aCounter[op]; if( resetFlag ) pVdbe->aCounter[op] = 0; return (int)v; } #ifdef SQLITE_ENABLE_STMT_SCANSTATUS /* ** Return status data for a single loop within query pStmt. */ int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement being queried */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Which metric to return */ void *pOut /* OUT: Write the answer here */ ){ Vdbe *p = (Vdbe*)pStmt; ScanStatus *pScan; if( idx<0 || idx>=p->nScan ) return 1; pScan = &p->aScan[idx]; switch( iScanStatusOp ){ case SQLITE_SCANSTAT_NLOOP: { *(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop]; break; } case SQLITE_SCANSTAT_NVISIT: { *(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit]; break; } case SQLITE_SCANSTAT_EST: { double r = 1.0; LogEst x = pScan->nEst; while( x<100 ){ x += 10; r *= 0.5; } *(double*)pOut = r*sqlite3LogEstToInt(x); break; } case SQLITE_SCANSTAT_NAME: { *(const char**)pOut = pScan->zName; break; } case SQLITE_SCANSTAT_EXPLAIN: { if( pScan->addrExplain ){ *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z; }else{ *(const char**)pOut = 0; } break; } case SQLITE_SCANSTAT_SELECTID: { if( pScan->addrExplain ){ *(int*)pOut = p->aOp[ pScan->addrExplain ].p1; }else{ *(int*)pOut = -1; } break; } default: { return 1; } } return 0; } /* ** Zero all counters associated with the sqlite3_stmt_scanstatus() data. */ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; memset(p->anExec, 0, p->nOp * sizeof(i64)); } #endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
592 593 594 595 596 597 598 599 600 601 602 603 604 605 | } #endif } p->nOp += nOp; } return addr; } /* ** 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. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 | } #endif } p->nOp += nOp; } return addr; } #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) /* ** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus(). */ void sqlite3VdbeScanStatus( Vdbe *p, /* VM to add scanstatus() to */ int addrExplain, /* Address of OP_Explain (or 0) */ int addrLoop, /* Address of loop counter */ int addrVisit, /* Address of rows visited counter */ LogEst nEst, /* Estimated number of output rows */ const char *zName /* Name of table or index being scanned */ ){ int nByte = (p->nScan+1) * sizeof(ScanStatus); ScanStatus *aNew; aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); if( aNew ){ ScanStatus *pNew = &aNew[p->nScan++]; pNew->addrExplain = addrExplain; pNew->addrLoop = addrLoop; pNew->addrVisit = addrVisit; pNew->nEst = nEst; pNew->zName = sqlite3DbStrDup(p->db, zName); p->aScan = aNew; } } #endif /* ** 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. */ |
︙ | ︙ | |||
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 | p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte); p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte); p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte); p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte); p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), &zCsr, zEnd, &nByte); p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte); if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } zCsr = p->pFree; zEnd = &zCsr[nByte]; }while( nByte && !db->mallocFailed ); | > > > | 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 | p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte); p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte); p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte); p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte); p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), &zCsr, zEnd, &nByte); p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), &zCsr, zEnd, &nByte); #endif if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } zCsr = p->pFree; zEnd = &zCsr[nByte]; }while( nByte && !db->mallocFailed ); |
︙ | ︙ | |||
1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 | /* ** Copy the values stored in the VdbeFrame structure to its Vdbe. This ** is used, for example, when a trigger sub-program is halted to restore ** control to the main program. */ int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ Vdbe *v = pFrame->v; v->aOnceFlag = pFrame->aOnceFlag; v->nOnceFlag = pFrame->nOnceFlag; v->aOp = pFrame->aOp; v->nOp = pFrame->nOp; v->aMem = pFrame->aMem; v->nMem = pFrame->nMem; v->apCsr = pFrame->apCsr; | > > > | 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 | /* ** Copy the values stored in the VdbeFrame structure to its Vdbe. This ** is used, for example, when a trigger sub-program is halted to restore ** control to the main program. */ int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ Vdbe *v = pFrame->v; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS v->anExec = pFrame->anExec; #endif v->aOnceFlag = pFrame->aOnceFlag; v->nOnceFlag = pFrame->nOnceFlag; v->aOp = pFrame->aOp; v->nOp = pFrame->nOp; v->aMem = pFrame->aMem; v->nMem = pFrame->nMem; v->apCsr = pFrame->apCsr; |
︙ | ︙ | |||
2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 | sqlite3DbFree(db, pSub); } for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); sqlite3DbFree(db, p->pFree); } /* ** Delete an entire VDBE. */ void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; | > > > > > > | 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 | sqlite3DbFree(db, pSub); } for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); sqlite3DbFree(db, p->pFree); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS for(i=0; i<p->nScan; i++){ sqlite3DbFree(db, p->aScan[i].zName); } sqlite3DbFree(db, p->aScan); #endif } /* ** Delete an entire VDBE. */ void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
372 373 374 375 376 377 378 | db = p->db; sqlite3_mutex_enter(db->mutex); v = (Vdbe*)p->pStmt; if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; | < < > | 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 | db = p->db; sqlite3_mutex_enter(db->mutex); v = (Vdbe*)p->pStmt; if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; }else if( v==0 ){ /* If there is no statement handle, then the blob-handle has ** already been invalidated. Return SQLITE_ABORT in this case. */ rc = SQLITE_ABORT; }else{ /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is ** returned, clean-up the statement handle. */ assert( db == v->db ); sqlite3BtreeEnterCursor(p->pCsr); rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); sqlite3BtreeLeaveCursor(p->pCsr); if( rc==SQLITE_ABORT ){ sqlite3VdbeFinalize(v); p->pStmt = 0; }else{ v->rc = rc; } } sqlite3Error(db, rc); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } /* ** Read data from a blob handle. |
︙ | ︙ |
Changes to src/vdbesort.c.
︙ | ︙ | |||
96 97 98 99 100 101 102 | ** calling thread usually launches a worker thread to do so. Except, if ** there are already N worker threads running, the main thread does the work ** itself. ** ** The sorter is running in multi-threaded mode if (a) the library was built ** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater ** than zero, and (b) worker threads have been enabled at runtime by calling | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | ** calling thread usually launches a worker thread to do so. Except, if ** there are already N worker threads running, the main thread does the work ** itself. ** ** The sorter is running in multi-threaded mode if (a) the library was built ** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater ** than zero, and (b) worker threads have been enabled at runtime by calling ** "PRAGMA threads=N" with some value of N greater than 0. ** ** When Rewind() is called, any data remaining in memory is flushed to a ** final PMA. So at this point the data is stored in some number of sorted ** PMAs within temporary files on disk. ** ** If there are fewer than SORTER_MAX_MERGE_COUNT PMAs in total and the ** sorter is running in single-threaded mode, then these PMAs are merged |
︙ | ︙ | |||
843 844 845 846 847 848 849 | if( !sqlite3TempInMemory(db) ){ pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz; mxCache = db->aDb[0].pSchema->cache_size; if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING; pSorter->mxPmaSize = mxCache * pgsz; | | | < | < | 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 | if( !sqlite3TempInMemory(db) ){ pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz; mxCache = db->aDb[0].pSchema->cache_size; if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING; pSorter->mxPmaSize = mxCache * pgsz; /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary ** large heap allocations. */ if( sqlite3GlobalConfig.pScratch==0 ){ assert( pSorter->iMemory==0 ); pSorter->nMemory = pgsz; pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz); if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM; } |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
1505 1506 1507 1508 1509 1510 1511 | #endif } /* ** Free an iterator allocated by walIteratorInit(). */ static void walIteratorFree(WalIterator *p){ | | | 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 | #endif } /* ** Free an iterator allocated by walIteratorInit(). */ static void walIteratorFree(WalIterator *p){ sqlite3_free(p); } /* ** Construct a WalInterator object that can be used to loop over all ** pages in the WAL in ascending order. The caller must hold the checkpoint ** lock. ** |
︙ | ︙ | |||
1540 1541 1542 1543 1544 1545 1546 | iLast = pWal->hdr.mxFrame; /* Allocate space for the WalIterator object. */ nSegment = walFramePage(iLast) + 1; nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); | | | | 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 | iLast = pWal->hdr.mxFrame; /* Allocate space for the WalIterator object. */ nSegment = walFramePage(iLast) + 1; nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); p = (WalIterator *)sqlite3_malloc(nByte); if( !p ){ return SQLITE_NOMEM; } memset(p, 0, nByte); p->nSegment = nSegment; /* Allocate temporary space used by the merge-sort routine. This block ** of memory will be freed before this function returns. */ aTmp = (ht_slot *)sqlite3_malloc( sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) ); if( !aTmp ){ rc = SQLITE_NOMEM; } for(i=0; rc==SQLITE_OK && i<nSegment; i++){ |
︙ | ︙ | |||
1587 1588 1589 1590 1591 1592 1593 | walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry); p->aSegment[i].iZero = iZero; p->aSegment[i].nEntry = nEntry; p->aSegment[i].aIndex = aIndex; p->aSegment[i].aPgno = (u32 *)aPgno; } } | | | 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 | walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry); p->aSegment[i].iZero = iZero; p->aSegment[i].nEntry = nEntry; p->aSegment[i].aIndex = aIndex; p->aSegment[i].aPgno = (u32 *)aPgno; } } sqlite3_free(aTmp); if( rc!=SQLITE_OK ){ walIteratorFree(p); } *pp = p; return rc; } |
︙ | ︙ | |||
2519 2520 2521 2522 2523 2524 2525 | /* Restore the clients cache of the wal-index header to the state it ** was in before the client began writing to the database. */ memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); for(iFrame=pWal->hdr.mxFrame+1; | | < | 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 | /* Restore the clients cache of the wal-index header to the state it ** was in before the client began writing to the database. */ memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); for(iFrame=pWal->hdr.mxFrame+1; rc==SQLITE_OK && iFrame<=iMax; iFrame++ ){ /* This call cannot fail. Unless the page for which the page number ** is passed as the second argument is (a) in the cache and ** (b) has an outstanding reference, then xUndo is either a no-op ** (if (a) is false) or simply expels the page from the cache (if (b) ** is false). ** ** If the upper layer is doing a rollback, it is guaranteed that there ** 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); } return rc; } /* ** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 ** values. This function populates the array with values required to ** "rollback" the write position of the WAL handle back to the current |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
1893 1894 1895 1896 1897 1898 1899 | } } return pParse->nErr; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ | < | > | | 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 | } } return pParse->nErr; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Estimate the location of a particular key among all keys in an ** index. Store the results in aStat as follows: ** ** aStat[0] Est. number of rows less than pVal ** aStat[1] Est. number of rows equal to pVal ** ** Return the index of the sample that is the smallest sample that ** is greater than or equal to pRec. */ static int whereKeyStats( Parse *pParse, /* Database connection */ Index *pIdx, /* Index to consider domain of */ UnpackedRecord *pRec, /* Vector of values to consider */ int roundUp, /* Round up if true. Round down if false */ tRowcnt *aStat /* OUT: stats written here */ ){ IndexSample *aSample = pIdx->aSample; |
︙ | ︙ | |||
1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 | if( roundUp ){ iGap = (iGap*2)/3; }else{ iGap = iGap/3; } aStat[0] = iLower + iGap; } } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* ** If it is not NULL, pTerm is a term that provides an upper or lower ** bound on a range scan. Without considering pTerm, it is estimated ** that the scan will visit nNew rows. This function returns the number | > | 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 | if( roundUp ){ iGap = (iGap*2)/3; }else{ iGap = iGap/3; } aStat[0] = iLower + iGap; } return i; } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* ** If it is not NULL, pTerm is a term that provides an upper or lower ** bound on a range scan. Without considering pTerm, it is estimated ** that the scan will visit nNew rows. This function returns the number |
︙ | ︙ | |||
2136 2137 2138 2139 2140 2141 2142 | ** |_____| |_____| ** | | ** pLower pUpper ** ** If either of the upper or lower bound is not present, then NULL is passed in ** place of the corresponding WhereTerm. ** | | | | 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 | ** |_____| |_____| ** | | ** pLower pUpper ** ** If either of the upper or lower bound is not present, then NULL is passed in ** place of the corresponding WhereTerm. ** ** The value in (pBuilder->pNew->u.btree.nEq) is the number of the index ** column subject to the range constraint. Or, equivalently, the number of ** equality constraints optimized by the proposed index scan. For example, ** assuming index p is on t1(a, b), and the SQL query is: ** ** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ... ** ** then nEq is set to 1 (as the range restricted column, b, is the second ** left-most column of the index). Or, if the query is: ** ** ... FROM t1 WHERE a > ? AND a < ? ... ** ** then nEq is set to 0. ** ** When this function is called, *pnOut is set to the sqlite3LogEst() of the ** number of rows that the index scan is expected to visit without ** considering the range constraints. If nEq is 0, then *pnOut is the number of ** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced) ** to account for the range constraints pLower and pUpper. ** ** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be ** used, a single range inequality reduces the search space by a factor of 4. ** and a pair of constraints (x>? AND x<?) reduces the expected number of ** rows visited by a factor of 64. |
︙ | ︙ | |||
2176 2177 2178 2179 2180 2181 2182 | int nOut = pLoop->nOut; LogEst nNew; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 Index *p = pLoop->u.btree.pIndex; int nEq = pLoop->u.btree.nEq; | | < < | > > | | > > | 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 | int nOut = pLoop->nOut; LogEst nNew; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 Index *p = pLoop->u.btree.pIndex; int nEq = pLoop->u.btree.nEq; if( p->nSample>0 && nEq<p->nSampleCol ){ if( nEq==pBuilder->nRecValid ){ UnpackedRecord *pRec = pBuilder->pRec; tRowcnt a[2]; u8 aff; /* Variable iLower will be set to the estimate of the number of rows in ** the index that are less than the lower bound of the range query. The ** lower bound being the concatenation of $P and $L, where $P is the ** key-prefix formed by the nEq values matched against the nEq left-most ** columns of the index, and $L is the value in pLower. ** ** Or, if pLower is NULL or $L cannot be extracted from it (because it ** is not a simple variable or literal value), the lower bound of the ** range is $P. Due to a quirk in the way whereKeyStats() works, even ** if $L is available, whereKeyStats() is called for both ($P) and ** ($P:$L) and the larger of the two returned values is used. ** ** Similarly, iUpper is to be set to the estimate of the number of rows ** less than the upper bound of the range query. Where the upper bound ** is either ($P) or ($P:$U). Again, even if $U is available, both values ** of iUpper are requested of whereKeyStats() and the smaller used. ** ** The number of rows between the two bounds is then just iUpper-iLower. */ tRowcnt iLower; /* Rows less than the lower bound */ tRowcnt iUpper; /* Rows less than the upper bound */ int iLwrIdx = -2; /* aSample[] for the lower bound */ int iUprIdx = -1; /* aSample[] for the upper bound */ if( pRec ){ testcase( pRec->nField!=pBuilder->nRecValid ); pRec->nField = pBuilder->nRecValid; } if( nEq==p->nKeyCol ){ aff = SQLITE_AFF_INTEGER; |
︙ | ︙ | |||
2240 2241 2242 2243 2244 2245 2246 | /* If possible, improve on the iLower estimate using ($P:$L). */ if( pLower ){ int bOk; /* True if value is extracted from pExpr */ Expr *pExpr = pLower->pExpr->pRight; rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ tRowcnt iNew; | | | > > > > > | 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 | /* If possible, improve on the iLower estimate using ($P:$L). */ if( pLower ){ int bOk; /* True if value is extracted from pExpr */ Expr *pExpr = pLower->pExpr->pRight; rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ tRowcnt iNew; iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a); iNew = a[0] + ((pLower->eOperator & (WO_GT|WO_LE)) ? a[1] : 0); if( iNew>iLower ) iLower = iNew; nOut--; pLower = 0; } } /* If possible, improve on the iUpper estimate using ($P:$U). */ if( pUpper ){ int bOk; /* True if value is extracted from pExpr */ Expr *pExpr = pUpper->pExpr->pRight; rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ tRowcnt iNew; iUprIdx = whereKeyStats(pParse, p, pRec, 1, a); iNew = a[0] + ((pUpper->eOperator & (WO_GT|WO_LE)) ? a[1] : 0); if( iNew<iUpper ) iUpper = iNew; nOut--; pUpper = 0; } } pBuilder->pRec = pRec; if( rc==SQLITE_OK ){ if( iUpper>iLower ){ nNew = sqlite3LogEst(iUpper - iLower); /* TUNING: If both iUpper and iLower are derived from the same ** sample, then assume they are 4x more selective. This brings ** the estimated selectivity more in line with what it would be ** if estimated without the use of STAT3/4 tables. */ if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) ); }else{ nNew = 10; assert( 10==sqlite3LogEst(2) ); } if( nNew<nOut ){ nOut = nNew; } WHERETRACE(0x10, ("STAT4 range scan: %u..%u est=%d\n", |
︙ | ︙ | |||
2804 2805 2806 2807 2808 2809 2810 | explainAppendTerm(pStr, i, z, "<"); } sqlite3StrAccumAppend(pStr, ")", 1); } /* ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN | | > | | > > | > | | | 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 | explainAppendTerm(pStr, i, z, "<"); } sqlite3StrAccumAppend(pStr, ")", 1); } /* ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN ** command, or if either SQLITE_DEBUG or SQLITE_ENABLE_STMT_SCANSTATUS was ** defined at compile-time. If it is not a no-op, a single OP_Explain opcode ** is added to the output to describe the table scan strategy in pLevel. ** ** If an OP_Explain opcode is added to the VM, its address is returned. ** Otherwise, if no OP_Explain is coded, zero is returned. */ static int explainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ int iLevel, /* Value for "level" column of output */ int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ){ int ret = 0; #if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) if( pParse->explain==2 ) #endif { struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; Vdbe *v = pParse->pVdbe; /* VM being constructed */ sqlite3 *db = pParse->db; /* Database handle */ int iId = pParse->iSelectId; /* Select id (left-most output column) */ int isSearch; /* True for a SEARCH. False for SCAN. */ WhereLoop *pLoop; /* The controlling WhereLoop object */ u32 flags; /* Flags that describe this loop */ char *zMsg; /* Text to add to EQP output */ StrAccum str; /* EQP output string */ char zBuf[100]; /* Initial space for EQP output string */ pLoop = pLevel->pWLoop; flags = pLoop->wsFlags; if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return 0; isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); str.db = db; |
︙ | ︙ | |||
2905 2906 2907 2908 2909 2910 2911 | if( pLoop->nOut>=10 ){ sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); }else{ sqlite3StrAccumAppend(&str, " (~1 row)", 9); } #endif zMsg = sqlite3StrAccumFinish(&str); | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | if( pLoop->nOut>=10 ){ sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); }else{ sqlite3StrAccumAppend(&str, " (~1 row)", 9); } #endif zMsg = sqlite3StrAccumFinish(&str); ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC); } return ret; } #else # define explainOneScan(u,v,w,x,y,z) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS /* ** Configure the VM passed as the first argument with an ** sqlite3_stmt_scanstatus() entry corresponding to the scan used to ** implement level pLvl. Argument pSrclist is a pointer to the FROM ** clause that the scan reads data from. ** ** If argument addrExplain is not 0, it must be the address of an ** OP_Explain instruction that describes the same loop. */ static void addScanStatus( Vdbe *v, /* Vdbe to add scanstatus entry to */ SrcList *pSrclist, /* FROM clause pLvl reads data from */ WhereLevel *pLvl, /* Level to add scanstatus() entry for */ int addrExplain /* Address of OP_Explain (or 0) */ ){ const char *zObj = 0; WhereLoop *pLoop = pLvl->pWLoop; if( (pLoop->wsFlags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ zObj = pLoop->u.btree.pIndex->zName; }else{ zObj = pSrclist->a[pLvl->iFrom].zName; } sqlite3VdbeScanStatus( v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj ); } #else # define addScanStatus(a, b, c, d) ((void)d) #endif /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. */ static Bitmask codeOneLoopStart( |
︙ | ︙ | |||
3578 3579 3580 3581 3582 3583 3584 | /* Loop through table entries that match term pOrTerm. */ WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, wctrlFlags, iCovCur); assert( pSubWInfo || pParse->nErr || db->mallocFailed ); if( pSubWInfo ){ WhereLoop *pSubLoop; | | > > | 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 | /* Loop through table entries that match term pOrTerm. */ WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, wctrlFlags, iCovCur); assert( pSubWInfo || pParse->nErr || db->mallocFailed ); if( pSubWInfo ){ WhereLoop *pSubLoop; int addrExplain = explainOneScan( pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 ); addScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); /* This is the sub-WHERE clause body. First skip over ** duplicate rows from prior sub-WHERE clauses, and record the ** rowid (or PRIMARY KEY) for the current row so that the same ** row will be skipped in subsequent sub-WHERE clauses. */ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ int r; |
︙ | ︙ | |||
3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 | pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } } /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; testcase( pTerm->wtFlags & TERM_VIRTUAL ); | > > > > | 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 | pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } } #ifdef SQLITE_ENABLE_STMT_SCANSTATUS pLevel->addrVisit = sqlite3VdbeCurrentAddr(v); #endif /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; testcase( pTerm->wtFlags & TERM_VIRTUAL ); |
︙ | ︙ | |||
3961 3962 3963 3964 3965 3966 3967 | whereLoopDelete(db, p); } sqlite3DbFree(db, pWInfo); } } /* | | > | > > > | 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 | whereLoopDelete(db, p); } sqlite3DbFree(db, pWInfo); } } /* ** Return TRUE if all of the following are true: ** ** (1) X has the same or lower cost that Y ** (2) X is a proper subset of Y ** (3) X skips at least as many columns as Y ** ** By "proper subset" we mean that X uses fewer WHERE clause terms ** than Y and that every WHERE clause term used by X is also used ** by Y. ** ** If X is a proper subset of Y then Y is a better choice and ought ** to have a lower cost. This routine returns TRUE when that cost ** relationship is inverted and needs to be adjusted. The third rule ** was added because if X uses skip-scan less than Y it still might ** deserve a lower cost even if it is a proper subset of Y. */ static int whereLoopCheaperProperSubset( const WhereLoop *pX, /* First WhereLoop to compare */ const WhereLoop *pY /* Compare against this WhereLoop */ ){ int i, j; if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){ return 0; /* X is not a subset of Y */ } if( pY->nSkip > pX->nSkip ) return 0; if( pX->rRun >= pY->rRun ){ if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */ if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */ } for(i=pX->nLTerm-1; i>=0; i--){ if( pX->aLTerm[i]==0 ) continue; for(j=pY->nLTerm-1; j>=0; j--){ |
︙ | ︙ | |||
4017 4018 4019 4020 4021 4022 4023 | static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return; for(; p; p=p->pNextLoop){ if( p->iTab!=pTemplate->iTab ) continue; if( (p->wsFlags & WHERE_INDEXED)==0 ) continue; if( whereLoopCheaperProperSubset(p, pTemplate) ){ /* Adjust pTemplate cost downward so that it is cheaper than its | | < < | 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 | static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return; for(; p; p=p->pNextLoop){ if( p->iTab!=pTemplate->iTab ) continue; if( (p->wsFlags & WHERE_INDEXED)==0 ) continue; if( whereLoopCheaperProperSubset(p, pTemplate) ){ /* Adjust pTemplate cost downward so that it is cheaper than its ** subset p. */ WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n", pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1)); pTemplate->rRun = p->rRun; pTemplate->nOut = p->nOut - 1; }else if( whereLoopCheaperProperSubset(pTemplate, p) ){ /* Adjust pTemplate cost upward so that it is costlier than p since ** pTemplate is a proper subset of p */ |
︙ | ︙ | |||
6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 | /* Generate the code to do the search. Each iteration of the for ** loop below generates code for a single nested loop of the VM ** program. */ notReady = ~(Bitmask)0; for(ii=0; ii<nTabList; ii++){ pLevel = &pWInfo->a[ii]; #ifndef SQLITE_OMIT_AUTOMATIC_INDEX if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ constructAutomaticIndex(pParse, &pWInfo->sWC, &pTabList->a[pLevel->iFrom], notReady, pLevel); if( db->mallocFailed ) goto whereBeginError; } #endif | > > > > | > > > > | 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 | /* Generate the code to do the search. Each iteration of the for ** loop below generates code for a single nested loop of the VM ** program. */ notReady = ~(Bitmask)0; for(ii=0; ii<nTabList; ii++){ int addrExplain; int wsFlags; pLevel = &pWInfo->a[ii]; wsFlags = pLevel->pWLoop->wsFlags; #ifndef SQLITE_OMIT_AUTOMATIC_INDEX if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ constructAutomaticIndex(pParse, &pWInfo->sWC, &pTabList->a[pLevel->iFrom], notReady, pLevel); if( db->mallocFailed ) goto whereBeginError; } #endif addrExplain = explainOneScan( pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags ); pLevel->addrBody = sqlite3VdbeCurrentAddr(v); notReady = codeOneLoopStart(pWInfo, ii, notReady); pWInfo->iContinue = pLevel->addrCont; if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_ONETABLE_ONLY)==0 ){ addScanStatus(v, pTabList, pLevel, addrExplain); } } /* Done. */ VdbeModuleComment((v, "Begin WHERE-core")); return pWInfo; /* Jump here if malloc fails */ |
︙ | ︙ |
Changes to src/whereInt.h.
︙ | ︙ | |||
81 82 83 84 85 86 87 88 89 90 91 92 93 94 | u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; struct WhereLoop *pWLoop; /* The selected WhereLoop object */ Bitmask notReady; /* FROM entries not usable at this level */ }; /* ** Each instance of this object represents an algorithm for evaluating one ** term of a join. Every term of the FROM clause will have at least ** one corresponding WhereLoop object (unless INDEXED BY constraints ** prevent a query solution - which is an error) and many terms of the | > > > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; struct WhereLoop *pWLoop; /* The selected WhereLoop object */ Bitmask notReady; /* FROM entries not usable at this level */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS int addrVisit; /* Address at which row is visited */ #endif }; /* ** Each instance of this object represents an algorithm for evaluating one ** term of a join. Every term of the FROM clause will have at least ** one corresponding WhereLoop object (unless INDEXED BY constraints ** prevent a query solution - which is an error) and many terms of the |
︙ | ︙ |
Changes to test/analyze8.test.
︙ | ︙ | |||
82 83 84 85 86 87 88 | } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}} # There are many more values of c between 0 and 100000 than there are # between 800000 and 900000. So t1c is more selective for the latter # range. # # Test 3.2 is a little unstable. It depends on the planner estimating | | | | | | 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 107 108 109 110 111 112 | } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}} # There are many more values of c between 0 and 100000 than there are # between 800000 and 900000. So t1c is more selective for the latter # range. # # Test 3.2 is a little unstable. It depends on the planner estimating # that (b BETWEEN 30 AND 34) will match more rows than (c BETWEEN # 800000 AND 900000). Which is a pretty close call (50 vs. 32), so # the planner could get it wrong with an unlucky set of samples. This # case happens to work, but others ("b BETWEEN 40 AND 44" for example) # will fail. # do_execsql_test 3.0 { SELECT count(*) FROM t1 WHERE b BETWEEN 30 AND 34; SELECT count(*) FROM t1 WHERE c BETWEEN 0 AND 100000; SELECT count(*) FROM t1 WHERE c BETWEEN 800000 AND 900000; } {50 376 32} do_test 3.1 { eqp {SELECT * FROM t1 WHERE b BETWEEN 30 AND 34 AND c BETWEEN 0 AND 100000} } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}} do_test 3.2 { eqp {SELECT * FROM t1 WHERE b BETWEEN 30 AND 34 AND c BETWEEN 800000 AND 900000} } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}} do_test 3.3 { eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000} } {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} do_test 3.4 { eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 800000 AND 900000} |
︙ | ︙ |
Changes to test/backup.test.
︙ | ︙ | |||
213 214 215 216 217 218 219 220 221 222 223 224 225 226 | CREATE INDEX ${file_dest}.i1 ON t1(a, b); " $db_dest for {set ii 0} {$ii < $rows_dest} {incr ii} { execsql " INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000)) " $db_dest } } # Backup the source database. do_test backup-2.$iTest.1 { sqlite3_backup B $db_dest $file_dest db main while {[B step $nPagePerStep]=="SQLITE_OK"} {} B finish | > | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | CREATE INDEX ${file_dest}.i1 ON t1(a, b); " $db_dest for {set ii 0} {$ii < $rows_dest} {incr ii} { execsql " INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000)) " $db_dest } execsql COMMIT $db_dest } # Backup the source database. do_test backup-2.$iTest.1 { sqlite3_backup B $db_dest $file_dest db main while {[B step $nPagePerStep]=="SQLITE_OK"} {} B finish |
︙ | ︙ |
Added test/backup5.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 | # 2014 November 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix backup5 forcedelete test2.db do_execsql_test 1.0 { CREATE TABLE t1(a, b); CREATE TABLE t2(a, b); INSERT INTO t2 VALUES(1, 1); INSERT INTO t2 VALUES(2, 2); INSERT INTO t2 VALUES(3, 3); } do_test 1.1 { forcecopy test.db test.db2 db eval { DROP TABLE t2; INSERT INTO t1 VALUES(zeroblob(1000), zeroblob(1000)); INSERT INTO t1 VALUES(randomblob(1000), randomblob(1000)); } } {} do_test 1.2 { sqlite3 db2 test.db2 set stmt [sqlite3_prepare_v2 db2 "SELECT * FROM t2" -1 dummy] sqlite3_step $stmt } {SQLITE_ROW} do_test 1.3 { list [catch { sqlite3_backup B db2 main db main } msg] $msg } {1 {sqlite3_backup_init() failed}} do_test 1.4 { sqlite3_errmsg db2 } {destination database is in use} do_test 1.5 { sqlite3_reset $stmt sqlite3_backup B db2 main db main B step 200 B finish } {SQLITE_OK} do_test 1.6 { list [sqlite3_step $stmt] [sqlite3_finalize $stmt] } {SQLITE_ERROR SQLITE_ERROR} do_test 1.7 { sqlite3_errmsg db2 } {no such table: t2} finish_test |
Changes to test/capi3.test.
︙ | ︙ | |||
908 909 910 911 912 913 914 | } } {0 {}} do_test capi3-11.9.3 { sqlite3_get_autocommit $DB } 1 do_test capi3-11.10 { sqlite3_step $STMT | | | | | 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 | } } {0 {}} do_test capi3-11.9.3 { sqlite3_get_autocommit $DB } 1 do_test capi3-11.10 { sqlite3_step $STMT } {SQLITE_ROW} ifcapable !autoreset { # If SQLITE_OMIT_AUTORESET is defined, then the statement must be # reset() before it can be passed to step() again. do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE} do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT} } do_test capi3-11.11 { sqlite3_step $STMT } {SQLITE_DONE} do_test capi3-11.12 { sqlite3_step $STMT sqlite3_step $STMT } {SQLITE_ROW} do_test capi3-11.13 { sqlite3_finalize $STMT } {SQLITE_OK} do_test capi3-11.14 { execsql { SELECT a FROM t2; } |
︙ | ︙ |
Changes to test/capi3c.test.
︙ | ︙ | |||
859 860 861 862 863 864 865 | } } {0 {}} do_test capi3c-11.9.3 { sqlite3_get_autocommit $DB } 1 do_test capi3c-11.10 { sqlite3_step $STMT | | | | | 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 | } } {0 {}} do_test capi3c-11.9.3 { sqlite3_get_autocommit $DB } 1 do_test capi3c-11.10 { sqlite3_step $STMT } {SQLITE_ROW} ifcapable !autoreset { # If SQLITE_OMIT_AUTORESET is defined, then the statement must be # reset() before it can be passed to step() again. do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE} do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT} } do_test capi3c-11.11 { sqlite3_step $STMT } {SQLITE_DONE} do_test capi3c-11.12 { sqlite3_step $STMT sqlite3_step $STMT } {SQLITE_ROW} do_test capi3c-11.13 { sqlite3_finalize $STMT } {SQLITE_OK} do_test capi3c-11.14 { execsql { SELECT a FROM t2; } |
︙ | ︙ |
Changes to test/capi3d.test.
︙ | ︙ | |||
151 152 153 154 155 156 157 | do_execsql_test capi3d-4.1 { CREATE TABLE t4(x,y); BEGIN; } do_test capi3d-4.2.1 { | < | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | do_execsql_test capi3d-4.1 { CREATE TABLE t4(x,y); BEGIN; } do_test capi3d-4.2.1 { set ::s1 [sqlite3_prepare_v2 db "ROLLBACK" -1 notused] sqlite3_step $::s1 } {SQLITE_DONE} do_test capi3d-4.2.2 { sqlite3_stmt_busy $::s1 } {1} |
︙ | ︙ |
Changes to test/corruptH.test.
︙ | ︙ | |||
60 61 62 63 64 65 66 | } db close hexio_write test.db [expr {($r(t2)-1)*1024 + 11}] [format %.2X $r(t1)] sqlite3 db test.db } {} do_test 1.3 { | < | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | } db close hexio_write test.db [expr {($r(t2)-1)*1024 + 11}] [format %.2X $r(t1)] sqlite3 db test.db } {} do_test 1.3 { db eval { PRAGMA secure_delete=1 } list [catch { db eval { SELECT * FROM t1 WHERE a IN (1, 2) } { db eval { DELETE FROM t2 } } } msg] $msg } {1 {database disk image is malformed}} |
︙ | ︙ |
Added test/e_blobbytes.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 | # 2014 October 30 # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix e_blobbytes do_execsql_test 1.0 { CREATE TABLE q1(r INTEGER PRIMARY KEY, s TEXT); WITH d(a, b) AS ( SELECT 0, '' UNION ALL SELECT a+1, b||'.' FROM d WHERE a<10000 ) INSERT INTO q1 SELECT * FROM d; } # EVIDENCE-OF: R-07796-55423 Returns the size in bytes of the BLOB # accessible via the successfully opened BLOB handle in its only # argument. # proc check_blob_size {tn rowid bytes} { uplevel [list do_test $tn [subst -nocommands { sqlite3_blob_open db main q1 s $rowid 0 B set res [sqlite3_blob_bytes [set B]] sqlite3_blob_close [set B] set res }] $bytes] } check_blob_size 1.1 43 43 check_blob_size 1.2 391 391 check_blob_size 1.3 6349 6349 check_blob_size 1.4 2621 2621 check_blob_size 1.5 7771 7771 check_blob_size 1.6 7949 7949 check_blob_size 1.7 4374 4374 check_blob_size 1.8 2578 2578 check_blob_size 1.9 7004 7004 check_blob_size 1.10 2180 2180 check_blob_size 1.11 3796 3796 check_blob_size 1.12 7101 7101 check_blob_size 1.13 7449 7449 check_blob_size 1.14 7224 7224 check_blob_size 1.15 3038 3038 check_blob_size 1.16 1083 1083 check_blob_size 1.17 5157 5157 check_blob_size 1.18 6686 6686 check_blob_size 1.19 6592 6592 check_blob_size 1.20 0 0 # EVIDENCE-OF: R-53088-19343 The incremental blob I/O routines can only # read or overwriting existing blob content; they cannot change the size # of a blob. # # Also demonstrated in other e_blobXXX.test files. # do_test 2.1 { sqlite3_blob_open db main q1 s 86 1 B list [catch { sqlite3_blob_write $B 86 "1" 1 } msg] $msg } {1 SQLITE_ERROR} sqlite3_blob_close $B finish_test |
Added test/e_blobclose.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 107 108 109 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 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 | # 2014 October 30 # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix e_blobclose set dots [string repeat . 40] do_execsql_test 1.0 { CREATE TABLE x1(a INTEGER PRIMARY KEY, b DOTS); INSERT INTO x1 VALUES(-1, $dots); INSERT INTO x1 VALUES(-10, $dots); INSERT INTO x1 VALUES(-100, $dots); INSERT INTO x1 VALUES(-1000, $dots); INSERT INTO x1 VALUES(-10000, $dots); } # EVIDENCE-OF: R-03145-46390 This function closes an open BLOB handle. # # It's not clear how to test that a blob handle really is closed. # Attempting to use a closed blob handle will likely crash the process. # Assume here that if the SHARED lock on the db file is released, # the blob handle has been closed. # do_execsql_test 1.1 { PRAGMA lock_status } {main unlocked temp closed} sqlite3_blob_open db main x1 b -1 0 B do_execsql_test 1.2 { PRAGMA lock_status } {main shared temp closed} sqlite3_blob_close $B do_execsql_test 1.3 { PRAGMA lock_status } {main unlocked temp closed} # EVIDENCE-OF: R-34027-00617 If the blob handle being closed was opened # for read-write access, and if the database is in auto-commit mode and # there are no other open read-write blob handles or active write # statements, the current transaction is committed. # # 2.1.*: Transaction is not committed if there are other open # read-write blob handles. # # 2.2.*: Transaction is not committed if not in auto-commit mode. # # 2.3.*: Active write statements. # do_test 2.1.1 { sqlite3_blob_open db main x1 b -100 1 B1 sqlite3_blob_open db main x1 b -1000 1 B2 sqlite3_blob_open db main x1 b -10000 1 B3 sqlite3_blob_open db main x1 b -10000 0 B4 ;# B4 is read-only! execsql { PRAGMA lock_status } } {main reserved temp closed} do_test 2.1.2 { sqlite3_blob_close $B1 execsql { PRAGMA lock_status } } {main reserved temp closed} do_test 2.1.3 { sqlite3_blob_close $B2 execsql { PRAGMA lock_status } } {main reserved temp closed} do_test 2.1.4 { sqlite3_blob_close $B3 execsql { PRAGMA lock_status } } {main shared temp closed} do_test 2.1.5 { sqlite3_blob_close $B4 execsql { PRAGMA lock_status } } {main unlocked temp closed} do_test 2.2.1 { sqlite3_blob_open db main x1 b -100 1 B1 execsql { PRAGMA lock_status } } {main reserved temp closed} do_test 2.2.2 { execsql { BEGIN } sqlite3_blob_close $B1 execsql { PRAGMA lock_status } } {main reserved temp closed} do_test 2.2.3 { execsql { COMMIT } execsql { PRAGMA lock_status } } {main unlocked temp closed} proc val {} { sqlite3_blob_close $::B db eval { PRAGMA lock_status } } db func val val do_test 2.3.1 { sqlite3_blob_open db main x1 b -100 1 B execsql { PRAGMA lock_status } } {main reserved temp closed} do_test 2.3.2 { execsql { INSERT INTO x1 VALUES(15, val()) } execsql { PRAGMA lock_status } } {main unlocked temp closed} do_test 2.3.3 { execsql { SELECT * FROM x1 WHERE a = 15 } } {15 {main reserved temp closed}} # A reader does not inhibit commit. do_test 2.3.4 { sqlite3_blob_open db main x1 b -100 1 B execsql { PRAGMA lock_status } } {main reserved temp closed} do_test 2.3.5 { execsql { SELECT a, val() FROM x1 LIMIT 1 } } {-10000 {main shared temp closed}} do_test 3.1 { sqlite3_blob_open db main x1 b -10 1 B execsql { INSERT INTO x1 VALUES(1, 'abc'); SELECT * FROM x1 WHERE a=1; } } {1 abc} do_test 3.2 { sqlite3_blob_write $B 0 "abcdefghij" 10 execsql { SELECT * FROM x1 WHERE a=-10 } } {-10 abcdefghij..............................} do_test 3.3 { sqlite3 db2 test.db execsql { BEGIN ; SELECT * FROM x1 } db2 sqlite3_blob_close $B } {SQLITE_BUSY} # EVIDENCE-OF: R-41959-38737 Otherwise, if this function is passed a # valid open blob handle, the values returned by the sqlite3_errcode() # and sqlite3_errmsg() functions are set before returning. # do_test 3.4 { list [sqlite3_errcode db] [sqlite3_errmsg db] } {SQLITE_BUSY {database is locked}} # EVIDENCE-OF: R-37801-37633 The BLOB handle is closed unconditionally. # Even if this routine returns an error code, the handle is still # closed. # # Test that the lock has been released. Assume this means the handle # is closed, even though blob_close() returned SQLITE_BUSY. # do_execsql_test 3.4 { PRAGMA lock_status } {main unlocked temp closed} # EVIDENCE-OF: R-35111-05628 If an error occurs while committing the # transaction, an error code is returned and the transaction rolled # back. # # Row 1 is removed (it was inserted this transaction) and row -10 # is restored to its original state. Transaction has been rolled back. # do_execsql_test 3.5 { SELECT * FROM x1 WHERE a IN (1, -10); } {-10 ........................................} # EVIDENCE-OF: R-25894-51060 Calling this routine with a null pointer # (such as would be returned by a failed call to sqlite3_blob_open()) is # a harmless no-op. # do_test 4.0 { sqlite3_blob_close 0 } {} finish_test |
Added test/e_blobopen.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 107 108 109 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 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 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 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 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 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 | # 2014 October 30 # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix e_blobopen forcedelete test.db2 do_execsql_test 1.0 { ATTACH 'test.db2' AS aux; CREATE TABLE main.t1(a INTEGER PRIMARY KEY, b TEXT, c BLOB); CREATE TEMP TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c BLOB); CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b TEXT, c BLOB); CREATE TABLE main.x1(a INTEGER PRIMARY KEY, b TEXT, c BLOB); CREATE TEMP TABLE x2(a INTEGER PRIMARY KEY, b TEXT, c BLOB); CREATE TABLE aux.x3(a INTEGER PRIMARY KEY, b TEXT, c BLOB); INSERT INTO main.t1 VALUES(1, 'main one', X'0101'); INSERT INTO main.t1 VALUES(2, 'main two', X'0102'); INSERT INTO main.t1 VALUES(3, 'main three', X'0103'); INSERT INTO main.t1 VALUES(4, 'main four', X'0104'); INSERT INTO main.t1 VALUES(5, 'main five', X'0105'); INSERT INTO main.x1 VALUES(1, 'x main one', X'000101'); INSERT INTO main.x1 VALUES(2, 'x main two', X'000102'); INSERT INTO main.x1 VALUES(3, 'x main three', X'000103'); INSERT INTO main.x1 VALUES(4, 'x main four', X'000104'); INSERT INTO main.x1 VALUES(5, 'x main five', X'000105'); INSERT INTO temp.t1 VALUES(1, 'temp one', X'0201'); INSERT INTO temp.t1 VALUES(2, 'temp two', X'0202'); INSERT INTO temp.t1 VALUES(3, 'temp three', X'0203'); INSERT INTO temp.t1 VALUES(4, 'temp four', X'0204'); INSERT INTO temp.t1 VALUES(5, 'temp five', X'0205'); INSERT INTO temp.x2 VALUES(1, 'x temp one', X'000201'); INSERT INTO temp.x2 VALUES(2, 'x temp two', X'000202'); INSERT INTO temp.x2 VALUES(3, 'x temp three', X'000203'); INSERT INTO temp.x2 VALUES(4, 'x temp four', X'000204'); INSERT INTO temp.x2 VALUES(5, 'x temp five', X'000205'); INSERT INTO aux.t1 VALUES(1, 'aux one', X'0301'); INSERT INTO aux.t1 VALUES(2, 'aux two', X'0302'); INSERT INTO aux.t1 VALUES(3, 'aux three', X'0303'); INSERT INTO aux.t1 VALUES(4, 'aux four', X'0304'); INSERT INTO aux.t1 VALUES(5, 'aux five', X'0305'); INSERT INTO aux.x3 VALUES(1, 'x aux one', X'000301'); INSERT INTO aux.x3 VALUES(2, 'x aux two', X'000302'); INSERT INTO aux.x3 VALUES(3, 'x aux three', X'000303'); INSERT INTO aux.x3 VALUES(4, 'x aux four', X'000304'); INSERT INTO aux.x3 VALUES(5, 'x aux five', X'000305'); } #------------------------------------------------------------------------- # EVIDENCE-OF: R-37639-55938 This interfaces opens a handle to the BLOB # located in row iRow, column zColumn, table zTable in database zDb; in # other words, the same BLOB that would be selected by: SELECT zColumn # FROM zDb.zTable WHERE rowid = iRow; # proc read_blob {zDb zTab zCol iRow} { sqlite3_blob_open db $zDb $zTab $zCol $iRow 0 B set nByte [sqlite3_blob_bytes $B] set data [sqlite3_blob_read $B 0 $nByte] sqlite3_blob_close $B return $data } do_test 1.1.1 { read_blob main t1 b 1 } "main one" do_test 1.1.2 { read_blob main t1 c 1 } "\01\01" do_test 1.1.3 { read_blob temp t1 b 1 } "temp one" do_test 1.1.4 { read_blob temp t1 c 1 } "\02\01" do_test 1.1.6 { read_blob aux t1 b 1 } "aux one" do_test 1.1.7 { read_blob aux t1 c 1 } "\03\01" do_test 1.2.1 { read_blob main t1 b 4 } "main four" do_test 1.2.2 { read_blob main t1 c 4 } "\01\04" do_test 1.2.3 { read_blob temp t1 b 4 } "temp four" do_test 1.2.4 { read_blob temp t1 c 4 } "\02\04" do_test 1.2.6 { read_blob aux t1 b 4 } "aux four" do_test 1.2.7 { read_blob aux t1 c 4 } "\03\04" do_test 1.3.1 { read_blob main x1 b 2 } "x main two" do_test 1.3.2 { read_blob main x1 c 2 } "\00\01\02" do_test 1.3.3 { read_blob temp x2 b 2 } "x temp two" do_test 1.3.4 { read_blob temp x2 c 2 } "\00\02\02" do_test 1.3.6 { read_blob aux x3 b 2 } "x aux two" do_test 1.3.7 { read_blob aux x3 c 2 } "\00\03\02" #------------------------------------------------------------------------- # EVIDENCE-OF: R-27234-05761 Parameter zDb is not the filename that # contains the database, but rather the symbolic name of the database. # For attached databases, this is the name that appears after the AS # keyword in the ATTACH statement. For the main database file, the # database name is "main". For TEMP tables, the database name is "temp". # # The test cases immediately above demonstrate that the database name # for the main db, for TEMP tables and for those in attached databases # is correct. The following tests check that filenames cannot be # used as well. # do_test 2.1 { list [catch { sqlite3_blob_open db "test.db" t1 b 1 0 B } msg] $msg } {1 SQLITE_ERROR} do_test 2.2 { list [catch { sqlite3_blob_open db "test.db2" t1 b 1 0 B } msg] $msg } {1 SQLITE_ERROR} #------------------------------------------------------------------------- # EVIDENCE-OF: R-50854-53979 If the flags parameter is non-zero, then # the BLOB is opened for read and write access. # # EVIDENCE-OF: R-03922-41160 If the flags parameter is zero, the BLOB is # opened for read-only access. # foreach {tn iRow flags} { 1 1 0 2 2 1 3 3 -1 4 4 2147483647 5 5 -2147483648 } { do_test 3.$tn.1 { sqlite3_blob_open db main x1 c $iRow $flags B set n [sqlite3_blob_bytes $B] sqlite3_blob_read $B 0 $n } [binary format ccc 0 1 $iRow] if {$flags==0} { # Blob was opened for read-only access - writing returns an error. do_test 3.$tn.2 { list [catch { sqlite3_blob_write $B 0 xxx 3 } msg] $msg } {1 SQLITE_READONLY} do_execsql_test 3.$tn.3 { SELECT c FROM x1 WHERE a=$iRow; } [binary format ccc 0 1 $iRow] } else { # Blob was opened for read/write access - writing succeeds do_test 3.$tn.4 { list [catch { sqlite3_blob_write $B 0 xxx 3 } msg] $msg } {0 {}} do_execsql_test 3.$tn.5 { SELECT c FROM x1 WHERE a=$iRow; } {xxx} } sqlite3_blob_close $B } #------------------------------------------------------------------------- # reset_db do_execsql_test 4.0 { CREATE TABLE t1(x, y); INSERT INTO t1 VALUES('abcd', 152); INSERT INTO t1 VALUES(NULL, X'00010203'); INSERT INTO t1 VALUES('', 154.2); CREATE TABLE t2(x PRIMARY KEY, y) WITHOUT ROWID; INSERT INTO t2 VALUES(1, 'blob'); CREATE TABLE t3(a PRIMARY KEY, b, c, d, e, f, UNIQUE(e, f)); INSERT INTO t3 VALUES('aaaa', 'bbbb', 'cccc', 'dddd', 'eeee', 'ffff'); CREATE INDEX t3b ON t3(b); CREATE TABLE p1(x PRIMARY KEY); INSERT INTO p1 VALUES('abc'); CREATE TABLE c1(a INTEGER PRIMARY KEY, b REFERENCES p1); INSERT INTO c1 VALUES(45, 'abc'); } proc test_blob_open {tn zDb zTab zCol iRow flags errcode errmsg} { global B set B "0x1234" if {$errcode=="SQLITE_OK"} { set expected "0 {}" } else { set expected "1 $errcode" } set ::res [list [ catch { sqlite3_blob_open db $zDb $zTab $zCol $iRow $flags B } msg ] $msg] do_test 4.$tn.1 { set ::res } $expected # EVIDENCE-OF: R-08940-21305 Unless it returns SQLITE_MISUSE, this # function sets the database connection error code and message # accessible via sqlite3_errcode() and sqlite3_errmsg() and related # functions. # # This proc (test_blob_open) is used below to test various error and # non-error conditions. But never SQLITE_MISUSE conditions. So these # test cases are considered as partly verifying the requirement above. # See below for a test of the SQLITE_MISUSE case. # do_test 4.$tn.2 { sqlite3_errcode db } $errcode do_test 4.$tn.3 { sqlite3_errmsg db } $errmsg # EVIDENCE-OF: R-31086-35521 On success, SQLITE_OK is returned and the # new BLOB handle is stored in *ppBlob. Otherwise an error code is # returned and, unless the error code is SQLITE_MISUSE, *ppBlob is set # to NULL. # do_test 4.$tn.4 { expr {$B == "0"} } [expr {$errcode != "SQLITE_OK"}] # EVIDENCE-OF: R-63421-15521 This means that, provided the API is not # misused, it is always safe to call sqlite3_blob_close() on *ppBlob # after this function it returns. do_test 4.$tn.5 { sqlite3_blob_close $B } {} } # EVIDENCE-OF: R-31204-44780 Database zDb does not exist test_blob_open 1 nosuchdb t1 x 1 0 SQLITE_ERROR "no such table: nosuchdb.t1" # EVIDENCE-OF: R-28676-08005 Table zTable does not exist within database zDb test_blob_open 2 main tt1 x 1 0 SQLITE_ERROR "no such table: main.tt1" # EVIDENCE-OF: R-40134-30296 Table zTable is a WITHOUT ROWID table test_blob_open 3 main t2 y 1 0 SQLITE_ERROR \ "cannot open table without rowid: t2" # EVIDENCE-OF: R-56376-21261 Column zColumn does not exist test_blob_open 4 main t1 z 2 0 SQLITE_ERROR "no such column: \"z\"" # EVIDENCE-OF: R-28258-23166 Row iRow is not present in the table test_blob_open 5 main t1 y 6 0 SQLITE_ERROR "no such rowid: 6" # EVIDENCE-OF: R-11683-62380 The specified column of row iRow contains a # value that is not a TEXT or BLOB value test_blob_open 6 main t1 x 2 0 SQLITE_ERROR "cannot open value of type null" test_blob_open 7 main t1 y 1 0 SQLITE_ERROR "cannot open value of type integer" test_blob_open 8 main t1 y 3 0 SQLITE_ERROR "cannot open value of type real" # EVIDENCE-OF: R-34146-30782 Column zColumn is part of an index, PRIMARY # KEY or UNIQUE constraint and the blob is being opened for read/write # access # # Test cases 8.1.* show that such columns can be opened for read-access. # Tests 8.2.* show that read-write access is different. Columns "c" and "c" # are not part of an index, PK or UNIQUE constraint, so they work in both # cases. # test_blob_open 8.1.1 main t3 a 1 0 SQLITE_OK "not an error" test_blob_open 8.1.2 main t3 b 1 0 SQLITE_OK "not an error" test_blob_open 8.1.3 main t3 c 1 0 SQLITE_OK "not an error" test_blob_open 8.1.4 main t3 d 1 0 SQLITE_OK "not an error" test_blob_open 8.1.5 main t3 e 1 0 SQLITE_OK "not an error" test_blob_open 8.1.6 main t3 f 1 0 SQLITE_OK "not an error" set cannot "cannot open indexed column for writing" test_blob_open 8.2.1 main t3 a 1 8 SQLITE_ERROR $cannot test_blob_open 8.2.2 main t3 b 1 8 SQLITE_ERROR $cannot test_blob_open 8.2.3 main t3 c 1 8 SQLITE_OK "not an error" test_blob_open 8.2.4 main t3 d 1 8 SQLITE_OK "not an error" test_blob_open 8.2.5 main t3 e 1 8 SQLITE_ERROR $cannot test_blob_open 8.2.6 main t3 f 1 8 SQLITE_ERROR $cannot # EVIDENCE-OF: R-50117-55204 Foreign key constraints are enabled, column # zColumn is part of a child key definition and the blob is being opened # for read/write access # # 9.1: FK disabled, read-only access. # 9.2: FK disabled, read-only access. # 9.3: FK enabled, read/write access. # 9.4: FK enabled, read/write access. # test_blob_open 9.1 main c1 b 45 0 SQLITE_OK "not an error" test_blob_open 9.2 main c1 b 45 1 SQLITE_OK "not an error" execsql { PRAGMA foreign_keys = ON } test_blob_open 9.3 main c1 b 45 0 SQLITE_OK "not an error" test_blob_open 9.4 main c1 b 45 1 SQLITE_ERROR \ "cannot open foreign key column for writing" #------------------------------------------------------------------------- # EVIDENCE-OF: R-08940-21305 Unless it returns SQLITE_MISUSE, this # function sets the database connection error code and message # accessible via sqlite3_errcode() and sqlite3_errmsg() and related # functions. # # This requirement is partially verified by the many uses of test # command [test_blob_open] above. All that is left is to verify the # SQLITE_MISUSE case. # # SQLITE_MISUSE is only returned if SQLITE_ENABLE_API_ARMOR is defined # during compilation. # ifcapable api_armor { sqlite3_blob_open db main t1 x 1 0 B do_test 10.1.1 { list [catch {sqlite3_blob_open $B main t1 x 1 0 B2} msg] $msg } {1 SQLITE_MISUSE} do_test 10.1.2 { list [sqlite3_errcode db] [sqlite3_errmsg db] } {SQLITE_OK {not an error}} sqlite3_blob_close $B do_test 10.2.1 { list [catch {sqlite3_blob_open db main {} x 1 0 B} msg] $msg } {1 SQLITE_MISUSE} do_test 10.2.2 { list [sqlite3_errcode db] [sqlite3_errmsg db] } {SQLITE_OK {not an error}} } #------------------------------------------------------------------------- # EVIDENCE-OF: R-50542-62589 If the row that a BLOB handle points to is # modified by an UPDATE, DELETE, or by ON CONFLICT side-effects then the # BLOB handle is marked as "expired". This is true if any column of the # row is changed, even a column other than the one the BLOB handle is # open on. # # EVIDENCE-OF: R-48367-20048 Calls to sqlite3_blob_read() and # sqlite3_blob_write() for an expired BLOB handle fail with a return # code of SQLITE_ABORT. # # 11.2: read-only handle, DELETE. # 11.3: read-only handle, UPDATE. # 11.4: read-only handle, REPLACE. # 11.5: read/write handle, DELETE. # 11.6: read/write handle, UPDATE. # 11.7: read/write handle, REPLACE. # do_execsql_test 11.1 { CREATE TABLE b1(a INTEGER PRIMARY KEY, b, c UNIQUE); INSERT INTO b1 VALUES(1, '1234567890', 1); INSERT INTO b1 VALUES(2, '1234567890', 2); INSERT INTO b1 VALUES(3, '1234567890', 3); INSERT INTO b1 VALUES(4, '1234567890', 4); INSERT INTO b1 VALUES(5, '1234567890', 5); INSERT INTO b1 VALUES(6, '1234567890', 6); CREATE TABLE b2(a INTEGER PRIMARY KEY, b, c UNIQUE); INSERT INTO b2 VALUES(1, '1234567890', 1); INSERT INTO b2 VALUES(2, '1234567890', 2); INSERT INTO b2 VALUES(3, '1234567890', 3); INSERT INTO b2 VALUES(4, '1234567890', 4); INSERT INTO b2 VALUES(5, '1234567890', 5); INSERT INTO b2 VALUES(6, '1234567890', 6); } do_test 11.2.1 { sqlite3_blob_open db main b1 b 2 0 B sqlite3_blob_read $B 0 10 } {1234567890} do_test 11.2.2 { # Deleting a different row does not invalidate the blob handle. execsql { DELETE FROM b1 WHERE a = 1 } sqlite3_blob_read $B 0 10 } {1234567890} do_test 11.2.3 { execsql { DELETE FROM b1 WHERE a = 2 } list [catch { sqlite3_blob_read $B 0 10 } msg] $msg } {1 SQLITE_ABORT} do_test 11.2.4 { sqlite3_blob_close $B } {} do_test 11.3.1 { sqlite3_blob_open db main b1 b 3 0 B sqlite3_blob_read $B 0 10 } {1234567890} do_test 11.3.2 { # Updating a different row execsql { UPDATE b1 SET c = 42 WHERE a=4 } sqlite3_blob_read $B 0 10 } {1234567890} do_test 11.3.3 { execsql { UPDATE b1 SET c = 43 WHERE a=3 } list [catch { sqlite3_blob_read $B 0 10 } msg] $msg } {1 SQLITE_ABORT} do_test 11.3.4 { sqlite3_blob_close $B } {} do_test 11.4.1 { sqlite3_blob_open db main b1 b 6 0 B sqlite3_blob_read $B 0 10 } {1234567890} do_test 11.4.2 { # Replace a different row execsql { INSERT OR REPLACE INTO b1 VALUES(10, 'abcdefghij', 5) } sqlite3_blob_read $B 0 10 } {1234567890} do_test 11.4.3 { execsql { INSERT OR REPLACE INTO b1 VALUES(11, 'abcdefghij', 6) } list [catch { sqlite3_blob_read $B 0 10 } msg] $msg } {1 SQLITE_ABORT} do_test 11.4.4 { sqlite3_blob_close $B } {} do_test 11.4.1 { sqlite3_blob_open db main b2 b 2 1 B sqlite3_blob_write $B 0 "abcdefghij" } {} do_test 11.4.2 { # Deleting a different row does not invalidate the blob handle. execsql { DELETE FROM b2 WHERE a = 1 } sqlite3_blob_write $B 0 "ABCDEFGHIJ" } {} do_test 11.4.3 { execsql { DELETE FROM b2 WHERE a = 2 } list [catch { sqlite3_blob_write $B 0 "0987654321" } msg] $msg } {1 SQLITE_ABORT} do_test 11.4.4 { sqlite3_blob_close $B } {} do_test 11.5.1 { sqlite3_blob_open db main b2 b 3 1 B sqlite3_blob_write $B 0 "abcdefghij" } {} do_test 11.5.2 { # Updating a different row execsql { UPDATE b2 SET c = 42 WHERE a=4 } sqlite3_blob_write $B 0 "ABCDEFGHIJ" } {} do_test 11.5.3 { execsql { UPDATE b2 SET c = 43 WHERE a=3 } list [catch { sqlite3_blob_write $B 0 "0987654321" } msg] $msg } {1 SQLITE_ABORT} do_test 11.5.4 { sqlite3_blob_close $B } {} do_test 11.6.1 { sqlite3_blob_open db main b2 b 6 1 B sqlite3_blob_write $B 0 "abcdefghij" } {} do_test 11.6.2 { # Replace a different row execsql { INSERT OR REPLACE INTO b2 VALUES(10, 'abcdefghij', 5) } sqlite3_blob_write $B 0 "ABCDEFGHIJ" } {} do_test 11.6.3 { execsql { INSERT OR REPLACE INTO b2 VALUES(11, 'abcdefghij', 6) } list [catch { sqlite3_blob_write $B 0 "0987654321" } msg] $msg } {1 SQLITE_ABORT} do_test 11.6.4 { sqlite3_blob_close $B } {} #------------------------------------------------------------------------- # EVIDENCE-OF: R-45408-40694 Changes written into a BLOB prior to the # BLOB expiring are not rolled back by the expiration of the BLOB. Such # changes will eventually commit if the transaction continues to # completion. # do_execsql_test 12.1 { CREATE TABLE b3(x INTEGER PRIMARY KEY, y TEXT, z INTEGER); INSERT INTO b3 VALUES(22, '..........', NULL); } do_test 12.2 { sqlite3_blob_open db main b3 y 22 1 B sqlite3_blob_write $B 0 "xxxxx" 5 } {} do_execsql_test 12.3 { UPDATE b3 SET z = 'not null'; } do_test 12.4 { list [catch {sqlite3_blob_write $B 5 "xxxxx" 5} msg] $msg } {1 SQLITE_ABORT} do_execsql_test 12.5 { SELECT * FROM b3; } {22 xxxxx..... {not null}} do_test 12.5 { sqlite3_blob_close $B } {} do_execsql_test 12.6 { SELECT * FROM b3; } {22 xxxxx..... {not null}} #------------------------------------------------------------------------- # EVIDENCE-OF: R-58813-55036 The sqlite3_bind_zeroblob() and # sqlite3_result_zeroblob() interfaces and the built-in zeroblob SQL # function may be used to create a zero-filled blob to read or write # using the incremental-blob interface. # do_execsql_test 13.1 { CREATE TABLE c2(i INTEGER PRIMARY KEY, j); INSERT INTO c2 VALUES(10, zeroblob(24)); } do_test 13.2 { set stmt [sqlite3_prepare_v2 db "INSERT INTO c2 VALUES(11, ?)" -1] sqlite3_bind_zeroblob $stmt 1 45 sqlite3_step $stmt sqlite3_finalize $stmt } {SQLITE_OK} # The blobs can be read: # do_test 13.3.1 { sqlite3_blob_open db main c2 j 10 1 B sqlite3_blob_open db main c2 j 11 1 B2 list [sqlite3_blob_bytes $B] [sqlite3_blob_bytes $B2] } {24 45} do_test 13.3.2 { sqlite3_blob_read $B 0 24 } [string repeat [binary format c 0] 24] do_test 13.3.3 { sqlite3_blob_read $B2 0 45 } [string repeat [binary format c 0] 45] # And also written: # do_test 13.4.1 { sqlite3_blob_write $B 0 [string repeat [binary format c 1] 24] } {} do_test 13.4.2 { sqlite3_blob_write $B2 0 [string repeat [binary format c 1] 45] } {} do_test 13.5 { sqlite3_blob_close $B sqlite3_blob_close $B2 execsql { SELECT j FROM c2 } } [list \ [string repeat [binary format c 1] 24] \ [string repeat [binary format c 1] 45] \ ] finish_test |
Added test/e_blobwrite.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 107 108 109 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 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 199 200 201 202 203 204 | # 2014 October 30 # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix e_blobwrite #-------------------------------------------------------------------------- # EVIDENCE-OF: R-62898-22698 This function is used to write data into an # open BLOB handle from a caller-supplied buffer. N bytes of data are # copied from the buffer Z into the open BLOB, starting at offset # iOffset. # set dots [string repeat . 40] do_execsql_test 1.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, t TEXT); INSERT INTO t1 VALUES(-1, $dots); INSERT INTO t1 VALUES(-2, $dots); INSERT INTO t1 VALUES(-3, $dots); INSERT INTO t1 VALUES(-4, $dots); INSERT INTO t1 VALUES(-5, $dots); INSERT INTO t1 VALUES(-6, $dots); } proc blob_write_test {tn id iOffset blob nData final} { sqlite3_blob_open db main t1 t $id 1 B # EVIDENCE-OF: R-45864-01884 On success, sqlite3_blob_write() returns # SQLITE_OK. Otherwise, an error code or an extended error code is # returned. # # This block tests the SQLITE_OK case in the requirement above (the # Tcl sqlite3_blob_write() wrapper uses an empty string in place of # "SQLITE_OK"). The error cases are tested by the "blob_write_error_test" # tests below. # set res [sqlite3_blob_write $B $iOffset $blob $nData] uplevel [list do_test $tn.1 [list set {} $res] {}] sqlite3_blob_close $B uplevel [list do_execsql_test $tn.3 "SELECT t FROM t1 WHERE a=$id" $final] } set blob "0123456789012345678901234567890123456789" blob_write_test 1.1 -1 0 $blob 10 { 0123456789.............................. } blob_write_test 1.2 -2 8 $blob 10 { ........0123456789...................... } blob_write_test 1.3 -3 8 $blob 1 { ........0............................... } blob_write_test 1.4 -4 18 $blob 22 { ..................0123456789012345678901 } blob_write_test 1.5 -5 18 $blob 0 { ........................................ } blob_write_test 1.6 -6 0 $blob 40 { 0123456789012345678901234567890123456789 } proc blob_write_error_test {tn B iOffset blob nData errcode errmsg} { # In cases where the underlying sqlite3_blob_write() function returns # SQLITE_OK, the Tcl wrapper returns an empty string. If the underlying # function returns an error, the Tcl wrapper throws an exception with # the error code as the Tcl exception message. # if {$errcode=="SQLITE_OK"} { set ret "" set isError 0 } else { set ret $errcode set isError 1 } set cmd [list sqlite3_blob_write $B $iOffset $blob $nData] uplevel [list do_test $tn.1 [subst -nocommands { list [catch {$cmd} msg] [set msg] }] [list $isError $ret]] # EVIDENCE-OF: R-34782-18311 Unless SQLITE_MISUSE is returned, this # function sets the database connection error code and message # accessible via sqlite3_errcode() and sqlite3_errmsg() and related # functions. # if {$errcode == "SQLITE_MISUSE"} { error "test proc misuse!" } uplevel [list do_test $tn.2 [list sqlite3_errcode db] $errcode] uplevel [list do_test $tn.3 [list sqlite3_errmsg db] $errmsg] } do_execsql_test 2.0 { CREATE TABLE t2(a TEXT, b INTEGER PRIMARY KEY); INSERT INTO t2 VALUES($dots, 43); INSERT INTO t2 VALUES($dots, 44); INSERT INTO t2 VALUES($dots, 45); } # EVIDENCE-OF: R-63341-57517 If the BLOB handle passed as the first # argument was not opened for writing (the flags parameter to # sqlite3_blob_open() was zero), this function returns SQLITE_READONLY. # sqlite3_blob_open db main t2 a 43 0 B blob_write_error_test 2.1 $B 0 $blob 10 \ SQLITE_READONLY {attempt to write a readonly database} sqlite3_blob_close $B # EVIDENCE-OF: R-29804-27366 If offset iOffset is less than N bytes from # the end of the BLOB, SQLITE_ERROR is returned and no data is written. # sqlite3_blob_open db main t2 a 44 3 B blob_write_error_test 2.2.1 $B 31 $blob 10 \ SQLITE_ERROR {SQL logic error or missing database} # Make a successful write to the blob handle. This shows that the # sqlite3_errcode() and sqlite3_errmsg() values are set even if the # blob_write() call succeeds (see requirement in the [blob_write_error_test] # proc). blob_write_error_test 2.2.1 $B 30 $blob 10 SQLITE_OK {not an error} # EVIDENCE-OF: R-58570-38916 If N or iOffset are less than zero # SQLITE_ERROR is returned and no data is written. # blob_write_error_test 2.2.2 $B 31 $blob -1 \ SQLITE_ERROR {SQL logic error or missing database} blob_write_error_test 2.2.3 $B 20 $blob 10 SQLITE_OK {not an error} blob_write_error_test 2.2.4 $B -1 $blob 10 \ SQLITE_ERROR {SQL logic error or missing database} sqlite3_blob_close $B # EVIDENCE-OF: R-20958-54138 An attempt to write to an expired BLOB # handle fails with an error code of SQLITE_ABORT. # do_test 2.3 { sqlite3_blob_open db main t2 a 43 0 B execsql { DELETE FROM t2 WHERE b=43 } } {} blob_write_error_test 2.3.1 $B 5 $blob 5 \ SQLITE_ABORT {callback requested query abort} do_test 2.3.2 { execsql { SELECT 1, 2, 3 } sqlite3_errcode db } {SQLITE_OK} blob_write_error_test 2.3.3 $B 5 $blob 5 \ SQLITE_ABORT {callback requested query abort} sqlite3_blob_close $B # EVIDENCE-OF: R-08382-59936 Writes to the BLOB that occurred before the # BLOB handle expired are not rolled back by the expiration of the # handle, though of course those changes might have been overwritten by # the statement that expired the BLOB handle or by other independent # statements. # # 3.1.*: not rolled back, # 3.2.*: overwritten. # do_execsql_test 3.0 { CREATE TABLE t3(i INTEGER PRIMARY KEY, j TEXT, k TEXT); INSERT INTO t3 VALUES(1, $dots, $dots); INSERT INTO t3 VALUES(2, $dots, $dots); SELECT * FROM t3 WHERE i=1; } { 1 ........................................ ........................................ } sqlite3_blob_open db main t3 j 1 1 B blob_write_error_test 3.1.1 $B 5 $blob 10 SQLITE_OK {not an error} do_execsql_test 3.1.2 { UPDATE t3 SET k = 'xyz' WHERE i=1; SELECT * FROM t3 WHERE i=1; } { 1 .....0123456789......................... xyz } blob_write_error_test 3.1.3 $B 15 $blob 10 \ SQLITE_ABORT {callback requested query abort} sqlite3_blob_close $B do_execsql_test 3.1.4 { SELECT * FROM t3 WHERE i=1; } { 1 .....0123456789......................... xyz } sqlite3_blob_open db main t3 j 2 1 B blob_write_error_test 3.2.1 $B 5 $blob 10 SQLITE_OK {not an error} do_execsql_test 3.2.2 { UPDATE t3 SET j = 'xyz' WHERE i=2; SELECT * FROM t3 WHERE i=2; } { 2 xyz ........................................ } blob_write_error_test 3.2.3 $B 15 $blob 10 \ SQLITE_ABORT {callback requested query abort} sqlite3_blob_close $B do_execsql_test 3.2.4 { SELECT * FROM t3 WHERE i=2; } { 2 xyz ........................................ } finish_test |
Changes to test/fkey7.test.
︙ | ︙ | |||
46 47 48 49 50 51 52 53 54 | } do_tblsread_test 1.2 { UPDATE par SET b=? WHERE a=? } {par s1} do_tblsread_test 1.3 { UPDATE par SET a=? WHERE b=? } {c1 c2 par} do_tblsread_test 1.4 { UPDATE par SET c=? WHERE b=? } {c3 par} do_tblsread_test 1.5 { UPDATE par SET a=?,b=?,c=? WHERE b=? } {c1 c2 c3 par s1} finish_test | > > > > > > > > > > > > > > > > > | 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 | } do_tblsread_test 1.2 { UPDATE par SET b=? WHERE a=? } {par s1} do_tblsread_test 1.3 { UPDATE par SET a=? WHERE b=? } {c1 c2 par} do_tblsread_test 1.4 { UPDATE par SET c=? WHERE b=? } {c3 par} do_tblsread_test 1.5 { UPDATE par SET a=?,b=?,c=? WHERE b=? } {c1 c2 c3 par s1} ifcapable incrblob { do_execsql_test 2.0 { CREATE TABLE pX(x PRIMARY KEY); CREATE TABLE cX(a INTEGER PRIMARY KEY, b REFERENCES pX); } do_catchsql_test 2.1 { INSERT INTO cX VALUES(11, zeroblob(40)); } {1 {FOREIGN KEY constraint failed}} do_test 2.2 { set stmt [sqlite3_prepare_v2 db "INSERT INTO cX VALUES(11, ?)" -1] sqlite3_bind_zeroblob $stmt 1 45 sqlite3_step $stmt sqlite3_finalize $stmt } {SQLITE_CONSTRAINT} } finish_test |
Changes to test/in5.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl do_test in5-1.1 { execsql { CREATE TABLE t1x(x INTEGER PRIMARY KEY); INSERT INTO t1x VALUES(1),(3),(5),(7),(9); CREATE TABLE t1y(y INTEGER UNIQUE); INSERT INTO t1y VALUES(2),(4),(6),(8); | > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix in5 do_test in5-1.1 { execsql { CREATE TABLE t1x(x INTEGER PRIMARY KEY); INSERT INTO t1x VALUES(1),(3),(5),(7),(9); CREATE TABLE t1y(y INTEGER UNIQUE); INSERT INTO t1y VALUES(2),(4),(6),(8); |
︙ | ︙ | |||
130 131 132 133 134 135 136 137 138 | } } {23g} do_test in5-5.3 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z }] } {0} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | } } {23g} do_test in5-5.3 { regexp {OpenEphemeral} [db eval { EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z }] } {0} #------------------------------------------------------------------------- # At one point SQLite was removing the DISTINCT keyword from expressions # similar to: # # <expr1> IN (SELECT DISTINCT <expr2> FROM...) # # However, there are a few obscure cases where this is incorrect. For # example, if the SELECT features a LIMIT clause, or if the collation # sequence or affinity used by the DISTINCT does not match the one used # by the IN(...) expression. # do_execsql_test 6.1.1 { CREATE TABLE t1(a COLLATE nocase); INSERT INTO t1 VALUES('one'); INSERT INTO t1 VALUES('ONE'); } do_execsql_test 6.1.2 { SELECT count(*) FROM t1 WHERE a COLLATE BINARY IN (SELECT DISTINCT a FROM t1) } {1} do_execsql_test 6.2.1 { CREATE TABLE t3(a, b); INSERT INTO t3 VALUES(1, 1); INSERT INTO t3 VALUES(1, 2); INSERT INTO t3 VALUES(1, 3); INSERT INTO t3 VALUES(2, 4); INSERT INTO t3 VALUES(2, 5); INSERT INTO t3 VALUES(2, 6); INSERT INTO t3 VALUES(3, 7); INSERT INTO t3 VALUES(3, 8); INSERT INTO t3 VALUES(3, 9); } do_execsql_test 6.2.2 { SELECT count(*) FROM t3 WHERE b IN (SELECT DISTINCT a FROM t3 LIMIT 5); } {3} do_execsql_test 6.2.3 { SELECT count(*) FROM t3 WHERE b IN (SELECT a FROM t3 LIMIT 5); } {2} do_execsql_test 6.3.1 { CREATE TABLE x1(a); CREATE TABLE x2(b); INSERT INTO x1 VALUES(1), (1), (2); INSERT INTO x2 VALUES(1), (2); SELECT count(*) FROM x2 WHERE b IN (SELECT DISTINCT a FROM x1 LIMIT 2); } {2} finish_test |
Changes to test/ioerr2.test.
︙ | ︙ | |||
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | set ::sqlite_io_error_pending $::N foreach {::go res} [catchsql $sql] {} check_db ioerr2-4.[expr {$bPersist+2}].$::N } } do_test ioerr2-5 { execsql { CREATE TABLE t2 AS SELECT * FROM t1; PRAGMA temp_store = memory; } set ::sqlite_io_error_persist 0 set ::go 1 set rc [catch { for {set ::N 2} {$::N<200} {incr ::N} { db eval {SELECT * FROM t1 WHERE rowid IN (1, 5, 10, 15, 20)} { set ::sqlite_io_error_hit 0 set ::sqlite_io_error_pending $::N set sql {UPDATE t2 SET b = randstr(400,400)} foreach {::go res} [catchsql $sql] {} } } } msg] list $rc $msg | > > > > > > | | 108 109 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 143 144 145 146 | set ::sqlite_io_error_pending $::N foreach {::go res} [catchsql $sql] {} check_db ioerr2-4.[expr {$bPersist+2}].$::N } } # When this test was written, an IO error within the UPDATE statement caused # a rollback, which tripped all read-cursors, causing the outer SELECT to # fail with "abort due to ROLLBACK". Now, the loop continues until the UPDATE # is run successfully. At this point the next IO error occurs within the # SELECT - throwing the "disk I/O error" that the test case now expects. # do_test ioerr2-5 { execsql { CREATE TABLE t2 AS SELECT * FROM t1; PRAGMA temp_store = memory; } set ::sqlite_io_error_persist 0 set ::go 1 set rc [catch { for {set ::N 2} {$::N<200} {incr ::N} { db eval {SELECT * FROM t1 WHERE rowid IN (1, 5, 10, 15, 20)} { set ::sqlite_io_error_hit 0 set ::sqlite_io_error_pending $::N set sql {UPDATE t2 SET b = randstr(400,400)} foreach {::go res} [catchsql $sql] {} } } } msg] list $rc $msg } {1 {disk I/O error}} ;# used to be "{1 {abort due to ROLLBACK}}" if {$::tcl_platform(platform) == "unix"} { # Cause the call to xAccess used by [pragma temp_store_directory] to # determine if the specified directory is writable to fail. This causes # SQLite to report "not a writable directory", which is probably the # right answer. # |
︙ | ︙ |
Added test/misc8.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 | # 2014-11-10 # # 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 file implements regression tests for SQLite library. # The focus of this script is testing the "eval.c" loadable extension. # set testdir [file dirname $argv0] source $testdir/tester.tcl load_static_extension db eval do_execsql_test misc8-1.0 { CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3),(4,5,6); SELECT quote(eval('SELECT * FROM t1 ORDER BY a','-abc-')); } {'1-abc-2-abc-3-abc-4-abc-5-abc-6'} do_execsql_test misc8-1.1 { SELECT quote(eval('SELECT * FROM t1 ORDER BY a')); } {{'1 2 3 4 5 6'}} do_catchsql_test misc8-1.2 { SELECT quote(eval('SELECT d FROM t1 ORDER BY a')); } {1 {no such column: d}} do_execsql_test misc8-1.3 { INSERT INTO t1 VALUES(7,null,9); SELECT eval('SELECT * FROM t1 ORDER BY a',','); } {1,2,3,4,5,6,7,,9} do_catchsql_test misc8-1.4 { BEGIN; INSERT INTO t1 VALUES(10,11,12); SELECT a, coalesce(b, eval('ROLLBACK; SELECT ''bam'';')), c FROM t1 ORDER BY a; } {0 {1 2 3 4 5 6 7 bam 9}} do_catchsql_test misc8-1.5 { INSERT INTO t1 VALUES(10,11,12); SELECT a, coalesce(b, eval('SELECT ''bam''')), c FROM t1 ORDER BY rowid; } {0 {1 2 3 4 5 6 7 bam 9 10 11 12}} do_catchsql_test misc8-1.6 { SELECT a, coalesce(b, eval('DELETE FROM t1; SELECT ''bam''')), c FROM t1 ORDER BY rowid; } {0 {1 2 3 4 5 6 7 bam {}}} do_catchsql_test misc8-1.7 { INSERT INTO t1 VALUES(1,2,3),(4,5,6),(7,null,9); BEGIN; CREATE TABLE t2(x); SELECT a, coalesce(b, eval('ROLLBACK; SELECT ''bam''')), c FROM t1 ORDER BY rowid; } {1 {abort due to ROLLBACK}} reset_db proc dbeval {sql} { db eval $sql } db func eval dbeval do_execsql_test misc8-2.1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER) WITHOUT ROWID; CREATE TABLE t2(c INTEGER PRIMARY KEY, d INTEGER, x BLOB); INSERT INTO t1 VALUES(0,0); INSERT INTO t1 VALUES(10,10); INSERT INTO t2 VALUES(1,1,zeroblob(200)); INSERT INTO t2 VALUES(2,2,zeroblob(200)); INSERT INTO t2 VALUES(3,3,zeroblob(200)); INSERT INTO t2 VALUES(4,4,zeroblob(200)); INSERT INTO t2 VALUES(5,5,zeroblob(200)); INSERT INTO t2 VALUES(6,6,zeroblob(200)); INSERT INTO t2 VALUES(7,7,zeroblob(200)); INSERT INTO t2 VALUES(8,8,zeroblob(200)); INSERT INTO t2 VALUES(9,9,zeroblob(200)); INSERT INTO t2 VALUES(10,10,zeroblob(200)); SELECT a, c, eval( printf('DELETE FROM t2 WHERE c=%d AND %d>5', a+c, a+c) ) FROM t1, t2; } { 0 1 {} 10 1 {} 0 2 {} 10 2 {} 0 3 {} 10 3 {} 0 4 {} 10 4 {} 0 5 {} 10 5 {} 0 6 {} 10 {} {} 0 7 {} 10 {} {} 0 8 {} 10 {} {} 0 9 {} 10 {} {} 0 10 {} 10 {} {} } finish_test |
Changes to test/mmap1.test.
︙ | ︙ | |||
29 30 31 32 33 34 35 | } proc register_rblob_code {dbname seed} { return [subst -nocommands { set ::rcnt $seed proc rblob {n} { set ::rcnt [expr (([set ::rcnt] << 3) + [set ::rcnt] + 456) & 0xFFFFFFFF] | | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | } proc register_rblob_code {dbname seed} { return [subst -nocommands { set ::rcnt $seed proc rblob {n} { set ::rcnt [expr (([set ::rcnt] << 3) + [set ::rcnt] + 456) & 0xFFFFFFFF] set str [format %.8x [expr [set ::rcnt] ^ 0xbdf20da3]] string range [string repeat [set str] [expr [set n]/4]] 1 [set n] } $dbname func rblob rblob }] } # For cases 1.1 and 1.4, the number of pages read using xRead() is 4 on # unix and 9 on windows. The difference is that windows only ever maps # an integer number of OS pages (i.e. creates mappings that are a multiple # of 4KB in size). Whereas on unix any sized mapping may be created. # foreach {t mmap_size nRead c2init} { 1.1 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 0} 1.2 { PRAGMA mmap_size = 53248 } 150 {PRAGMA mmap_size = 0} 1.3 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = 0} 1.4 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 67108864 } |
︙ | ︙ | |||
102 103 104 105 106 107 108 | do_test $t.$tn.5 { nRead db } $nRead } } set ::rcnt 0 proc rblob {n} { set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF] | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 102 103 104 105 106 107 108 109 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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | do_test $t.$tn.5 { nRead db } $nRead } } set ::rcnt 0 proc rblob {n} { set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF] set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]] string range [string repeat $str [expr $n/4]] 1 $n } reset_db db func rblob rblob ifcapable wal { do_execsql_test 2.1 { PRAGMA auto_vacuum = 1; PRAGMA mmap_size = 67108864; PRAGMA journal_mode = wal; CREATE TABLE t1(a, b, UNIQUE(a, b)); INSERT INTO t1 VALUES(rblob(500), rblob(500)); INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 2 INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 4 INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 8 INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 16 INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 32 PRAGMA wal_checkpoint; } {67108864 wal 0 103 103} do_execsql_test 2.2 { PRAGMA auto_vacuum; SELECT count(*) FROM t1; } {1 32} if {[permutation] != "inmemory_journal"} { do_test 2.3 { sqlite3 db2 test.db db2 func rblob rblob db2 eval { DELETE FROM t1 WHERE (rowid%4); PRAGMA wal_checkpoint; } db2 eval { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 16 SELECT count(*) FROM t1; } } {16} do_execsql_test 2.4 { PRAGMA wal_checkpoint; } {0 24 24} db2 close } } reset_db execsql { PRAGMA mmap_size = 67108864; } db func rblob rblob do_execsql_test 3.1 { PRAGMA auto_vacuum = 1; |
︙ | ︙ | |||
223 224 225 226 227 228 229 | do_test 4.4 { sqlite3_finalize $::STMT } SQLITE_OK do_execsql_test 4.5 { COMMIT } #------------------------------------------------------------------------- | | | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | do_test 4.4 { sqlite3_finalize $::STMT } SQLITE_OK do_execsql_test 4.5 { COMMIT } #------------------------------------------------------------------------- # Ensure that existing cursors holding xFetch() references are not # confused if those pages are moved to make way for the root page of a # new table or index. # reset_db execsql { PRAGMA mmap_size = 67108864; } do_execsql_test 5.1 { PRAGMA auto_vacuum = 2; |
︙ | ︙ | |||
292 293 294 295 296 297 298 | code1 [register_rblob_code db 0] code2 [register_rblob_code db2 444] sql1 "PRAGMA mmap_size = $mmap1" sql2 "PRAGMA mmap_size = $mmap2" | | | | 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 | code1 [register_rblob_code db 0] code2 [register_rblob_code db2 444] sql1 "PRAGMA mmap_size = $mmap1" sql2 "PRAGMA mmap_size = $mmap2" do_test $tn1.$tn { for {set i 1} {$i <= 100} {incr i} { if {$i % 2} { set c1 sql1 set c2 sql2 } else { set c1 sql2 set c2 sql1 } $c1 { INSERT INTO t1 VALUES( rblob(5000) ); UPDATE t2 SET x = (SELECT md5sum(a) FROM t1); } set res [$c2 { SELECT count(*) FROM t1; SELECT x == (SELECT md5sum(a) FROM t1) FROM t2; PRAGMA integrity_check; }] if {$res != [list $i 1 ok]} { do_test $tn1.$tn.$i { set ::res |
︙ | ︙ |
Changes to test/rollback.test.
︙ | ︙ | |||
56 57 58 59 60 61 62 | } } {1 {UNIQUE constraint failed: t3.a}} # Try to continue with the SELECT statement # do_test rollback-1.5 { sqlite3_step $STMT | | | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | } } {1 {UNIQUE constraint failed: t3.a}} # Try to continue with the SELECT statement # do_test rollback-1.5 { sqlite3_step $STMT } {SQLITE_ROW} # Restart the SELECT statement # do_test rollback-1.6 { sqlite3_reset $STMT } {SQLITE_OK} } else { do_test rollback-1.6 { sqlite3_reset $STMT } {SQLITE_OK} } do_test rollback-1.7 { sqlite3_step $STMT } {SQLITE_ROW} |
︙ | ︙ |
Added test/rollback2.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 107 108 109 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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | # 2014 November 12 # # 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 file containst tests to verify that ROLLBACK or ROLLBACK TO # operations interact correctly with ongoing SELECT statements. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix rollback2 proc int2hex {i} { format %.2X $i } db func int2hex int2hex do_execsql_test 1.0 { SELECT int2hex(0), int2hex(100), int2hex(255) } {00 64 FF} do_execsql_test 1.1 { CREATE TABLE t1(i, h); CREATE INDEX i1 ON t1(h); WITH data(a, b) AS ( SELECT 1, int2hex(1) UNION ALL SELECT a+1, int2hex(a+1) FROM data WHERE a<40 ) INSERT INTO t1 SELECT * FROM data; } {} # do_rollback_test ID SWITCHES # # where SWITCHES are: # # -setup SQL script to open transaction and begin writing. # -select SELECT to execute after -setup script # -result Expected result of -select statement # -rollback Use this SQL command ("ROLLBACK" or "ROLLBACK TO ...") to # rollback the transaction in the middle of the -select statment # execution. # proc do_rollback_test {tn args} { set A(-setup) "" set A(-select) "" set A(-result) "" set A(-rollback) ROLLBACK array set O $args foreach k [array names O] { if {[info exists A($k)]==0} { error "unknown option: $k" } set A($k) $O($k) } for {set iRollback 0} 1 {incr iRollback} { catch { db eval ROLLBACK } set res [list] db eval $A(-setup) set i 0 db eval $A(-select) x { if {$i==$iRollback} { db eval $A(-rollback) } foreach k $x(*) { lappend res $x($k) } incr i } do_test $tn.$iRollback [list set {} $res] [list {*}$A(-result)] if {$i < $iRollback} break } } do_rollback_test 2.1 -setup { BEGIN; DELETE FROM t1 WHERE (i%2)==1; } -select { SELECT i FROM t1 WHERE (i%2)==0 } -result { 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 } do_rollback_test 2.2 -setup { BEGIN; DELETE FROM t1 WHERE (i%4)==1; SAVEPOINT one; DELETE FROM t1 WHERE (i%2)==1; } -rollback { ROLLBACK TO one; } -select { SELECT i FROM t1 WHERE (i%2)==0 } -result { 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 } #-------------------------------------------------------------------- # Try with some index scans # do_eqp_test 3.1 { SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC; } {0 0 0 {SCAN TABLE t1 USING INDEX i1}} do_rollback_test 3.2 -setup { BEGIN; DELETE FROM t1 WHERE (i%2)==1; } -select { SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC; } -result { 40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2 } do_rollback_test 3.3 -setup { BEGIN; DELETE FROM t1 WHERE (i%4)==1; SAVEPOINT one; DELETE FROM t1 WHERE (i%2)==1; } -rollback { ROLLBACK TO one; } -select { SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC; } -result { 40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2 } #-------------------------------------------------------------------- # Now with some index scans that feature overflow keys. # set leader [string repeat "abcdefghij" 70] do_execsql_test 4.1 { UPDATE t1 SET h = $leader || h; } do_eqp_test 4.2 { SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC; } {0 0 0 {SCAN TABLE t1 USING INDEX i1}} do_rollback_test 4.3 -setup { BEGIN; DELETE FROM t1 WHERE (i%2)==1; } -select { SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC; } -result { 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 } do_rollback_test 4.4 -setup { BEGIN; DELETE FROM t1 WHERE (i%4)==1; SAVEPOINT one; DELETE FROM t1 WHERE (i%2)==1; } -rollback { ROLLBACK TO one; } -select { SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC; } -result { 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 } finish_test |
Added test/rollbackfault.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 | # 2014-11-12 # # 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. # #*********************************************************************** # # Test that errors encountered during a ROLLBACK operation correctly # affect ongoing SQL statements. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl set testprefix rollbackfault proc int2hex {i} { format %.2X $i } db func int2hex int2hex do_execsql_test 1.0 { SELECT int2hex(0), int2hex(100), int2hex(255) } {00 64 FF} do_execsql_test 1.1 { CREATE TABLE t1(i, h); CREATE INDEX i1 ON t1(h); WITH data(a, b) AS ( SELECT 1, int2hex(1) UNION ALL SELECT a+1, int2hex(a+1) FROM data WHERE a<40 ) INSERT INTO t1 SELECT * FROM data; } {} foreach f {oom ioerr} { do_faultsim_test 1.2 -faults $f* -prep { set sql1 { SELECT i FROM t1 WHERE (i%2)==0 } set sql2 { SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h } set ::s1 [sqlite3_prepare db $sql1 -1 dummy] set ::s2 [sqlite3_prepare db $sql2 -1 dummy] for {set i 0} {$i < 10} {incr i} { sqlite3_step $::s1 } for {set i 0} {$i < 3} {incr i} { sqlite3_step $::s2 } execsql { BEGIN; DELETE FROM t1 WHERE (i%2) } } -body { execsql { ROLLBACK } } -test { set res1 [list] set res2 [list] while {"SQLITE_ROW" == [sqlite3_step $::s1]} { lappend res1 [sqlite3_column_text $::s1 0] } while {"SQLITE_ROW" == [sqlite3_step $::s2]} { lappend res2 [sqlite3_column_text $::s2 0] } set rc1 [sqlite3_finalize $::s1] set rc2 [sqlite3_finalize $::s2] catchsql { ROLLBACK } if {$rc1=="SQLITE_OK" && $rc2=="SQLITE_OK" && $res1=="22 24 26 28 30 32 34 36 38 40" && $res2=="8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40" } { # This is Ok. } elseif {$rc1!="SQLITE_OK" && $rc2!="SQLITE_OK" && $res1=="" &&$res2==""} { # Also Ok. } else { error "statements don't look right" } } } finish_test |
Changes to test/savepoint.test.
︙ | ︙ | |||
311 312 313 314 315 316 317 | } {0 {hellontyeight character blob}} do_test savepoint-5.3.2.2 { catchsql {ROLLBACK TO def} } {0 {}} do_test savepoint-5.3.2.3 { set rc [catch {seek $fd 0; read $fd} res] set rc | | | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | } {0 {hellontyeight character blob}} do_test savepoint-5.3.2.2 { catchsql {ROLLBACK TO def} } {0 {}} do_test savepoint-5.3.2.3 { set rc [catch {seek $fd 0; read $fd} res] set rc } {0} do_test savepoint-5.3.3 { catchsql {RELEASE def} } {0 {}} do_test savepoint-5.3.4 { close $fd execsql {savepoint def} set fd [db incrblob blobs x 1] |
︙ | ︙ |
Changes to test/savepoint7.test.
︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | INSERT INTO t1 VALUES(4,5,6); INSERT INTO t1 VALUES(7,8,9); SAVEPOINT x1; } db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); RELEASE x2; } } db eval {SELECT * FROM t2; RELEASE x1} } {1 2 3 4 5 6 7 8 9} do_test savepoint7-1.2 { db eval {DELETE FROM t2;} db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); RELEASE x2; } } | > | | | > | | 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 | INSERT INTO t1 VALUES(4,5,6); INSERT INTO t1 VALUES(7,8,9); SAVEPOINT x1; } db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; CREATE TABLE IF NOT EXISTS t3(xyz); INSERT INTO t2 VALUES($a,$b,$c); RELEASE x2; } } db eval {SELECT * FROM t2; RELEASE x1} } {1 2 3 4 5 6 7 8 9} do_test savepoint7-1.2 { db eval {DELETE FROM t2;} db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); RELEASE x2; } } db eval {SELECT * FROM t2;} } {1 2 3 4 5 6 7 8 9} do_test savepoint7-1.3 { db eval {DELETE FROM t2; BEGIN;} db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); RELEASE x2; } } db eval {SELECT * FROM t2; ROLLBACK;} } {1 2 3 4 5 6 7 8 9} # However, a ROLLBACK of an inner savepoint will abort all queries, including # queries in outer contexts. # do_test savepoint7-2.1 { db eval {DELETE FROM t2; SAVEPOINT x1; CREATE TABLE t4(abc);} set rc [catch { db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); ROLLBACK TO x2; } } } msg] db eval {RELEASE x1} list $rc $msg [db eval {SELECT * FROM t2}] } {1 {abort due to ROLLBACK} {}} do_test savepoint7-2.2 { db eval {DELETE FROM t2;} set rc [catch { db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; CREATE TABLE t5(pqr); INSERT INTO t2 VALUES($a,$b,$c); ROLLBACK TO x2; } } } msg] list $rc $msg [db eval {SELECT * FROM t2}] } {1 {abort due to ROLLBACK} {}} finish_test |
Added test/scanstatus.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 107 108 109 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 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 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 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 | # 2014 November 1 # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix scanstatus ifcapable !scanstatus { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(a, b); CREATE TABLE t2(x, y); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t2 VALUES('a', 'b'); INSERT INTO t2 VALUES('c', 'd'); INSERT INTO t2 VALUES('e', 'f'); } proc do_scanstatus_test {tn res} { set stmt [db_last_stmt_ptr db] set idx 0 set ret [list] while {1} { set r [sqlite3_stmt_scanstatus $stmt $idx] if {[llength $r]==0} break lappend ret {*}$r incr idx } uplevel [list do_test $tn [list set {} $ret] [list {*}$res]] } do_execsql_test 1.1 { SELECT count(*) FROM t1, t2; } 6 do_scanstatus_test 1.2 { nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN TABLE t1} nLoop 2 nVisit 6 nEst 1048576.0 zName t2 zExplain {SCAN TABLE t2} } do_execsql_test 1.3 { ANALYZE; SELECT count(*) FROM t1, t2; } 6 do_scanstatus_test 1.4 { nLoop 1 nVisit 2 nEst 2.0 zName t1 zExplain {SCAN TABLE t1} nLoop 2 nVisit 6 nEst 3.0 zName t2 zExplain {SCAN TABLE t2} } do_execsql_test 1.5 { ANALYZE } do_execsql_test 1.6 { SELECT count(*) FROM t1, t2 WHERE t2.rowid>1; } 4 do_scanstatus_test 1.7 { nLoop 1 nVisit 2 nEst 2.0 zName t2 zExplain {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)} nLoop 2 nVisit 4 nEst 2.0 zName t1 zExplain {SCAN TABLE t1} } do_execsql_test 1.8 { SELECT count(*) FROM t1, t2 WHERE t2.rowid>1; } 4 do_scanstatus_test 1.9 { nLoop 2 nVisit 4 nEst 2.0 zName t2 zExplain {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)} nLoop 4 nVisit 8 nEst 2.0 zName t1 zExplain {SCAN TABLE t1} } do_test 1.9 { sqlite3_stmt_scanstatus_reset [db_last_stmt_ptr db] } {} do_scanstatus_test 1.10 { nLoop 0 nVisit 0 nEst 2.0 zName t2 zExplain {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)} nLoop 0 nVisit 0 nEst 2.0 zName t1 zExplain {SCAN TABLE t1} } #------------------------------------------------------------------------- # Try a few different types of scans. # reset_db do_execsql_test 2.1 { CREATE TABLE x1(i INTEGER PRIMARY KEY, j); INSERT INTO x1 VALUES(1, 'one'); INSERT INTO x1 VALUES(2, 'two'); INSERT INTO x1 VALUES(3, 'three'); INSERT INTO x1 VALUES(4, 'four'); CREATE INDEX x1j ON x1(j); SELECT * FROM x1 WHERE i=2; } {2 two} do_scanstatus_test 2.2 { nLoop 1 nVisit 1 nEst 1.0 zName x1 zExplain {SEARCH TABLE x1 USING INTEGER PRIMARY KEY (rowid=?)} } do_execsql_test 2.3.1 { SELECT * FROM x1 WHERE j='two' } {2 two} do_scanstatus_test 2.3.2 { nLoop 1 nVisit 1 nEst 10.0 zName x1j zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j=?)} } do_execsql_test 2.4.1 { SELECT * FROM x1 WHERE j<'two' } {4 four 1 one 3 three} do_scanstatus_test 2.4.2 { nLoop 1 nVisit 3 nEst 262144.0 zName x1j zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j<?)} } do_execsql_test 2.5.1 { SELECT * FROM x1 WHERE j>='two' } {2 two} do_scanstatus_test 2.5.2 { nLoop 1 nVisit 1 nEst 262144.0 zName x1j zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>?)} } do_execsql_test 2.6.1 { SELECT * FROM x1 WHERE j BETWEEN 'three' AND 'two' } {3 three 2 two} do_scanstatus_test 2.6.2 { nLoop 1 nVisit 2 nEst 16384.0 zName x1j zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>? AND j<?)} } do_execsql_test 2.7.1 { CREATE TABLE x2(i INTEGER, j, k); INSERT INTO x2 SELECT i, j, i || ' ' || j FROM x1; CREATE INDEX x2j ON x2(j); CREATE INDEX x2ij ON x2(i, j); SELECT * FROM x2 WHERE j BETWEEN 'three' AND 'two' } {3 three {3 three} 2 two {2 two}} do_scanstatus_test 2.7.2 { nLoop 1 nVisit 2 nEst 16384.0 zName x2j zExplain {SEARCH TABLE x2 USING INDEX x2j (j>? AND j<?)} } do_execsql_test 2.8.1 { SELECT * FROM x2 WHERE i=1 AND j='two' } do_scanstatus_test 2.8.2 { nLoop 1 nVisit 0 nEst 8.0 zName x2ij zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)} } do_execsql_test 2.9.1 { SELECT * FROM x2 WHERE i=5 AND j='two' } do_scanstatus_test 2.9.2 { nLoop 1 nVisit 0 nEst 8.0 zName x2ij zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)} } do_execsql_test 2.10.1 { SELECT * FROM x2 WHERE i=3 AND j='three' } {3 three {3 three}} do_scanstatus_test 2.10.2 { nLoop 1 nVisit 1 nEst 8.0 zName x2ij zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)} } #------------------------------------------------------------------------- # Try with queries that use the OR optimization. # do_execsql_test 3.1 { CREATE TABLE a1(a, b, c, d); CREATE INDEX a1a ON a1(a); CREATE INDEX a1bc ON a1(b, c); WITH d(x) AS (SELECT 1 UNION ALL SELECT x+1 AS n FROM d WHERE n<=100) INSERT INTO a1 SELECT x, x, x, x FROM d; } do_execsql_test 3.2.1 { SELECT d FROM a1 WHERE (a=4 OR b=13) } {4 13} do_scanstatus_test 3.2.2 { nLoop 1 nVisit 1 nEst 10.0 zName a1a zExplain {SEARCH TABLE a1 USING INDEX a1a (a=?)} nLoop 1 nVisit 1 nEst 10.0 zName a1bc zExplain {SEARCH TABLE a1 USING INDEX a1bc (b=?)} } do_execsql_test 3.2.1 { SELECT count(*) FROM a1 WHERE (a BETWEEN 4 AND 12) OR (b BETWEEN 40 AND 60) } {30} do_scanstatus_test 3.2.2 { nLoop 1 nVisit 9 nEst 16384.0 zName a1a zExplain {SEARCH TABLE a1 USING INDEX a1a (a>? AND a<?)} nLoop 1 nVisit 21 nEst 16384.0 zName a1bc zExplain {SEARCH TABLE a1 USING INDEX a1bc (b>? AND b<?)} } do_execsql_test 3.3.1 { SELECT count(*) FROM a1 AS x, a1 AS y WHERE (x.a BETWEEN 4 AND 12) AND (y.b BETWEEN 1 AND 10) } {90} do_scanstatus_test 3.2.2 { nLoop 1 nVisit 10 nEst 16384.0 zName a1bc zExplain {SEARCH TABLE a1 AS y USING COVERING INDEX a1bc (b>? AND b<?)} nLoop 10 nVisit 90 nEst 16384.0 zName a1a zExplain {SEARCH TABLE a1 AS x USING COVERING INDEX a1a (a>? AND a<?)} } do_execsql_test 3.4.1 { SELECT count(*) FROM a1 WHERE a IN (1, 5, 10, 15); } {4} do_scanstatus_test 3.4.2 { nLoop 1 nVisit 4 nEst 40.0 zName a1a zExplain {SEARCH TABLE a1 USING COVERING INDEX a1a (a=?)} } do_execsql_test 3.4.1 { SELECT count(*) FROM a1 WHERE rowid IN (1, 5, 10, 15); } {4} do_scanstatus_test 3.4.2 { nLoop 1 nVisit 4 nEst 4.0 zName a1 zExplain {SEARCH TABLE a1 USING INTEGER PRIMARY KEY (rowid=?)} } #------------------------------------------------------------------------- # Test that scanstatus() data is not available for searches performed # by triggers. # # It is available for searches performed as part of FK processing, but # not FK action processing. # do_execsql_test 4.0 { CREATE TABLE t1(a, b, c); CREATE TABLE t2(x PRIMARY KEY, y, z); CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT * FROM t2 WHERE x BETWEEN 20 AND 40; END; WITH d(x) AS (SELECT 1 UNION ALL SELECT x+1 AS n FROM d WHERE n<=100) INSERT INTO t2 SELECT x, x*2, x*3 FROM d; } do_execsql_test 4.1.1 { INSERT INTO t1 VALUES(1, 2, 3); } do_scanstatus_test 4.1.2 { } do_execsql_test 4.2 { CREATE TABLE p1(x PRIMARY KEY); INSERT INTO p1 VALUES(1), (2), (3), (4); CREATE TABLE c1(y REFERENCES p1); INSERT INTO c1 VALUES(1), (2), (3); PRAGMA foreign_keys=on; } do_execsql_test 4.2.1 { DELETE FROM p1 WHERE x=4 } do_scanstatus_test 4.2.2 { nLoop 1 nVisit 1 nEst 1.0 zName sqlite_autoindex_p1_1 zExplain {SEARCH TABLE p1 USING INDEX sqlite_autoindex_p1_1 (x=?)} nLoop 1 nVisit 3 nEst 524288.0 zName c1 zExplain {SCAN TABLE c1} } #------------------------------------------------------------------------- # Further tests of different scan types. # reset_db proc tochar {i} { set alphabet {a b c d e f g h i j k l m n o p q r s t u v w x y z} return [lindex $alphabet [expr $i % [llength $alphabet]]] } db func tochar tochar do_execsql_test 5.0 { CREATE TABLE t1(a PRIMARY KEY, b, c); INSERT INTO t1 VALUES(0, 1, 'a'); INSERT INTO t1 VALUES(1, 0, 'b'); INSERT INTO t1 VALUES(2, 1, 'c'); INSERT INTO t1 VALUES(3, 0, 'd'); INSERT INTO t1 VALUES(4, 1, 'e'); INSERT INTO t1 VALUES(5, 0, 'a'); INSERT INTO t1 VALUES(6, 1, 'b'); INSERT INTO t1 VALUES(7, 0, 'c'); INSERT INTO t1 VALUES(8, 1, 'd'); INSERT INTO t1 VALUES(9, 0, 'e'); CREATE INDEX t1bc ON t1(b, c); CREATE TABLE t2(x, y); CREATE INDEX t2xy ON t2(x, y); WITH data(i, x, y) AS ( SELECT 0, 0, tochar(0) UNION ALL SELECT i+1, (i+1)%2, tochar(i+1) FROM data WHERE i<500 ) INSERT INTO t2 SELECT x, y FROM data; CREATE TABLE t3(x, y); INSERT INTO t3 SELECT * FROM t2; ANALYZE; } do_execsql_test 5.1.1 { SELECT count(*) FROM t1 WHERE a IN (SELECT b FROM t1 AS ii) } {2} do_scanstatus_test 5.1.2 { nLoop 1 nVisit 10 nEst 10.0 zName t1bc zExplain {SCAN TABLE t1 AS ii USING COVERING INDEX t1bc} nLoop 1 nVisit 2 nEst 8.0 zName sqlite_autoindex_t1_1 zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)} } do_execsql_test 5.2.1 { SELECT count(*) FROM t1 WHERE a IN (0, 1) } {2} do_scanstatus_test 5.2.2 { nLoop 1 nVisit 2 nEst 2.0 zName sqlite_autoindex_t1_1 zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)} } do_eqp_test 5.3.1 { SELECT count(*) FROM t2 WHERE y = 'j'; } {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}} do_execsql_test 5.3.2 { SELECT count(*) FROM t2 WHERE y = 'j'; } {19} do_scanstatus_test 5.3.3 { nLoop 1 nVisit 19 nEst 56.0 zName t2xy zExplain {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)} } do_eqp_test 5.4.1 { SELECT count(*) FROM t1, t2 WHERE y = c; } { 0 0 0 {SCAN TABLE t1 USING COVERING INDEX t1bc} 0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)} } do_execsql_test 5.4.2 { SELECT count(*) FROM t1, t2 WHERE y = c; } {200} do_scanstatus_test 5.4.3 { nLoop 1 nVisit 10 nEst 10.0 zName t1bc zExplain {SCAN TABLE t1 USING COVERING INDEX t1bc} nLoop 10 nVisit 200 nEst 56.0 zName t2xy zExplain {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)} } do_eqp_test 5.5.1 { SELECT count(*) FROM t1, t3 WHERE y = c; } { 0 0 1 {SCAN TABLE t3} 0 1 0 {SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)} } do_execsql_test 5.5.2 { SELECT count(*) FROM t1, t3 WHERE y = c; } {200} do_scanstatus_test 5.5.3 { nLoop 1 nVisit 501 nEst 480.0 zName t3 zExplain {SCAN TABLE t3} nLoop 501 nVisit 200 nEst 20.0 zName auto-index zExplain {SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)} } #------------------------------------------------------------------------- # Virtual table scans # ifcapable fts3 { do_execsql_test 6.0 { CREATE VIRTUAL TABLE ft1 USING fts4; INSERT INTO ft1 VALUES('a d c f g h e i f c'); INSERT INTO ft1 VALUES('g c h b g b f f f g'); INSERT INTO ft1 VALUES('h h c c h f a e d d'); INSERT INTO ft1 VALUES('e j i j i e b c f g'); INSERT INTO ft1 VALUES('g f b g j c h a d f'); INSERT INTO ft1 VALUES('j i a e g f a i a c'); INSERT INTO ft1 VALUES('f d g g j j c a h g'); INSERT INTO ft1 VALUES('b d h a d j j j b i'); INSERT INTO ft1 VALUES('j e a b j e c b c i'); INSERT INTO ft1 VALUES('a d e f b j j c g d'); } do_execsql_test 6.1.1 { SELECT count(*) FROM ft1 WHERE ft1 MATCH 'd' } {6} do_scanstatus_test 6.1.2 { nLoop 1 nVisit 6 nEst 24.0 zName ft1 zExplain {SCAN TABLE ft1 VIRTUAL TABLE INDEX 3:} } } finish_test |
Changes to test/shared_err.test.
︙ | ︙ | |||
442 443 444 445 446 447 448 449 450 | ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_NOMEM") || ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_IOERR") || ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_CORRUPT") } } {1} db2 close } do_test shared_malloc-8.X { # Test that one or more queries were aborted due to the malloc() failure. | > > > > > | > | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_NOMEM") || ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_IOERR") || ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_CORRUPT") } } {1} db2 close } # When this test case was written, OOM errors in write statements would # cause transaction rollback, which would trip cursors in other statements, # aborting them. This no longer happens. # do_test shared_malloc-8.X { # Test that one or more queries were aborted due to the malloc() failure. # expr $::aborted>=1 expr $::aborted==0 } {1} # This test is designed to catch a specific bug that was present during # development of 3.5.0. If a malloc() failed while setting the page-size, # a buffer (Pager.pTmpSpace) was being freed. This could cause a seg-fault # later if another connection tried to use the pager. # |
︙ | ︙ |
Changes to test/skipscan6.test.
︙ | ︙ | |||
135 136 137 138 139 140 141 142 143 144 145 | EXPLAIN QUERY PLAN SELECT COUNT(*) FROM t1 WHERE bb=21 AND aa=1 AND dd BETWEEN 1413833728 and 1413837331; } {/INDEX good .bb=. AND aa=. AND dd>. AND dd<../} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 199 200 | EXPLAIN QUERY PLAN SELECT COUNT(*) FROM t1 WHERE bb=21 AND aa=1 AND dd BETWEEN 1413833728 and 1413837331; } {/INDEX good .bb=. AND aa=. AND dd>. AND dd<../} # Create a table containing 100 rows. Column "a" contains a copy of the # rowid value - sequentially increasing integers from 1 to 100. Column # "b" contains the value of (a % 5). Columns "c" and "d" both contain # constant values (i.e. the same for every row). # # Then create a second table t2. t2 is the same as t3 except for the # order in which the indexes are created. # do_execsql_test 3.0 { CREATE TABLE t3(a, b, c, d); CREATE INDEX t3_ba ON t3(b, a, c); CREATE INDEX t3_a ON t3(a); WITH d(a, b) AS ( SELECT 1, 1 UNION ALL SELECT a+1, (a+1) % 5 FROM d WHERE a<100 ) INSERT INTO t3 SELECT a, b, 'c', 'd' FROM d; CREATE TABLE t2(a, b, c, d); CREATE INDEX t2_a ON t2(a); CREATE INDEX t2_ba ON t2(b, a, c); INSERT INTO t2 SELECT * FROM t3; ANALYZE; SELECT * FROM sqlite_stat1; } { t2 t2_ba {100 20 1 1} t2 t2_a {100 1} t3 t3_a {100 1} t3 t3_ba {100 20 1 1} } # Use index "t3_a", as (a=?) is expected to match only a single row. # do_eqp_test 3.1 { SELECT * FROM t3 WHERE a = ? AND c = ? } { 0 0 0 {SEARCH TABLE t3 USING INDEX t3_a (a=?)} } # The same query on table t2. This should use index "t2_a", for the # same reason. At one point though, it was mistakenly using a skip-scan. # do_eqp_test 3.2 { SELECT * FROM t2 WHERE a = ? AND c = ? } { 0 0 0 {SEARCH TABLE t2 USING INDEX t2_a (a=?)} } finish_test finish_test |
Changes to test/sort2.test.
︙ | ︙ | |||
58 59 60 61 62 63 64 | do_execsql_test $tn.2.3 { CREATE UNIQUE INDEX i2 ON t1(a); } do_execsql_test $tn.2.4 { PRAGMA integrity_check } {ok} | < | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | do_execsql_test $tn.2.3 { CREATE UNIQUE INDEX i2 ON t1(a); } do_execsql_test $tn.2.4 { PRAGMA integrity_check } {ok} do_execsql_test $tn.3 { PRAGMA cache_size = 5; WITH r(x,y) AS ( SELECT 1, randomblob(100) UNION ALL SELECT x+1, randomblob(100) FROM r LIMIT 1000000 |
︙ | ︙ |
Changes to test/table.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 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 file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 2001 September 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 file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a basic table and verify it is added to sqlite_master # do_test table-1.1 { |
︙ | ︙ | |||
768 769 770 771 772 773 774 775 776 | CREATE TABLE t16(x DEFAULT(group_concat('x',','))); INSERT INTO t16(rowid) VALUES(123); SELECT rowid, x FROM t16; } {1 {unknown function: group_concat()}} do_catchsql_test table-16.7 { INSERT INTO t16 DEFAULT VALUES; } {1 {unknown function: group_concat()}} finish_test | > > > > > > > > > > > > > > > > > | 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 | CREATE TABLE t16(x DEFAULT(group_concat('x',','))); INSERT INTO t16(rowid) VALUES(123); SELECT rowid, x FROM t16; } {1 {unknown function: group_concat()}} do_catchsql_test table-16.7 { INSERT INTO t16 DEFAULT VALUES; } {1 {unknown function: group_concat()}} # Ticket [https://www.sqlite.org/src/info/094d39a4c95ee4abbc417f04214617675ba15c63] # describes a assertion fault that occurs on a CREATE TABLE .. AS SELECT statement. # the following test verifies that the problem has been fixed. # do_execsql_test table-17.1 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(a TEXT); INSERT INTO t1(a) VALUES(1),(2); DROP TABLE IF EXISTS t2; CREATE TABLE t2(x TEXT, y TEXT); INSERT INTO t2(x,y) VALUES(3,4); DROP TABLE IF EXISTS t3; CREATE TABLE t3 AS SELECT a AS p, coalesce(y,a) AS q FROM t1 LEFT JOIN t2 ON a=x; SELECT p, q, '|' FROM t3 ORDER BY p; } {1 1 | 2 2 |} finish_test |
Changes to test/tkt-f777251dc7a.test.
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 | catch {db eval {INSERT OR ROLLBACK INTO t1 VALUES(1)}} } db function force_rollback force_rollback do_test tkt-f7772-1.2 { catchsql { BEGIN IMMEDIATE; SELECT x, force_rollback(), EXISTS(SELECT 1 FROM t3 WHERE w=x) FROM t2; } } {1 {abort due to ROLLBACK}} do_test tkt-f7772-1.3 { sqlite3_get_autocommit db } {1} | > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | catch {db eval {INSERT OR ROLLBACK INTO t1 VALUES(1)}} } db function force_rollback force_rollback do_test tkt-f7772-1.2 { catchsql { BEGIN IMMEDIATE; CREATE TABLE xyzzy(abc); SELECT x, force_rollback(), EXISTS(SELECT 1 FROM t3 WHERE w=x) FROM t2; } } {1 {abort due to ROLLBACK}} do_test tkt-f7772-1.3 { sqlite3_get_autocommit db } {1} |
︙ | ︙ | |||
63 64 65 66 67 68 69 | execsql { BEGIN IMMEDIATE; CREATE TEMP TABLE t3(w, z); } catchsql { SELECT x, force_rollback(), EXISTS(SELECT 1 FROM t3 WHERE w=x) FROM t2 } | | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | execsql { BEGIN IMMEDIATE; CREATE TEMP TABLE t3(w, z); } catchsql { SELECT x, force_rollback(), EXISTS(SELECT 1 FROM t3 WHERE w=x) FROM t2 } } {1 {abort due to ROLLBACK}} do_test tkt-f7772-2.3 { sqlite3_get_autocommit db } {1} do_test tkt-f7772-3.1 { execsql { DROP TABLE IF EXISTS t1; |
︙ | ︙ |
Changes to test/trans3.test.
︙ | ︙ | |||
48 49 50 51 52 53 54 | do_test trans3-1.3.1 { sqlite3_get_autocommit db } 1 do_test trans3-1.4 { db eval {SELECT * FROM t1} } {1 2 3 4} do_test trans3-1.5 { | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | do_test trans3-1.3.1 { sqlite3_get_autocommit db } 1 do_test trans3-1.4 { db eval {SELECT * FROM t1} } {1 2 3 4} do_test trans3-1.5 { db eval {BEGIN; CREATE TABLE xyzzy(abc);} db eval {INSERT INTO t1 VALUES(5);} set ::ecode {} set x [catch { db eval {SELECT * FROM t1} { if {[catch {db eval ROLLBACK} errmsg]} { set ::ecode [sqlite3_extended_errcode db] error $errmsg |
︙ | ︙ |
Changes to test/without_rowid5.test.
︙ | ︙ | |||
181 182 183 184 185 186 187 | do_execsql_test without_rowid5-5.9 { SELECT count(*) FROM nnw; } {1} # EVIDENCE-OF: R-12643-30541 The incremental blob I/O mechanism does not # work for WITHOUT ROWID tables. # | < | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | do_execsql_test without_rowid5-5.9 { SELECT count(*) FROM nnw; } {1} # EVIDENCE-OF: R-12643-30541 The incremental blob I/O mechanism does not # work for WITHOUT ROWID tables. # # EVIDENCE-OF: R-40134-30296 Table zTable is a WITHOUT ROWID table # do_execsql_test without_rowid5-6.1 { CREATE TABLE b1(a INTEGER PRIMARY KEY, b BLOB) WITHOUT ROWID; INSERT INTO b1 VALUES(1,x'0102030405060708090a0b0c0d0e0f'); } {} do_test without_rowid5-6.2 { set rc [catch {db incrblob b1 b 1} msg] |
︙ | ︙ |
Changes to tool/showstat4.c.
︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 | sqlite3_stmt *pStmt; char *zIdx = 0; int rc, j, x, y, mxHdr; const unsigned char *aSample; int nSample; i64 iVal; const char *zSep; if( argc!=2 ){ fprintf(stderr, "Usage: %s DATABASE-FILE\n", argv[0]); exit(1); } rc = sqlite3_open(argv[1], &db); if( rc!=SQLITE_OK || db==0 ){ | > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | sqlite3_stmt *pStmt; char *zIdx = 0; int rc, j, x, y, mxHdr; const unsigned char *aSample; int nSample; i64 iVal; const char *zSep; int iRow = 0; if( argc!=2 ){ fprintf(stderr, "Usage: %s DATABASE-FILE\n", argv[0]); exit(1); } rc = sqlite3_open(argv[1], &db); if( rc!=SQLITE_OK || db==0 ){ |
︙ | ︙ | |||
56 57 58 59 60 61 62 | if( rc!=SQLITE_OK || pStmt==0 ){ fprintf(stderr, "%s\n", sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } while( SQLITE_ROW==sqlite3_step(pStmt) ){ if( zIdx==0 || strcmp(zIdx, (const char*)sqlite3_column_text(pStmt,0))!=0 ){ | | > < < < > > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | if( rc!=SQLITE_OK || pStmt==0 ){ fprintf(stderr, "%s\n", sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } while( SQLITE_ROW==sqlite3_step(pStmt) ){ if( zIdx==0 || strcmp(zIdx, (const char*)sqlite3_column_text(pStmt,0))!=0 ){ if( zIdx ) printf("\n**************************************" "**************\n\n"); sqlite3_free(zIdx); zIdx = sqlite3_mprintf("%s", sqlite3_column_text(pStmt,0)); iRow = 0; } printf("%s sample %d ------------------------------------\n", zIdx, ++iRow); printf(" nEq = %s\n", sqlite3_column_text(pStmt,1)); printf(" nLt = %s\n", sqlite3_column_text(pStmt,2)); printf(" nDLt = %s\n", sqlite3_column_text(pStmt,3)); printf(" sample = x'"); aSample = sqlite3_column_blob(pStmt,4); nSample = sqlite3_column_bytes(pStmt,4); for(j=0; j<nSample; j++) printf("%02x", aSample[j]); |
︙ | ︙ |