From: drh Date: Mon, 23 Mar 2020 17:24:46 +0000 (+0000) Subject: Begin breaking appear the sqlite3VdbeList() routine into subroutines that X-Git-Tag: version-3.32.0~50^2~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=356cd76aa8bf20f3cc471da18b0ccb0370541565;p=thirdparty%2Fsqlite.git Begin breaking appear the sqlite3VdbeList() routine into subroutines that can be reused by the bytecode() table. FossilOrigin-Name: 2c4dd79fbd4b9f72634a732abb9ed833cd8c9b05fe1e10af8f23e6d6ec023c7c --- diff --git a/manifest b/manifest index 974ed5692d..c0d019b2af 100644 --- a/manifest +++ b/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 diff --git a/manifest.uuid b/manifest.uuid index 289745682d..b14f5c4877 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2795f0d633577e0de66b389d9e8e44c55e85975bdc62f1a0b8f93959d19b22bf \ No newline at end of file +2c4dd79fbd4b9f72634a732abb9ed833cd8c9b05fe1e10af8f23e6d6ec023c7c \ No newline at end of file diff --git a/src/vdbeInt.h b/src/vdbeInt.h index a256ed5bd1..9aa10d89bf 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -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*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index e18a811b69..d57c4821df 100644 --- a/src/vdbeaux.c +++ b/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; inOp; + } + } + iPc = *piPc; + while(1){ /* Loop exits via break */ + i = iPc++; + if( i>=nRow ){ + p->rc = SQLITE_OK; + rc = SQLITE_DONE; + break; + } + if( inOp ){ + /* 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( inOp || j+1aOp; + } + + /* 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; jrc = 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; inOp; - } + }else{ + pSub = 0; } - while(1){ /* Loop exits via break */ - i = p->pc++; - if( i>=nRow ){ - p->rc = SQLITE_OK; - rc = SQLITE_DONE; - break; - } - if( inOp ){ - /* 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( inOp || j+1aOp[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; jp4.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;