Fossil SCM
Update the built-in SQLite to the latest 3.8.12 beta.
Commit
1059aae93c2304153fc5391470b5985d93775693
Parent
5c9aecae2149c16…
2 files changed
+287
-161
+27
-2
+287
-161
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -325,11 +325,11 @@ | ||
| 325 | 325 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 326 | 326 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 327 | 327 | */ |
| 328 | 328 | #define SQLITE_VERSION "3.8.12" |
| 329 | 329 | #define SQLITE_VERSION_NUMBER 3008012 |
| 330 | -#define SQLITE_SOURCE_ID "2015-09-28 14:40:20 9d057f52217e7ef9c3f3eb84117abe3365503f44" | |
| 330 | +#define SQLITE_SOURCE_ID "2015-10-01 18:31:29 6f90839e91024e2006042f5eb7f21ca5b47a9b4a" | |
| 331 | 331 | |
| 332 | 332 | /* |
| 333 | 333 | ** CAPI3REF: Run-Time Library Version Numbers |
| 334 | 334 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 335 | 335 | ** |
| @@ -5845,18 +5845,36 @@ | ||
| 5845 | 5845 | ** indicates that the expense of the operation is similar to that of a |
| 5846 | 5846 | ** binary search on a unique indexed field of an SQLite table with N rows. |
| 5847 | 5847 | ** |
| 5848 | 5848 | ** ^The estimatedRows value is an estimate of the number of rows that |
| 5849 | 5849 | ** will be returned by the strategy. |
| 5850 | +** | |
| 5851 | +** The xBestIndex method may optionally populate the idxFlags field with a | |
| 5852 | +** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - | |
| 5853 | +** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite | |
| 5854 | +** assumes that the strategy may visit at most one row. | |
| 5855 | +** | |
| 5856 | +** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then | |
| 5857 | +** SQLite also assumes that if a call to the xUpdate() method is made as | |
| 5858 | +** part of the same statement to delete or update a virtual table row and the | |
| 5859 | +** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback | |
| 5860 | +** any database changes. In other words, if the xUpdate() returns | |
| 5861 | +** SQLITE_CONSTRAINT, the database contents must be exactly as they were | |
| 5862 | +** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not | |
| 5863 | +** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by | |
| 5864 | +** the xUpdate method are automatically rolled back by SQLite. | |
| 5850 | 5865 | ** |
| 5851 | 5866 | ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info |
| 5852 | 5867 | ** structure for SQLite version 3.8.2. If a virtual table extension is |
| 5853 | 5868 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5854 | 5869 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5855 | 5870 | ** to included crashing the application). The estimatedRows field should |
| 5856 | 5871 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5857 | -** value greater than or equal to 3008002. | |
| 5872 | +** value greater than or equal to 3008002. Similarly, the idxFlags field | |
| 5873 | +** was added for version 3.8.12. It may therefore only be used if | |
| 5874 | +** sqlite3_libversion_number() returns a value greater than or equal to | |
| 5875 | +** 3008012. | |
| 5858 | 5876 | */ |
| 5859 | 5877 | struct sqlite3_index_info { |
| 5860 | 5878 | /* Inputs */ |
| 5861 | 5879 | int nConstraint; /* Number of entries in aConstraint */ |
| 5862 | 5880 | struct sqlite3_index_constraint { |
| @@ -5880,12 +5898,19 @@ | ||
| 5880 | 5898 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5881 | 5899 | int orderByConsumed; /* True if output is already ordered */ |
| 5882 | 5900 | double estimatedCost; /* Estimated cost of using this index */ |
| 5883 | 5901 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5884 | 5902 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5903 | + /* Fields below are only available in SQLite 3.8.12 and later */ | |
| 5904 | + int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ | |
| 5885 | 5905 | }; |
| 5886 | 5906 | |
| 5907 | +/* | |
| 5908 | +** CAPI3REF: Virtual Table Scan Flags | |
| 5909 | +*/ | |
| 5910 | +#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ | |
| 5911 | + | |
| 5887 | 5912 | /* |
| 5888 | 5913 | ** CAPI3REF: Virtual Table Constraint Operator Codes |
| 5889 | 5914 | ** |
| 5890 | 5915 | ** These macros defined the allowed values for the |
| 5891 | 5916 | ** [sqlite3_index_info].aConstraint[].op field. Each value represents |
| @@ -11914,10 +11939,16 @@ | ||
| 11914 | 11939 | #define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY) |
| 11915 | 11940 | |
| 11916 | 11941 | /* Return true if index X is a UNIQUE index */ |
| 11917 | 11942 | #define IsUniqueIndex(X) ((X)->onError!=OE_None) |
| 11918 | 11943 | |
| 11944 | +/* The Index.aiColumn[] values are normally positive integer. But | |
| 11945 | +** there are some negative values that have special meaning: | |
| 11946 | +*/ | |
| 11947 | +#define XN_ROWID (-1) /* Indexed column is the rowid */ | |
| 11948 | +#define XN_EXPR (-2) /* Indexed column is an expression */ | |
| 11949 | + | |
| 11919 | 11950 | /* |
| 11920 | 11951 | ** Each sample stored in the sqlite_stat3 table is represented in memory |
| 11921 | 11952 | ** using a structure of this type. See documentation at the top of the |
| 11922 | 11953 | ** analyze.c source file for additional information. |
| 11923 | 11954 | */ |
| @@ -13501,19 +13532,21 @@ | ||
| 13501 | 13532 | SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); |
| 13502 | 13533 | SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); |
| 13503 | 13534 | SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); |
| 13504 | 13535 | SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); |
| 13505 | 13536 | # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) |
| 13537 | +# define sqlite3IsToplevel(p) ((p)->pToplevel==0) | |
| 13506 | 13538 | #else |
| 13507 | 13539 | # define sqlite3TriggersExist(B,C,D,E,F) 0 |
| 13508 | 13540 | # define sqlite3DeleteTrigger(A,B) |
| 13509 | 13541 | # define sqlite3DropTriggerPtr(A,B) |
| 13510 | 13542 | # define sqlite3UnlinkAndDeleteTrigger(A,B,C) |
| 13511 | 13543 | # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) |
| 13512 | 13544 | # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) |
| 13513 | 13545 | # define sqlite3TriggerList(X, Y) 0 |
| 13514 | 13546 | # define sqlite3ParseToplevel(p) p |
| 13547 | +# define sqlite3IsToplevel(p) 1 | |
| 13515 | 13548 | # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 |
| 13516 | 13549 | #endif |
| 13517 | 13550 | |
| 13518 | 13551 | SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); |
| 13519 | 13552 | SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); |
| @@ -54599,11 +54632,11 @@ | ||
| 54599 | 54632 | if( rc==SQLITE_OK ){ |
| 54600 | 54633 | btreeReleaseAllCursorPages(pCur); |
| 54601 | 54634 | pCur->eState = CURSOR_REQUIRESEEK; |
| 54602 | 54635 | } |
| 54603 | 54636 | |
| 54604 | - invalidateOverflowCache(pCur); | |
| 54637 | + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl|BTCF_AtLast); | |
| 54605 | 54638 | return rc; |
| 54606 | 54639 | } |
| 54607 | 54640 | |
| 54608 | 54641 | /* Forward reference */ |
| 54609 | 54642 | static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); |
| @@ -61562,11 +61595,11 @@ | ||
| 61562 | 61595 | ** It is critical that the child page be defragmented before being |
| 61563 | 61596 | ** copied into the parent, because if the parent is page 1 then it will |
| 61564 | 61597 | ** by smaller than the child due to the database header, and so all the |
| 61565 | 61598 | ** free space needs to be up front. |
| 61566 | 61599 | */ |
| 61567 | - assert( nNew==1 ); | |
| 61600 | + assert( nNew==1 || CORRUPT_DB ); | |
| 61568 | 61601 | rc = defragmentPage(apNew[0]); |
| 61569 | 61602 | testcase( rc!=SQLITE_OK ); |
| 61570 | 61603 | assert( apNew[0]->nFree == |
| 61571 | 61604 | (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) |
| 61572 | 61605 | || rc!=SQLITE_OK |
| @@ -79270,11 +79303,11 @@ | ||
| 79270 | 79303 | #endif |
| 79271 | 79304 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 79272 | 79305 | int j; |
| 79273 | 79306 | for(j=0; j<pIdx->nKeyCol; j++){ |
| 79274 | 79307 | /* FIXME: Be smarter about indexes that use expressions */ |
| 79275 | - if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==(-2) ){ | |
| 79308 | + if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){ | |
| 79276 | 79309 | zFault = "indexed"; |
| 79277 | 79310 | } |
| 79278 | 79311 | } |
| 79279 | 79312 | } |
| 79280 | 79313 | if( zFault ){ |
| @@ -86848,19 +86881,19 @@ | ||
| 86848 | 86881 | int iTabCur, /* Cursor pointing to a table row */ |
| 86849 | 86882 | int iIdxCol, /* The column of the index to be loaded */ |
| 86850 | 86883 | int regOut /* Store the index column value in this register */ |
| 86851 | 86884 | ){ |
| 86852 | 86885 | i16 iTabCol = pIdx->aiColumn[iIdxCol]; |
| 86853 | - if( iTabCol>=(-1) ){ | |
| 86886 | + if( iTabCol==XN_EXPR ){ | |
| 86887 | + assert( pIdx->aColExpr ); | |
| 86888 | + assert( pIdx->aColExpr->nExpr>iIdxCol ); | |
| 86889 | + pParse->iSelfTab = iTabCur; | |
| 86890 | + sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); | |
| 86891 | + }else{ | |
| 86854 | 86892 | sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur, |
| 86855 | 86893 | iTabCol, regOut); |
| 86856 | - return; | |
| 86857 | 86894 | } |
| 86858 | - assert( pIdx->aColExpr ); | |
| 86859 | - assert( pIdx->aColExpr->nExpr>iIdxCol ); | |
| 86860 | - pParse->iSelfTab = iTabCur; | |
| 86861 | - sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); | |
| 86862 | 86895 | } |
| 86863 | 86896 | |
| 86864 | 86897 | /* |
| 86865 | 86898 | ** Generate code to extract the value of the iCol-th column of a table. |
| 86866 | 86899 | */ |
| @@ -92379,10 +92412,12 @@ | ||
| 92379 | 92412 | DbMaskTest(pParse->writeMask,iDb), /* P2 */ |
| 92380 | 92413 | pParse->cookieValue[iDb], /* P3 */ |
| 92381 | 92414 | db->aDb[iDb].pSchema->iGeneration /* P4 */ |
| 92382 | 92415 | ); |
| 92383 | 92416 | if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); |
| 92417 | + VdbeComment((v, | |
| 92418 | + "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); | |
| 92384 | 92419 | } |
| 92385 | 92420 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 92386 | 92421 | for(i=0; i<pParse->nVtabLock; i++){ |
| 92387 | 92422 | char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); |
| 92388 | 92423 | sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); |
| @@ -95321,11 +95356,11 @@ | ||
| 95321 | 95356 | } |
| 95322 | 95357 | |
| 95323 | 95358 | /* Analyze the list of expressions that form the terms of the index and |
| 95324 | 95359 | ** report any errors. In the common case where the expression is exactly |
| 95325 | 95360 | ** a table column, store that column in aiColumn[]. For general expressions, |
| 95326 | - ** populate pIndex->aColExpr and store -2 in aiColumn[]. | |
| 95361 | + ** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[]. | |
| 95327 | 95362 | ** |
| 95328 | 95363 | ** TODO: Issue a warning if two or more columns of the index are identical. |
| 95329 | 95364 | ** TODO: Issue a warning if the table primary key is used as part of the |
| 95330 | 95365 | ** index key. |
| 95331 | 95366 | */ |
| @@ -95350,12 +95385,12 @@ | ||
| 95350 | 95385 | if( !db->mallocFailed ){ |
| 95351 | 95386 | assert( pCopy!=0 ); |
| 95352 | 95387 | pListItem = &pCopy->a[i]; |
| 95353 | 95388 | } |
| 95354 | 95389 | } |
| 95355 | - j = -2; | |
| 95356 | - pIndex->aiColumn[i] = -2; | |
| 95390 | + j = XN_EXPR; | |
| 95391 | + pIndex->aiColumn[i] = XN_EXPR; | |
| 95357 | 95392 | pIndex->uniqNotNull = 0; |
| 95358 | 95393 | }else{ |
| 95359 | 95394 | j = pCExpr->iColumn; |
| 95360 | 95395 | assert( j<=0x7fff ); |
| 95361 | 95396 | if( j<0 ){ |
| @@ -95404,11 +95439,11 @@ | ||
| 95404 | 95439 | i++; |
| 95405 | 95440 | } |
| 95406 | 95441 | } |
| 95407 | 95442 | assert( i==pIndex->nColumn ); |
| 95408 | 95443 | }else{ |
| 95409 | - pIndex->aiColumn[i] = -1; | |
| 95444 | + pIndex->aiColumn[i] = XN_ROWID; | |
| 95410 | 95445 | pIndex->azColl[i] = "BINARY"; |
| 95411 | 95446 | } |
| 95412 | 95447 | sqlite3DefaultRowEst(pIndex); |
| 95413 | 95448 | if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); |
| 95414 | 95449 | |
| @@ -97508,11 +97543,11 @@ | ||
| 97508 | 97543 | ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. |
| 97509 | 97544 | */ |
| 97510 | 97545 | pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); |
| 97511 | 97546 | if( pWInfo==0 ) goto delete_from_cleanup; |
| 97512 | 97547 | eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); |
| 97513 | - assert( IsVirtual(pTab)==0 || eOnePass==ONEPASS_OFF ); | |
| 97548 | + assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); | |
| 97514 | 97549 | assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); |
| 97515 | 97550 | |
| 97516 | 97551 | /* Keep track of the number of rows to be deleted */ |
| 97517 | 97552 | if( db->flags & SQLITE_CountRows ){ |
| 97518 | 97553 | sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); |
| @@ -97519,11 +97554,11 @@ | ||
| 97519 | 97554 | } |
| 97520 | 97555 | |
| 97521 | 97556 | /* Extract the rowid or primary key for the current row */ |
| 97522 | 97557 | if( pPk ){ |
| 97523 | 97558 | for(i=0; i<nPk; i++){ |
| 97524 | - assert( pPk->aiColumn[i]>=(-1) ); | |
| 97559 | + assert( pPk->aiColumn[i]>=0 ); | |
| 97525 | 97560 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, |
| 97526 | 97561 | pPk->aiColumn[i], iPk+i); |
| 97527 | 97562 | } |
| 97528 | 97563 | iKey = iPk; |
| 97529 | 97564 | }else{ |
| @@ -97591,11 +97626,11 @@ | ||
| 97591 | 97626 | /* Set up a loop over the rowids/primary-keys that were found in the |
| 97592 | 97627 | ** where-clause loop above. |
| 97593 | 97628 | */ |
| 97594 | 97629 | if( eOnePass!=ONEPASS_OFF ){ |
| 97595 | 97630 | assert( nKey==nPk ); /* OP_Found will use an unpacked key */ |
| 97596 | - if( aToOpen[iDataCur-iTabCur] ){ | |
| 97631 | + if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ | |
| 97597 | 97632 | assert( pPk!=0 || pTab->pSelect!=0 ); |
| 97598 | 97633 | sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); |
| 97599 | 97634 | VdbeCoverage(v); |
| 97600 | 97635 | } |
| 97601 | 97636 | }else if( pPk ){ |
| @@ -97613,11 +97648,15 @@ | ||
| 97613 | 97648 | if( IsVirtual(pTab) ){ |
| 97614 | 97649 | const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); |
| 97615 | 97650 | sqlite3VtabMakeWritable(pParse, pTab); |
| 97616 | 97651 | sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); |
| 97617 | 97652 | sqlite3VdbeChangeP5(v, OE_Abort); |
| 97653 | + assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); | |
| 97618 | 97654 | sqlite3MayAbort(pParse); |
| 97655 | + if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ | |
| 97656 | + pParse->isMultiWrite = 0; | |
| 97657 | + } | |
| 97619 | 97658 | }else |
| 97620 | 97659 | #endif |
| 97621 | 97660 | { |
| 97622 | 97661 | int count = (pParse->nested==0); /* True to count changes */ |
| 97623 | 97662 | int iIdxNoSeek = -1; |
| @@ -97951,11 +97990,11 @@ | ||
| 97951 | 97990 | regBase = sqlite3GetTempRange(pParse, nCol); |
| 97952 | 97991 | if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0; |
| 97953 | 97992 | for(j=0; j<nCol; j++){ |
| 97954 | 97993 | if( pPrior |
| 97955 | 97994 | && pPrior->aiColumn[j]==pIdx->aiColumn[j] |
| 97956 | - && pPrior->aiColumn[j]>=(-1) | |
| 97995 | + && pPrior->aiColumn[j]!=XN_EXPR | |
| 97957 | 97996 | ){ |
| 97958 | 97997 | /* This column was already computed by the previous index */ |
| 97959 | 97998 | continue; |
| 97960 | 97999 | } |
| 97961 | 98000 | sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); |
| @@ -100039,10 +100078,12 @@ | ||
| 100039 | 100078 | for(i=0; i<nCol; i++){ |
| 100040 | 100079 | i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */ |
| 100041 | 100080 | char *zDfltColl; /* Def. collation for column */ |
| 100042 | 100081 | char *zIdxCol; /* Name of indexed column */ |
| 100043 | 100082 | |
| 100083 | + if( iCol<0 ) break; /* No foreign keys against expression indexes */ | |
| 100084 | + | |
| 100044 | 100085 | /* If the index uses a collation sequence that is different from |
| 100045 | 100086 | ** the default collation sequence for the column, this index is |
| 100046 | 100087 | ** unusable. Bail out early in this case. */ |
| 100047 | 100088 | zDfltColl = pParent->aCol[iCol].zColl; |
| 100048 | 100089 | if( !zDfltColl ){ |
| @@ -100191,10 +100232,11 @@ | ||
| 100191 | 100232 | if( pTab==pFKey->pFrom && nIncr==1 ){ |
| 100192 | 100233 | int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; |
| 100193 | 100234 | for(i=0; i<nCol; i++){ |
| 100194 | 100235 | int iChild = aiCol[i]+1+regData; |
| 100195 | 100236 | int iParent = pIdx->aiColumn[i]+1+regData; |
| 100237 | + assert( pIdx->aiColumn[i]>=0 ); | |
| 100196 | 100238 | assert( aiCol[i]!=pTab->iPKey ); |
| 100197 | 100239 | if( pIdx->aiColumn[i]==pTab->iPKey ){ |
| 100198 | 100240 | /* The parent key is a composite key that includes the IPK column */ |
| 100199 | 100241 | iParent = regData; |
| 100200 | 100242 | } |
| @@ -100399,10 +100441,11 @@ | ||
| 100399 | 100441 | Expr *pEq, *pAll = 0; |
| 100400 | 100442 | Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 100401 | 100443 | assert( pIdx!=0 ); |
| 100402 | 100444 | for(i=0; i<pPk->nKeyCol; i++){ |
| 100403 | 100445 | i16 iCol = pIdx->aiColumn[i]; |
| 100446 | + assert( iCol>=0 ); | |
| 100404 | 100447 | pLeft = exprTableRegister(pParse, pTab, regData, iCol); |
| 100405 | 100448 | pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); |
| 100406 | 100449 | pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); |
| 100407 | 100450 | pAll = sqlite3ExprAnd(db, pAll, pEq); |
| 100408 | 100451 | } |
| @@ -100718,10 +100761,11 @@ | ||
| 100718 | 100761 | } |
| 100719 | 100762 | for(i=0; i<pFKey->nCol; i++){ |
| 100720 | 100763 | if( aiCol[i]==pTab->iPKey ){ |
| 100721 | 100764 | aiCol[i] = -1; |
| 100722 | 100765 | } |
| 100766 | + assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); | |
| 100723 | 100767 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 100724 | 100768 | /* Request permission to read the parent key columns. If the |
| 100725 | 100769 | ** authorization callback returns SQLITE_IGNORE, behave as if any |
| 100726 | 100770 | ** values read from the parent table are NULL. */ |
| 100727 | 100771 | if( db->xAuth ){ |
| @@ -100849,11 +100893,14 @@ | ||
| 100849 | 100893 | } |
| 100850 | 100894 | for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 100851 | 100895 | Index *pIdx = 0; |
| 100852 | 100896 | sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); |
| 100853 | 100897 | if( pIdx ){ |
| 100854 | - for(i=0; i<pIdx->nKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); | |
| 100898 | + for(i=0; i<pIdx->nKeyCol; i++){ | |
| 100899 | + assert( pIdx->aiColumn[i]>=0 ); | |
| 100900 | + mask |= COLUMN_MASK(pIdx->aiColumn[i]); | |
| 100901 | + } | |
| 100855 | 100902 | } |
| 100856 | 100903 | } |
| 100857 | 100904 | } |
| 100858 | 100905 | return mask; |
| 100859 | 100906 | } |
| @@ -100972,10 +101019,11 @@ | ||
| 100972 | 101019 | Expr *pEq; /* tFromCol = OLD.tToCol */ |
| 100973 | 101020 | |
| 100974 | 101021 | iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
| 100975 | 101022 | assert( iFromCol>=0 ); |
| 100976 | 101023 | assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); |
| 101024 | + assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); | |
| 100977 | 101025 | tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; |
| 100978 | 101026 | tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; |
| 100979 | 101027 | |
| 100980 | 101028 | tToCol.n = sqlite3Strlen30(tToCol.z); |
| 100981 | 101029 | tFromCol.n = sqlite3Strlen30(tFromCol.z); |
| @@ -101281,15 +101329,15 @@ | ||
| 101281 | 101329 | } |
| 101282 | 101330 | for(n=0; n<pIdx->nColumn; n++){ |
| 101283 | 101331 | i16 x = pIdx->aiColumn[n]; |
| 101284 | 101332 | if( x>=0 ){ |
| 101285 | 101333 | pIdx->zColAff[n] = pTab->aCol[x].affinity; |
| 101286 | - }else if( x==(-1) ){ | |
| 101334 | + }else if( x==XN_ROWID ){ | |
| 101287 | 101335 | pIdx->zColAff[n] = SQLITE_AFF_INTEGER; |
| 101288 | 101336 | }else{ |
| 101289 | 101337 | char aff; |
| 101290 | - assert( x==(-2) ); | |
| 101338 | + assert( x==XN_EXPR ); | |
| 101291 | 101339 | assert( pIdx->aColExpr!=0 ); |
| 101292 | 101340 | aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); |
| 101293 | 101341 | if( aff==0 ) aff = SQLITE_AFF_BLOB; |
| 101294 | 101342 | pIdx->zColAff[n] = aff; |
| 101295 | 101343 | } |
| @@ -101451,11 +101499,11 @@ | ||
| 101451 | 101499 | Vdbe *v = pParse->pVdbe; /* VDBE under construction */ |
| 101452 | 101500 | |
| 101453 | 101501 | /* This routine is never called during trigger-generation. It is |
| 101454 | 101502 | ** only called from the top-level */ |
| 101455 | 101503 | assert( pParse->pTriggerTab==0 ); |
| 101456 | - assert( pParse==sqlite3ParseToplevel(pParse) ); | |
| 101504 | + assert( sqlite3IsToplevel(pParse) ); | |
| 101457 | 101505 | |
| 101458 | 101506 | assert( v ); /* We failed long ago if this is not so */ |
| 101459 | 101507 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 101460 | 101508 | pDb = &db->aDb[p->iDb]; |
| 101461 | 101509 | memId = p->regCtr; |
| @@ -102599,17 +102647,17 @@ | ||
| 102599 | 102647 | */ |
| 102600 | 102648 | regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn); |
| 102601 | 102649 | for(i=0; i<pIdx->nColumn; i++){ |
| 102602 | 102650 | int iField = pIdx->aiColumn[i]; |
| 102603 | 102651 | int x; |
| 102604 | - if( iField==(-2) ){ | |
| 102652 | + if( iField==XN_EXPR ){ | |
| 102605 | 102653 | pParse->ckBase = regNewData+1; |
| 102606 | 102654 | sqlite3ExprCode(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); |
| 102607 | 102655 | pParse->ckBase = 0; |
| 102608 | 102656 | VdbeComment((v, "%s column %d", pIdx->zName, i)); |
| 102609 | 102657 | }else{ |
| 102610 | - if( iField==(-1) || iField==pTab->iPKey ){ | |
| 102658 | + if( iField==XN_ROWID || iField==pTab->iPKey ){ | |
| 102611 | 102659 | if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */ |
| 102612 | 102660 | x = regNewData; |
| 102613 | 102661 | regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i; |
| 102614 | 102662 | }else{ |
| 102615 | 102663 | x = iField + regNewData + 1; |
| @@ -102664,10 +102712,11 @@ | ||
| 102664 | 102712 | int x; |
| 102665 | 102713 | /* Extract the PRIMARY KEY from the end of the index entry and |
| 102666 | 102714 | ** store it in registers regR..regR+nPk-1 */ |
| 102667 | 102715 | if( pIdx!=pPk ){ |
| 102668 | 102716 | for(i=0; i<pPk->nKeyCol; i++){ |
| 102717 | + assert( pPk->aiColumn[i]>=0 ); | |
| 102669 | 102718 | x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); |
| 102670 | 102719 | sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); |
| 102671 | 102720 | VdbeComment((v, "%s.%s", pTab->zName, |
| 102672 | 102721 | pTab->aCol[pPk->aiColumn[i]].zName)); |
| 102673 | 102722 | } |
| @@ -102685,10 +102734,11 @@ | ||
| 102685 | 102734 | int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR); |
| 102686 | 102735 | |
| 102687 | 102736 | for(i=0; i<pPk->nKeyCol; i++){ |
| 102688 | 102737 | char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); |
| 102689 | 102738 | x = pPk->aiColumn[i]; |
| 102739 | + assert( x>=0 ); | |
| 102690 | 102740 | if( i==(pPk->nKeyCol-1) ){ |
| 102691 | 102741 | addrJump = addrUniqueOk; |
| 102692 | 102742 | op = OP_Eq; |
| 102693 | 102743 | } |
| 102694 | 102744 | sqlite3VdbeAddOp4(v, op, |
| @@ -102936,11 +102986,11 @@ | ||
| 102936 | 102986 | } |
| 102937 | 102987 | for(i=0; i<pSrc->nKeyCol; i++){ |
| 102938 | 102988 | if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ |
| 102939 | 102989 | return 0; /* Different columns indexed */ |
| 102940 | 102990 | } |
| 102941 | - if( pSrc->aiColumn[i]==(-2) ){ | |
| 102991 | + if( pSrc->aiColumn[i]==XN_EXPR ){ | |
| 102942 | 102992 | assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 ); |
| 102943 | 102993 | if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr, |
| 102944 | 102994 | pDest->aColExpr->a[i].pExpr, -1)!=0 ){ |
| 102945 | 102995 | return 0; /* Different expressions in the index */ |
| 102946 | 102996 | } |
| @@ -106741,11 +106791,11 @@ | ||
| 106741 | 106791 | int uniqOk = sqlite3VdbeMakeLabel(v); |
| 106742 | 106792 | int jmp6; |
| 106743 | 106793 | int kk; |
| 106744 | 106794 | for(kk=0; kk<pIdx->nKeyCol; kk++){ |
| 106745 | 106795 | int iCol = pIdx->aiColumn[kk]; |
| 106746 | - assert( iCol!=(-1) && iCol<pTab->nCol ); | |
| 106796 | + assert( iCol!=XN_ROWID && iCol<pTab->nCol ); | |
| 106747 | 106797 | if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; |
| 106748 | 106798 | sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); |
| 106749 | 106799 | VdbeCoverage(v); |
| 106750 | 106800 | } |
| 106751 | 106801 | jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); |
| @@ -112261,21 +112311,13 @@ | ||
| 112261 | 112311 | ** an entry of the FROM clause is a subquery instead of a table or view, |
| 112262 | 112312 | ** then create a transient table structure to describe the subquery. |
| 112263 | 112313 | */ |
| 112264 | 112314 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 112265 | 112315 | Table *pTab; |
| 112266 | - assert( pFrom->fg.isRecursive==0 || pFrom->pTab ); | |
| 112316 | + assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 ); | |
| 112267 | 112317 | if( pFrom->fg.isRecursive ) continue; |
| 112268 | - if( pFrom->pTab!=0 ){ | |
| 112269 | - /* This statement has already been prepared. There is no need | |
| 112270 | - ** to go further. */ | |
| 112271 | - assert( i==0 ); | |
| 112272 | -#ifndef SQLITE_OMIT_CTE | |
| 112273 | - selectPopWith(pWalker, p); | |
| 112274 | -#endif | |
| 112275 | - return WRC_Prune; | |
| 112276 | - } | |
| 112318 | + assert( pFrom->pTab==0 ); | |
| 112277 | 112319 | #ifndef SQLITE_OMIT_CTE |
| 112278 | 112320 | if( withExpand(pWalker, pFrom) ) return WRC_Abort; |
| 112279 | 112321 | if( pFrom->pTab ) {} else |
| 112280 | 112322 | #endif |
| 112281 | 112323 | if( pFrom->zName==0 ){ |
| @@ -112563,23 +112605,23 @@ | ||
| 112563 | 112605 | int i; |
| 112564 | 112606 | SrcList *pTabList; |
| 112565 | 112607 | struct SrcList_item *pFrom; |
| 112566 | 112608 | |
| 112567 | 112609 | assert( p->selFlags & SF_Resolved ); |
| 112568 | - if( (p->selFlags & SF_HasTypeInfo)==0 ){ | |
| 112569 | - p->selFlags |= SF_HasTypeInfo; | |
| 112570 | - pParse = pWalker->pParse; | |
| 112571 | - pTabList = p->pSrc; | |
| 112572 | - for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ | |
| 112573 | - Table *pTab = pFrom->pTab; | |
| 112574 | - if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ | |
| 112575 | - /* A sub-query in the FROM clause of a SELECT */ | |
| 112576 | - Select *pSel = pFrom->pSelect; | |
| 112577 | - if( pSel ){ | |
| 112578 | - while( pSel->pPrior ) pSel = pSel->pPrior; | |
| 112579 | - selectAddColumnTypeAndCollation(pParse, pTab, pSel); | |
| 112580 | - } | |
| 112610 | + assert( (p->selFlags & SF_HasTypeInfo)==0 ); | |
| 112611 | + p->selFlags |= SF_HasTypeInfo; | |
| 112612 | + pParse = pWalker->pParse; | |
| 112613 | + pTabList = p->pSrc; | |
| 112614 | + for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ | |
| 112615 | + Table *pTab = pFrom->pTab; | |
| 112616 | + assert( pTab!=0 ); | |
| 112617 | + if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ | |
| 112618 | + /* A sub-query in the FROM clause of a SELECT */ | |
| 112619 | + Select *pSel = pFrom->pSelect; | |
| 112620 | + if( pSel ){ | |
| 112621 | + while( pSel->pPrior ) pSel = pSel->pPrior; | |
| 112622 | + selectAddColumnTypeAndCollation(pParse, pTab, pSel); | |
| 112581 | 112623 | } |
| 112582 | 112624 | } |
| 112583 | 112625 | } |
| 112584 | 112626 | } |
| 112585 | 112627 | #endif |
| @@ -115133,13 +115175,13 @@ | ||
| 115133 | 115175 | int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */ |
| 115134 | 115176 | int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ |
| 115135 | 115177 | |
| 115136 | 115178 | /* Register Allocations */ |
| 115137 | 115179 | int regRowCount = 0; /* A count of rows changed */ |
| 115138 | - int regOldRowid; /* The old rowid */ | |
| 115139 | - int regNewRowid; /* The new rowid */ | |
| 115140 | - int regNew; /* Content of the NEW.* table in triggers */ | |
| 115180 | + int regOldRowid = 0; /* The old rowid */ | |
| 115181 | + int regNewRowid = 0; /* The new rowid */ | |
| 115182 | + int regNew = 0; /* Content of the NEW.* table in triggers */ | |
| 115141 | 115183 | int regOld = 0; /* Content of OLD.* table in triggers */ |
| 115142 | 115184 | int regRowSet = 0; /* Rowset of rows to be updated */ |
| 115143 | 115185 | int regKey = 0; /* composite PRIMARY KEY value */ |
| 115144 | 115186 | |
| 115145 | 115187 | memset(&sContext, 0, sizeof(sContext)); |
| @@ -115299,33 +115341,24 @@ | ||
| 115299 | 115341 | v = sqlite3GetVdbe(pParse); |
| 115300 | 115342 | if( v==0 ) goto update_cleanup; |
| 115301 | 115343 | if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); |
| 115302 | 115344 | sqlite3BeginWriteOperation(pParse, 1, iDb); |
| 115303 | 115345 | |
| 115304 | -#ifndef SQLITE_OMIT_VIRTUALTABLE | |
| 115305 | - /* Virtual tables must be handled separately */ | |
| 115306 | - if( IsVirtual(pTab) ){ | |
| 115307 | - updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, | |
| 115308 | - pWhere, onError); | |
| 115309 | - pWhere = 0; | |
| 115310 | - pTabList = 0; | |
| 115311 | - goto update_cleanup; | |
| 115312 | - } | |
| 115313 | -#endif | |
| 115314 | - | |
| 115315 | - /* Allocate required registers. */ | |
| 115316 | - regRowSet = ++pParse->nMem; | |
| 115317 | - regOldRowid = regNewRowid = ++pParse->nMem; | |
| 115318 | - if( chngPk || pTrigger || hasFK ){ | |
| 115319 | - regOld = pParse->nMem + 1; | |
| 115320 | - pParse->nMem += pTab->nCol; | |
| 115321 | - } | |
| 115322 | - if( chngKey || pTrigger || hasFK ){ | |
| 115323 | - regNewRowid = ++pParse->nMem; | |
| 115324 | - } | |
| 115325 | - regNew = pParse->nMem + 1; | |
| 115326 | - pParse->nMem += pTab->nCol; | |
| 115346 | + /* Allocate required registers. */ | |
| 115347 | + if( !IsVirtual(pTab) ){ | |
| 115348 | + regRowSet = ++pParse->nMem; | |
| 115349 | + regOldRowid = regNewRowid = ++pParse->nMem; | |
| 115350 | + if( chngPk || pTrigger || hasFK ){ | |
| 115351 | + regOld = pParse->nMem + 1; | |
| 115352 | + pParse->nMem += pTab->nCol; | |
| 115353 | + } | |
| 115354 | + if( chngKey || pTrigger || hasFK ){ | |
| 115355 | + regNewRowid = ++pParse->nMem; | |
| 115356 | + } | |
| 115357 | + regNew = pParse->nMem + 1; | |
| 115358 | + pParse->nMem += pTab->nCol; | |
| 115359 | + } | |
| 115327 | 115360 | |
| 115328 | 115361 | /* Start the view context. */ |
| 115329 | 115362 | if( isView ){ |
| 115330 | 115363 | sqlite3AuthContextPush(pParse, &sContext, pTab->zName); |
| 115331 | 115364 | } |
| @@ -115343,10 +115376,19 @@ | ||
| 115343 | 115376 | ** WHERE clause. |
| 115344 | 115377 | */ |
| 115345 | 115378 | if( sqlite3ResolveExprNames(&sNC, pWhere) ){ |
| 115346 | 115379 | goto update_cleanup; |
| 115347 | 115380 | } |
| 115381 | + | |
| 115382 | +#ifndef SQLITE_OMIT_VIRTUALTABLE | |
| 115383 | + /* Virtual tables must be handled separately */ | |
| 115384 | + if( IsVirtual(pTab) ){ | |
| 115385 | + updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, | |
| 115386 | + pWhere, onError); | |
| 115387 | + goto update_cleanup; | |
| 115388 | + } | |
| 115389 | +#endif | |
| 115348 | 115390 | |
| 115349 | 115391 | /* Begin the database scan |
| 115350 | 115392 | */ |
| 115351 | 115393 | if( HasRowid(pTab) ){ |
| 115352 | 115394 | sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); |
| @@ -115383,11 +115425,11 @@ | ||
| 115383 | 115425 | pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, |
| 115384 | 115426 | WHERE_ONEPASS_DESIRED, iIdxCur); |
| 115385 | 115427 | if( pWInfo==0 ) goto update_cleanup; |
| 115386 | 115428 | okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); |
| 115387 | 115429 | for(i=0; i<nPk; i++){ |
| 115388 | - assert( pPk->aiColumn[i]>=(-1) ); | |
| 115430 | + assert( pPk->aiColumn[i]>=0 ); | |
| 115389 | 115431 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i], |
| 115390 | 115432 | iPk+i); |
| 115391 | 115433 | } |
| 115392 | 115434 | if( okOnePass ){ |
| 115393 | 115435 | sqlite3VdbeChangeToNoop(v, addrOpen); |
| @@ -115506,11 +115548,10 @@ | ||
| 115506 | 115548 | ** be used eliminates some redundant opcodes. |
| 115507 | 115549 | */ |
| 115508 | 115550 | newmask = sqlite3TriggerColmask( |
| 115509 | 115551 | pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError |
| 115510 | 115552 | ); |
| 115511 | - /*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/ | |
| 115512 | 115553 | for(i=0; i<pTab->nCol; i++){ |
| 115513 | 115554 | if( i==pTab->iPKey ){ |
| 115514 | 115555 | sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); |
| 115515 | 115556 | }else{ |
| 115516 | 115557 | j = aXRef[i]; |
| @@ -115684,25 +115725,27 @@ | ||
| 115684 | 115725 | |
| 115685 | 115726 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 115686 | 115727 | /* |
| 115687 | 115728 | ** Generate code for an UPDATE of a virtual table. |
| 115688 | 115729 | ** |
| 115689 | -** The strategy is that we create an ephemeral table that contains | |
| 115730 | +** There are two possible strategies - the default and the special | |
| 115731 | +** "onepass" strategy. Onepass is only used if the virtual table | |
| 115732 | +** implementation indicates that pWhere may match at most one row. | |
| 115733 | +** | |
| 115734 | +** The default strategy is to create an ephemeral table that contains | |
| 115690 | 115735 | ** for each row to be changed: |
| 115691 | 115736 | ** |
| 115692 | 115737 | ** (A) The original rowid of that row. |
| 115693 | -** (B) The revised rowid for the row. (note1) | |
| 115738 | +** (B) The revised rowid for the row. | |
| 115694 | 115739 | ** (C) The content of every column in the row. |
| 115695 | 115740 | ** |
| 115696 | -** Then we loop over this ephemeral table and for each row in | |
| 115697 | -** the ephemeral table call VUpdate. | |
| 115698 | -** | |
| 115699 | -** When finished, drop the ephemeral table. | |
| 115700 | -** | |
| 115701 | -** (note1) Actually, if we know in advance that (A) is always the same | |
| 115702 | -** as (B) we only store (A), then duplicate (A) when pulling | |
| 115703 | -** it out of the ephemeral table before calling VUpdate. | |
| 115741 | +** Then loop through the contents of this ephemeral table executing a | |
| 115742 | +** VUpdate for each row. When finished, drop the ephemeral table. | |
| 115743 | +** | |
| 115744 | +** The "onepass" strategy does not use an ephemeral table. Instead, it | |
| 115745 | +** stores the same values (A, B and C above) in a register array and | |
| 115746 | +** makes a single invocation of VUpdate. | |
| 115704 | 115747 | */ |
| 115705 | 115748 | static void updateVirtualTable( |
| 115706 | 115749 | Parse *pParse, /* The parsing context */ |
| 115707 | 115750 | SrcList *pSrc, /* The virtual table to be modified */ |
| 115708 | 115751 | Table *pTab, /* The virtual table */ |
| @@ -115711,70 +115754,100 @@ | ||
| 115711 | 115754 | int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ |
| 115712 | 115755 | Expr *pWhere, /* WHERE clause of the UPDATE statement */ |
| 115713 | 115756 | int onError /* ON CONFLICT strategy */ |
| 115714 | 115757 | ){ |
| 115715 | 115758 | Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ |
| 115716 | - ExprList *pEList = 0; /* The result set of the SELECT statement */ | |
| 115717 | - Select *pSelect = 0; /* The SELECT statement */ | |
| 115718 | - Expr *pExpr; /* Temporary expression */ | |
| 115719 | 115759 | int ephemTab; /* Table holding the result of the SELECT */ |
| 115720 | 115760 | int i; /* Loop counter */ |
| 115721 | - int addr; /* Address of top of loop */ | |
| 115722 | - int iReg; /* First register in set passed to OP_VUpdate */ | |
| 115723 | 115761 | sqlite3 *db = pParse->db; /* Database connection */ |
| 115724 | 115762 | const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); |
| 115725 | - SelectDest dest; | |
| 115726 | - | |
| 115727 | - /* Construct the SELECT statement that will find the new values for | |
| 115728 | - ** all updated rows. | |
| 115729 | - */ | |
| 115730 | - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_")); | |
| 115731 | - if( pRowid ){ | |
| 115732 | - pEList = sqlite3ExprListAppend(pParse, pEList, | |
| 115733 | - sqlite3ExprDup(db, pRowid, 0)); | |
| 115734 | - } | |
| 115735 | - assert( pTab->iPKey<0 ); | |
| 115736 | - for(i=0; i<pTab->nCol; i++){ | |
| 115737 | - if( aXRef[i]>=0 ){ | |
| 115738 | - pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0); | |
| 115739 | - }else{ | |
| 115740 | - pExpr = sqlite3Expr(db, TK_ID, pTab->aCol[i].zName); | |
| 115741 | - } | |
| 115742 | - pEList = sqlite3ExprListAppend(pParse, pEList, pExpr); | |
| 115743 | - } | |
| 115744 | - pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); | |
| 115745 | - | |
| 115746 | - /* Create the ephemeral table into which the update results will | |
| 115747 | - ** be stored. | |
| 115748 | - */ | |
| 115763 | + WhereInfo *pWInfo; | |
| 115764 | + int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */ | |
| 115765 | + int regArg; /* First register in VUpdate arg array */ | |
| 115766 | + int regRec; /* Register in which to assemble record */ | |
| 115767 | + int regRowid; /* Register for ephem table rowid */ | |
| 115768 | + int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ | |
| 115769 | + int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ | |
| 115770 | + int bOnePass; /* True to use onepass strategy */ | |
| 115771 | + int addr; /* Address of OP_OpenEphemeral */ | |
| 115772 | + | |
| 115773 | + /* Allocate nArg registers to martial the arguments to VUpdate. Then | |
| 115774 | + ** create and open the ephemeral table in which the records created from | |
| 115775 | + ** these arguments will be temporarily stored. */ | |
| 115749 | 115776 | assert( v ); |
| 115750 | 115777 | ephemTab = pParse->nTab++; |
| 115751 | - | |
| 115752 | - /* fill the ephemeral table | |
| 115753 | - */ | |
| 115754 | - sqlite3SelectDestInit(&dest, SRT_EphemTab, ephemTab); | |
| 115755 | - sqlite3Select(pParse, pSelect, &dest); | |
| 115756 | - | |
| 115757 | - /* Generate code to scan the ephemeral table and call VUpdate. */ | |
| 115758 | - iReg = ++pParse->nMem; | |
| 115759 | - pParse->nMem += pTab->nCol+1; | |
| 115760 | - addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); | |
| 115761 | - sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); | |
| 115762 | - sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); | |
| 115778 | + addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg); | |
| 115779 | + regArg = pParse->nMem + 1; | |
| 115780 | + pParse->nMem += nArg; | |
| 115781 | + regRec = ++pParse->nMem; | |
| 115782 | + regRowid = ++pParse->nMem; | |
| 115783 | + | |
| 115784 | + /* Start scanning the virtual table */ | |
| 115785 | + pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0); | |
| 115786 | + if( pWInfo==0 ) return; | |
| 115787 | + | |
| 115788 | + /* Populate the argument registers. */ | |
| 115789 | + sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); | |
| 115790 | + if( pRowid ){ | |
| 115791 | + sqlite3ExprCode(pParse, pRowid, regArg+1); | |
| 115792 | + }else{ | |
| 115793 | + sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); | |
| 115794 | + } | |
| 115763 | 115795 | for(i=0; i<pTab->nCol; i++){ |
| 115764 | - sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i); | |
| 115796 | + if( aXRef[i]>=0 ){ | |
| 115797 | + sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); | |
| 115798 | + }else{ | |
| 115799 | + sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); | |
| 115800 | + } | |
| 115801 | + } | |
| 115802 | + | |
| 115803 | + bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); | |
| 115804 | + | |
| 115805 | + if( bOnePass ){ | |
| 115806 | + /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded | |
| 115807 | + ** above. Also, if this is a top-level parse (not a trigger), clear the | |
| 115808 | + ** multi-write flag so that the VM does not open a statement journal */ | |
| 115809 | + sqlite3VdbeChangeToNoop(v, addr); | |
| 115810 | + if( sqlite3IsToplevel(pParse) ){ | |
| 115811 | + pParse->isMultiWrite = 0; | |
| 115812 | + } | |
| 115813 | + }else{ | |
| 115814 | + /* Create a record from the argument register contents and insert it into | |
| 115815 | + ** the ephemeral table. */ | |
| 115816 | + sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); | |
| 115817 | + sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); | |
| 115818 | + sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); | |
| 115819 | + } | |
| 115820 | + | |
| 115821 | + | |
| 115822 | + if( bOnePass==0 ){ | |
| 115823 | + /* End the virtual table scan */ | |
| 115824 | + sqlite3WhereEnd(pWInfo); | |
| 115825 | + | |
| 115826 | + /* Begin scannning through the ephemeral table. */ | |
| 115827 | + addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v); | |
| 115828 | + | |
| 115829 | + /* Extract arguments from the current row of the ephemeral table and | |
| 115830 | + ** invoke the VUpdate method. */ | |
| 115831 | + for(i=0; i<nArg; i++){ | |
| 115832 | + sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i); | |
| 115833 | + } | |
| 115765 | 115834 | } |
| 115766 | 115835 | sqlite3VtabMakeWritable(pParse, pTab); |
| 115767 | - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB); | |
| 115836 | + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB); | |
| 115768 | 115837 | sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); |
| 115769 | 115838 | sqlite3MayAbort(pParse); |
| 115770 | - sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); | |
| 115771 | - sqlite3VdbeJumpHere(v, addr); | |
| 115772 | - sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); | |
| 115773 | 115839 | |
| 115774 | - /* Cleanup */ | |
| 115775 | - sqlite3SelectDelete(db, pSelect); | |
| 115840 | + /* End of the ephemeral table scan. Or, if using the onepass strategy, | |
| 115841 | + ** jump to here if the scan visited zero rows. */ | |
| 115842 | + if( bOnePass==0 ){ | |
| 115843 | + sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); | |
| 115844 | + sqlite3VdbeJumpHere(v, addr); | |
| 115845 | + sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); | |
| 115846 | + }else{ | |
| 115847 | + sqlite3WhereEnd(pWInfo); | |
| 115848 | + } | |
| 115776 | 115849 | } |
| 115777 | 115850 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 115778 | 115851 | |
| 115779 | 115852 | /************** End of update.c **********************************************/ |
| 115780 | 115853 | /************** Begin file vacuum.c ******************************************/ |
| @@ -117091,11 +117164,13 @@ | ||
| 117091 | 117164 | ** sqlite3.aVTrans[] array. */ |
| 117092 | 117165 | rc = growVTrans(db); |
| 117093 | 117166 | if( rc==SQLITE_OK ){ |
| 117094 | 117167 | rc = pModule->xBegin(pVTab->pVtab); |
| 117095 | 117168 | if( rc==SQLITE_OK ){ |
| 117169 | + int iSvpt = db->nStatement + db->nSavepoint; | |
| 117096 | 117170 | addToVTrans(db, pVTab); |
| 117171 | + if( iSvpt ) rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, iSvpt-1); | |
| 117097 | 117172 | } |
| 117098 | 117173 | } |
| 117099 | 117174 | } |
| 117100 | 117175 | return rc; |
| 117101 | 117176 | } |
| @@ -117949,12 +118024,12 @@ | ||
| 117949 | 118024 | /* |
| 117950 | 118025 | ** Return the name of the i-th column of the pIdx index. |
| 117951 | 118026 | */ |
| 117952 | 118027 | static const char *explainIndexColumnName(Index *pIdx, int i){ |
| 117953 | 118028 | i = pIdx->aiColumn[i]; |
| 117954 | - if( i==(-2) ) return "<expr>"; | |
| 117955 | - if( i==(-1) ) return "rowid"; | |
| 118029 | + if( i==XN_EXPR ) return "<expr>"; | |
| 118030 | + if( i==XN_ROWID ) return "rowid"; | |
| 117956 | 118031 | return pIdx->pTable->aCol[i].zName; |
| 117957 | 118032 | } |
| 117958 | 118033 | |
| 117959 | 118034 | /* |
| 117960 | 118035 | ** Argument pLevel describes a strategy for scanning table pTab. This |
| @@ -118417,11 +118492,11 @@ | ||
| 118417 | 118492 | VdbeCoverageIf(v, bRev==0); |
| 118418 | 118493 | VdbeCoverageIf(v, bRev!=0); |
| 118419 | 118494 | sqlite3VdbeJumpHere(v, j); |
| 118420 | 118495 | for(j=0; j<nSkip; j++){ |
| 118421 | 118496 | sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j); |
| 118422 | - testcase( pIdx->aiColumn[j]==(-2) ); | |
| 118497 | + testcase( pIdx->aiColumn[j]==XN_EXPR ); | |
| 118423 | 118498 | VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); |
| 118424 | 118499 | } |
| 118425 | 118500 | } |
| 118426 | 118501 | |
| 118427 | 118502 | /* Evaluate the equality constraints |
| @@ -118603,12 +118678,12 @@ | ||
| 118603 | 118678 | for(j=0; j<nConstraint && j<16; j++){ |
| 118604 | 118679 | if( (pLoop->u.vtab.omitMask>>j)&1 ){ |
| 118605 | 118680 | disableTerm(pLevel, pLoop->aLTerm[j]); |
| 118606 | 118681 | } |
| 118607 | 118682 | } |
| 118608 | - pLevel->op = OP_VNext; | |
| 118609 | 118683 | pLevel->p1 = iCur; |
| 118684 | + pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; | |
| 118610 | 118685 | pLevel->p2 = sqlite3VdbeCurrentAddr(v); |
| 118611 | 118686 | sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); |
| 118612 | 118687 | sqlite3ExprCachePop(pParse); |
| 118613 | 118688 | }else |
| 118614 | 118689 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| @@ -120846,10 +120921,17 @@ | ||
| 120846 | 120921 | ** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is |
| 120847 | 120922 | ** unable to use the ONEPASS optimization. |
| 120848 | 120923 | */ |
| 120849 | 120924 | SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){ |
| 120850 | 120925 | memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); |
| 120926 | +#ifdef WHERETRACE_ENABLED | |
| 120927 | + if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){ | |
| 120928 | + sqlite3DebugPrintf("%s cursors: %d %d\n", | |
| 120929 | + pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI", | |
| 120930 | + aiCur[0], aiCur[1]); | |
| 120931 | + } | |
| 120932 | +#endif | |
| 120851 | 120933 | return pWInfo->eOnePass; |
| 120852 | 120934 | } |
| 120853 | 120935 | |
| 120854 | 120936 | /* |
| 120855 | 120937 | ** Move the content of pSrc into pDest |
| @@ -120941,16 +121023,16 @@ | ||
| 120941 | 121023 | int k = pScan->k; /* Where to start scanning */ |
| 120942 | 121024 | |
| 120943 | 121025 | while( pScan->iEquiv<=pScan->nEquiv ){ |
| 120944 | 121026 | iCur = pScan->aiCur[pScan->iEquiv-1]; |
| 120945 | 121027 | iColumn = pScan->aiColumn[pScan->iEquiv-1]; |
| 120946 | - if( iColumn==(-2) && pScan->pIdxExpr==0 ) return 0; | |
| 121028 | + if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; | |
| 120947 | 121029 | while( (pWC = pScan->pWC)!=0 ){ |
| 120948 | 121030 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 120949 | 121031 | if( pTerm->leftCursor==iCur |
| 120950 | 121032 | && pTerm->u.leftColumn==iColumn |
| 120951 | - && (iColumn!=(-2) | |
| 121033 | + && (iColumn!=XN_EXPR | |
| 120952 | 121034 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| 120953 | 121035 | && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) |
| 120954 | 121036 | ){ |
| 120955 | 121037 | if( (pTerm->eOperator & WO_EQUIV)!=0 |
| 120956 | 121038 | && pScan->nEquiv<ArraySize(pScan->aiCur) |
| @@ -121040,11 +121122,11 @@ | ||
| 121040 | 121122 | pScan->pWC = pWC; |
| 121041 | 121123 | pScan->pIdxExpr = 0; |
| 121042 | 121124 | if( pIdx ){ |
| 121043 | 121125 | j = iColumn; |
| 121044 | 121126 | iColumn = pIdx->aiColumn[j]; |
| 121045 | - if( iColumn==(-2) ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; | |
| 121127 | + if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; | |
| 121046 | 121128 | } |
| 121047 | 121129 | if( pIdx && iColumn>=0 ){ |
| 121048 | 121130 | pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; |
| 121049 | 121131 | pScan->zCollName = pIdx->azColl[j]; |
| 121050 | 121132 | }else{ |
| @@ -121479,11 +121561,11 @@ | ||
| 121479 | 121561 | pIdx->azColl[n] = "BINARY"; |
| 121480 | 121562 | n++; |
| 121481 | 121563 | } |
| 121482 | 121564 | } |
| 121483 | 121565 | assert( n==nKeyCol ); |
| 121484 | - pIdx->aiColumn[n] = -1; | |
| 121566 | + pIdx->aiColumn[n] = XN_ROWID; | |
| 121485 | 121567 | pIdx->azColl[n] = "BINARY"; |
| 121486 | 121568 | |
| 121487 | 121569 | /* Create the automatic index */ |
| 121488 | 121570 | assert( pLevel->iIdxCur>=0 ); |
| 121489 | 121571 | pLevel->iIdxCur = pParse->nTab++; |
| @@ -122994,11 +123076,13 @@ | ||
| 122994 | 123076 | |
| 122995 | 123077 | }else if( eOp & (WO_EQ|WO_IS) ){ |
| 122996 | 123078 | int iCol = pProbe->aiColumn[saved_nEq]; |
| 122997 | 123079 | pNew->wsFlags |= WHERE_COLUMN_EQ; |
| 122998 | 123080 | assert( saved_nEq==pNew->u.btree.nEq ); |
| 122999 | - if( iCol==(-1) || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){ | |
| 123081 | + if( iCol==XN_ROWID | |
| 123082 | + || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) | |
| 123083 | + ){ | |
| 123000 | 123084 | if( iCol>=0 && pProbe->uniqNotNull==0 ){ |
| 123001 | 123085 | pNew->wsFlags |= WHERE_UNQ_WANTED; |
| 123002 | 123086 | }else{ |
| 123003 | 123087 | pNew->wsFlags |= WHERE_ONEROW; |
| 123004 | 123088 | } |
| @@ -123194,11 +123278,11 @@ | ||
| 123194 | 123278 | for(jj=0; jj<pIndex->nKeyCol; jj++){ |
| 123195 | 123279 | if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; |
| 123196 | 123280 | } |
| 123197 | 123281 | }else if( (aColExpr = pIndex->aColExpr)!=0 ){ |
| 123198 | 123282 | for(jj=0; jj<pIndex->nKeyCol; jj++){ |
| 123199 | - if( pIndex->aiColumn[jj]!=(-2) ) continue; | |
| 123283 | + if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; | |
| 123200 | 123284 | if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ |
| 123201 | 123285 | return 1; |
| 123202 | 123286 | } |
| 123203 | 123287 | } |
| 123204 | 123288 | } |
| @@ -123591,10 +123675,11 @@ | ||
| 123591 | 123675 | pIdxInfo->idxNum = 0; |
| 123592 | 123676 | pIdxInfo->needToFreeIdxStr = 0; |
| 123593 | 123677 | pIdxInfo->orderByConsumed = 0; |
| 123594 | 123678 | pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; |
| 123595 | 123679 | pIdxInfo->estimatedRows = 25; |
| 123680 | + pIdxInfo->idxFlags = 0; | |
| 123596 | 123681 | rc = vtabBestIndex(pParse, pTab, pIdxInfo); |
| 123597 | 123682 | if( rc ) goto whereLoopAddVtab_exit; |
| 123598 | 123683 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 123599 | 123684 | pNew->prereq = mExtra; |
| 123600 | 123685 | mxTerm = -1; |
| @@ -123636,10 +123721,11 @@ | ||
| 123636 | 123721 | ** consume the ORDER BY clause because (1) the order of IN terms |
| 123637 | 123722 | ** is not necessarily related to the order of output terms and |
| 123638 | 123723 | ** (2) Multiple outputs from a single IN value will not merge |
| 123639 | 123724 | ** together. */ |
| 123640 | 123725 | pIdxInfo->orderByConsumed = 0; |
| 123726 | + pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; | |
| 123641 | 123727 | } |
| 123642 | 123728 | } |
| 123643 | 123729 | } |
| 123644 | 123730 | if( i>=nConstraint ){ |
| 123645 | 123731 | pNew->nLTerm = mxTerm+1; |
| @@ -123651,10 +123737,18 @@ | ||
| 123651 | 123737 | pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? |
| 123652 | 123738 | pIdxInfo->nOrderBy : 0); |
| 123653 | 123739 | pNew->rSetup = 0; |
| 123654 | 123740 | pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); |
| 123655 | 123741 | pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); |
| 123742 | + | |
| 123743 | + /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated | |
| 123744 | + ** that the scan will visit at most one row. Clear it otherwise. */ | |
| 123745 | + if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){ | |
| 123746 | + pNew->wsFlags |= WHERE_ONEROW; | |
| 123747 | + }else{ | |
| 123748 | + pNew->wsFlags &= ~WHERE_ONEROW; | |
| 123749 | + } | |
| 123656 | 123750 | whereLoopInsert(pBuilder, pNew); |
| 123657 | 123751 | if( pNew->u.vtab.needFree ){ |
| 123658 | 123752 | sqlite3_free(pNew->u.vtab.idxStr); |
| 123659 | 123753 | pNew->u.vtab.needFree = 0; |
| 123660 | 123754 | } |
| @@ -123972,11 +124066,12 @@ | ||
| 123972 | 124066 | return 0; |
| 123973 | 124067 | }else{ |
| 123974 | 124068 | nKeyCol = pIndex->nKeyCol; |
| 123975 | 124069 | nColumn = pIndex->nColumn; |
| 123976 | 124070 | assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) ); |
| 123977 | - assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable)); | |
| 124071 | + assert( pIndex->aiColumn[nColumn-1]==XN_ROWID | |
| 124072 | + || !HasRowid(pIndex->pTable)); | |
| 123978 | 124073 | isOrderDistinct = IsUniqueIndex(pIndex); |
| 123979 | 124074 | } |
| 123980 | 124075 | |
| 123981 | 124076 | /* Loop through all columns of the index and deal with the ones |
| 123982 | 124077 | ** that are not constrained by == or IN. |
| @@ -124004,11 +124099,11 @@ | ||
| 124004 | 124099 | if( pIndex ){ |
| 124005 | 124100 | iColumn = pIndex->aiColumn[j]; |
| 124006 | 124101 | revIdx = pIndex->aSortOrder[j]; |
| 124007 | 124102 | if( iColumn==pIndex->pTable->iPKey ) iColumn = -1; |
| 124008 | 124103 | }else{ |
| 124009 | - iColumn = -1; | |
| 124104 | + iColumn = XN_ROWID; | |
| 124010 | 124105 | revIdx = 0; |
| 124011 | 124106 | } |
| 124012 | 124107 | |
| 124013 | 124108 | /* An unconstrained column that might be NULL means that this |
| 124014 | 124109 | ** WhereLoop is not well-ordered |
| @@ -124869,11 +124964,12 @@ | ||
| 124869 | 124964 | pWInfo->pOrderBy = pResultSet; |
| 124870 | 124965 | } |
| 124871 | 124966 | } |
| 124872 | 124967 | |
| 124873 | 124968 | /* Construct the WhereLoop objects */ |
| 124874 | - WHERETRACE(0xffff,("*** Optimizer Start ***\n")); | |
| 124969 | + WHERETRACE(0xffff,("*** Optimizer Start *** (wctrlFlags: 0x%x)\n", | |
| 124970 | + wctrlFlags)); | |
| 124875 | 124971 | #if defined(WHERETRACE_ENABLED) |
| 124876 | 124972 | if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ |
| 124877 | 124973 | int i; |
| 124878 | 124974 | for(i=0; i<sWLB.pWC->nTerm; i++){ |
| 124879 | 124975 | whereTermPrint(&sWLB.pWC->a[i], i); |
| @@ -125303,10 +125399,11 @@ | ||
| 125303 | 125399 | int x = pOp->p2; |
| 125304 | 125400 | assert( pIdx->pTable==pTab ); |
| 125305 | 125401 | if( !HasRowid(pTab) ){ |
| 125306 | 125402 | Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 125307 | 125403 | x = pPk->aiColumn[x]; |
| 125404 | + assert( x>=0 ); | |
| 125308 | 125405 | } |
| 125309 | 125406 | x = sqlite3ColumnOfIndex(pIdx, x); |
| 125310 | 125407 | if( x>=0 ){ |
| 125311 | 125408 | pOp->p2 = x; |
| 125312 | 125409 | pOp->p1 = pLevel->iIdxCur; |
| @@ -135127,10 +135224,11 @@ | ||
| 135127 | 135224 | } *aIndex; |
| 135128 | 135225 | int nMaxPendingData; /* Max pending data before flush to disk */ |
| 135129 | 135226 | int nPendingData; /* Current bytes of pending data */ |
| 135130 | 135227 | sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ |
| 135131 | 135228 | int iPrevLangid; /* Langid of recently inserted document */ |
| 135229 | + int bPrevDelete; /* True if last operation was a delete */ | |
| 135132 | 135230 | |
| 135133 | 135231 | #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) |
| 135134 | 135232 | /* State variables used for validating that the transaction control |
| 135135 | 135233 | ** methods of the virtual table are called at appropriate times. These |
| 135136 | 135234 | ** values do not contribute to FTS functionality; they are used for |
| @@ -136701,10 +136799,23 @@ | ||
| 136701 | 136799 | if( sqlite3_libversion_number()>=3008002 ){ |
| 136702 | 136800 | pIdxInfo->estimatedRows = nRow; |
| 136703 | 136801 | } |
| 136704 | 136802 | #endif |
| 136705 | 136803 | } |
| 136804 | + | |
| 136805 | +/* | |
| 136806 | +** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this | |
| 136807 | +** extension is currently being used by a version of SQLite too old to | |
| 136808 | +** support index-info flags. In that case this function is a no-op. | |
| 136809 | +*/ | |
| 136810 | +static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ | |
| 136811 | +#if SQLITE_VERSION_NUMBER>=3008012 | |
| 136812 | + if( sqlite3_libversion_number()>=3008012 ){ | |
| 136813 | + pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; | |
| 136814 | + } | |
| 136815 | +#endif | |
| 136816 | +} | |
| 136706 | 136817 | |
| 136707 | 136818 | /* |
| 136708 | 136819 | ** Implementation of the xBestIndex method for FTS3 tables. There |
| 136709 | 136820 | ** are three possible strategies, in order of preference: |
| 136710 | 136821 | ** |
| @@ -136791,10 +136902,13 @@ | ||
| 136791 | 136902 | iDocidLe = i; |
| 136792 | 136903 | break; |
| 136793 | 136904 | } |
| 136794 | 136905 | } |
| 136795 | 136906 | } |
| 136907 | + | |
| 136908 | + /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */ | |
| 136909 | + if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo); | |
| 136796 | 136910 | |
| 136797 | 136911 | iIdx = 1; |
| 136798 | 136912 | if( iCons>=0 ){ |
| 136799 | 136913 | pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; |
| 136800 | 136914 | pInfo->aConstraintUsage[iCons].omit = 1; |
| @@ -146037,30 +146151,34 @@ | ||
| 146037 | 146151 | ** fts3PendingTermsAdd() are to add term/position-list pairs for the |
| 146038 | 146152 | ** contents of the document with docid iDocid. |
| 146039 | 146153 | */ |
| 146040 | 146154 | static int fts3PendingTermsDocid( |
| 146041 | 146155 | Fts3Table *p, /* Full-text table handle */ |
| 146156 | + int bDelete, /* True if this op is a delete */ | |
| 146042 | 146157 | int iLangid, /* Language id of row being written */ |
| 146043 | 146158 | sqlite_int64 iDocid /* Docid of row being written */ |
| 146044 | 146159 | ){ |
| 146045 | 146160 | assert( iLangid>=0 ); |
| 146161 | + assert( bDelete==1 || bDelete==0 ); | |
| 146046 | 146162 | |
| 146047 | 146163 | /* TODO(shess) Explore whether partially flushing the buffer on |
| 146048 | 146164 | ** forced-flush would provide better performance. I suspect that if |
| 146049 | 146165 | ** we ordered the doclists by size and flushed the largest until the |
| 146050 | 146166 | ** buffer was half empty, that would let the less frequent terms |
| 146051 | 146167 | ** generate longer doclists. |
| 146052 | 146168 | */ |
| 146053 | - if( iDocid<=p->iPrevDocid | |
| 146169 | + if( iDocid<p->iPrevDocid | |
| 146170 | + || (iDocid==p->iPrevDocid && p->bPrevDelete==0) | |
| 146054 | 146171 | || p->iPrevLangid!=iLangid |
| 146055 | 146172 | || p->nPendingData>p->nMaxPendingData |
| 146056 | 146173 | ){ |
| 146057 | 146174 | int rc = sqlite3Fts3PendingTermsFlush(p); |
| 146058 | 146175 | if( rc!=SQLITE_OK ) return rc; |
| 146059 | 146176 | } |
| 146060 | 146177 | p->iPrevDocid = iDocid; |
| 146061 | 146178 | p->iPrevLangid = iLangid; |
| 146179 | + p->bPrevDelete = bDelete; | |
| 146062 | 146180 | return SQLITE_OK; |
| 146063 | 146181 | } |
| 146064 | 146182 | |
| 146065 | 146183 | /* |
| 146066 | 146184 | ** Discard the contents of the pending-terms hash tables. |
| @@ -146246,11 +146364,12 @@ | ||
| 146246 | 146364 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); |
| 146247 | 146365 | if( rc==SQLITE_OK ){ |
| 146248 | 146366 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 146249 | 146367 | int i; |
| 146250 | 146368 | int iLangid = langidFromSelect(p, pSelect); |
| 146251 | - rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); | |
| 146369 | + i64 iDocid = sqlite3_column_int64(pSelect, 0); | |
| 146370 | + rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid); | |
| 146252 | 146371 | for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ |
| 146253 | 146372 | int iCol = i-1; |
| 146254 | 146373 | if( p->abNotindexed[iCol]==0 ){ |
| 146255 | 146374 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 146256 | 146375 | rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]); |
| @@ -146494,18 +146613,23 @@ | ||
| 146494 | 146613 | |
| 146495 | 146614 | if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){ |
| 146496 | 146615 | |
| 146497 | 146616 | if( fts3SegReaderIsPending(pReader) ){ |
| 146498 | 146617 | Fts3HashElem *pElem = *(pReader->ppNextElem); |
| 146499 | - if( pElem==0 ){ | |
| 146500 | - pReader->aNode = 0; | |
| 146501 | - }else{ | |
| 146618 | + sqlite3_free(pReader->aNode); | |
| 146619 | + pReader->aNode = 0; | |
| 146620 | + if( pElem ){ | |
| 146621 | + char *aCopy; | |
| 146502 | 146622 | PendingList *pList = (PendingList *)fts3HashData(pElem); |
| 146623 | + int nCopy = pList->nData+1; | |
| 146503 | 146624 | pReader->zTerm = (char *)fts3HashKey(pElem); |
| 146504 | 146625 | pReader->nTerm = fts3HashKeysize(pElem); |
| 146505 | - pReader->nNode = pReader->nDoclist = pList->nData + 1; | |
| 146506 | - pReader->aNode = pReader->aDoclist = pList->aData; | |
| 146626 | + aCopy = (char*)sqlite3_malloc(nCopy); | |
| 146627 | + if( !aCopy ) return SQLITE_NOMEM; | |
| 146628 | + memcpy(aCopy, pList->aData, nCopy); | |
| 146629 | + pReader->nNode = pReader->nDoclist = nCopy; | |
| 146630 | + pReader->aNode = pReader->aDoclist = aCopy; | |
| 146507 | 146631 | pReader->ppNextElem++; |
| 146508 | 146632 | assert( pReader->aNode ); |
| 146509 | 146633 | } |
| 146510 | 146634 | return SQLITE_OK; |
| 146511 | 146635 | } |
| @@ -146741,16 +146865,18 @@ | ||
| 146741 | 146865 | /* |
| 146742 | 146866 | ** Free all allocations associated with the iterator passed as the |
| 146743 | 146867 | ** second argument. |
| 146744 | 146868 | */ |
| 146745 | 146869 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ |
| 146746 | - if( pReader && !fts3SegReaderIsPending(pReader) ){ | |
| 146747 | - sqlite3_free(pReader->zTerm); | |
| 146870 | + if( pReader ){ | |
| 146871 | + if( !fts3SegReaderIsPending(pReader) ){ | |
| 146872 | + sqlite3_free(pReader->zTerm); | |
| 146873 | + } | |
| 146748 | 146874 | if( !fts3SegReaderIsRootOnly(pReader) ){ |
| 146749 | 146875 | sqlite3_free(pReader->aNode); |
| 146750 | - sqlite3_blob_close(pReader->pBlob); | |
| 146751 | 146876 | } |
| 146877 | + sqlite3_blob_close(pReader->pBlob); | |
| 146752 | 146878 | } |
| 146753 | 146879 | sqlite3_free(pReader); |
| 146754 | 146880 | } |
| 146755 | 146881 | |
| 146756 | 146882 | /* |
| @@ -148689,11 +148815,11 @@ | ||
| 148689 | 148815 | } |
| 148690 | 148816 | |
| 148691 | 148817 | while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 148692 | 148818 | int iCol; |
| 148693 | 148819 | int iLangid = langidFromSelect(p, pStmt); |
| 148694 | - rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); | |
| 148820 | + rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0)); | |
| 148695 | 148821 | memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); |
| 148696 | 148822 | for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ |
| 148697 | 148823 | if( p->abNotindexed[iCol]==0 ){ |
| 148698 | 148824 | const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); |
| 148699 | 148825 | rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); |
| @@ -150794,11 +150920,11 @@ | ||
| 150794 | 150920 | if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ |
| 150795 | 150921 | rc = FTS_CORRUPT_VTAB; |
| 150796 | 150922 | } |
| 150797 | 150923 | } |
| 150798 | 150924 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ |
| 150799 | - rc = fts3PendingTermsDocid(p, iLangid, *pRowid); | |
| 150925 | + rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); | |
| 150800 | 150926 | } |
| 150801 | 150927 | if( rc==SQLITE_OK ){ |
| 150802 | 150928 | assert( p->iPrevDocid==*pRowid ); |
| 150803 | 150929 | rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); |
| 150804 | 150930 | } |
| 150805 | 150931 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -325,11 +325,11 @@ | |
| 325 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 326 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 327 | */ |
| 328 | #define SQLITE_VERSION "3.8.12" |
| 329 | #define SQLITE_VERSION_NUMBER 3008012 |
| 330 | #define SQLITE_SOURCE_ID "2015-09-28 14:40:20 9d057f52217e7ef9c3f3eb84117abe3365503f44" |
| 331 | |
| 332 | /* |
| 333 | ** CAPI3REF: Run-Time Library Version Numbers |
| 334 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 335 | ** |
| @@ -5845,18 +5845,36 @@ | |
| 5845 | ** indicates that the expense of the operation is similar to that of a |
| 5846 | ** binary search on a unique indexed field of an SQLite table with N rows. |
| 5847 | ** |
| 5848 | ** ^The estimatedRows value is an estimate of the number of rows that |
| 5849 | ** will be returned by the strategy. |
| 5850 | ** |
| 5851 | ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info |
| 5852 | ** structure for SQLite version 3.8.2. If a virtual table extension is |
| 5853 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5854 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5855 | ** to included crashing the application). The estimatedRows field should |
| 5856 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5857 | ** value greater than or equal to 3008002. |
| 5858 | */ |
| 5859 | struct sqlite3_index_info { |
| 5860 | /* Inputs */ |
| 5861 | int nConstraint; /* Number of entries in aConstraint */ |
| 5862 | struct sqlite3_index_constraint { |
| @@ -5880,12 +5898,19 @@ | |
| 5880 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5881 | int orderByConsumed; /* True if output is already ordered */ |
| 5882 | double estimatedCost; /* Estimated cost of using this index */ |
| 5883 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5884 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5885 | }; |
| 5886 | |
| 5887 | /* |
| 5888 | ** CAPI3REF: Virtual Table Constraint Operator Codes |
| 5889 | ** |
| 5890 | ** These macros defined the allowed values for the |
| 5891 | ** [sqlite3_index_info].aConstraint[].op field. Each value represents |
| @@ -11914,10 +11939,16 @@ | |
| 11914 | #define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY) |
| 11915 | |
| 11916 | /* Return true if index X is a UNIQUE index */ |
| 11917 | #define IsUniqueIndex(X) ((X)->onError!=OE_None) |
| 11918 | |
| 11919 | /* |
| 11920 | ** Each sample stored in the sqlite_stat3 table is represented in memory |
| 11921 | ** using a structure of this type. See documentation at the top of the |
| 11922 | ** analyze.c source file for additional information. |
| 11923 | */ |
| @@ -13501,19 +13532,21 @@ | |
| 13501 | SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); |
| 13502 | SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); |
| 13503 | SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); |
| 13504 | SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); |
| 13505 | # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) |
| 13506 | #else |
| 13507 | # define sqlite3TriggersExist(B,C,D,E,F) 0 |
| 13508 | # define sqlite3DeleteTrigger(A,B) |
| 13509 | # define sqlite3DropTriggerPtr(A,B) |
| 13510 | # define sqlite3UnlinkAndDeleteTrigger(A,B,C) |
| 13511 | # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) |
| 13512 | # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) |
| 13513 | # define sqlite3TriggerList(X, Y) 0 |
| 13514 | # define sqlite3ParseToplevel(p) p |
| 13515 | # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 |
| 13516 | #endif |
| 13517 | |
| 13518 | SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); |
| 13519 | SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); |
| @@ -54599,11 +54632,11 @@ | |
| 54599 | if( rc==SQLITE_OK ){ |
| 54600 | btreeReleaseAllCursorPages(pCur); |
| 54601 | pCur->eState = CURSOR_REQUIRESEEK; |
| 54602 | } |
| 54603 | |
| 54604 | invalidateOverflowCache(pCur); |
| 54605 | return rc; |
| 54606 | } |
| 54607 | |
| 54608 | /* Forward reference */ |
| 54609 | static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); |
| @@ -61562,11 +61595,11 @@ | |
| 61562 | ** It is critical that the child page be defragmented before being |
| 61563 | ** copied into the parent, because if the parent is page 1 then it will |
| 61564 | ** by smaller than the child due to the database header, and so all the |
| 61565 | ** free space needs to be up front. |
| 61566 | */ |
| 61567 | assert( nNew==1 ); |
| 61568 | rc = defragmentPage(apNew[0]); |
| 61569 | testcase( rc!=SQLITE_OK ); |
| 61570 | assert( apNew[0]->nFree == |
| 61571 | (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) |
| 61572 | || rc!=SQLITE_OK |
| @@ -79270,11 +79303,11 @@ | |
| 79270 | #endif |
| 79271 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 79272 | int j; |
| 79273 | for(j=0; j<pIdx->nKeyCol; j++){ |
| 79274 | /* FIXME: Be smarter about indexes that use expressions */ |
| 79275 | if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==(-2) ){ |
| 79276 | zFault = "indexed"; |
| 79277 | } |
| 79278 | } |
| 79279 | } |
| 79280 | if( zFault ){ |
| @@ -86848,19 +86881,19 @@ | |
| 86848 | int iTabCur, /* Cursor pointing to a table row */ |
| 86849 | int iIdxCol, /* The column of the index to be loaded */ |
| 86850 | int regOut /* Store the index column value in this register */ |
| 86851 | ){ |
| 86852 | i16 iTabCol = pIdx->aiColumn[iIdxCol]; |
| 86853 | if( iTabCol>=(-1) ){ |
| 86854 | sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur, |
| 86855 | iTabCol, regOut); |
| 86856 | return; |
| 86857 | } |
| 86858 | assert( pIdx->aColExpr ); |
| 86859 | assert( pIdx->aColExpr->nExpr>iIdxCol ); |
| 86860 | pParse->iSelfTab = iTabCur; |
| 86861 | sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); |
| 86862 | } |
| 86863 | |
| 86864 | /* |
| 86865 | ** Generate code to extract the value of the iCol-th column of a table. |
| 86866 | */ |
| @@ -92379,10 +92412,12 @@ | |
| 92379 | DbMaskTest(pParse->writeMask,iDb), /* P2 */ |
| 92380 | pParse->cookieValue[iDb], /* P3 */ |
| 92381 | db->aDb[iDb].pSchema->iGeneration /* P4 */ |
| 92382 | ); |
| 92383 | if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); |
| 92384 | } |
| 92385 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 92386 | for(i=0; i<pParse->nVtabLock; i++){ |
| 92387 | char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); |
| 92388 | sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); |
| @@ -95321,11 +95356,11 @@ | |
| 95321 | } |
| 95322 | |
| 95323 | /* Analyze the list of expressions that form the terms of the index and |
| 95324 | ** report any errors. In the common case where the expression is exactly |
| 95325 | ** a table column, store that column in aiColumn[]. For general expressions, |
| 95326 | ** populate pIndex->aColExpr and store -2 in aiColumn[]. |
| 95327 | ** |
| 95328 | ** TODO: Issue a warning if two or more columns of the index are identical. |
| 95329 | ** TODO: Issue a warning if the table primary key is used as part of the |
| 95330 | ** index key. |
| 95331 | */ |
| @@ -95350,12 +95385,12 @@ | |
| 95350 | if( !db->mallocFailed ){ |
| 95351 | assert( pCopy!=0 ); |
| 95352 | pListItem = &pCopy->a[i]; |
| 95353 | } |
| 95354 | } |
| 95355 | j = -2; |
| 95356 | pIndex->aiColumn[i] = -2; |
| 95357 | pIndex->uniqNotNull = 0; |
| 95358 | }else{ |
| 95359 | j = pCExpr->iColumn; |
| 95360 | assert( j<=0x7fff ); |
| 95361 | if( j<0 ){ |
| @@ -95404,11 +95439,11 @@ | |
| 95404 | i++; |
| 95405 | } |
| 95406 | } |
| 95407 | assert( i==pIndex->nColumn ); |
| 95408 | }else{ |
| 95409 | pIndex->aiColumn[i] = -1; |
| 95410 | pIndex->azColl[i] = "BINARY"; |
| 95411 | } |
| 95412 | sqlite3DefaultRowEst(pIndex); |
| 95413 | if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); |
| 95414 | |
| @@ -97508,11 +97543,11 @@ | |
| 97508 | ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. |
| 97509 | */ |
| 97510 | pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); |
| 97511 | if( pWInfo==0 ) goto delete_from_cleanup; |
| 97512 | eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); |
| 97513 | assert( IsVirtual(pTab)==0 || eOnePass==ONEPASS_OFF ); |
| 97514 | assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); |
| 97515 | |
| 97516 | /* Keep track of the number of rows to be deleted */ |
| 97517 | if( db->flags & SQLITE_CountRows ){ |
| 97518 | sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); |
| @@ -97519,11 +97554,11 @@ | |
| 97519 | } |
| 97520 | |
| 97521 | /* Extract the rowid or primary key for the current row */ |
| 97522 | if( pPk ){ |
| 97523 | for(i=0; i<nPk; i++){ |
| 97524 | assert( pPk->aiColumn[i]>=(-1) ); |
| 97525 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, |
| 97526 | pPk->aiColumn[i], iPk+i); |
| 97527 | } |
| 97528 | iKey = iPk; |
| 97529 | }else{ |
| @@ -97591,11 +97626,11 @@ | |
| 97591 | /* Set up a loop over the rowids/primary-keys that were found in the |
| 97592 | ** where-clause loop above. |
| 97593 | */ |
| 97594 | if( eOnePass!=ONEPASS_OFF ){ |
| 97595 | assert( nKey==nPk ); /* OP_Found will use an unpacked key */ |
| 97596 | if( aToOpen[iDataCur-iTabCur] ){ |
| 97597 | assert( pPk!=0 || pTab->pSelect!=0 ); |
| 97598 | sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); |
| 97599 | VdbeCoverage(v); |
| 97600 | } |
| 97601 | }else if( pPk ){ |
| @@ -97613,11 +97648,15 @@ | |
| 97613 | if( IsVirtual(pTab) ){ |
| 97614 | const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); |
| 97615 | sqlite3VtabMakeWritable(pParse, pTab); |
| 97616 | sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); |
| 97617 | sqlite3VdbeChangeP5(v, OE_Abort); |
| 97618 | sqlite3MayAbort(pParse); |
| 97619 | }else |
| 97620 | #endif |
| 97621 | { |
| 97622 | int count = (pParse->nested==0); /* True to count changes */ |
| 97623 | int iIdxNoSeek = -1; |
| @@ -97951,11 +97990,11 @@ | |
| 97951 | regBase = sqlite3GetTempRange(pParse, nCol); |
| 97952 | if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0; |
| 97953 | for(j=0; j<nCol; j++){ |
| 97954 | if( pPrior |
| 97955 | && pPrior->aiColumn[j]==pIdx->aiColumn[j] |
| 97956 | && pPrior->aiColumn[j]>=(-1) |
| 97957 | ){ |
| 97958 | /* This column was already computed by the previous index */ |
| 97959 | continue; |
| 97960 | } |
| 97961 | sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); |
| @@ -100039,10 +100078,12 @@ | |
| 100039 | for(i=0; i<nCol; i++){ |
| 100040 | i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */ |
| 100041 | char *zDfltColl; /* Def. collation for column */ |
| 100042 | char *zIdxCol; /* Name of indexed column */ |
| 100043 | |
| 100044 | /* If the index uses a collation sequence that is different from |
| 100045 | ** the default collation sequence for the column, this index is |
| 100046 | ** unusable. Bail out early in this case. */ |
| 100047 | zDfltColl = pParent->aCol[iCol].zColl; |
| 100048 | if( !zDfltColl ){ |
| @@ -100191,10 +100232,11 @@ | |
| 100191 | if( pTab==pFKey->pFrom && nIncr==1 ){ |
| 100192 | int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; |
| 100193 | for(i=0; i<nCol; i++){ |
| 100194 | int iChild = aiCol[i]+1+regData; |
| 100195 | int iParent = pIdx->aiColumn[i]+1+regData; |
| 100196 | assert( aiCol[i]!=pTab->iPKey ); |
| 100197 | if( pIdx->aiColumn[i]==pTab->iPKey ){ |
| 100198 | /* The parent key is a composite key that includes the IPK column */ |
| 100199 | iParent = regData; |
| 100200 | } |
| @@ -100399,10 +100441,11 @@ | |
| 100399 | Expr *pEq, *pAll = 0; |
| 100400 | Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 100401 | assert( pIdx!=0 ); |
| 100402 | for(i=0; i<pPk->nKeyCol; i++){ |
| 100403 | i16 iCol = pIdx->aiColumn[i]; |
| 100404 | pLeft = exprTableRegister(pParse, pTab, regData, iCol); |
| 100405 | pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); |
| 100406 | pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); |
| 100407 | pAll = sqlite3ExprAnd(db, pAll, pEq); |
| 100408 | } |
| @@ -100718,10 +100761,11 @@ | |
| 100718 | } |
| 100719 | for(i=0; i<pFKey->nCol; i++){ |
| 100720 | if( aiCol[i]==pTab->iPKey ){ |
| 100721 | aiCol[i] = -1; |
| 100722 | } |
| 100723 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 100724 | /* Request permission to read the parent key columns. If the |
| 100725 | ** authorization callback returns SQLITE_IGNORE, behave as if any |
| 100726 | ** values read from the parent table are NULL. */ |
| 100727 | if( db->xAuth ){ |
| @@ -100849,11 +100893,14 @@ | |
| 100849 | } |
| 100850 | for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 100851 | Index *pIdx = 0; |
| 100852 | sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); |
| 100853 | if( pIdx ){ |
| 100854 | for(i=0; i<pIdx->nKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
| 100855 | } |
| 100856 | } |
| 100857 | } |
| 100858 | return mask; |
| 100859 | } |
| @@ -100972,10 +101019,11 @@ | |
| 100972 | Expr *pEq; /* tFromCol = OLD.tToCol */ |
| 100973 | |
| 100974 | iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
| 100975 | assert( iFromCol>=0 ); |
| 100976 | assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); |
| 100977 | tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; |
| 100978 | tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; |
| 100979 | |
| 100980 | tToCol.n = sqlite3Strlen30(tToCol.z); |
| 100981 | tFromCol.n = sqlite3Strlen30(tFromCol.z); |
| @@ -101281,15 +101329,15 @@ | |
| 101281 | } |
| 101282 | for(n=0; n<pIdx->nColumn; n++){ |
| 101283 | i16 x = pIdx->aiColumn[n]; |
| 101284 | if( x>=0 ){ |
| 101285 | pIdx->zColAff[n] = pTab->aCol[x].affinity; |
| 101286 | }else if( x==(-1) ){ |
| 101287 | pIdx->zColAff[n] = SQLITE_AFF_INTEGER; |
| 101288 | }else{ |
| 101289 | char aff; |
| 101290 | assert( x==(-2) ); |
| 101291 | assert( pIdx->aColExpr!=0 ); |
| 101292 | aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); |
| 101293 | if( aff==0 ) aff = SQLITE_AFF_BLOB; |
| 101294 | pIdx->zColAff[n] = aff; |
| 101295 | } |
| @@ -101451,11 +101499,11 @@ | |
| 101451 | Vdbe *v = pParse->pVdbe; /* VDBE under construction */ |
| 101452 | |
| 101453 | /* This routine is never called during trigger-generation. It is |
| 101454 | ** only called from the top-level */ |
| 101455 | assert( pParse->pTriggerTab==0 ); |
| 101456 | assert( pParse==sqlite3ParseToplevel(pParse) ); |
| 101457 | |
| 101458 | assert( v ); /* We failed long ago if this is not so */ |
| 101459 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 101460 | pDb = &db->aDb[p->iDb]; |
| 101461 | memId = p->regCtr; |
| @@ -102599,17 +102647,17 @@ | |
| 102599 | */ |
| 102600 | regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn); |
| 102601 | for(i=0; i<pIdx->nColumn; i++){ |
| 102602 | int iField = pIdx->aiColumn[i]; |
| 102603 | int x; |
| 102604 | if( iField==(-2) ){ |
| 102605 | pParse->ckBase = regNewData+1; |
| 102606 | sqlite3ExprCode(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); |
| 102607 | pParse->ckBase = 0; |
| 102608 | VdbeComment((v, "%s column %d", pIdx->zName, i)); |
| 102609 | }else{ |
| 102610 | if( iField==(-1) || iField==pTab->iPKey ){ |
| 102611 | if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */ |
| 102612 | x = regNewData; |
| 102613 | regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i; |
| 102614 | }else{ |
| 102615 | x = iField + regNewData + 1; |
| @@ -102664,10 +102712,11 @@ | |
| 102664 | int x; |
| 102665 | /* Extract the PRIMARY KEY from the end of the index entry and |
| 102666 | ** store it in registers regR..regR+nPk-1 */ |
| 102667 | if( pIdx!=pPk ){ |
| 102668 | for(i=0; i<pPk->nKeyCol; i++){ |
| 102669 | x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); |
| 102670 | sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); |
| 102671 | VdbeComment((v, "%s.%s", pTab->zName, |
| 102672 | pTab->aCol[pPk->aiColumn[i]].zName)); |
| 102673 | } |
| @@ -102685,10 +102734,11 @@ | |
| 102685 | int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR); |
| 102686 | |
| 102687 | for(i=0; i<pPk->nKeyCol; i++){ |
| 102688 | char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); |
| 102689 | x = pPk->aiColumn[i]; |
| 102690 | if( i==(pPk->nKeyCol-1) ){ |
| 102691 | addrJump = addrUniqueOk; |
| 102692 | op = OP_Eq; |
| 102693 | } |
| 102694 | sqlite3VdbeAddOp4(v, op, |
| @@ -102936,11 +102986,11 @@ | |
| 102936 | } |
| 102937 | for(i=0; i<pSrc->nKeyCol; i++){ |
| 102938 | if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ |
| 102939 | return 0; /* Different columns indexed */ |
| 102940 | } |
| 102941 | if( pSrc->aiColumn[i]==(-2) ){ |
| 102942 | assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 ); |
| 102943 | if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr, |
| 102944 | pDest->aColExpr->a[i].pExpr, -1)!=0 ){ |
| 102945 | return 0; /* Different expressions in the index */ |
| 102946 | } |
| @@ -106741,11 +106791,11 @@ | |
| 106741 | int uniqOk = sqlite3VdbeMakeLabel(v); |
| 106742 | int jmp6; |
| 106743 | int kk; |
| 106744 | for(kk=0; kk<pIdx->nKeyCol; kk++){ |
| 106745 | int iCol = pIdx->aiColumn[kk]; |
| 106746 | assert( iCol!=(-1) && iCol<pTab->nCol ); |
| 106747 | if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; |
| 106748 | sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); |
| 106749 | VdbeCoverage(v); |
| 106750 | } |
| 106751 | jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); |
| @@ -112261,21 +112311,13 @@ | |
| 112261 | ** an entry of the FROM clause is a subquery instead of a table or view, |
| 112262 | ** then create a transient table structure to describe the subquery. |
| 112263 | */ |
| 112264 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 112265 | Table *pTab; |
| 112266 | assert( pFrom->fg.isRecursive==0 || pFrom->pTab ); |
| 112267 | if( pFrom->fg.isRecursive ) continue; |
| 112268 | if( pFrom->pTab!=0 ){ |
| 112269 | /* This statement has already been prepared. There is no need |
| 112270 | ** to go further. */ |
| 112271 | assert( i==0 ); |
| 112272 | #ifndef SQLITE_OMIT_CTE |
| 112273 | selectPopWith(pWalker, p); |
| 112274 | #endif |
| 112275 | return WRC_Prune; |
| 112276 | } |
| 112277 | #ifndef SQLITE_OMIT_CTE |
| 112278 | if( withExpand(pWalker, pFrom) ) return WRC_Abort; |
| 112279 | if( pFrom->pTab ) {} else |
| 112280 | #endif |
| 112281 | if( pFrom->zName==0 ){ |
| @@ -112563,23 +112605,23 @@ | |
| 112563 | int i; |
| 112564 | SrcList *pTabList; |
| 112565 | struct SrcList_item *pFrom; |
| 112566 | |
| 112567 | assert( p->selFlags & SF_Resolved ); |
| 112568 | if( (p->selFlags & SF_HasTypeInfo)==0 ){ |
| 112569 | p->selFlags |= SF_HasTypeInfo; |
| 112570 | pParse = pWalker->pParse; |
| 112571 | pTabList = p->pSrc; |
| 112572 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 112573 | Table *pTab = pFrom->pTab; |
| 112574 | if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
| 112575 | /* A sub-query in the FROM clause of a SELECT */ |
| 112576 | Select *pSel = pFrom->pSelect; |
| 112577 | if( pSel ){ |
| 112578 | while( pSel->pPrior ) pSel = pSel->pPrior; |
| 112579 | selectAddColumnTypeAndCollation(pParse, pTab, pSel); |
| 112580 | } |
| 112581 | } |
| 112582 | } |
| 112583 | } |
| 112584 | } |
| 112585 | #endif |
| @@ -115133,13 +115175,13 @@ | |
| 115133 | int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */ |
| 115134 | int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ |
| 115135 | |
| 115136 | /* Register Allocations */ |
| 115137 | int regRowCount = 0; /* A count of rows changed */ |
| 115138 | int regOldRowid; /* The old rowid */ |
| 115139 | int regNewRowid; /* The new rowid */ |
| 115140 | int regNew; /* Content of the NEW.* table in triggers */ |
| 115141 | int regOld = 0; /* Content of OLD.* table in triggers */ |
| 115142 | int regRowSet = 0; /* Rowset of rows to be updated */ |
| 115143 | int regKey = 0; /* composite PRIMARY KEY value */ |
| 115144 | |
| 115145 | memset(&sContext, 0, sizeof(sContext)); |
| @@ -115299,33 +115341,24 @@ | |
| 115299 | v = sqlite3GetVdbe(pParse); |
| 115300 | if( v==0 ) goto update_cleanup; |
| 115301 | if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); |
| 115302 | sqlite3BeginWriteOperation(pParse, 1, iDb); |
| 115303 | |
| 115304 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 115305 | /* Virtual tables must be handled separately */ |
| 115306 | if( IsVirtual(pTab) ){ |
| 115307 | updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, |
| 115308 | pWhere, onError); |
| 115309 | pWhere = 0; |
| 115310 | pTabList = 0; |
| 115311 | goto update_cleanup; |
| 115312 | } |
| 115313 | #endif |
| 115314 | |
| 115315 | /* Allocate required registers. */ |
| 115316 | regRowSet = ++pParse->nMem; |
| 115317 | regOldRowid = regNewRowid = ++pParse->nMem; |
| 115318 | if( chngPk || pTrigger || hasFK ){ |
| 115319 | regOld = pParse->nMem + 1; |
| 115320 | pParse->nMem += pTab->nCol; |
| 115321 | } |
| 115322 | if( chngKey || pTrigger || hasFK ){ |
| 115323 | regNewRowid = ++pParse->nMem; |
| 115324 | } |
| 115325 | regNew = pParse->nMem + 1; |
| 115326 | pParse->nMem += pTab->nCol; |
| 115327 | |
| 115328 | /* Start the view context. */ |
| 115329 | if( isView ){ |
| 115330 | sqlite3AuthContextPush(pParse, &sContext, pTab->zName); |
| 115331 | } |
| @@ -115343,10 +115376,19 @@ | |
| 115343 | ** WHERE clause. |
| 115344 | */ |
| 115345 | if( sqlite3ResolveExprNames(&sNC, pWhere) ){ |
| 115346 | goto update_cleanup; |
| 115347 | } |
| 115348 | |
| 115349 | /* Begin the database scan |
| 115350 | */ |
| 115351 | if( HasRowid(pTab) ){ |
| 115352 | sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); |
| @@ -115383,11 +115425,11 @@ | |
| 115383 | pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, |
| 115384 | WHERE_ONEPASS_DESIRED, iIdxCur); |
| 115385 | if( pWInfo==0 ) goto update_cleanup; |
| 115386 | okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); |
| 115387 | for(i=0; i<nPk; i++){ |
| 115388 | assert( pPk->aiColumn[i]>=(-1) ); |
| 115389 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i], |
| 115390 | iPk+i); |
| 115391 | } |
| 115392 | if( okOnePass ){ |
| 115393 | sqlite3VdbeChangeToNoop(v, addrOpen); |
| @@ -115506,11 +115548,10 @@ | |
| 115506 | ** be used eliminates some redundant opcodes. |
| 115507 | */ |
| 115508 | newmask = sqlite3TriggerColmask( |
| 115509 | pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError |
| 115510 | ); |
| 115511 | /*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/ |
| 115512 | for(i=0; i<pTab->nCol; i++){ |
| 115513 | if( i==pTab->iPKey ){ |
| 115514 | sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); |
| 115515 | }else{ |
| 115516 | j = aXRef[i]; |
| @@ -115684,25 +115725,27 @@ | |
| 115684 | |
| 115685 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 115686 | /* |
| 115687 | ** Generate code for an UPDATE of a virtual table. |
| 115688 | ** |
| 115689 | ** The strategy is that we create an ephemeral table that contains |
| 115690 | ** for each row to be changed: |
| 115691 | ** |
| 115692 | ** (A) The original rowid of that row. |
| 115693 | ** (B) The revised rowid for the row. (note1) |
| 115694 | ** (C) The content of every column in the row. |
| 115695 | ** |
| 115696 | ** Then we loop over this ephemeral table and for each row in |
| 115697 | ** the ephemeral table call VUpdate. |
| 115698 | ** |
| 115699 | ** When finished, drop the ephemeral table. |
| 115700 | ** |
| 115701 | ** (note1) Actually, if we know in advance that (A) is always the same |
| 115702 | ** as (B) we only store (A), then duplicate (A) when pulling |
| 115703 | ** it out of the ephemeral table before calling VUpdate. |
| 115704 | */ |
| 115705 | static void updateVirtualTable( |
| 115706 | Parse *pParse, /* The parsing context */ |
| 115707 | SrcList *pSrc, /* The virtual table to be modified */ |
| 115708 | Table *pTab, /* The virtual table */ |
| @@ -115711,70 +115754,100 @@ | |
| 115711 | int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ |
| 115712 | Expr *pWhere, /* WHERE clause of the UPDATE statement */ |
| 115713 | int onError /* ON CONFLICT strategy */ |
| 115714 | ){ |
| 115715 | Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ |
| 115716 | ExprList *pEList = 0; /* The result set of the SELECT statement */ |
| 115717 | Select *pSelect = 0; /* The SELECT statement */ |
| 115718 | Expr *pExpr; /* Temporary expression */ |
| 115719 | int ephemTab; /* Table holding the result of the SELECT */ |
| 115720 | int i; /* Loop counter */ |
| 115721 | int addr; /* Address of top of loop */ |
| 115722 | int iReg; /* First register in set passed to OP_VUpdate */ |
| 115723 | sqlite3 *db = pParse->db; /* Database connection */ |
| 115724 | const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); |
| 115725 | SelectDest dest; |
| 115726 | |
| 115727 | /* Construct the SELECT statement that will find the new values for |
| 115728 | ** all updated rows. |
| 115729 | */ |
| 115730 | pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_")); |
| 115731 | if( pRowid ){ |
| 115732 | pEList = sqlite3ExprListAppend(pParse, pEList, |
| 115733 | sqlite3ExprDup(db, pRowid, 0)); |
| 115734 | } |
| 115735 | assert( pTab->iPKey<0 ); |
| 115736 | for(i=0; i<pTab->nCol; i++){ |
| 115737 | if( aXRef[i]>=0 ){ |
| 115738 | pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0); |
| 115739 | }else{ |
| 115740 | pExpr = sqlite3Expr(db, TK_ID, pTab->aCol[i].zName); |
| 115741 | } |
| 115742 | pEList = sqlite3ExprListAppend(pParse, pEList, pExpr); |
| 115743 | } |
| 115744 | pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); |
| 115745 | |
| 115746 | /* Create the ephemeral table into which the update results will |
| 115747 | ** be stored. |
| 115748 | */ |
| 115749 | assert( v ); |
| 115750 | ephemTab = pParse->nTab++; |
| 115751 | |
| 115752 | /* fill the ephemeral table |
| 115753 | */ |
| 115754 | sqlite3SelectDestInit(&dest, SRT_EphemTab, ephemTab); |
| 115755 | sqlite3Select(pParse, pSelect, &dest); |
| 115756 | |
| 115757 | /* Generate code to scan the ephemeral table and call VUpdate. */ |
| 115758 | iReg = ++pParse->nMem; |
| 115759 | pParse->nMem += pTab->nCol+1; |
| 115760 | addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); |
| 115761 | sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); |
| 115762 | sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); |
| 115763 | for(i=0; i<pTab->nCol; i++){ |
| 115764 | sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i); |
| 115765 | } |
| 115766 | sqlite3VtabMakeWritable(pParse, pTab); |
| 115767 | sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB); |
| 115768 | sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); |
| 115769 | sqlite3MayAbort(pParse); |
| 115770 | sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); |
| 115771 | sqlite3VdbeJumpHere(v, addr); |
| 115772 | sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); |
| 115773 | |
| 115774 | /* Cleanup */ |
| 115775 | sqlite3SelectDelete(db, pSelect); |
| 115776 | } |
| 115777 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 115778 | |
| 115779 | /************** End of update.c **********************************************/ |
| 115780 | /************** Begin file vacuum.c ******************************************/ |
| @@ -117091,11 +117164,13 @@ | |
| 117091 | ** sqlite3.aVTrans[] array. */ |
| 117092 | rc = growVTrans(db); |
| 117093 | if( rc==SQLITE_OK ){ |
| 117094 | rc = pModule->xBegin(pVTab->pVtab); |
| 117095 | if( rc==SQLITE_OK ){ |
| 117096 | addToVTrans(db, pVTab); |
| 117097 | } |
| 117098 | } |
| 117099 | } |
| 117100 | return rc; |
| 117101 | } |
| @@ -117949,12 +118024,12 @@ | |
| 117949 | /* |
| 117950 | ** Return the name of the i-th column of the pIdx index. |
| 117951 | */ |
| 117952 | static const char *explainIndexColumnName(Index *pIdx, int i){ |
| 117953 | i = pIdx->aiColumn[i]; |
| 117954 | if( i==(-2) ) return "<expr>"; |
| 117955 | if( i==(-1) ) return "rowid"; |
| 117956 | return pIdx->pTable->aCol[i].zName; |
| 117957 | } |
| 117958 | |
| 117959 | /* |
| 117960 | ** Argument pLevel describes a strategy for scanning table pTab. This |
| @@ -118417,11 +118492,11 @@ | |
| 118417 | VdbeCoverageIf(v, bRev==0); |
| 118418 | VdbeCoverageIf(v, bRev!=0); |
| 118419 | sqlite3VdbeJumpHere(v, j); |
| 118420 | for(j=0; j<nSkip; j++){ |
| 118421 | sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j); |
| 118422 | testcase( pIdx->aiColumn[j]==(-2) ); |
| 118423 | VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); |
| 118424 | } |
| 118425 | } |
| 118426 | |
| 118427 | /* Evaluate the equality constraints |
| @@ -118603,12 +118678,12 @@ | |
| 118603 | for(j=0; j<nConstraint && j<16; j++){ |
| 118604 | if( (pLoop->u.vtab.omitMask>>j)&1 ){ |
| 118605 | disableTerm(pLevel, pLoop->aLTerm[j]); |
| 118606 | } |
| 118607 | } |
| 118608 | pLevel->op = OP_VNext; |
| 118609 | pLevel->p1 = iCur; |
| 118610 | pLevel->p2 = sqlite3VdbeCurrentAddr(v); |
| 118611 | sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); |
| 118612 | sqlite3ExprCachePop(pParse); |
| 118613 | }else |
| 118614 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| @@ -120846,10 +120921,17 @@ | |
| 120846 | ** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is |
| 120847 | ** unable to use the ONEPASS optimization. |
| 120848 | */ |
| 120849 | SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){ |
| 120850 | memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); |
| 120851 | return pWInfo->eOnePass; |
| 120852 | } |
| 120853 | |
| 120854 | /* |
| 120855 | ** Move the content of pSrc into pDest |
| @@ -120941,16 +121023,16 @@ | |
| 120941 | int k = pScan->k; /* Where to start scanning */ |
| 120942 | |
| 120943 | while( pScan->iEquiv<=pScan->nEquiv ){ |
| 120944 | iCur = pScan->aiCur[pScan->iEquiv-1]; |
| 120945 | iColumn = pScan->aiColumn[pScan->iEquiv-1]; |
| 120946 | if( iColumn==(-2) && pScan->pIdxExpr==0 ) return 0; |
| 120947 | while( (pWC = pScan->pWC)!=0 ){ |
| 120948 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 120949 | if( pTerm->leftCursor==iCur |
| 120950 | && pTerm->u.leftColumn==iColumn |
| 120951 | && (iColumn!=(-2) |
| 120952 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| 120953 | && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) |
| 120954 | ){ |
| 120955 | if( (pTerm->eOperator & WO_EQUIV)!=0 |
| 120956 | && pScan->nEquiv<ArraySize(pScan->aiCur) |
| @@ -121040,11 +121122,11 @@ | |
| 121040 | pScan->pWC = pWC; |
| 121041 | pScan->pIdxExpr = 0; |
| 121042 | if( pIdx ){ |
| 121043 | j = iColumn; |
| 121044 | iColumn = pIdx->aiColumn[j]; |
| 121045 | if( iColumn==(-2) ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; |
| 121046 | } |
| 121047 | if( pIdx && iColumn>=0 ){ |
| 121048 | pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; |
| 121049 | pScan->zCollName = pIdx->azColl[j]; |
| 121050 | }else{ |
| @@ -121479,11 +121561,11 @@ | |
| 121479 | pIdx->azColl[n] = "BINARY"; |
| 121480 | n++; |
| 121481 | } |
| 121482 | } |
| 121483 | assert( n==nKeyCol ); |
| 121484 | pIdx->aiColumn[n] = -1; |
| 121485 | pIdx->azColl[n] = "BINARY"; |
| 121486 | |
| 121487 | /* Create the automatic index */ |
| 121488 | assert( pLevel->iIdxCur>=0 ); |
| 121489 | pLevel->iIdxCur = pParse->nTab++; |
| @@ -122994,11 +123076,13 @@ | |
| 122994 | |
| 122995 | }else if( eOp & (WO_EQ|WO_IS) ){ |
| 122996 | int iCol = pProbe->aiColumn[saved_nEq]; |
| 122997 | pNew->wsFlags |= WHERE_COLUMN_EQ; |
| 122998 | assert( saved_nEq==pNew->u.btree.nEq ); |
| 122999 | if( iCol==(-1) || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){ |
| 123000 | if( iCol>=0 && pProbe->uniqNotNull==0 ){ |
| 123001 | pNew->wsFlags |= WHERE_UNQ_WANTED; |
| 123002 | }else{ |
| 123003 | pNew->wsFlags |= WHERE_ONEROW; |
| 123004 | } |
| @@ -123194,11 +123278,11 @@ | |
| 123194 | for(jj=0; jj<pIndex->nKeyCol; jj++){ |
| 123195 | if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; |
| 123196 | } |
| 123197 | }else if( (aColExpr = pIndex->aColExpr)!=0 ){ |
| 123198 | for(jj=0; jj<pIndex->nKeyCol; jj++){ |
| 123199 | if( pIndex->aiColumn[jj]!=(-2) ) continue; |
| 123200 | if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ |
| 123201 | return 1; |
| 123202 | } |
| 123203 | } |
| 123204 | } |
| @@ -123591,10 +123675,11 @@ | |
| 123591 | pIdxInfo->idxNum = 0; |
| 123592 | pIdxInfo->needToFreeIdxStr = 0; |
| 123593 | pIdxInfo->orderByConsumed = 0; |
| 123594 | pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; |
| 123595 | pIdxInfo->estimatedRows = 25; |
| 123596 | rc = vtabBestIndex(pParse, pTab, pIdxInfo); |
| 123597 | if( rc ) goto whereLoopAddVtab_exit; |
| 123598 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 123599 | pNew->prereq = mExtra; |
| 123600 | mxTerm = -1; |
| @@ -123636,10 +123721,11 @@ | |
| 123636 | ** consume the ORDER BY clause because (1) the order of IN terms |
| 123637 | ** is not necessarily related to the order of output terms and |
| 123638 | ** (2) Multiple outputs from a single IN value will not merge |
| 123639 | ** together. */ |
| 123640 | pIdxInfo->orderByConsumed = 0; |
| 123641 | } |
| 123642 | } |
| 123643 | } |
| 123644 | if( i>=nConstraint ){ |
| 123645 | pNew->nLTerm = mxTerm+1; |
| @@ -123651,10 +123737,18 @@ | |
| 123651 | pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? |
| 123652 | pIdxInfo->nOrderBy : 0); |
| 123653 | pNew->rSetup = 0; |
| 123654 | pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); |
| 123655 | pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); |
| 123656 | whereLoopInsert(pBuilder, pNew); |
| 123657 | if( pNew->u.vtab.needFree ){ |
| 123658 | sqlite3_free(pNew->u.vtab.idxStr); |
| 123659 | pNew->u.vtab.needFree = 0; |
| 123660 | } |
| @@ -123972,11 +124066,12 @@ | |
| 123972 | return 0; |
| 123973 | }else{ |
| 123974 | nKeyCol = pIndex->nKeyCol; |
| 123975 | nColumn = pIndex->nColumn; |
| 123976 | assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) ); |
| 123977 | assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable)); |
| 123978 | isOrderDistinct = IsUniqueIndex(pIndex); |
| 123979 | } |
| 123980 | |
| 123981 | /* Loop through all columns of the index and deal with the ones |
| 123982 | ** that are not constrained by == or IN. |
| @@ -124004,11 +124099,11 @@ | |
| 124004 | if( pIndex ){ |
| 124005 | iColumn = pIndex->aiColumn[j]; |
| 124006 | revIdx = pIndex->aSortOrder[j]; |
| 124007 | if( iColumn==pIndex->pTable->iPKey ) iColumn = -1; |
| 124008 | }else{ |
| 124009 | iColumn = -1; |
| 124010 | revIdx = 0; |
| 124011 | } |
| 124012 | |
| 124013 | /* An unconstrained column that might be NULL means that this |
| 124014 | ** WhereLoop is not well-ordered |
| @@ -124869,11 +124964,12 @@ | |
| 124869 | pWInfo->pOrderBy = pResultSet; |
| 124870 | } |
| 124871 | } |
| 124872 | |
| 124873 | /* Construct the WhereLoop objects */ |
| 124874 | WHERETRACE(0xffff,("*** Optimizer Start ***\n")); |
| 124875 | #if defined(WHERETRACE_ENABLED) |
| 124876 | if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ |
| 124877 | int i; |
| 124878 | for(i=0; i<sWLB.pWC->nTerm; i++){ |
| 124879 | whereTermPrint(&sWLB.pWC->a[i], i); |
| @@ -125303,10 +125399,11 @@ | |
| 125303 | int x = pOp->p2; |
| 125304 | assert( pIdx->pTable==pTab ); |
| 125305 | if( !HasRowid(pTab) ){ |
| 125306 | Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 125307 | x = pPk->aiColumn[x]; |
| 125308 | } |
| 125309 | x = sqlite3ColumnOfIndex(pIdx, x); |
| 125310 | if( x>=0 ){ |
| 125311 | pOp->p2 = x; |
| 125312 | pOp->p1 = pLevel->iIdxCur; |
| @@ -135127,10 +135224,11 @@ | |
| 135127 | } *aIndex; |
| 135128 | int nMaxPendingData; /* Max pending data before flush to disk */ |
| 135129 | int nPendingData; /* Current bytes of pending data */ |
| 135130 | sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ |
| 135131 | int iPrevLangid; /* Langid of recently inserted document */ |
| 135132 | |
| 135133 | #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) |
| 135134 | /* State variables used for validating that the transaction control |
| 135135 | ** methods of the virtual table are called at appropriate times. These |
| 135136 | ** values do not contribute to FTS functionality; they are used for |
| @@ -136701,10 +136799,23 @@ | |
| 136701 | if( sqlite3_libversion_number()>=3008002 ){ |
| 136702 | pIdxInfo->estimatedRows = nRow; |
| 136703 | } |
| 136704 | #endif |
| 136705 | } |
| 136706 | |
| 136707 | /* |
| 136708 | ** Implementation of the xBestIndex method for FTS3 tables. There |
| 136709 | ** are three possible strategies, in order of preference: |
| 136710 | ** |
| @@ -136791,10 +136902,13 @@ | |
| 136791 | iDocidLe = i; |
| 136792 | break; |
| 136793 | } |
| 136794 | } |
| 136795 | } |
| 136796 | |
| 136797 | iIdx = 1; |
| 136798 | if( iCons>=0 ){ |
| 136799 | pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; |
| 136800 | pInfo->aConstraintUsage[iCons].omit = 1; |
| @@ -146037,30 +146151,34 @@ | |
| 146037 | ** fts3PendingTermsAdd() are to add term/position-list pairs for the |
| 146038 | ** contents of the document with docid iDocid. |
| 146039 | */ |
| 146040 | static int fts3PendingTermsDocid( |
| 146041 | Fts3Table *p, /* Full-text table handle */ |
| 146042 | int iLangid, /* Language id of row being written */ |
| 146043 | sqlite_int64 iDocid /* Docid of row being written */ |
| 146044 | ){ |
| 146045 | assert( iLangid>=0 ); |
| 146046 | |
| 146047 | /* TODO(shess) Explore whether partially flushing the buffer on |
| 146048 | ** forced-flush would provide better performance. I suspect that if |
| 146049 | ** we ordered the doclists by size and flushed the largest until the |
| 146050 | ** buffer was half empty, that would let the less frequent terms |
| 146051 | ** generate longer doclists. |
| 146052 | */ |
| 146053 | if( iDocid<=p->iPrevDocid |
| 146054 | || p->iPrevLangid!=iLangid |
| 146055 | || p->nPendingData>p->nMaxPendingData |
| 146056 | ){ |
| 146057 | int rc = sqlite3Fts3PendingTermsFlush(p); |
| 146058 | if( rc!=SQLITE_OK ) return rc; |
| 146059 | } |
| 146060 | p->iPrevDocid = iDocid; |
| 146061 | p->iPrevLangid = iLangid; |
| 146062 | return SQLITE_OK; |
| 146063 | } |
| 146064 | |
| 146065 | /* |
| 146066 | ** Discard the contents of the pending-terms hash tables. |
| @@ -146246,11 +146364,12 @@ | |
| 146246 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); |
| 146247 | if( rc==SQLITE_OK ){ |
| 146248 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 146249 | int i; |
| 146250 | int iLangid = langidFromSelect(p, pSelect); |
| 146251 | rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); |
| 146252 | for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ |
| 146253 | int iCol = i-1; |
| 146254 | if( p->abNotindexed[iCol]==0 ){ |
| 146255 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 146256 | rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]); |
| @@ -146494,18 +146613,23 @@ | |
| 146494 | |
| 146495 | if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){ |
| 146496 | |
| 146497 | if( fts3SegReaderIsPending(pReader) ){ |
| 146498 | Fts3HashElem *pElem = *(pReader->ppNextElem); |
| 146499 | if( pElem==0 ){ |
| 146500 | pReader->aNode = 0; |
| 146501 | }else{ |
| 146502 | PendingList *pList = (PendingList *)fts3HashData(pElem); |
| 146503 | pReader->zTerm = (char *)fts3HashKey(pElem); |
| 146504 | pReader->nTerm = fts3HashKeysize(pElem); |
| 146505 | pReader->nNode = pReader->nDoclist = pList->nData + 1; |
| 146506 | pReader->aNode = pReader->aDoclist = pList->aData; |
| 146507 | pReader->ppNextElem++; |
| 146508 | assert( pReader->aNode ); |
| 146509 | } |
| 146510 | return SQLITE_OK; |
| 146511 | } |
| @@ -146741,16 +146865,18 @@ | |
| 146741 | /* |
| 146742 | ** Free all allocations associated with the iterator passed as the |
| 146743 | ** second argument. |
| 146744 | */ |
| 146745 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ |
| 146746 | if( pReader && !fts3SegReaderIsPending(pReader) ){ |
| 146747 | sqlite3_free(pReader->zTerm); |
| 146748 | if( !fts3SegReaderIsRootOnly(pReader) ){ |
| 146749 | sqlite3_free(pReader->aNode); |
| 146750 | sqlite3_blob_close(pReader->pBlob); |
| 146751 | } |
| 146752 | } |
| 146753 | sqlite3_free(pReader); |
| 146754 | } |
| 146755 | |
| 146756 | /* |
| @@ -148689,11 +148815,11 @@ | |
| 148689 | } |
| 148690 | |
| 148691 | while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 148692 | int iCol; |
| 148693 | int iLangid = langidFromSelect(p, pStmt); |
| 148694 | rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); |
| 148695 | memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); |
| 148696 | for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ |
| 148697 | if( p->abNotindexed[iCol]==0 ){ |
| 148698 | const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); |
| 148699 | rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); |
| @@ -150794,11 +150920,11 @@ | |
| 150794 | if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ |
| 150795 | rc = FTS_CORRUPT_VTAB; |
| 150796 | } |
| 150797 | } |
| 150798 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ |
| 150799 | rc = fts3PendingTermsDocid(p, iLangid, *pRowid); |
| 150800 | } |
| 150801 | if( rc==SQLITE_OK ){ |
| 150802 | assert( p->iPrevDocid==*pRowid ); |
| 150803 | rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); |
| 150804 | } |
| 150805 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -325,11 +325,11 @@ | |
| 325 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 326 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 327 | */ |
| 328 | #define SQLITE_VERSION "3.8.12" |
| 329 | #define SQLITE_VERSION_NUMBER 3008012 |
| 330 | #define SQLITE_SOURCE_ID "2015-10-01 18:31:29 6f90839e91024e2006042f5eb7f21ca5b47a9b4a" |
| 331 | |
| 332 | /* |
| 333 | ** CAPI3REF: Run-Time Library Version Numbers |
| 334 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 335 | ** |
| @@ -5845,18 +5845,36 @@ | |
| 5845 | ** indicates that the expense of the operation is similar to that of a |
| 5846 | ** binary search on a unique indexed field of an SQLite table with N rows. |
| 5847 | ** |
| 5848 | ** ^The estimatedRows value is an estimate of the number of rows that |
| 5849 | ** will be returned by the strategy. |
| 5850 | ** |
| 5851 | ** The xBestIndex method may optionally populate the idxFlags field with a |
| 5852 | ** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - |
| 5853 | ** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite |
| 5854 | ** assumes that the strategy may visit at most one row. |
| 5855 | ** |
| 5856 | ** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then |
| 5857 | ** SQLite also assumes that if a call to the xUpdate() method is made as |
| 5858 | ** part of the same statement to delete or update a virtual table row and the |
| 5859 | ** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback |
| 5860 | ** any database changes. In other words, if the xUpdate() returns |
| 5861 | ** SQLITE_CONSTRAINT, the database contents must be exactly as they were |
| 5862 | ** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not |
| 5863 | ** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by |
| 5864 | ** the xUpdate method are automatically rolled back by SQLite. |
| 5865 | ** |
| 5866 | ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info |
| 5867 | ** structure for SQLite version 3.8.2. If a virtual table extension is |
| 5868 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5869 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5870 | ** to included crashing the application). The estimatedRows field should |
| 5871 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5872 | ** value greater than or equal to 3008002. Similarly, the idxFlags field |
| 5873 | ** was added for version 3.8.12. It may therefore only be used if |
| 5874 | ** sqlite3_libversion_number() returns a value greater than or equal to |
| 5875 | ** 3008012. |
| 5876 | */ |
| 5877 | struct sqlite3_index_info { |
| 5878 | /* Inputs */ |
| 5879 | int nConstraint; /* Number of entries in aConstraint */ |
| 5880 | struct sqlite3_index_constraint { |
| @@ -5880,12 +5898,19 @@ | |
| 5898 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5899 | int orderByConsumed; /* True if output is already ordered */ |
| 5900 | double estimatedCost; /* Estimated cost of using this index */ |
| 5901 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5902 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5903 | /* Fields below are only available in SQLite 3.8.12 and later */ |
| 5904 | int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ |
| 5905 | }; |
| 5906 | |
| 5907 | /* |
| 5908 | ** CAPI3REF: Virtual Table Scan Flags |
| 5909 | */ |
| 5910 | #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ |
| 5911 | |
| 5912 | /* |
| 5913 | ** CAPI3REF: Virtual Table Constraint Operator Codes |
| 5914 | ** |
| 5915 | ** These macros defined the allowed values for the |
| 5916 | ** [sqlite3_index_info].aConstraint[].op field. Each value represents |
| @@ -11914,10 +11939,16 @@ | |
| 11939 | #define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY) |
| 11940 | |
| 11941 | /* Return true if index X is a UNIQUE index */ |
| 11942 | #define IsUniqueIndex(X) ((X)->onError!=OE_None) |
| 11943 | |
| 11944 | /* The Index.aiColumn[] values are normally positive integer. But |
| 11945 | ** there are some negative values that have special meaning: |
| 11946 | */ |
| 11947 | #define XN_ROWID (-1) /* Indexed column is the rowid */ |
| 11948 | #define XN_EXPR (-2) /* Indexed column is an expression */ |
| 11949 | |
| 11950 | /* |
| 11951 | ** Each sample stored in the sqlite_stat3 table is represented in memory |
| 11952 | ** using a structure of this type. See documentation at the top of the |
| 11953 | ** analyze.c source file for additional information. |
| 11954 | */ |
| @@ -13501,19 +13532,21 @@ | |
| 13532 | SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); |
| 13533 | SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); |
| 13534 | SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); |
| 13535 | SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); |
| 13536 | # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) |
| 13537 | # define sqlite3IsToplevel(p) ((p)->pToplevel==0) |
| 13538 | #else |
| 13539 | # define sqlite3TriggersExist(B,C,D,E,F) 0 |
| 13540 | # define sqlite3DeleteTrigger(A,B) |
| 13541 | # define sqlite3DropTriggerPtr(A,B) |
| 13542 | # define sqlite3UnlinkAndDeleteTrigger(A,B,C) |
| 13543 | # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) |
| 13544 | # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) |
| 13545 | # define sqlite3TriggerList(X, Y) 0 |
| 13546 | # define sqlite3ParseToplevel(p) p |
| 13547 | # define sqlite3IsToplevel(p) 1 |
| 13548 | # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 |
| 13549 | #endif |
| 13550 | |
| 13551 | SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); |
| 13552 | SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); |
| @@ -54599,11 +54632,11 @@ | |
| 54632 | if( rc==SQLITE_OK ){ |
| 54633 | btreeReleaseAllCursorPages(pCur); |
| 54634 | pCur->eState = CURSOR_REQUIRESEEK; |
| 54635 | } |
| 54636 | |
| 54637 | pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl|BTCF_AtLast); |
| 54638 | return rc; |
| 54639 | } |
| 54640 | |
| 54641 | /* Forward reference */ |
| 54642 | static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); |
| @@ -61562,11 +61595,11 @@ | |
| 61595 | ** It is critical that the child page be defragmented before being |
| 61596 | ** copied into the parent, because if the parent is page 1 then it will |
| 61597 | ** by smaller than the child due to the database header, and so all the |
| 61598 | ** free space needs to be up front. |
| 61599 | */ |
| 61600 | assert( nNew==1 || CORRUPT_DB ); |
| 61601 | rc = defragmentPage(apNew[0]); |
| 61602 | testcase( rc!=SQLITE_OK ); |
| 61603 | assert( apNew[0]->nFree == |
| 61604 | (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) |
| 61605 | || rc!=SQLITE_OK |
| @@ -79270,11 +79303,11 @@ | |
| 79303 | #endif |
| 79304 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 79305 | int j; |
| 79306 | for(j=0; j<pIdx->nKeyCol; j++){ |
| 79307 | /* FIXME: Be smarter about indexes that use expressions */ |
| 79308 | if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){ |
| 79309 | zFault = "indexed"; |
| 79310 | } |
| 79311 | } |
| 79312 | } |
| 79313 | if( zFault ){ |
| @@ -86848,19 +86881,19 @@ | |
| 86881 | int iTabCur, /* Cursor pointing to a table row */ |
| 86882 | int iIdxCol, /* The column of the index to be loaded */ |
| 86883 | int regOut /* Store the index column value in this register */ |
| 86884 | ){ |
| 86885 | i16 iTabCol = pIdx->aiColumn[iIdxCol]; |
| 86886 | if( iTabCol==XN_EXPR ){ |
| 86887 | assert( pIdx->aColExpr ); |
| 86888 | assert( pIdx->aColExpr->nExpr>iIdxCol ); |
| 86889 | pParse->iSelfTab = iTabCur; |
| 86890 | sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); |
| 86891 | }else{ |
| 86892 | sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur, |
| 86893 | iTabCol, regOut); |
| 86894 | } |
| 86895 | } |
| 86896 | |
| 86897 | /* |
| 86898 | ** Generate code to extract the value of the iCol-th column of a table. |
| 86899 | */ |
| @@ -92379,10 +92412,12 @@ | |
| 92412 | DbMaskTest(pParse->writeMask,iDb), /* P2 */ |
| 92413 | pParse->cookieValue[iDb], /* P3 */ |
| 92414 | db->aDb[iDb].pSchema->iGeneration /* P4 */ |
| 92415 | ); |
| 92416 | if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); |
| 92417 | VdbeComment((v, |
| 92418 | "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); |
| 92419 | } |
| 92420 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 92421 | for(i=0; i<pParse->nVtabLock; i++){ |
| 92422 | char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); |
| 92423 | sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); |
| @@ -95321,11 +95356,11 @@ | |
| 95356 | } |
| 95357 | |
| 95358 | /* Analyze the list of expressions that form the terms of the index and |
| 95359 | ** report any errors. In the common case where the expression is exactly |
| 95360 | ** a table column, store that column in aiColumn[]. For general expressions, |
| 95361 | ** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[]. |
| 95362 | ** |
| 95363 | ** TODO: Issue a warning if two or more columns of the index are identical. |
| 95364 | ** TODO: Issue a warning if the table primary key is used as part of the |
| 95365 | ** index key. |
| 95366 | */ |
| @@ -95350,12 +95385,12 @@ | |
| 95385 | if( !db->mallocFailed ){ |
| 95386 | assert( pCopy!=0 ); |
| 95387 | pListItem = &pCopy->a[i]; |
| 95388 | } |
| 95389 | } |
| 95390 | j = XN_EXPR; |
| 95391 | pIndex->aiColumn[i] = XN_EXPR; |
| 95392 | pIndex->uniqNotNull = 0; |
| 95393 | }else{ |
| 95394 | j = pCExpr->iColumn; |
| 95395 | assert( j<=0x7fff ); |
| 95396 | if( j<0 ){ |
| @@ -95404,11 +95439,11 @@ | |
| 95439 | i++; |
| 95440 | } |
| 95441 | } |
| 95442 | assert( i==pIndex->nColumn ); |
| 95443 | }else{ |
| 95444 | pIndex->aiColumn[i] = XN_ROWID; |
| 95445 | pIndex->azColl[i] = "BINARY"; |
| 95446 | } |
| 95447 | sqlite3DefaultRowEst(pIndex); |
| 95448 | if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); |
| 95449 | |
| @@ -97508,11 +97543,11 @@ | |
| 97543 | ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. |
| 97544 | */ |
| 97545 | pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); |
| 97546 | if( pWInfo==0 ) goto delete_from_cleanup; |
| 97547 | eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); |
| 97548 | assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); |
| 97549 | assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); |
| 97550 | |
| 97551 | /* Keep track of the number of rows to be deleted */ |
| 97552 | if( db->flags & SQLITE_CountRows ){ |
| 97553 | sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); |
| @@ -97519,11 +97554,11 @@ | |
| 97554 | } |
| 97555 | |
| 97556 | /* Extract the rowid or primary key for the current row */ |
| 97557 | if( pPk ){ |
| 97558 | for(i=0; i<nPk; i++){ |
| 97559 | assert( pPk->aiColumn[i]>=0 ); |
| 97560 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, |
| 97561 | pPk->aiColumn[i], iPk+i); |
| 97562 | } |
| 97563 | iKey = iPk; |
| 97564 | }else{ |
| @@ -97591,11 +97626,11 @@ | |
| 97626 | /* Set up a loop over the rowids/primary-keys that were found in the |
| 97627 | ** where-clause loop above. |
| 97628 | */ |
| 97629 | if( eOnePass!=ONEPASS_OFF ){ |
| 97630 | assert( nKey==nPk ); /* OP_Found will use an unpacked key */ |
| 97631 | if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ |
| 97632 | assert( pPk!=0 || pTab->pSelect!=0 ); |
| 97633 | sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); |
| 97634 | VdbeCoverage(v); |
| 97635 | } |
| 97636 | }else if( pPk ){ |
| @@ -97613,11 +97648,15 @@ | |
| 97648 | if( IsVirtual(pTab) ){ |
| 97649 | const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); |
| 97650 | sqlite3VtabMakeWritable(pParse, pTab); |
| 97651 | sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); |
| 97652 | sqlite3VdbeChangeP5(v, OE_Abort); |
| 97653 | assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); |
| 97654 | sqlite3MayAbort(pParse); |
| 97655 | if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ |
| 97656 | pParse->isMultiWrite = 0; |
| 97657 | } |
| 97658 | }else |
| 97659 | #endif |
| 97660 | { |
| 97661 | int count = (pParse->nested==0); /* True to count changes */ |
| 97662 | int iIdxNoSeek = -1; |
| @@ -97951,11 +97990,11 @@ | |
| 97990 | regBase = sqlite3GetTempRange(pParse, nCol); |
| 97991 | if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0; |
| 97992 | for(j=0; j<nCol; j++){ |
| 97993 | if( pPrior |
| 97994 | && pPrior->aiColumn[j]==pIdx->aiColumn[j] |
| 97995 | && pPrior->aiColumn[j]!=XN_EXPR |
| 97996 | ){ |
| 97997 | /* This column was already computed by the previous index */ |
| 97998 | continue; |
| 97999 | } |
| 98000 | sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); |
| @@ -100039,10 +100078,12 @@ | |
| 100078 | for(i=0; i<nCol; i++){ |
| 100079 | i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */ |
| 100080 | char *zDfltColl; /* Def. collation for column */ |
| 100081 | char *zIdxCol; /* Name of indexed column */ |
| 100082 | |
| 100083 | if( iCol<0 ) break; /* No foreign keys against expression indexes */ |
| 100084 | |
| 100085 | /* If the index uses a collation sequence that is different from |
| 100086 | ** the default collation sequence for the column, this index is |
| 100087 | ** unusable. Bail out early in this case. */ |
| 100088 | zDfltColl = pParent->aCol[iCol].zColl; |
| 100089 | if( !zDfltColl ){ |
| @@ -100191,10 +100232,11 @@ | |
| 100232 | if( pTab==pFKey->pFrom && nIncr==1 ){ |
| 100233 | int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; |
| 100234 | for(i=0; i<nCol; i++){ |
| 100235 | int iChild = aiCol[i]+1+regData; |
| 100236 | int iParent = pIdx->aiColumn[i]+1+regData; |
| 100237 | assert( pIdx->aiColumn[i]>=0 ); |
| 100238 | assert( aiCol[i]!=pTab->iPKey ); |
| 100239 | if( pIdx->aiColumn[i]==pTab->iPKey ){ |
| 100240 | /* The parent key is a composite key that includes the IPK column */ |
| 100241 | iParent = regData; |
| 100242 | } |
| @@ -100399,10 +100441,11 @@ | |
| 100441 | Expr *pEq, *pAll = 0; |
| 100442 | Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 100443 | assert( pIdx!=0 ); |
| 100444 | for(i=0; i<pPk->nKeyCol; i++){ |
| 100445 | i16 iCol = pIdx->aiColumn[i]; |
| 100446 | assert( iCol>=0 ); |
| 100447 | pLeft = exprTableRegister(pParse, pTab, regData, iCol); |
| 100448 | pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); |
| 100449 | pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); |
| 100450 | pAll = sqlite3ExprAnd(db, pAll, pEq); |
| 100451 | } |
| @@ -100718,10 +100761,11 @@ | |
| 100761 | } |
| 100762 | for(i=0; i<pFKey->nCol; i++){ |
| 100763 | if( aiCol[i]==pTab->iPKey ){ |
| 100764 | aiCol[i] = -1; |
| 100765 | } |
| 100766 | assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); |
| 100767 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 100768 | /* Request permission to read the parent key columns. If the |
| 100769 | ** authorization callback returns SQLITE_IGNORE, behave as if any |
| 100770 | ** values read from the parent table are NULL. */ |
| 100771 | if( db->xAuth ){ |
| @@ -100849,11 +100893,14 @@ | |
| 100893 | } |
| 100894 | for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 100895 | Index *pIdx = 0; |
| 100896 | sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); |
| 100897 | if( pIdx ){ |
| 100898 | for(i=0; i<pIdx->nKeyCol; i++){ |
| 100899 | assert( pIdx->aiColumn[i]>=0 ); |
| 100900 | mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
| 100901 | } |
| 100902 | } |
| 100903 | } |
| 100904 | } |
| 100905 | return mask; |
| 100906 | } |
| @@ -100972,10 +101019,11 @@ | |
| 101019 | Expr *pEq; /* tFromCol = OLD.tToCol */ |
| 101020 | |
| 101021 | iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
| 101022 | assert( iFromCol>=0 ); |
| 101023 | assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); |
| 101024 | assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); |
| 101025 | tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; |
| 101026 | tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; |
| 101027 | |
| 101028 | tToCol.n = sqlite3Strlen30(tToCol.z); |
| 101029 | tFromCol.n = sqlite3Strlen30(tFromCol.z); |
| @@ -101281,15 +101329,15 @@ | |
| 101329 | } |
| 101330 | for(n=0; n<pIdx->nColumn; n++){ |
| 101331 | i16 x = pIdx->aiColumn[n]; |
| 101332 | if( x>=0 ){ |
| 101333 | pIdx->zColAff[n] = pTab->aCol[x].affinity; |
| 101334 | }else if( x==XN_ROWID ){ |
| 101335 | pIdx->zColAff[n] = SQLITE_AFF_INTEGER; |
| 101336 | }else{ |
| 101337 | char aff; |
| 101338 | assert( x==XN_EXPR ); |
| 101339 | assert( pIdx->aColExpr!=0 ); |
| 101340 | aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); |
| 101341 | if( aff==0 ) aff = SQLITE_AFF_BLOB; |
| 101342 | pIdx->zColAff[n] = aff; |
| 101343 | } |
| @@ -101451,11 +101499,11 @@ | |
| 101499 | Vdbe *v = pParse->pVdbe; /* VDBE under construction */ |
| 101500 | |
| 101501 | /* This routine is never called during trigger-generation. It is |
| 101502 | ** only called from the top-level */ |
| 101503 | assert( pParse->pTriggerTab==0 ); |
| 101504 | assert( sqlite3IsToplevel(pParse) ); |
| 101505 | |
| 101506 | assert( v ); /* We failed long ago if this is not so */ |
| 101507 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 101508 | pDb = &db->aDb[p->iDb]; |
| 101509 | memId = p->regCtr; |
| @@ -102599,17 +102647,17 @@ | |
| 102647 | */ |
| 102648 | regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn); |
| 102649 | for(i=0; i<pIdx->nColumn; i++){ |
| 102650 | int iField = pIdx->aiColumn[i]; |
| 102651 | int x; |
| 102652 | if( iField==XN_EXPR ){ |
| 102653 | pParse->ckBase = regNewData+1; |
| 102654 | sqlite3ExprCode(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); |
| 102655 | pParse->ckBase = 0; |
| 102656 | VdbeComment((v, "%s column %d", pIdx->zName, i)); |
| 102657 | }else{ |
| 102658 | if( iField==XN_ROWID || iField==pTab->iPKey ){ |
| 102659 | if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */ |
| 102660 | x = regNewData; |
| 102661 | regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i; |
| 102662 | }else{ |
| 102663 | x = iField + regNewData + 1; |
| @@ -102664,10 +102712,11 @@ | |
| 102712 | int x; |
| 102713 | /* Extract the PRIMARY KEY from the end of the index entry and |
| 102714 | ** store it in registers regR..regR+nPk-1 */ |
| 102715 | if( pIdx!=pPk ){ |
| 102716 | for(i=0; i<pPk->nKeyCol; i++){ |
| 102717 | assert( pPk->aiColumn[i]>=0 ); |
| 102718 | x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); |
| 102719 | sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); |
| 102720 | VdbeComment((v, "%s.%s", pTab->zName, |
| 102721 | pTab->aCol[pPk->aiColumn[i]].zName)); |
| 102722 | } |
| @@ -102685,10 +102734,11 @@ | |
| 102734 | int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR); |
| 102735 | |
| 102736 | for(i=0; i<pPk->nKeyCol; i++){ |
| 102737 | char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); |
| 102738 | x = pPk->aiColumn[i]; |
| 102739 | assert( x>=0 ); |
| 102740 | if( i==(pPk->nKeyCol-1) ){ |
| 102741 | addrJump = addrUniqueOk; |
| 102742 | op = OP_Eq; |
| 102743 | } |
| 102744 | sqlite3VdbeAddOp4(v, op, |
| @@ -102936,11 +102986,11 @@ | |
| 102986 | } |
| 102987 | for(i=0; i<pSrc->nKeyCol; i++){ |
| 102988 | if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ |
| 102989 | return 0; /* Different columns indexed */ |
| 102990 | } |
| 102991 | if( pSrc->aiColumn[i]==XN_EXPR ){ |
| 102992 | assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 ); |
| 102993 | if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr, |
| 102994 | pDest->aColExpr->a[i].pExpr, -1)!=0 ){ |
| 102995 | return 0; /* Different expressions in the index */ |
| 102996 | } |
| @@ -106741,11 +106791,11 @@ | |
| 106791 | int uniqOk = sqlite3VdbeMakeLabel(v); |
| 106792 | int jmp6; |
| 106793 | int kk; |
| 106794 | for(kk=0; kk<pIdx->nKeyCol; kk++){ |
| 106795 | int iCol = pIdx->aiColumn[kk]; |
| 106796 | assert( iCol!=XN_ROWID && iCol<pTab->nCol ); |
| 106797 | if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; |
| 106798 | sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); |
| 106799 | VdbeCoverage(v); |
| 106800 | } |
| 106801 | jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); |
| @@ -112261,21 +112311,13 @@ | |
| 112311 | ** an entry of the FROM clause is a subquery instead of a table or view, |
| 112312 | ** then create a transient table structure to describe the subquery. |
| 112313 | */ |
| 112314 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 112315 | Table *pTab; |
| 112316 | assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 ); |
| 112317 | if( pFrom->fg.isRecursive ) continue; |
| 112318 | assert( pFrom->pTab==0 ); |
| 112319 | #ifndef SQLITE_OMIT_CTE |
| 112320 | if( withExpand(pWalker, pFrom) ) return WRC_Abort; |
| 112321 | if( pFrom->pTab ) {} else |
| 112322 | #endif |
| 112323 | if( pFrom->zName==0 ){ |
| @@ -112563,23 +112605,23 @@ | |
| 112605 | int i; |
| 112606 | SrcList *pTabList; |
| 112607 | struct SrcList_item *pFrom; |
| 112608 | |
| 112609 | assert( p->selFlags & SF_Resolved ); |
| 112610 | assert( (p->selFlags & SF_HasTypeInfo)==0 ); |
| 112611 | p->selFlags |= SF_HasTypeInfo; |
| 112612 | pParse = pWalker->pParse; |
| 112613 | pTabList = p->pSrc; |
| 112614 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 112615 | Table *pTab = pFrom->pTab; |
| 112616 | assert( pTab!=0 ); |
| 112617 | if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
| 112618 | /* A sub-query in the FROM clause of a SELECT */ |
| 112619 | Select *pSel = pFrom->pSelect; |
| 112620 | if( pSel ){ |
| 112621 | while( pSel->pPrior ) pSel = pSel->pPrior; |
| 112622 | selectAddColumnTypeAndCollation(pParse, pTab, pSel); |
| 112623 | } |
| 112624 | } |
| 112625 | } |
| 112626 | } |
| 112627 | #endif |
| @@ -115133,13 +115175,13 @@ | |
| 115175 | int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */ |
| 115176 | int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ |
| 115177 | |
| 115178 | /* Register Allocations */ |
| 115179 | int regRowCount = 0; /* A count of rows changed */ |
| 115180 | int regOldRowid = 0; /* The old rowid */ |
| 115181 | int regNewRowid = 0; /* The new rowid */ |
| 115182 | int regNew = 0; /* Content of the NEW.* table in triggers */ |
| 115183 | int regOld = 0; /* Content of OLD.* table in triggers */ |
| 115184 | int regRowSet = 0; /* Rowset of rows to be updated */ |
| 115185 | int regKey = 0; /* composite PRIMARY KEY value */ |
| 115186 | |
| 115187 | memset(&sContext, 0, sizeof(sContext)); |
| @@ -115299,33 +115341,24 @@ | |
| 115341 | v = sqlite3GetVdbe(pParse); |
| 115342 | if( v==0 ) goto update_cleanup; |
| 115343 | if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); |
| 115344 | sqlite3BeginWriteOperation(pParse, 1, iDb); |
| 115345 | |
| 115346 | /* Allocate required registers. */ |
| 115347 | if( !IsVirtual(pTab) ){ |
| 115348 | regRowSet = ++pParse->nMem; |
| 115349 | regOldRowid = regNewRowid = ++pParse->nMem; |
| 115350 | if( chngPk || pTrigger || hasFK ){ |
| 115351 | regOld = pParse->nMem + 1; |
| 115352 | pParse->nMem += pTab->nCol; |
| 115353 | } |
| 115354 | if( chngKey || pTrigger || hasFK ){ |
| 115355 | regNewRowid = ++pParse->nMem; |
| 115356 | } |
| 115357 | regNew = pParse->nMem + 1; |
| 115358 | pParse->nMem += pTab->nCol; |
| 115359 | } |
| 115360 | |
| 115361 | /* Start the view context. */ |
| 115362 | if( isView ){ |
| 115363 | sqlite3AuthContextPush(pParse, &sContext, pTab->zName); |
| 115364 | } |
| @@ -115343,10 +115376,19 @@ | |
| 115376 | ** WHERE clause. |
| 115377 | */ |
| 115378 | if( sqlite3ResolveExprNames(&sNC, pWhere) ){ |
| 115379 | goto update_cleanup; |
| 115380 | } |
| 115381 | |
| 115382 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 115383 | /* Virtual tables must be handled separately */ |
| 115384 | if( IsVirtual(pTab) ){ |
| 115385 | updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, |
| 115386 | pWhere, onError); |
| 115387 | goto update_cleanup; |
| 115388 | } |
| 115389 | #endif |
| 115390 | |
| 115391 | /* Begin the database scan |
| 115392 | */ |
| 115393 | if( HasRowid(pTab) ){ |
| 115394 | sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); |
| @@ -115383,11 +115425,11 @@ | |
| 115425 | pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, |
| 115426 | WHERE_ONEPASS_DESIRED, iIdxCur); |
| 115427 | if( pWInfo==0 ) goto update_cleanup; |
| 115428 | okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); |
| 115429 | for(i=0; i<nPk; i++){ |
| 115430 | assert( pPk->aiColumn[i]>=0 ); |
| 115431 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i], |
| 115432 | iPk+i); |
| 115433 | } |
| 115434 | if( okOnePass ){ |
| 115435 | sqlite3VdbeChangeToNoop(v, addrOpen); |
| @@ -115506,11 +115548,10 @@ | |
| 115548 | ** be used eliminates some redundant opcodes. |
| 115549 | */ |
| 115550 | newmask = sqlite3TriggerColmask( |
| 115551 | pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError |
| 115552 | ); |
| 115553 | for(i=0; i<pTab->nCol; i++){ |
| 115554 | if( i==pTab->iPKey ){ |
| 115555 | sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); |
| 115556 | }else{ |
| 115557 | j = aXRef[i]; |
| @@ -115684,25 +115725,27 @@ | |
| 115725 | |
| 115726 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 115727 | /* |
| 115728 | ** Generate code for an UPDATE of a virtual table. |
| 115729 | ** |
| 115730 | ** There are two possible strategies - the default and the special |
| 115731 | ** "onepass" strategy. Onepass is only used if the virtual table |
| 115732 | ** implementation indicates that pWhere may match at most one row. |
| 115733 | ** |
| 115734 | ** The default strategy is to create an ephemeral table that contains |
| 115735 | ** for each row to be changed: |
| 115736 | ** |
| 115737 | ** (A) The original rowid of that row. |
| 115738 | ** (B) The revised rowid for the row. |
| 115739 | ** (C) The content of every column in the row. |
| 115740 | ** |
| 115741 | ** Then loop through the contents of this ephemeral table executing a |
| 115742 | ** VUpdate for each row. When finished, drop the ephemeral table. |
| 115743 | ** |
| 115744 | ** The "onepass" strategy does not use an ephemeral table. Instead, it |
| 115745 | ** stores the same values (A, B and C above) in a register array and |
| 115746 | ** makes a single invocation of VUpdate. |
| 115747 | */ |
| 115748 | static void updateVirtualTable( |
| 115749 | Parse *pParse, /* The parsing context */ |
| 115750 | SrcList *pSrc, /* The virtual table to be modified */ |
| 115751 | Table *pTab, /* The virtual table */ |
| @@ -115711,70 +115754,100 @@ | |
| 115754 | int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ |
| 115755 | Expr *pWhere, /* WHERE clause of the UPDATE statement */ |
| 115756 | int onError /* ON CONFLICT strategy */ |
| 115757 | ){ |
| 115758 | Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ |
| 115759 | int ephemTab; /* Table holding the result of the SELECT */ |
| 115760 | int i; /* Loop counter */ |
| 115761 | sqlite3 *db = pParse->db; /* Database connection */ |
| 115762 | const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); |
| 115763 | WhereInfo *pWInfo; |
| 115764 | int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */ |
| 115765 | int regArg; /* First register in VUpdate arg array */ |
| 115766 | int regRec; /* Register in which to assemble record */ |
| 115767 | int regRowid; /* Register for ephem table rowid */ |
| 115768 | int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ |
| 115769 | int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ |
| 115770 | int bOnePass; /* True to use onepass strategy */ |
| 115771 | int addr; /* Address of OP_OpenEphemeral */ |
| 115772 | |
| 115773 | /* Allocate nArg registers to martial the arguments to VUpdate. Then |
| 115774 | ** create and open the ephemeral table in which the records created from |
| 115775 | ** these arguments will be temporarily stored. */ |
| 115776 | assert( v ); |
| 115777 | ephemTab = pParse->nTab++; |
| 115778 | addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg); |
| 115779 | regArg = pParse->nMem + 1; |
| 115780 | pParse->nMem += nArg; |
| 115781 | regRec = ++pParse->nMem; |
| 115782 | regRowid = ++pParse->nMem; |
| 115783 | |
| 115784 | /* Start scanning the virtual table */ |
| 115785 | pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0); |
| 115786 | if( pWInfo==0 ) return; |
| 115787 | |
| 115788 | /* Populate the argument registers. */ |
| 115789 | sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); |
| 115790 | if( pRowid ){ |
| 115791 | sqlite3ExprCode(pParse, pRowid, regArg+1); |
| 115792 | }else{ |
| 115793 | sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); |
| 115794 | } |
| 115795 | for(i=0; i<pTab->nCol; i++){ |
| 115796 | if( aXRef[i]>=0 ){ |
| 115797 | sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); |
| 115798 | }else{ |
| 115799 | sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); |
| 115800 | } |
| 115801 | } |
| 115802 | |
| 115803 | bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); |
| 115804 | |
| 115805 | if( bOnePass ){ |
| 115806 | /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded |
| 115807 | ** above. Also, if this is a top-level parse (not a trigger), clear the |
| 115808 | ** multi-write flag so that the VM does not open a statement journal */ |
| 115809 | sqlite3VdbeChangeToNoop(v, addr); |
| 115810 | if( sqlite3IsToplevel(pParse) ){ |
| 115811 | pParse->isMultiWrite = 0; |
| 115812 | } |
| 115813 | }else{ |
| 115814 | /* Create a record from the argument register contents and insert it into |
| 115815 | ** the ephemeral table. */ |
| 115816 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); |
| 115817 | sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); |
| 115818 | sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); |
| 115819 | } |
| 115820 | |
| 115821 | |
| 115822 | if( bOnePass==0 ){ |
| 115823 | /* End the virtual table scan */ |
| 115824 | sqlite3WhereEnd(pWInfo); |
| 115825 | |
| 115826 | /* Begin scannning through the ephemeral table. */ |
| 115827 | addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v); |
| 115828 | |
| 115829 | /* Extract arguments from the current row of the ephemeral table and |
| 115830 | ** invoke the VUpdate method. */ |
| 115831 | for(i=0; i<nArg; i++){ |
| 115832 | sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i); |
| 115833 | } |
| 115834 | } |
| 115835 | sqlite3VtabMakeWritable(pParse, pTab); |
| 115836 | sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB); |
| 115837 | sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); |
| 115838 | sqlite3MayAbort(pParse); |
| 115839 | |
| 115840 | /* End of the ephemeral table scan. Or, if using the onepass strategy, |
| 115841 | ** jump to here if the scan visited zero rows. */ |
| 115842 | if( bOnePass==0 ){ |
| 115843 | sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); |
| 115844 | sqlite3VdbeJumpHere(v, addr); |
| 115845 | sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); |
| 115846 | }else{ |
| 115847 | sqlite3WhereEnd(pWInfo); |
| 115848 | } |
| 115849 | } |
| 115850 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 115851 | |
| 115852 | /************** End of update.c **********************************************/ |
| 115853 | /************** Begin file vacuum.c ******************************************/ |
| @@ -117091,11 +117164,13 @@ | |
| 117164 | ** sqlite3.aVTrans[] array. */ |
| 117165 | rc = growVTrans(db); |
| 117166 | if( rc==SQLITE_OK ){ |
| 117167 | rc = pModule->xBegin(pVTab->pVtab); |
| 117168 | if( rc==SQLITE_OK ){ |
| 117169 | int iSvpt = db->nStatement + db->nSavepoint; |
| 117170 | addToVTrans(db, pVTab); |
| 117171 | if( iSvpt ) rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, iSvpt-1); |
| 117172 | } |
| 117173 | } |
| 117174 | } |
| 117175 | return rc; |
| 117176 | } |
| @@ -117949,12 +118024,12 @@ | |
| 118024 | /* |
| 118025 | ** Return the name of the i-th column of the pIdx index. |
| 118026 | */ |
| 118027 | static const char *explainIndexColumnName(Index *pIdx, int i){ |
| 118028 | i = pIdx->aiColumn[i]; |
| 118029 | if( i==XN_EXPR ) return "<expr>"; |
| 118030 | if( i==XN_ROWID ) return "rowid"; |
| 118031 | return pIdx->pTable->aCol[i].zName; |
| 118032 | } |
| 118033 | |
| 118034 | /* |
| 118035 | ** Argument pLevel describes a strategy for scanning table pTab. This |
| @@ -118417,11 +118492,11 @@ | |
| 118492 | VdbeCoverageIf(v, bRev==0); |
| 118493 | VdbeCoverageIf(v, bRev!=0); |
| 118494 | sqlite3VdbeJumpHere(v, j); |
| 118495 | for(j=0; j<nSkip; j++){ |
| 118496 | sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j); |
| 118497 | testcase( pIdx->aiColumn[j]==XN_EXPR ); |
| 118498 | VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); |
| 118499 | } |
| 118500 | } |
| 118501 | |
| 118502 | /* Evaluate the equality constraints |
| @@ -118603,12 +118678,12 @@ | |
| 118678 | for(j=0; j<nConstraint && j<16; j++){ |
| 118679 | if( (pLoop->u.vtab.omitMask>>j)&1 ){ |
| 118680 | disableTerm(pLevel, pLoop->aLTerm[j]); |
| 118681 | } |
| 118682 | } |
| 118683 | pLevel->p1 = iCur; |
| 118684 | pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; |
| 118685 | pLevel->p2 = sqlite3VdbeCurrentAddr(v); |
| 118686 | sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); |
| 118687 | sqlite3ExprCachePop(pParse); |
| 118688 | }else |
| 118689 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| @@ -120846,10 +120921,17 @@ | |
| 120921 | ** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is |
| 120922 | ** unable to use the ONEPASS optimization. |
| 120923 | */ |
| 120924 | SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){ |
| 120925 | memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); |
| 120926 | #ifdef WHERETRACE_ENABLED |
| 120927 | if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){ |
| 120928 | sqlite3DebugPrintf("%s cursors: %d %d\n", |
| 120929 | pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI", |
| 120930 | aiCur[0], aiCur[1]); |
| 120931 | } |
| 120932 | #endif |
| 120933 | return pWInfo->eOnePass; |
| 120934 | } |
| 120935 | |
| 120936 | /* |
| 120937 | ** Move the content of pSrc into pDest |
| @@ -120941,16 +121023,16 @@ | |
| 121023 | int k = pScan->k; /* Where to start scanning */ |
| 121024 | |
| 121025 | while( pScan->iEquiv<=pScan->nEquiv ){ |
| 121026 | iCur = pScan->aiCur[pScan->iEquiv-1]; |
| 121027 | iColumn = pScan->aiColumn[pScan->iEquiv-1]; |
| 121028 | if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; |
| 121029 | while( (pWC = pScan->pWC)!=0 ){ |
| 121030 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 121031 | if( pTerm->leftCursor==iCur |
| 121032 | && pTerm->u.leftColumn==iColumn |
| 121033 | && (iColumn!=XN_EXPR |
| 121034 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| 121035 | && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) |
| 121036 | ){ |
| 121037 | if( (pTerm->eOperator & WO_EQUIV)!=0 |
| 121038 | && pScan->nEquiv<ArraySize(pScan->aiCur) |
| @@ -121040,11 +121122,11 @@ | |
| 121122 | pScan->pWC = pWC; |
| 121123 | pScan->pIdxExpr = 0; |
| 121124 | if( pIdx ){ |
| 121125 | j = iColumn; |
| 121126 | iColumn = pIdx->aiColumn[j]; |
| 121127 | if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; |
| 121128 | } |
| 121129 | if( pIdx && iColumn>=0 ){ |
| 121130 | pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; |
| 121131 | pScan->zCollName = pIdx->azColl[j]; |
| 121132 | }else{ |
| @@ -121479,11 +121561,11 @@ | |
| 121561 | pIdx->azColl[n] = "BINARY"; |
| 121562 | n++; |
| 121563 | } |
| 121564 | } |
| 121565 | assert( n==nKeyCol ); |
| 121566 | pIdx->aiColumn[n] = XN_ROWID; |
| 121567 | pIdx->azColl[n] = "BINARY"; |
| 121568 | |
| 121569 | /* Create the automatic index */ |
| 121570 | assert( pLevel->iIdxCur>=0 ); |
| 121571 | pLevel->iIdxCur = pParse->nTab++; |
| @@ -122994,11 +123076,13 @@ | |
| 123076 | |
| 123077 | }else if( eOp & (WO_EQ|WO_IS) ){ |
| 123078 | int iCol = pProbe->aiColumn[saved_nEq]; |
| 123079 | pNew->wsFlags |= WHERE_COLUMN_EQ; |
| 123080 | assert( saved_nEq==pNew->u.btree.nEq ); |
| 123081 | if( iCol==XN_ROWID |
| 123082 | || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) |
| 123083 | ){ |
| 123084 | if( iCol>=0 && pProbe->uniqNotNull==0 ){ |
| 123085 | pNew->wsFlags |= WHERE_UNQ_WANTED; |
| 123086 | }else{ |
| 123087 | pNew->wsFlags |= WHERE_ONEROW; |
| 123088 | } |
| @@ -123194,11 +123278,11 @@ | |
| 123278 | for(jj=0; jj<pIndex->nKeyCol; jj++){ |
| 123279 | if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; |
| 123280 | } |
| 123281 | }else if( (aColExpr = pIndex->aColExpr)!=0 ){ |
| 123282 | for(jj=0; jj<pIndex->nKeyCol; jj++){ |
| 123283 | if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; |
| 123284 | if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ |
| 123285 | return 1; |
| 123286 | } |
| 123287 | } |
| 123288 | } |
| @@ -123591,10 +123675,11 @@ | |
| 123675 | pIdxInfo->idxNum = 0; |
| 123676 | pIdxInfo->needToFreeIdxStr = 0; |
| 123677 | pIdxInfo->orderByConsumed = 0; |
| 123678 | pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; |
| 123679 | pIdxInfo->estimatedRows = 25; |
| 123680 | pIdxInfo->idxFlags = 0; |
| 123681 | rc = vtabBestIndex(pParse, pTab, pIdxInfo); |
| 123682 | if( rc ) goto whereLoopAddVtab_exit; |
| 123683 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 123684 | pNew->prereq = mExtra; |
| 123685 | mxTerm = -1; |
| @@ -123636,10 +123721,11 @@ | |
| 123721 | ** consume the ORDER BY clause because (1) the order of IN terms |
| 123722 | ** is not necessarily related to the order of output terms and |
| 123723 | ** (2) Multiple outputs from a single IN value will not merge |
| 123724 | ** together. */ |
| 123725 | pIdxInfo->orderByConsumed = 0; |
| 123726 | pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; |
| 123727 | } |
| 123728 | } |
| 123729 | } |
| 123730 | if( i>=nConstraint ){ |
| 123731 | pNew->nLTerm = mxTerm+1; |
| @@ -123651,10 +123737,18 @@ | |
| 123737 | pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? |
| 123738 | pIdxInfo->nOrderBy : 0); |
| 123739 | pNew->rSetup = 0; |
| 123740 | pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); |
| 123741 | pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); |
| 123742 | |
| 123743 | /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated |
| 123744 | ** that the scan will visit at most one row. Clear it otherwise. */ |
| 123745 | if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){ |
| 123746 | pNew->wsFlags |= WHERE_ONEROW; |
| 123747 | }else{ |
| 123748 | pNew->wsFlags &= ~WHERE_ONEROW; |
| 123749 | } |
| 123750 | whereLoopInsert(pBuilder, pNew); |
| 123751 | if( pNew->u.vtab.needFree ){ |
| 123752 | sqlite3_free(pNew->u.vtab.idxStr); |
| 123753 | pNew->u.vtab.needFree = 0; |
| 123754 | } |
| @@ -123972,11 +124066,12 @@ | |
| 124066 | return 0; |
| 124067 | }else{ |
| 124068 | nKeyCol = pIndex->nKeyCol; |
| 124069 | nColumn = pIndex->nColumn; |
| 124070 | assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) ); |
| 124071 | assert( pIndex->aiColumn[nColumn-1]==XN_ROWID |
| 124072 | || !HasRowid(pIndex->pTable)); |
| 124073 | isOrderDistinct = IsUniqueIndex(pIndex); |
| 124074 | } |
| 124075 | |
| 124076 | /* Loop through all columns of the index and deal with the ones |
| 124077 | ** that are not constrained by == or IN. |
| @@ -124004,11 +124099,11 @@ | |
| 124099 | if( pIndex ){ |
| 124100 | iColumn = pIndex->aiColumn[j]; |
| 124101 | revIdx = pIndex->aSortOrder[j]; |
| 124102 | if( iColumn==pIndex->pTable->iPKey ) iColumn = -1; |
| 124103 | }else{ |
| 124104 | iColumn = XN_ROWID; |
| 124105 | revIdx = 0; |
| 124106 | } |
| 124107 | |
| 124108 | /* An unconstrained column that might be NULL means that this |
| 124109 | ** WhereLoop is not well-ordered |
| @@ -124869,11 +124964,12 @@ | |
| 124964 | pWInfo->pOrderBy = pResultSet; |
| 124965 | } |
| 124966 | } |
| 124967 | |
| 124968 | /* Construct the WhereLoop objects */ |
| 124969 | WHERETRACE(0xffff,("*** Optimizer Start *** (wctrlFlags: 0x%x)\n", |
| 124970 | wctrlFlags)); |
| 124971 | #if defined(WHERETRACE_ENABLED) |
| 124972 | if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ |
| 124973 | int i; |
| 124974 | for(i=0; i<sWLB.pWC->nTerm; i++){ |
| 124975 | whereTermPrint(&sWLB.pWC->a[i], i); |
| @@ -125303,10 +125399,11 @@ | |
| 125399 | int x = pOp->p2; |
| 125400 | assert( pIdx->pTable==pTab ); |
| 125401 | if( !HasRowid(pTab) ){ |
| 125402 | Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 125403 | x = pPk->aiColumn[x]; |
| 125404 | assert( x>=0 ); |
| 125405 | } |
| 125406 | x = sqlite3ColumnOfIndex(pIdx, x); |
| 125407 | if( x>=0 ){ |
| 125408 | pOp->p2 = x; |
| 125409 | pOp->p1 = pLevel->iIdxCur; |
| @@ -135127,10 +135224,11 @@ | |
| 135224 | } *aIndex; |
| 135225 | int nMaxPendingData; /* Max pending data before flush to disk */ |
| 135226 | int nPendingData; /* Current bytes of pending data */ |
| 135227 | sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ |
| 135228 | int iPrevLangid; /* Langid of recently inserted document */ |
| 135229 | int bPrevDelete; /* True if last operation was a delete */ |
| 135230 | |
| 135231 | #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) |
| 135232 | /* State variables used for validating that the transaction control |
| 135233 | ** methods of the virtual table are called at appropriate times. These |
| 135234 | ** values do not contribute to FTS functionality; they are used for |
| @@ -136701,10 +136799,23 @@ | |
| 136799 | if( sqlite3_libversion_number()>=3008002 ){ |
| 136800 | pIdxInfo->estimatedRows = nRow; |
| 136801 | } |
| 136802 | #endif |
| 136803 | } |
| 136804 | |
| 136805 | /* |
| 136806 | ** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this |
| 136807 | ** extension is currently being used by a version of SQLite too old to |
| 136808 | ** support index-info flags. In that case this function is a no-op. |
| 136809 | */ |
| 136810 | static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ |
| 136811 | #if SQLITE_VERSION_NUMBER>=3008012 |
| 136812 | if( sqlite3_libversion_number()>=3008012 ){ |
| 136813 | pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; |
| 136814 | } |
| 136815 | #endif |
| 136816 | } |
| 136817 | |
| 136818 | /* |
| 136819 | ** Implementation of the xBestIndex method for FTS3 tables. There |
| 136820 | ** are three possible strategies, in order of preference: |
| 136821 | ** |
| @@ -136791,10 +136902,13 @@ | |
| 136902 | iDocidLe = i; |
| 136903 | break; |
| 136904 | } |
| 136905 | } |
| 136906 | } |
| 136907 | |
| 136908 | /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */ |
| 136909 | if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo); |
| 136910 | |
| 136911 | iIdx = 1; |
| 136912 | if( iCons>=0 ){ |
| 136913 | pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; |
| 136914 | pInfo->aConstraintUsage[iCons].omit = 1; |
| @@ -146037,30 +146151,34 @@ | |
| 146151 | ** fts3PendingTermsAdd() are to add term/position-list pairs for the |
| 146152 | ** contents of the document with docid iDocid. |
| 146153 | */ |
| 146154 | static int fts3PendingTermsDocid( |
| 146155 | Fts3Table *p, /* Full-text table handle */ |
| 146156 | int bDelete, /* True if this op is a delete */ |
| 146157 | int iLangid, /* Language id of row being written */ |
| 146158 | sqlite_int64 iDocid /* Docid of row being written */ |
| 146159 | ){ |
| 146160 | assert( iLangid>=0 ); |
| 146161 | assert( bDelete==1 || bDelete==0 ); |
| 146162 | |
| 146163 | /* TODO(shess) Explore whether partially flushing the buffer on |
| 146164 | ** forced-flush would provide better performance. I suspect that if |
| 146165 | ** we ordered the doclists by size and flushed the largest until the |
| 146166 | ** buffer was half empty, that would let the less frequent terms |
| 146167 | ** generate longer doclists. |
| 146168 | */ |
| 146169 | if( iDocid<p->iPrevDocid |
| 146170 | || (iDocid==p->iPrevDocid && p->bPrevDelete==0) |
| 146171 | || p->iPrevLangid!=iLangid |
| 146172 | || p->nPendingData>p->nMaxPendingData |
| 146173 | ){ |
| 146174 | int rc = sqlite3Fts3PendingTermsFlush(p); |
| 146175 | if( rc!=SQLITE_OK ) return rc; |
| 146176 | } |
| 146177 | p->iPrevDocid = iDocid; |
| 146178 | p->iPrevLangid = iLangid; |
| 146179 | p->bPrevDelete = bDelete; |
| 146180 | return SQLITE_OK; |
| 146181 | } |
| 146182 | |
| 146183 | /* |
| 146184 | ** Discard the contents of the pending-terms hash tables. |
| @@ -146246,11 +146364,12 @@ | |
| 146364 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); |
| 146365 | if( rc==SQLITE_OK ){ |
| 146366 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 146367 | int i; |
| 146368 | int iLangid = langidFromSelect(p, pSelect); |
| 146369 | i64 iDocid = sqlite3_column_int64(pSelect, 0); |
| 146370 | rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid); |
| 146371 | for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ |
| 146372 | int iCol = i-1; |
| 146373 | if( p->abNotindexed[iCol]==0 ){ |
| 146374 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 146375 | rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]); |
| @@ -146494,18 +146613,23 @@ | |
| 146613 | |
| 146614 | if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){ |
| 146615 | |
| 146616 | if( fts3SegReaderIsPending(pReader) ){ |
| 146617 | Fts3HashElem *pElem = *(pReader->ppNextElem); |
| 146618 | sqlite3_free(pReader->aNode); |
| 146619 | pReader->aNode = 0; |
| 146620 | if( pElem ){ |
| 146621 | char *aCopy; |
| 146622 | PendingList *pList = (PendingList *)fts3HashData(pElem); |
| 146623 | int nCopy = pList->nData+1; |
| 146624 | pReader->zTerm = (char *)fts3HashKey(pElem); |
| 146625 | pReader->nTerm = fts3HashKeysize(pElem); |
| 146626 | aCopy = (char*)sqlite3_malloc(nCopy); |
| 146627 | if( !aCopy ) return SQLITE_NOMEM; |
| 146628 | memcpy(aCopy, pList->aData, nCopy); |
| 146629 | pReader->nNode = pReader->nDoclist = nCopy; |
| 146630 | pReader->aNode = pReader->aDoclist = aCopy; |
| 146631 | pReader->ppNextElem++; |
| 146632 | assert( pReader->aNode ); |
| 146633 | } |
| 146634 | return SQLITE_OK; |
| 146635 | } |
| @@ -146741,16 +146865,18 @@ | |
| 146865 | /* |
| 146866 | ** Free all allocations associated with the iterator passed as the |
| 146867 | ** second argument. |
| 146868 | */ |
| 146869 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ |
| 146870 | if( pReader ){ |
| 146871 | if( !fts3SegReaderIsPending(pReader) ){ |
| 146872 | sqlite3_free(pReader->zTerm); |
| 146873 | } |
| 146874 | if( !fts3SegReaderIsRootOnly(pReader) ){ |
| 146875 | sqlite3_free(pReader->aNode); |
| 146876 | } |
| 146877 | sqlite3_blob_close(pReader->pBlob); |
| 146878 | } |
| 146879 | sqlite3_free(pReader); |
| 146880 | } |
| 146881 | |
| 146882 | /* |
| @@ -148689,11 +148815,11 @@ | |
| 148815 | } |
| 148816 | |
| 148817 | while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 148818 | int iCol; |
| 148819 | int iLangid = langidFromSelect(p, pStmt); |
| 148820 | rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0)); |
| 148821 | memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); |
| 148822 | for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ |
| 148823 | if( p->abNotindexed[iCol]==0 ){ |
| 148824 | const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); |
| 148825 | rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); |
| @@ -150794,11 +150920,11 @@ | |
| 150920 | if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ |
| 150921 | rc = FTS_CORRUPT_VTAB; |
| 150922 | } |
| 150923 | } |
| 150924 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ |
| 150925 | rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); |
| 150926 | } |
| 150927 | if( rc==SQLITE_OK ){ |
| 150928 | assert( p->iPrevDocid==*pRowid ); |
| 150929 | rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); |
| 150930 | } |
| 150931 |
+27
-2
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -111,11 +111,11 @@ | ||
| 111 | 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | 113 | */ |
| 114 | 114 | #define SQLITE_VERSION "3.8.12" |
| 115 | 115 | #define SQLITE_VERSION_NUMBER 3008012 |
| 116 | -#define SQLITE_SOURCE_ID "2015-09-28 14:40:20 9d057f52217e7ef9c3f3eb84117abe3365503f44" | |
| 116 | +#define SQLITE_SOURCE_ID "2015-10-01 18:31:29 6f90839e91024e2006042f5eb7f21ca5b47a9b4a" | |
| 117 | 117 | |
| 118 | 118 | /* |
| 119 | 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | 121 | ** |
| @@ -5631,18 +5631,36 @@ | ||
| 5631 | 5631 | ** indicates that the expense of the operation is similar to that of a |
| 5632 | 5632 | ** binary search on a unique indexed field of an SQLite table with N rows. |
| 5633 | 5633 | ** |
| 5634 | 5634 | ** ^The estimatedRows value is an estimate of the number of rows that |
| 5635 | 5635 | ** will be returned by the strategy. |
| 5636 | +** | |
| 5637 | +** The xBestIndex method may optionally populate the idxFlags field with a | |
| 5638 | +** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - | |
| 5639 | +** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite | |
| 5640 | +** assumes that the strategy may visit at most one row. | |
| 5641 | +** | |
| 5642 | +** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then | |
| 5643 | +** SQLite also assumes that if a call to the xUpdate() method is made as | |
| 5644 | +** part of the same statement to delete or update a virtual table row and the | |
| 5645 | +** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback | |
| 5646 | +** any database changes. In other words, if the xUpdate() returns | |
| 5647 | +** SQLITE_CONSTRAINT, the database contents must be exactly as they were | |
| 5648 | +** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not | |
| 5649 | +** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by | |
| 5650 | +** the xUpdate method are automatically rolled back by SQLite. | |
| 5636 | 5651 | ** |
| 5637 | 5652 | ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info |
| 5638 | 5653 | ** structure for SQLite version 3.8.2. If a virtual table extension is |
| 5639 | 5654 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5640 | 5655 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5641 | 5656 | ** to included crashing the application). The estimatedRows field should |
| 5642 | 5657 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5643 | -** value greater than or equal to 3008002. | |
| 5658 | +** value greater than or equal to 3008002. Similarly, the idxFlags field | |
| 5659 | +** was added for version 3.8.12. It may therefore only be used if | |
| 5660 | +** sqlite3_libversion_number() returns a value greater than or equal to | |
| 5661 | +** 3008012. | |
| 5644 | 5662 | */ |
| 5645 | 5663 | struct sqlite3_index_info { |
| 5646 | 5664 | /* Inputs */ |
| 5647 | 5665 | int nConstraint; /* Number of entries in aConstraint */ |
| 5648 | 5666 | struct sqlite3_index_constraint { |
| @@ -5666,12 +5684,19 @@ | ||
| 5666 | 5684 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5667 | 5685 | int orderByConsumed; /* True if output is already ordered */ |
| 5668 | 5686 | double estimatedCost; /* Estimated cost of using this index */ |
| 5669 | 5687 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5670 | 5688 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5689 | + /* Fields below are only available in SQLite 3.8.12 and later */ | |
| 5690 | + int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ | |
| 5671 | 5691 | }; |
| 5672 | 5692 | |
| 5693 | +/* | |
| 5694 | +** CAPI3REF: Virtual Table Scan Flags | |
| 5695 | +*/ | |
| 5696 | +#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ | |
| 5697 | + | |
| 5673 | 5698 | /* |
| 5674 | 5699 | ** CAPI3REF: Virtual Table Constraint Operator Codes |
| 5675 | 5700 | ** |
| 5676 | 5701 | ** These macros defined the allowed values for the |
| 5677 | 5702 | ** [sqlite3_index_info].aConstraint[].op field. Each value represents |
| 5678 | 5703 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -111,11 +111,11 @@ | |
| 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | */ |
| 114 | #define SQLITE_VERSION "3.8.12" |
| 115 | #define SQLITE_VERSION_NUMBER 3008012 |
| 116 | #define SQLITE_SOURCE_ID "2015-09-28 14:40:20 9d057f52217e7ef9c3f3eb84117abe3365503f44" |
| 117 | |
| 118 | /* |
| 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | ** |
| @@ -5631,18 +5631,36 @@ | |
| 5631 | ** indicates that the expense of the operation is similar to that of a |
| 5632 | ** binary search on a unique indexed field of an SQLite table with N rows. |
| 5633 | ** |
| 5634 | ** ^The estimatedRows value is an estimate of the number of rows that |
| 5635 | ** will be returned by the strategy. |
| 5636 | ** |
| 5637 | ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info |
| 5638 | ** structure for SQLite version 3.8.2. If a virtual table extension is |
| 5639 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5640 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5641 | ** to included crashing the application). The estimatedRows field should |
| 5642 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5643 | ** value greater than or equal to 3008002. |
| 5644 | */ |
| 5645 | struct sqlite3_index_info { |
| 5646 | /* Inputs */ |
| 5647 | int nConstraint; /* Number of entries in aConstraint */ |
| 5648 | struct sqlite3_index_constraint { |
| @@ -5666,12 +5684,19 @@ | |
| 5666 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5667 | int orderByConsumed; /* True if output is already ordered */ |
| 5668 | double estimatedCost; /* Estimated cost of using this index */ |
| 5669 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5670 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5671 | }; |
| 5672 | |
| 5673 | /* |
| 5674 | ** CAPI3REF: Virtual Table Constraint Operator Codes |
| 5675 | ** |
| 5676 | ** These macros defined the allowed values for the |
| 5677 | ** [sqlite3_index_info].aConstraint[].op field. Each value represents |
| 5678 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -111,11 +111,11 @@ | |
| 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | */ |
| 114 | #define SQLITE_VERSION "3.8.12" |
| 115 | #define SQLITE_VERSION_NUMBER 3008012 |
| 116 | #define SQLITE_SOURCE_ID "2015-10-01 18:31:29 6f90839e91024e2006042f5eb7f21ca5b47a9b4a" |
| 117 | |
| 118 | /* |
| 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | ** |
| @@ -5631,18 +5631,36 @@ | |
| 5631 | ** indicates that the expense of the operation is similar to that of a |
| 5632 | ** binary search on a unique indexed field of an SQLite table with N rows. |
| 5633 | ** |
| 5634 | ** ^The estimatedRows value is an estimate of the number of rows that |
| 5635 | ** will be returned by the strategy. |
| 5636 | ** |
| 5637 | ** The xBestIndex method may optionally populate the idxFlags field with a |
| 5638 | ** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - |
| 5639 | ** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite |
| 5640 | ** assumes that the strategy may visit at most one row. |
| 5641 | ** |
| 5642 | ** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then |
| 5643 | ** SQLite also assumes that if a call to the xUpdate() method is made as |
| 5644 | ** part of the same statement to delete or update a virtual table row and the |
| 5645 | ** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback |
| 5646 | ** any database changes. In other words, if the xUpdate() returns |
| 5647 | ** SQLITE_CONSTRAINT, the database contents must be exactly as they were |
| 5648 | ** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not |
| 5649 | ** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by |
| 5650 | ** the xUpdate method are automatically rolled back by SQLite. |
| 5651 | ** |
| 5652 | ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info |
| 5653 | ** structure for SQLite version 3.8.2. If a virtual table extension is |
| 5654 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5655 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5656 | ** to included crashing the application). The estimatedRows field should |
| 5657 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5658 | ** value greater than or equal to 3008002. Similarly, the idxFlags field |
| 5659 | ** was added for version 3.8.12. It may therefore only be used if |
| 5660 | ** sqlite3_libversion_number() returns a value greater than or equal to |
| 5661 | ** 3008012. |
| 5662 | */ |
| 5663 | struct sqlite3_index_info { |
| 5664 | /* Inputs */ |
| 5665 | int nConstraint; /* Number of entries in aConstraint */ |
| 5666 | struct sqlite3_index_constraint { |
| @@ -5666,12 +5684,19 @@ | |
| 5684 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5685 | int orderByConsumed; /* True if output is already ordered */ |
| 5686 | double estimatedCost; /* Estimated cost of using this index */ |
| 5687 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5688 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5689 | /* Fields below are only available in SQLite 3.8.12 and later */ |
| 5690 | int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ |
| 5691 | }; |
| 5692 | |
| 5693 | /* |
| 5694 | ** CAPI3REF: Virtual Table Scan Flags |
| 5695 | */ |
| 5696 | #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ |
| 5697 | |
| 5698 | /* |
| 5699 | ** CAPI3REF: Virtual Table Constraint Operator Codes |
| 5700 | ** |
| 5701 | ** These macros defined the allowed values for the |
| 5702 | ** [sqlite3_index_info].aConstraint[].op field. Each value represents |
| 5703 |