Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Combine cases 3 and 4 in where.c, since case 4 is now a special case of case 3. (CVS 5029) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9a976819246eb558ba43429f8889972c |
User & Date: | danielk1977 2008-04-18 10:25:24.000 |
Context
2008-04-18
| ||
11:31 | Remove unused code from OP_IdxLt and OP_IdxGE. (CVS 5030) (check-in: df02175ec0 user: danielk1977 tags: trunk) | |
10:25 | Combine cases 3 and 4 in where.c, since case 4 is now a special case of case 3. (CVS 5029) (check-in: 9a97681924 user: danielk1977 tags: trunk) | |
09:01 | Allow OP_MoveGt and similar to use an array of registers instead of a serialized record. Modify one type of index range scan to use this. (CVS 5028) (check-in: c448f15aa5 user: danielk1977 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.732 2008/04/18 10:25:24 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include "vdbeInt.h" /* ** The following global variable is incremented every time a cursor |
︙ | ︙ | |||
2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 | case OP_Affinity: { char *zAffinity = pOp->p4.z; Mem *pData0 = &p->aMem[pOp->p1]; Mem *pLast = &pData0[pOp->p2-1]; Mem *pRec; for(pRec=pData0; pRec<=pLast; pRec++){ applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } break; } /* Opcode: MakeRecord P1 P2 P3 P4 * ** | > | 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 | case OP_Affinity: { char *zAffinity = pOp->p4.z; Mem *pData0 = &p->aMem[pOp->p1]; Mem *pLast = &pData0[pOp->p2-1]; Mem *pRec; for(pRec=pData0; pRec<=pLast; pRec++){ ExpandBlob(pRec); applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } break; } /* Opcode: MakeRecord P1 P2 P3 P4 * ** |
︙ | ︙ | |||
2786 2787 2788 2789 2790 2791 2792 | int i = pOp->p1; assert( i>=0 && i<p->nCursor ); sqlite3VdbeFreeCursor(p, p->apCsr[i]); p->apCsr[i] = 0; break; } | | > | > > > | < | | | > | > > > | < | | | > | > > > | < | | | | | | | | | < | 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 | int i = pOp->p1; assert( i>=0 && i<p->nCursor ); sqlite3VdbeFreeCursor(p, p->apCsr[i]); p->apCsr[i] = 0; break; } /* Opcode: MoveGe P1 P2 P3 P4 * ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), ** use the integer value in register P3 as a key. If cursor P1 refers ** to an SQL index, then P3 is the first in an array of P4 registers ** that are used as an unpacked index key. ** ** Reposition cursor P1 so that it points to the smallest entry that ** is greater than or equal to the key value. If there are no records ** greater than or equal to the key and P2 is not zero, then jump to P2. ** ** A special feature of this opcode (and different from the ** related OP_MoveGt, OP_MoveLt, and OP_MoveLe) is that if P2 is ** zero and P1 is an SQL table (a b-tree with integer keys) then ** the seek is deferred until it is actually needed. It might be ** the case that the cursor is never accessed. By deferring the ** seek, we avoid unnecessary seeks. ** ** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe */ /* Opcode: MoveGt P1 P2 P3 P4 * ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), ** use the integer value in register P3 as a key. If cursor P1 refers ** to an SQL index, then P3 is the first in an array of P4 registers ** that are used as an unpacked index key. ** ** Reposition cursor P1 so that it points to the smallest entry that ** is greater than the key value. If there are no records greater than ** the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe */ /* Opcode: MoveLt P1 P2 P3 P4 * ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), ** use the integer value in register P3 as a key. If cursor P1 refers ** to an SQL index, then P3 is the first in an array of P4 registers ** that are used as an unpacked index key. ** ** Reposition cursor P1 so that it points to the largest entry that ** is less than the key value. If there are no records less than ** the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe */ /* Opcode: MoveLe P1 P2 P3 P4 * ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), ** use the integer value in register P3 as a key. If cursor P1 refers ** to an SQL index, then P3 is the first in an array of P4 registers ** that are used as an unpacked index key. ** ** Reposition cursor P1 so that it points to the largest entry that ** is less than or equal to the key value. If there are no records ** less than or equal to the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt */ case OP_MoveLt: /* jump, in3 */ case OP_MoveLe: /* jump, in3 */ case OP_MoveGe: /* jump, in3 */ case OP_MoveGt: { /* jump, in3 */ |
︙ | ︙ | |||
2868 2869 2870 2871 2872 2873 2874 | rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->lastRowid = iKey; pC->rowidIsValid = res==0; }else{ | > | | | < < < < | | | | | | < | 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 | rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->lastRowid = iKey; pC->rowidIsValid = res==0; }else{ UnpackedRecord r; int nField = pOp->p4.i; assert( pOp->p4type==P4_INT32 ); assert( nField>0 ); r.pKeyInfo = pC->pKeyInfo; r.nField = nField; r.needFree = 0; r.needDestroy = 0; r.aMem = &p->aMem[pOp->p3]; rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->rowidIsValid = 0; } pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** ** $Id: where.c,v 1.301 2008/04/18 10:25:24 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) |
︙ | ︙ | |||
1723 1724 1725 1726 1727 1728 1729 | disableTerm(pLevel, pOther); } } } } /* | | < < | < < | < < < < < | | < < | | | | > | 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 | disableTerm(pLevel, pOther); } } } } /* ** Apply the affinities associated with the first n columns of index ** pIdx to the values in the n registers starting at base. */ static void codeApplyAffinity(Parse *pParse, int base, int n, Index *pIdx){ if( n>0 ){ Vdbe *v = pParse->pVdbe; assert( v!=0 ); sqlite3VdbeAddOp2(v, OP_Affinity, base, n); sqlite3IndexAffinityStr(v, pIdx); sqlite3ExprCacheAffinityChange(pParse, base, n); } } /* ** Generate code for a single equality term of the WHERE clause. An equality ** term can be either X=expr or X IN (...). pTerm is the term to be ** coded. |
︙ | ︙ | |||
2459 2460 2461 2462 2463 2464 2465 | int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); /* sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); */ sqlite3VdbeAddOp3(v, testOp, pLevel->iMem, brk, r1); sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); sqlite3ReleaseTempReg(pParse, r1); } | | > > | | | | > | | > > > > > > > > > > > > | | | | | | | 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 | int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); /* sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); */ sqlite3VdbeAddOp3(v, testOp, pLevel->iMem, brk, r1); sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); sqlite3ReleaseTempReg(pParse, r1); } }else if( pLevel->flags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){ /* Case 3: A scan using an index. ** ** The WHERE clause may contain one or more equality ** terms ("==" or "IN" operators) that refer to the N ** left-most columns of the index. It may also contain ** inequality constraints (>, <, >= or <=) on the indexed ** column that immediately follows the N equalities. Only ** the right-most column can be an inequality - the rest must ** use the "==" and "IN" operators. For example, if the ** index is on (x,y,z), then the following clauses are all ** optimized: ** ** x=5 ** x=5 AND y=10 ** x=5 AND y<10 ** x=5 AND y>5 AND y<10 ** x=5 AND y=5 AND z<=10 ** ** This cannot be optimized: ** ** x=5 AND z<10 ** ** This case is also used when there are no WHERE clause ** constraints but an index is selected anyway, in order ** to force the output order to conform to an ORDER BY. */ int aStartOp[] = { 0, 0, OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ OP_Last, /* 3: (!start_constraints && startEq && bRev) */ OP_MoveGt, /* 4: (start_constraints && !startEq && !bRev) */ OP_MoveLt, /* 5: (start_constraints && !startEq && bRev) */ OP_MoveGe, /* 6: (start_constraints && startEq && !bRev) */ OP_MoveLe /* 7: (start_constraints && startEq && bRev) */ }; int aEndOp[] = { OP_Noop, /* 0: (!end_constraints) */ OP_IdxGE, /* 1: (end_constraints && !bRev) */ OP_IdxLT /* 2: (end_constraints && bRev) */ }; int nEq = pLevel->nEq; int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ int regBase; /* Base register holding constraint values */ int r1; /* Temp register */ |
︙ | ︙ | |||
2522 2523 2524 2525 2526 2527 2528 | && (pLevel->flags&WHERE_ORDERBY) && (pIdx->nColumn>nEq) && (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq]) ){ isMinQuery = 1; } | | | 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 | && (pLevel->flags&WHERE_ORDERBY) && (pIdx->nColumn>nEq) && (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq]) ){ isMinQuery = 1; } /* Find any inequality constraint terms for the start and end ** of the range. */ if( pLevel->flags & WHERE_TOP_LIMIT ){ pRangeEnd = findTerm(&wc, iCur, k, notReady, (WO_LT|WO_LE), pIdx); } if( pLevel->flags & WHERE_BTM_LIMIT ){ pRangeStart = findTerm(&wc, iCur, k, notReady, (WO_GT|WO_GE), pIdx); |
︙ | ︙ | |||
2561 2562 2563 2564 2565 2566 2567 | ptr++; }else if( isMinQuery ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); ptr++; startEq = 0; start_constraints = 1; } | | < > < < | 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 | ptr++; }else if( isMinQuery ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); ptr++; startEq = 0; start_constraints = 1; } codeApplyAffinity(pParse, regBase, (int)ptr, pIdx); op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, ptr, P4_INT32); /* Load the value for the inequality constraint at the end of the ** range (if any). */ ptr = (char *)(sqlite3_intptr_t)nEq; if( pRangeEnd ){ sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq); sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt); codeApplyAffinity(pParse, regBase, nEq+1, pIdx); ptr++; } /* Top of the loop body */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ op = aEndOp[((pRangeEnd || nEq)?1:0) * (1 + bRev)]; sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, ptr, P4_INT32); |
︙ | ︙ | |||
2611 2612 2613 2614 2615 2616 2617 | /* Record the instruction used to terminate the loop. Disable ** WHERE clause terms made redundant by the index range scan. */ pLevel->op = bRev ? OP_Prev : OP_Next; pLevel->p1 = iIdxCur; disableTerm(pLevel, pRangeStart); disableTerm(pLevel, pRangeEnd); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 | /* Record the instruction used to terminate the loop. Disable ** WHERE clause terms made redundant by the index range scan. */ pLevel->op = bRev ? OP_Prev : OP_Next; pLevel->p1 = iIdxCur; disableTerm(pLevel, pRangeStart); disableTerm(pLevel, pRangeEnd); }else{ /* Case 5: There is no usable index. We must do a complete ** scan of the entire table. */ assert( omitTable==0 ); assert( bRev==0 ); pLevel->op = OP_Next; |
︙ | ︙ |