Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Defer the {quote: MoveTo} opcode in VDBE until the data is actually needed. Sometimes the data is never needed, resulting in a performance increase. On an indexed order search with a large OFFSET, queries times can be an order of magnitude faster. (CVS 1165) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
d3e96da20d269a068188915b3cc0eb02 |
User & Date: | drh 2004-01-07 18:52:57.000 |
Context
2004-01-07
| ||
19:24 | Permit sqlite_exec() to be called from within user-defined functions. (CVS 1166) (check-in: 03636c94a5 user: drh tags: trunk) | |
18:52 | Defer the {quote: MoveTo} opcode in VDBE until the data is actually needed. Sometimes the data is never needed, resulting in a performance increase. On an indexed order search with a large OFFSET, queries times can be an order of magnitude faster. (CVS 1165) (check-in: d3e96da20d user: drh tags: trunk) | |
03:41 | Make it safe to call sqliteMalloc() with a request for 0 bytes. Ticket #534. (CVS 1164) (check-in: 6c858db2c0 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.247 2004/01/07 18:52:57 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
358 359 360 361 362 363 364 | pTail->pNext = pLeft; }else if( pRight ){ pTail->pNext = pRight; } return sHead.pNext; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | pTail->pNext = pLeft; }else if( pRight ){ pTail->pNext = pRight; } return sHead.pNext; } /* ** Code contained within the VERIFY() macro is not needed for correct ** execution. It is there only to catch errors. So when we compile ** with NDEBUG=1, the VERIFY() code is omitted. */ #ifdef NDEBUG # define VERIFY(X) |
︙ | ︙ | |||
2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 | Cursor *pC; VERIFY( if( tos<0 ) goto not_enough_stack; ) assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->pCursor!=0 ){ int res, oc; if( aStack[tos].flags & STK_Int ){ int iKey = intToKey(aStack[tos].i); sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res); pC->lastRecno = aStack[tos].i; pC->recnoIsValid = res==0; }else{ Stringify(p, tos); sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res); pC->recnoIsValid = 0; } | > > > > > > > | | 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 | Cursor *pC; VERIFY( if( tos<0 ) goto not_enough_stack; ) assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->pCursor!=0 ){ int res, oc; pC->nullRow = 0; if( aStack[tos].flags & STK_Int ){ int iKey = intToKey(aStack[tos].i); if( pOp->p2==0 && pOp->opcode==OP_MoveTo ){ pC->movetoTarget = iKey; pC->deferredMoveto = 1; POPSTACK; break; } sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res); pC->lastRecno = aStack[tos].i; pC->recnoIsValid = res==0; }else{ Stringify(p, tos); sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res); pC->recnoIsValid = 0; } pC->deferredMoveto = 0; sqlite_search_count++; oc = pOp->opcode; if( oc==OP_MoveTo && res<0 ){ sqliteBtreeNext(pC->pCursor, &res); pC->recnoIsValid = 0; if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; |
︙ | ︙ | |||
2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 | Cursor *pC; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){ int res, rx; Stringify(p, tos); rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res); alreadyExists = rx==SQLITE_OK && res==0; } if( pOp->opcode==OP_Found ){ if( alreadyExists ) pc = pOp->p2 - 1; }else{ if( !alreadyExists ) pc = pOp->p2 - 1; } if( pOp->opcode!=OP_Distinct ){ | > | 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 | Cursor *pC; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){ int res, rx; Stringify(p, tos); rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; } if( pOp->opcode==OP_Found ){ if( alreadyExists ) pc = pOp->p2 - 1; }else{ if( !alreadyExists ) pc = pOp->p2 - 1; } if( pOp->opcode!=OP_Distinct ){ |
︙ | ︙ | |||
2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 | zKey = zStack[nos]; nKey = aStack[nos].n; assert( nKey >= 4 ); /* 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. */ rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res<0 ){ rc = sqliteBtreeNext(pCrsr, &res); if( res ){ pc = pOp->p2 - 1; break; | > | 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 | zKey = zStack[nos]; nKey = aStack[nos].n; assert( nKey >= 4 ); /* 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( p->aCsr[i].deferredMoveto==0 ); rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res<0 ){ rc = sqliteBtreeNext(pCrsr, &res); if( res ){ pc = pOp->p2 - 1; break; |
︙ | ︙ | |||
2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 | db->priorNewRowid = v; if( rx==SQLITE_OK && res==0 ){ rc = SQLITE_FULL; goto abort_due_to_error; } } pC->recnoIsValid = 0; } p->tos++; aStack[p->tos].i = v; aStack[p->tos].flags = STK_Int; break; } | > | 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 | db->priorNewRowid = v; if( rx==SQLITE_OK && res==0 ){ rc = SQLITE_FULL; goto abort_due_to_error; } } pC->recnoIsValid = 0; pC->deferredMoveto = 0; } p->tos++; aStack[p->tos].i = v; aStack[p->tos].flags = STK_Int; break; } |
︙ | ︙ | |||
2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 | } pC->nullRow = 0; }else{ rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey, zStack[tos], aStack[tos].n); } pC->recnoIsValid = 0; } POPSTACK; POPSTACK; break; } /* Opcode: Delete P1 P2 * | > | 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 | } pC->nullRow = 0; }else{ rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey, zStack[tos], aStack[tos].n); } pC->recnoIsValid = 0; pC->deferredMoveto = 0; } POPSTACK; POPSTACK; break; } /* Opcode: Delete P1 P2 * |
︙ | ︙ | |||
3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 | */ case OP_Delete: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->pCursor!=0 ){ rc = sqliteBtreeDelete(pC->pCursor); pC->nextRowidValid = 0; } if( pOp->p2 ) db->nChange++; break; } | > | 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 | */ case OP_Delete: { int i = pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->pCursor!=0 ){ sqliteVdbeCursorMoveto(pC); rc = sqliteBtreeDelete(pC->pCursor); pC->nextRowidValid = 0; } if( pOp->p2 ) db->nChange++; break; } |
︙ | ︙ | |||
3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 | assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->nullRow ){ aStack[tos].flags = STK_Null; }else if( pC->pCursor!=0 ){ BtCursor *pCrsr = pC->pCursor; if( pC->nullRow ){ aStack[tos].flags = STK_Null; break; }else if( pC->keyAsData ){ sqliteBtreeKeySize(pCrsr, &n); }else{ sqliteBtreeDataSize(pCrsr, &n); | > | 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 | assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( pC->nullRow ){ aStack[tos].flags = STK_Null; }else if( pC->pCursor!=0 ){ BtCursor *pCrsr = pC->pCursor; sqliteVdbeCursorMoveto(pC); if( pC->nullRow ){ aStack[tos].flags = STK_Null; break; }else if( pC->keyAsData ){ sqliteBtreeKeySize(pCrsr, &n); }else{ sqliteBtreeDataSize(pCrsr, &n); |
︙ | ︙ | |||
3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 | assert( i<p->nCursor ); if( i<0 ){ VERIFY( if( tos+i<0 ) goto bad_instruction; ) VERIFY( if( (aStack[tos+i].flags & STK_Str)==0 ) goto bad_instruction; ) zRec = zStack[tos+i]; payloadSize = aStack[tos+i].n; }else if( (pC = &p->aCsr[i])->pCursor!=0 ){ zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; }else if( pC->keyAsData ){ sqliteBtreeKeySize(pCrsr, &payloadSize); }else{ | > | 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 | assert( i<p->nCursor ); if( i<0 ){ VERIFY( if( tos+i<0 ) goto bad_instruction; ) VERIFY( if( (aStack[tos+i].flags & STK_Str)==0 ) goto bad_instruction; ) zRec = zStack[tos+i]; payloadSize = aStack[tos+i].n; }else if( (pC = &p->aCsr[i])->pCursor!=0 ){ sqliteVdbeCursorMoveto(pC); zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; }else if( pC->keyAsData ){ sqliteBtreeKeySize(pCrsr, &payloadSize); }else{ |
︙ | ︙ | |||
3233 3234 3235 3236 3237 3238 3239 | case OP_Recno: { int i = pOp->p1; int tos = ++p->tos; Cursor *pC; int v; assert( i>=0 && i<p->nCursor ); | | > > | 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 | case OP_Recno: { int i = pOp->p1; int tos = ++p->tos; Cursor *pC; int v; assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; sqliteVdbeCursorMoveto(pC); if( pC->recnoIsValid ){ v = pC->lastRecno; }else if( pC->pseudoTable ){ v = keyToInt(pC->iKey); }else if( pC->nullRow || pC->pCursor==0 ){ aStack[tos].flags = STK_Null; break; }else{ |
︙ | ︙ | |||
3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 | VERIFY( if( !p->aCsr[i].keyAsData ) goto bad_instruction; ) VERIFY( if( p->aCsr[i].pseudoTable ) goto bad_instruction; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int amt; char *z; sqliteBtreeKeySize(pCrsr, &amt); if( amt<=0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } if( amt>NBFS ){ z = sqliteMallocRaw( amt ); | > | 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 | VERIFY( if( !p->aCsr[i].keyAsData ) goto bad_instruction; ) VERIFY( if( p->aCsr[i].pseudoTable ) goto bad_instruction; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int amt; char *z; sqliteVdbeCursorMoveto(&p->aCsr[i]); sqliteBtreeKeySize(pCrsr, &amt); if( amt<=0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } if( amt>NBFS ){ z = sqliteMallocRaw( amt ); |
︙ | ︙ | |||
3325 3326 3327 3328 3329 3330 3331 | BtCursor *pCrsr; assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqliteBtreeLast(pCrsr, &res); | | > | 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 | BtCursor *pCrsr; assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqliteBtreeLast(pCrsr, &res); pC->nullRow = res; pC->deferredMoveto = 0; if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; } }else{ pC->nullRow = 0; } break; |
︙ | ︙ | |||
3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 | assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqliteBtreeFirst(pCrsr, &res); pC->atFirst = res==0; pC->nullRow = res; if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; } }else{ pC->nullRow = 0; } break; | > | 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 | assert( i>=0 && i<p->nCursor ); pC = &p->aCsr[i]; if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqliteBtreeFirst(pCrsr, &res); pC->atFirst = res==0; pC->nullRow = res; pC->deferredMoveto = 0; if( res && pOp->p2>0 ){ pc = pOp->p2 - 1; } }else{ pC->nullRow = 0; } break; |
︙ | ︙ | |||
3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = &p->aCsr[pOp->p1]; if( (pCrsr = pC->pCursor)!=0 ){ int res; if( pC->nullRow ){ res = 1; }else{ rc = pOp->opcode==OP_Next ? sqliteBtreeNext(pCrsr, &res) : sqliteBtreePrevious(pCrsr, &res); pC->nullRow = res; } if( res==0 ){ pc = pOp->p2 - 1; sqlite_search_count++; | > | 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = &p->aCsr[pOp->p1]; if( (pCrsr = pC->pCursor)!=0 ){ int res; if( pC->nullRow ){ res = 1; }else{ assert( pC->deferredMoveto==0 ); rc = pOp->opcode==OP_Next ? sqliteBtreeNext(pCrsr, &res) : sqliteBtreePrevious(pCrsr, &res); pC->nullRow = res; } if( res==0 ){ pc = pOp->p2 - 1; sqlite_search_count++; |
︙ | ︙ | |||
3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 | res = +1; }else{ break; } } } rc = sqliteBtreeInsert(pCrsr, zKey, nKey, "", 0); } POPSTACK; break; } /* Opcode: IdxDelete P1 * * ** | > | 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 | res = +1; }else{ break; } } } rc = sqliteBtreeInsert(pCrsr, zKey, nKey, "", 0); assert( p->aCsr[i].deferredMoveto==0 ); } POPSTACK; break; } /* Opcode: IdxDelete P1 * * ** |
︙ | ︙ | |||
3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 | VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int rx, res; rx = sqliteBtreeMoveto(pCrsr, zStack[tos], aStack[tos].n, &res); if( rx==SQLITE_OK && res==0 ){ rc = sqliteBtreeDelete(pCrsr); } } POPSTACK; break; } /* Opcode: IdxRecno P1 * * ** | > | 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 | VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int rx, res; rx = sqliteBtreeMoveto(pCrsr, zStack[tos], aStack[tos].n, &res); if( rx==SQLITE_OK && res==0 ){ rc = sqliteBtreeDelete(pCrsr); } assert( p->aCsr[i].deferredMoveto==0 ); } POPSTACK; break; } /* Opcode: IdxRecno P1 * * ** |
︙ | ︙ | |||
3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 | int i = pOp->p1; int tos = ++p->tos; BtCursor *pCrsr; if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int v; int sz; sqliteBtreeKeySize(pCrsr, &sz); if( sz<sizeof(u32) ){ aStack[tos].flags = STK_Null; }else{ sqliteBtreeKey(pCrsr, sz - sizeof(u32), sizeof(u32), (char*)&v); v = keyToInt(v); aStack[tos].i = v; | > | 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 | int i = pOp->p1; int tos = ++p->tos; BtCursor *pCrsr; if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int v; int sz; assert( p->aCsr[i].deferredMoveto==0 ); sqliteBtreeKeySize(pCrsr, &sz); if( sz<sizeof(u32) ){ aStack[tos].flags = STK_Null; }else{ sqliteBtreeKey(pCrsr, sz - sizeof(u32), sizeof(u32), (char*)&v); v = keyToInt(v); aStack[tos].i = v; |
︙ | ︙ | |||
3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 | int tos = p->tos; BtCursor *pCrsr; if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int res, rc; Stringify(p, tos); rc = sqliteBtreeKeyCompare(pCrsr, zStack[tos], aStack[tos].n, 4, &res); if( rc!=SQLITE_OK ){ break; } if( pOp->opcode==OP_IdxLT ){ res = -res; }else if( pOp->opcode==OP_IdxGE ){ | > | 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 | int tos = p->tos; BtCursor *pCrsr; if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int res, rc; Stringify(p, tos); assert( p->aCsr[i].deferredMoveto==0 ); rc = sqliteBtreeKeyCompare(pCrsr, zStack[tos], aStack[tos].n, 4, &res); if( rc!=SQLITE_OK ){ break; } if( pOp->opcode==OP_IdxLT ){ res = -res; }else if( pOp->opcode==OP_IdxGE ){ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ** This is the header file for information that is private to the ** VDBE. This information used to all be at the top of the single ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. */ /* ** The makefile scans this source file and creates the following ** array of string constants which are the names of all VDBE opcodes. ** This array is defined in a separate source code file named opcode.c ** which is automatically generated by the makefile. */ extern char *sqliteOpcodeNames[]; | > > > > > > > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ** This is the header file for information that is private to the ** VDBE. This information used to all be at the top of the single ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. */ /* ** When converting from the native format to the key format and back ** again, in addition to changing the byte order we invert the high-order ** bit of the most significant byte. This causes negative numbers to ** sort before positive numbers in the memcmp() function. */ #define keyToInt(X) (sqliteVdbeByteSwap(X) ^ 0x80000000) #define intToKey(X) (sqliteVdbeByteSwap((X) ^ 0x80000000)) /* ** The makefile scans this source file and creates the following ** array of string constants which are the names of all VDBE opcodes. ** This array is defined in a separate source code file named opcode.c ** which is automatically generated by the makefile. */ extern char *sqliteOpcodeNames[]; |
︙ | ︙ | |||
58 59 60 61 62 63 64 65 66 67 68 69 70 71 | Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool nextRowidValid; /* True if the nextRowid field is valid */ Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ Btree *pBt; /* Separate file holding temporary table */ int nData; /* Number of bytes in pData */ char *pData; /* Data for a NEW or OLD pseudo-table */ int iKey; /* Key for the NEW or OLD pseudo-table row */ }; typedef struct Cursor Cursor; | > > | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool nextRowidValid; /* True if the nextRowid field is valid */ Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ Bool deferredMoveto; /* A call to sqliteBtreeMoveto() is needed */ int movetoTarget; /* Argument to the deferred sqliteBtreeMoveto() */ Btree *pBt; /* Separate file holding temporary table */ int nData; /* Number of bytes in pData */ char *pData; /* Data for a NEW or OLD pseudo-table */ int iKey; /* Key for the NEW or OLD pseudo-table row */ }; typedef struct Cursor Cursor; |
︙ | ︙ | |||
290 291 292 293 294 295 296 297 298 299 | ** Function prototypes */ void sqliteVdbeCleanupCursor(Cursor*); void sqliteVdbeSorterReset(Vdbe*); void sqliteVdbeAggReset(Agg*); void sqliteVdbeKeylistFree(Keylist*); void sqliteVdbePopStack(Vdbe*,int); #if !defined(NDEBUG) || defined(VDBE_PROFILE) void sqliteVdbePrintOp(FILE*, int, Op*); #endif | > > | 301 302 303 304 305 306 307 308 309 310 311 312 | ** Function prototypes */ void sqliteVdbeCleanupCursor(Cursor*); void sqliteVdbeSorterReset(Vdbe*); void sqliteVdbeAggReset(Agg*); void sqliteVdbeKeylistFree(Keylist*); void sqliteVdbePopStack(Vdbe*,int); int sqliteVdbeCursorMoveto(Cursor*); int sqliteVdbeByteSwap(int); #if !defined(NDEBUG) || defined(VDBE_PROFILE) void sqliteVdbePrintOp(FILE*, int, Op*); #endif |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
988 989 990 991 992 993 994 | } sqliteFree(p->aOp); sqliteFree(p->aLabel); sqliteFree(p->aStack); p->magic = VDBE_MAGIC_DEAD; sqliteFree(p); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 | } sqliteFree(p->aOp); sqliteFree(p->aLabel); sqliteFree(p->aStack); p->magic = VDBE_MAGIC_DEAD; sqliteFree(p); } /* ** Convert an integer in between the native integer format and ** the bigEndian format used as the record number for tables. ** ** The bigEndian format (most significant byte first) is used for ** record numbers so that records will sort into the correct order ** even though memcmp() is used to compare the keys. On machines ** whose native integer format is little endian (ex: i486) the ** order of bytes is reversed. On native big-endian machines ** (ex: Alpha, Sparc, Motorola) the byte order is the same. ** ** This function is its own inverse. In other words ** ** X == byteSwap(byteSwap(X)) */ int sqliteVdbeByteSwap(int x){ union { char zBuf[sizeof(int)]; int i; } ux; ux.zBuf[3] = x&0xff; ux.zBuf[2] = (x>>8)&0xff; ux.zBuf[1] = (x>>16)&0xff; ux.zBuf[0] = (x>>24)&0xff; return ux.i; } /* ** If a MoveTo operation is pending on the given cursor, then do that ** MoveTo now. Return an error code. If no MoveTo is pending, this ** routine does nothing and returns SQLITE_OK. */ int sqliteVdbeCursorMoveto(Cursor *p){ if( p->deferredMoveto ){ int res; extern int sqlite_search_count; sqliteBtreeMoveto(p->pCursor, (char*)&p->movetoTarget, sizeof(int), &res); p->lastRecno = keyToInt(p->movetoTarget); p->recnoIsValid = res==0; if( res<0 ){ sqliteBtreeNext(p->pCursor, &res); } sqlite_search_count++; p->deferredMoveto = 0; } return SQLITE_OK; } |