Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch cache-stats Excluding Merge-Ins
This is equivalent to a diff from 36be31ff to 89272357
2011-09-22
| ||
03:13 | Merge the cache-stats enhancement into trunk. (Closed-Leaf check-in: 646db971 user: drh tags: mistake) | |
2011-09-21
| ||
16:43 | Change the way the sqlite3_analyzer executable is built. (check-in: 05e3cced user: dan tags: trunk) | |
00:09 | Pull in the latest changes from trunk. Update the STAT3 documentation. (check-in: 63fc3e4b user: drh tags: stat3-trunk) | |
2011-09-20
| ||
15:53 | Add SQLITE_STMTSTATUS_CACHE_HIT/MISS and SQLITE_DB_STATUS_CACHE_HIT/MISS. For querying the number of pager cache hits and misses on a statement or connection basis. (Closed-Leaf check-in: 89272357 user: dan tags: cache-stats) | |
2011-09-19
| ||
20:56 | Minor comment change in the description of the different memory allocator options. No changes to code. (check-in: 36be31ff user: drh tags: trunk) | |
18:00 | Version 3.7.8 (check-in: 3e0da808 user: drh tags: trunk, release, version-3.7.8) | |
Changes to src/pager.c.
︙ | ︙ | |||
666 667 668 669 670 671 672 673 | int pageSize; /* Number of bytes in a page */ Pgno mxPgno; /* Maximum allowed size of the database */ i64 journalSizeLimit; /* Size limit for persistent journal files */ char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ #ifdef SQLITE_TEST | > < | 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 | int pageSize; /* Number of bytes in a page */ Pgno mxPgno; /* Maximum allowed size of the database */ i64 journalSizeLimit; /* Size limit for persistent journal files */ char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ int nHit, nMiss; /* Total cache hits and misses */ #ifdef SQLITE_TEST int nRead, nWrite; /* Database pages read/written */ #endif void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ #ifdef SQLITE_HAS_CODEC void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */ void (*xCodecFree)(void*); /* Destructor for the codec */ |
︙ | ︙ | |||
4165 4166 4167 4168 4169 4170 4171 | ** pages belonging to the same sector. ** ** The doNotSpill flag inhibits all cache spilling regardless of whether ** or not a sync is required. This is set during a rollback. ** ** Spilling is also prohibited when in an error state since that could ** lead to database corruption. In the current implementaton it | | | 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 | ** pages belonging to the same sector. ** ** The doNotSpill flag inhibits all cache spilling regardless of whether ** or not a sync is required. This is set during a rollback. ** ** Spilling is also prohibited when in an error state since that could ** lead to database corruption. In the current implementaton it ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1 ** while in the error state, hence it is impossible for this routine to ** be called in the error state. Nevertheless, we include a NEVER() ** test for the error state as a safeguard against future changes. */ if( NEVER(pPager->errCode) ) return SQLITE_OK; if( pPager->doNotSpill ) return SQLITE_OK; if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){ |
︙ | ︙ | |||
5001 5002 5003 5004 5005 5006 5007 | assert( (*ppPage)->pgno==pgno ); assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 ); if( (*ppPage)->pPager && !noContent ){ /* In this case the pcache already contains an initialized copy of ** the page. Return without further ado. */ assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); | | < | 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 | assert( (*ppPage)->pgno==pgno ); assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 ); if( (*ppPage)->pPager && !noContent ){ /* In this case the pcache already contains an initialized copy of ** the page. Return without further ado. */ assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); pPager->nHit++; return SQLITE_OK; }else{ /* The pager cache has created a new page. Its content needs to ** be initialized. */ pPg = *ppPage; pPg->pPager = pPager; /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page ** number greater than this, or the unused locking-page, is requested. */ if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ rc = SQLITE_CORRUPT_BKPT; |
︙ | ︙ | |||
5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 | testcase( rc==SQLITE_NOMEM ); sqlite3EndBenignMalloc(); } memset(pPg->pData, 0, pPager->pageSize); IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ assert( pPg->pPager==pPager ); rc = readDbPage(pPg); if( rc!=SQLITE_OK ){ goto pager_acquire_err; } } pager_set_pagehash(pPg); } | > | 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 | testcase( rc==SQLITE_NOMEM ); sqlite3EndBenignMalloc(); } memset(pPg->pData, 0, pPager->pageSize); IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ assert( pPg->pPager==pPager ); pPager->nMiss++; rc = readDbPage(pPg); if( rc!=SQLITE_OK ){ goto pager_acquire_err; } } pager_set_pagehash(pPg); } |
︙ | ︙ | |||
6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 | a[7] = pPager->nMiss; a[8] = 0; /* Used to be pPager->nOvfl */ a[9] = pPager->nRead; a[10] = pPager->nWrite; return a; } #endif /* ** Return true if this is an in-memory pager. */ int sqlite3PagerIsMemdb(Pager *pPager){ return MEMDB; } | > > > > > > > > > > > | 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 | a[7] = pPager->nMiss; a[8] = 0; /* Used to be pPager->nOvfl */ a[9] = pPager->nRead; a[10] = pPager->nWrite; return a; } #endif /* ** This function is used to access the cache hit/miss counts maintained ** by the Pager object. Before returning, *pnHit is incremented by the ** total number of cache-hits that have occurred since the pager was ** created, and *pnMiss is incremented by the total number of misses. */ void sqlite3PagerCacheStats(Pager *pPager, int *pnHit, int *pnMiss){ *pnHit += pPager->nHit; *pnMiss += pPager->nMiss; } /* ** Return true if this is an in-memory pager. */ int sqlite3PagerIsMemdb(Pager *pPager){ return MEMDB; } |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 160 161 162 163 164 | const char *sqlite3PagerFilename(Pager*); const sqlite3_vfs *sqlite3PagerVfs(Pager*); sqlite3_file *sqlite3PagerFile(Pager*); const char *sqlite3PagerJournalname(Pager*); int sqlite3PagerNosync(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); /* Functions used to truncate the database file. */ void sqlite3PagerTruncateImage(Pager*,Pgno); #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) void *sqlite3PagerCodec(DbPage *); #endif | > | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | const char *sqlite3PagerFilename(Pager*); const sqlite3_vfs *sqlite3PagerVfs(Pager*); sqlite3_file *sqlite3PagerFile(Pager*); const char *sqlite3PagerJournalname(Pager*); int sqlite3PagerNosync(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); void sqlite3PagerCacheStats(Pager *, int *, int *); /* Functions used to truncate the database file. */ void sqlite3PagerTruncateImage(Pager*,Pgno); #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) void *sqlite3PagerCodec(DbPage *); #endif |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 | ** ** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt> ** <dd>This parameter returns the approximate number of of bytes of heap ** and lookaside memory used by all prepared statements associated with ** the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. ** </dd> ** </dl> */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 #define SQLITE_DBSTATUS_CACHE_USED 1 #define SQLITE_DBSTATUS_SCHEMA_USED 2 #define SQLITE_DBSTATUS_STMT_USED 3 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 | > > > > > > > > > > > > > > | | 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 | ** ** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt> ** <dd>This parameter returns the approximate number of of bytes of heap ** and lookaside memory used by all prepared statements associated with ** the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. ** </dd> ** ** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt> ** <dd>This parameter returns the number of pager cache hits that have ** occurred. ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT ** is always 0. ** </dd> ** ** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt> ** <dd>This parameter returns the number of pager cache misses that have ** occurred. ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS ** is always 0. ** </dd> ** </dl> */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 #define SQLITE_DBSTATUS_CACHE_USED 1 #define SQLITE_DBSTATUS_SCHEMA_USED 2 #define SQLITE_DBSTATUS_STMT_USED 3 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */ /* ** CAPI3REF: Prepared Statement Status ** ** ^(Each prepared statement maintains various ** [SQLITE_STMTSTATUS counters] that measure the number |
︙ | ︙ | |||
5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 | ** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt> ** <dd>^This is the number of rows inserted into transient indices that ** were created automatically in order to help joins run faster. ** A non-zero value in this counter may indicate an opportunity to ** improvement performance by adding permanent indices that do not ** need to be reinitialized each time the statement is run.</dd> ** ** </dl> */ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 /* ** CAPI3REF: Custom Page Cache Object ** ** The sqlite3_pcache type is opaque. It is implemented by ** the pluggable module. The SQLite core has no knowledge of ** its size or internal structure and never deals with the | > > > > > > > > > > | 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 | ** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt> ** <dd>^This is the number of rows inserted into transient indices that ** were created automatically in order to help joins run faster. ** A non-zero value in this counter may indicate an opportunity to ** improvement performance by adding permanent indices that do not ** need to be reinitialized each time the statement is run.</dd> ** ** [[SQLITE_STMTSTATUS_CACHE_HIT]] <dt>SQLITE_STMTSTATUS_CACHE_HIT</dt> ** <dd>^This is the number of pager cache hits encountered during execution of ** the statement.</dd> ** ** [[SQLITE_STMTSTATUS_CACHE_MISS]] <dt>SQLITE_STMTSTATUS_CACHE_MISS</dt> ** <dd>^This is the number of pager cache misses encountered during execution ** of the statement.</dd> ** ** </dl> */ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 #define SQLITE_STMTSTATUS_CACHE_HIT 4 #define SQLITE_STMTSTATUS_CACHE_MISS 5 /* ** CAPI3REF: Custom Page Cache Object ** ** The sqlite3_pcache type is opaque. It is implemented by ** the pluggable module. The SQLite core has no knowledge of ** its size or internal structure and never deals with the |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
889 890 891 892 893 894 895 896 897 898 899 900 901 902 | Db aDbStatic[2]; /* Static space for the 2 default backends */ Savepoint *pSavepoint; /* List of active savepoints */ int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ i64 nDeferredCons; /* Net deferred constraints this transaction. */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY /* The following variables are all protected by the STATIC_MASTER ** mutex, not by sqlite3.mutex. They are used by code in notify.c. ** ** When X.pUnlockConnection==Y, that means that X is waiting for Y to ** unlock so that it can proceed. | > | 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 | Db aDbStatic[2]; /* Static space for the 2 default backends */ Savepoint *pSavepoint; /* List of active savepoints */ int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ i64 nDeferredCons; /* Net deferred constraints this transaction. */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ int aHitMiss[2]; /* DBSTATUS_CACHEHIT and CACHEMISS stats */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY /* The following variables are all protected by the STATIC_MASTER ** mutex, not by sqlite3.mutex. They are used by code in notify.c. ** ** When X.pUnlockConnection==Y, that means that X is waiting for Y to ** unlock so that it can proceed. |
︙ | ︙ |
Changes to src/status.c.
︙ | ︙ | |||
213 214 215 216 217 218 219 220 221 222 223 224 225 226 | db->pnBytesFreed = 0; *pHighwater = 0; *pCurrent = nByte; break; } default: { rc = SQLITE_ERROR; } } sqlite3_mutex_leave(db->mutex); return rc; | > > > > > > > > > > > > > > > > | 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 | db->pnBytesFreed = 0; *pHighwater = 0; *pCurrent = nByte; break; } /* ** Set *pCurrent to the total cache hits or misses encountered by the ** database connection since the last reset. *pHighwater is always set to ** zero. */ case SQLITE_DBSTATUS_CACHE_HIT: case SQLITE_DBSTATUS_CACHE_MISS: { assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); *pHighwater = 0; *pCurrent = db->aHitMiss[op-SQLITE_DBSTATUS_CACHE_HIT]; if( resetFlag ){ db->aHitMiss[op-SQLITE_DBSTATUS_CACHE_HIT] = 0; } break; } default: { rc = SQLITE_ERROR; } } sqlite3_mutex_leave(db->mutex); return rc; |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 | static const struct { const char *zName; int op; } aOp[] = { { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP }, { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT }, { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX }, }; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG"); return TCL_ERROR; } if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; zOpName = Tcl_GetString(objv[2]); | > > | 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 | static const struct { const char *zName; int op; } aOp[] = { { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP }, { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT }, { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX }, { "SQLITE_STMTSTATUS_CACHE_HIT", SQLITE_STMTSTATUS_CACHE_HIT }, { "SQLITE_STMTSTATUS_CACHE_MISS", SQLITE_STMTSTATUS_CACHE_MISS }, }; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG"); return TCL_ERROR; } if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; zOpName = Tcl_GetString(objv[2]); |
︙ | ︙ |
Changes to src/test_malloc.c.
︙ | ︙ | |||
1321 1322 1323 1324 1325 1326 1327 | } aOp[] = { { "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED }, { "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED }, { "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED }, { "STMT_USED", SQLITE_DBSTATUS_STMT_USED }, { "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT }, { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE }, | | > > | | 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 | } aOp[] = { { "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED }, { "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED }, { "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED }, { "STMT_USED", SQLITE_DBSTATUS_STMT_USED }, { "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT }, { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE }, { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT }, { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS } }; Tcl_Obj *pResult; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB PARAMETER RESETFLAG"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zOpName = Tcl_GetString(objv[2]); if( memcmp(zOpName, "SQLITE_", 7)==0 ) zOpName += 7; if( memcmp(zOpName, "DBSTATUS_", 9)==0 ) zOpName += 9; for(i=0; i<ArraySize(aOp); i++){ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
514 515 516 517 518 519 520 521 522 523 524 525 526 527 | sqlite3 *db = p->db; sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg); sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; } /* ** Execute as much of a VDBE program as we can then return. ** ** sqlite3VdbeMakeReady() must be called before this routine in order to ** close the program with a final OP_Halt and to set up the callbacks ** and the error message pointer. | > > > > > > > > > > > > > > > > > > > > > | 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 | sqlite3 *db = p->db; sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg); sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; } /* ** Call sqlite3PagerCacheStats() on all database pagers used by the VM ** passed as the first argument, incrementing *pnHit and *pnMiss for ** with each call. */ static void vdbeCacheStats(Vdbe *p, int *pnHit, int *pnMiss){ int i; yDbMask mask; sqlite3 *db; Db *aDb; int nDb; if( p->lockMask==0 ) return; /* The common case */ db = p->db; aDb = db->aDb; nDb = db->nDb; for(i=0, mask=1; i<nDb; i++, mask += mask){ if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ sqlite3PagerCacheStats(sqlite3BtreePager(aDb[i].pBt), pnHit, pnMiss); } } } /* ** Execute as much of a VDBE program as we can then return. ** ** sqlite3VdbeMakeReady() must be called before this routine in order to ** close the program with a final OP_Halt and to set up the callbacks ** and the error message pointer. |
︙ | ︙ | |||
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 | int iCompare = 0; /* Result of last OP_Compare operation */ int *aPermute = 0; /* Permutation of columns for OP_Compare */ i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ #ifdef VDBE_PROFILE u64 start; /* CPU clock count at start of opcode */ int origPc; /* Program counter at start of opcode */ #endif /*** INSERT STACK UNION HERE ***/ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ sqlite3VdbeEnter(p); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; | > > > | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 | int iCompare = 0; /* Result of last OP_Compare operation */ int *aPermute = 0; /* Permutation of columns for OP_Compare */ i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ #ifdef VDBE_PROFILE u64 start; /* CPU clock count at start of opcode */ int origPc; /* Program counter at start of opcode */ #endif int nHit = 0; /* Cache hits for this call */ int nMiss = 0; /* Cache misses for this call */ /*** INSERT STACK UNION HERE ***/ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ sqlite3VdbeEnter(p); vdbeCacheStats(p, &nHit, &nMiss); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; |
︙ | ︙ | |||
6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 | } /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: db->lastRowid = lastRowid; sqlite3VdbeLeave(p); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH ** is encountered. */ too_big: | > > > > > > > > > > | 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 | } /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: db->lastRowid = lastRowid; /* Update the statement and database cache hit/miss statistics. */ nHit = -nHit; nMiss = -nMiss; vdbeCacheStats(p, &nHit, &nMiss); p->aCounter[SQLITE_STMTSTATUS_CACHE_HIT-1] += nHit; p->aCounter[SQLITE_STMTSTATUS_CACHE_MISS-1] += nMiss; db->aHitMiss[0] += nHit; db->aHitMiss[1] += nMiss; sqlite3VdbeLeave(p); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH ** is encountered. */ too_big: |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
306 307 308 309 310 311 312 | u8 usesStmtJournal; /* True if uses a statement journal */ u8 readOnly; /* True for read-only statements */ u8 isPrepareV2; /* True if prepared with prepare_v2() */ int nChange; /* Number of db changes made since last reset */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ | | | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | u8 usesStmtJournal; /* True if uses a statement journal */ u8 readOnly; /* True for read-only statements */ u8 isPrepareV2; /* True if prepared with prepare_v2() */ int nChange; /* Number of db changes made since last reset */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ int aCounter[5]; /* Counters used by sqlite3_stmt_status() */ #ifndef SQLITE_OMIT_TRACE i64 startTime; /* Time when query started - used for profiling */ #endif i64 nFkConstraint; /* Number of imm. FK constraints this VM */ i64 nStmtDefCons; /* Number of def. constraints when stmt started */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ************************************************************************* ** ** This file contains code used to implement incremental BLOB I/O. */ #include "sqliteInt.h" #include "vdbeInt.h" #ifndef SQLITE_OMIT_INCRBLOB /* ** Valid sqlite3_blob* handles point to Incrblob structures. */ typedef struct Incrblob Incrblob; | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** ** This file contains code used to implement incremental BLOB I/O. */ #include "sqliteInt.h" #include "vdbeInt.h" #include "btreeInt.h" #ifndef SQLITE_OMIT_INCRBLOB /* ** Valid sqlite3_blob* handles point to Incrblob structures. */ typedef struct Incrblob Incrblob; |
︙ | ︙ | |||
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | ** 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{ db->errCode = rc; v->rc = rc; | > > > > > > > > | 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 | ** 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. */ Pager *pPager = p->pCsr->pBt->pPager; int nHit = 0; int nMiss = 0; assert( db == v->db ); sqlite3BtreeEnterCursor(p->pCsr); sqlite3PagerCacheStats(pPager, &nHit, &nMiss); rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); db->aHitMiss[0] -= nHit; db->aHitMiss[1] -= nMiss; sqlite3PagerCacheStats(pPager, &db->aHitMiss[0], &db->aHitMiss[1]); sqlite3BtreeLeaveCursor(p->pCsr); if( rc==SQLITE_ABORT ){ sqlite3VdbeFinalize(v); p->pStmt = 0; }else{ db->errCode = rc; v->rc = rc; |
︙ | ︙ |
Added test/stmtstatus.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 | # 2011 September 20 # # 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. # #*********************************************************************** # # Tests for the sqlite3_stmt_status() function # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix stmtstatus do_execsql_test 1.0 { PRAGMA page_size = 1024; PRAGMA auto_vacuum = 0; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(1, randomblob(600)); INSERT INTO t1 VALUES(2, randomblob(600)); INSERT INTO t1 VALUES(3, randomblob(600)); } proc stmt_hit_miss {stmt {reset 0}} { list [sqlite3_stmt_status $stmt SQLITE_STMTSTATUS_CACHE_HIT $reset] \ [sqlite3_stmt_status $stmt SQLITE_STMTSTATUS_CACHE_MISS $reset] } do_test 1.1 { db close sqlite3 db test.db expr {[file size test.db] / 1024} } 6 do_test 1.2 { set ::stmt [sqlite3_prepare_v2 db "SELECT b FROM t1 WHERE a=2" -1 dummy] stmt_hit_miss $::stmt } {0 0} breakpoint do_test 1.3 { sqlite3_step $::stmt sqlite3_reset $::stmt } SQLITE_OK do_test 1.4 { stmt_hit_miss $::stmt } {1 3} do_test 1.5 { sqlite3_step $::stmt sqlite3_reset $::stmt } SQLITE_OK do_test 1.6 { stmt_hit_miss $::stmt } {5 3} do_test 1.7 { stmt_hit_miss $::stmt 0 } {5 3} do_test 1.8 { stmt_hit_miss $::stmt 1 } {5 3} do_test 1.9 { stmt_hit_miss $::stmt 0 } {0 0} do_test 1.10 { sqlite3_finalize $::stmt } SQLITE_OK do_test 1.11 { sqlite3_db_status db CACHE_HIT 0 } {0 6 0} do_test 1.12 { sqlite3_db_status db CACHE_MISS 0 } {0 3 0} do_test 1.13 { sqlite3_db_status db CACHE_HIT 1 } {0 6 0} do_test 1.14 { sqlite3_db_status db CACHE_MISS 1 } {0 3 0} do_test 1.15 { sqlite3_db_status db CACHE_HIT 0 } {0 0 0} do_test 1.16 { sqlite3_db_status db CACHE_MISS 0 } {0 0 0} do_test 1.17 { set fd [db incrblob main t1 b 1] set len [string length [read $fd]] close $fd set len } 600 do_test 1.18 { sqlite3_db_status db CACHE_HIT 0 } {0 2 0} do_test 1.19 { sqlite3_db_status db CACHE_MISS 0 } {0 1 0} finish_test |