Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Allocates VDBE cursors one by one in separate memory so that pointers to cursors can persist through a realloc(). (CVS 1383) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
d8bacc16801606176fe8639b2f55b458 |
User & Date: | drh 2004-05-14 21:59:40.000 |
Context
2004-05-15
| ||
00:29 | More speed improvements to btree. (CVS 1384) (check-in: aab4b794b4 user: drh tags: trunk) | |
2004-05-14
| ||
21:59 | Allocates VDBE cursors one by one in separate memory so that pointers to cursors can persist through a realloc(). (CVS 1383) (check-in: d8bacc1680 user: drh tags: trunk) | |
21:12 | Cache record headers in the OP_Column opcode. (CVS 1382) (check-in: 8d9eab178f 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.293 2004/05/14 21:59:40 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
409 410 411 412 413 414 415 | ** allocate more. ** ** If a memory allocation error occurs, return 1. Return 0 if ** everything works. */ static int expandCursorArraySize(Vdbe *p, int mxCursor){ if( mxCursor>=p->nCursor ){ | | | < | | > > > | 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | ** allocate more. ** ** If a memory allocation error occurs, return 1. Return 0 if ** everything works. */ static int expandCursorArraySize(Vdbe *p, int mxCursor){ if( mxCursor>=p->nCursor ){ p->apCsr = sqliteRealloc( p->apCsr, (mxCursor+1)*sizeof(Cursor*) ); if( p->apCsr==0 ) return 1; while( p->nCursor<=mxCursor ){ Cursor *pC; p->apCsr[p->nCursor++] = pC = sqliteMalloc( sizeof(Cursor) ); if( pC==0 ) return 1; } } return 0; } /* ** Apply any conversion required by the supplied column affinity to ** memory cell pRec. affinity may be one of: |
︙ | ︙ | |||
558 559 560 561 562 563 564 | unsigned long long start; /* CPU clock count at start of opcode */ int origPc; /* Program counter at start of opcode */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif | < < < | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | unsigned long long start; /* CPU clock count at start of opcode */ int origPc; /* Program counter at start of opcode */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; assert( db->magic==SQLITE_MAGIC_BUSY ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; assert( p->explain==0 ); if( sqlite3_malloc_failed ) goto no_mem; pTos = p->pTos; |
︙ | ︙ | |||
1917 1918 1919 1920 1921 1922 1923 | */ if( i<0 ){ assert( &pTos[i]>=p->aStack ); assert( pTos[i].flags & MEM_Str ); zRec = pTos[i].z; payloadSize = pTos[i].n; pC->cacheValid = 0; | | | 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 | */ if( i<0 ){ assert( &pTos[i]>=p->aStack ); assert( pTos[i].flags & MEM_Str ); zRec = pTos[i].z; payloadSize = pTos[i].n; pC->cacheValid = 0; }else if( (pC = p->apCsr[i])->pCursor!=0 ){ sqlite3VdbeCursorMoveto(pC); zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; }else if( pC->cacheValid ){ payloadSize = pC->payloadSize; |
︙ | ︙ | |||
2619 2620 2621 2622 2623 2624 2625 | sqlite3SetString(&p->zErrMsg, "root page number less than 2", (char*)0); rc = SQLITE_INTERNAL; break; } } assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; | | < | 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 | sqlite3SetString(&p->zErrMsg, "root page number less than 2", (char*)0); rc = SQLITE_INTERNAL; break; } } assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; pCur = p->apCsr[i]; sqlite3VdbeCleanupCursor(pCur); pCur->nullRow = 1; if( pX==0 ) break; do{ /* When opening cursors, always supply the comparison function ** sqlite3VdbeKeyCompare(). If the table being opened is of type ** INTKEY, the btree layer won't call the comparison function anyway. */ |
︙ | ︙ | |||
2687 2688 2689 2690 2691 2692 2693 | ** of the connection to the database. Same word; different meanings. */ case OP_OpenTemp: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; | | | 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 | ** of the connection to the database. Same word; different meanings. */ case OP_OpenTemp: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; pCx = p->apCsr[i]; sqlite3VdbeCleanupCursor(pCx); memset(pCx, 0, sizeof(*pCx)); pCx->nullRow = 1; rc = sqlite3BtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt); if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pCx->pBt); |
︙ | ︙ | |||
2732 2733 2734 2735 2736 2737 2738 | ** NEW or OLD tables in a trigger. */ case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; | | | | 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 | ** NEW or OLD tables in a trigger. */ case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; pCx = p->apCsr[i]; sqlite3VdbeCleanupCursor(pCx); memset(pCx, 0, sizeof(*pCx)); pCx->nullRow = 1; pCx->pseudoTable = 1; break; } /* Opcode: Close P1 * * ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. */ case OP_Close: { int i = pOp->p1; if( i>=0 && i<p->nCursor ){ sqlite3VdbeCleanupCursor(p->apCsr[i]); } break; } /* Opcode: MoveTo P1 P2 * ** ** Pop the top of the stack and use its value as a key. Reposition |
︙ | ︙ | |||
2791 2792 2793 2794 2795 2796 2797 | case OP_MoveLt: case OP_MoveTo: { int i = pOp->p1; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); | | | 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 | case OP_MoveLt: case OP_MoveTo: { int i = pOp->p1; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; if( pC->pCursor!=0 ){ int res, oc; pC->nullRow = 0; if( pC->intKey ){ i64 iKey; assert( !pOp->p3 ); Integerify(pTos); |
︙ | ︙ | |||
2891 2892 2893 2894 2895 2896 2897 | case OP_NotFound: case OP_Found: { int i = pOp->p1; int alreadyExists = 0; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); | | | 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 | case OP_NotFound: case OP_Found: { int i = pOp->p1; int alreadyExists = 0; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); if( (pC = p->apCsr[i])->pCursor!=0 ){ int res, rx; assert( pC->intKey==0 ); Stringify(pTos); rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; pC->cacheValid = 0; |
︙ | ︙ | |||
2946 2947 2948 2949 2950 2951 2952 | /* Pop the value R off the top of the stack */ assert( pNos>=p->aStack ); Integerify(pTos); R = pTos->i; pTos--; assert( i>=0 && i<=p->nCursor ); | | | 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 | /* Pop the value R off the top of the stack */ assert( pNos>=p->aStack ); Integerify(pTos); R = pTos->i; pTos--; assert( i>=0 && i<=p->nCursor ); pCx = p->apCsr[i]; pCrsr = pCx->pCursor; if( pCrsr!=0 ){ int res, rc; i64 v; /* The record number on the P1 entry that matches K */ char *zKey; /* The value of K */ int nKey; /* Number of bytes in K */ int len; /* Number of bytes in K without the rowid at the end */ |
︙ | ︙ | |||
3030 3031 3032 3033 3034 3035 3036 | */ case OP_NotExists: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); | | | | 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 | */ case OP_NotExists: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res, rx; u64 iKey; assert( pTos->flags & MEM_Int ); assert( p->apCsr[i]->intKey ); iKey = intToKey(pTos->i); rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res); pC->lastRecno = pTos->i; pC->recnoIsValid = res==0; pC->nullRow = 0; pC->cacheValid = 0; if( rx!=SQLITE_OK || res!=0 ){ |
︙ | ︙ | |||
3063 3064 3065 3066 3067 3068 3069 | ** onto the stack. */ case OP_NewRecno: { int i = pOp->p1; i64 v = 0; Cursor *pC; assert( i>=0 && i<p->nCursor ); | | | 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 | ** onto the stack. */ case OP_NewRecno: { int i = pOp->p1; i64 v = 0; Cursor *pC; assert( i>=0 && i<p->nCursor ); if( (pC = p->apCsr[i])->pCursor==0 ){ /* The zero initialization above is all that is needed */ }else{ /* The next rowid or record number (different terms for the same ** thing) is obtained in a two-step algorithm. ** ** First we attempt to find the largest existing rowid and add one ** to that. But if the largest existing rowid is already the maximum |
︙ | ︙ | |||
3191 3192 3193 3194 3195 3196 3197 | case OP_PutIntKey: case OP_PutStrKey: { Mem *pNos = &pTos[-1]; int i = pOp->p1; Cursor *pC; assert( pNos>=p->aStack ); assert( i>=0 && i<p->nCursor ); | | | 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 | case OP_PutIntKey: case OP_PutStrKey: { Mem *pNos = &pTos[-1]; int i = pOp->p1; Cursor *pC; assert( pNos>=p->aStack ); assert( i>=0 && i<p->nCursor ); if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){ char *zKey; i64 nKey; i64 iKey; if( pOp->opcode==OP_PutStrKey ){ Stringify(pNos); nKey = pNos->n; zKey = pNos->z; |
︙ | ︙ | |||
3278 3279 3280 3281 3282 3283 3284 | ** ** If P1 is a pseudo-table, then this instruction is a no-op. */ case OP_Delete: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); | | | 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 | ** ** If P1 is a pseudo-table, then this instruction is a no-op. */ case OP_Delete: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; if( pC->pCursor!=0 ){ sqlite3VdbeCursorMoveto(pC); rc = sqlite3BtreeDelete(pC->pCursor); pC->nextRowidValid = 0; pC->cacheValid = 0; } if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++; |
︙ | ︙ | |||
3311 3312 3313 3314 3315 3316 3317 | ** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls ** data off of the key rather than the data. This is used for ** processing compound selects. */ case OP_KeyAsData: { int i = pOp->p1; assert( i>=0 && i<p->nCursor ); | | | 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 | ** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls ** data off of the key rather than the data. This is used for ** processing compound selects. */ case OP_KeyAsData: { int i = pOp->p1; assert( i>=0 && i<p->nCursor ); p->apCsr[i]->keyAsData = pOp->p2; break; } /* Opcode: RowData P1 * * ** ** Push onto the stack the complete row data for cursor P1. ** There is no interpretation of the data. It is just copied |
︙ | ︙ | |||
3341 3342 3343 3344 3345 3346 3347 | case OP_RowData: { int i = pOp->p1; Cursor *pC; int n; pTos++; assert( i>=0 && i<p->nCursor ); | | | 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 | case OP_RowData: { int i = pOp->p1; Cursor *pC; int n; pTos++; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; if( pC->nullRow ){ pTos->flags = MEM_Null; }else if( pC->pCursor!=0 ){ BtCursor *pCrsr = pC->pCursor; sqlite3VdbeCursorMoveto(pC); if( pC->nullRow ){ pTos->flags = MEM_Null; |
︙ | ︙ | |||
3396 3397 3398 3399 3400 3401 3402 | */ case OP_Recno: { int i = pOp->p1; Cursor *pC; i64 v; assert( i>=0 && i<p->nCursor ); | | | 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 | */ case OP_Recno: { int i = pOp->p1; Cursor *pC; i64 v; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; sqlite3VdbeCursorMoveto(pC); pTos++; if( pC->recnoIsValid ){ v = pC->lastRecno; }else if( pC->pseudoTable ){ v = keyToInt(pC->iKey); }else if( pC->nullRow || pC->pCursor==0 ){ |
︙ | ︙ | |||
3430 3431 3432 3433 3434 3435 3436 3437 | ** integer. This instruction pushes the entire key as a string. ** ** This opcode may not be used on a pseudo-table. */ case OP_FullKey: { int i = pOp->p1; BtCursor *pCrsr; | > | | | | | | 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 | ** integer. This instruction pushes the entire key as a string. ** ** This opcode may not be used on a pseudo-table. */ case OP_FullKey: { int i = pOp->p1; BtCursor *pCrsr; Cursor *pC; assert( p->apCsr[i]->keyAsData ); assert( !p->apCsr[i]->pseudoTable ); assert( i>=0 && i<p->nCursor ); pTos++; if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ u64 amt; char *z; sqlite3VdbeCursorMoveto(pC); assert( pC->intKey==0 ); sqlite3BtreeKeySize(pCrsr, &amt); if( amt<=0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } if( amt>NBFS ){ z = sqliteMallocRaw( amt ); |
︙ | ︙ | |||
3469 3470 3471 3472 3473 3474 3475 3476 3477 | ** ** Move the cursor P1 to a null row. Any OP_Column operations ** that occur while the cursor is on the null row will always push ** a NULL onto the stack. */ case OP_NullRow: { int i = pOp->p1; assert( i>=0 && i<p->nCursor ); | > > | | | | 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 | ** ** Move the cursor P1 to a null row. Any OP_Column operations ** that occur while the cursor is on the null row will always push ** a NULL onto the stack. */ case OP_NullRow: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; pC->nullRow = 1; pC->recnoIsValid = 0; break; } /* Opcode: Last P1 P2 * ** ** The next use of the Recno or Column or Next instruction for P1 ** will refer to the last entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ case OP_Last: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqlite3BtreeLast(pCrsr, &res); pC->nullRow = res; pC->deferredMoveto = 0; pC->cacheValid = 0; if( res && pOp->p2>0 ){ |
︙ | ︙ | |||
3521 3522 3523 3524 3525 3526 3527 | case OP_Rewind: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; int res; assert( i>=0 && i<p->nCursor ); | | | 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 | case OP_Rewind: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; int res; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; if( (pCrsr = pC->pCursor)!=0 ){ rc = sqlite3BtreeFirst(pCrsr, &res); pC->atFirst = res==0; pC->deferredMoveto = 0; pC->cacheValid = 0; }else{ res = 1; |
︙ | ︙ | |||
3560 3561 3562 3563 3564 3565 3566 | case OP_Prev: case OP_Next: { Cursor *pC; BtCursor *pCrsr; CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); | | | 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 | case OP_Prev: case OP_Next: { Cursor *pC; BtCursor *pCrsr; CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; if( (pCrsr = pC->pCursor)!=0 ){ int res; if( pC->nullRow ){ res = 1; }else{ assert( pC->deferredMoveto==0 ); rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) : |
︙ | ︙ | |||
3601 3602 3603 3604 3605 3606 3607 | case OP_IdxPut: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); assert( pTos->flags & MEM_Str ); | | | 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 | case OP_IdxPut: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); assert( pTos->flags & MEM_Str ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int nKey = pTos->n; const char *zKey = pTos->z; if( pOp->p2 ){ int res; int len; u64 n; |
︙ | ︙ | |||
3658 3659 3660 3661 3662 3663 3664 | case OP_IdxDelete: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( pTos->flags & MEM_Str ); assert( i>=0 && i<p->nCursor ); | | | 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 | case OP_IdxDelete: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( pTos->flags & MEM_Str ); assert( i>=0 && i<p->nCursor ); 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->cacheValid = 0; |
︙ | ︙ | |||
3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 | ** the record number of the table entry to which this index entry points. ** ** See also: Recno, MakeIdxKey. */ case OP_IdxRecno: { int i = pOp->p1; BtCursor *pCrsr; assert( i>=0 && i<p->nCursor ); pTos++; | > | | | | 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 | ** the record number of the table entry to which this index entry points. ** ** See also: Recno, MakeIdxKey. */ case OP_IdxRecno: { int i = pOp->p1; BtCursor *pCrsr; Cursor *pC; assert( i>=0 && i<p->nCursor ); pTos++; if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ i64 rowid; assert( pC->deferredMoveto==0 ); assert( pC->intKey==0 ); rc = sqlite3VdbeIdxRowid(pCrsr, &rowid); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pTos->flags = MEM_Int; pTos->i = rowid; |
︙ | ︙ | |||
3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 | ** In either case, the stack is popped once. */ case OP_IdxLT: case OP_IdxGT: case OP_IdxGE: { int i= pOp->p1; BtCursor *pCrsr; assert( i>=0 && i<p->nCursor ); assert( pTos>=p->aStack ); | > | < | | 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 | ** In either case, the stack is popped once. */ case OP_IdxLT: case OP_IdxGT: case OP_IdxGE: { int i= pOp->p1; BtCursor *pCrsr; Cursor *pC; assert( i>=0 && i<p->nCursor ); assert( pTos>=p->aStack ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res, rc; Stringify(pTos); assert( pC->deferredMoveto==0 ); if( pOp->p3 ){ pC->incrKey = 1; } rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, pTos->z, 0, &res); pC->incrKey = 0; if( rc!=SQLITE_OK ){ break; |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
261 262 263 264 265 266 267 | int nLabel; /* Number of labels used */ int nLabelAlloc; /* Number of slots allocated in aLabel[] */ int *aLabel; /* Space to hold the labels */ Mem *aStack; /* The operand stack, except string values */ Mem *pTos; /* Top entry in the operand stack */ char **zArgv; /* Text values used by the callback */ char **azColName; /* Becomes the 4th parameter to callbacks */ | | | | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | int nLabel; /* Number of labels used */ int nLabelAlloc; /* Number of slots allocated in aLabel[] */ int *aLabel; /* Space to hold the labels */ Mem *aStack; /* The operand stack, except string values */ Mem *pTos; /* Top entry in the operand stack */ char **zArgv; /* Text values used by the callback */ char **azColName; /* Becomes the 4th parameter to callbacks */ int nCursor; /* Number of slots in apCsr[] */ Cursor **apCsr; /* One element of this array for each open cursor */ Sorter *pSort; /* A linked list of objects to be sorted */ FILE *pFile; /* At most one open file handler */ int nField; /* Number of file fields */ char **azField; /* Data for each file field */ int nVar; /* Number of entries in azVariable[] */ char **azVar; /* Values for the OP_Variable opcode */ int *anVar; /* Length of each value in azVariable[] */ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
732 733 734 735 736 737 738 | sqlite3BtreeCloseCursor(pCx->pCursor); } if( pCx->pBt ){ sqlite3BtreeClose(pCx->pBt); } sqliteFree(pCx->pData); sqliteFree(pCx->aType); | | > | > | | | 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 | sqlite3BtreeCloseCursor(pCx->pCursor); } if( pCx->pBt ){ sqlite3BtreeClose(pCx->pBt); } sqliteFree(pCx->pData); sqliteFree(pCx->aType); memset(pCx, 0, sizeof(*pCx)); } /* ** Close all cursors */ static void closeAllCursors(Vdbe *p){ int i; for(i=0; i<p->nCursor; i++){ Cursor *pC = p->apCsr[i]; sqlite3VdbeCleanupCursor(pC); sqliteFree(pC); } sqliteFree(p->apCsr); p->apCsr = 0; p->nCursor = 0; } /* ** Clean up the VM after execution. ** ** This routine will automatically close any cursors, lists, and/or |
︙ | ︙ |