diff options
author | danielk1977 <danielk1977@noemail.net> | 2004-05-17 10:48:57 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2004-05-17 10:48:57 +0000 |
commit | e014a83880e3064cbc202de5ff92a4059faa274c (patch) | |
tree | 97d34760fc860b91ffc1a174b4b7b65b34b0d049 /src | |
parent | 93edea938088fc2cab91224d76191bd912fb53b3 (diff) | |
download | sqlite-e014a83880e3064cbc202de5ff92a4059faa274c.tar.gz sqlite-e014a83880e3064cbc202de5ff92a4059faa274c.zip |
More changes to support the new types model. Compound SELECTs are currently
broken. (CVS 1389)
FossilOrigin-Name: 0f6c9b05e688e281fa168aacdd867db408df2863
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 218 | ||||
-rw-r--r-- | src/insert.c | 8 | ||||
-rw-r--r-- | src/select.c | 20 | ||||
-rw-r--r-- | src/sqliteInt.h | 6 | ||||
-rw-r--r-- | src/vdbe.c | 86 | ||||
-rw-r--r-- | src/vdbeaux.c | 2 | ||||
-rw-r--r-- | src/where.c | 54 |
7 files changed, 264 insertions, 130 deletions
diff --git a/src/expr.c b/src/expr.c index 1ba427ef5..be2c26573 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,11 +12,39 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.120 2004/05/16 22:55:28 danielk1977 Exp $ +** $Id: expr.c,v 1.121 2004/05/17 10:48:58 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> +char const *sqlite3AffinityString(char affinity){ + switch( affinity ){ + case SQLITE_AFF_INTEGER: return "i"; + case SQLITE_AFF_NUMERIC: return "n"; + case SQLITE_AFF_TEXT: return "t"; + case SQLITE_AFF_NONE: return "o"; + default: + assert(0); + } +} + + +/* +** Return the 'affinity' of the expression pExpr if any. +** +** If pExpr is a column, a reference to a column via an 'AS' alias, +** or a sub-select with a column as the return value, then the +** affinity of that column is returned. Otherwise, 0x00 is returned, +** indicating no affinity for the expression. +** +** i.e. the WHERE clause expresssions in the following statements all +** have an affinity: +** +** CREATE TABLE t1(a); +** SELECT * FROM t1 WHERE a; +** SELECT a AS b FROM t1 WHERE b; +** SELECT * FROM t1 WHERE (select a from t1); +*/ static char exprAffinity(Expr *pExpr){ if( pExpr->op==TK_AS ){ return exprAffinity(pExpr->pLeft); @@ -27,34 +55,74 @@ static char exprAffinity(Expr *pExpr){ return pExpr->affinity; } -/* -** Return the P1 value that should be used for a binary comparison -** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. -** If jumpIfNull is true, then set the low byte of the returned -** P1 value to tell the opcode to jump if either expression -** evaluates to NULL. -*/ -int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ - char aff1 = exprAffinity(pExpr1); - char aff2 = exprAffinity(pExpr2); - +char sqlite3CompareAffinity(Expr *pExpr, char aff2){ + char aff1 = exprAffinity(pExpr); if( aff1 && aff2 ){ /* Both sides of the comparison are columns. If one has numeric or ** integer affinity, use that. Otherwise use no affinity. */ if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){ - aff1 = SQLITE_AFF_INTEGER; - }else - if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){ - aff1 = SQLITE_AFF_NUMERIC; + return SQLITE_AFF_INTEGER; + }else if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){ + return SQLITE_AFF_NUMERIC; }else{ - aff1 = SQLITE_AFF_NONE; + return SQLITE_AFF_NONE; } - }else if( !aff1 ){ - aff1 = aff2; + }else if( !aff1 && !aff2 ){ + /* Neither side of the comparison is a column. Use numeric affinity + ** for the comparison. + */ + return SQLITE_AFF_NUMERIC; + }else{ + /* One side is a column, the other is not. Use the columns affinity. */ + return (aff1 + aff2); + } +} + +static char comparisonAffinity(Expr *pExpr){ + char aff; + assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || + pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || + pExpr->op==TK_NE ); + assert( pExpr->pLeft ); + aff = exprAffinity(pExpr->pLeft); + if( pExpr->pRight ){ + aff = sqlite3CompareAffinity(pExpr->pRight, aff); + } + else if( pExpr->pSelect ){ + aff = sqlite3CompareAffinity(pExpr->pSelect->pEList->a[0].pExpr, aff); + } + else if( !aff ){ + aff = SQLITE_AFF_NUMERIC; } + return aff; +} + +/* +** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. +** idx_affinity is the affinity of an indexed column. Return true +** if the index with affinity idx_affinity may be used to implement +** the comparison in pExpr. +*/ +int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ + char aff = comparisonAffinity(pExpr); + return + (aff==SQLITE_AFF_NONE) || + (aff==SQLITE_AFF_NUMERIC && idx_affinity==SQLITE_AFF_INTEGER) || + (aff==SQLITE_AFF_INTEGER && idx_affinity==SQLITE_AFF_NUMERIC) || + (aff==idx_affinity); +} - return (((int)aff1)<<8)+(jumpIfNull?1:0); +/* +** Return the P1 value that should be used for a binary comparison +** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. +** If jumpIfNull is true, then set the low byte of the returned +** P1 value to tell the opcode to jump if either expression +** evaluates to NULL. +*/ +static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ + char aff = exprAffinity(pExpr2); + return (((int)sqlite3CompareAffinity(pExpr1, aff))<<8)+(jumpIfNull?1:0); } /* @@ -728,30 +796,59 @@ int sqlite3ExprResolveIds( } case TK_IN: { + char affinity; Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return 1; if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){ return 1; } + affinity = exprAffinity(pExpr->pLeft); + + /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)' + ** expression it is handled the same way. A temporary table is + ** filled with single-field index keys representing the results + ** from the SELECT or the <exprlist>. + ** + ** If the 'x' expression is a column value, or the SELECT... + ** statement returns a column value, then the affinity of that + ** column is used to build the index keys. If both 'x' and the + ** SELECT... statement are columns, then numeric affinity is used + ** if either column has NUMERIC or INTEGER affinity. If neither + ** 'x' nor the SELECT... statement are columns, then numeric affinity + ** is used. + */ + pExpr->iTable = pParse->nTab++; + sqlite3VdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1); + if( pExpr->pSelect ){ /* Case 1: expr IN (SELECT ...) ** - ** Generate code to write the results of the select into a temporary - ** table. The cursor number of the temporary table has already - ** been put in iTable by sqlite3ExprResolveInSelect(). + ** Generate code to write the results of the select into the temporary + ** table allocated and opened above. */ - pExpr->iTable = pParse->nTab++; - sqlite3VdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1); - sqlite3Select(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0); + int iParm = pExpr->iTable + (((int)affinity)<<16); + assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); + sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0); }else if( pExpr->pList ){ /* Case 2: expr IN (exprlist) ** - ** Create a set to put the exprlist values in. The Set id is stored - ** in iTable. + ** For each expression, build an index key from the evaluation and + ** store it in the temporary table. If <expr> is a column, then use + ** that columns affinity when building index keys. If <expr> is not + ** a column, use numeric affinity. */ - int i, iSet; + int i; + char const *affStr; + if( !affinity ){ + affinity = SQLITE_AFF_NUMERIC; + } + affStr = sqlite3AffinityString(affinity); + + /* Loop through each expression in <exprlist>. */ for(i=0; i<pExpr->pList->nExpr; i++){ Expr *pE2 = pExpr->pList->a[i].pExpr; + + /* Check that the expression is constant and valid. */ if( !sqlite3ExprIsConstant(pE2) ){ sqlite3ErrorMsg(pParse, "right-hand side of IN operator must be constant"); @@ -760,27 +857,12 @@ int sqlite3ExprResolveIds( if( sqlite3ExprCheck(pParse, pE2, 0, 0) ){ return 1; } - } - iSet = pExpr->iTable = pParse->nSet++; - for(i=0; i<pExpr->pList->nExpr; i++){ - Expr *pE2 = pExpr->pList->a[i].pExpr; - switch( pE2->op ){ - case TK_FLOAT: - case TK_INTEGER: - case TK_STRING: { - int addr; - assert( pE2->token.z ); - addr = sqlite3VdbeOp3(v, OP_SetInsert, iSet, 0, - pE2->token.z, pE2->token.n); - sqlite3VdbeDequoteP3(v, addr); - break; - } - default: { - sqlite3ExprCode(pParse, pE2); - sqlite3VdbeAddOp(v, OP_SetInsert, iSet, 0); - break; - } - } + + /* Evaluate the expression and insert it into the temp table */ + sqlite3ExprCode(pParse, pE2); + sqlite3VdbeOp3(v, OP_MakeKey, 1, 0, affStr, P3_STATIC); + sqlite3VdbeAddOp(v, OP_String, 0, 0); + sqlite3VdbeAddOp(v, OP_PutStrKey, pExpr->iTable, 0); } } break; @@ -1127,12 +1209,6 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3ExprCode(pParse, pExpr->pRight); sqlite3VdbeAddOp(v, op, p1, 0); break; -#if 0 - if( sqlite3ExprType(pExpr)==SQLITE_SO_TEXT ){ - op += 6; /* Convert numeric opcodes to text opcodes */ - } - /* Fall through into the next case */ -#endif } case TK_AND: case TK_OR: @@ -1225,19 +1301,29 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ } case TK_IN: { int addr; + char const *affStr; + + /* Figure out the affinity to use to create a key from the results + ** of the expression. affinityStr stores a static string suitable for + ** P3 of OP_MakeKey. + */ + affStr = sqlite3AffinityString(comparisonAffinity(pExpr)); + sqlite3VdbeAddOp(v, OP_Integer, 1, 0); + + /* Code the <expr> from "<expr> IN (...)". The temporary table + ** pExpr->iTable contains the values that make up the (...) set. + */ sqlite3ExprCode(pParse, pExpr->pLeft); addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4); + sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4); /* addr + 0 */ sqlite3VdbeAddOp(v, OP_Pop, 2, 0); sqlite3VdbeAddOp(v, OP_String, 0, 0); - sqlite3VdbeAddOp(v, OP_Goto, 0, addr+6); - if( pExpr->pSelect ){ - sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+6); - }else{ - sqlite3VdbeAddOp(v, OP_SetFound, pExpr->iTable, addr+6); - } - sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7); + sqlite3VdbeOp3(v, OP_MakeKey, 1, 0, affStr, P3_STATIC); /* addr + 4 */ + sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7); + sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); /* addr + 6 */ + break; } case TK_BETWEEN: { @@ -1407,6 +1493,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3VdbeAddOp(v, op, 1, dest); break; } +#if 0 case TK_IN: { int addr; sqlite3ExprCode(pParse, pExpr->pLeft); @@ -1421,6 +1508,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ } break; } +#endif case TK_BETWEEN: { int addr; sqlite3ExprCode(pParse, pExpr->pLeft); @@ -1500,6 +1588,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3VdbeAddOp(v, op, 1, dest); break; } +#if 0 case TK_IN: { int addr; sqlite3ExprCode(pParse, pExpr->pLeft); @@ -1514,6 +1603,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ } break; } +#endif case TK_BETWEEN: { int addr; sqlite3ExprCode(pParse, pExpr->pLeft); diff --git a/src/insert.c b/src/insert.c index a3c12ed12..fd73dbba8 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.99 2004/05/16 11:15:38 danielk1977 Exp $ +** $Id: insert.c,v 1.100 2004/05/17 10:48:58 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -30,12 +30,12 @@ */ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ if( !pIdx->zColAff ){ - /* The first time a column affinity string for a particular table is + /* The first time a column affinity string for a particular index is ** required, it is allocated and populated here. It is then stored as - ** a member of the Table structure for subsequent use. + ** a member of the Index structure for subsequent use. ** ** The column affinity string will eventually be deleted by - ** sqliteDeleteIndex() when the Table structure itself is cleaned + ** sqliteDeleteIndex() when the Index structure itself is cleaned ** up. */ int n; diff --git a/src/select.c b/src/select.c index 475a0fd3d..c4e5d1ece 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.164 2004/05/11 06:55:14 danielk1977 Exp $ +** $Id: select.c,v 1.165 2004/05/17 10:48:58 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -479,6 +479,7 @@ static int selectInnerLoop( case SRT_Set: { int addr1 = sqlite3VdbeCurrentAddr(v); int addr2; + assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_NotNull, -1, addr1+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); @@ -486,8 +487,13 @@ static int selectInnerLoop( if( pOrderBy ){ pushOntoSorter(pParse, v, pOrderBy); }else{ + char const *affStr; + char aff = (iParm>>16)&0xFF; + aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff); + affStr = sqlite3AffinityString(aff); + sqlite3VdbeOp3(v, OP_MakeKey, 1, 1, affStr, P3_STATIC); sqlite3VdbeAddOp(v, OP_String, 0, 0); - sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0); + sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0); } sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v)); break; @@ -593,8 +599,9 @@ static void generateSortTail( sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeOp3(v, OP_MakeKey, 1, 1, "n", P3_STATIC); sqlite3VdbeAddOp(v, OP_String, 0, 0); - sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0); + sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0); break; } case SRT_Mem: { @@ -799,7 +806,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ char zBuf[30]; sprintf(zBuf,"_%d",++cnt); n = strlen(zBuf); - sqlite3SetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf, n,0); + sqlite3SetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf,n,0); j = -1; } } @@ -810,6 +817,9 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ sprintf(zBuf, "column%d", i+1); pTab->aCol[i].zName = sqliteStrDup(zBuf); } + + /* Affinity is always NONE, as there is no type name. */ + pTab->aCol[i].affinity = SQLITE_AFF_NONE; } pTab->iPKey = -1; return pTab; @@ -1942,7 +1952,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ ** ** SRT_Mem Store first result in memory cell iParm ** -** SRT_Set Store results as keys of a table with cursor iParm +** SRT_Set Store results as keys of table iParm. ** ** SRT_Union Store results as a key in a temporary table iParm ** diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ee8861960..29aac804d 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.234 2004/05/16 11:15:39 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.235 2004/05/17 10:48:58 danielk1977 Exp $ */ #include "config.h" #include "sqlite.h" @@ -1306,4 +1306,6 @@ int sqlite3VarintLen(u64 v); char sqlite3AffinityType(const char *, int); void sqlite3IndexAffinityStr(Vdbe *, Index *); void sqlite3TableAffinityStr(Vdbe *, Table *); - +char sqlite3CompareAffinity(Expr *pExpr, char aff2); +char const *sqlite3AffinityString(char affinity); +int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); diff --git a/src/vdbe.c b/src/vdbe.c index a66a29136..0126b9cef 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.295 2004/05/16 11:57:28 danielk1977 Exp $ +** $Id: vdbe.c,v 1.296 2004/05/17 10:48:58 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -1379,16 +1379,10 @@ mismatch: ** operand is NULL (and thus if the result is unknown) then take the jump ** only if the least significant byte of P1 is 0x01. ** -** The second least significant byte of P1 determines whether any -** conversions are applied to the two values before the comparison is made. -** If this byte is 0x00, and one of the values being compared is numeric -** and the other text, an attempt is made to convert the text value to -** a numeric form. -** -** If the second least significant byte of P1 is not 0x00, then it must -** be an affinity character - 'n', 't', 'i' or 'o'. In this case an -** attempt is made to coerce both values according to the affinity before -** the comparison is made. +** The second least significant byte of P1 must be an affinity character - +** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values +** according to the affinity before the comparison is made. If the byte is +** 0x00, then numeric affinity is used. ** ** Once any conversions have taken place, and neither value is NULL, ** the values are compared. If both values are blobs, or both are text, @@ -1527,13 +1521,9 @@ case OP_Ge: { } affinity = (pOp->p1>>8)&0xFF; - if( !affinity && (flags&(MEM_Real|MEM_Int)) ){ - affinity = SQLITE_AFF_NUMERIC; - } - if( affinity ){ - applyAffinity(pNos, affinity); - applyAffinity(pTos, affinity); - } + if( affinity=='\0' ) affinity = 'n'; + applyAffinity(pNos, affinity); + applyAffinity(pTos, affinity); res = sqlite3MemCompare(pNos, pTos); switch( pOp->opcode ){ @@ -2401,11 +2391,7 @@ case OP_MakeIdxKey: { */ for(pRec=pData0; pRec<=pTos; pRec++){ u64 serial_type; - if( zAffinity ){ - applyAffinity(pRec, zAffinity[pRec-pData0]); - }else{ - applyAffinity(pRec, SQLITE_SO_NUM); - } + applyAffinity(pRec, zAffinity[pRec-pData0]); if( pRec->flags&MEM_Null ){ containsNull = 1; } @@ -2837,7 +2823,8 @@ case OP_OpenTemp: { rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); - rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, 0, 0, &pCx->pCursor); + rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeKeyCompare, + pCx, &pCx->pCursor); } }else{ rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor); @@ -3546,6 +3533,57 @@ case OP_Recno: { break; } +/* Opcode: IdxColumn P1 * * +** +** P1 is a cursor opened on an index. Push the first field from the +** current index key onto the stack. +*/ +case OP_IdxColumn: { + char *zData; + i64 n; + u64 serial_type; + int len; + int freeZData = 0; + BtCursor *pCsr; + + assert( 0==p->apCsr[pOp->p1]->intKey ); + pCsr = p->apCsr[pOp->p1]->pCursor; + rc = sqlite3BtreeKeySize(pCsr, &n); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + if( n>10 ) n = 10; + + zData = (char *)sqlite3BtreeKeyFetch(pCsr, n); + assert( zData ); + + len = sqlite3GetVarint(zData, &serial_type); + n = sqlite3VdbeSerialTypeLen(serial_type); + + zData = (char *)sqlite3BtreeKeyFetch(pCsr, len+n); + if( !zData ){ + zData = (char *)sqliteMalloc(n); + if( !zData ){ + rc = SQLITE_NOMEM; + goto abort_due_to_error; + } + rc = sqlite3BtreeKey(pCsr, len, n, zData); + if( rc!=SQLITE_OK ){ + sqliteFree(zData); + goto abort_due_to_error; + } + freeZData = 1; + len = 0; + } + + pTos++; + sqlite3VdbeSerialGet(&zData[len], serial_type, pTos); + if( freeZData ){ + sqliteFree(zData); + } + break; +} + /* Opcode: FullKey P1 * * ** ** Extract the complete key from the record that cursor P1 is currently diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 80a0f9a9b..e88341e84 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1458,8 +1458,6 @@ int sqlite3VdbeKeyCompare( return -1; } -return_result: - return 0; } diff --git a/src/where.c b/src/where.c index aa3f3283b..e65362e82 100644 --- a/src/where.c +++ b/src/where.c @@ -12,7 +12,7 @@ ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. ** -** $Id: where.c,v 1.94 2004/05/16 11:15:41 danielk1977 Exp $ +** $Id: where.c,v 1.95 2004/05/17 10:48:58 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -536,8 +536,10 @@ WhereInfo *sqlite3WhereBegin( && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){ int iColumn = aExpr[j].p->pLeft->iColumn; int k; + char idxaff = pIdx->pTable->aCol[iColumn].affinity; for(k=0; k<pIdx->nColumn; k++){ - if( pIdx->aiColumn[k]==iColumn ){ + if( pIdx->aiColumn[k]==iColumn + && sqlite3IndexAffinityOk(aExpr[j].p, idxaff) ){ switch( aExpr[j].p->op ){ case TK_IN: { if( k==0 ) inMask |= 1; @@ -571,8 +573,10 @@ WhereInfo *sqlite3WhereBegin( && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){ int iColumn = aExpr[j].p->pRight->iColumn; int k; + char idxaff = pIdx->pTable->aCol[iColumn].affinity; for(k=0; k<pIdx->nColumn; k++){ - if( pIdx->aiColumn[k]==iColumn ){ + if( pIdx->aiColumn[k]==iColumn + && sqlite3IndexAffinityOk(aExpr[j].p, idxaff) ){ switch( aExpr[j].p->op ){ case TK_EQ: { eqMask |= 1<<k; @@ -720,16 +724,10 @@ WhereInfo *sqlite3WhereBegin( Expr *pX = aExpr[k].p; if( pX->op!=TK_IN ){ sqlite3ExprCode(pParse, aExpr[k].p->pRight); - }else if( pX->pList ){ - sqlite3VdbeAddOp(v, OP_SetFirst, pX->iTable, brk); - pLevel->inOp = OP_SetNext; - pLevel->inP1 = pX->iTable; - pLevel->inP2 = sqlite3VdbeCurrentAddr(v); }else{ - assert( pX->pSelect ); sqlite3VdbeAddOp(v, OP_Rewind, pX->iTable, brk); sqlite3VdbeAddOp(v, OP_KeyAsData, pX->iTable, 1); - pLevel->inP2 = sqlite3VdbeAddOp(v, OP_FullKey, pX->iTable, 0); + pLevel->inP2 = sqlite3VdbeAddOp(v, OP_IdxColumn, pX->iTable, 0); pLevel->inOp = OP_Next; pLevel->inP1 = pX->iTable; } @@ -758,27 +756,22 @@ WhereInfo *sqlite3WhereBegin( && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight && pX->pLeft->iColumn==pIdx->aiColumn[j] ){ - if( pX->op==TK_EQ ){ - sqlite3ExprCode(pParse, pX->pRight); - aExpr[k].p = 0; - break; - } - if( pX->op==TK_IN && nColumn==1 ){ - if( pX->pList ){ - sqlite3VdbeAddOp(v, OP_SetFirst, pX->iTable, brk); - pLevel->inOp = OP_SetNext; - pLevel->inP1 = pX->iTable; - pLevel->inP2 = sqlite3VdbeCurrentAddr(v); - }else{ - assert( pX->pSelect ); + char idxaff = pIdx->pTable->aCol[pX->pLeft->iColumn].affinity; + if( sqlite3IndexAffinityOk(aExpr[k].p, idxaff) ){ + if( pX->op==TK_EQ ){ + sqlite3ExprCode(pParse, pX->pRight); + aExpr[k].p = 0; + break; + } + if( pX->op==TK_IN && nColumn==1 ){ sqlite3VdbeAddOp(v, OP_Rewind, pX->iTable, brk); sqlite3VdbeAddOp(v, OP_KeyAsData, pX->iTable, 1); - pLevel->inP2 = sqlite3VdbeAddOp(v, OP_FullKey, pX->iTable, 0); + pLevel->inP2 = sqlite3VdbeAddOp(v, OP_IdxColumn, pX->iTable, 0); pLevel->inOp = OP_Next; pLevel->inP1 = pX->iTable; + aExpr[k].p = 0; + break; } - aExpr[k].p = 0; - break; } } if( aExpr[k].idxRight==iCur @@ -786,9 +779,12 @@ WhereInfo *sqlite3WhereBegin( && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j] ){ - sqlite3ExprCode(pParse, aExpr[k].p->pLeft); - aExpr[k].p = 0; - break; + char idxaff = pIdx->pTable->aCol[pX->pRight->iColumn].affinity; + if( sqlite3IndexAffinityOk(aExpr[k].p, idxaff) ){ + sqlite3ExprCode(pParse, aExpr[k].p->pLeft); + aExpr[k].p = 0; + break; + } } } } |