Begin breaking appear the sqlite3VdbeList() routine into subroutines that
can be reused by the bytecode() table. FossilOrigin-Name: 2c4dd79fbd4b9f72634a732abb9ed833cd8c9b05fe1e10af8f23e6d6ec023c7c
This commit is contained in:
parent
691b5c54b8
commit
356cd76aa8
17
manifest
17
manifest
@ -1,5 +1,5 @@
|
||||
C Infrastructure\sfor\sthe\sbytecode()\stable-valued\sfunction.\s\sThe\sfunction\sitself\nis\snot\syet\simplemented.
|
||||
D 2020-03-23T15:49:22.754
|
||||
C Begin\sbreaking\sappear\sthe\ssqlite3VdbeList()\sroutine\sinto\ssubroutines\sthat\ncan\sbe\sreused\sby\sthe\sbytecode()\stable.
|
||||
D 2020-03-23T17:24:46.014
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -605,9 +605,9 @@ F src/util.c a285c1e026907b69fa2592bd05047a565a1d8a1aef2b73c924b6a8ffe772871a
|
||||
F src/vacuum.c 813b510ba887fee6492bcb11f2bf77d7eb58b232b83649136372e0a2fc17f4b9
|
||||
F src/vdbe.c c1c123c6248fa88940b932a00bcc75056921b6d046d45a82566cb97415d2299c
|
||||
F src/vdbe.h 07b8c636a87df8b6e58f29d6badd7f10d5844353deff1d7c88ed1c2bfe3bbd35
|
||||
F src/vdbeInt.h 0b728ee662862a38b1912af741e2ac64f524de3c77aa86cf4306c42bdcd9de59
|
||||
F src/vdbeInt.h 198e552a1a8945061c7576d3d7f8c8603300bbbb9ba0a337184bf13a7cdda65d
|
||||
F src/vdbeapi.c 1252d80c548711e47a6d84dae88ed4e95d3fbb4e7bd0eaa1347299af7efddf02
|
||||
F src/vdbeaux.c b78b4b71e04643f63820f074ece069834ffa658580546e9f248d5d85966daed2
|
||||
F src/vdbeaux.c 46991da5699ff4986c15264c46d6300a56c008b758adade974dcebb5b9dba74e
|
||||
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
|
||||
F src/vdbemem.c 39b942ecca179f4f30a32b54579a85d74ccaefa5af2a0ad2700abe5ef0768b22
|
||||
F src/vdbesort.c 2be76d26998ce2b3324cdcc9f6443728e54b6c7677c553ad909c7d7cfab587df
|
||||
@ -1861,10 +1861,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 5d14a1c4f2fc17de98ad685ad1422cdfda89dfccb00afcaf32ee416b6f84f525
|
||||
R 3485af640bb73943f778dcc7ece65b48
|
||||
T *branch * bytecode-function
|
||||
T *sym-bytecode-function *
|
||||
T -sym-trunk *
|
||||
P 2795f0d633577e0de66b389d9e8e44c55e85975bdc62f1a0b8f93959d19b22bf
|
||||
R d0c0c7fad919870cffac31ef6d1a6170
|
||||
U drh
|
||||
Z c3d3bb21394129afccd09dd7aadc133f
|
||||
Z bedd18e23757a54ddb7ae33ec04cb1e6
|
||||
|
@ -1 +1 @@
|
||||
2795f0d633577e0de66b389d9e8e44c55e85975bdc62f1a0b8f93959d19b22bf
|
||||
2c4dd79fbd4b9f72634a732abb9ed833cd8c9b05fe1e10af8f23e6d6ec023c7c
|
@ -497,6 +497,7 @@ int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
|
||||
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
|
||||
int sqlite3VdbeExec(Vdbe*);
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**);
|
||||
int sqlite3VdbeList(Vdbe*);
|
||||
#endif
|
||||
int sqlite3VdbeHalt(Vdbe*);
|
||||
|
183
src/vdbeaux.c
183
src/vdbeaux.c
@ -1943,6 +1943,108 @@ void sqlite3VdbeFrameMemDel(void *pArg){
|
||||
pFrame->v->pDelFrame = pFrame;
|
||||
}
|
||||
|
||||
/*
|
||||
** Locate the next opcode to be displayed in EXPLAIN or EXPLAIN
|
||||
** QUERY PLAN output.
|
||||
**
|
||||
** Return SQLITE_ROW on success. Return SQLITE_DONE if there are no
|
||||
** more opcodes to be displayed.
|
||||
*/
|
||||
int sqlite3VdbeNextOpcode(
|
||||
Vdbe *p, /* The statement being explained */
|
||||
Mem *pSub, /* Storage for keeping track of subprogram nesting */
|
||||
int bEqp, /* True to return only OP_Explain opcodes */
|
||||
int *piPc, /* IN/OUT: Current rowid. Overwritten with next rowid */
|
||||
int *piAddr, /* OUT: Write index into (*paOp)[] here */
|
||||
Op **paOp /* OUT: Write the opcode array here */
|
||||
){
|
||||
int nRow; /* Stop when row count reaches this */
|
||||
int nSub = 0; /* Number of sub-vdbes seen so far */
|
||||
SubProgram **apSub = 0; /* Array of sub-vdbes */
|
||||
int i; /* Next instruction address */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
Op *aOp; /* Opcode array */
|
||||
int iPc; /* Rowid. Copy of value in *piPc */
|
||||
|
||||
/* When the number of output rows reaches nRow, that means the
|
||||
** listing has finished and sqlite3_step() should return SQLITE_DONE.
|
||||
** nRow is the sum of the number of rows in the main program, plus
|
||||
** the sum of the number of rows in all trigger subprograms encountered
|
||||
** so far. The nRow value will increase as new trigger subprograms are
|
||||
** encountered, but p->pc will eventually catch up to nRow.
|
||||
*/
|
||||
nRow = p->nOp;
|
||||
if( pSub!=0 ){
|
||||
if( pSub->flags&MEM_Blob ){
|
||||
/* pSub is initiallly NULL. It is initialized to a BLOB by
|
||||
** the P4_SUBPROGRAM processing logic below */
|
||||
nSub = pSub->n/sizeof(Vdbe*);
|
||||
apSub = (SubProgram **)pSub->z;
|
||||
}
|
||||
for(i=0; i<nSub; i++){
|
||||
nRow += apSub[i]->nOp;
|
||||
}
|
||||
}
|
||||
iPc = *piPc;
|
||||
while(1){ /* Loop exits via break */
|
||||
i = iPc++;
|
||||
if( i>=nRow ){
|
||||
p->rc = SQLITE_OK;
|
||||
rc = SQLITE_DONE;
|
||||
break;
|
||||
}
|
||||
if( i<p->nOp ){
|
||||
/* The rowid is small enough that we are still in the
|
||||
** main program. */
|
||||
aOp = p->aOp;
|
||||
}else{
|
||||
/* We are currently listing subprograms. Figure out which one and
|
||||
** pick up the appropriate opcode. */
|
||||
int j;
|
||||
i -= p->nOp;
|
||||
assert( apSub!=0 );
|
||||
assert( nSub>0 );
|
||||
for(j=0; i>=apSub[j]->nOp; j++){
|
||||
i -= apSub[j]->nOp;
|
||||
assert( i<apSub[j]->nOp || j+1<nSub );
|
||||
}
|
||||
aOp = apSub[j]->aOp;
|
||||
}
|
||||
|
||||
/* When an OP_Program opcode is encounter (the only opcode that has
|
||||
** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
|
||||
** kept in p->aMem[9].z to hold the new program - assuming this subprogram
|
||||
** has not already been seen.
|
||||
*/
|
||||
if( pSub!=0 && aOp[i].p4type==P4_SUBPROGRAM ){
|
||||
int nByte = (nSub+1)*sizeof(SubProgram*);
|
||||
int j;
|
||||
for(j=0; j<nSub; j++){
|
||||
if( apSub[j]==aOp[i].p4.pProgram ) break;
|
||||
}
|
||||
if( j==nSub ){
|
||||
p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
|
||||
if( p->rc!=SQLITE_OK ){
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
apSub = (SubProgram **)pSub->z;
|
||||
apSub[nSub++] = aOp[i].p4.pProgram;
|
||||
pSub->flags |= MEM_Blob;
|
||||
pSub->n = nSub*sizeof(SubProgram*);
|
||||
nRow += aOp[i].p4.pProgram->nOp;
|
||||
}
|
||||
}
|
||||
if( !bEqp ) break;
|
||||
if( aOp[i].opcode==OP_Explain ) break;
|
||||
if( aOp[i].opcode==OP_Init && p->pc>1 ) break;
|
||||
}
|
||||
*piPc = iPc;
|
||||
*piAddr = i;
|
||||
*paOp = aOp;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
|
||||
@ -1983,16 +2085,14 @@ void sqlite3VdbeFrameDelete(VdbeFrame *p){
|
||||
int sqlite3VdbeList(
|
||||
Vdbe *p /* The VDBE */
|
||||
){
|
||||
int nRow; /* Stop when row count reaches this */
|
||||
int nSub = 0; /* Number of sub-vdbes seen so far */
|
||||
SubProgram **apSub = 0; /* Array of sub-vdbes */
|
||||
Mem *pSub = 0; /* Memory cell hold array of subprogs */
|
||||
sqlite3 *db = p->db; /* The database connection */
|
||||
int i; /* Loop counter */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Mem *pMem = &p->aMem[1]; /* First Mem of result set */
|
||||
int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
|
||||
Op *pOp = 0;
|
||||
Op *aOp; /* Array of opcodes */
|
||||
Op *pOp; /* Current opcode */
|
||||
|
||||
assert( p->explain );
|
||||
assert( p->magic==VDBE_MAGIC_RUN );
|
||||
@ -2012,14 +2112,6 @@ int sqlite3VdbeList(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* When the number of output rows reaches nRow, that means the
|
||||
** listing has finished and sqlite3_step() should return SQLITE_DONE.
|
||||
** nRow is the sum of the number of rows in the main program, plus
|
||||
** the sum of the number of rows in all trigger subprograms encountered
|
||||
** so far. The nRow value will increase as new trigger subprograms are
|
||||
** encountered, but p->pc will eventually catch up to nRow.
|
||||
*/
|
||||
nRow = p->nOp;
|
||||
if( bListSubprogs ){
|
||||
/* The first 8 memory cells are used for the result set. So we will
|
||||
** commandeer the 9th cell to use as storage for an array of pointers
|
||||
@ -2027,72 +2119,15 @@ int sqlite3VdbeList(
|
||||
** cells. */
|
||||
assert( p->nMem>9 );
|
||||
pSub = &p->aMem[9];
|
||||
if( pSub->flags&MEM_Blob ){
|
||||
/* On the first call to sqlite3_step(), pSub will hold a NULL. It is
|
||||
** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
|
||||
nSub = pSub->n/sizeof(Vdbe*);
|
||||
apSub = (SubProgram **)pSub->z;
|
||||
}
|
||||
for(i=0; i<nSub; i++){
|
||||
nRow += apSub[i]->nOp;
|
||||
}
|
||||
}else{
|
||||
pSub = 0;
|
||||
}
|
||||
|
||||
while(1){ /* Loop exits via break */
|
||||
i = p->pc++;
|
||||
if( i>=nRow ){
|
||||
p->rc = SQLITE_OK;
|
||||
rc = SQLITE_DONE;
|
||||
break;
|
||||
}
|
||||
if( i<p->nOp ){
|
||||
/* The output line number is small enough that we are still in the
|
||||
** main program. */
|
||||
pOp = &p->aOp[i];
|
||||
}else{
|
||||
/* We are currently listing subprograms. Figure out which one and
|
||||
** pick up the appropriate opcode. */
|
||||
int j;
|
||||
i -= p->nOp;
|
||||
assert( apSub!=0 );
|
||||
assert( nSub>0 );
|
||||
for(j=0; i>=apSub[j]->nOp; j++){
|
||||
i -= apSub[j]->nOp;
|
||||
assert( i<apSub[j]->nOp || j+1<nSub );
|
||||
}
|
||||
pOp = &apSub[j]->aOp[i];
|
||||
}
|
||||
|
||||
/* When an OP_Program opcode is encounter (the only opcode that has
|
||||
** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
|
||||
** kept in p->aMem[9].z to hold the new program - assuming this subprogram
|
||||
** has not already been seen.
|
||||
*/
|
||||
if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
|
||||
int nByte = (nSub+1)*sizeof(SubProgram*);
|
||||
int j;
|
||||
for(j=0; j<nSub; j++){
|
||||
if( apSub[j]==pOp->p4.pProgram ) break;
|
||||
}
|
||||
if( j==nSub ){
|
||||
p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
|
||||
if( p->rc!=SQLITE_OK ){
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
apSub = (SubProgram **)pSub->z;
|
||||
apSub[nSub++] = pOp->p4.pProgram;
|
||||
pSub->flags |= MEM_Blob;
|
||||
pSub->n = nSub*sizeof(SubProgram*);
|
||||
nRow += pOp->p4.pProgram->nOp;
|
||||
}
|
||||
}
|
||||
if( p->explain<2 ) break;
|
||||
if( pOp->opcode==OP_Explain ) break;
|
||||
if( pOp->opcode==OP_Init && p->pc>1 ) break;
|
||||
}
|
||||
/* Figure out which opcode is next to display */
|
||||
rc = sqlite3VdbeNextOpcode(p, pSub, p->explain==2, &p->pc, &i, &aOp);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
pOp = aOp + i;
|
||||
if( db->u1.isInterrupted ){
|
||||
p->rc = SQLITE_INTERRUPT;
|
||||
rc = SQLITE_ERROR;
|
||||
|
Loading…
Reference in New Issue
Block a user