Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Enhance the sqlite3VdbeGetOp() routine so that it always returns a pointer to VdbeOp, even following an OOM fault. This simplifies error handling in callers. Cleanup to the column cache logic and the expr.c source module. (CVS 6691) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ede06dacdf7acab23cd9666a0a0d092a |
User & Date: | drh 2009-05-29 19:00:13.000 |
Context
2009-05-30
| ||
10:46 | In vacuum.c use "PagerIsMemdb(X)" instead of "PagerFile(X)->pMethods==0". (CVS 6692) (check-in: 874295ce71 user: danielk1977 tags: trunk) | |
2009-05-29
| ||
19:00 | Enhance the sqlite3VdbeGetOp() routine so that it always returns a pointer to VdbeOp, even following an OOM fault. This simplifies error handling in callers. Cleanup to the column cache logic and the expr.c source module. (CVS 6691) (check-in: ede06dacdf user: drh tags: trunk) | |
14:39 | Refinements in expression handling logic that have resulted from recent structural testing. (CVS 6690) (check-in: bd89f2c29b user: drh tags: trunk) | |
Changes
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.441 2009/05/29 19:00:13 drh Exp $ */ #include "sqliteInt.h" /* ** Return the 'affinity' of the expression pExpr if any. ** ** If pExpr is a column, a reference to a column via an 'AS' alias, |
︙ | ︙ | |||
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 | */ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ int i; int minLru; int idxLru; struct yColCache *p; /* First replace any existing entry */ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){ cacheEntryClear(pParse, p); p->iLevel = pParse->iCacheLevel; p->iReg = iReg; p->affChange = 0; p->lru = pParse->iCacheCnt++; return; } } | > > > < | 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 | */ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ int i; int minLru; int idxLru; struct yColCache *p; assert( iReg>0 ); /* Register numbers are always positive */ assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ /* First replace any existing entry */ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){ cacheEntryClear(pParse, p); p->iLevel = pParse->iCacheLevel; p->iReg = iReg; p->affChange = 0; p->lru = pParse->iCacheCnt++; return; } } /* Find an empty slot and replace it */ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->iReg==0 ){ p->iLevel = pParse->iCacheLevel; p->iTable = iTab; p->iColumn = iCol; |
︙ | ︙ | |||
1805 1806 1807 1808 1809 1810 1811 | idxLru = -1; for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->lru<minLru ){ idxLru = i; minLru = p->lru; } } | | | 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 | idxLru = -1; for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->lru<minLru ){ idxLru = i; minLru = p->lru; } } if( ALWAYS(idxLru>=0) ){ p = &pParse->aColCache[idxLru]; p->iLevel = pParse->iCacheLevel; p->iTable = iTab; p->iColumn = iCol; p->iReg = iReg; p->affChange = 0; p->tempReg = 0; |
︙ | ︙ | |||
1907 1908 1909 1910 1911 1912 1913 | Vdbe *v = pParse->pVdbe; int i; struct yColCache *p; for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn && (!p->affChange || allowAffChng) ){ | < < < < | < < | 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 | Vdbe *v = pParse->pVdbe; int i; struct yColCache *p; for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn && (!p->affChange || allowAffChng) ){ p->lru = pParse->iCacheCnt++; sqlite3ExprCachePinRegister(pParse, p->iReg); return p->iReg; } } assert( v!=0 ); if( iColumn<0 ){ sqlite3VdbeAddOp2(v, OP_Rowid, iTable, iReg); }else if( ALWAYS(pTab!=0) ){ 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); } |
︙ | ︙ | |||
1973 1974 1975 1976 1977 1978 1979 | /* ** Generate code to move content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. */ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ int i; struct yColCache *p; | | | | 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 | /* ** Generate code to move content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. */ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ int i; struct yColCache *p; if( NEVER(iFrom==iTo) ) return; sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ int x = p->iReg; if( x>=iFrom && x<iFrom+nReg ){ p->iReg += iTo-iFrom; } } } /* ** Generate code to copy content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. */ void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){ int i; if( NEVER(iFrom==iTo) ) return; for(i=0; i<nReg; i++){ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, iFrom+i, iTo+i); } } /* ** Return true if any register in the range iFrom..iTo (inclusive) |
︙ | ︙ | |||
2015 2016 2017 2018 2019 2020 2021 | /* ** If the last instruction coded is an ephemeral copy of any of ** the registers in the nReg registers beginning with iReg, then ** convert the last instruction from OP_SCopy to OP_Copy. */ void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){ | < > < > | | | | 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 | /* ** If the last instruction coded is an ephemeral copy of any of ** the registers in the nReg registers beginning with iReg, then ** convert the last instruction from OP_SCopy to OP_Copy. */ void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){ VdbeOp *pOp; Vdbe *v; assert( pParse->db->mallocFailed==0 ); v = pParse->pVdbe; assert( v!=0 ); pOp = sqlite3VdbeGetOp(v, -1); assert( pOp!=0 ); if( pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){ pOp->opcode = OP_Copy; } } /* ** Generate code to store the value of the iAlias-th alias in register ** target. The first time this is called, pExpr is evaluated to compute |
︙ | ︙ | |||
2094 2095 2096 2097 2098 2099 2100 | int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ Vdbe *v = pParse->pVdbe; /* The VM under construction */ int op; /* The opcode being coded */ int inReg = target; /* Results stored in register inReg */ int regFree1 = 0; /* If non-zero free this temporary register */ int regFree2 = 0; /* If non-zero free this temporary register */ int r1, r2, r3, r4; /* Various register numbers */ | | < < | > > > | 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 | int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ Vdbe *v = pParse->pVdbe; /* The VM under construction */ int op; /* The opcode being coded */ int inReg = target; /* Results stored in register inReg */ int regFree1 = 0; /* If non-zero free this temporary register */ int regFree2 = 0; /* If non-zero free this temporary register */ int r1, r2, r3, r4; /* Various register numbers */ sqlite3 *db = pParse->db; /* The database connection */ assert( target>0 && target<=pParse->nMem ); if( v==0 ){ assert( pParse->db->mallocFailed ); return 0; } if( pExpr==0 ){ op = TK_NULL; }else{ op = pExpr->op; } switch( op ){ |
︙ | ︙ | |||
2169 2170 2171 2172 2173 2174 2175 | assert( z[n]=='\'' ); zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); break; } #endif case TK_VARIABLE: { | < < | | 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 | assert( z[n]=='\'' ); zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); break; } #endif case TK_VARIABLE: { VdbeOp *pOp; assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( pExpr->u.zToken!=0 ); assert( pExpr->u.zToken[0]!=0 ); if( pExpr->u.zToken[1]==0 && (pOp = sqlite3VdbeGetOp(v, -1))->opcode==OP_Variable && pOp->p1+pOp->p3==pExpr->iTable && pOp->p2+pOp->p3==target && pOp->p4.z==0 ){ /* If the previous instruction was a copy of the previous unnamed ** parameter into the previous register, then simply increment the ** repeat count on the prior instruction rather than making a new |
︙ | ︙ | |||
2884 2885 2886 2887 2888 2889 2890 | Vdbe *v = sqlite3GetVdbe(pParse); if( iReg!=target+i ){ sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i); } }else{ sqlite3ExprCode(pParse, pItem->pExpr, target+i); } | | | 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 | Vdbe *v = sqlite3GetVdbe(pParse); if( iReg!=target+i ){ sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i); } }else{ sqlite3ExprCode(pParse, pItem->pExpr, target+i); } if( doHardCopy && !pParse->db->mallocFailed ){ sqlite3ExprHardCopy(pParse, target, n); } } return n; } /* |
︙ | ︙ |
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.268 2009/05/29 19:00:13 drh Exp $ */ #include "sqliteInt.h" /* ** Generate code that will open a table for reading. */ void sqlite3OpenTable( |
︙ | ︙ | |||
858 859 860 861 862 863 864 | if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); }else if( pSelect ){ sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid); }else{ VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid); | | | 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 | if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); }else if( pSelect ){ sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid); }else{ VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid); pOp = sqlite3VdbeGetOp(v, -1); if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){ appendFlag = 1; pOp->opcode = OP_NewRowid; pOp->p1 = baseCur; pOp->p2 = regRowid; pOp->p3 = regAutoinc; } |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** ** $Id: vdbeaux.c,v 1.458 2009/05/29 19:00:13 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" /* |
︙ | ︙ | |||
614 615 616 617 618 619 620 | *pz = sqlite3VMPrintf(p->db, zFormat, ap); va_end(ap); } } #endif /* NDEBUG */ /* | | > > > > > > > > > > > > | > | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | *pz = sqlite3VMPrintf(p->db, zFormat, ap); va_end(ap); } } #endif /* NDEBUG */ /* ** Return the opcode for a given address. If the address is -1, then ** return the most recently inserted opcode. ** ** If a memory allocation error has occurred prior to the calling of this ** routine, then a pointer to a dummy VdbeOp will be returned. That opcode ** is readable and writable, but it has no effect. The return of a dummy ** opcode allows the call to continue functioning after a OOM fault without ** having to check to see if the return from this routine is a valid pointer. */ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ static VdbeOp dummy; assert( p->magic==VDBE_MAGIC_INIT ); if( addr<0 ) addr = p->nOp - 1; assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed ); if( p->db->mallocFailed ){ return &dummy; }else{ return &p->aOp[addr]; } } #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* ** Compute a string that describes the P4 parameter for an opcode. ** Use zTemp for any required temporary buffer space. |
︙ | ︙ |