Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Avoid duplicate OP_Column opcodes by remembering prior results. This is similar to CSE, but only applies to columns. (CVS 4943) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c29ee0fed23dcdbd9dde6b1e42b60310 |
User & Date: | drh 2008-03-31 23:48:04.000 |
Context
2008-03-31
| ||
23:51 | Add the veryquick.test script for a very fast overview test that omits all i/o and malloc testing. (CVS 4944) (check-in: f61df8daa8 user: drh tags: trunk) | |
23:48 | Avoid duplicate OP_Column opcodes by remembering prior results. This is similar to CSE, but only applies to columns. (CVS 4943) (check-in: c29ee0fed2 user: drh tags: trunk) | |
18:19 | Factor constant subexpressions out of loops. (CVS 4942) (check-in: 2126db3985 user: drh tags: trunk) | |
Changes
Changes to src/delete.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** ** $Id: delete.c,v 1.165 2008/03/31 23:48:04 drh Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, ** add an error message to pParse->zErrMsg and return NULL. If all tables ** are found, return a pointer to the last table. |
︙ | ︙ | |||
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); sqlite3ColumnDefault(v, pTab, idx); } } if( doMakeRec ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); sqlite3IndexAffinityStr(v, pIdx); } sqlite3ReleaseTempRange(pParse, regBase, nCol+1); return regBase; } /* Make sure "isView" gets undefined in case this file becomes part of ** the amalgamation - so that subsequent files do not see isView as a ** macro. */ #undef isView | > | 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); sqlite3ColumnDefault(v, pTab, idx); } } if( doMakeRec ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); sqlite3IndexAffinityStr(v, pIdx); sqlite3ExprExpireColumnCacheLines(pParse, regBase, regBase+nCol); } sqlite3ReleaseTempRange(pParse, regBase, nCol+1); return regBase; } /* Make sure "isView" gets undefined in case this file becomes part of ** the amalgamation - so that subsequent files do not see isView as a ** macro. */ #undef isView |
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.359 2008/03/31 23:48:04 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 | */ if( testAddr && !sqlite3ExprIsConstant(pE2) ){ sqlite3VdbeChangeToNoop(v, testAddr-1, 2); testAddr = 0; } /* Evaluate the expression and insert it into the temp table */ sqlite3ExprCode(pParse, pE2, r1); sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO); break; | > > > | 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 | */ if( testAddr && !sqlite3ExprIsConstant(pE2) ){ sqlite3VdbeChangeToNoop(v, testAddr-1, 2); testAddr = 0; } /* Evaluate the expression and insert it into the temp table */ pParse->disableColCache++; sqlite3ExprCode(pParse, pE2, r1); pParse->disableColCache--; sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); sqlite3ExprExpireColumnCacheLines(pParse, r1, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO); break; |
︙ | ︙ | |||
1890 1891 1892 1893 1894 1895 1896 | } } } /* ** Generate code that will extract the iColumn-th column from | | > > > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 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 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 | } } } /* ** Generate code that will extract the iColumn-th column from ** table pTab and store the column value in a register. An effort ** is made to store the column value in register iReg, but this is ** not guaranteed. The location of the column value is returned. ** ** There must be an open cursor to pTab in iTable when this routine ** is called. If iColumn<0 then code is generated that extracts the rowid. */ int sqlite3ExprCodeGetColumn( Parse *pParse, /* Parsing and code generating context */ Table *pTab, /* Description of the table we are reading from */ int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ int iReg /* Store results here */ ){ Vdbe *v = pParse->pVdbe; int i; for(i=0; i<pParse->nColCache; i++){ if( pParse->aColCache[i].iTable==iTable && pParse->aColCache[i].iColumn==iColumn ){ #if 0 sqlite3VdbeAddOp0(v, OP_Noop); VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, pParse->aColCache[i].iReg)); #endif return pParse->aColCache[i].iReg; } } assert( v!=0 ); if( iColumn<0 ){ int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid; sqlite3VdbeAddOp2(v, op, iTable, iReg); }else if( pTab==0 ){ sqlite3VdbeAddOp3(v, OP_Column, iTable, iColumn, iReg); }else{ int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg); sqlite3ColumnDefault(v, pTab, iColumn); #ifndef SQLITE_OMIT_FLOATING_POINT if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){ sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); } #endif } if( pParse->disableColCache==0 ){ i = pParse->iColCache; pParse->aColCache[i].iTable = iTable; pParse->aColCache[i].iColumn = iColumn; pParse->aColCache[i].iReg = iReg; i++; if( i>ArraySize(pParse->aColCache) ) i = 0; if( i>pParse->nColCache ) pParse->nColCache = i; } return iReg; } /* ** Disable (+1) or enable (-1) the adding of new column cache entries. */ void sqlite3ExprColumnCacheDisable(Parse *pParse, int disable){ assert( disable==-1 || disable==+1 ); assert( pParse->disableColCache>0 || disable==1 ); pParse->disableColCache += disable; } /* ** Clear all column cache entries associated with the vdbe ** cursor with cursor number iTable. */ void sqlite3ExprClearColumnCache(Parse *pParse, int iTable){ if( iTable<0 ){ pParse->nColCache = 0; pParse->iColCache = 0; }else{ int i; for(i=0; i<pParse->nColCache; i++){ if( pParse->aColCache[i].iTable==iTable ){ pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; } } pParse->iColCache = pParse->nColCache; } } /* ** Expire all column cache entry associated with register between ** iFrom and iTo, inclusive. If there are no column cache entries ** on those registers then this routine is a no-op. ** ** Call this routine when register contents are overwritten to ** make sure the new register value is not used in place of the ** value that was overwritten. */ void sqlite3ExprExpireColumnCacheLines(Parse *pParse, int iFrom, int iTo){ int i; for(i=0; i<pParse->nColCache; i++){ int r = pParse->aColCache[i].iReg; if( r>=iFrom && r<=iTo ){ pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; } } pParse->iColCache = pParse->nColCache; } /* ** Generate code to moves content from one register to another. ** Keep the column cache up-to-date. */ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo){ int i; if( iFrom==iTo ) return; sqlite3VdbeAddOp2(pParse->pVdbe, OP_Move, iFrom, iTo); for(i=0; i<pParse->nColCache; i++){ if( pParse->aColCache[i].iReg==iFrom ){ pParse->aColCache[i].iReg = iTo; } } } /* ** Generate code into the current Vdbe to evaluate the given ** expression. Attempt to store the results in register "target". ** Return the register where results are stored. |
︙ | ︙ | |||
1967 1968 1969 1970 1971 1972 1973 | } case TK_COLUMN: { if( pExpr->iTable<0 ){ /* This only happens when coding check constraints */ assert( pParse->ckBase>0 ); inReg = pExpr->iColumn + pParse->ckBase; }else{ | | | 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 | } case TK_COLUMN: { if( pExpr->iTable<0 ){ /* This only happens when coding check constraints */ assert( pParse->ckBase>0 ); inReg = pExpr->iColumn + pParse->ckBase; }else{ inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, pExpr->iColumn, pExpr->iTable, target); } break; } case TK_INTEGER: { codeInteger(v, (char*)pExpr->token.z, pExpr->token.n, 0, target); break; |
︙ | ︙ | |||
2092 2093 2094 2095 2096 2097 2098 | codeReal(v, (char*)p->z, p->n, 1, target); }else{ codeInteger(v, (char*)p->z, p->n, 1, target); } }else{ regFree1 = r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); | | | 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 | codeReal(v, (char*)p->z, p->n, 1, target); }else{ codeInteger(v, (char*)p->z, p->n, 1, target); } }else{ regFree1 = r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); } inReg = target; break; } case TK_BITNOT: case TK_NOT: { |
︙ | ︙ | |||
2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 | } sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, nExpr); if( nExpr ){ sqlite3ReleaseTempRange(pParse, r1, nExpr); } break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { if( pExpr->iColumn==0 ){ sqlite3CodeSubselect(pParse, pExpr); | > | 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 | } sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, nExpr); if( nExpr ){ sqlite3ReleaseTempRange(pParse, r1, nExpr); } sqlite3ExprExpireColumnCacheLines(pParse, r1, r1+nExpr-1); break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { if( pExpr->iColumn==0 ){ sqlite3CodeSubselect(pParse, pExpr); |
︙ | ︙ | |||
2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 | j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, r1); j5 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, j3); sqlite3VdbeJumpHere(v, j4); }else{ r2 = regFree2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2); } sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeJumpHere(v, j2); sqlite3VdbeJumpHere(v, j5); break; } | > | 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 | j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, r1); j5 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, j3); sqlite3VdbeJumpHere(v, j4); }else{ r2 = regFree2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); sqlite3ExprExpireColumnCacheLines(pParse, r1, r1); j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2); } sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeJumpHere(v, j2); sqlite3VdbeJumpHere(v, j5); break; } |
︙ | ︙ | |||
2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 | assert(pExpr->pList); assert((pExpr->pList->nExpr % 2) == 0); assert(pExpr->pList->nExpr > 0); pEList = pExpr->pList; aListelem = pEList->a; nExpr = pEList->nExpr; endLabel = sqlite3VdbeMakeLabel(v); if( (pX = pExpr->pLeft)!=0 ){ cacheX = *pX; cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1); cacheX.op = TK_REGISTER; cacheX.iColumn = 0; opCompare.op = TK_EQ; opCompare.pLeft = &cacheX; | > | 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 | assert(pExpr->pList); assert((pExpr->pList->nExpr % 2) == 0); assert(pExpr->pList->nExpr > 0); pEList = pExpr->pList; aListelem = pEList->a; nExpr = pEList->nExpr; endLabel = sqlite3VdbeMakeLabel(v); sqlite3ExprColumnCacheDisable(pParse, 1); if( (pX = pExpr->pLeft)!=0 ){ cacheX = *pX; cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1); cacheX.op = TK_REGISTER; cacheX.iColumn = 0; opCompare.op = TK_EQ; opCompare.pLeft = &cacheX; |
︙ | ︙ | |||
2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 | } if( pExpr->pRight ){ sqlite3ExprCode(pParse, pExpr->pRight, target); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } sqlite3VdbeResolveLabel(v, endLabel); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { if( !pParse->trigStack ){ sqlite3ErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); | > | 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 | } if( pExpr->pRight ){ sqlite3ExprCode(pParse, pExpr->pRight, target); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } sqlite3VdbeResolveLabel(v, endLabel); sqlite3ExprColumnCacheDisable(pParse, -1); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { if( !pParse->trigStack ){ sqlite3ErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); |
︙ | ︙ | |||
2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 | assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); if( v==0 || pExpr==0 ) return; op = pExpr->op; switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); break; } case TK_OR: { sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_NOT: { sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: | > > > > | 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 | assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); if( v==0 || pExpr==0 ) return; op = pExpr->op; switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); pParse->disableColCache++; sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); pParse->disableColCache--; sqlite3VdbeResolveLabel(v, d2); break; } case TK_OR: { sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); pParse->disableColCache++; sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); pParse->disableColCache--; break; } case TK_NOT: { sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: |
︙ | ︙ | |||
2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 | assert( pExpr->op!=TK_LE || op==OP_Gt ); assert( pExpr->op!=TK_GT || op==OP_Le ); assert( pExpr->op!=TK_GE || op==OP_Lt ); switch( pExpr->op ){ case TK_AND: { sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_OR: { int d2 = sqlite3VdbeMakeLabel(v); sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); break; } case TK_NOT: { sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } | > > > > | 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 | assert( pExpr->op!=TK_LE || op==OP_Gt ); assert( pExpr->op!=TK_GT || op==OP_Le ); assert( pExpr->op!=TK_GE || op==OP_Lt ); switch( pExpr->op ){ case TK_AND: { sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); pParse->disableColCache++; sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); pParse->disableColCache--; break; } case TK_OR: { int d2 = sqlite3VdbeMakeLabel(v); sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); pParse->disableColCache++; sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); pParse->disableColCache--; sqlite3VdbeResolveLabel(v, d2); break; } case TK_NOT: { sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } |
︙ | ︙ | |||
2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 | int i; if( pList ){ for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){ sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); } } } /* ** Allocate or deallocate temporary use registers during code generation. */ int sqlite3GetTempReg(Parse *pParse){ | > > > > > > > > > > > > > > | > > > | > > | > > > > > | < | > > | 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 | int i; if( pList ){ for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){ sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); } } } /* ** Return true if any register in the range iFrom..iTo (inclusive) ** is used as part of the column cache. */ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; for(i=0; i<pParse->nColCache; i++){ int r = pParse->aColCache[i].iReg; if( r>=iFrom && r<=iTo ) return 1; } return 0; } /* ** Allocate or deallocate temporary use registers during code generation. */ int sqlite3GetTempReg(Parse *pParse){ int i, r; if( pParse->nTempReg==0 ){ return ++pParse->nMem; } for(i=0; i<pParse->nTempReg; i++){ r = pParse->aTempReg[i]; if( usedAsColumnCache(pParse, r, r) ) continue; } if( i>=pParse->nTempReg ){ return ++pParse->nMem; } while( i<pParse->nTempReg-1 ){ pParse->aTempReg[i] = pParse->aTempReg[i+1]; } pParse->nTempReg--; return r; } void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ assert( iReg>0 ); pParse->aTempReg[pParse->nTempReg++] = iReg; } } /* ** Allocate or deallocate a block of nReg consecutive registers */ int sqlite3GetTempRange(Parse *pParse, int nReg){ int i, n; i = pParse->iRangeReg; n = pParse->nRangeReg; if( nReg<=n && !usedAsColumnCache(pParse, i, i+n-1) ){ pParse->iRangeReg += nReg; pParse->nRangeReg -= nReg; }else{ i = pParse->nMem+1; pParse->nMem += nReg; } return i; |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** ** $Id: insert.c,v 1.234 2008/03/31 23:48:05 drh Exp $ */ #include "sqliteInt.h" /* ** Set P4 of the most recently inserted opcode to a column affinity ** string for index pIdx. A column affinity string has one character ** for each column in the table, according to the affinity of the column: |
︙ | ︙ | |||
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 | }else{ sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i); } } sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]); sqlite3IndexAffinityStr(v, pIdx); sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); /* Find out what action to take in case there is an indexing conflict */ onError = pIdx->onError; if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */ if( overrideError!=OE_Default ){ onError = overrideError; | > | 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 | }else{ sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i); } } sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]); sqlite3IndexAffinityStr(v, pIdx); sqlite3ExprExpireColumnCacheLines(pParse, regIdx, regIdx+pIdx->nColumn); sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); /* Find out what action to take in case there is an indexing conflict */ onError = pIdx->onError; if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */ if( overrideError!=OE_Default ){ onError = overrideError; |
︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 | if( aRegIdx[i]==0 ) continue; sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]); } regData = regRowid + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3TableAffinityStr(v, pTab); #ifndef SQLITE_OMIT_TRIGGER if( newIdx>=0 ){ sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid); } #endif if( pParse->nested ){ pik_flags = 0; | > | 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 | if( aRegIdx[i]==0 ) continue; sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]); } regData = regRowid + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3TableAffinityStr(v, pTab); sqlite3ExprExpireColumnCacheLines(pParse, regData, regData+pTab->nCol-1); #ifndef SQLITE_OMIT_TRIGGER if( newIdx>=0 ){ sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid); } #endif if( pParse->nested ){ pik_flags = 0; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.424 2008/03/31 23:48:05 drh Exp $ */ #include "sqliteInt.h" /* ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. |
︙ | ︙ | |||
237 238 239 240 241 242 243 | */ Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){ Token dummy; setToken(&dummy, zName); return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy); } | < | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | */ Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){ Token dummy; setToken(&dummy, zName); return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy); } /* ** Add a term to the WHERE expression in *ppExpr that requires the ** zCol column to be equal in the two tables pTab1 and pTab2. */ static void addWhereTerm( Parse *pParse, /* Parsing context */ const char *zCol, /* Name of the column */ |
︙ | ︙ | |||
421 422 423 424 425 426 427 | ){ Vdbe *v = pParse->pVdbe; int nExpr = pOrderBy->nExpr; int regBase = sqlite3GetTempRange(pParse, nExpr+2); int regRecord = sqlite3GetTempReg(pParse); sqlite3ExprCodeExprList(pParse, pOrderBy, regBase); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); | | | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | ){ Vdbe *v = pParse->pVdbe; int nExpr = pOrderBy->nExpr; int regBase = sqlite3GetTempRange(pParse, nExpr+2); int regRecord = sqlite3GetTempReg(pParse); sqlite3ExprCodeExprList(pParse, pOrderBy, regBase); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nExpr+2); if( pSelect->iLimit>=0 ){ int addr1, addr2; int iLimit; |
︙ | ︙ | |||
666 667 668 669 670 671 672 673 674 675 676 677 678 679 | ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ pushOntoSorter(pParse, pOrderBy, p, regResult); }else{ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3ReleaseTempReg(pParse, r1); } sqlite3VdbeJumpHere(v, addr2); break; } | > | 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 | ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ pushOntoSorter(pParse, pOrderBy, p, regResult); }else{ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1); sqlite3ExprExpireColumnCacheLines(pParse, regResult, regResult); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3ReleaseTempReg(pParse, r1); } sqlite3VdbeJumpHere(v, addr2); break; } |
︙ | ︙ | |||
690 691 692 693 694 695 696 | ** of the scan loop. */ case SRT_Mem: { assert( nColumn==1 ); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p, regResult); }else{ | | | 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 | ** of the scan loop. */ case SRT_Mem: { assert( nColumn==1 ); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p, regResult); }else{ sqlite3ExprCodeMove(pParse, regResult, iParm); /* The LIMIT clause will jump out of the loop for us */ } break; } #endif /* #ifndef SQLITE_OMIT_SUBQUERY */ /* Send the data to the callback function or to a subroutine. In the |
︙ | ︙ | |||
712 713 714 715 716 717 718 719 720 721 722 723 724 725 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); }else if( eDest==SRT_Subroutine ){ sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); } break; } #if !defined(SQLITE_OMIT_TRIGGER) /* Discard the results. This is used for SELECT statements inside ** the body of a TRIGGER. The purpose of such selects is to call | > | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); }else if( eDest==SRT_Subroutine ){ sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); sqlite3ExprExpireColumnCacheLines(pParse,regResult,regResult+nColumn-1); } break; } #if !defined(SQLITE_OMIT_TRIGGER) /* Discard the results. This is used for SELECT statements inside ** the body of a TRIGGER. The purpose of such selects is to call |
︙ | ︙ | |||
830 831 832 833 834 835 836 837 838 839 840 841 842 | } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { int j1; assert( nColumn==1 ); j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); sqlite3VdbeJumpHere(v, j1); break; } case SRT_Mem: { assert( nColumn==1 ); | > | > > | 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 | } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { int j1; assert( nColumn==1 ); j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1); sqlite3ExprExpireColumnCacheLines(pParse, regRow, regRow); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); sqlite3VdbeJumpHere(v, j1); break; } case SRT_Mem: { assert( nColumn==1 ); sqlite3ExprCodeMove(pParse, regRow, iParm); /* The LIMIT clause will terminate the loop for us */ break; } #endif case SRT_Callback: case SRT_Subroutine: { int i; sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid); for(i=0; i<nColumn; i++){ assert( regRow!=pDest->iMem+i ); sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i); } if( eDest==SRT_Callback ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); sqlite3ExprExpireColumnCacheLines(pParse, pDest->iMem, pDest->iMem+nColumn-1); }else{ sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); } break; } default: { /* Do nothing */ |
︙ | ︙ | |||
2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 | } sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem, (void*)pF->pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, nArg); sqlite3ReleaseTempRange(pParse, regAgg, nArg); if( addrNext ){ sqlite3VdbeResolveLabel(v, addrNext); } } for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); } | > | 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 | } sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem, (void*)pF->pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, nArg); sqlite3ReleaseTempRange(pParse, regAgg, nArg); sqlite3ExprExpireColumnCacheLines(pParse, regAgg, regAgg+nArg-1); if( addrNext ){ sqlite3VdbeResolveLabel(v, addrNext); } } for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); } |
︙ | ︙ | |||
3430 3431 3432 3433 3434 3435 3436 | regBase = sqlite3GetTempRange(pParse, nCol); sqlite3ExprCodeExprList(pParse, pGroupBy, regBase); sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy); j = nGroupBy+1; for(i=0; i<sAggInfo.nColumn; i++){ struct AggInfo_col *pCol = &sAggInfo.aCol[i]; if( pCol->iSorterColumn>=j ){ | < | > > > > > | 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 | regBase = sqlite3GetTempRange(pParse, nCol); sqlite3ExprCodeExprList(pParse, pGroupBy, regBase); sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy); j = nGroupBy+1; for(i=0; i<sAggInfo.nColumn; i++){ struct AggInfo_col *pCol = &sAggInfo.aCol[i]; if( pCol->iSorterColumn>=j ){ int r1 = j + regBase; int r2 = sqlite3ExprCodeGetColumn(pParse, pCol->pTab, pCol->iColumn, pCol->iTable, r1); if( r1!=r2 ){ sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); } j++; } } regRecord = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); |
︙ | ︙ | |||
3481 3482 3483 3484 3485 3486 3487 | ** This code copies current group by terms in b0,b1,b2,... ** over to a0,a1,a2. It then calls the output subroutine ** and resets the aggregate accumulator registers in preparation ** for the next GROUP BY batch. */ sqlite3VdbeResolveLabel(v, addrGroupByChange); for(j=0; j<pGroupBy->nExpr; j++){ | | | 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 | ** This code copies current group by terms in b0,b1,b2,... ** over to a0,a1,a2. It then calls the output subroutine ** and resets the aggregate accumulator registers in preparation ** for the next GROUP BY batch. */ sqlite3VdbeResolveLabel(v, addrGroupByChange); for(j=0; j<pGroupBy->nExpr; j++){ sqlite3ExprCodeMove(pParse, iBMem+j, iAMem+j); } sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow); VdbeComment((v, "output one row")); sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeComment((v, "check abort flag")); sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrReset); VdbeComment((v, "reset accumulator")); |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.683 2008/03/31 23:48:05 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Include the configuration header output by 'configure' if it was run ** (otherwise we get an empty default). |
︙ | ︙ | |||
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 | int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int ckBase; /* Base register of data during check constraints */ u32 writeMask; /* Start a write transaction on these databases */ u32 cookieMask; /* Bitmask of schema verified databases */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ | > > > > > > > > | 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 | int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int ckBase; /* Base register of data during check constraints */ int disableColCache; /* True to disable adding to column cache */ int nColCache; /* Number of entries in the column cache */ int iColCache; /* Next entry of the cache to replace */ struct { int iTable; /* Table cursor number */ int iColumn; /* Table column number */ int iReg; /* Register holding value of this column */ } aColCache[10]; /* One for each valid column cache entry */ u32 writeMask; /* Start a write transaction on these databases */ u32 cookieMask; /* Bitmask of schema verified databases */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ |
︙ | ︙ | |||
1825 1826 1827 1828 1829 1830 1831 | Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8); void sqlite3WhereEnd(WhereInfo*); | | > > > > | 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 | Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8); void sqlite3WhereEnd(WhereInfo*); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int); void sqlite3ExprClearColumnCache(Parse*, int); void sqlite3ExprColumnCacheDisable(Parse*, int); void sqlite3ExprExpireColumnCacheLines(Parse*, int, int); int sqlite3ExprCode(Parse*, Expr*, int); int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); int sqlite3ExprCodeAndCache(Parse*, Expr*, int); void sqlite3ExprCodeConstants(Parse*, Expr*); int sqlite3ExprCodeExprList(Parse*, ExprList*, int); void sqlite3ExprIfTrue(Parse*, Expr*, int, int); |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** ** $Id: update.c,v 1.174 2008/03/31 23:48:05 drh Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ |
︙ | ︙ | |||
442 443 444 445 446 447 448 449 450 451 452 453 454 455 | }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i); } } sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow); if( !isView ){ sqlite3TableAffinityStr(v, pTab); } sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); if( pParse->nErr ) goto update_cleanup; sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRow, regRowid); sqlite3ReleaseTempReg(pParse, regRowid); sqlite3ReleaseTempReg(pParse, regRow); | > | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i); } } sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow); if( !isView ){ sqlite3TableAffinityStr(v, pTab); sqlite3ExprExpireColumnCacheLines(pParse, regCols, regCols+pTab->nCol-1); } sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); if( pParse->nErr ) goto update_cleanup; sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRow, regRowid); sqlite3ReleaseTempReg(pParse, regRowid); sqlite3ReleaseTempReg(pParse, regRow); |
︙ | ︙ |
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.296 2008/03/31 23:48:05 drh Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) |
︙ | ︙ | |||
1725 1726 1727 1728 1729 1730 1731 | ** ** There should be nColumn values on the stack. The index ** to be probed is pIdx. Pop the values from the stack and ** replace them all with a single record that is the index ** problem. */ static void buildIndexProbe( | | > > > | 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 | ** ** There should be nColumn values on the stack. The index ** to be probed is pIdx. Pop the values from the stack and ** replace them all with a single record that is the index ** problem. */ static void buildIndexProbe( Parse *pParse, /* Parsing and code generation context */ int nColumn, /* The number of columns to check for NULL */ Index *pIdx, /* Index that we will be searching */ int regSrc, /* Take values from this register */ int regDest /* Write the result into this register */ ){ Vdbe *v = pParse->pVdbe; assert( regSrc>0 ); assert( regDest>0 ); assert( v!=0 ); sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest); sqlite3IndexAffinityStr(v, pIdx); sqlite3ExprExpireColumnCacheLines(pParse, regSrc, regSrc+nColumn-1); } /* ** 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. |
︙ | ︙ | |||
2528 2529 2530 2531 2532 2533 2534 | if( testOp!=OP_Noop || (isMinQuery&&bRev) ){ int nCol = nEq + topLimit; if( isMinQuery && bRev && !topLimit ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol); nCol++; topEq = 0; } | | | 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 | if( testOp!=OP_Noop || (isMinQuery&&bRev) ){ int nCol = nEq + topLimit; if( isMinQuery && bRev && !topLimit ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol); nCol++; topEq = 0; } buildIndexProbe(pParse, nCol, pIdx, regBase, pLevel->iMem); if( bRev ){ int op = topEq ? OP_MoveLe : OP_MoveLt; sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, pLevel->iMem); } }else if( bRev ){ sqlite3VdbeAddOp2(v, OP_Last, iIdxCur, brk); } |
︙ | ︙ | |||
2573 2574 2575 2576 2577 2578 2579 | } if( bRev ){ r1 = pLevel->iMem; testOp = OP_IdxLT; }else{ r1 = sqlite3GetTempReg(pParse); } | | | 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 | } if( bRev ){ r1 = pLevel->iMem; testOp = OP_IdxLT; }else{ r1 = sqlite3GetTempReg(pParse); } buildIndexProbe(pParse, nCol, pIdx, regBase, r1); if( !bRev ){ int op = btmEq ? OP_MoveGe : OP_MoveGt; sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1); sqlite3ReleaseTempReg(pParse, r1); } }else if( bRev ){ testOp = OP_Noop; |
︙ | ︙ | |||
2634 2635 2636 2637 2638 2639 2640 | if( (obflag==ORDERBY_MIN) && (pLevel->flags&WHERE_ORDERBY) && (pIdx->nColumn>nEq) && (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq]) ){ isMinQuery = 1; | | | | | 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 | if( (obflag==ORDERBY_MIN) && (pLevel->flags&WHERE_ORDERBY) && (pIdx->nColumn>nEq) && (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq]) ){ isMinQuery = 1; buildIndexProbe(pParse, nEq, pIdx, regBase, pLevel->iMem); sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); r1 = ++pParse->nMem; buildIndexProbe(pParse, nEq+1, pIdx, regBase, r1); }else{ /* Generate a single key that will be used to both start and ** terminate the search */ r1 = pLevel->iMem; buildIndexProbe(pParse, nEq, pIdx, regBase, r1); } /* Generate code (1) to move to the first matching element of the table. ** Then generate code (2) that jumps to "nxt" after the cursor is past ** the last matching element of the table. The code (1) is executed ** once to initialize the search, the code (2) is executed before each ** iteration of the scan to see if the scan has finished. */ |
︙ | ︙ | |||
2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 | /* For a LEFT OUTER JOIN, generate code that will record the fact that ** at least one row of the right table has matched the left table. */ if( pLevel->iLeftJoin ){ pLevel->top = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){ if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & notReady)!=0 ) continue; assert( pTerm->pExpr ); sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, SQLITE_JUMPIFNULL); pTerm->flags |= TERM_CODED; } | > > | 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 | /* For a LEFT OUTER JOIN, generate code that will record the fact that ** at least one row of the right table has matched the left table. */ if( pLevel->iLeftJoin ){ pLevel->top = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); sqlite3ExprClearColumnCache(pParse, pLevel->iTabCur); sqlite3ExprClearColumnCache(pParse, pLevel->iIdxCur); for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){ if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & notReady)!=0 ) continue; assert( pTerm->pExpr ); sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, SQLITE_JUMPIFNULL); pTerm->flags |= TERM_CODED; } |
︙ | ︙ | |||
2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 | Vdbe *v = pWInfo->pParse->pVdbe; int i; WhereLevel *pLevel; SrcList *pTabList = pWInfo->pTabList; /* Generate loop termination code. */ for(i=pTabList->nSrc-1; i>=0; i--){ pLevel = &pWInfo->a[i]; sqlite3VdbeResolveLabel(v, pLevel->cont); if( pLevel->op!=OP_Noop ){ sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2); } if( pLevel->nIn ){ | > | 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 | Vdbe *v = pWInfo->pParse->pVdbe; int i; WhereLevel *pLevel; SrcList *pTabList = pWInfo->pTabList; /* Generate loop termination code. */ sqlite3ExprClearColumnCache(pWInfo->pParse, -1); for(i=pTabList->nSrc-1; i>=0; i--){ pLevel = &pWInfo->a[i]; sqlite3VdbeResolveLabel(v, pLevel->cont); if( pLevel->op!=OP_Noop ){ sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2); } if( pLevel->nIn ){ |
︙ | ︙ |