mirror of https://github.com/sqlite/sqlite
Pull the latest trunk changes into the wal-readonly branch.
FossilOrigin-Name: 0b63b71357a65e26ecd3f3bb34a5f14feee322f4
This commit is contained in:
commit
f167694f9a
32
manifest
32
manifest
|
@ -1,5 +1,5 @@
|
|||
C Merge\sthe\slatest\strunk\schanges\sinto\sthe\swal-readonly\sbranch.
|
||||
D 2011-05-31T17:08:32.975
|
||||
C Pull\sthe\slatest\strunk\schanges\sinto\sthe\swal-readonly\sbranch.
|
||||
D 2011-06-01T19:44:57.308
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 11dcc00a8d0e5202def00e81732784fb0cc4fe1d
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
|
@ -125,13 +125,13 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
|||
F src/btree.c 0d3b39dcb79565c053e35fc12713f12d8a74d6a9
|
||||
F src/btree.h d796dc4030b3cce7f5a0cc4f2f986d2befa6b8ac
|
||||
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
|
||||
F src/build.c 0132bc6631fa617a1d28ef805921f6dbac18a514
|
||||
F src/build.c c10ab9e2c77ade99dee23554787f8acfc0c231fc
|
||||
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
|
||||
F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
|
||||
F src/delete.c cecc926c70783452f3e8eb452c728291ce1a0b21
|
||||
F src/expr.c e3cf0957c6b8faaaf7386a3bc69e53c0dc9705be
|
||||
F src/expr.c ab46ab0f0c44979a8164ca31728d7d10ae5e8106
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c a43ba8a005fb5efd1deeee06853e3a6120d46a91
|
||||
F src/func.c b9117e40975245b8504cf3625d7e321d8d4b63dc
|
||||
|
@ -179,9 +179,9 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
|
|||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||
F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff
|
||||
F src/shell.c decd04236a7ef26be5ef46d4ea963044bfad9a48
|
||||
F src/sqlite.h.in 55fe75ae0d2ee71c33283bae647443c8ec8400be
|
||||
F src/sqlite.h.in dbe88418628302c0a93671a216346acb5746211a
|
||||
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
|
||||
F src/sqliteInt.h 8936583efbbc5820e9b01befa6e76947a2be8f52
|
||||
F src/sqliteInt.h 219b21e80f46eef7cc7bb7477c12de61d00f5607
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
|
@ -230,18 +230,18 @@ F src/test_vfs.c e7855568dfa1e0ba73668d273b65605d9f8b77e8
|
|||
F src/test_vfstrace.c 0b884e06094a746da729119a2cabdc7aa790063d
|
||||
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
|
||||
F src/tokenize.c 7b0c9281b2368dc69135e7a50bd271de9af1b467
|
||||
F src/trigger.c 144cc18bb701f3286484aae4292a9531f09278c8
|
||||
F src/update.c 5bcb56e5c7380a2eecb0e71891dbd4ad7437748f
|
||||
F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60
|
||||
F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70
|
||||
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
|
||||
F src/vdbe.c 103827f560cdc48b1d455ce4d4b3573dd88f9ab4
|
||||
F src/vdbe.h 8a675fefdf7119441fe817c800a9a52440c2e797
|
||||
F src/vdbeInt.h fe8f58d305e629fff02f61f655aca1d299f1f6ae
|
||||
F src/vdbeapi.c e0e2672e0a96ae3f8575c8ecd02912a3e8a554a1
|
||||
F src/vdbeaux.c 99900868d18618a07ffaf780ecc41fd807834bde
|
||||
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
|
||||
F src/vdbe.c 2ec37637fa70ab0c694d8327ee5dcedbc0621524
|
||||
F src/vdbe.h d9c6123384189dc37d27beac1bf44688aa75b6cb
|
||||
F src/vdbeInt.h ad84226cc0adcb1185c22b70696b235a1678bb45
|
||||
F src/vdbeapi.c 0eeadc75e44a30efd996d6af6e7c5a2488e35be8
|
||||
F src/vdbeaux.c 0505dc4f7ff3cf35e219fe0a20ab798a42772b8b
|
||||
F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
|
||||
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
||||
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
|
||||
F src/vtab.c 9ba8c7fdb7d39260c033a402f6032d3e7bc5d336
|
||||
|
@ -939,7 +939,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
|||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P 6a2ea52e6c09a570428161090c2f087c66f714ec a0ae314c7f41d0146a9ee1adc576cd977219a378
|
||||
R 2d882c761e53216861edc4b651b9e13f
|
||||
P 2c6b5a28e3f6b7cb96b944d0a254f3707885f1ce e704e8690ae35decc9769a45cf8d519ccad8b79d
|
||||
R 5f4edf2ff77d011b562e3dc234f8f21d
|
||||
U drh
|
||||
Z 136bd350bac5191ea5a92cebd8db2492
|
||||
Z 99212444a62258034d706d358ee0a50e
|
||||
|
|
|
@ -1 +1 @@
|
|||
2c6b5a28e3f6b7cb96b944d0a254f3707885f1ce
|
||||
0b63b71357a65e26ecd3f3bb34a5f14feee322f4
|
|
@ -200,9 +200,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
|||
/* A minimum of one cursor is required if autoincrement is used
|
||||
* See ticket [a696379c1f08866] */
|
||||
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
|
||||
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem,
|
||||
pParse->nTab, pParse->nMaxArg, pParse->explain,
|
||||
pParse->isMultiWrite && pParse->mayAbort);
|
||||
sqlite3VdbeMakeReady(v, pParse);
|
||||
pParse->rc = SQLITE_DONE;
|
||||
pParse->colNamesSet = 0;
|
||||
}else{
|
||||
|
|
90
src/expr.c
90
src/expr.c
|
@ -555,53 +555,53 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
|||
/* Wildcard of the form "?". Assign the next variable number */
|
||||
assert( z[0]=='?' );
|
||||
pExpr->iColumn = (ynVar)(++pParse->nVar);
|
||||
}else if( z[0]=='?' ){
|
||||
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
|
||||
** use it as the variable number */
|
||||
i64 i;
|
||||
int bOk = 0==sqlite3Atoi64(&z[1], &i, sqlite3Strlen30(&z[1]), SQLITE_UTF8);
|
||||
pExpr->iColumn = (ynVar)i;
|
||||
testcase( i==0 );
|
||||
testcase( i==1 );
|
||||
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
|
||||
testcase( 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",
|
||||
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
|
||||
}
|
||||
if( i>pParse->nVar ){
|
||||
pParse->nVar = (int)i;
|
||||
}
|
||||
}else{
|
||||
/* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
|
||||
** number as the prior appearance of the same name, or if the name
|
||||
** has never appeared before, reuse the same variable number
|
||||
*/
|
||||
int i;
|
||||
u32 n;
|
||||
n = sqlite3Strlen30(z);
|
||||
for(i=0; i<pParse->nVarExpr; i++){
|
||||
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;
|
||||
ynVar x = 0;
|
||||
u32 n = sqlite3Strlen30(z);
|
||||
if( z[0]=='?' ){
|
||||
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
|
||||
** use it as the variable number */
|
||||
i64 i;
|
||||
int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
|
||||
pExpr->iColumn = x = (ynVar)i;
|
||||
testcase( i==0 );
|
||||
testcase( i==1 );
|
||||
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
|
||||
testcase( 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",
|
||||
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
|
||||
x = 0;
|
||||
}
|
||||
if( i>pParse->nVar ){
|
||||
pParse->nVar = (int)i;
|
||||
}
|
||||
}else{
|
||||
/* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
|
||||
** number as the prior appearance of the same name, or if the name
|
||||
** has never appeared before, reuse the same variable number
|
||||
*/
|
||||
ynVar i;
|
||||
for(i=0; i<pParse->nzVar; i++){
|
||||
if( pParse->azVar[i] && memcmp(pParse->azVar[i],z,n+1)==0 ){
|
||||
pExpr->iColumn = x = (ynVar)i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
|
||||
}
|
||||
if( i>=pParse->nVarExpr ){
|
||||
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( x>0 ){
|
||||
if( x>pParse->nzVar ){
|
||||
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( !db->mallocFailed ){
|
||||
assert( pParse->apVarExpr!=0 );
|
||||
pParse->apVarExpr[pParse->nVarExpr++] = pExpr;
|
||||
if( z[0]!='?' || pParse->azVar[x-1]==0 ){
|
||||
sqlite3DbFree(db, pParse->azVar[x-1]);
|
||||
pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2345,7 +2345,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||
assert( pExpr->u.zToken[0]!=0 );
|
||||
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
|
||||
if( pExpr->u.zToken[1]!=0 ){
|
||||
sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, P4_TRANSIENT);
|
||||
assert( pExpr->u.zToken[0]=='?'
|
||||
|| strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
|
||||
sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -3109,8 +3109,6 @@ int sqlite3_bind_parameter_count(sqlite3_stmt*);
|
|||
** is included as part of the name.)^
|
||||
** ^Parameters of the form "?" without a following integer have no name
|
||||
** 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.
|
||||
**
|
||||
|
|
|
@ -2230,9 +2230,8 @@ struct Parse {
|
|||
** each recursion */
|
||||
|
||||
int nVar; /* Number of '?' variables seen in the SQL so far */
|
||||
int nVarExpr; /* Number of used slots in apVarExpr[] */
|
||||
int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */
|
||||
Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */
|
||||
int nzVar; /* Number of available slots in azVar[] */
|
||||
char **azVar; /* Pointers to names of parameters */
|
||||
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
|
||||
int nAlias; /* Number of aliased result set columns */
|
||||
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->pNewTrigger==0 );
|
||||
assert( pParse->nVar==0 );
|
||||
assert( pParse->nVarExpr==0 );
|
||||
assert( pParse->nVarExprAlloc==0 );
|
||||
assert( pParse->apVarExpr==0 );
|
||||
assert( pParse->nzVar==0 );
|
||||
assert( pParse->azVar==0 );
|
||||
enableLookaside = db->lookaside.bEnabled;
|
||||
if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
|
||||
while( !db->mallocFailed && zSql[i]!=0 ){
|
||||
|
@ -508,7 +507,8 @@ abort_parse:
|
|||
}
|
||||
|
||||
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);
|
||||
while( pParse->pAinc ){
|
||||
AutoincInfo *p = pParse->pAinc;
|
||||
|
|
|
@ -988,6 +988,7 @@ case OP_Variable: { /* out2-prerelease */
|
|||
Mem *pVar; /* Value being transferred */
|
||||
|
||||
assert( pOp->p1>0 && pOp->p1<=p->nVar );
|
||||
assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
|
||||
pVar = &p->aVar[pOp->p1 - 1];
|
||||
if( sqlite3VdbeMemTooBig(pVar) ){
|
||||
goto too_big;
|
||||
|
|
|
@ -185,7 +185,7 @@ int sqlite3VdbeMakeLabel(Vdbe*);
|
|||
void sqlite3VdbeRunOnlyOnce(Vdbe*);
|
||||
void sqlite3VdbeDelete(Vdbe*);
|
||||
void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
|
||||
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int);
|
||||
void sqlite3VdbeMakeReady(Vdbe*,Parse*);
|
||||
int sqlite3VdbeFinalize(Vdbe*);
|
||||
void sqlite3VdbeResolveLabel(Vdbe*, int);
|
||||
int sqlite3VdbeCurrentAddr(Vdbe*);
|
||||
|
@ -194,6 +194,7 @@ int sqlite3VdbeCurrentAddr(Vdbe*);
|
|||
void sqlite3VdbeTrace(Vdbe*,FILE*);
|
||||
#endif
|
||||
void sqlite3VdbeResetStepResult(Vdbe*);
|
||||
void sqlite3VdbeRewind(Vdbe*);
|
||||
int sqlite3VdbeReset(Vdbe*);
|
||||
void sqlite3VdbeSetNumCols(Vdbe*,int);
|
||||
int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
|
||||
|
|
|
@ -287,11 +287,11 @@ struct Vdbe {
|
|||
Mem *aVar; /* Values for the OP_Variable opcode. */
|
||||
char **azVar; /* Name of variables */
|
||||
ynVar nVar; /* Number of entries in aVar[] */
|
||||
ynVar nzVar; /* Number of entries in azVar[] */
|
||||
u32 cacheCtr; /* VdbeCursor row cache generation counter */
|
||||
int pc; /* The program counter */
|
||||
int rc; /* Value to return */
|
||||
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 changeCntOn; /* True to update the change-counter */
|
||||
u8 expired; /* True if the VM needs to be recompiled */
|
||||
|
|
|
@ -102,7 +102,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt){
|
|||
Vdbe *v = (Vdbe*)pStmt;
|
||||
sqlite3_mutex_enter(v->db->mutex);
|
||||
rc = sqlite3VdbeReset(v);
|
||||
sqlite3VdbeMakeReady(v, -1, 0, 0, 0, 0, 0);
|
||||
sqlite3VdbeRewind(v);
|
||||
assert( (rc & (v->db->errMask))==rc );
|
||||
rc = sqlite3ApiExit(v->db, rc);
|
||||
sqlite3_mutex_leave(v->db->mutex);
|
||||
|
@ -1167,32 +1167,6 @@ int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
|
|||
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
|
||||
** 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){
|
||||
Vdbe *p = (Vdbe*)pStmt;
|
||||
if( p==0 || i<1 || i>p->nVar ){
|
||||
if( p==0 || i<1 || i>p->nzVar ){
|
||||
return 0;
|
||||
}
|
||||
createVarMap(p);
|
||||
return p->azVar[i-1];
|
||||
}
|
||||
|
||||
|
@ -1218,9 +1191,8 @@ int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
|
|||
if( p==0 ){
|
||||
return 0;
|
||||
}
|
||||
createVarMap(p);
|
||||
if( zName ){
|
||||
for(i=0; i<p->nVar; i++){
|
||||
for(i=0; i<p->nzVar; i++){
|
||||
const char *z = p->azVar[i];
|
||||
if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
|
||||
return i+1;
|
||||
|
|
229
src/vdbeaux.c
229
src/vdbeaux.c
|
@ -1391,34 +1391,13 @@ static void *allocSpace(
|
|||
}
|
||||
|
||||
/*
|
||||
** Prepare a virtual machine for execution. 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 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.
|
||||
** Rewind the VDBE back to the beginning in preparation for
|
||||
** running it.
|
||||
*/
|
||||
void sqlite3VdbeMakeReady(
|
||||
Vdbe *p, /* The VDBE */
|
||||
int nVar, /* Number of '?' see in the SQL statement */
|
||||
int nMem, /* Number of memory cells to allocate */
|
||||
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;
|
||||
|
||||
void sqlite3VdbeRewind(Vdbe *p){
|
||||
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
||||
int i;
|
||||
#endif
|
||||
assert( p!=0 );
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
|
||||
|
@ -1429,6 +1408,71 @@ void sqlite3VdbeMakeReady(
|
|||
/* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
|
||||
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
|
||||
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
|
||||
** the vdbe program. Instead they are used to allocate space for
|
||||
|
@ -1441,91 +1485,68 @@ void sqlite3VdbeMakeReady(
|
|||
nMem += nCursor;
|
||||
|
||||
/* Allocate space for memory registers, SQL variables, VDBE cursors and
|
||||
** an array to marshal SQL function arguments in. This is only done the
|
||||
** first time this function is called for a given VDBE, not when it is
|
||||
** being called from sqlite3_reset() to reset the virtual machine.
|
||||
** an array to marshal SQL function arguments in.
|
||||
*/
|
||||
if( nVar>=0 && ALWAYS(db->mallocFailed==0) ){
|
||||
u8 *zCsr = (u8 *)&p->aOp[p->nOp]; /* Memory avaliable for alloation */
|
||||
u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc]; /* First byte past available mem */
|
||||
int nByte; /* How much extra memory needed */
|
||||
zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
|
||||
zEnd = (u8*)&p->aOp[p->nOpAlloc]; /* First byte past end of zCsr[] */
|
||||
|
||||
resolveP2Values(p, &nArg);
|
||||
p->usesStmtJournal = (u8)usesStmtJournal;
|
||||
if( isExplain && nMem<10 ){
|
||||
nMem = 10;
|
||||
resolveP2Values(p, &nArg);
|
||||
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
|
||||
if( pParse->explain && nMem<10 ){
|
||||
nMem = 10;
|
||||
}
|
||||
memset(zCsr, 0, zEnd-zCsr);
|
||||
zCsr += (zCsr - (u8*)0)&7;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
|
||||
|
||||
/* Memory for registers, parameters, cursor, etc, is allocated in two
|
||||
** passes. On the first pass, we try to reuse unused space at the
|
||||
** end of the opcode array. If we are unable to satisfy all memory
|
||||
** requirements by reusing the opcode array tail, then the second
|
||||
** pass will fill in the rest using a fresh allocation.
|
||||
**
|
||||
** This two-pass approach that reuses as much memory as possible from
|
||||
** the leftover space at the end of the opcode array can significantly
|
||||
** reduce the amount of memory held by a prepared statement.
|
||||
*/
|
||||
do {
|
||||
nByte = 0;
|
||||
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
|
||||
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
|
||||
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
|
||||
&zCsr, zEnd, &nByte);
|
||||
if( nByte ){
|
||||
p->pFree = sqlite3DbMallocZero(db, nByte);
|
||||
}
|
||||
memset(zCsr, 0, zEnd-zCsr);
|
||||
zCsr += (zCsr - (u8*)0)&7;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
|
||||
zCsr = p->pFree;
|
||||
zEnd = &zCsr[nByte];
|
||||
}while( nByte && !db->mallocFailed );
|
||||
|
||||
/* Memory for registers, parameters, cursor, etc, is allocated in two
|
||||
** passes. On the first pass, we try to reuse unused space at the
|
||||
** end of the opcode array. If we are unable to satisfy all memory
|
||||
** requirements by reusing the opcode array tail, then the second
|
||||
** pass will fill in the rest using a fresh allocation.
|
||||
**
|
||||
** This two-pass approach that reuses as much memory as possible from
|
||||
** the leftover space at the end of the opcode array can significantly
|
||||
** reduce the amount of memory held by a prepared statement.
|
||||
*/
|
||||
do {
|
||||
nByte = 0;
|
||||
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
|
||||
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
|
||||
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
|
||||
&zCsr, zEnd, &nByte);
|
||||
if( nByte ){
|
||||
p->pFree = sqlite3DbMallocZero(db, nByte);
|
||||
}
|
||||
zCsr = p->pFree;
|
||||
zEnd = &zCsr[nByte];
|
||||
}while( nByte && !db->mallocFailed );
|
||||
|
||||
p->nCursor = (u16)nCursor;
|
||||
if( p->aVar ){
|
||||
p->nVar = (ynVar)nVar;
|
||||
for(n=0; n<nVar; n++){
|
||||
p->aVar[n].flags = MEM_Null;
|
||||
p->aVar[n].db = db;
|
||||
}
|
||||
}
|
||||
if( p->aMem ){
|
||||
p->aMem--; /* aMem[] goes from 1..nMem */
|
||||
p->nMem = nMem; /* not from 0..nMem-1 */
|
||||
for(n=1; n<=nMem; n++){
|
||||
p->aMem[n].flags = MEM_Null;
|
||||
p->aMem[n].db = db;
|
||||
}
|
||||
p->nCursor = (u16)nCursor;
|
||||
if( p->aVar ){
|
||||
p->nVar = (ynVar)nVar;
|
||||
for(n=0; n<nVar; n++){
|
||||
p->aVar[n].flags = MEM_Null;
|
||||
p->aVar[n].db = db;
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
for(n=1; n<p->nMem; n++){
|
||||
assert( p->aMem[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]));
|
||||
}
|
||||
#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;
|
||||
if( p->aMem ){
|
||||
p->aMem--; /* aMem[] goes from 1..nMem */
|
||||
p->nMem = nMem; /* not from 0..nMem-1 */
|
||||
for(n=1; n<=nMem; n++){
|
||||
p->aMem[n].flags = MEM_Null;
|
||||
p->aMem[n].db = db;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
p->explain = pParse->explain;
|
||||
sqlite3VdbeRewind(p);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2399,6 +2420,7 @@ void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
|
|||
*/
|
||||
void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
|
||||
SubProgram *pSub, *pNext;
|
||||
int i;
|
||||
assert( p->db==0 || p->db==db );
|
||||
releaseMemArray(p->aVar, p->nVar);
|
||||
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
|
||||
|
@ -2407,6 +2429,7 @@ void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
|
|||
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
|
||||
sqlite3DbFree(db, pSub);
|
||||
}
|
||||
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
|
||||
vdbeFreeOpArray(db, p->aOp, p->nOp);
|
||||
sqlite3DbFree(db, p->aLabel);
|
||||
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);
|
||||
sqlite3VdbeChangeP2(v, 7, pTab->nCol);
|
||||
if( !db->mallocFailed ){
|
||||
sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0);
|
||||
pParse->nVar = 1;
|
||||
pParse->nMem = 1;
|
||||
pParse->nTab = 1;
|
||||
sqlite3VdbeMakeReady(v, pParse);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue