1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-11 01:42:22 +03:00

More changes to support the new types model. Compound SELECTs are currently

broken. (CVS 1389)

FossilOrigin-Name: 0f6c9b05e688e281fa168aacdd867db408df2863
This commit is contained in:
danielk1977
2004-05-17 10:48:57 +00:00
parent 93edea9380
commit e014a83880
10 changed files with 406 additions and 153 deletions

View File

@@ -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,6 +55,64 @@ static char exprAffinity(Expr *pExpr){
return pExpr->affinity;
}
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 ){
return SQLITE_AFF_INTEGER;
}else if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){
return SQLITE_AFF_NUMERIC;
}else{
return SQLITE_AFF_NONE;
}
}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 the P1 value that should be used for a binary comparison
** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
@@ -34,27 +120,9 @@ static char exprAffinity(Expr *pExpr){
** 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);
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;
}else{
aff1 = SQLITE_AFF_NONE;
}
}else if( !aff1 ){
aff1 = aff2;
}
return (((int)aff1)<<8)+(jumpIfNull?1:0);
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);

View File

@@ -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;

View File

@@ -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
**

View File

@@ -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);

View File

@@ -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

View File

@@ -1458,8 +1458,6 @@ int sqlite3VdbeKeyCompare(
return -1;
}
return_result:
return 0;
}

View File

@@ -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;
}
}
}
}