Improvements to the way sqlite3VdbeAddOpList() works, resulting in a slightly
smaller and faster binary. FossilOrigin-Name: 88ceb588bcdb3ca86d0c58cfdeb61b5fe070872f
This commit is contained in:
parent
8631402e6a
commit
2ce1865dd8
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Add\sfurther\stests\sfor\sfts5.\sFix\ssome\sproblems\swith\sdetail=col\smode\sand\sauxiliary\sfunctions.
|
||||
D 2016-01-16T18:58:51.767
|
||||
C Improvements\sto\sthe\sway\ssqlite3VdbeAddOpList()\sworks,\sresulting\sin\sa\sslightly\nsmaller\sand\sfaster\sbinary.
|
||||
D 2016-01-16T20:50:21.742
|
||||
F Makefile.in a476545d0c8626224d0bacac85c6e2967474af81
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 01e855f958932d0d3ed62ec675fc63e2cef61fcb
|
||||
@ -336,7 +336,7 @@ F src/parse.y caad1e98edeca6960493d0c60d31b76820dd7776
|
||||
F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23
|
||||
F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
|
||||
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
|
||||
F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6
|
||||
F src/pragma.c 53c95f5454e2a8bdb25ebf1567bed6690910ce25
|
||||
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
|
||||
F src/prepare.c 74855ddbdfad6a1c4a4d5c4b0913ebb01174ba19
|
||||
F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32
|
||||
@ -409,11 +409,11 @@ F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3
|
||||
F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c b90d9d38e5e0260c2eafa3cb4c2274d8ea94da27
|
||||
F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637
|
||||
F src/vdbe.h 22f8c913bd2c8549b3d3a897da3428efbe944378
|
||||
F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189
|
||||
F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e
|
||||
F src/vdbeaux.c 906c0350f316dd13a26d8a91865f1dd7f14dc19b
|
||||
F src/vdbeblob.c fdc4a81605ae7a35ae94a55bd768b66d6be16f15
|
||||
F src/vdbeaux.c 82969fb2558e6cf57601e283f0101d0f60f5a4f2
|
||||
F src/vdbeblob.c 8542f282b58293bd61c2ea4b2125f250f4fc9543
|
||||
F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0
|
||||
F src/vdbesort.c 0971557e5d3c289e46f56a52aed2197c13251de7
|
||||
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
|
||||
@ -1417,7 +1417,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P a4258cd4613c55acacb5c7b61faa3de7eb0759d2
|
||||
R 7d01724b879e1ef98656daadba5b9cfb
|
||||
U dan
|
||||
Z d745955e2f048d17831d9a126adffb23
|
||||
P de77d6026e8035c505a704e7b8cfe5af6579d35f
|
||||
R e442832cd3e3e0853ec0a993c2468ee7
|
||||
U drh
|
||||
Z 51b7d6e877f13b345892ef271baf2a12
|
||||
|
@ -1 +1 @@
|
||||
de77d6026e8035c505a704e7b8cfe5af6579d35f
|
||||
88ceb588bcdb3ca86d0c58cfdeb61b5fe070872f
|
87
src/pragma.c
87
src/pragma.c
@ -430,15 +430,17 @@ void sqlite3Pragma(
|
||||
{ OP_Noop, 0, 0, 0},
|
||||
{ OP_ResultRow, 1, 1, 0},
|
||||
};
|
||||
int addr;
|
||||
VdbeOp *aOp;
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
if( !zRight ){
|
||||
setOneColumnName(v, "cache_size");
|
||||
pParse->nMem += 2;
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize,iLn);
|
||||
sqlite3VdbeChangeP1(v, addr, iDb);
|
||||
sqlite3VdbeChangeP1(v, addr+1, iDb);
|
||||
sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE);
|
||||
sqlite3VdbeVerifyAvailableSpace(v, ArraySize(getCacheSize));
|
||||
aOp = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize, iLn);
|
||||
assert( aOp!=0 );
|
||||
aOp[0].p1 = iDb;
|
||||
aOp[1].p1 = iDb;
|
||||
aOp[6].p1 = SQLITE_DEFAULT_CACHE_SIZE;
|
||||
}else{
|
||||
int size = sqlite3AbsInt32(sqlite3Atoi(zRight));
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
@ -684,13 +686,16 @@ void sqlite3Pragma(
|
||||
{ OP_Integer, 0, 1, 0}, /* 4 */
|
||||
{ OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
|
||||
};
|
||||
int iAddr;
|
||||
iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn);
|
||||
sqlite3VdbeChangeP1(v, iAddr, iDb);
|
||||
sqlite3VdbeChangeP1(v, iAddr+1, iDb);
|
||||
sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
|
||||
sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
|
||||
sqlite3VdbeChangeP1(v, iAddr+5, iDb);
|
||||
VdbeOp *aOp;
|
||||
int iAddr = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeVerifyAvailableSpace(v, ArraySize(setMeta6));
|
||||
aOp = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn);
|
||||
assert( aOp!=0 );
|
||||
aOp[0].p1 = iDb;
|
||||
aOp[1].p1 = iDb;
|
||||
aOp[2].p2 = iAddr+4;
|
||||
aOp[4].p1 = eAuto - 1;
|
||||
aOp[5].p1 = iDb;
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
}
|
||||
}
|
||||
@ -1396,18 +1401,6 @@ void sqlite3Pragma(
|
||||
case PragTyp_INTEGRITY_CHECK: {
|
||||
int i, j, addr, mxErr;
|
||||
|
||||
/* Code that appears at the end of the integrity check. If no error
|
||||
** messages have been generated, output OK. Otherwise output the
|
||||
** error message
|
||||
*/
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList endCode[] = {
|
||||
{ OP_AddImm, 1, 0, 0}, /* 0 */
|
||||
{ OP_If, 1, 0, 0}, /* 1 */
|
||||
{ OP_String8, 0, 3, 0}, /* 2 */
|
||||
{ OP_ResultRow, 3, 1, 0},
|
||||
};
|
||||
|
||||
int isQuick = (sqlite3Tolower(zLeft[0])=='q');
|
||||
|
||||
/* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check",
|
||||
@ -1604,10 +1597,24 @@ void sqlite3Pragma(
|
||||
#endif /* SQLITE_OMIT_BTREECOUNT */
|
||||
}
|
||||
}
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
|
||||
sqlite3VdbeChangeP2(v, addr, -mxErr);
|
||||
sqlite3VdbeJumpHere(v, addr+1);
|
||||
sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
|
||||
{
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList endCode[] = {
|
||||
{ OP_AddImm, 1, 0, 0}, /* 0 */
|
||||
{ OP_If, 1, 0, 0}, /* 1 */
|
||||
{ OP_String8, 0, 3, 0}, /* 2 */
|
||||
{ OP_ResultRow, 3, 1, 0},
|
||||
};
|
||||
VdbeOp *aOp;
|
||||
|
||||
aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
|
||||
if( aOp ){
|
||||
aOp[0].p2 = -mxErr;
|
||||
aOp[1].p2 = sqlite3VdbeCurrentAddr(v);
|
||||
aOp[2].p4type = P4_STATIC;
|
||||
aOp[2].p4.z = "ok";
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
@ -1724,11 +1731,14 @@ void sqlite3Pragma(
|
||||
{ OP_Integer, 0, 1, 0}, /* 1 */
|
||||
{ OP_SetCookie, 0, 0, 1}, /* 2 */
|
||||
};
|
||||
int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);
|
||||
sqlite3VdbeChangeP1(v, addr, iDb);
|
||||
sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight));
|
||||
sqlite3VdbeChangeP1(v, addr+2, iDb);
|
||||
sqlite3VdbeChangeP2(v, addr+2, iCookie);
|
||||
VdbeOp *aOp;
|
||||
sqlite3VdbeVerifyAvailableSpace(v, ArraySize(setCookie));
|
||||
aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);
|
||||
assert( aOp!=0 );
|
||||
aOp[0].p1 = iDb;
|
||||
aOp[1].p1 = sqlite3Atoi(zRight);
|
||||
aOp[2].p1 = iDb;
|
||||
aOp[2].p2 = iCookie;
|
||||
}else{
|
||||
/* Read the specified cookie value */
|
||||
static const VdbeOpList readCookie[] = {
|
||||
@ -1736,10 +1746,13 @@ void sqlite3Pragma(
|
||||
{ OP_ReadCookie, 0, 1, 0}, /* 1 */
|
||||
{ OP_ResultRow, 1, 1, 0}
|
||||
};
|
||||
int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie, 0);
|
||||
sqlite3VdbeChangeP1(v, addr, iDb);
|
||||
sqlite3VdbeChangeP1(v, addr+1, iDb);
|
||||
sqlite3VdbeChangeP3(v, addr+1, iCookie);
|
||||
VdbeOp *aOp;
|
||||
sqlite3VdbeVerifyAvailableSpace(v, ArraySize(readCookie));
|
||||
aOp = sqlite3VdbeAddOpList(v, ArraySize(readCookie),readCookie,0);
|
||||
assert( aOp!=0 );
|
||||
aOp[0].p1 = iDb;
|
||||
aOp[1].p1 = iDb;
|
||||
aOp[1].p3 = iCookie;
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
@ -180,7 +180,12 @@ int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
|
||||
int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
|
||||
int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
|
||||
int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
|
||||
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
|
||||
#ifdef SQLITE_DEBUG
|
||||
void sqlite3VdbeVerifyAvailableSpace(Vdbe *p, int N);
|
||||
#else
|
||||
# define sqlite3VdbeVerifyAvailableSpace(A,B)
|
||||
#endif
|
||||
VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
|
||||
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
|
||||
void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
|
||||
void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
|
||||
@ -188,7 +193,7 @@ void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
|
||||
void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
|
||||
void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
|
||||
void sqlite3VdbeJumpHere(Vdbe*, int addr);
|
||||
void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
|
||||
int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
|
||||
int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
|
||||
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
|
||||
void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
|
||||
|
@ -250,8 +250,7 @@ void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes, ...){
|
||||
for(i=0; (c = zTypes[i])!=0; i++){
|
||||
if( c=='s' ){
|
||||
const char *z = va_arg(ap, const char*);
|
||||
int addr = sqlite3VdbeAddOp2(p, z==0 ? OP_Null : OP_String8, 0, iDest++);
|
||||
if( z ) sqlite3VdbeChangeP4(p, addr, z, 0);
|
||||
sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest++, 0, z, 0);
|
||||
}else{
|
||||
assert( c=='i' );
|
||||
sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest++);
|
||||
@ -606,6 +605,17 @@ int sqlite3VdbeCurrentAddr(Vdbe *p){
|
||||
return p->nOp;
|
||||
}
|
||||
|
||||
/*
|
||||
** Verify that at least N opcode slots are available in p without
|
||||
** having to malloc for more space. This interface is used for
|
||||
** testing only.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
void sqlite3VdbeVerifyAvailableSpace(Vdbe *p, int N){
|
||||
assert( p->nOp + N <= p->pParse->nOpAlloc );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function returns a pointer to the array of opcodes associated with
|
||||
** the Vdbe passed as the first argument. It is the callers responsibility
|
||||
@ -631,19 +641,23 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a whole list of operations to the operation stack. Return the
|
||||
** address of the first operation added.
|
||||
** Add a whole list of operations to the operation stack. Return a
|
||||
** pointer to the first operation inserted.
|
||||
*/
|
||||
int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
|
||||
int addr, i;
|
||||
VdbeOp *pOut;
|
||||
VdbeOp *sqlite3VdbeAddOpList(
|
||||
Vdbe *p, /* Add opcodes to the prepared statement */
|
||||
int nOp, /* Number of opcodes to add */
|
||||
VdbeOpList const *aOp, /* The opcodes to be added */
|
||||
int iLineno /* Source-file line number of first opcode */
|
||||
){
|
||||
int i;
|
||||
VdbeOp *pOut, *pFirst;
|
||||
assert( nOp>0 );
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
|
||||
return 0;
|
||||
}
|
||||
addr = p->nOp;
|
||||
pOut = &p->aOp[addr];
|
||||
pFirst = pOut = &p->aOp[p->nOp];
|
||||
for(i=0; i<nOp; i++, aOp++, pOut++){
|
||||
pOut->opcode = aOp->opcode;
|
||||
pOut->p1 = aOp->p1;
|
||||
@ -663,12 +677,12 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
|
||||
sqlite3VdbePrintOp(0, i+p->nOp, &p->aOp[i+p->nOp]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
p->nOp += nOp;
|
||||
return addr;
|
||||
return pFirst;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS)
|
||||
@ -826,14 +840,15 @@ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
|
||||
/*
|
||||
** Change the opcode at addr into OP_Noop
|
||||
*/
|
||||
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
if( addr<p->nOp ){
|
||||
VdbeOp *pOp = &p->aOp[addr];
|
||||
sqlite3 *db = p->db;
|
||||
freeP4(db, pOp->p4type, pOp->p4.p);
|
||||
memset(pOp, 0, sizeof(pOp[0]));
|
||||
pOp->opcode = OP_Noop;
|
||||
}
|
||||
int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
VdbeOp *pOp;
|
||||
if( p->db->mallocFailed ) return 0;
|
||||
assert( addr>=0 && addr<p->nOp );
|
||||
pOp = &p->aOp[addr];
|
||||
freeP4(p->db, pOp->p4type, pOp->p4.p);
|
||||
memset(pOp, 0, sizeof(pOp[0]));
|
||||
pOp->opcode = OP_Noop;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -842,8 +857,7 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
*/
|
||||
int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
|
||||
if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
|
||||
sqlite3VdbeChangeToNoop(p, p->nOp-1);
|
||||
return 1;
|
||||
return sqlite3VdbeChangeToNoop(p, p->nOp-1);
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
|
113
src/vdbeblob.c
113
src/vdbeblob.c
@ -115,38 +115,6 @@ int sqlite3_blob_open(
|
||||
){
|
||||
int nAttempt = 0;
|
||||
int iCol; /* Index of zColumn in row-record */
|
||||
|
||||
/* This VDBE program seeks a btree cursor to the identified
|
||||
** db/table/row entry. The reason for using a vdbe program instead
|
||||
** of writing code to use the b-tree layer directly is that the
|
||||
** vdbe program will take advantage of the various transaction,
|
||||
** locking and error handling infrastructure built into the vdbe.
|
||||
**
|
||||
** After seeking the cursor, the vdbe executes an OP_ResultRow.
|
||||
** Code external to the Vdbe then "borrows" the b-tree cursor and
|
||||
** uses it to implement the blob_read(), blob_write() and
|
||||
** blob_bytes() functions.
|
||||
**
|
||||
** The sqlite3_blob_close() function finalizes the vdbe program,
|
||||
** which closes the b-tree cursor and (possibly) commits the
|
||||
** transaction.
|
||||
*/
|
||||
static const int iLn = VDBE_OFFSET_LINENO(4);
|
||||
static const VdbeOpList openBlob[] = {
|
||||
/* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */
|
||||
{OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */
|
||||
/* One of the following two instructions is replaced by an OP_Noop. */
|
||||
{OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */
|
||||
{OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */
|
||||
{OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */
|
||||
{OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */
|
||||
{OP_Column, 0, 0, 1}, /* 6 */
|
||||
{OP_ResultRow, 1, 0, 0}, /* 7 */
|
||||
{OP_Goto, 0, 4, 0}, /* 8 */
|
||||
{OP_Close, 0, 0, 0}, /* 9 */
|
||||
{OP_Halt, 0, 0, 0}, /* 10 */
|
||||
};
|
||||
|
||||
int rc = SQLITE_OK;
|
||||
char *zErr = 0;
|
||||
Table *pTab;
|
||||
@ -265,45 +233,80 @@ int sqlite3_blob_open(
|
||||
pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse);
|
||||
assert( pBlob->pStmt || db->mallocFailed );
|
||||
if( pBlob->pStmt ){
|
||||
|
||||
/* This VDBE program seeks a btree cursor to the identified
|
||||
** db/table/row entry. The reason for using a vdbe program instead
|
||||
** of writing code to use the b-tree layer directly is that the
|
||||
** vdbe program will take advantage of the various transaction,
|
||||
** locking and error handling infrastructure built into the vdbe.
|
||||
**
|
||||
** After seeking the cursor, the vdbe executes an OP_ResultRow.
|
||||
** Code external to the Vdbe then "borrows" the b-tree cursor and
|
||||
** uses it to implement the blob_read(), blob_write() and
|
||||
** blob_bytes() functions.
|
||||
**
|
||||
** The sqlite3_blob_close() function finalizes the vdbe program,
|
||||
** which closes the b-tree cursor and (possibly) commits the
|
||||
** transaction.
|
||||
*/
|
||||
static const int iLn = VDBE_OFFSET_LINENO(3);
|
||||
static const VdbeOpList openBlob[] = {
|
||||
/* {OP_Transaction, 0, 0, 0}, // inserted separately */
|
||||
{OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */
|
||||
{OP_OpenRead, 0, 0, 0}, /* 1: Open cursor 0 for reading */
|
||||
{OP_OpenWrite, 0, 0, 0}, /* 2: Open cursor 0 for read/write */
|
||||
{OP_Variable, 1, 1, 1}, /* 3: Push the rowid to the stack */
|
||||
{OP_NotExists, 0, 10, 1}, /* 4: Seek the cursor */
|
||||
{OP_Column, 0, 0, 1}, /* 5 */
|
||||
{OP_ResultRow, 1, 0, 0}, /* 6 */
|
||||
{OP_Goto, 0, 4, 0}, /* 7 */
|
||||
{OP_Close, 0, 0, 0}, /* 8 */
|
||||
{OP_Halt, 0, 0, 0}, /* 9 */
|
||||
};
|
||||
Vdbe *v = (Vdbe *)pBlob->pStmt;
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
|
||||
VdbeOp *aOp;
|
||||
|
||||
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags,
|
||||
pTab->pSchema->schema_cookie,
|
||||
pTab->pSchema->iGeneration);
|
||||
sqlite3VdbeChangeP5(v, 1);
|
||||
sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
|
||||
aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
|
||||
|
||||
/* Make sure a mutex is held on the table to be accessed */
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
|
||||
/* Configure the OP_TableLock instruction */
|
||||
if( db->mallocFailed==0 ){
|
||||
assert( aOp!=0 );
|
||||
/* Configure the OP_TableLock instruction */
|
||||
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||
sqlite3VdbeChangeToNoop(v, 1);
|
||||
aOp[0].opcode = OP_Noop;
|
||||
#else
|
||||
sqlite3VdbeChangeP1(v, 1, iDb);
|
||||
sqlite3VdbeChangeP2(v, 1, pTab->tnum);
|
||||
sqlite3VdbeChangeP3(v, 1, flags);
|
||||
sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
|
||||
aOp[0].p1 = iDb;
|
||||
aOp[0].p2 = pTab->tnum;
|
||||
aOp[0].p3 = flags;
|
||||
sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
|
||||
}
|
||||
if( db->mallocFailed==0 ){
|
||||
#endif
|
||||
|
||||
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
|
||||
** parameter of the other to pTab->tnum. */
|
||||
sqlite3VdbeChangeToNoop(v, 3 - flags);
|
||||
sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum);
|
||||
sqlite3VdbeChangeP3(v, 2 + flags, iDb);
|
||||
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
|
||||
** parameter of the other to pTab->tnum. */
|
||||
aOp[2-flags].opcode = OP_Noop;
|
||||
aOp[1+flags].p2 = pTab->tnum;
|
||||
aOp[1+flags].p3 = iDb;
|
||||
|
||||
/* Configure the number of columns. Configure the cursor to
|
||||
** think that the table has one more column than it really
|
||||
** does. An OP_Column to retrieve this imaginary column will
|
||||
** always return an SQL NULL. This is useful because it means
|
||||
** we can invoke OP_Column to fill in the vdbe cursors type
|
||||
** and offset cache without causing any IO.
|
||||
*/
|
||||
aOp[1+flags].p4type = P4_INT32;
|
||||
aOp[1+flags].p4.i = pTab->nCol+1;
|
||||
aOp[5].p2 = pTab->nCol;
|
||||
|
||||
/* Configure the number of columns. Configure the cursor to
|
||||
** think that the table has one more column than it really
|
||||
** does. An OP_Column to retrieve this imaginary column will
|
||||
** always return an SQL NULL. This is useful because it means
|
||||
** we can invoke OP_Column to fill in the vdbe cursors type
|
||||
** and offset cache without causing any IO.
|
||||
*/
|
||||
sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
|
||||
sqlite3VdbeChangeP2(v, 6, pTab->nCol);
|
||||
if( !db->mallocFailed ){
|
||||
pParse->nVar = 1;
|
||||
pParse->nMem = 1;
|
||||
pParse->nTab = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user