| | @@ -16,11 +16,11 @@ |
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | | -** 2b17bc49655c577029919c2d409de994b0d2 with changes in files: |
| 21 | +** d2fe6b05f38d9d7cd78c5d252e99ac59f1ae with changes in files: |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| | @@ -465,11 +465,11 @@ |
| 465 | 465 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 466 | 466 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 467 | 467 | */ |
| 468 | 468 | #define SQLITE_VERSION "3.48.0" |
| 469 | 469 | #define SQLITE_VERSION_NUMBER 3048000 |
| 470 | | -#define SQLITE_SOURCE_ID "2024-12-30 21:23:53 2b17bc49655c577029919c2d409de994b0d252f8efb5da1ba0913f2c96bee552" |
| 470 | +#define SQLITE_SOURCE_ID "2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e84010" |
| 471 | 471 | |
| 472 | 472 | /* |
| 473 | 473 | ** CAPI3REF: Run-Time Library Version Numbers |
| 474 | 474 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 475 | 475 | ** |
| | @@ -33052,11 +33052,14 @@ |
| 33052 | 33052 | } |
| 33053 | 33053 | if( pItem->fg.fromDDL ){ |
| 33054 | 33054 | sqlite3_str_appendf(&x, " DDL"); |
| 33055 | 33055 | } |
| 33056 | 33056 | if( pItem->fg.isCte ){ |
| 33057 | | - sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse); |
| 33057 | + static const char *aMat[] = {",MAT", "", ",NO-MAT"}; |
| 33058 | + sqlite3_str_appendf(&x, " CteUse=%d%s", |
| 33059 | + pItem->u2.pCteUse->nUse, |
| 33060 | + aMat[pItem->u2.pCteUse->eM10d]); |
| 33058 | 33061 | } |
| 33059 | 33062 | if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){ |
| 33060 | 33063 | sqlite3_str_appendf(&x, " isOn"); |
| 33061 | 33064 | } |
| 33062 | 33065 | if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc"); |
| | @@ -33083,13 +33086,10 @@ |
| 33083 | 33086 | if( pItem->pSTab ){ |
| 33084 | 33087 | Table *pTab = pItem->pSTab; |
| 33085 | 33088 | sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1); |
| 33086 | 33089 | } |
| 33087 | 33090 | assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) ); |
| 33088 | | - sqlite3TreeViewPush(&pView, 0); |
| 33089 | | - sqlite3TreeViewLine(pView, "SUBQUERY"); |
| 33090 | | - sqlite3TreeViewPop(&pView); |
| 33091 | 33091 | sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0); |
| 33092 | 33092 | } |
| 33093 | 33093 | if( pItem->fg.isTabFunc ){ |
| 33094 | 33094 | sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); |
| 33095 | 33095 | } |
| | @@ -112713,10 +112713,11 @@ |
| 112713 | 112713 | if( mCol & colUsed ) break; /* Each column used only once */ |
| 112714 | 112714 | colUsed |= mCol; |
| 112715 | 112715 | if( aiMap ) aiMap[i] = j; |
| 112716 | 112716 | } |
| 112717 | 112717 | |
| 112718 | + assert( nExpr>0 && nExpr<BMS ); |
| 112718 | 112719 | assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) ); |
| 112719 | 112720 | if( colUsed==(MASKBIT(nExpr)-1) ){ |
| 112720 | 112721 | /* If we reach this point, that means the index pIdx is usable */ |
| 112721 | 112722 | int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); |
| 112722 | 112723 | ExplainQueryPlan((pParse, 0, |
| | @@ -164142,10 +164143,15 @@ |
| 164142 | 164143 | ** |
| 164143 | 164144 | ** 2. If iCol is part of an existing index that has an aiRowLogEst of |
| 164144 | 164145 | ** more than 20, then return false. |
| 164145 | 164146 | ** |
| 164146 | 164147 | ** 3. If no disqualifying conditions above are found, return true. |
| 164148 | +** |
| 164149 | +** 2025-01-03: I experimented with a new rule that returns false if the |
| 164150 | +** the datatype of the column is "BOOLEAN". This did not improve |
| 164151 | +** performance on any queries at hand, but it did burn CPU cycles, so the |
| 164152 | +** idea was not committed. |
| 164147 | 164153 | */ |
| 164148 | 164154 | static SQLITE_NOINLINE int columnIsGoodIndexCandidate( |
| 164149 | 164155 | const Table *pTab, |
| 164150 | 164156 | int iCol |
| 164151 | 164157 | ){ |
| | @@ -226243,10 +226249,28 @@ |
| 226243 | 226249 | static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ |
| 226244 | 226250 | DbpageCursor *pCsr = (DbpageCursor *)pCursor; |
| 226245 | 226251 | *pRowid = pCsr->pgno; |
| 226246 | 226252 | return SQLITE_OK; |
| 226247 | 226253 | } |
| 226254 | + |
| 226255 | +/* |
| 226256 | +** Open write transactions. Since we do not know in advance which database |
| 226257 | +** files will be written by the sqlite_dbpage virtual table, start a write |
| 226258 | +** transaction on them all. |
| 226259 | +** |
| 226260 | +** Return SQLITE_OK if successful, or an SQLite error code otherwise. |
| 226261 | +*/ |
| 226262 | +static int dbpageBeginTrans(DbpageTable *pTab){ |
| 226263 | + sqlite3 *db = pTab->db; |
| 226264 | + int rc = SQLITE_OK; |
| 226265 | + int i; |
| 226266 | + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ |
| 226267 | + Btree *pBt = db->aDb[i].pBt; |
| 226268 | + if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0); |
| 226269 | + } |
| 226270 | + return rc; |
| 226271 | +} |
| 226248 | 226272 | |
| 226249 | 226273 | static int dbpageUpdate( |
| 226250 | 226274 | sqlite3_vtab *pVtab, |
| 226251 | 226275 | int argc, |
| 226252 | 226276 | sqlite3_value **argv, |
| | @@ -226311,10 +226335,16 @@ |
| 226311 | 226335 | }else{ |
| 226312 | 226336 | zErr = "bad page value"; |
| 226313 | 226337 | goto update_fail; |
| 226314 | 226338 | } |
| 226315 | 226339 | } |
| 226340 | + |
| 226341 | + if( dbpageBeginTrans(pTab)!=SQLITE_OK ){ |
| 226342 | + zErr = "failed to open transaction"; |
| 226343 | + goto update_fail; |
| 226344 | + } |
| 226345 | + |
| 226316 | 226346 | pPager = sqlite3BtreePager(pBt); |
| 226317 | 226347 | rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0); |
| 226318 | 226348 | if( rc==SQLITE_OK ){ |
| 226319 | 226349 | const void *pData = sqlite3_value_blob(argv[3]); |
| 226320 | 226350 | if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){ |
| | @@ -226332,22 +226362,12 @@ |
| 226332 | 226362 | sqlite3_free(pVtab->zErrMsg); |
| 226333 | 226363 | pVtab->zErrMsg = sqlite3_mprintf("%s", zErr); |
| 226334 | 226364 | return SQLITE_ERROR; |
| 226335 | 226365 | } |
| 226336 | 226366 | |
| 226337 | | -/* Since we do not know in advance which database files will be |
| 226338 | | -** written by the sqlite_dbpage virtual table, start a write transaction |
| 226339 | | -** on them all. |
| 226340 | | -*/ |
| 226341 | 226367 | static int dbpageBegin(sqlite3_vtab *pVtab){ |
| 226342 | 226368 | DbpageTable *pTab = (DbpageTable *)pVtab; |
| 226343 | | - sqlite3 *db = pTab->db; |
| 226344 | | - int i; |
| 226345 | | - for(i=0; i<db->nDb; i++){ |
| 226346 | | - Btree *pBt = db->aDb[i].pBt; |
| 226347 | | - if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0); |
| 226348 | | - } |
| 226349 | 226369 | pTab->pgnoTrunc = 0; |
| 226350 | 226370 | return SQLITE_OK; |
| 226351 | 226371 | } |
| 226352 | 226372 | |
| 226353 | 226373 | /* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT |
| | @@ -226379,11 +226399,11 @@ |
| 226379 | 226399 | /* |
| 226380 | 226400 | ** Invoke this routine to register the "dbpage" virtual table module |
| 226381 | 226401 | */ |
| 226382 | 226402 | SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ |
| 226383 | 226403 | static sqlite3_module dbpage_module = { |
| 226384 | | - 0, /* iVersion */ |
| 226404 | + 2, /* iVersion */ |
| 226385 | 226405 | dbpageConnect, /* xCreate */ |
| 226386 | 226406 | dbpageConnect, /* xConnect */ |
| 226387 | 226407 | dbpageBestIndex, /* xBestIndex */ |
| 226388 | 226408 | dbpageDisconnect, /* xDisconnect */ |
| 226389 | 226409 | dbpageDisconnect, /* xDestroy */ |
| | @@ -231698,16 +231718,16 @@ |
| 231698 | 231718 | if( res!=SQLITE_CHANGESET_OMIT ){ |
| 231699 | 231719 | rc = SQLITE_CONSTRAINT; |
| 231700 | 231720 | } |
| 231701 | 231721 | } |
| 231702 | 231722 | } |
| 231703 | | - sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0); |
| 231704 | 231723 | |
| 231705 | 231724 | if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ |
| 231706 | 231725 | if( rc==SQLITE_OK ){ |
| 231707 | 231726 | rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); |
| 231708 | | - }else{ |
| 231727 | + } |
| 231728 | + if( rc!=SQLITE_OK ){ |
| 231709 | 231729 | sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); |
| 231710 | 231730 | sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); |
| 231711 | 231731 | } |
| 231712 | 231732 | } |
| 231713 | 231733 | |
| | @@ -243323,13 +243343,17 @@ |
| 243323 | 243343 | sqlite3_stmt **ppStmt, |
| 243324 | 243344 | char *zSql |
| 243325 | 243345 | ){ |
| 243326 | 243346 | if( p->rc==SQLITE_OK ){ |
| 243327 | 243347 | if( zSql ){ |
| 243328 | | - p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1, |
| 243348 | + int rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1, |
| 243329 | 243349 | SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB, |
| 243330 | 243350 | ppStmt, 0); |
| 243351 | + /* If this prepare() call fails with SQLITE_ERROR, then one of the |
| 243352 | + ** %_idx or %_data tables has been removed or modified. Call this |
| 243353 | + ** corruption. */ |
| 243354 | + p->rc = (rc==SQLITE_ERROR ? SQLITE_CORRUPT : rc); |
| 243331 | 243355 | }else{ |
| 243332 | 243356 | p->rc = SQLITE_NOMEM; |
| 243333 | 243357 | } |
| 243334 | 243358 | } |
| 243335 | 243359 | sqlite3_free(zSql); |
| | @@ -247904,10 +247928,28 @@ |
| 247904 | 247928 | int nTerm, |
| 247905 | 247929 | i64 iRowid |
| 247906 | 247930 | ){ |
| 247907 | 247931 | const int f = FTS5INDEX_QUERY_SKIPHASH; |
| 247908 | 247932 | Fts5Iter *pIter = 0; /* Used to find term instance */ |
| 247933 | + |
| 247934 | + /* If the version number has not been set to SECUREDELETE, do so now. */ |
| 247935 | + if( p->pConfig->iVersion!=FTS5_CURRENT_VERSION_SECUREDELETE ){ |
| 247936 | + Fts5Config *pConfig = p->pConfig; |
| 247937 | + sqlite3_stmt *pStmt = 0; |
| 247938 | + fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf( |
| 247939 | + "REPLACE INTO %Q.'%q_config' VALUES ('version', %d)", |
| 247940 | + pConfig->zDb, pConfig->zName, FTS5_CURRENT_VERSION_SECUREDELETE |
| 247941 | + )); |
| 247942 | + if( p->rc==SQLITE_OK ){ |
| 247943 | + int rc; |
| 247944 | + sqlite3_step(pStmt); |
| 247945 | + rc = sqlite3_finalize(pStmt); |
| 247946 | + if( p->rc==SQLITE_OK ) p->rc = rc; |
| 247947 | + pConfig->iCookie++; |
| 247948 | + pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE; |
| 247949 | + } |
| 247950 | + } |
| 247909 | 247951 | |
| 247910 | 247952 | fts5MultiIterNew(p, pStruct, f, 0, (const u8*)zTerm, nTerm, -1, 0, &pIter); |
| 247911 | 247953 | if( fts5MultiIterEof(p, pIter)==0 ){ |
| 247912 | 247954 | i64 iThis = fts5MultiIterRowid(pIter); |
| 247913 | 247955 | if( iThis<iRowid ){ |
| | @@ -253745,11 +253787,10 @@ |
| 253745 | 253787 | ){ |
| 253746 | 253788 | Fts5FullTable *pTab = (Fts5FullTable*)pVtab; |
| 253747 | 253789 | Fts5Config *pConfig = pTab->p.pConfig; |
| 253748 | 253790 | int eType0; /* value_type() of apVal[0] */ |
| 253749 | 253791 | int rc = SQLITE_OK; /* Return code */ |
| 253750 | | - int bUpdateOrDelete = 0; |
| 253751 | 253792 | |
| 253752 | 253793 | /* A transaction must be open when this is called. */ |
| 253753 | 253794 | assert( pTab->ts.eState==1 || pTab->ts.eState==2 ); |
| 253754 | 253795 | |
| 253755 | 253796 | assert( pVtab->zErrMsg==0 ); |
| | @@ -253757,11 +253798,11 @@ |
| 253757 | 253798 | assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER |
| 253758 | 253799 | || sqlite3_value_type(apVal[0])==SQLITE_NULL |
| 253759 | 253800 | ); |
| 253760 | 253801 | assert( pTab->p.pConfig->pzErrmsg==0 ); |
| 253761 | 253802 | if( pConfig->pgsz==0 ){ |
| 253762 | | - rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); |
| 253803 | + rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie); |
| 253763 | 253804 | if( rc!=SQLITE_OK ) return rc; |
| 253764 | 253805 | } |
| 253765 | 253806 | |
| 253766 | 253807 | pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg; |
| 253767 | 253808 | |
| | @@ -253782,11 +253823,10 @@ |
| 253782 | 253823 | "'delete' may not be used with a contentless_delete=1 table" |
| 253783 | 253824 | ); |
| 253784 | 253825 | rc = SQLITE_ERROR; |
| 253785 | 253826 | }else{ |
| 253786 | 253827 | rc = fts5SpecialDelete(pTab, apVal); |
| 253787 | | - bUpdateOrDelete = 1; |
| 253788 | 253828 | } |
| 253789 | 253829 | }else{ |
| 253790 | 253830 | rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); |
| 253791 | 253831 | } |
| 253792 | 253832 | }else{ |
| | @@ -253819,11 +253859,10 @@ |
| 253819 | 253859 | ); |
| 253820 | 253860 | rc = SQLITE_ERROR; |
| 253821 | 253861 | }else{ |
| 253822 | 253862 | i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ |
| 253823 | 253863 | rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0); |
| 253824 | | - bUpdateOrDelete = 1; |
| 253825 | 253864 | } |
| 253826 | 253865 | } |
| 253827 | 253866 | |
| 253828 | 253867 | /* INSERT or UPDATE */ |
| 253829 | 253868 | else{ |
| | @@ -253847,11 +253886,10 @@ |
| 253847 | 253886 | /* An INSERT statement. If the conflict-mode is REPLACE, first remove |
| 253848 | 253887 | ** the current entry (if any). */ |
| 253849 | 253888 | if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){ |
| 253850 | 253889 | i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */ |
| 253851 | 253890 | rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0); |
| 253852 | | - bUpdateOrDelete = 1; |
| 253853 | 253891 | } |
| 253854 | 253892 | fts5StorageInsert(&rc, pTab, apVal, pRowid); |
| 253855 | 253893 | } |
| 253856 | 253894 | |
| 253857 | 253895 | /* UPDATE */ |
| | @@ -253901,27 +253939,12 @@ |
| 253901 | 253939 | } |
| 253902 | 253940 | }else{ |
| 253903 | 253941 | rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1); |
| 253904 | 253942 | fts5StorageInsert(&rc, pTab, apVal, pRowid); |
| 253905 | 253943 | } |
| 253906 | | - bUpdateOrDelete = 1; |
| 253907 | 253944 | sqlite3Fts5StorageReleaseDeleteRow(pStorage); |
| 253908 | 253945 | } |
| 253909 | | - |
| 253910 | | - } |
| 253911 | | - } |
| 253912 | | - |
| 253913 | | - if( rc==SQLITE_OK |
| 253914 | | - && bUpdateOrDelete |
| 253915 | | - && pConfig->bSecureDelete |
| 253916 | | - && pConfig->iVersion==FTS5_CURRENT_VERSION |
| 253917 | | - ){ |
| 253918 | | - rc = sqlite3Fts5StorageConfigValue( |
| 253919 | | - pTab->pStorage, "version", 0, FTS5_CURRENT_VERSION_SECUREDELETE |
| 253920 | | - ); |
| 253921 | | - if( rc==SQLITE_OK ){ |
| 253922 | | - pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE; |
| 253923 | 253946 | } |
| 253924 | 253947 | } |
| 253925 | 253948 | |
| 253926 | 253949 | update_out: |
| 253927 | 253950 | pTab->p.pConfig->pzErrmsg = 0; |
| | @@ -253970,10 +253993,11 @@ |
| 253970 | 253993 | static int fts5RollbackMethod(sqlite3_vtab *pVtab){ |
| 253971 | 253994 | int rc; |
| 253972 | 253995 | Fts5FullTable *pTab = (Fts5FullTable*)pVtab; |
| 253973 | 253996 | fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0); |
| 253974 | 253997 | rc = sqlite3Fts5StorageRollback(pTab->pStorage); |
| 253998 | + pTab->p.pConfig->pgsz = 0; |
| 253975 | 253999 | return rc; |
| 253976 | 254000 | } |
| 253977 | 254001 | |
| 253978 | 254002 | static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*); |
| 253979 | 254003 | |
| | @@ -255438,11 +255462,11 @@ |
| 255438 | 255462 | int nArg, /* Number of args */ |
| 255439 | 255463 | sqlite3_value **apUnused /* Function arguments */ |
| 255440 | 255464 | ){ |
| 255441 | 255465 | assert( nArg==0 ); |
| 255442 | 255466 | UNUSED_PARAM2(nArg, apUnused); |
| 255443 | | - sqlite3_result_text(pCtx, "fts5: 2024-12-30 21:23:53 2b17bc49655c577029919c2d409de994b0d252f8efb5da1ba0913f2c96bee552", -1, SQLITE_TRANSIENT); |
| 255467 | + sqlite3_result_text(pCtx, "fts5: 2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e84010", -1, SQLITE_TRANSIENT); |
| 255444 | 255468 | } |
| 255445 | 255469 | |
| 255446 | 255470 | /* |
| 255447 | 255471 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 255448 | 255472 | ** |
| | @@ -255918,10 +255942,15 @@ |
| 255918 | 255942 | rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0); |
| 255919 | 255943 | p->pConfig->bLock--; |
| 255920 | 255944 | sqlite3_free(zSql); |
| 255921 | 255945 | if( rc!=SQLITE_OK && pzErrMsg ){ |
| 255922 | 255946 | *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db)); |
| 255947 | + } |
| 255948 | + if( rc==SQLITE_ERROR && eStmt>FTS5_STMT_LOOKUP2 && eStmt<FTS5_STMT_SCAN ){ |
| 255949 | + /* One of the internal tables - not the %_content table - is missing. |
| 255950 | + ** This counts as a corrupted table. */ |
| 255951 | + rc = SQLITE_CORRUPT; |
| 255923 | 255952 | } |
| 255924 | 255953 | } |
| 255925 | 255954 | } |
| 255926 | 255955 | |
| 255927 | 255956 | *ppStmt = p->aStmt[eStmt]; |
| 255928 | 255957 | |