| | @@ -678,11 +678,11 @@ |
| 678 | 678 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 679 | 679 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 680 | 680 | */ |
| 681 | 681 | #define SQLITE_VERSION "3.7.17" |
| 682 | 682 | #define SQLITE_VERSION_NUMBER 3007017 |
| 683 | | -#define SQLITE_SOURCE_ID "2013-05-03 15:23:24 b2efe4f225adc5f4c2e3080bf459cc52fff82e18" |
| 683 | +#define SQLITE_SOURCE_ID "2013-05-08 17:06:28 1fa8c457394c94864f7584e4c893ec09e685fba4" |
| 684 | 684 | |
| 685 | 685 | /* |
| 686 | 686 | ** CAPI3REF: Run-Time Library Version Numbers |
| 687 | 687 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 688 | 688 | ** |
| | @@ -99219,10 +99219,73 @@ |
| 99219 | 99219 | } |
| 99220 | 99220 | pFrom->pIndex = pIdx; |
| 99221 | 99221 | } |
| 99222 | 99222 | return SQLITE_OK; |
| 99223 | 99223 | } |
| 99224 | +/* |
| 99225 | +** Detect compound SELECT statements that use an ORDER BY clause with |
| 99226 | +** an alternative collating sequence. |
| 99227 | +** |
| 99228 | +** SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ... |
| 99229 | +** |
| 99230 | +** These are rewritten as a subquery: |
| 99231 | +** |
| 99232 | +** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2) |
| 99233 | +** ORDER BY ... COLLATE ... |
| 99234 | +** |
| 99235 | +** This transformation is necessary because the multiSelectOrderBy() routine |
| 99236 | +** above that generates the code for a compound SELECT with an ORDER BY clause |
| 99237 | +** uses a merge algorithm that requires the same collating sequence on the |
| 99238 | +** result columns as on the ORDER BY clause. See ticket |
| 99239 | +** http://www.sqlite.org/src/info/6709574d2a |
| 99240 | +** |
| 99241 | +** This transformation is only needed for EXCEPT, INTERSECT, and UNION. |
| 99242 | +** The UNION ALL operator works fine with multiSelectOrderBy() even when |
| 99243 | +** there are COLLATE terms in the ORDER BY. |
| 99244 | +*/ |
| 99245 | +static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ |
| 99246 | + int i; |
| 99247 | + Select *pNew; |
| 99248 | + Select *pX; |
| 99249 | + sqlite3 *db; |
| 99250 | + struct ExprList_item *a; |
| 99251 | + SrcList *pNewSrc; |
| 99252 | + Parse *pParse; |
| 99253 | + Token dummy; |
| 99254 | + |
| 99255 | + if( p->pPrior==0 ) return WRC_Continue; |
| 99256 | + if( p->pOrderBy==0 ) return WRC_Continue; |
| 99257 | + for(pX=p; pX && (pX->op==TK_ALL || pX->op==TK_SELECT); pX=pX->pPrior){} |
| 99258 | + if( pX==0 ) return WRC_Continue; |
| 99259 | + a = p->pOrderBy->a; |
| 99260 | + for(i=p->pOrderBy->nExpr-1; i>=0; i--){ |
| 99261 | + if( a[i].pExpr->flags & EP_Collate ) break; |
| 99262 | + } |
| 99263 | + if( i<0 ) return WRC_Continue; |
| 99264 | + |
| 99265 | + /* If we reach this point, that means the transformation is required. */ |
| 99266 | + |
| 99267 | + pParse = pWalker->pParse; |
| 99268 | + db = pParse->db; |
| 99269 | + pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); |
| 99270 | + if( pNew==0 ) return WRC_Abort; |
| 99271 | + memset(&dummy, 0, sizeof(dummy)); |
| 99272 | + pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0); |
| 99273 | + if( pNewSrc==0 ) return WRC_Abort; |
| 99274 | + *pNew = *p; |
| 99275 | + p->pSrc = pNewSrc; |
| 99276 | + p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ALL, 0)); |
| 99277 | + p->op = TK_SELECT; |
| 99278 | + p->pWhere = 0; |
| 99279 | + pNew->pGroupBy = 0; |
| 99280 | + pNew->pHaving = 0; |
| 99281 | + pNew->pOrderBy = 0; |
| 99282 | + p->pPrior = 0; |
| 99283 | + pNew->pLimit = 0; |
| 99284 | + pNew->pOffset = 0; |
| 99285 | + return WRC_Continue; |
| 99286 | +} |
| 99224 | 99287 | |
| 99225 | 99288 | /* |
| 99226 | 99289 | ** This routine is a Walker callback for "expanding" a SELECT statement. |
| 99227 | 99290 | ** "Expanding" means to do the following: |
| 99228 | 99291 | ** |
| | @@ -99536,13 +99599,15 @@ |
| 99536 | 99599 | ** and/or pParse->db->mallocFailed. |
| 99537 | 99600 | */ |
| 99538 | 99601 | static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ |
| 99539 | 99602 | Walker w; |
| 99540 | 99603 | memset(&w, 0, sizeof(w)); |
| 99541 | | - w.xSelectCallback = selectExpander; |
| 99604 | + w.xSelectCallback = convertCompoundSelectToSubquery; |
| 99542 | 99605 | w.xExprCallback = exprWalkNoop; |
| 99543 | 99606 | w.pParse = pParse; |
| 99607 | + sqlite3WalkSelect(&w, pSelect); |
| 99608 | + w.xSelectCallback = selectExpander; |
| 99544 | 99609 | sqlite3WalkSelect(&w, pSelect); |
| 99545 | 99610 | } |
| 99546 | 99611 | |
| 99547 | 99612 | |
| 99548 | 99613 | #ifndef SQLITE_OMIT_SUBQUERY |
| | @@ -102275,10 +102340,11 @@ |
| 102275 | 102340 | break; |
| 102276 | 102341 | } |
| 102277 | 102342 | } |
| 102278 | 102343 | if( j>=pTab->nCol ){ |
| 102279 | 102344 | if( sqlite3IsRowid(pChanges->a[i].zName) ){ |
| 102345 | + j = -1; |
| 102280 | 102346 | chngRowid = 1; |
| 102281 | 102347 | pRowidExpr = pChanges->a[i].pExpr; |
| 102282 | 102348 | }else{ |
| 102283 | 102349 | sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); |
| 102284 | 102350 | pParse->checkSchema = 1; |
| | @@ -102287,11 +102353,12 @@ |
| 102287 | 102353 | } |
| 102288 | 102354 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 102289 | 102355 | { |
| 102290 | 102356 | int rc; |
| 102291 | 102357 | rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, |
| 102292 | | - pTab->aCol[j].zName, db->aDb[iDb].zName); |
| 102358 | + j<0 ? "ROWID" : pTab->aCol[j].zName, |
| 102359 | + db->aDb[iDb].zName); |
| 102293 | 102360 | if( rc==SQLITE_DENY ){ |
| 102294 | 102361 | goto update_cleanup; |
| 102295 | 102362 | }else if( rc==SQLITE_IGNORE ){ |
| 102296 | 102363 | aXRef[j] = -1; |
| 102297 | 102364 | } |
| | @@ -119270,11 +119337,11 @@ |
| 119270 | 119337 | SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); |
| 119271 | 119338 | SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); |
| 119272 | 119339 | SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); |
| 119273 | 119340 | |
| 119274 | 119341 | /* fts3_tokenize_vtab.c */ |
| 119275 | | -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*); |
| 119342 | +SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *); |
| 119276 | 119343 | |
| 119277 | 119344 | /* fts3_unicode2.c (functions generated by parsing unicode text files) */ |
| 119278 | 119345 | #ifdef SQLITE_ENABLE_FTS4_UNICODE61 |
| 119279 | 119346 | SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int); |
| 119280 | 119347 | SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int); |
| | @@ -122584,13 +122651,10 @@ |
| 122584 | 122651 | #endif |
| 122585 | 122652 | |
| 122586 | 122653 | rc = sqlite3Fts3InitAux(db); |
| 122587 | 122654 | if( rc!=SQLITE_OK ) return rc; |
| 122588 | 122655 | |
| 122589 | | - rc = sqlite3Fts3InitTok(db); |
| 122590 | | - if( rc!=SQLITE_OK ) return rc; |
| 122591 | | - |
| 122592 | 122656 | sqlite3Fts3SimpleTokenizerModule(&pSimple); |
| 122593 | 122657 | sqlite3Fts3PorterTokenizerModule(&pPorter); |
| 122594 | 122658 | |
| 122595 | 122659 | /* Allocate and initialize the hash-table used to store tokenizers. */ |
| 122596 | 122660 | pHash = sqlite3_malloc(sizeof(Fts3Hash)); |
| | @@ -122640,12 +122704,16 @@ |
| 122640 | 122704 | if( rc==SQLITE_OK ){ |
| 122641 | 122705 | rc = sqlite3_create_module_v2( |
| 122642 | 122706 | db, "fts4", &fts3Module, (void *)pHash, 0 |
| 122643 | 122707 | ); |
| 122644 | 122708 | } |
| 122709 | + if( rc==SQLITE_OK ){ |
| 122710 | + rc = sqlite3Fts3InitTok(db, (void *)pHash); |
| 122711 | + } |
| 122645 | 122712 | return rc; |
| 122646 | 122713 | } |
| 122714 | + |
| 122647 | 122715 | |
| 122648 | 122716 | /* An error has occurred. Delete the hash table and return the error code. */ |
| 122649 | 122717 | assert( rc!=SQLITE_OK ); |
| 122650 | 122718 | if( pHash ){ |
| 122651 | 122719 | sqlite3Fts3HashClear(pHash); |
| | @@ -125710,10 +125778,11 @@ |
| 125710 | 125778 | if( apLeaf[i] ){ |
| 125711 | 125779 | if( p==0 ){ |
| 125712 | 125780 | p = apLeaf[i]; |
| 125713 | 125781 | p->pParent = 0; |
| 125714 | 125782 | }else{ |
| 125783 | + assert( pFree!=0 ); |
| 125715 | 125784 | pFree->pRight = p; |
| 125716 | 125785 | pFree->pLeft = apLeaf[i]; |
| 125717 | 125786 | pFree->pLeft->pParent = pFree; |
| 125718 | 125787 | pFree->pRight->pParent = pFree; |
| 125719 | 125788 | |
| | @@ -127945,32 +128014,26 @@ |
| 127945 | 128014 | |
| 127946 | 128015 | /* |
| 127947 | 128016 | ** Query FTS for the tokenizer implementation named zName. |
| 127948 | 128017 | */ |
| 127949 | 128018 | static int fts3tokQueryTokenizer( |
| 127950 | | - sqlite3 *db, |
| 128019 | + Fts3Hash *pHash, |
| 127951 | 128020 | const char *zName, |
| 127952 | | - const sqlite3_tokenizer_module **pp |
| 127953 | | -){ |
| 127954 | | - int rc; |
| 127955 | | - sqlite3_stmt *pStmt; |
| 127956 | | - const char *zSql = "SELECT fts3_tokenizer(?)"; |
| 127957 | | - |
| 127958 | | - *pp = 0; |
| 127959 | | - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
| 127960 | | - if( rc!=SQLITE_OK ){ |
| 127961 | | - return rc; |
| 127962 | | - } |
| 127963 | | - |
| 127964 | | - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); |
| 127965 | | - if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 127966 | | - if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ |
| 127967 | | - memcpy((void*)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); |
| 127968 | | - } |
| 127969 | | - } |
| 127970 | | - |
| 127971 | | - return sqlite3_finalize(pStmt); |
| 128021 | + const sqlite3_tokenizer_module **pp, |
| 128022 | + char **pzErr |
| 128023 | +){ |
| 128024 | + sqlite3_tokenizer_module *p; |
| 128025 | + int nName = (int)strlen(zName); |
| 128026 | + |
| 128027 | + p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); |
| 128028 | + if( !p ){ |
| 128029 | + *pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName); |
| 128030 | + return SQLITE_ERROR; |
| 128031 | + } |
| 128032 | + |
| 128033 | + *pp = p; |
| 128034 | + return SQLITE_OK; |
| 127972 | 128035 | } |
| 127973 | 128036 | |
| 127974 | 128037 | /* |
| 127975 | 128038 | ** The second argument, argv[], is an array of pointers to nul-terminated |
| 127976 | 128039 | ** strings. This function makes a copy of the array and strings into a |
| | @@ -128033,11 +128096,11 @@ |
| 128033 | 128096 | ** argv[2]: table name |
| 128034 | 128097 | ** argv[3]: first argument (tokenizer name) |
| 128035 | 128098 | */ |
| 128036 | 128099 | static int fts3tokConnectMethod( |
| 128037 | 128100 | sqlite3 *db, /* Database connection */ |
| 128038 | | - void *pUnused, /* Unused */ |
| 128101 | + void *pHash, /* Hash table of tokenizers */ |
| 128039 | 128102 | int argc, /* Number of elements in argv array */ |
| 128040 | 128103 | const char * const *argv, /* xCreate/xConnect argument array */ |
| 128041 | 128104 | sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ |
| 128042 | 128105 | char **pzErr /* OUT: sqlite3_malloc'd error message */ |
| 128043 | 128106 | ){ |
| | @@ -128045,11 +128108,10 @@ |
| 128045 | 128108 | const sqlite3_tokenizer_module *pMod = 0; |
| 128046 | 128109 | sqlite3_tokenizer *pTok = 0; |
| 128047 | 128110 | int rc; |
| 128048 | 128111 | char **azDequote = 0; |
| 128049 | 128112 | int nDequote; |
| 128050 | | - UNUSED_PARAMETER(pUnused); |
| 128051 | 128113 | |
| 128052 | 128114 | rc = sqlite3_declare_vtab(db, FTS3_TOK_SCHEMA); |
| 128053 | 128115 | if( rc!=SQLITE_OK ) return rc; |
| 128054 | 128116 | |
| 128055 | 128117 | nDequote = argc-3; |
| | @@ -128060,18 +128122,15 @@ |
| 128060 | 128122 | if( nDequote<1 ){ |
| 128061 | 128123 | zModule = "simple"; |
| 128062 | 128124 | }else{ |
| 128063 | 128125 | zModule = azDequote[0]; |
| 128064 | 128126 | } |
| 128065 | | - rc = fts3tokQueryTokenizer(db, zModule, &pMod); |
| 128127 | + rc = fts3tokQueryTokenizer((Fts3Hash*)pHash, zModule, &pMod, pzErr); |
| 128066 | 128128 | } |
| 128067 | 128129 | |
| 128068 | | - if( rc!=SQLITE_OK ){ |
| 128069 | | - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
| 128070 | | - }else if( pMod==0 ){ |
| 128071 | | - rc = SQLITE_ERROR; |
| 128072 | | - }else{ |
| 128130 | + assert( (rc==SQLITE_OK)==(pMod!=0) ); |
| 128131 | + if( rc==SQLITE_OK ){ |
| 128073 | 128132 | const char * const *azArg = (const char * const *)&azDequote[1]; |
| 128074 | 128133 | rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok); |
| 128075 | 128134 | } |
| 128076 | 128135 | |
| 128077 | 128136 | if( rc==SQLITE_OK ){ |
| | @@ -128299,11 +128358,11 @@ |
| 128299 | 128358 | |
| 128300 | 128359 | /* |
| 128301 | 128360 | ** Register the fts3tok module with database connection db. Return SQLITE_OK |
| 128302 | 128361 | ** if successful or an error code if sqlite3_create_module() fails. |
| 128303 | 128362 | */ |
| 128304 | | -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db){ |
| 128363 | +SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){ |
| 128305 | 128364 | static const sqlite3_module fts3tok_module = { |
| 128306 | 128365 | 0, /* iVersion */ |
| 128307 | 128366 | fts3tokConnectMethod, /* xCreate */ |
| 128308 | 128367 | fts3tokConnectMethod, /* xConnect */ |
| 128309 | 128368 | fts3tokBestIndexMethod, /* xBestIndex */ |
| | @@ -128327,11 +128386,11 @@ |
| 128327 | 128386 | 0, /* xRelease */ |
| 128328 | 128387 | 0 /* xRollbackTo */ |
| 128329 | 128388 | }; |
| 128330 | 128389 | int rc; /* Return code */ |
| 128331 | 128390 | |
| 128332 | | - rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, 0); |
| 128391 | + rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash); |
| 128333 | 128392 | return rc; |
| 128334 | 128393 | } |
| 128335 | 128394 | |
| 128336 | 128395 | #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ |
| 128337 | 128396 | |
| 128338 | 128397 | |