Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Consider explicit collate clauses when matching WHERE constraints to indices. Fix for #2391. (CVS 4040) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f9a95e92dfaaa61ec0a44b9b7017b079 |
User & Date: | danielk1977 2007-05-29 12:11:30.000 |
Context
2007-05-30
| ||
06:19 | Fix a problem with zeroblob() and CAST(...) expressions that could cause an assert() to fail. (CVS 4041) (check-in: 03750a2a6b user: danielk1977 tags: trunk) | |
2007-05-29
| ||
12:11 | Consider explicit collate clauses when matching WHERE constraints to indices. Fix for #2391. (CVS 4040) (check-in: f9a95e92df user: danielk1977 tags: trunk) | |
2007-05-24
| ||
10:18 | Add some tests to verify that the parameter to the incremental_vacuum pragma is working. It is. (CVS 4039) (check-in: 1abf784fe2 user: danielk1977 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.295 2007/05/29 12:11:30 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
167 168 169 170 171 172 173 174 | ** Return a pointer to the collation sequence that should be used by ** a binary comparison operator comparing pLeft and pRight. ** ** If the left hand expression has a collating sequence type, then it is ** used. Otherwise the collation sequence for the right hand expression ** is used, or the default (BINARY) if neither expression has a collating ** type. */ | > > > | > > > > < | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | ** Return a pointer to the collation sequence that should be used by ** a binary comparison operator comparing pLeft and pRight. ** ** If the left hand expression has a collating sequence type, then it is ** used. Otherwise the collation sequence for the right hand expression ** is used, or the default (BINARY) if neither expression has a collating ** type. ** ** Argument pRight (but not pLeft) may be a null pointer. In this case, ** it is not considered. */ CollSeq* sqlite3BinaryCompareCollSeq( Parse *pParse, Expr *pLeft, Expr *pRight ){ CollSeq *pColl; assert( pLeft ); if( pLeft->flags & EP_ExpCollate ){ assert( pLeft->pColl ); pColl = pLeft->pColl; }else if( pRight && pRight->flags & EP_ExpCollate ){ assert( pRight->pColl ); pColl = pRight->pColl; }else{ pColl = sqlite3ExprCollSeq(pParse, pLeft); if( !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pRight); } |
︙ | ︙ | |||
199 200 201 202 203 204 205 | Expr *pLeft, /* The left operand */ Expr *pRight, /* The right operand */ int opcode, /* The comparison opcode */ int dest, /* Jump here if true. */ int jumpIfNull /* If true, jump if either operand is NULL */ ){ int p1 = binaryCompareP1(pLeft, pRight, jumpIfNull); | | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | Expr *pLeft, /* The left operand */ Expr *pRight, /* The right operand */ int opcode, /* The comparison opcode */ int dest, /* Jump here if true. */ int jumpIfNull /* If true, jump if either operand is NULL */ ){ int p1 = binaryCompareP1(pLeft, pRight, jumpIfNull); CollSeq *p3 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); return sqlite3VdbeOp3(pParse->pVdbe, opcode, p1, dest, (void*)p3, P3_COLLSEQ); } /* ** Construct a new expression node and return a pointer to it. Memory ** for this node is obtained from sqliteMalloc(). The calling function ** is responsible for making sure the node eventually gets freed. |
︙ | ︙ | |||
1529 1530 1531 1532 1533 1534 1535 | ExprList *pEList; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); if( sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0) ){ return; } pEList = pExpr->pSelect->pEList; if( pEList && pEList->nExpr>0 ){ | | | 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 | ExprList *pEList; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); if( sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0) ){ return; } pEList = pExpr->pSelect->pEList; if( pEList && pEList->nExpr>0 ){ keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pEList->a[0].pExpr); } }else if( pExpr->pList ){ /* Case 2: expr IN (exprlist) ** ** For each expression, build an index key from the evaluation and ** store it in the temporary table. If <expr> is a column, then use |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.570 2007/05/29 12:11:30 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ #include "limits.h" #if defined(SQLITE_TCL) || defined(TCLSH) |
︙ | ︙ | |||
1565 1566 1567 1568 1569 1570 1571 | ** ** Notes On Invalid UTF-8: ** ** * These macros never allow a 7-bit character (0x00 through 0x7f) to ** be encoded as a multi-byte character. Any multi-byte character that ** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd. ** | | | 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 | ** ** Notes On Invalid UTF-8: ** ** * These macros never allow a 7-bit character (0x00 through 0x7f) to ** be encoded as a multi-byte character. Any multi-byte character that ** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd. ** ** * These macros never allow a UTF16 surrogate value to be encoded. ** If a multi-byte character attempts to encode a value between ** 0xd800 and 0xe000 then it is rendered as 0xfffd. ** ** * Bytes in the range of 0x80 through 0xbf which occur as the first ** byte of a character are interpreted as single-byte characters ** and rendered as themselves even though they are technically ** invalid characters. |
︙ | ︙ | |||
1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 | int sqlite3VtabCallConnect(Parse*, Table*); int sqlite3VtabCallDestroy(sqlite3*, int, const char *); int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *); FuncDef *sqlite3VtabOverloadFunction(FuncDef*, int nArg, Expr*); void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); int sqlite3Reprepare(Vdbe*); void sqlite3ExprListCheckLength(Parse*, ExprList*, int, const char*); #if SQLITE_MAX_EXPR_DEPTH>0 void sqlite3ExprSetHeight(Expr *); int sqlite3SelectExprHeight(Select *); #else #define sqlite3ExprSetHeight(x) #endif | > | 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 | int sqlite3VtabCallConnect(Parse*, Table*); int sqlite3VtabCallDestroy(sqlite3*, int, const char *); int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *); FuncDef *sqlite3VtabOverloadFunction(FuncDef*, int nArg, Expr*); void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); int sqlite3Reprepare(Vdbe*); void sqlite3ExprListCheckLength(Parse*, ExprList*, int, const char*); CollSeq* sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); #if SQLITE_MAX_EXPR_DEPTH>0 void sqlite3ExprSetHeight(Expr *); int sqlite3SelectExprHeight(Select *); #else #define sqlite3ExprSetHeight(x) #endif |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** ** $Id: where.c,v 1.249 2007/05/29 12:11:30 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) |
︙ | ︙ | |||
448 449 450 451 452 453 454 | CollSeq *pColl; char idxaff; int j; Parse *pParse = pWC->pParse; idxaff = pIdx->pTable->aCol[iColumn].affinity; if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue; | | > > | > | | < | | | | | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 | CollSeq *pColl; char idxaff; int j; Parse *pParse = pWC->pParse; idxaff = pIdx->pTable->aCol[iColumn].affinity; if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue; /* Figure out the collation sequence required from an index for ** it to be useful for optimising expression pX. Store this ** value in variable pColl. */ assert(pX->pLeft); pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); if( !pColl ){ pColl = pParse->db->pDfltColl; } for(j=0; j<pIdx->nColumn && pIdx->aiColumn[j]!=iColumn; j++){} assert( j<pIdx->nColumn ); if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; } return pTerm; } } |
︙ | ︙ |
Added test/tkt2391.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | # # 2007 May 28 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # $Id: tkt2391.test,v 1.1 2007/05/29 12:11:30 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt2391.1 { execsql { CREATE TABLE folders(folderid, parentid, foldername COLLATE binary); INSERT INTO folders VALUES(1, 3, 'FolderA'); INSERT INTO folders VALUES(1, 3, 'folderB'); INSERT INTO folders VALUES(4, 0, 'FolderC'); } } {} do_test tkt2391.2 { execsql { SELECT count(*) FROM folders WHERE foldername < 'FolderC'; } } {1} do_test tkt2391.3 { execsql { SELECT count(*) FROM folders WHERE foldername < 'FolderC' COLLATE nocase; } } {2} # This demonstrates the bug. Creating the index causes SQLite to ignore # the "COLLATE nocase" clause and use the default collation sequence # for column "foldername" instead (happens to be BINARY in this case). # do_test tkt2391.4 { execsql { CREATE INDEX f_i ON folders(foldername); SELECT count(*) FROM folders WHERE foldername < 'FolderC' COLLATE nocase; } } {2} finish_test |