-C Do\snot\sdo\sa\sdeferred\sseek\son\sa\scursor\sthat\sis\smarked\snullRow.
-D 2022-02-25T16:21:00.933
+C Attempt\sto\stransform\sOP_Column\sto\smake\suse\sof\seCurState\sinstead\sof\sthe\sother\nmiscellaneous\sflags.
+D 2022-02-25T18:15:09.709
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 602fe229f32a96ceccae4f40824129669582096f7c355f53dbac156c9fecef23
F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3
-F src/vdbe.c 588de992e0efc2cc167748888b90fc0910e93b3030a16b5685f0acd7cb5f1cb3
+F src/vdbe.c 7778e0f54e7ffe99edf44133e346915cb1ababb696186e6f566ff0053d39f28d
F src/vdbe.h a1d0e3b934e835e73edd146f2e7c4eadb711b5c9875c18159a57483fd78e550e
F src/vdbeInt.h 68756566247e190f22ea8f175a81f9d1b91b6258bcdd69832ea2eb3c78ecfb11
F src/vdbeapi.c 8863ffb5a7bac42fe9a68aaa3526ee29fc18fb02a9b27188b756de41e33856e9
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7953716c12ca1deb50ee2c91d9b62a029e38f7cb61af418eeca438283c45f825
-R 85c483559243dc30f8f8dd48c45fb13f
+P 1c026bcb3c9e1ae0f38ad8a3e6e3bda1a0cdff9dcc77a08b1820f2fdde2ee200
+R 6589fae24aaa3fb0ff9b2ab0fa20c61e
U drh
-Z 6cb6334f470796473908dc1f535cd43a
+Z bb01b1e110beac42908286888d97e4bc
# Remove this line to create a well-formed Fossil manifest.
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
p2 = (u32)pOp->p2;
-
- /* If the cursor cache is stale (meaning it is not currently point at
- ** the correct row) then bring it up-to-date by doing the necessary
- ** B-Tree seek. */
- rc = sqlite3VdbeCursorMoveto(&pC, &p2);
- if( rc ) goto abort_due_to_error;
-
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
+
+op_column_restart:
assert( pC!=0 );
assert( p2<(u32)pC->nField );
aOffset = pC->aOffset;
assert( aOffset==pC->aType+pC->nField );
+ assert( aOffset==pC->aType+pC->nField );
assert( pC->eCurType!=CURTYPE_VTAB );
assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
assert( pC->eCurType!=CURTYPE_SORTER );
- if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/
- if( pC->nullRow ){
- if( pC->eCurType==CURTYPE_PSEUDO ){
- /* For the special case of as pseudo-cursor, the seekResult field
- ** identifies the register that holds the record */
- assert( pC->seekResult>0 );
- assert( pC->eCurState==CURSTATE_PSEUDO_UNINIT
- || pC->eCurState==CURSTATE_NULLROW );
- pReg = &aMem[pC->seekResult];
- assert( pReg->flags & MEM_Blob );
- assert( memIsValid(pReg) );
- pC->payloadSize = pC->szRow = pReg->n;
- pC->aRow = (u8*)pReg->z;
- }else{
- assert( pC->eCurState==CURSTATE_NULLROW );
- sqlite3VdbeMemSetNull(pDest);
- goto op_column_out;
+ switch( pC->eCurState ){
+ case CURSTATE_READY: {
+ rc = sqlite3VdbeCursorRestore(pC);
+ if( rc ) goto abort_due_to_error;
+ break;
+ }
+ case CURSTATE_PSEUDO: {
+ break;
+ }
+ case CURSTATE_DEFERRED: {
+ u32 iMap;
+ assert( !pC->isEphemeral );
+ if( pC->ub.aAltMap && (iMap = pC->ub.aAltMap[1+p2])>0 ){
+ pC = pC->pAltCursor;
+ p2 = iMap - 1;
+ goto op_column_restart;
}
- }else{
+ rc = sqlite3VdbeFinishMoveto(pC);
+ if( rc ) goto abort_due_to_error;
+ goto op_column_btree_init;
+ }
+ case CURSTATE_PSEUDO_UNINIT: {
+ assert( pC->eCurType==CURTYPE_PSEUDO );
+ /* For the special case of as pseudo-cursor, the seekResult field
+ ** identifies the register that holds the record */
+ assert( pC->seekResult>0 );
+ pReg = &aMem[pC->seekResult];
+ assert( pReg->flags & MEM_Blob );
+ assert( memIsValid(pReg) );
+ pC->payloadSize = pC->szRow = pReg->n;
+ pC->aRow = (u8*)pReg->z;
+ goto op_column_init_cache;
+ }
+ case CURSTATE_UNINIT: {
+ rc = sqlite3VdbeCursorRestore(pC);
+ if( rc ) goto abort_due_to_error;
+ op_column_btree_init:
pCrsr = pC->uc.pCursor;
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->eCurState==CURSTATE_UNINIT );
if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- }
- pC->eCurState = pC->eCurType;
- pC->cacheStatus = p->cacheCtr;
- pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]);
- pC->nHdrParsed = 0;
-
-
- if( pC->szRow<aOffset[0] ){ /*OPTIMIZATION-IF-FALSE*/
- /* pC->aRow does not have to hold the entire row, but it does at least
- ** need to cover the header of the record. If pC->aRow does not contain
- ** the complete header, then set it to zero, forcing the header to be
- ** dynamically allocated. */
- pC->aRow = 0;
- pC->szRow = 0;
-
- /* Make sure a corrupt database has not given us an oversize header.
- ** Do this now to avoid an oversize memory allocation.
- **
- ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
- ** types use so much data space that there can only be 4096 and 32 of
- ** them, respectively. So the maximum header length results from a
- ** 3-byte type for each of the maximum of 32768 columns plus three
- ** extra bytes for the header length itself. 32768*3 + 3 = 98307.
- */
- if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){
- goto op_column_corrupt;
+ op_column_init_cache:
+ pC->eCurState = pC->eCurType;
+ pC->cacheStatus = p->cacheCtr;
+ pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]);
+ pC->nHdrParsed = 0;
+
+ if( pC->szRow<aOffset[0] ){ /*OPTIMIZATION-IF-FALSE*/
+ /* pC->aRow does not have to hold the entire row, but it does at least
+ ** need to cover the header of the record. If pC->aRow does not contain
+ ** the complete header, then set it to zero, forcing the header to be
+ ** dynamically allocated. */
+ pC->aRow = 0;
+ pC->szRow = 0;
+
+ /* Make sure a corrupt database has not given us an oversize header.
+ ** Do this now to avoid an oversize memory allocation.
+ **
+ ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
+ ** types use so much data space that there can only be 4096 and 32 of
+ ** them, respectively. So the maximum header length results from a
+ ** 3-byte type for each of the maximum of 32768 columns plus three
+ ** extra bytes for the header length itself. 32768*3 + 3 = 98307.
+ */
+ if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){
+ goto op_column_corrupt;
+ }
+ }else{
+ /* This is an optimization. By skipping over the first few tests
+ ** (ex: pC->nHdrParsed<=p2) in the next section, we achieve a
+ ** measurable performance gain.
+ **
+ ** This branch is taken even if aOffset[0]==0. Such a record is never
+ ** generated by SQLite, and could be considered corruption, but we
+ ** accept it for historical reasons. When aOffset[0]==0, the code this
+ ** branch jumps to reads past the end of the record, but never more
+ ** than a few bytes. Even if the record occurs at the end of the page
+ ** content area, the "page header" comes after the page content and so
+ ** this overread is harmless. Similar overreads can occur for a corrupt
+ ** database file.
+ */
+ zData = pC->aRow;
+ assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */
+ testcase( aOffset[0]==0 );
+ goto op_column_read_header;
}
- }else{
- /* This is an optimization. By skipping over the first few tests
- ** (ex: pC->nHdrParsed<=p2) in the next section, we achieve a
- ** measurable performance gain.
- **
- ** This branch is taken even if aOffset[0]==0. Such a record is never
- ** generated by SQLite, and could be considered corruption, but we
- ** accept it for historical reasons. When aOffset[0]==0, the code this
- ** branch jumps to reads past the end of the record, but never more
- ** than a few bytes. Even if the record occurs at the end of the page
- ** content area, the "page header" comes after the page content and so
- ** this overread is harmless. Similar overreads can occur for a corrupt
- ** database file.
- */
- zData = pC->aRow;
- assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */
- testcase( aOffset[0]==0 );
- goto op_column_read_header;
+ break;
+ }
+ default: {
+ assert( pC->eCurState==CURSTATE_NULLROW );
+ sqlite3VdbeMemSetNull(pDest);
+ goto op_column_out;
}
}
assert( pC!=0 );
pC->nullRow = 1;
pC->cacheStatus = CACHE_STALE;
- pC->eCurState = CURSTATE_NULLROW;
if( pC->eCurType==CURTYPE_BTREE ){
assert( pC->uc.pCursor!=0 );
sqlite3BtreeClearCursor(pC->uc.pCursor);
+ pC->eCurState = CURSTATE_NULLROW;
+ }else if( pC->eCurType==CURTYPE_PSEUDO ){
+ pC->eCurState = CURSTATE_PSEUDO_UNINIT;
+ }else{
+ pC->eCurState = CURSTATE_NULLROW;
}
#ifdef SQLITE_DEBUG
if( pC->seekOp==0 ) pC->seekOp = OP_NullRow;