Compare commits

...

9 Commits

Author SHA1 Message Date
drh 399665beb5 Merge the Parse.prepFlags change from trunk.
FossilOrigin-Name: c8d77f398099f357bed0aab10f066c6b26ba4ad8ffd68bb7b4465c0c4999599b
2022-10-01 13:28:04 +00:00
drh 5035c33df8 Merge the latest trunk enhancements into the stmt-cache branch.
FossilOrigin-Name: 7812aea6ea2a922599970cd56933dadaa340bcf40781701844f62456772501c2
2022-10-01 12:00:39 +00:00
drh 11969c1269 Fix the bytecode engine so that it is able to handle an incoming
SQLITE_TOOBIG error, which is now possible using the statement cache.

FossilOrigin-Name: 7763b98b36bec186c5cc4a06382ee424fe9c7f401c70858fdfa490baa4bf437c
2022-08-25 18:29:12 +00:00
drh 546d46a40d Do not attempt to cache DDL statement.
FossilOrigin-Name: 8f6a1f77b8d11c4eea315672353ea18a1ac50aa46a8e3f06f7d3b81de25f88c6
2022-08-25 17:12:30 +00:00
drh aae210884c Improved documentation of new features. Minor speed enhancements.
FossilOrigin-Name: da9aa5476c342ed02a982e81eb8272cb33adb2ed3d0b5df44b2c88b27d80a94c
2022-08-25 15:09:31 +00:00
drh 7b7a373706 Merge changes from trunk into the stmt-cache branch.
FossilOrigin-Name: bc988ce727bee0c7ac6406b5c9af486e353f1adf1e13b11ba0ac963fbea1f14e
2022-08-25 14:31:08 +00:00
drh 2578cf2eb7 If a perpared statement runs the Expire opcode, then disqualify it from
being cached.

FossilOrigin-Name: f27d919f3535f2be6642a02cf03cee82c66ff9d1e727f0c59c137f2a7f1d00c9
2022-08-25 13:09:02 +00:00
drh 1544960b3d Change sqlite3_prepare_v3() to require SQLITE_PREPARE_CACHE in order for a
statement to be a cache candidate.  But any statement can pull from the cache.
Also add statement cache control to the CLI.

FossilOrigin-Name: c9dc536db9d13c0d66e5b84e564d6813c184ae26c889413a64b365781bf8ee50
2022-08-24 23:50:45 +00:00
drh 4f2bf6bf88 First attempt at adding a built-in prepared statement cache. This is
mostly working, but still has a few obscure faults.

FossilOrigin-Name: c217b763b148e8bece9d1f72525fd5026d3f710b337c010ffd0306fde4f9add8
2022-08-24 17:55:27 +00:00
16 changed files with 410 additions and 65 deletions
+10 -2
View File
@@ -31,7 +31,7 @@ SQLITE_EXTENSION_INIT1
#ifndef SQLITE_OMIT_VIRTUALTABLE
#define STMT_NUM_INTEGER_COLUMN 10
#define STMT_NUM_INTEGER_COLUMN 11
typedef struct StmtRow StmtRow;
struct StmtRow {
sqlite3_int64 iRowid; /* Rowid value */
@@ -95,11 +95,12 @@ static int stmtConnect(
#define STMT_COLUMN_REPREP 8 /* SQLITE_STMTSTATUS_REPREPARE */
#define STMT_COLUMN_RUN 9 /* SQLITE_STMTSTATUS_RUN */
#define STMT_COLUMN_MEM 10 /* SQLITE_STMTSTATUS_MEMUSED */
#define STMT_COLUMN_STATE 11 /* SQLITE_STMTSTATUS_STATE */
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep,"
"reprep,run,mem)");
"reprep,run,mem,state)");
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc64( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
@@ -175,6 +176,10 @@ static int stmtColumn(
StmtRow *pRow = pCur->pRow;
if( i==STMT_COLUMN_SQL ){
sqlite3_result_text(ctx, pRow->zSql, -1, SQLITE_TRANSIENT);
}else if( i==STMT_COLUMN_STATE ){
const char *azStateName[] = { "INIT", "READY", "RUN", "HALT", "CACHE" };
int j = pRow->aCol[i];
sqlite3_result_text(ctx, azStateName[j%5], -1, SQLITE_STATIC);
}else{
sqlite3_result_int(ctx, pRow->aCol[i]);
}
@@ -253,6 +258,9 @@ static int stmtFilter(
pNew->aCol[STMT_COLUMN_MEM] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_MEMUSED, 0
);
pNew->aCol[STMT_COLUMN_STATE] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_STATE, 0
);
pNew->iRowid = iRowid++;
*ppRow = pNew;
ppRow = &pNew->pNext;
+19 -19
View File
@@ -1,5 +1,5 @@
C Replace\sthe\sParse.disableVtab\sfield\swith\sParse.prepFlags\sfor\sincreased\ngenerality,\sa\ssmall\ssize\sreduction,\sand\sa\ssmall\sperformance\sincrease.
D 2022-10-01T13:17:53.450
C Merge\sthe\sParse.prepFlags\schange\sfrom\strunk.
D 2022-10-01T13:28:04.924
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -328,7 +328,7 @@ F ext/misc/shathree.c 7b17615869a495659f1569ada1d8d3d21b4a24614f2746d93cc87ef7c0
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
F ext/misc/sqlar.c 0ace5d3c10fe736dc584bf1159a36b8e2e60fab309d310cd8a0eecd9036621b6
F ext/misc/stmt.c ed05ad78013edccd43f4fc33d8244001f6f886eb2dfd2106ba33616ac514c6fb
F ext/misc/stmt.c 36ad8e9a5352e4795dd1da1d04c6ab9680c58d1dd648bdb26a53123c976a0f2b
F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
F ext/misc/totype.c fa4aedeb07f66169005dffa8de3b0a2b621779fd44f85c103228a42afa71853b
F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a030b
@@ -531,7 +531,7 @@ F src/btmutex.c 6ffb0a22c19e2f9110be0964d0731d2ef1c67b5f7fabfbaeb7b9dabc4b7740ca
F src/btree.c ef9c126d6dc5dff8ff76abc807dfef5b8aac42144e3be11cbcd9cb6eaecef580
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btreeInt.h 8ce1332edd89dfd2461d561ac10a0ab5601c8e06200cb5230596c3caaf54482e
F src/build.c 6e3ee380a4f0ff95de4b53bf510f66600cff08e4e04b92e95fae789072563f8f
F src/build.c 50cf41a7710c5ebfd22e4a233d359598a10e62f55b984fa91c85b883b2e27d37
F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484a
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 93e4b5f4faf6d3f688988a116773259a4fbfb4ddac0e9bf9d0ae0429390c2543
@@ -552,7 +552,7 @@ F src/insert.c aea5361767817f917b0f0f647a1f0b1621bd858938ae6ae545c3b6b9814b798f
F src/json.c 7749b98c62f691697c7ee536b570c744c0583cab4a89200fdd0fc2aa8cc8cbd6
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 853385cc7a604157e137585097949252d5d0c731768e16b044608e5c95c3614b
F src/main.c 8983b4a316d7e09946dd731913aa41712f02e2b55cb5c6c92126ccfe2473244a
F src/main.c 123ac0cc427dee4befdd47ff0f999cbb8f035f805c5d5f365dda5ba577c03ea3
F src/malloc.c dfddca1e163496c0a10250cedeafaf56dff47673e0f15888fb0925340a8e3f90
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -583,17 +583,17 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c dee95e3cd2b61e6512dc814c5ab76d5eb36f0bfc9441dbb4260fccc0d12bbddc
F src/pragma.c 9bf7d8a2a9ad3bc36df3ec0d61817a44c38a1da527d59c26c203047f906e334a
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 0e61df99f063f12896a89c893fd3f8868e9fb13252c05e3e4e8cea7422094d0a
F src/prepare.c fbcfdd127ec6e0e011da7f31b9b30dfd70d520ce3f6b2e6c27d3e7904d0faea1
F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764
F src/random.c 546d6feb15ec69c1aafe9bb351a277cbb498fd5410e646add673acb805714960
F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c bb18acf4eded647fef88d4d543c673874dbebff516fbeba90a85e6c13f2a58cd
F src/shell.c.in e7e7c2c69ae86c5ee9e8ad66227203d46ff6dce8700a1b1dababff01c71d33df
F src/sqlite.h.in b9b7fd73239d94db20332bb6e504688001e5564b655e1318a4427a1caef4b99e
F src/shell.c.in a1152c45017c9ce634b1616d16ccf530397df1260302fccc7aafee7afe57173a
F src/sqlite.h.in 24e7d46e187456b778ca8f6e28b194667b80f8a61e4c1a861239a91fd6d3e686
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h a988810c9b21c0dc36dc7a62735012339dc76fc7ab448fb0792721d30eacb69d
F src/sqliteInt.h 7571703e6d11cd0e0283be68e9b6baceefedf10e3bbac5869d12183e031c5254
F src/sqliteInt.h 89f957680385f5725ec701ec94b41274d6d77ef25feb96fcda67a0aa545badb4
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -654,17 +654,17 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 1305797eab3542a0896b552c6e7669c972c1468e11e92b370533c1f37a37082b
F src/treeview.c 07787f67cd297a6d09d04b8d70c06769c60c9c1d9080378f93929c16f8fd3298
F src/trigger.c 4163ada044af89d51caba1cb713a73165347b2ec05fe84a283737c134d61fcd5
F src/trigger.c 78dd02836a0559e41321318668f6f0c266b27cc172d1676879431765b27720c5
F src/update.c c52a7991bece0453d22c77c08469512ee2f1391c12503fd347d1c939220c5877
F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 0be191521ff6d2805995f4910f0b6231b42843678b2efdc1abecaf39929a673f
F src/vacuum.c bb346170b0b54c6683bba4a5983aea40485597fdf605c87ec8bc2e199fe88cd8
F src/vdbe.c 0d1e3c658d98a7bb7201532ea7a3e4d59bf9165421c780d5f84c361e372f1179
F src/vdbe.h 64619af62603dc3c4f5ff6ff6d2c8f389abd667a29ce6007ed44bd22b3211cd0
F src/vdbeInt.h 17b7461ffcf9ee760d1341731715a419f6b8c763089a7ece25c2e8098d702b3f
F src/vdbeapi.c fc3183daf72808b4311b228989120fdbc2dc44972fb0d77d5c453460cc0e5b2c
F src/vdbeaux.c c719cebaffa75e166f16a405b3dee96e7150d60fc563ab2dea716b60c6a51312
F src/vdbe.c 5ea5f28e90ea64d53fc61ff638c2e6d76009a13aa872bd1c53765bf81ad5848a
F src/vdbe.h c4c9defdf2ad9465f9c9c7f79c3b03555f47aa930ea2744f358d9b27269763c7
F src/vdbeInt.h 1c58993f8bdf604706120838d018495289ab82dfb8d575748293a3396cd3e2d0
F src/vdbeapi.c ba51a59b3c0ecbf76f337de087089986464da83d1bf42b4fdebef8d74de173b2
F src/vdbeaux.c 173eb3ffc4f906411b1c1fb5fe7bb59a5bd53befd43a276fb07f6225ebb4702e
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
F src/vdbemem.c c3ce80af15e2ff5c2824a8db881681cbf511376f13613da020bac6d320c535b1
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
@@ -1480,7 +1480,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
F test/speedtest1.c 8bf7ebac9ac316feed6656951249db531dc380c73fb3e3b22e224ffda96beff6
F test/speedtest1.c 07b9d2cc48ea0d68ba7ab85de86b7a26af638737f6ac65054d557f3ca50efbfa
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -2000,8 +2000,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P bd8ae5febbb8d3122f1e2e09b9fcdd6ac20c075ae1cf60bcdbd36080f3736417
R b431f195d6909dd213769258d329fb1f
P 7812aea6ea2a922599970cd56933dadaa340bcf40781701844f62456772501c2 b7da0bcdf70e53ab1ec00a0694e17c7429e23bc6eb3f39b622d06a930aa2f6a3
R 4fea9345ef5af6b4a81a531a14cab26b
U drh
Z 5ff8e8c9111016b6f28cef573224105e
Z a63cbed431bd786ee17d13092323f381
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
b7da0bcdf70e53ab1ec00a0694e17c7429e23bc6eb3f39b622d06a930aa2f6a3
c8d77f398099f357bed0aab10f066c6b26ba4ad8ffd68bb7b4465c0c4999599b
+1
View File
@@ -2791,6 +2791,7 @@ void sqlite3EndTable(
#ifndef SQLITE_OMIT_VIEW
}else{
/* A view */
sqlite3VdbeRunOnlyOnce(v);
zType = "view";
zType2 = "VIEW";
#endif
+12
View File
@@ -918,6 +918,16 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
sqlite3_mutex_enter(db->mutex);
va_start(ap, op);
switch( op ){
case SQLITE_DBCONFIG_STMTCACHE_SIZE: {
int szDesired = va_arg(ap,int);
int *pszNew = va_arg(ap,int*);
if( szDesired>=0 ){
sqlite3VdbeChangeStmtCacheSize(db, szDesired);
}
if( pszNew ) *pszNew = (int)db->mxCache;
rc = SQLITE_OK;
break;
}
case SQLITE_DBCONFIG_MAINDBNAME: {
/* IMP: R-06824-28531 */
/* IMP: R-36257-52125 */
@@ -1214,6 +1224,7 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
}
/* Force xDisconnect calls on all virtual tables */
sqlite3VdbeChangeStmtCacheSize(db, 0);
disconnectAllVtab(db);
/* If a transaction is open, the disconnectAllVtab() call above
@@ -3252,6 +3263,7 @@ static int openDatabase(
db->autoCommit = 1;
db->nextAutovac = -1;
db->szMmap = sqlite3GlobalConfig.szMmap;
db->mxCache = SQLITE_DEFAULT_STMTCACHE_SIZE;
db->nextPagesize = 0;
db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */
#ifdef SQLITE_ENABLE_SORTER_MMAP
+17 -2
View File
@@ -686,6 +686,7 @@ static int sqlite3Prepare(
int rc = SQLITE_OK; /* Result code */
int i; /* Loop counter */
Parse sParse; /* Parsing context */
u32 hSql = 0; /* Hash of the input SQL */
/* sqlite3ParseObjectInit(&sParse, db); // inlined for performance */
memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ);
@@ -698,10 +699,23 @@ static int sqlite3Prepare(
if( db->mallocFailed ) sqlite3ErrorMsg(&sParse, "out of memory");
assert( sqlite3_mutex_held(db->mutex) );
if( db->nCache>0 ){
Vdbe *pCache;
if( nBytes<0 ) nBytes = sqlite3Strlen30(zSql);
pCache = sqlite3VdbeFindInStmtCache(db, zSql, nBytes, &hSql);
if( pCache ){
*ppStmt = (sqlite3_stmt*)pCache;
if( pzTail ){
*pzTail = &zSql[nBytes];
}
goto end_prepare;
}
}
/* For a long-term use prepared statement avoid the use of
** lookaside memory.
*/
if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
if( prepFlags & (SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_CACHE) ){
sParse.disableLookaside++;
DisableLookaside;
}
@@ -776,7 +790,8 @@ static int sqlite3Prepare(
}
if( db->init.busy==0 ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql),
prepFlags, hSql);
}
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM_BKPT;
+85 -13
View File
@@ -1112,6 +1112,7 @@ struct ShellState {
int cnt; /* Number of records displayed so far */
int lineno; /* Line number of last line read from in */
int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
int prepFlags; /* Flags for sqlite3_prepare_v3() */
FILE *in; /* Read commands from this stream */
FILE *out; /* Write results here */
FILE *traceOut; /* Output for sqlite3_trace() */
@@ -2662,7 +2663,7 @@ static int run_table_dump_query(
int nResult;
int i;
const char *z;
rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
rc = sqlite3_prepare_v3(p->db, zSelect, -1, p->prepFlags, &pSelect, 0);
if( rc!=SQLITE_OK || !pSelect ){
char *zContext = shell_error_context(zSelect, p->db);
utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
@@ -3858,7 +3859,7 @@ static int shell_exec(
while( zSql[0] && (SQLITE_OK == rc) ){
static const char *zStmtSql;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
rc = sqlite3_prepare_v3(db, zSql, -1, pArg->prepFlags, &pStmt, &zLeftover);
if( SQLITE_OK != rc ){
if( pzErrMsg ){
*pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
@@ -3924,7 +3925,7 @@ static int shell_exec(
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
/* Reprepare pStmt before reactiving trace modes */
sqlite3_finalize(pStmt);
sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
sqlite3_prepare_v3(db, zSql, -1, pArg->prepFlags, &pStmt, 0);
if( pArg ) pArg->pStmt = pStmt;
}
restore_debug_trace_modes();
@@ -4023,7 +4024,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){
zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
shell_check_oom(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
rc = sqlite3_prepare_v3(p->db, zSql, -1, p->prepFlags, &pStmt, 0);
sqlite3_free(zSql);
if( rc ) return 0;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
@@ -4068,7 +4069,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){
zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
" WHERE origin='pk'", zTab);
shell_check_oom(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
rc = sqlite3_prepare_v3(p->db, zSql, -1, p->prepFlags, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
freeColumnList(azCol);
@@ -8320,8 +8321,10 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
/* The undocumented ".breakpoint" command causes a call to the no-op
** routine named test_breakpoint().
/* UNDOCUMENTED COMMAND: .breakpoint
**
** Causes a call to the no-op routine named test_breakpoint(). This provides
** a convenient function on which to set a breakpoint.
*/
if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
test_breakpoint();
@@ -8500,6 +8503,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
{ "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
{ "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
{ "stmtcache_size", SQLITE_DBCONFIG_STMTCACHE_SIZE },
{ "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
{ "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
{ "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
@@ -8507,12 +8511,22 @@ static int do_meta_command(char *zLine, ShellState *p){
int ii, v;
open_db(p, 0);
for(ii=0; ii<ArraySize(aDbConfig); ii++){
int op;
if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
op = aDbConfig[ii].op;
if( nArg>=3 ){
sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
if( op==SQLITE_DBCONFIG_STMTCACHE_SIZE ){
sqlite3_db_config(p->db, op, (int)integerValue(azArg[2]), 0);
}else{
sqlite3_db_config(p->db, op, booleanValue(azArg[2]), 0);
}
}
sqlite3_db_config(p->db, op, -1, &v);
if( op==SQLITE_DBCONFIG_STMTCACHE_SIZE ){
utf8_printf(p->out, "%19s %d\n", aDbConfig[ii].zName, v);
}else{
utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
}
sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
if( nArg>1 ) break;
}
if( nArg>1 && ii==ArraySize(aDbConfig) ){
@@ -9926,6 +9940,47 @@ static int do_meta_command(char *zLine, ShellState *p){
showHelp(p->out, "parameter");
}else
/* UNDOCUMENTED COMMAND: .prepflags (+|-)FLAG ...
**
** For SQLite core debugging use only.
**
** Change the value of ShellState.prepFlags which becomes the flags
** parameter to sqlite3_prepare_v3() in some calls in this application.
*/
if( c=='p' && n>=3 && strncmp(azArg[0], "prepflags", n)==0 ){
int i;
for(i=1; i<nArg; i++){
int op = 0;
if( azArg[i][0]!='-' && azArg[i][0]!='+' ){
utf8_printf(p->out, "unknown option: \"%s\"\n", azArg[i]);
rc = 1;
goto meta_command_exit;
}
if( strcmp(azArg[i]+1, "persist")==0 ){
op = SQLITE_PREPARE_PERSISTENT;
}else if( strcmp(azArg[i]+1, "no-vtab")==0 ){
op = SQLITE_PREPARE_NO_VTAB;
}else if( strcmp(azArg[i]+1, "cache")==0 ){
op = SQLITE_PREPARE_CACHE;
}else{
utf8_printf(p->out, "option \"%s\" should be one of: \"%cpersist\""
"\"%cno-vtab\" \"%ccache\"\n",
azArg[i], azArg[i][0],azArg[i][0],azArg[i][0]);
rc = 1;
goto meta_command_exit;
}
if( azArg[i][0]=='+' ){
p->prepFlags |= op;
}else{
p->prepFlags &= ~op;
}
}
utf8_printf(p->out, " prepflags:");
utf8_printf(p->out, " %cpersist", (p->prepFlags & SQLITE_PREPARE_PERSISTENT)?'+':'-');
utf8_printf(p->out, " %cno-vtab", (p->prepFlags & SQLITE_PREPARE_NO_VTAB)?'+':'-');
utf8_printf(p->out, " %ccache\n", (p->prepFlags & SQLITE_PREPARE_CACHE)?'+':'-');
}else
if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
int i;
for(i=1; i<nArg; i++){
@@ -10242,6 +10297,13 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
/* UNDOCUMENTED COMMAND: .treetrace N
**
** For SQLite core debugging use only.
**
** Set the treetrace mask to N. Also called ".selectrace" for historical
** compatibility.
*/
if( (c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0)
|| (c=='t' && n==9 && strncmp(azArg[0], "treetrace", n)==0)
){
@@ -10743,6 +10805,9 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
goto meta_command_exit;
}
utf8_printf(p->out,"%12.12s: ", "colseparator");
output_c_string(p->out, p->colSeparator);
raw_printf(p->out, "\n");
utf8_printf(p->out, "%12.12s: %s\n","echo",
azBool[ShellHasFlag(p, SHFLG_Echo)]);
utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
@@ -10765,9 +10830,10 @@ static int do_meta_command(char *zLine, ShellState *p){
raw_printf(p->out, "\n");
utf8_printf(p->out,"%12.12s: %s\n","output",
strlen30(p->outfile) ? p->outfile : "stdout");
utf8_printf(p->out,"%12.12s: ", "colseparator");
output_c_string(p->out, p->colSeparator);
raw_printf(p->out, "\n");
utf8_printf(p->out,"%12.12s:", "prepflags");
utf8_printf(p->out," %cpersist",(p->prepFlags&SQLITE_PREPARE_PERSISTENT)?'+':'-');
utf8_printf(p->out," %cno-vtab",(p->prepFlags&SQLITE_PREPARE_NO_VTAB)?'+':'-');
utf8_printf(p->out," %ccache\n",(p->prepFlags&SQLITE_PREPARE_CACHE)?'+':'-');
utf8_printf(p->out,"%12.12s: ", "rowseparator");
output_c_string(p->out, p->rowSeparator);
raw_printf(p->out, "\n");
@@ -11381,6 +11447,12 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
/* UNDOCUMENTED COMMMAND: .wheretrace NUMBER
**
** For SQLite core debugging use only.
**
** See the wheretrace mask to NUMBER.
*/
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
+73 -9
View File
@@ -2128,7 +2128,61 @@ struct sqlite3_mem_methods {
** non-zero [error code] if a discontinued or unsupported configuration option
** is invoked.
**
** Most of these configuration options are used to set, clear, or query flags.
** All such options take two arguments: And integer (X) and a pointer to an
** integer (P). If the X argument is greater than zero, the flag is set. If
** X is equal to zero, the flag is cleared. If X is less than zero, the flag
** remains unchanged. In all cases, the value of the flag after any changes
** (either 0 or 1) is written into the integer pointed to by P. All of the
** configuration options listed below operate this way, with the following
** exceptions:
**
** <ul>
** <li> [SQLITE_DBCONFIG_MAINDBNAME]
** <li> [SQLITE_DBCONFIG_LOOKASIDE]
** <li> [SQLITE_DBCONFIG_STMTCACHE_SIZE]
** </ul>
**
** <dl>
** [[SQLITE_DBCONFIG_STMTCACHE_SIZE]] <dt>SQLITE_DBCONFIG_STMTCACHE_SIZE</dt>
** <dd> The SQLITE_DBCONFIG_STMTCACHE_SIZE option is used to query or change
** the maximum number of [prepared statements] that SQLite will cache. Prepared
** statements are only candidates for caching if they are prepared using
** [sqlite3_prepare_v3()] with the [SQLITE_PREPARE_PERSISTENT] option. If
** SQLite chooses to cache a perpared statement, that means that when
** [sqlite3_finalize()] is called on the prepared statement, the statement is
** not immediately deleted, but instead is put into the cache. Subsequent
** calls to any of the [sqlite3_prepare()] ineterfaces with the exact same
** SQL text may reuse the cached prepared statement rather than creating a new
** prepared statement. This setting adjusts the maximum number of prepared
** statements that SQLite will keep in cache. The default value is
** SQLITE_DEFAULT_STMTCACHE_SIZE which is 10 unless overridden at compile-time.
** Setting the maximum cache size to zero disables the cache. The cache is
** automatically trimmed back to its maximum size when the cache size is
** reduced. Hence the cache can be flushed, by set the cache size to zero
** then set it back to its original value.
** <p>This configuration option takes two parameters. The first parameter (N) is
** an integer which is the desired new size of the statement cache. A negative
** value for N leaves the cache size unchanged. The second parameter (P)
** is a pointer to an integer into which the new cache size is written.
** The database connection is free to limit or truncate the N value that is
** passed in, so the new cache size returned in P is not necessarily the same
** as the N argument.
** </dd>
**
** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
** <dd> ^This option is used to change the name of the "main" database
** schema. ^The sole argument is a pointer to a constant UTF8 string
** which will become the new schema name in place of "main". ^SQLite
** does not make a copy of the new main schema name string, so the application
** must ensure that the argument passed into this DBCONFIG option is unchanged
** until after the database connection closes. The application is responsible
** for managing the storage associated with the string passed in as the
** argument. SQLite does not attempt to free the string, or do anything else
** to reclaim storage space associated with the string, when the database
** connection closes.
** </dd>
**
** [[SQLITE_DBCONFIG_LOOKASIDE]]
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
** <dd> ^This option takes three additional arguments that determine the
@@ -2229,15 +2283,6 @@ struct sqlite3_mem_methods {
** be a NULL pointer, in which case the new setting is not reported back.
** </dd>
**
** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
** <dd> ^This option is used to change the name of the "main" database
** schema. ^The sole argument is a pointer to a constant UTF8 string
** which will become the new schema name in place of "main". ^SQLite
** does not make a copy of the new main schema name string, so the application
** must ensure that the argument passed into this DBCONFIG option is unchanged
** until after the database connection closes.
** </dd>
**
** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
** <dd> Usually, when a database in wal mode is closed or detached from a
@@ -2396,6 +2441,7 @@ struct sqlite3_mem_methods {
** </dd>
** </dl>
*/
#define SQLITE_DBCONFIG_STMTCACHE_SIZE 999 /* int int* */
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
@@ -4047,11 +4093,19 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
** to return an error (error code SQLITE_ERROR) if the statement uses
** any virtual tables.
**
** [[SQLITE_PREPARE_CACHE]] <td>SQLITE_PREPARE_CACHE</dt>
** <dd>The SQLITE_PREPARE_CACHE flag gives SQLite permission to attempt
** to cache the prepared statement after it is
** [sqlite3_finalized|finalized] and attempt to reuse it as the
** return value for the next call to a [sqlite3_prepare()] that has
** the same SQL. This flag also implies [SQLITE_PREPARE_PERSISTENT].
** </dl>
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
#define SQLITE_PREPARE_NORMALIZE 0x02
#define SQLITE_PREPARE_NO_VTAB 0x04
#define SQLITE_PREPARE_CACHE 0x08
/*
** CAPI3REF: Compiling An SQL Statement
@@ -8560,6 +8614,15 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** times that the Bloom filter returned a find, and thus the join step
** had to be processed as normal.
**
** [[SQLITE_STMTSTATUS_STATE]] <dt>SQLITE_STMTSTATUS_STATE</dt>
** <dd>During its lifetime, a prepare statement transitions through
** various "states". This interface returns the current state of the
** prepared statement, as an integer. This information is intended
** for use by SQLite core developers only. The internal state numbers
** for prepared statements can and do change from one release of
** SQLite to the next. Hence the value returned for this property
** code can change from one release of SQLite to the next.
**
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
** <dd>^This is the approximate number of bytes of heap memory
** used to store the prepared statement. ^This value is not actually
@@ -8576,6 +8639,7 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
#define SQLITE_STMTSTATUS_RUN 6
#define SQLITE_STMTSTATUS_FILTER_MISS 7
#define SQLITE_STMTSTATUS_FILTER_HIT 8
#define SQLITE_STMTSTATUS_STATE 98
#define SQLITE_STMTSTATUS_MEMUSED 99
/*
+11
View File
@@ -352,6 +352,16 @@
# define SQLITE_DEFAULT_MEMSTATUS 1
#endif
/*
** Set the default maximum statement cache size
*/
#if !defined(SQLITE_DEFAULT_STMTCACHE_SIZE)
# define SQLITE_DEFAULT_STMTCACHE_SIZE 10
#endif
#if SQLITE_DEFAULT_STMTCACHE_SIZE<0 || SQLITE_DEFAULT_STMTCACHE_SIZE>254
# error SQLITE_DEFAULT_STMTCACHE_SIZE must be between 0 and 254
#endif
/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
@@ -1565,6 +1575,7 @@ struct sqlite3 {
u8 noSharedCache; /* True if no shared-cache backends */
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
u8 eOpenState; /* Current condition of the connection */
u8 mxCache, nCache; /* Max and current size of statement cache */
int nextPagesize; /* Pagesize after VACUUM if >0 */
i64 nChange; /* Value returned by sqlite3_changes() */
i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
+1
View File
@@ -372,6 +372,7 @@ void sqlite3FinishTrigger(
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto triggerfinish_cleanup;
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3VdbeRunOnlyOnce(v);
z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
testcase( z==0 );
sqlite3NestedParse(pParse,
+15 -7
View File
@@ -753,14 +753,20 @@ int sqlite3VdbeExec(
nProgressLimit = LARGEST_UINT64;
}
#endif
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;
if( p->rc ){
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;
}
if( p->rc==SQLITE_TOOBIG ){
/* This happens if the SQLITE_LENGTH is reduced on a cached prepared
** statement. */
goto too_big;
}
assert( (p->rc&0xff)==SQLITE_BUSY );
p->rc = SQLITE_OK;
}
assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
testcase( p->rc!=SQLITE_OK );
p->rc = SQLITE_OK;
assert( p->bIsReader || p->readOnly!=0 );
p->iCurrentTime = 0;
assert( p->explain==0 );
@@ -6631,6 +6637,7 @@ case OP_CreateBtree: { /* out2 */
Db *pDb;
sqlite3VdbeIncrWriteCounter(p, 0);
p->hSql = 0;
pOut = out2Prerelease(p, pOp);
pgno = 0;
assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY );
@@ -7702,6 +7709,7 @@ case OP_Expire: {
}else{
p->expired = pOp->p2+1;
}
p->hSql = 0;
break;
}
+3 -1
View File
@@ -262,7 +262,9 @@ int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
void sqlite3VdbeCountChanges(Vdbe*);
sqlite3 *sqlite3VdbeDb(Vdbe*);
u8 sqlite3VdbePrepareFlags(Vdbe*);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8, u32);
Vdbe *sqlite3VdbeFindInStmtCache(sqlite3*,const char*,int,u32*);
void sqlite3VdbeChangeStmtCacheSize(sqlite3*,int);
#ifdef SQLITE_ENABLE_NORMALIZE
void sqlite3VdbeAddDblquoteStr(sqlite3*,Vdbe*,const char*);
int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*);
+5
View File
@@ -470,6 +470,8 @@ struct Vdbe {
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */
u32 hSql; /* Hash for zSql. 0 if non-cacheable. */
int nSql; /* Number of bytes in zSql[] */
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_ENABLE_NORMALIZE
char *zNormSql; /* Normalization of the associated SQL statement */
@@ -496,6 +498,7 @@ struct Vdbe {
#define VDBE_READY_STATE 1 /* Ready to run but not yet started */
#define VDBE_RUN_STATE 2 /* Run in progress */
#define VDBE_HALT_STATE 3 /* Finished. Need reset() or finalize() */
#define VDBE_CACHE_STATE 4 /* In statement cache */
/*
** Structure used to store the context required by the
@@ -653,9 +656,11 @@ int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
#ifdef SQLITE_DEBUG
void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*);
void sqlite3VdbeAssertAbortable(Vdbe*);
void sqlite3VdbeCheckActiveVdbeCount(sqlite3*);
#else
# define sqlite3VdbeIncrWriteCounter(V,C)
# define sqlite3VdbeAssertAbortable(V)
# define sqlite3VdbeCheckActiveVdbeCount(D)
#endif
#if !defined(SQLITE_OMIT_SHARED_CACHE)
+16 -1
View File
@@ -110,7 +110,19 @@ int sqlite3_finalize(sqlite3_stmt *pStmt){
checkProfileCallback(db, v);
assert( v->eVdbeState>=VDBE_READY_STATE );
rc = sqlite3VdbeReset(v);
sqlite3VdbeDelete(v);
if( v->hSql>0
&& db->mxCache>0
&& v->expired==0
){
v->eVdbeState = VDBE_CACHE_STATE;
db->nCache++;
if( db->nCache>db->mxCache){
sqlite3VdbeChangeStmtCacheSize(db, db->mxCache);
}
}else{
sqlite3VdbeDelete(v);
}
sqlite3VdbeCheckActiveVdbeCount(db);
rc = sqlite3ApiExit(db, rc);
sqlite3LeaveMutexAndCloseZombie(db);
}
@@ -689,6 +701,7 @@ static int sqlite3Step(Vdbe *p){
if( p->bIsReader ) db->nVdbeRead++;
p->pc = 0;
p->eVdbeState = VDBE_RUN_STATE;
sqlite3VdbeCheckActiveVdbeCount(db);
}else
if( ALWAYS(p->eVdbeState==VDBE_HALT_STATE) ){
@@ -1842,6 +1855,8 @@ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
db->pnBytesFreed = 0;
db->lookaside.pEnd = db->lookaside.pTrueEnd;
sqlite3_mutex_leave(db->mutex);
}else if( op==SQLITE_STMTSTATUS_STATE ){
v = pVdbe->eVdbeState;
}else{
v = pVdbe->aCounter[op];
if( resetFlag ) pVdbe->aCounter[op] = 0;
+107 -6
View File
@@ -64,10 +64,29 @@ void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
va_end(ap);
}
/*
** Compute a hash on the SQL used to generate a prepared statement.
*/
static u32 sqlHash(const char *zSql, int nSql){
u32 hSql = 0;
int i;
for(i=0; i<nSql; i++){
hSql = (hSql + zSql[i]) * 0x9e3779b1;
}
hSql |= 1;
return hSql;
}
/*
** Remember the SQL string for a prepared statement.
*/
void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){
void sqlite3VdbeSetSql(
Vdbe *p, /* The VDBE whose SQL text is to be set */
const char *z, /* the SQL text */
int n, /* Number of bytes in z[] */
u8 prepFlags, /* prepFlags */
u32 hSql /* Hash of z[] used for fast cache lookups */
){
if( p==0 ) return;
p->prepFlags = prepFlags;
if( (prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){
@@ -75,8 +94,58 @@ void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){
}
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
p->nSql = n;
if( prepFlags & SQLITE_PREPARE_CACHE ){
if( hSql==0 ) hSql = sqlHash(z, n);
p->hSql = hSql;
}else{
p->hSql = 0;
}
}
/*
** Search for a cached VDBE that that implements the given SQL.
*/
Vdbe *sqlite3VdbeFindInStmtCache(
sqlite3 *db, /* The database connection holding the cache */
const char *zSql, /* Input SQL text */
int nSql, /* Size of zSql[] in bytes */
u32 *phSql /* Write the hash value here if not found */
){
Vdbe *pCache; /* Candidate statement */
u32 hSql; /* A hash of the SQL input */
assert( nSql>=0 );
hSql = sqlHash(zSql, nSql);
if( db->nCache ){
for(pCache = db->pVdbe; pCache; pCache=pCache->pVNext){
if( pCache->hSql==hSql
&& pCache->eVdbeState==VDBE_CACHE_STATE
&& pCache->nSql==nSql
&& strncmp(zSql, pCache->zSql, nSql)==0
){
pCache->eVdbeState = VDBE_READY_STATE;
db->nCache--;
if( pCache!=db->pVdbe ){
if( pCache->pVNext ){
pCache->pVNext->ppVPrev = pCache->ppVPrev;
}
*pCache->ppVPrev = pCache->pVNext;
pCache->pVNext = db->pVdbe;
pCache->ppVPrev = &db->pVdbe;
db->pVdbe->ppVPrev = &pCache->pVNext;
db->pVdbe = pCache;
}
sqlite3VdbeCheckActiveVdbeCount(db);
return pCache;
}
}
}
*phSql = hSql;
return 0;
}
#ifdef SQLITE_ENABLE_NORMALIZE
/*
** Add a new element to the Vdbe->pDblStr list.
@@ -3010,7 +3079,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
** This is a no-op if NDEBUG is defined.
*/
#ifndef NDEBUG
static void checkActiveVdbeCnt(sqlite3 *db){
void sqlite3VdbeCheckActiveVdbeCount(sqlite3 *db){
Vdbe *p;
int cnt = 0;
int nWrite = 0;
@@ -3028,10 +3097,36 @@ static void checkActiveVdbeCnt(sqlite3 *db){
assert( nWrite==db->nVdbeWrite );
assert( nRead==db->nVdbeRead );
}
#else
#define checkActiveVdbeCnt(x)
#endif
/*
** Attempt to change the statement cache size. If the statement cache
** size is reduced remove excess elements from the cache.
**
** The argument is the *desired* new statement cache size. The new
** statement cache size will not necessarily be the same size.
*/
void sqlite3VdbeChangeStmtCacheSize(sqlite3 *db, int szDesired){
assert( szDesired>=0 );
if( szDesired>100 ) szDesired = 100;
if( db->nCache>szDesired ){
Vdbe *p, *pNext;
int n = szDesired;
for(p=db->pVdbe; p; p=pNext){
pNext = p->pVNext;
if( p->hSql==0 ) continue;
if( p->eVdbeState!=VDBE_CACHE_STATE ) continue;
if( n>0 ){ n--; continue; }
sqlite3VdbeDelete(p);
assert( db->nCache>szDesired );
db->nCache--;
}
assert( db->nCache==szDesired );
}
db->mxCache = szDesired;
sqlite3VdbeCheckActiveVdbeCount(db);
}
/*
** If the Vdbe passed as the first argument opened a statement-transaction,
** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
@@ -3160,7 +3255,7 @@ int sqlite3VdbeHalt(Vdbe *p){
p->rc = SQLITE_NOMEM_BKPT;
}
closeAllCursors(p);
checkActiveVdbeCnt(db);
sqlite3VdbeCheckActiveVdbeCount(db);
/* No commit or rollback needed if the program never started or if the
** SQL statement does not read or write a database file. */
@@ -3319,7 +3414,7 @@ int sqlite3VdbeHalt(Vdbe *p){
assert( db->nVdbeRead>=db->nVdbeWrite );
assert( db->nVdbeWrite>=0 );
p->eVdbeState = VDBE_HALT_STATE;
checkActiveVdbeCnt(db);
sqlite3VdbeCheckActiveVdbeCount(db);
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
@@ -5106,6 +5201,12 @@ void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){
for(p = db->pVdbe; p; p=p->pVNext){
p->expired = iCode+1;
}
if( db->nCache>0 ){
u8 mxCache = db->mxCache;
sqlite3VdbeChangeStmtCacheSize(db, 0);
assert( db->nCache==0 );
db->mxCache = mxCache;
}
}
/*
+34 -4
View File
@@ -25,6 +25,7 @@ static const char zHelp[] =
" --output FILE Store SQL output in FILE\n"
" --pagesize N Set the page size to N\n"
" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
" --persist Use the SQLITE_PREPARE_PERSISTENT flag\n"
" --primarykey Use PRIMARY KEY instead of UNIQUE where appropriate\n"
" --repeat N Repeat each SELECT N times (default: 1)\n"
" --reprepare Reprepare each statement upon every invocation\n"
@@ -37,6 +38,7 @@ static const char zHelp[] =
" --size N Relative test size. Default=100\n"
" --strict Use STRICT table where appropriate\n"
" --stats Show statistics at the end\n"
" --stmtcache N Use a statement cache of size N\n"
" --temp N N from 0 to 9. 0: no temp table. 9: all temp tables\n"
" --testset T Run test-set T (main, cte, rtree, orm, fp, debug)\n"
" --trace Turn on SQL tracing\n"
@@ -66,6 +68,10 @@ static const char zHelp[] =
# define sqlite3_int64 sqlite_int64
#endif
#ifndef SQLITE_PREPARE_CACHE
# define SQLITE_PREPARE_CACHE 0x40000000
#endif
typedef sqlite3_uint64 u64;
/*
@@ -88,6 +94,7 @@ static struct Global {
sqlite3_int64 iTotal; /* Total time */
int bWithoutRowid; /* True for --without-rowid */
int bReprepare; /* True to reprepare the SQL on each rerun */
unsigned int mPrepFlags; /* Flags passed into sqlite3_prepare_v3() */
int bSqlOnly; /* True to print the SQL once only */
int bExplain; /* Print SQL with EXPLAIN prefix */
int bVerify; /* Try to verify that results are correct */
@@ -97,6 +104,7 @@ static struct Global {
int nRepeat; /* Repeat selects this many times */
int doCheckpoint; /* Run PRAGMA wal_checkpoint after each trans */
int nReserve; /* Reserve bytes */
int szStmtCache; /* Size of the statement cache */
const char *zWR; /* Might be WITHOUT ROWID */
const char *zNN; /* Might be NOT NULL */
const char *zPK; /* Might be UNIQUE or PRIMARY KEY */
@@ -502,7 +510,7 @@ char *speedtest1_once(const char *zFormat, ...){
if( g.bSqlOnly ){
printSql(zSql);
}else{
int rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0);
int rc = sqlite3_prepare_v3(g.db, zSql, -1, 0, &pStmt, 0);
if( rc ){
fatal_error("SQL error: %s\n", sqlite3_errmsg(g.db));
}
@@ -534,7 +542,7 @@ void speedtest1_prepare(const char *zFormat, ...){
}else{
int rc;
if( g.pStmt ) sqlite3_finalize(g.pStmt);
rc = sqlite3_prepare_v2(g.db, zSql, -1, &g.pStmt, 0);
rc = sqlite3_prepare_v3(g.db, zSql, -1, g.mPrepFlags, &g.pStmt, 0);
if( rc ){
fatal_error("SQL error: %s\n", sqlite3_errmsg(g.db));
}
@@ -602,8 +610,16 @@ void speedtest1_run(void){
#if SQLITE_VERSION_NUMBER>=3006001
if( g.bReprepare ){
sqlite3_stmt *pNew;
sqlite3_prepare_v2(g.db, sqlite3_sql(g.pStmt), -1, &pNew, 0);
sqlite3_finalize(g.pStmt);
if( g.mPrepFlags & SQLITE_PREPARE_CACHE ){
char zBuf[1000];
strncpy(zBuf, sqlite3_sql(g.pStmt), sizeof(zBuf));
zBuf[sizeof(zBuf)-1] = 0;
sqlite3_finalize(g.pStmt);
sqlite3_prepare_v3(g.db, zBuf, -1, g.mPrepFlags, &pNew, 0);
}else{
sqlite3_prepare_v2(g.db, sqlite3_sql(g.pStmt), -1, &pNew, 0);
sqlite3_finalize(g.pStmt);
}
g.pStmt = pNew;
}else
#endif
@@ -2289,6 +2305,8 @@ int main(int argc, char **argv){
if( i>=argc-1 ) fatal_error("missing arguments on %s\n", argv[i]);
g.nRepeat = integerValue(argv[i+1]);
i += 1;
}else if( strcmp(z,"persist")==0 ){
g.mPrepFlags |= SQLITE_PREPARE_PERSISTENT;
}else if( strcmp(z,"reprepare")==0 ){
g.bReprepare = 1;
#if SQLITE_VERSION_NUMBER>=3006000
@@ -2311,6 +2329,10 @@ int main(int argc, char **argv){
}else if( strcmp(z,"size")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
g.szTest = integerValue(argv[++i]);
}else if( strcmp(z,"stmtcache")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
g.szStmtCache = integerValue(argv[++i]);
g.mPrepFlags |= SQLITE_PREPARE_CACHE;
}else if( strcmp(z,"stats")==0 ){
showStats = 1;
}else if( strcmp(z,"temp")==0 ){
@@ -2405,6 +2427,14 @@ int main(int argc, char **argv){
if( rc ) fatal_error("lookaside configuration failed: %d\n", rc);
}
#endif
#ifdef SQLITE_DBCONFIG_STMTCACHE_SIZE
if( g.mPrepFlags & SQLITE_PREPARE_CACHE ){
int nCache = 0;
rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_STMTCACHE_SIZE,
g.szStmtCache, &nCache);
if( rc ) fatal_error("statement cache configuration failed: %d\n", rc);
}
#endif /* SQLITE_DBCONFIG_STMTCACHE_SIZE */
if( g.nReserve>0 ){
sqlite3_file_control(g.db, 0, SQLITE_FCNTL_RESERVE_BYTES, &g.nReserve);
}