Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Activate the ability to use expressions in indexes in a query. There are some test failures, but mostly this seems to work. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | index-expr |
Files: | files | file ages | folders |
SHA1: |
42f93f582eccd8a778189aa6c113874f |
User & Date: | drh 2015-08-27 18:24:02.056 |
Context
2015-08-27
| ||
19:56 | Fix problems in the indexed-expression handling in the optimizer. (check-in: 0337501769 user: drh tags: index-expr) | |
18:24 | Activate the ability to use expressions in indexes in a query. There are some test failures, but mostly this seems to work. (check-in: 42f93f582e user: drh tags: index-expr) | |
16:07 | Merge changes from trunk. (check-in: c80e9e8e8c user: drh tags: index-expr) | |
Changes
Changes to src/insert.c.
︙ | ︙ | |||
89 90 91 92 93 94 95 96 97 | for(n=0; n<pIdx->nColumn; n++){ i16 x = pIdx->aiColumn[n]; if( x>=0 ){ pIdx->zColAff[n] = pTab->aCol[x].affinity; }else if( x==(-1) ){ pIdx->zColAff[n] = SQLITE_AFF_INTEGER; }else{ assert( x==(-2) ); assert( pIdx->aColExpr!=0 ); | > | > > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | for(n=0; n<pIdx->nColumn; n++){ i16 x = pIdx->aiColumn[n]; if( x>=0 ){ pIdx->zColAff[n] = pTab->aCol[x].affinity; }else if( x==(-1) ){ pIdx->zColAff[n] = SQLITE_AFF_INTEGER; }else{ char aff; assert( x==(-2) ); assert( pIdx->aColExpr!=0 ); aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); if( aff==0 ) aff = SQLITE_AFF_BLOB; pIdx->zColAff[n] = aff; } } pIdx->zColAff[n] = 0; } return pIdx->zColAff; } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | WhereClause *pWC; /* Shorthand for pScan->pWC */ WhereTerm *pTerm; /* The term being tested */ int k = pScan->k; /* Where to start scanning */ while( pScan->iEquiv<=pScan->nEquiv ){ iCur = pScan->aiCur[pScan->iEquiv-1]; iColumn = pScan->aiColumn[pScan->iEquiv-1]; while( (pWC = pScan->pWC)!=0 ){ for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquiv<ArraySize(pScan->aiCur) ){ int j; pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight); | > > > | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | WhereClause *pWC; /* Shorthand for pScan->pWC */ WhereTerm *pTerm; /* The term being tested */ int k = pScan->k; /* Where to start scanning */ while( pScan->iEquiv<=pScan->nEquiv ){ iCur = pScan->aiCur[pScan->iEquiv-1]; iColumn = pScan->aiColumn[pScan->iEquiv-1]; assert( iColumn!=(-2) || pScan->pIdxExpr!=0 ); while( (pWC = pScan->pWC)!=0 ){ for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn && (iColumn!=(-2) || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquiv<ArraySize(pScan->aiCur) ){ int j; pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight); |
︙ | ︙ | |||
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | Index *pIdx /* Must be compatible with this index */ ){ int j; /* memset(pScan, 0, sizeof(*pScan)); */ pScan->pOrigWC = pWC; pScan->pWC = pWC; if( pIdx ){ j = iColumn; iColumn = pIdx->aiColumn[j]; } if( pIdx && iColumn>=0 ){ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; pScan->zCollName = pIdx->azColl[j]; }else{ pScan->idxaff = 0; pScan->zCollName = 0; | > > | 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | Index *pIdx /* Must be compatible with this index */ ){ int j; /* memset(pScan, 0, sizeof(*pScan)); */ pScan->pOrigWC = pWC; pScan->pWC = pWC; pScan->pIdxExpr = 0; if( pIdx ){ j = iColumn; iColumn = pIdx->aiColumn[j]; if( iColumn==(-2) ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; } if( pIdx && iColumn>=0 ){ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; pScan->zCollName = pIdx->azColl[j]; }else{ pScan->idxaff = 0; pScan->zCollName = 0; |
︙ | ︙ | |||
2220 2221 2222 2223 2224 2225 2226 | assert( nIn>0 ); /* RHS always has 2 or more terms... The parser ** changes "x IN (?)" into "x=?". */ }else if( eOp & (WO_EQ|WO_IS) ){ int iCol = pProbe->aiColumn[saved_nEq]; pNew->wsFlags |= WHERE_COLUMN_EQ; assert( saved_nEq==pNew->u.btree.nEq ); | | | 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 | assert( nIn>0 ); /* RHS always has 2 or more terms... The parser ** changes "x IN (?)" into "x=?". */ }else if( eOp & (WO_EQ|WO_IS) ){ int iCol = pProbe->aiColumn[saved_nEq]; pNew->wsFlags |= WHERE_COLUMN_EQ; assert( saved_nEq==pNew->u.btree.nEq ); if( iCol==(-1) || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){ if( iCol>=0 && pProbe->uniqNotNull==0 ){ pNew->wsFlags |= WHERE_UNQ_WANTED; }else{ pNew->wsFlags |= WHERE_ONEROW; } } }else if( eOp & WO_ISNULL ){ |
︙ | ︙ |
Changes to src/whereInt.h.
︙ | ︙ | |||
282 283 284 285 286 287 288 289 290 291 292 293 294 295 | ** An instance of the WhereScan object is used as an iterator for locating ** terms in the WHERE clause that are useful to the query planner. */ struct WhereScan { WhereClause *pOrigWC; /* Original, innermost WhereClause */ WhereClause *pWC; /* WhereClause currently being scanned */ char *zCollName; /* Required collating sequence, if not NULL */ char idxaff; /* Must match this affinity, if zCollName!=NULL */ unsigned char nEquiv; /* Number of entries in aEquiv[] */ unsigned char iEquiv; /* Next unused slot in aEquiv[] */ u32 opMask; /* Acceptable operators */ int k; /* Resume scanning at this->pWC->a[this->k] */ int aiCur[11]; /* Cursors in the equivalence class */ i16 aiColumn[11]; /* Corresponding column number in the eq-class */ | > | 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | ** An instance of the WhereScan object is used as an iterator for locating ** terms in the WHERE clause that are useful to the query planner. */ struct WhereScan { WhereClause *pOrigWC; /* Original, innermost WhereClause */ WhereClause *pWC; /* WhereClause currently being scanned */ char *zCollName; /* Required collating sequence, if not NULL */ Expr *pIdxExpr; /* Search for this index expression */ char idxaff; /* Must match this affinity, if zCollName!=NULL */ unsigned char nEquiv; /* Number of entries in aEquiv[] */ unsigned char iEquiv; /* Next unused slot in aEquiv[] */ u32 opMask; /* Acceptable operators */ int k; /* Resume scanning at this->pWC->a[this->k] */ int aiCur[11]; /* Cursors in the equivalence class */ i16 aiColumn[11]; /* Corresponding column number in the eq-class */ |
︙ | ︙ |
Changes to src/whereexpr.c.
︙ | ︙ | |||
867 868 869 870 871 872 873 874 875 876 877 878 879 880 | if( allowedOp(op) ){ Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; if( pLeft->op==TK_COLUMN ){ pTerm->leftCursor = pLeft->iTable; pTerm->u.leftColumn = pLeft->iColumn; pTerm->eOperator = operatorMask(op) & opMask; } if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; if( pRight && pRight->op==TK_COLUMN ){ WhereTerm *pNew; Expr *pDup; u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ | > > > > > > | 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 | if( allowedOp(op) ){ Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; if( pLeft->op==TK_COLUMN ){ pTerm->leftCursor = pLeft->iTable; pTerm->u.leftColumn = pLeft->iColumn; pTerm->eOperator = operatorMask(op) & opMask; }else if( prereqLeft!=0 && (prereqLeft&(prereqLeft-1))==0 ){ int i; for(i=0; (prereqLeft>>i)<1; i++){} pTerm->leftCursor = pMaskSet->ix[i]; pTerm->u.leftColumn = -2; pTerm->eOperator = operatorMask(op) & opMask; } if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; if( pRight && pRight->op==TK_COLUMN ){ WhereTerm *pNew; Expr *pDup; u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ |
︙ | ︙ |