mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Refactor the SQL parameter processing so that parameter names for values
that are optimized out of the prepare statement are not forgotten. FossilOrigin-Name: b3aaf715b60b8a338cc6c92dad1ead4a3f7146a3
This commit is contained in:
30
manifest
30
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\sa\sproblem\sin\sthe\ssqlite3TestErrorName()\sfunction\s(used\sonly\sfor\stesting)\nthat\sappears\sto\shave\soriginated\sfrom\sa\sbad\smerge.
|
C Refactor\sthe\sSQL\sparameter\sprocessing\sso\sthat\sparameter\snames\sfor\svalues\nthat\sare\soptimized\sout\sof\sthe\sprepare\sstatement\sare\snot\sforgotten.
|
||||||
D 2011-05-31T16:50:23.129
|
D 2011-06-01T18:15:55.858
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 11dcc00a8d0e5202def00e81732784fb0cc4fe1d
|
F Makefile.in 11dcc00a8d0e5202def00e81732784fb0cc4fe1d
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -125,13 +125,13 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
|||||||
F src/btree.c 0d3b39dcb79565c053e35fc12713f12d8a74d6a9
|
F src/btree.c 0d3b39dcb79565c053e35fc12713f12d8a74d6a9
|
||||||
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
|
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
|
||||||
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
|
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
|
||||||
F src/build.c 0132bc6631fa617a1d28ef805921f6dbac18a514
|
F src/build.c c10ab9e2c77ade99dee23554787f8acfc0c231fc
|
||||||
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
|
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
|
||||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||||
F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
|
F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
|
||||||
F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
|
F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
|
||||||
F src/delete.c cecc926c70783452f3e8eb452c728291ce1a0b21
|
F src/delete.c cecc926c70783452f3e8eb452c728291ce1a0b21
|
||||||
F src/expr.c e3cf0957c6b8faaaf7386a3bc69e53c0dc9705be
|
F src/expr.c c33584bcf4ee011e28ff74e4dcef02da1dc09dd6
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c a43ba8a005fb5efd1deeee06853e3a6120d46a91
|
F src/fkey.c a43ba8a005fb5efd1deeee06853e3a6120d46a91
|
||||||
F src/func.c b9117e40975245b8504cf3625d7e321d8d4b63dc
|
F src/func.c b9117e40975245b8504cf3625d7e321d8d4b63dc
|
||||||
@@ -179,9 +179,9 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
|
|||||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||||
F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff
|
F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff
|
||||||
F src/shell.c decd04236a7ef26be5ef46d4ea963044bfad9a48
|
F src/shell.c decd04236a7ef26be5ef46d4ea963044bfad9a48
|
||||||
F src/sqlite.h.in c095996e68e0082f674f32e68ca909fc24196a2a
|
F src/sqlite.h.in 91c63a69eeddbd62182ec00dbfee390016972bdb
|
||||||
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
|
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
|
||||||
F src/sqliteInt.h d9ff5f198b5bac7ee0c6e1ea55f76897ba4dda87
|
F src/sqliteInt.h 6e58c558c57c8f44011736d5fa5295eb3130f9de
|
||||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||||
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
|
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
@@ -230,18 +230,18 @@ F src/test_vfs.c e7855568dfa1e0ba73668d273b65605d9f8b77e8
|
|||||||
F src/test_vfstrace.c 0b884e06094a746da729119a2cabdc7aa790063d
|
F src/test_vfstrace.c 0b884e06094a746da729119a2cabdc7aa790063d
|
||||||
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
|
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
|
||||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||||
F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
|
F src/tokenize.c 7b0c9281b2368dc69135e7a50bd271de9af1b467
|
||||||
F src/trigger.c 144cc18bb701f3286484aae4292a9531f09278c8
|
F src/trigger.c 144cc18bb701f3286484aae4292a9531f09278c8
|
||||||
F src/update.c 5bcb56e5c7380a2eecb0e71891dbd4ad7437748f
|
F src/update.c 5bcb56e5c7380a2eecb0e71891dbd4ad7437748f
|
||||||
F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60
|
F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60
|
||||||
F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70
|
F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70
|
||||||
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
|
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
|
||||||
F src/vdbe.c 103827f560cdc48b1d455ce4d4b3573dd88f9ab4
|
F src/vdbe.c 103827f560cdc48b1d455ce4d4b3573dd88f9ab4
|
||||||
F src/vdbe.h 8a675fefdf7119441fe817c800a9a52440c2e797
|
F src/vdbe.h d9c6123384189dc37d27beac1bf44688aa75b6cb
|
||||||
F src/vdbeInt.h fe8f58d305e629fff02f61f655aca1d299f1f6ae
|
F src/vdbeInt.h ad84226cc0adcb1185c22b70696b235a1678bb45
|
||||||
F src/vdbeapi.c e0e2672e0a96ae3f8575c8ecd02912a3e8a554a1
|
F src/vdbeapi.c 0eeadc75e44a30efd996d6af6e7c5a2488e35be8
|
||||||
F src/vdbeaux.c 99900868d18618a07ffaf780ecc41fd807834bde
|
F src/vdbeaux.c 0505dc4f7ff3cf35e219fe0a20ab798a42772b8b
|
||||||
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
|
F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
|
||||||
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
||||||
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
|
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
|
||||||
F src/vtab.c 9ba8c7fdb7d39260c033a402f6032d3e7bc5d336
|
F src/vtab.c 9ba8c7fdb7d39260c033a402f6032d3e7bc5d336
|
||||||
@@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
|||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
P 701b8a23e3ea2c94454af5d9bd1e72acb66d0fe2
|
P a0ae314c7f41d0146a9ee1adc576cd977219a378
|
||||||
R 0252c62ef68072dedfcd687577c244b5
|
R d99e1065a540709b7ea760de89dbcfd0
|
||||||
U drh
|
U drh
|
||||||
Z 32d78009c9e58634b2f842adf352a1be
|
Z ce5ce2791f47aa05a4daaafded206f56
|
||||||
|
@@ -1 +1 @@
|
|||||||
a0ae314c7f41d0146a9ee1adc576cd977219a378
|
b3aaf715b60b8a338cc6c92dad1ead4a3f7146a3
|
@@ -200,9 +200,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
|||||||
/* A minimum of one cursor is required if autoincrement is used
|
/* A minimum of one cursor is required if autoincrement is used
|
||||||
* See ticket [a696379c1f08866] */
|
* See ticket [a696379c1f08866] */
|
||||||
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
|
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
|
||||||
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem,
|
sqlite3VdbeMakeReady(v, pParse);
|
||||||
pParse->nTab, pParse->nMaxArg, pParse->explain,
|
|
||||||
pParse->isMultiWrite && pParse->mayAbort);
|
|
||||||
pParse->rc = SQLITE_DONE;
|
pParse->rc = SQLITE_DONE;
|
||||||
pParse->colNamesSet = 0;
|
pParse->colNamesSet = 0;
|
||||||
}else{
|
}else{
|
||||||
|
48
src/expr.c
48
src/expr.c
@@ -555,12 +555,15 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
|||||||
/* Wildcard of the form "?". Assign the next variable number */
|
/* Wildcard of the form "?". Assign the next variable number */
|
||||||
assert( z[0]=='?' );
|
assert( z[0]=='?' );
|
||||||
pExpr->iColumn = (ynVar)(++pParse->nVar);
|
pExpr->iColumn = (ynVar)(++pParse->nVar);
|
||||||
}else if( z[0]=='?' ){
|
}else{
|
||||||
|
ynVar x = 0;
|
||||||
|
u32 n = sqlite3Strlen30(z);
|
||||||
|
if( z[0]=='?' ){
|
||||||
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
|
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
|
||||||
** use it as the variable number */
|
** use it as the variable number */
|
||||||
i64 i;
|
i64 i;
|
||||||
int bOk = 0==sqlite3Atoi64(&z[1], &i, sqlite3Strlen30(&z[1]), SQLITE_UTF8);
|
int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
|
||||||
pExpr->iColumn = (ynVar)i;
|
pExpr->iColumn = x = (ynVar)i;
|
||||||
testcase( i==0 );
|
testcase( i==0 );
|
||||||
testcase( i==1 );
|
testcase( i==1 );
|
||||||
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
|
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
|
||||||
@@ -568,6 +571,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
|||||||
if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
|
if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
|
||||||
sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
|
sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
|
||||||
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
|
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
|
||||||
|
x = 0;
|
||||||
}
|
}
|
||||||
if( i>pParse->nVar ){
|
if( i>pParse->nVar ){
|
||||||
pParse->nVar = (int)i;
|
pParse->nVar = (int)i;
|
||||||
@@ -577,31 +581,27 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
|||||||
** number as the prior appearance of the same name, or if the name
|
** number as the prior appearance of the same name, or if the name
|
||||||
** has never appeared before, reuse the same variable number
|
** has never appeared before, reuse the same variable number
|
||||||
*/
|
*/
|
||||||
int i;
|
ynVar i;
|
||||||
u32 n;
|
for(i=0; i<pParse->nzVar; i++){
|
||||||
n = sqlite3Strlen30(z);
|
if( pParse->azVar[i] && memcmp(pParse->azVar[i],z,n+1)==0 ){
|
||||||
for(i=0; i<pParse->nVarExpr; i++){
|
pExpr->iColumn = x = (ynVar)i+1;
|
||||||
Expr *pE = pParse->apVarExpr[i];
|
|
||||||
assert( pE!=0 );
|
|
||||||
if( memcmp(pE->u.zToken, z, n)==0 && pE->u.zToken[n]==0 ){
|
|
||||||
pExpr->iColumn = pE->iColumn;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( i>=pParse->nVarExpr ){
|
if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
|
||||||
pExpr->iColumn = (ynVar)(++pParse->nVar);
|
|
||||||
if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){
|
|
||||||
pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10;
|
|
||||||
pParse->apVarExpr =
|
|
||||||
sqlite3DbReallocOrFree(
|
|
||||||
db,
|
|
||||||
pParse->apVarExpr,
|
|
||||||
pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if( !db->mallocFailed ){
|
if( x>0 ){
|
||||||
assert( pParse->apVarExpr!=0 );
|
if( x>pParse->nzVar ){
|
||||||
pParse->apVarExpr[pParse->nVarExpr++] = pExpr;
|
char **a;
|
||||||
|
a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
|
||||||
|
if( a==0 ) return; /* Error reported through db->mallocFailed */
|
||||||
|
pParse->azVar = a;
|
||||||
|
memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
|
||||||
|
pParse->nzVar = x;
|
||||||
|
}
|
||||||
|
if( z[0]!='?' || pParse->azVar[x-1]==0 ){
|
||||||
|
sqlite3DbFree(db, pParse->azVar[x-1]);
|
||||||
|
pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3068,8 +3068,6 @@ int sqlite3_bind_parameter_count(sqlite3_stmt*);
|
|||||||
** is included as part of the name.)^
|
** is included as part of the name.)^
|
||||||
** ^Parameters of the form "?" without a following integer have no name
|
** ^Parameters of the form "?" without a following integer have no name
|
||||||
** and are referred to as "nameless" or "anonymous parameters".
|
** and are referred to as "nameless" or "anonymous parameters".
|
||||||
** ^Any parameter that is optimized out of the prepared statement by the
|
|
||||||
** query planner becomes a nameless or anonymous parameter.
|
|
||||||
**
|
**
|
||||||
** ^The first host parameter has an index of 1, not 0.
|
** ^The first host parameter has an index of 1, not 0.
|
||||||
**
|
**
|
||||||
|
@@ -2230,9 +2230,8 @@ struct Parse {
|
|||||||
** each recursion */
|
** each recursion */
|
||||||
|
|
||||||
int nVar; /* Number of '?' variables seen in the SQL so far */
|
int nVar; /* Number of '?' variables seen in the SQL so far */
|
||||||
int nVarExpr; /* Number of used slots in apVarExpr[] */
|
int nzVar; /* Number of available slots in azVar[] */
|
||||||
int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */
|
char **azVar; /* Pointers to names of parameters */
|
||||||
Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */
|
|
||||||
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
|
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
|
||||||
int nAlias; /* Number of aliased result set columns */
|
int nAlias; /* Number of aliased result set columns */
|
||||||
int nAliasAlloc; /* Number of allocated slots for aAlias[] */
|
int nAliasAlloc; /* Number of allocated slots for aAlias[] */
|
||||||
|
@@ -412,9 +412,8 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
|||||||
assert( pParse->pNewTable==0 );
|
assert( pParse->pNewTable==0 );
|
||||||
assert( pParse->pNewTrigger==0 );
|
assert( pParse->pNewTrigger==0 );
|
||||||
assert( pParse->nVar==0 );
|
assert( pParse->nVar==0 );
|
||||||
assert( pParse->nVarExpr==0 );
|
assert( pParse->nzVar==0 );
|
||||||
assert( pParse->nVarExprAlloc==0 );
|
assert( pParse->azVar==0 );
|
||||||
assert( pParse->apVarExpr==0 );
|
|
||||||
enableLookaside = db->lookaside.bEnabled;
|
enableLookaside = db->lookaside.bEnabled;
|
||||||
if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
|
if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
|
||||||
while( !db->mallocFailed && zSql[i]!=0 ){
|
while( !db->mallocFailed && zSql[i]!=0 ){
|
||||||
@@ -508,7 +507,8 @@ abort_parse:
|
|||||||
}
|
}
|
||||||
|
|
||||||
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
|
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
|
||||||
sqlite3DbFree(db, pParse->apVarExpr);
|
for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
|
||||||
|
sqlite3DbFree(db, pParse->azVar);
|
||||||
sqlite3DbFree(db, pParse->aAlias);
|
sqlite3DbFree(db, pParse->aAlias);
|
||||||
while( pParse->pAinc ){
|
while( pParse->pAinc ){
|
||||||
AutoincInfo *p = pParse->pAinc;
|
AutoincInfo *p = pParse->pAinc;
|
||||||
|
@@ -185,7 +185,7 @@ int sqlite3VdbeMakeLabel(Vdbe*);
|
|||||||
void sqlite3VdbeRunOnlyOnce(Vdbe*);
|
void sqlite3VdbeRunOnlyOnce(Vdbe*);
|
||||||
void sqlite3VdbeDelete(Vdbe*);
|
void sqlite3VdbeDelete(Vdbe*);
|
||||||
void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
|
void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
|
||||||
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int);
|
void sqlite3VdbeMakeReady(Vdbe*,Parse*);
|
||||||
int sqlite3VdbeFinalize(Vdbe*);
|
int sqlite3VdbeFinalize(Vdbe*);
|
||||||
void sqlite3VdbeResolveLabel(Vdbe*, int);
|
void sqlite3VdbeResolveLabel(Vdbe*, int);
|
||||||
int sqlite3VdbeCurrentAddr(Vdbe*);
|
int sqlite3VdbeCurrentAddr(Vdbe*);
|
||||||
@@ -194,6 +194,7 @@ int sqlite3VdbeCurrentAddr(Vdbe*);
|
|||||||
void sqlite3VdbeTrace(Vdbe*,FILE*);
|
void sqlite3VdbeTrace(Vdbe*,FILE*);
|
||||||
#endif
|
#endif
|
||||||
void sqlite3VdbeResetStepResult(Vdbe*);
|
void sqlite3VdbeResetStepResult(Vdbe*);
|
||||||
|
void sqlite3VdbeRewind(Vdbe*);
|
||||||
int sqlite3VdbeReset(Vdbe*);
|
int sqlite3VdbeReset(Vdbe*);
|
||||||
void sqlite3VdbeSetNumCols(Vdbe*,int);
|
void sqlite3VdbeSetNumCols(Vdbe*,int);
|
||||||
int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
|
int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
|
||||||
|
@@ -287,11 +287,11 @@ struct Vdbe {
|
|||||||
Mem *aVar; /* Values for the OP_Variable opcode. */
|
Mem *aVar; /* Values for the OP_Variable opcode. */
|
||||||
char **azVar; /* Name of variables */
|
char **azVar; /* Name of variables */
|
||||||
ynVar nVar; /* Number of entries in aVar[] */
|
ynVar nVar; /* Number of entries in aVar[] */
|
||||||
|
ynVar nzVar; /* Number of entries in azVar[] */
|
||||||
u32 cacheCtr; /* VdbeCursor row cache generation counter */
|
u32 cacheCtr; /* VdbeCursor row cache generation counter */
|
||||||
int pc; /* The program counter */
|
int pc; /* The program counter */
|
||||||
int rc; /* Value to return */
|
int rc; /* Value to return */
|
||||||
u8 errorAction; /* Recovery action to do in case of an error */
|
u8 errorAction; /* Recovery action to do in case of an error */
|
||||||
u8 okVar; /* True if azVar[] has been initialized */
|
|
||||||
u8 explain; /* True if EXPLAIN present on SQL command */
|
u8 explain; /* True if EXPLAIN present on SQL command */
|
||||||
u8 changeCntOn; /* True to update the change-counter */
|
u8 changeCntOn; /* True to update the change-counter */
|
||||||
u8 expired; /* True if the VM needs to be recompiled */
|
u8 expired; /* True if the VM needs to be recompiled */
|
||||||
|
@@ -102,7 +102,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt){
|
|||||||
Vdbe *v = (Vdbe*)pStmt;
|
Vdbe *v = (Vdbe*)pStmt;
|
||||||
sqlite3_mutex_enter(v->db->mutex);
|
sqlite3_mutex_enter(v->db->mutex);
|
||||||
rc = sqlite3VdbeReset(v);
|
rc = sqlite3VdbeReset(v);
|
||||||
sqlite3VdbeMakeReady(v, -1, 0, 0, 0, 0, 0);
|
sqlite3VdbeRewind(v);
|
||||||
assert( (rc & (v->db->errMask))==rc );
|
assert( (rc & (v->db->errMask))==rc );
|
||||||
rc = sqlite3ApiExit(v->db, rc);
|
rc = sqlite3ApiExit(v->db, rc);
|
||||||
sqlite3_mutex_leave(v->db->mutex);
|
sqlite3_mutex_leave(v->db->mutex);
|
||||||
@@ -1167,32 +1167,6 @@ int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
|
|||||||
return p ? p->nVar : 0;
|
return p ? p->nVar : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Create a mapping from variable numbers to variable names
|
|
||||||
** in the Vdbe.azVar[] array, if such a mapping does not already
|
|
||||||
** exist.
|
|
||||||
*/
|
|
||||||
static void createVarMap(Vdbe *p){
|
|
||||||
if( !p->okVar ){
|
|
||||||
int j;
|
|
||||||
Op *pOp;
|
|
||||||
sqlite3_mutex_enter(p->db->mutex);
|
|
||||||
/* The race condition here is harmless. If two threads call this
|
|
||||||
** routine on the same Vdbe at the same time, they both might end
|
|
||||||
** up initializing the Vdbe.azVar[] array. That is a little extra
|
|
||||||
** work but it results in the same answer.
|
|
||||||
*/
|
|
||||||
for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){
|
|
||||||
if( pOp->opcode==OP_Variable ){
|
|
||||||
assert( pOp->p1>0 && pOp->p1<=p->nVar );
|
|
||||||
p->azVar[pOp->p1-1] = pOp->p4.z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p->okVar = 1;
|
|
||||||
sqlite3_mutex_leave(p->db->mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Return the name of a wildcard parameter. Return NULL if the index
|
** Return the name of a wildcard parameter. Return NULL if the index
|
||||||
** is out of range or if the wildcard is unnamed.
|
** is out of range or if the wildcard is unnamed.
|
||||||
@@ -1201,10 +1175,9 @@ static void createVarMap(Vdbe *p){
|
|||||||
*/
|
*/
|
||||||
const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
|
const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
|
||||||
Vdbe *p = (Vdbe*)pStmt;
|
Vdbe *p = (Vdbe*)pStmt;
|
||||||
if( p==0 || i<1 || i>p->nVar ){
|
if( p==0 || i<1 || i>p->nzVar ){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
createVarMap(p);
|
|
||||||
return p->azVar[i-1];
|
return p->azVar[i-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1218,9 +1191,8 @@ int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
|
|||||||
if( p==0 ){
|
if( p==0 ){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
createVarMap(p);
|
|
||||||
if( zName ){
|
if( zName ){
|
||||||
for(i=0; i<p->nVar; i++){
|
for(i=0; i<p->nzVar; i++){
|
||||||
const char *z = p->azVar[i];
|
const char *z = p->azVar[i];
|
||||||
if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
|
if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
|
||||||
return i+1;
|
return i+1;
|
||||||
|
147
src/vdbeaux.c
147
src/vdbeaux.c
@@ -1391,34 +1391,13 @@ static void *allocSpace(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Prepare a virtual machine for execution. This involves things such
|
** Rewind the VDBE back to the beginning in preparation for
|
||||||
** as allocating stack space and initializing the program counter.
|
** running it.
|
||||||
** After the VDBE has be prepped, it can be executed by one or more
|
|
||||||
** calls to sqlite3VdbeExec().
|
|
||||||
**
|
|
||||||
** This is the only way to move a VDBE from VDBE_MAGIC_INIT to
|
|
||||||
** VDBE_MAGIC_RUN.
|
|
||||||
**
|
|
||||||
** This function may be called more than once on a single virtual machine.
|
|
||||||
** The first call is made while compiling the SQL statement. Subsequent
|
|
||||||
** calls are made as part of the process of resetting a statement to be
|
|
||||||
** re-executed (from a call to sqlite3_reset()). The nVar, nMem, nCursor
|
|
||||||
** and isExplain parameters are only passed correct values the first time
|
|
||||||
** the function is called. On subsequent calls, from sqlite3_reset(), nVar
|
|
||||||
** is passed -1 and nMem, nCursor and isExplain are all passed zero.
|
|
||||||
*/
|
*/
|
||||||
void sqlite3VdbeMakeReady(
|
void sqlite3VdbeRewind(Vdbe *p){
|
||||||
Vdbe *p, /* The VDBE */
|
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
||||||
int nVar, /* Number of '?' see in the SQL statement */
|
int i;
|
||||||
int nMem, /* Number of memory cells to allocate */
|
#endif
|
||||||
int nCursor, /* Number of cursors to allocate */
|
|
||||||
int nArg, /* Maximum number of args in SubPrograms */
|
|
||||||
int isExplain, /* True if the EXPLAIN keywords is present */
|
|
||||||
int usesStmtJournal /* True to set Vdbe.usesStmtJournal */
|
|
||||||
){
|
|
||||||
int n;
|
|
||||||
sqlite3 *db = p->db;
|
|
||||||
|
|
||||||
assert( p!=0 );
|
assert( p!=0 );
|
||||||
assert( p->magic==VDBE_MAGIC_INIT );
|
assert( p->magic==VDBE_MAGIC_INIT );
|
||||||
|
|
||||||
@@ -1429,6 +1408,71 @@ void sqlite3VdbeMakeReady(
|
|||||||
/* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
|
/* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
|
||||||
p->magic = VDBE_MAGIC_RUN;
|
p->magic = VDBE_MAGIC_RUN;
|
||||||
|
|
||||||
|
#ifdef SQLITE_DEBUG
|
||||||
|
for(i=1; i<p->nMem; i++){
|
||||||
|
assert( p->aMem[i].db==p->db );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
p->pc = -1;
|
||||||
|
p->rc = SQLITE_OK;
|
||||||
|
p->errorAction = OE_Abort;
|
||||||
|
p->magic = VDBE_MAGIC_RUN;
|
||||||
|
p->nChange = 0;
|
||||||
|
p->cacheCtr = 1;
|
||||||
|
p->minWriteFileFormat = 255;
|
||||||
|
p->iStatement = 0;
|
||||||
|
p->nFkConstraint = 0;
|
||||||
|
#ifdef VDBE_PROFILE
|
||||||
|
for(i=0; i<p->nOp; i++){
|
||||||
|
p->aOp[i].cnt = 0;
|
||||||
|
p->aOp[i].cycles = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Prepare a virtual machine for execution for the first time after
|
||||||
|
** creating the virtual machine. This involves things such
|
||||||
|
** as allocating stack space and initializing the program counter.
|
||||||
|
** After the VDBE has be prepped, it can be executed by one or more
|
||||||
|
** calls to sqlite3VdbeExec().
|
||||||
|
**
|
||||||
|
** This function may be called exact once on a each virtual machine.
|
||||||
|
** After this routine is called the VM has been "packaged" and is ready
|
||||||
|
** to run. After this routine is called, futher calls to
|
||||||
|
** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects
|
||||||
|
** the Vdbe from the Parse object that helped generate it so that the
|
||||||
|
** the Vdbe becomes an independent entity and the Parse object can be
|
||||||
|
** destroyed.
|
||||||
|
**
|
||||||
|
** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back
|
||||||
|
** to its initial state after it has been run.
|
||||||
|
*/
|
||||||
|
void sqlite3VdbeMakeReady(
|
||||||
|
Vdbe *p, /* The VDBE */
|
||||||
|
Parse *pParse /* Parsing context */
|
||||||
|
){
|
||||||
|
sqlite3 *db; /* The database connection */
|
||||||
|
int nVar; /* Number of parameters */
|
||||||
|
int nMem; /* Number of VM memory registers */
|
||||||
|
int nCursor; /* Number of cursors required */
|
||||||
|
int nArg; /* Number of arguments in subprograms */
|
||||||
|
int n; /* Loop counter */
|
||||||
|
u8 *zCsr; /* Memory available for allocation */
|
||||||
|
u8 *zEnd; /* First byte past allocated memory */
|
||||||
|
int nByte; /* How much extra memory is needed */
|
||||||
|
|
||||||
|
assert( p!=0 );
|
||||||
|
assert( p->nOp>0 );
|
||||||
|
assert( pParse!=0 );
|
||||||
|
assert( p->magic==VDBE_MAGIC_INIT );
|
||||||
|
db = p->db;
|
||||||
|
assert( db->mallocFailed==0 );
|
||||||
|
nVar = pParse->nVar;
|
||||||
|
nMem = pParse->nMem;
|
||||||
|
nCursor = pParse->nTab;
|
||||||
|
nArg = pParse->nMaxArg;
|
||||||
|
|
||||||
/* For each cursor required, also allocate a memory cell. Memory
|
/* For each cursor required, also allocate a memory cell. Memory
|
||||||
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
|
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
|
||||||
** the vdbe program. Instead they are used to allocate space for
|
** the vdbe program. Instead they are used to allocate space for
|
||||||
@@ -1441,18 +1485,14 @@ void sqlite3VdbeMakeReady(
|
|||||||
nMem += nCursor;
|
nMem += nCursor;
|
||||||
|
|
||||||
/* Allocate space for memory registers, SQL variables, VDBE cursors and
|
/* Allocate space for memory registers, SQL variables, VDBE cursors and
|
||||||
** an array to marshal SQL function arguments in. This is only done the
|
** an array to marshal SQL function arguments in.
|
||||||
** first time this function is called for a given VDBE, not when it is
|
|
||||||
** being called from sqlite3_reset() to reset the virtual machine.
|
|
||||||
*/
|
*/
|
||||||
if( nVar>=0 && ALWAYS(db->mallocFailed==0) ){
|
zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
|
||||||
u8 *zCsr = (u8 *)&p->aOp[p->nOp]; /* Memory avaliable for alloation */
|
zEnd = (u8*)&p->aOp[p->nOpAlloc]; /* First byte past end of zCsr[] */
|
||||||
u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc]; /* First byte past available mem */
|
|
||||||
int nByte; /* How much extra memory needed */
|
|
||||||
|
|
||||||
resolveP2Values(p, &nArg);
|
resolveP2Values(p, &nArg);
|
||||||
p->usesStmtJournal = (u8)usesStmtJournal;
|
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
|
||||||
if( isExplain && nMem<10 ){
|
if( pParse->explain && nMem<10 ){
|
||||||
nMem = 10;
|
nMem = 10;
|
||||||
}
|
}
|
||||||
memset(zCsr, 0, zEnd-zCsr);
|
memset(zCsr, 0, zEnd-zCsr);
|
||||||
@@ -1492,6 +1532,11 @@ void sqlite3VdbeMakeReady(
|
|||||||
p->aVar[n].db = db;
|
p->aVar[n].db = db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if( p->azVar ){
|
||||||
|
p->nzVar = pParse->nzVar;
|
||||||
|
memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0]));
|
||||||
|
memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0]));
|
||||||
|
}
|
||||||
if( p->aMem ){
|
if( p->aMem ){
|
||||||
p->aMem--; /* aMem[] goes from 1..nMem */
|
p->aMem--; /* aMem[] goes from 1..nMem */
|
||||||
p->nMem = nMem; /* not from 0..nMem-1 */
|
p->nMem = nMem; /* not from 0..nMem-1 */
|
||||||
@@ -1500,32 +1545,8 @@ void sqlite3VdbeMakeReady(
|
|||||||
p->aMem[n].db = db;
|
p->aMem[n].db = db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
p->explain = pParse->explain;
|
||||||
#ifdef SQLITE_DEBUG
|
sqlite3VdbeRewind(p);
|
||||||
for(n=1; n<p->nMem; n++){
|
|
||||||
assert( p->aMem[n].db==db );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
p->pc = -1;
|
|
||||||
p->rc = SQLITE_OK;
|
|
||||||
p->errorAction = OE_Abort;
|
|
||||||
p->explain |= isExplain;
|
|
||||||
p->magic = VDBE_MAGIC_RUN;
|
|
||||||
p->nChange = 0;
|
|
||||||
p->cacheCtr = 1;
|
|
||||||
p->minWriteFileFormat = 255;
|
|
||||||
p->iStatement = 0;
|
|
||||||
p->nFkConstraint = 0;
|
|
||||||
#ifdef VDBE_PROFILE
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0; i<p->nOp; i++){
|
|
||||||
p->aOp[i].cnt = 0;
|
|
||||||
p->aOp[i].cycles = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2399,6 +2420,7 @@ void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
|
|||||||
*/
|
*/
|
||||||
void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
|
void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
|
||||||
SubProgram *pSub, *pNext;
|
SubProgram *pSub, *pNext;
|
||||||
|
int i;
|
||||||
assert( p->db==0 || p->db==db );
|
assert( p->db==0 || p->db==db );
|
||||||
releaseMemArray(p->aVar, p->nVar);
|
releaseMemArray(p->aVar, p->nVar);
|
||||||
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
|
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
|
||||||
@@ -2407,6 +2429,7 @@ void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
|
|||||||
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
|
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
|
||||||
sqlite3DbFree(db, pSub);
|
sqlite3DbFree(db, pSub);
|
||||||
}
|
}
|
||||||
|
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
|
||||||
vdbeFreeOpArray(db, p->aOp, p->nOp);
|
vdbeFreeOpArray(db, p->aOp, p->nOp);
|
||||||
sqlite3DbFree(db, p->aLabel);
|
sqlite3DbFree(db, p->aLabel);
|
||||||
sqlite3DbFree(db, p->aColName);
|
sqlite3DbFree(db, p->aColName);
|
||||||
|
@@ -297,7 +297,10 @@ int sqlite3_blob_open(
|
|||||||
sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
|
sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
|
||||||
sqlite3VdbeChangeP2(v, 7, pTab->nCol);
|
sqlite3VdbeChangeP2(v, 7, pTab->nCol);
|
||||||
if( !db->mallocFailed ){
|
if( !db->mallocFailed ){
|
||||||
sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0);
|
pParse->nVar = 1;
|
||||||
|
pParse->nMem = 1;
|
||||||
|
pParse->nTab = 1;
|
||||||
|
sqlite3VdbeMakeReady(v, pParse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user