diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 31 | ||||
-rw-r--r-- | src/select.c | 12 | ||||
-rw-r--r-- | src/sqliteInt.h | 5 | ||||
-rw-r--r-- | src/test_func.c | 30 | ||||
-rw-r--r-- | src/vdbe.c | 3 |
5 files changed, 64 insertions, 17 deletions
diff --git a/src/expr.c b/src/expr.c index 3002ef7b1..f58743bc9 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.366 2008/04/11 15:36:03 drh Exp $ +** $Id: expr.c,v 1.367 2008/04/15 12:14:22 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -2104,6 +2104,24 @@ int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){ } /* +** 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){ + int addr; + VdbeOp *pOp; + Vdbe *v; + + v = pParse->pVdbe; + addr = sqlite3VdbeCurrentAddr(v); + pOp = sqlite3VdbeGetOp(v, addr-1); + if( pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){ + pOp->opcode = OP_Copy; + } +} + +/* ** 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. @@ -2374,7 +2392,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( pList ){ nExpr = pList->nExpr; r1 = sqlite3GetTempRange(pParse, nExpr); - sqlite3ExprCodeExprList(pParse, pList, r1); + sqlite3ExprCodeExprList(pParse, pList, r1, 1); }else{ nExpr = r1 = 0; } @@ -2804,7 +2822,8 @@ void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){ int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* The expression list to be coded */ - int target /* Where to write results */ + int target, /* Where to write results */ + int doHardCopy /* Call sqlite3ExprHardCopy on each element if true */ ){ struct ExprList_item *pItem; int i, n; @@ -2814,9 +2833,9 @@ int sqlite3ExprCodeExprList( } assert( target>0 ); n = pList->nExpr; - for(pItem=pList->a, i=n; i>0; i--, pItem++){ - sqlite3ExprCode(pParse, pItem->pExpr, target); - target++; + for(pItem=pList->a, i=0; i<n; i++, pItem++){ + sqlite3ExprCode(pParse, pItem->pExpr, target+i); + if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n); } return n; } diff --git a/src/select.c b/src/select.c index 89fe2e13e..4b9f1dfd9 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.426 2008/04/10 13:33:18 drh Exp $ +** $Id: select.c,v 1.427 2008/04/15 12:14:22 drh Exp $ */ #include "sqliteInt.h" @@ -422,7 +422,7 @@ static void pushOntoSorter( int nExpr = pOrderBy->nExpr; int regBase = sqlite3GetTempRange(pParse, nExpr+2); int regRecord = sqlite3GetTempReg(pParse); - sqlite3ExprCodeExprList(pParse, pOrderBy, regBase); + sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); @@ -580,9 +580,7 @@ static void selectInnerLoop( /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ - for(i=0; i<nResultCol; i++){ - sqlite3ExprCode(pParse, pEList->a[i].pExpr, regResult+i); - } + sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Callback); } nColumn = nResultCol; @@ -2902,7 +2900,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); - sqlite3ExprCodeExprList(pParse, pList, regAgg); + sqlite3ExprCodeExprList(pParse, pList, regAgg, 0); }else{ nArg = 0; regAgg = 0; @@ -3432,7 +3430,7 @@ int sqlite3Select( } } regBase = sqlite3GetTempRange(pParse, nCol); - sqlite3ExprCodeExprList(pParse, pGroupBy, regBase); + sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0); sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy); j = nGroupBy+1; for(i=0; i<sAggInfo.nColumn; i++){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b6f5b1ef6..6ff5b1f4b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.691 2008/04/10 16:47:42 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.692 2008/04/15 12:14:22 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1872,12 +1872,13 @@ void sqlite3ExprCodeMove(Parse*, int, int); void sqlite3ExprClearColumnCache(Parse*, int); void sqlite3ExprCacheAffinityChange(Parse*, int, int); int sqlite3ExprWritableRegister(Parse*,int,int); +void sqlite3ExprHardCopy(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); +int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int); void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); Table *sqlite3FindTable(sqlite3*,const char*, const char*); diff --git a/src/test_func.c b/src/test_func.c index 478474cbe..50d7bd60c 100644 --- a/src/test_func.c +++ b/src/test_func.c @@ -12,7 +12,7 @@ ** Code for testing all sorts of SQLite interfaces. This code ** implements new SQL functions used by the test scripts. ** -** $Id: test_func.c,v 1.4 2008/04/10 17:14:07 drh Exp $ +** $Id: test_func.c,v 1.5 2008/04/15 12:14:22 drh Exp $ */ #include "sqlite3.h" #include "tcl.h" @@ -204,6 +204,33 @@ static void test_error( } } +/* +** This function takes two arguments. It performance UTF-8/16 type +** conversions on the first argument then returns a copy of the second +** argument. +** +** This function is used in cases such as the following: +** +** SELECT test_isolation(x,x) FROM t1; +** +** We want to verify that the type conversions that occur on the +** first argument do not invalidate the second argument. +*/ +static void test_isolation( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ +#ifndef SQLITE_OMIT_UTF16 + sqlite3_value_text16(argv[0]); + sqlite3_value_text(argv[0]); + sqlite3_value_text16(argv[0]); + sqlite3_value_text(argv[0]); +#endif + sqlite3_result_value(pCtx, argv[1]); +} + + static int registerTestFunctions(sqlite3 *db){ static const struct { char *zName; @@ -218,6 +245,7 @@ static int registerTestFunctions(sqlite3 *db){ { "test_auxdata", -1, SQLITE_UTF8, test_auxdata}, { "test_error", 1, SQLITE_UTF8, test_error}, { "test_error", 2, SQLITE_UTF8, test_error}, + { "test_isolation", 2, SQLITE_UTF8, test_isolation}, }; int i; extern int Md5_Register(sqlite3*); diff --git a/src/vdbe.c b/src/vdbe.c index 7a45f6416..07bd6b99f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** 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.729 2008/04/10 14:00:10 drh Exp $ +** $Id: vdbe.c,v 1.730 2008/04/15 12:14:22 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -880,6 +880,7 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pOut) ) goto no_mem; pOut->zMalloc = 0; pOut->flags |= MEM_Static; + pOut->flags &= ~MEM_Dyn; if( pOp->p4type==P4_DYNAMIC ){ sqlite3_free(pOp->p4.z); } |