Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Invalidate all VDBE cursor row caches in between calls to sqlite3_step() since the emphemeral content that those caches point to might change if the statement is READ UNCOMMITTED. (CVS 2886) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
0ae461313c1642a49a9f6cda608c42c7 |
User & Date: | drh 2006-01-07 18:48:26.000 |
Context
2006-01-08
| ||
05:02 | Reduce memory requirements for ORDER BY combined with LIMIT. Ticket #1586. (CVS 2887) (check-in: 55e703ecac user: drh tags: trunk) | |
2006-01-07
| ||
18:48 | Invalidate all VDBE cursor row caches in between calls to sqlite3_step() since the emphemeral content that those caches point to might change if the statement is READ UNCOMMITTED. (CVS 2886) (check-in: 0ae461313c user: drh tags: trunk) | |
18:14 | Continued progress toward a working wince backend. (CVS 2885) (check-in: 15fda14ee0 user: drh tags: trunk) | |
Changes
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.516 2006/01/07 18:48:26 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
874 875 876 877 878 879 880 881 882 883 884 885 886 887 | ** the stack. Note that ephemeral data is never stored in memory ** cells so we do not have to worry about them. */ pFirstColumn = &pTos[0-pOp->p1]; for(pMem = p->aStack; pMem<pFirstColumn; pMem++){ Deephemeralize(pMem); } /* Make sure the results of the current row are \000 terminated ** and have an assigned type. The results are deephemeralized as ** as side effect. */ for(; pMem<=pTos; pMem++ ){ sqlite3VdbeMemNulTerminate(pMem); | > > > | 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 | ** the stack. Note that ephemeral data is never stored in memory ** cells so we do not have to worry about them. */ pFirstColumn = &pTos[0-pOp->p1]; for(pMem = p->aStack; pMem<pFirstColumn; pMem++){ Deephemeralize(pMem); } /* Invalidate all ephemeral cursor row caches */ p->cacheCtr = (p->cacheCtr + 2)|1; /* Make sure the results of the current row are \000 terminated ** and have an assigned type. The results are deephemeralized as ** as side effect. */ for(; pMem<=pTos; pMem++ ){ sqlite3VdbeMemNulTerminate(pMem); |
︙ | ︙ | |||
1904 1905 1906 1907 1908 1909 1910 | /* The record is stored in a B-Tree */ rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; | | | | 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 | /* The record is stored in a B-Tree */ rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; }else if( pC->cacheStatus==p->cacheCtr ){ payloadSize = pC->payloadSize; zRec = (char*)pC->aRow; }else if( pC->isIndex ){ i64 payloadSize64; sqlite3BtreeKeySize(pCrsr, &payloadSize64); payloadSize = payloadSize64; }else{ sqlite3BtreeDataSize(pCrsr, &payloadSize); } nField = pC->nField; #ifndef SQLITE_OMIT_TRIGGER }else if( pC->pseudoTable ){ /* The record is the sole entry of a pseudo-table */ payloadSize = pC->nData; zRec = pC->pData; pC->cacheStatus = CACHE_STALE; assert( payloadSize==0 || zRec!=0 ); nField = pC->nField; pCrsr = 0; #endif }else{ zRec = 0; payloadSize = 0; |
︙ | ︙ | |||
1943 1944 1945 1946 1947 1948 1949 | } assert( p2<nField ); /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ | | | 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 | } assert( p2<nField ); /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ if( pC && pC->cacheStatus==p->cacheCtr ){ aType = pC->aType; aOffset = pC->aOffset; }else{ int avail; /* Number of bytes of available data */ if( pC && pC->aType ){ aType = pC->aType; }else{ |
︙ | ︙ | |||
2038 2039 2040 2041 2042 2043 2044 | /* Remember all aType and aColumn information if we have a cursor ** to remember it in. */ if( pC ){ pC->payloadSize = payloadSize; pC->aType = aType; pC->aOffset = aOffset; | | | 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 | /* Remember all aType and aColumn information if we have a cursor ** to remember it in. */ if( pC ){ pC->payloadSize = payloadSize; pC->aType = aType; pC->aOffset = aOffset; pC->cacheStatus = p->cacheCtr; } } /* Get the column information. If aOffset[p2] is non-zero, then ** deserialize the value from the record. If aOffset[p2] is zero, ** then there are not enough fields in the record to satisfy the ** request. In this case, set the value NULL or to P3 if P3 is |
︙ | ︙ | |||
2801 2802 2803 2804 2805 2806 2807 | rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->rowidIsValid = 0; } pC->deferredMoveto = 0; | | | 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 | rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->rowidIsValid = 0; } pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; *pC->pIncrKey = 0; sqlite3_search_count++; if( oc==OP_MoveGe || oc==OP_MoveGt ){ if( res<0 ){ rc = sqlite3BtreeNext(pC->pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; pC->rowidIsValid = 0; |
︙ | ︙ | |||
2902 2903 2904 2905 2906 2907 2908 | if( (pC = p->apCsr[i])->pCursor!=0 ){ int res, rx; assert( pC->isTable==0 ); Stringify(pTos, db->enc); rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; | | | 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 | if( (pC = p->apCsr[i])->pCursor!=0 ){ int res, rx; assert( pC->isTable==0 ); Stringify(pTos, db->enc); rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; } if( pOp->opcode==OP_Found ){ if( alreadyExists ) pc = pOp->p2 - 1; }else{ if( !alreadyExists ) pc = pOp->p2 - 1; } if( pOp->opcode!=OP_Distinct ){ |
︙ | ︙ | |||
2976 2977 2978 2979 2980 2981 2982 | szRowid = sqlite3VdbeIdxRowidLen(nKey, (u8*)zKey); len = nKey-szRowid; /* Search for an entry in P1 where all but the last four bytes match K. ** If there is no such entry, jump immediately to P2. */ assert( pCx->deferredMoveto==0 ); | | | 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 | szRowid = sqlite3VdbeIdxRowidLen(nKey, (u8*)zKey); len = nKey-szRowid; /* Search for an entry in P1 where all but the last four bytes match K. ** If there is no such entry, jump immediately to P2. */ assert( pCx->deferredMoveto==0 ); pCx->cacheStatus = CACHE_STALE; rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res<0 ){ rc = sqlite3BtreeNext(pCrsr, &res); if( res ){ pc = pOp->p2 - 1; break; |
︙ | ︙ | |||
3049 3050 3051 3052 3053 3054 3055 | assert( pTos->flags & MEM_Int ); assert( p->apCsr[i]->isTable ); iKey = intToKey(pTos->i); rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res); pC->lastRowid = pTos->i; pC->rowidIsValid = res==0; pC->nullRow = 0; | | | 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 | assert( pTos->flags & MEM_Int ); assert( p->apCsr[i]->isTable ); iKey = intToKey(pTos->i); rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res); pC->lastRowid = pTos->i; pC->rowidIsValid = res==0; pC->nullRow = 0; pC->cacheStatus = CACHE_STALE; if( res!=0 ){ pc = pOp->p2 - 1; pC->rowidIsValid = 0; } } Release(pTos); pTos--; |
︙ | ︙ | |||
3225 3226 3227 3228 3229 3230 3231 | if( rx==SQLITE_OK && res==0 ){ rc = SQLITE_FULL; goto abort_due_to_error; } } pC->rowidIsValid = 0; pC->deferredMoveto = 0; | | | 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 | if( rx==SQLITE_OK && res==0 ){ rc = SQLITE_FULL; goto abort_due_to_error; } } pC->rowidIsValid = 0; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; } pTos++; pTos->i = v; pTos->flags = MEM_Int; break; } |
︙ | ︙ | |||
3299 3300 3301 3302 3303 3304 3305 | rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pTos->z, pTos->n); #ifndef SQLITE_OMIT_TRIGGER } #endif pC->rowidIsValid = 0; pC->deferredMoveto = 0; | | | 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 | rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pTos->z, pTos->n); #ifndef SQLITE_OMIT_TRIGGER } #endif pC->rowidIsValid = 0; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){ const char *zDb = db->aDb[pC->iDb].zName; const char *zTbl = pOp->p3; int op = ((pOp->p2 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); assert( pC->isTable ); |
︙ | ︙ | |||
3359 3360 3361 3362 3363 3364 3365 | } } rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; rc = sqlite3BtreeDelete(pC->pCursor); pC->nextRowidValid = 0; | | | 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 | } } rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; rc = sqlite3BtreeDelete(pC->pCursor); pC->nextRowidValid = 0; pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){ const char *zDb = db->aDb[pC->iDb].zName; const char *zTbl = pOp->p3; db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); assert( pC->iDb>=0 ); |
︙ | ︙ | |||
3537 3538 3539 3540 3541 3542 3543 | pC = p->apCsr[i]; assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqlite3BtreeLast(pCrsr, &res); pC->nullRow = res; pC->deferredMoveto = 0; | | | 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 | pC = p->apCsr[i]; assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqlite3BtreeLast(pCrsr, &res); pC->nullRow = res; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; } }else{ pC->nullRow = 0; } break; |
︙ | ︙ | |||
3586 3587 3588 3589 3590 3591 3592 | assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ rc = sqlite3BtreeFirst(pCrsr, &res); pC->atFirst = res==0; pC->deferredMoveto = 0; | | | 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 | assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ rc = sqlite3BtreeFirst(pCrsr, &res); pC->atFirst = res==0; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; }else{ res = 1; } pC->nullRow = res; if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; } |
︙ | ︙ | |||
3631 3632 3633 3634 3635 3636 3637 | if( pC->nullRow ){ res = 1; }else{ assert( pC->deferredMoveto==0 ); rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) : sqlite3BtreePrevious(pCrsr, &res); pC->nullRow = res; | | | 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 | if( pC->nullRow ){ res = 1; }else{ assert( pC->deferredMoveto==0 ); rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) : sqlite3BtreePrevious(pCrsr, &res); pC->nullRow = res; pC->cacheStatus = CACHE_STALE; } if( res==0 ){ pc = pOp->p2 - 1; sqlite3_search_count++; } }else{ pC->nullRow = 1; |
︙ | ︙ | |||
3668 3669 3670 3671 3672 3673 3674 | assert( pOp->p2==0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int nKey = pTos->n; const char *zKey = pTos->z; assert( pC->isTable==0 ); rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0); assert( pC->deferredMoveto==0 ); | | | 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 | assert( pOp->p2==0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int nKey = pTos->n; const char *zKey = pTos->z; assert( pC->isTable==0 ); rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0); assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; } Release(pTos); pTos--; break; } /* Opcode: IdxDelete P1 * * |
︙ | ︙ | |||
3695 3696 3697 3698 3699 3700 3701 | if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int rx, res; rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res); if( rx==SQLITE_OK && res==0 ){ rc = sqlite3BtreeDelete(pCrsr); } assert( pC->deferredMoveto==0 ); | | | 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 | if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int rx, res; rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res); if( rx==SQLITE_OK && res==0 ){ rc = sqlite3BtreeDelete(pCrsr); } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; } Release(pTos); pTos--; break; } /* Opcode: IdxRowid P1 * * |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
82 83 84 85 86 87 88 | u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ int nField; /* Number of fields in the header */ i64 seqCount; /* Sequence counter */ /* Cached information about the header for the data record that the ** cursor is currently pointing to. Only valid if cacheValid is true. | | | > | > > > > > | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ int nField; /* Number of fields in the header */ i64 seqCount; /* Sequence counter */ /* Cached information about the header for the data record that the ** cursor is currently pointing to. Only valid if cacheValid is true. ** aRow might point to (ephemeral) data for the current row, or it might ** be NULL. */ int cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ int payloadSize; /* Total number of bytes in the record */ u32 *aType; /* Type values for all entries in the record */ u32 *aOffset; /* Cached offsets to the start of each columns data */ u8 *aRow; /* Data for the current row, if all on one page */ }; typedef struct Cursor Cursor; /* ** Number of bytes of string storage space available to each stack ** layer without having to malloc. NBFS is short for Number of Bytes ** For Strings. */ #define NBFS 32 /* ** A value for Cursor.cacheValid that means the cache is always invalid. */ #define CACHE_STALE 0 /* ** Internally, the vdbe manipulates nearly all SQL values as Mem ** structures. Each Mem struct may cache multiple representations (string, ** integer etc.) of the same value. A value (and therefore Mem structure) ** has the following properties: ** ** Each value has a manifest type. The manifest type of the value stored |
︙ | ︙ | |||
283 284 285 286 287 288 289 290 291 292 293 294 295 296 | Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ int nCallback; /* Number of callbacks invoked so far */ Fifo sFifo; /* A list of ROWIDs */ int contextStackTop; /* Index of top element in the context stack */ int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ | > | 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ int nCallback; /* Number of callbacks invoked so far */ int cacheCtr; /* Cursor row cache generation counter */ Fifo sFifo; /* A list of ROWIDs */ int contextStackTop; /* Index of top element in the context stack */ int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
778 779 780 781 782 783 784 785 786 787 788 789 790 791 | p->uniqueCnt = 0; p->returnDepth = 0; p->errorAction = OE_Abort; p->popStack = 0; p->explain |= isExplain; p->magic = VDBE_MAGIC_RUN; p->nChange = 0; p->minWriteFileFormat = 255; #ifdef VDBE_PROFILE { int i; for(i=0; i<p->nOp; i++){ p->aOp[i].cnt = 0; p->aOp[i].cycles = 0; | > | 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 | p->uniqueCnt = 0; p->returnDepth = 0; p->errorAction = OE_Abort; p->popStack = 0; p->explain |= isExplain; p->magic = VDBE_MAGIC_RUN; p->nChange = 0; p->cacheCtr = 1; p->minWriteFileFormat = 255; #ifdef VDBE_PROFILE { int i; for(i=0; i<p->nOp; i++){ p->aOp[i].cnt = 0; p->aOp[i].cycles = 0; |
︙ | ︙ | |||
1449 1450 1451 1452 1453 1454 1455 | p->rowidIsValid = res==0; if( res<0 ){ rc = sqlite3BtreeNext(p->pCursor, &res); if( rc ) return rc; } sqlite3_search_count++; p->deferredMoveto = 0; | | | 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 | p->rowidIsValid = res==0; if( res<0 ){ rc = sqlite3BtreeNext(p->pCursor, &res); if( rc ) return rc; } sqlite3_search_count++; p->deferredMoveto = 0; p->cacheStatus = CACHE_STALE; } return SQLITE_OK; } /* ** The following functions: ** |
︙ | ︙ |