| | @@ -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 | | -** 4be9af4469d7e31ee852f67e5aa32996557. |
| 21 | +** ddc6ead6453e0f98943bd07aedd90d47bc2e. |
| 22 | 22 | */ |
| 23 | 23 | #define SQLITE_CORE 1 |
| 24 | 24 | #define SQLITE_AMALGAMATION 1 |
| 25 | 25 | #ifndef SQLITE_PRIVATE |
| 26 | 26 | # define SQLITE_PRIVATE static |
| | @@ -459,11 +459,11 @@ |
| 459 | 459 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 460 | 460 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 461 | 461 | */ |
| 462 | 462 | #define SQLITE_VERSION "3.44.0" |
| 463 | 463 | #define SQLITE_VERSION_NUMBER 3044000 |
| 464 | | -#define SQLITE_SOURCE_ID "2023-10-24 11:06:44 54be9af4469d7e31ee852f67e5aa32996557c10de654a60103fd165d2fedf311" |
| 464 | +#define SQLITE_SOURCE_ID "2023-10-29 20:05:18 ddc6ead6453e0f98943bd07aedd90d47bc2e9e9e27b008d493491168bea2b3f1" |
| 465 | 465 | |
| 466 | 466 | /* |
| 467 | 467 | ** CAPI3REF: Run-Time Library Version Numbers |
| 468 | 468 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 469 | 469 | ** |
| | @@ -2438,11 +2438,11 @@ |
| 2438 | 2438 | ** of a table column that its values are likely to be very large - larger |
| 2439 | 2439 | ** than the configured sorter-reference size threshold - then a reference |
| 2440 | 2440 | ** is stored in each sorted record and the required column values loaded |
| 2441 | 2441 | ** from the database as records are returned in sorted order. The default |
| 2442 | 2442 | ** value for this option is to never use this optimization. Specifying a |
| 2443 | | -** negative value for this option restores the default behaviour. |
| 2443 | +** negative value for this option restores the default behavior. |
| 2444 | 2444 | ** This option is only available if SQLite is compiled with the |
| 2445 | 2445 | ** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. |
| 2446 | 2446 | ** |
| 2447 | 2447 | ** [[SQLITE_CONFIG_MEMDB_MAXSIZE]] |
| 2448 | 2448 | ** <dt>SQLITE_CONFIG_MEMDB_MAXSIZE |
| | @@ -2613,11 +2613,11 @@ |
| 2613 | 2613 | ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> |
| 2614 | 2614 | ** <dd> Usually, when a database in wal mode is closed or detached from a |
| 2615 | 2615 | ** database handle, SQLite checks if this will mean that there are now no |
| 2616 | 2616 | ** connections at all to the database. If so, it performs a checkpoint |
| 2617 | 2617 | ** operation before closing the connection. This option may be used to |
| 2618 | | -** override this behaviour. The first parameter passed to this operation |
| 2618 | +** override this behavior. The first parameter passed to this operation |
| 2619 | 2619 | ** is an integer - positive to disable checkpoints-on-close, or zero (the |
| 2620 | 2620 | ** default) to enable them, and negative to leave the setting unchanged. |
| 2621 | 2621 | ** The second parameter is a pointer to an integer |
| 2622 | 2622 | ** into which is written 0 or 1 to indicate whether checkpoints-on-close |
| 2623 | 2623 | ** have been disabled - 0 if they are not disabled, 1 if they are. |
| | @@ -4266,10 +4266,11 @@ |
| 4266 | 4266 | ** <li> sqlite3_error_offset() |
| 4267 | 4267 | ** </ul> |
| 4268 | 4268 | ** |
| 4269 | 4269 | ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language |
| 4270 | 4270 | ** text that describes the error, as either UTF-8 or UTF-16 respectively. |
| 4271 | +** (See how SQLite handles [invalid UTF] for exceptions to this rule.) |
| 4271 | 4272 | ** ^(Memory to hold the error message string is managed internally. |
| 4272 | 4273 | ** The application does not need to worry about freeing the result. |
| 4273 | 4274 | ** However, the error string might be overwritten or deallocated by |
| 4274 | 4275 | ** subsequent calls to other SQLite interface functions.)^ |
| 4275 | 4276 | ** |
| | @@ -6271,11 +6272,11 @@ |
| 6271 | 6272 | ** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made |
| 6272 | 6273 | ** with the same D and N parameters. |
| 6273 | 6274 | ** <li> The database connection closes. SQLite does not make any guarantees |
| 6274 | 6275 | ** about the order in which destructors are called, only that all |
| 6275 | 6276 | ** destructors will be called exactly once at some point during the |
| 6276 | | -** database connection closingi process. |
| 6277 | +** database connection closing process. |
| 6277 | 6278 | ** </ul> |
| 6278 | 6279 | ** |
| 6279 | 6280 | ** SQLite does not do anything with client data other than invoke |
| 6280 | 6281 | ** destructors on the client data at the appropriate time. The intended |
| 6281 | 6282 | ** use for client data is to provide a mechanism for wrapper libraries |
| | @@ -6935,11 +6936,11 @@ |
| 6935 | 6936 | ** a valid schema, then -1 is returned. |
| 6936 | 6937 | */ |
| 6937 | 6938 | SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); |
| 6938 | 6939 | |
| 6939 | 6940 | /* |
| 6940 | | -** CAPI3REF: Allowed return values from [sqlite3_txn_state()] |
| 6941 | +** CAPI3REF: Allowed return values from sqlite3_txn_state() |
| 6941 | 6942 | ** KEYWORDS: {transaction state} |
| 6942 | 6943 | ** |
| 6943 | 6944 | ** These constants define the current transaction state of a database file. |
| 6944 | 6945 | ** ^The [sqlite3_txn_state(D,S)] interface returns one of these |
| 6945 | 6946 | ** constants in order to describe the transaction state of schema S |
| | @@ -7067,11 +7068,11 @@ |
| 7067 | 7068 | ** |
| 7068 | 7069 | ** <p>^There is only one autovacuum pages callback per database connection. |
| 7069 | 7070 | ** ^Each call to the sqlite3_autovacuum_pages() interface overrides all |
| 7070 | 7071 | ** previous invocations for that database connection. ^If the callback |
| 7071 | 7072 | ** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer, |
| 7072 | | -** then the autovacuum steps callback is cancelled. The return value |
| 7073 | +** then the autovacuum steps callback is canceled. The return value |
| 7073 | 7074 | ** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might |
| 7074 | 7075 | ** be some other error code if something goes wrong. The current |
| 7075 | 7076 | ** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other |
| 7076 | 7077 | ** return codes might be added in future releases. |
| 7077 | 7078 | ** |
| | @@ -7588,11 +7589,12 @@ |
| 7588 | 7589 | /* The methods above are in versions 1 and 2 of the sqlite_module object. |
| 7589 | 7590 | ** Those below are for version 3 and greater. */ |
| 7590 | 7591 | int (*xShadowName)(const char*); |
| 7591 | 7592 | /* The methods above are in versions 1 through 3 of the sqlite_module object. |
| 7592 | 7593 | ** Those below are for version 4 and greater. */ |
| 7593 | | - int (*xIntegrity)(sqlite3_vtab *pVTab, char**); |
| 7594 | + int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema, |
| 7595 | + const char *zTabName, int mFlags, char **pzErr); |
| 7594 | 7596 | }; |
| 7595 | 7597 | |
| 7596 | 7598 | /* |
| 7597 | 7599 | ** CAPI3REF: Virtual Table Indexing Information |
| 7598 | 7600 | ** KEYWORDS: sqlite3_index_info |
| | @@ -8076,11 +8078,11 @@ |
| 8076 | 8078 | ** blob handles or active write statements, the current transaction is |
| 8077 | 8079 | ** committed. ^If an error occurs while committing the transaction, an error |
| 8078 | 8080 | ** code is returned and the transaction rolled back. |
| 8079 | 8081 | ** |
| 8080 | 8082 | ** Calling this function with an argument that is not a NULL pointer or an |
| 8081 | | -** open blob handle results in undefined behaviour. ^Calling this routine |
| 8083 | +** open blob handle results in undefined behavior. ^Calling this routine |
| 8082 | 8084 | ** with a null pointer (such as would be returned by a failed call to |
| 8083 | 8085 | ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function |
| 8084 | 8086 | ** is passed a valid open blob handle, the values returned by the |
| 8085 | 8087 | ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. |
| 8086 | 8088 | */ |
| | @@ -9618,12 +9620,12 @@ |
| 9618 | 9620 | ** ^(There may be at most one unlock-notify callback registered by a |
| 9619 | 9621 | ** blocked connection. If sqlite3_unlock_notify() is called when the |
| 9620 | 9622 | ** blocked connection already has a registered unlock-notify callback, |
| 9621 | 9623 | ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is |
| 9622 | 9624 | ** called with a NULL pointer as its second argument, then any existing |
| 9623 | | -** unlock-notify callback is cancelled. ^The blocked connections |
| 9624 | | -** unlock-notify callback may also be cancelled by closing the blocked |
| 9625 | +** unlock-notify callback is canceled. ^The blocked connections |
| 9626 | +** unlock-notify callback may also be canceled by closing the blocked |
| 9625 | 9627 | ** connection using [sqlite3_close()]. |
| 9626 | 9628 | ** |
| 9627 | 9629 | ** The unlock-notify callback is not reentrant. If an application invokes |
| 9628 | 9630 | ** any sqlite3_xxx API functions from within an unlock-notify callback, a |
| 9629 | 9631 | ** crash or deadlock may be the result. |
| | @@ -19870,10 +19872,11 @@ |
| 19870 | 19872 | Trigger retTrig; /* The transient trigger that implements RETURNING */ |
| 19871 | 19873 | TriggerStep retTStep; /* The trigger step */ |
| 19872 | 19874 | int iRetCur; /* Transient table holding RETURNING results */ |
| 19873 | 19875 | int nRetCol; /* Number of in pReturnEL after expansion */ |
| 19874 | 19876 | int iRetReg; /* Register array for holding a row of RETURNING */ |
| 19877 | + char zName[40]; /* Name of trigger: "sqlite_returning_%p" */ |
| 19875 | 19878 | }; |
| 19876 | 19879 | |
| 19877 | 19880 | /* |
| 19878 | 19881 | ** An objected used to accumulate the text of a string where we |
| 19879 | 19882 | ** do not necessarily know how big the string will be in the end. |
| | @@ -40939,13 +40942,10 @@ |
| 40939 | 40942 | int rc = SQLITE_OK; |
| 40940 | 40943 | unixFile *pFile = (unixFile*)id; |
| 40941 | 40944 | unixInodeInfo *pInode; |
| 40942 | 40945 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 40943 | 40946 | int skipShared = 0; |
| 40944 | | -#ifdef SQLITE_TEST |
| 40945 | | - int h = pFile->h; |
| 40946 | | -#endif |
| 40947 | 40947 | |
| 40948 | 40948 | assert( pFile ); |
| 40949 | 40949 | OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, |
| 40950 | 40950 | pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, |
| 40951 | 40951 | osGetpid(0))); |
| | @@ -40957,13 +40957,10 @@ |
| 40957 | 40957 | pInode = pFile->pInode; |
| 40958 | 40958 | sqlite3_mutex_enter(pInode->pLockMutex); |
| 40959 | 40959 | assert( pInode->nShared!=0 ); |
| 40960 | 40960 | if( pFile->eFileLock>SHARED_LOCK ){ |
| 40961 | 40961 | assert( pInode->eFileLock==pFile->eFileLock ); |
| 40962 | | - SimulateIOErrorBenign(1); |
| 40963 | | - SimulateIOError( h=(-1) ) |
| 40964 | | - SimulateIOErrorBenign(0); |
| 40965 | 40962 | |
| 40966 | 40963 | #ifdef SQLITE_DEBUG |
| 40967 | 40964 | /* When reducing a lock such that other processes can start |
| 40968 | 40965 | ** reading the database file again, make sure that the |
| 40969 | 40966 | ** transaction counter was updated if any part of the database |
| | @@ -41008,13 +41005,10 @@ |
| 41008 | 41005 | ** the lock. |
| 41009 | 41006 | */ |
| 41010 | 41007 | unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte; |
| 41011 | 41008 | pInode->nShared--; |
| 41012 | 41009 | if( pInode->nShared==0 ){ |
| 41013 | | - SimulateIOErrorBenign(1); |
| 41014 | | - SimulateIOError( h=(-1) ) |
| 41015 | | - SimulateIOErrorBenign(0); |
| 41016 | 41010 | if( !skipShared ){ |
| 41017 | 41011 | rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); |
| 41018 | 41012 | } |
| 41019 | 41013 | if( !rc ){ |
| 41020 | 41014 | pInode->eFileLock = NO_LOCK; |
| | @@ -80220,11 +80214,10 @@ |
| 80220 | 80214 | ** |
| 80221 | 80215 | ** Also check that the page number is in bounds. |
| 80222 | 80216 | */ |
| 80223 | 80217 | static int checkRef(IntegrityCk *pCheck, Pgno iPage){ |
| 80224 | 80218 | if( iPage>pCheck->nCkPage || iPage==0 ){ |
| 80225 | | - if( pCheck->nCkPage==0 ) return 0; /* omit reference counting */ |
| 80226 | 80219 | checkAppendMsg(pCheck, "invalid page number %u", iPage); |
| 80227 | 80220 | return 1; |
| 80228 | 80221 | } |
| 80229 | 80222 | if( getPageReferenced(pCheck, iPage) ){ |
| 80230 | 80223 | checkAppendMsg(pCheck, "2nd reference to page %u", iPage); |
| | @@ -80726,19 +80719,14 @@ |
| 80726 | 80719 | sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; |
| 80727 | 80720 | if( sCheck.nCkPage==0 ){ |
| 80728 | 80721 | goto integrity_ck_cleanup; |
| 80729 | 80722 | } |
| 80730 | 80723 | |
| 80731 | | - if( bPartial ){ |
| 80732 | | - sCheck.nCkPage = 0; |
| 80733 | | - sCheck.aPgRef = 0; |
| 80734 | | - }else{ |
| 80735 | | - sCheck.aPgRef = sqlite3MallocZero((sCheck.nCkPage / 8)+ 1); |
| 80736 | | - if( !sCheck.aPgRef ){ |
| 80737 | | - checkOom(&sCheck); |
| 80738 | | - goto integrity_ck_cleanup; |
| 80739 | | - } |
| 80724 | + sCheck.aPgRef = sqlite3MallocZero((sCheck.nCkPage / 8)+ 1); |
| 80725 | + if( !sCheck.aPgRef ){ |
| 80726 | + checkOom(&sCheck); |
| 80727 | + goto integrity_ck_cleanup; |
| 80740 | 80728 | } |
| 80741 | 80729 | sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); |
| 80742 | 80730 | if( sCheck.heap==0 ){ |
| 80743 | 80731 | checkOom(&sCheck); |
| 80744 | 80732 | goto integrity_ck_cleanup; |
| | @@ -88408,10 +88396,15 @@ |
| 88408 | 88396 | ** Do a comparison between a 64-bit signed integer and a 64-bit floating-point |
| 88409 | 88397 | ** number. Return negative, zero, or positive if the first (i64) is less than, |
| 88410 | 88398 | ** equal to, or greater than the second (double). |
| 88411 | 88399 | */ |
| 88412 | 88400 | SQLITE_PRIVATE int sqlite3IntFloatCompare(i64 i, double r){ |
| 88401 | + if( sqlite3IsNaN(r) ){ |
| 88402 | + /* SQLite considers NaN to be a NULL. And all integer values are greater |
| 88403 | + ** than NULL */ |
| 88404 | + return 1; |
| 88405 | + } |
| 88413 | 88406 | if( sqlite3Config.bUseLongDouble ){ |
| 88414 | 88407 | LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; |
| 88415 | 88408 | testcase( x<r ); |
| 88416 | 88409 | testcase( x>r ); |
| 88417 | 88410 | testcase( x==r ); |
| | @@ -99047,25 +99040,33 @@ |
| 99047 | 99040 | ** Disable Auth and Trace callbacks while those statements are running if |
| 99048 | 99041 | ** P1 is true. |
| 99049 | 99042 | */ |
| 99050 | 99043 | case OP_SqlExec: { |
| 99051 | 99044 | char *zErr; |
| 99045 | +#ifndef SQLITE_OMIT_AUTHORIZATION |
| 99052 | 99046 | sqlite3_xauth xAuth; |
| 99047 | +#endif |
| 99053 | 99048 | u8 mTrace; |
| 99054 | 99049 | |
| 99055 | 99050 | sqlite3VdbeIncrWriteCounter(p, 0); |
| 99056 | 99051 | db->nSqlExec++; |
| 99057 | 99052 | zErr = 0; |
| 99053 | +#ifndef SQLITE_OMIT_AUTHORIZATION |
| 99058 | 99054 | xAuth = db->xAuth; |
| 99055 | +#endif |
| 99059 | 99056 | mTrace = db->mTrace; |
| 99060 | 99057 | if( pOp->p1 ){ |
| 99058 | +#ifndef SQLITE_OMIT_AUTHORIZATION |
| 99061 | 99059 | db->xAuth = 0; |
| 99060 | +#endif |
| 99062 | 99061 | db->mTrace = 0; |
| 99063 | 99062 | } |
| 99064 | 99063 | rc = sqlite3_exec(db, pOp->p4.z, 0, 0, &zErr); |
| 99065 | 99064 | db->nSqlExec--; |
| 99065 | +#ifndef SQLITE_OMIT_AUTHORIZATION |
| 99066 | 99066 | db->xAuth = xAuth; |
| 99067 | +#endif |
| 99067 | 99068 | db->mTrace = mTrace; |
| 99068 | 99069 | if( zErr || rc ){ |
| 99069 | 99070 | sqlite3VdbeError(p, "%s", zErr); |
| 99070 | 99071 | sqlite3_free(zErr); |
| 99071 | 99072 | if( rc==SQLITE_NOMEM ) goto no_mem; |
| | @@ -100290,17 +100291,18 @@ |
| 100290 | 100291 | break; |
| 100291 | 100292 | } |
| 100292 | 100293 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 100293 | 100294 | |
| 100294 | 100295 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 100295 | | -/* Opcode: VCheck * P2 * P4 * |
| 100296 | +/* Opcode: VCheck P1 P2 P3 P4 * |
| 100296 | 100297 | ** |
| 100297 | | -** P4 is a pointer to a Table object that is a virtual table that |
| 100298 | | -** supports the xIntegrity() method. This opcode runs the xIntegrity() |
| 100299 | | -** method for that virtual table. If an error is reported back, the error |
| 100300 | | -** message is stored in register P2. If no errors are seen, register P2 |
| 100301 | | -** is set to NULL. |
| 100298 | +** P4 is a pointer to a Table object that is a virtual table in schema P1 |
| 100299 | +** that supports the xIntegrity() method. This opcode runs the xIntegrity() |
| 100300 | +** method for that virtual table, using P3 as the integer argument. If |
| 100301 | +** an error is reported back, the table name is prepended to the error |
| 100302 | +** message and that message is stored in P2. If no errors are seen, |
| 100303 | +** register P2 is set to NULL. |
| 100302 | 100304 | */ |
| 100303 | 100305 | case OP_VCheck: { /* out2 */ |
| 100304 | 100306 | Table *pTab; |
| 100305 | 100307 | sqlite3_vtab *pVtab; |
| 100306 | 100308 | const sqlite3_module *pModule; |
| | @@ -100319,11 +100321,13 @@ |
| 100319 | 100321 | assert( pModule!=0 ); |
| 100320 | 100322 | assert( pModule->iVersion>=4 ); |
| 100321 | 100323 | assert( pModule->xIntegrity!=0 ); |
| 100322 | 100324 | pTab->nTabRef++; |
| 100323 | 100325 | sqlite3VtabLock(pTab->u.vtab.p); |
| 100324 | | - rc = pModule->xIntegrity(pVtab, &zErr); |
| 100326 | + assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 100327 | + rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName, |
| 100328 | + pOp->p3, &zErr); |
| 100325 | 100329 | sqlite3VtabUnlock(pTab->u.vtab.p); |
| 100326 | 100330 | sqlite3DeleteTable(db, pTab); |
| 100327 | 100331 | if( rc ){ |
| 100328 | 100332 | sqlite3_free(zErr); |
| 100329 | 100333 | goto abort_due_to_error; |
| | @@ -114667,20 +114671,21 @@ |
| 114667 | 114671 | assert( pExpr->pLeft->op==TK_ORDER ); |
| 114668 | 114672 | assert( ExprUseXList(pExpr->pLeft) ); |
| 114669 | 114673 | pItem->iOBTab = pParse->nTab++; |
| 114670 | 114674 | pOBList = pExpr->pLeft->x.pList; |
| 114671 | 114675 | assert( pOBList->nExpr>0 ); |
| 114676 | + assert( pItem->bOBUnique==0 ); |
| 114672 | 114677 | if( pOBList->nExpr==1 |
| 114673 | 114678 | && nArg==1 |
| 114674 | 114679 | && sqlite3ExprCompare(0,pOBList->a[0].pExpr, |
| 114675 | 114680 | pExpr->x.pList->a[0].pExpr,0)==0 |
| 114676 | 114681 | ){ |
| 114677 | 114682 | pItem->bOBPayload = 0; |
| 114683 | + pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct); |
| 114678 | 114684 | }else{ |
| 114679 | 114685 | pItem->bOBPayload = 1; |
| 114680 | 114686 | } |
| 114681 | | - pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct); |
| 114682 | 114687 | }else{ |
| 114683 | 114688 | pItem->iOBTab = -1; |
| 114684 | 114689 | } |
| 114685 | 114690 | if( ExprHasProperty(pExpr, EP_Distinct) && !pItem->bOBUnique ){ |
| 114686 | 114691 | pItem->iDistinct = pParse->nTab++; |
| | @@ -121468,24 +121473,17 @@ |
| 121468 | 121473 | pTab->tabFlags |= TF_OOOHidden; |
| 121469 | 121474 | } |
| 121470 | 121475 | } |
| 121471 | 121476 | #endif |
| 121472 | 121477 | |
| 121473 | | -/* |
| 121474 | | -** Name of the special TEMP trigger used to implement RETURNING. The |
| 121475 | | -** name begins with "sqlite_" so that it is guaranteed not to collide |
| 121476 | | -** with any application-generated triggers. |
| 121477 | | -*/ |
| 121478 | | -#define RETURNING_TRIGGER_NAME "sqlite_returning" |
| 121479 | | - |
| 121480 | 121478 | /* |
| 121481 | 121479 | ** Clean up the data structures associated with the RETURNING clause. |
| 121482 | 121480 | */ |
| 121483 | 121481 | static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){ |
| 121484 | 121482 | Hash *pHash; |
| 121485 | 121483 | pHash = &(db->aDb[1].pSchema->trigHash); |
| 121486 | | - sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0); |
| 121484 | + sqlite3HashInsert(pHash, pRet->zName, 0); |
| 121487 | 121485 | sqlite3ExprListDelete(db, pRet->pReturnEL); |
| 121488 | 121486 | sqlite3DbFree(db, pRet); |
| 121489 | 121487 | } |
| 121490 | 121488 | |
| 121491 | 121489 | /* |
| | @@ -121524,11 +121522,13 @@ |
| 121524 | 121522 | pRet->pReturnEL = pList; |
| 121525 | 121523 | sqlite3ParserAddCleanup(pParse, |
| 121526 | 121524 | (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet); |
| 121527 | 121525 | testcase( pParse->earlyCleanup ); |
| 121528 | 121526 | if( db->mallocFailed ) return; |
| 121529 | | - pRet->retTrig.zName = RETURNING_TRIGGER_NAME; |
| 121527 | + sqlite3_snprintf(sizeof(pRet->zName), pRet->zName, |
| 121528 | + "sqlite_returning_%p", pParse); |
| 121529 | + pRet->retTrig.zName = pRet->zName; |
| 121530 | 121530 | pRet->retTrig.op = TK_RETURNING; |
| 121531 | 121531 | pRet->retTrig.tr_tm = TRIGGER_AFTER; |
| 121532 | 121532 | pRet->retTrig.bReturning = 1; |
| 121533 | 121533 | pRet->retTrig.pSchema = db->aDb[1].pSchema; |
| 121534 | 121534 | pRet->retTrig.pTabSchema = db->aDb[1].pSchema; |
| | @@ -121535,13 +121535,13 @@ |
| 121535 | 121535 | pRet->retTrig.step_list = &pRet->retTStep; |
| 121536 | 121536 | pRet->retTStep.op = TK_RETURNING; |
| 121537 | 121537 | pRet->retTStep.pTrig = &pRet->retTrig; |
| 121538 | 121538 | pRet->retTStep.pExprList = pList; |
| 121539 | 121539 | pHash = &(db->aDb[1].pSchema->trigHash); |
| 121540 | | - assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 |
| 121540 | + assert( sqlite3HashFind(pHash, pRet->zName)==0 |
| 121541 | 121541 | || pParse->nErr || pParse->ifNotExists ); |
| 121542 | | - if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig) |
| 121542 | + if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig) |
| 121543 | 121543 | ==&pRet->retTrig ){ |
| 121544 | 121544 | sqlite3OomFault(db); |
| 121545 | 121545 | } |
| 121546 | 121546 | } |
| 121547 | 121547 | |
| | @@ -138973,11 +138973,11 @@ |
| 138973 | 138973 | pVTab = pTab->u.vtab.p->pVtab; |
| 138974 | 138974 | if( NEVER(pVTab==0) ) continue; |
| 138975 | 138975 | if( NEVER(pVTab->pModule==0) ) continue; |
| 138976 | 138976 | if( pVTab->pModule->iVersion<4 ) continue; |
| 138977 | 138977 | if( pVTab->pModule->xIntegrity==0 ) continue; |
| 138978 | | - sqlite3VdbeAddOp2(v, OP_VCheck, 0, 3); |
| 138978 | + sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick); |
| 138979 | 138979 | sqlite3VdbeAppendP4(v, pTab, P4_TABLE); |
| 138980 | 138980 | a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v); |
| 138981 | 138981 | integrityCheckResultRow(v); |
| 138982 | 138982 | sqlite3VdbeJumpHere(v, a1); |
| 138983 | 138983 | #endif |
| | @@ -147929,11 +147929,11 @@ |
| 147929 | 147929 | }else{ |
| 147930 | 147930 | assert( pF->pFExpr->pLeft!=0 ); |
| 147931 | 147931 | assert( ExprUseXList(pF->pFExpr->pLeft) ); |
| 147932 | 147932 | assert( pF->pFExpr->pLeft->x.pList!=0 ); |
| 147933 | 147933 | nKey = pF->pFExpr->pLeft->x.pList->nExpr; |
| 147934 | | - if( !pF->bOBUnique ) nKey++; |
| 147934 | + if( ALWAYS(!pF->bOBUnique) ) nKey++; |
| 147935 | 147935 | } |
| 147936 | 147936 | iTop = sqlite3VdbeAddOp1(v, OP_Rewind, pF->iOBTab); VdbeCoverage(v); |
| 147937 | 147937 | for(j=nArg-1; j>=0; j--){ |
| 147938 | 147938 | sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, nKey+j, regAgg+j); |
| 147939 | 147939 | } |
| | @@ -147985,10 +147985,11 @@ |
| 147985 | 147985 | for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){ |
| 147986 | 147986 | int nArg; |
| 147987 | 147987 | int addrNext = 0; |
| 147988 | 147988 | int regAgg; |
| 147989 | 147989 | int regAggSz = 0; |
| 147990 | + int regDistinct = 0; |
| 147990 | 147991 | ExprList *pList; |
| 147991 | 147992 | assert( ExprUseXList(pF->pFExpr) ); |
| 147992 | 147993 | assert( !IsWindowFunc(pF->pFExpr) ); |
| 147993 | 147994 | pList = pF->pFExpr->x.pList; |
| 147994 | 147995 | if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){ |
| | @@ -148034,22 +148035,25 @@ |
| 148034 | 148035 | if( pF->bOBPayload ){ |
| 148035 | 148036 | regAggSz += nArg; |
| 148036 | 148037 | } |
| 148037 | 148038 | regAggSz++; /* One extra register to hold result of MakeRecord */ |
| 148038 | 148039 | regAgg = sqlite3GetTempRange(pParse, regAggSz); |
| 148040 | + regDistinct = regAgg; |
| 148039 | 148041 | sqlite3ExprCodeExprList(pParse, pOBList, regAgg, 0, SQLITE_ECEL_DUP); |
| 148040 | 148042 | jj = pOBList->nExpr; |
| 148041 | 148043 | if( !pF->bOBUnique ){ |
| 148042 | 148044 | sqlite3VdbeAddOp2(v, OP_Sequence, pF->iOBTab, regAgg+jj); |
| 148043 | 148045 | jj++; |
| 148044 | 148046 | } |
| 148045 | 148047 | if( pF->bOBPayload ){ |
| 148046 | | - sqlite3ExprCodeExprList(pParse, pList, regAgg+jj, 0, SQLITE_ECEL_DUP); |
| 148048 | + regDistinct = regAgg+jj; |
| 148049 | + sqlite3ExprCodeExprList(pParse, pList, regDistinct, 0, SQLITE_ECEL_DUP); |
| 148047 | 148050 | } |
| 148048 | 148051 | }else if( pList ){ |
| 148049 | 148052 | nArg = pList->nExpr; |
| 148050 | 148053 | regAgg = sqlite3GetTempRange(pParse, nArg); |
| 148054 | + regDistinct = regAgg; |
| 148051 | 148055 | sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); |
| 148052 | 148056 | }else{ |
| 148053 | 148057 | nArg = 0; |
| 148054 | 148058 | regAgg = 0; |
| 148055 | 148059 | } |
| | @@ -148056,11 +148060,11 @@ |
| 148056 | 148060 | if( pF->iDistinct>=0 && pList ){ |
| 148057 | 148061 | if( addrNext==0 ){ |
| 148058 | 148062 | addrNext = sqlite3VdbeMakeLabel(pParse); |
| 148059 | 148063 | } |
| 148060 | 148064 | pF->iDistinct = codeDistinct(pParse, eDistinctType, |
| 148061 | | - pF->iDistinct, addrNext, pList, regAgg); |
| 148065 | + pF->iDistinct, addrNext, pList, regDistinct); |
| 148062 | 148066 | } |
| 148063 | 148067 | if( pF->iOBTab>=0 ){ |
| 148064 | 148068 | /* Insert a new record into the ORDER BY table */ |
| 148065 | 148069 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regAgg, regAggSz-1, |
| 148066 | 148070 | regAgg+regAggSz-1); |
| | @@ -150934,14 +150938,21 @@ |
| 150934 | 150938 | Returning *pReturning; |
| 150935 | 150939 | Select sSelect; |
| 150936 | 150940 | SrcList sFrom; |
| 150937 | 150941 | |
| 150938 | 150942 | assert( v!=0 ); |
| 150939 | | - assert( pParse->bReturning ); |
| 150943 | + if( !pParse->bReturning ){ |
| 150944 | + /* This RETURNING trigger must be for a different statement as |
| 150945 | + ** this statement lacks a RETURNING clause. */ |
| 150946 | + return; |
| 150947 | + } |
| 150940 | 150948 | assert( db->pParse==pParse ); |
| 150941 | 150949 | pReturning = pParse->u1.pReturning; |
| 150942 | | - assert( pTrigger == &(pReturning->retTrig) ); |
| 150950 | + if( pTrigger != &(pReturning->retTrig) ){ |
| 150951 | + /* This RETURNING trigger is for a different statement */ |
| 150952 | + return; |
| 150953 | + } |
| 150943 | 150954 | memset(&sSelect, 0, sizeof(sSelect)); |
| 150944 | 150955 | memset(&sFrom, 0, sizeof(sFrom)); |
| 150945 | 150956 | sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); |
| 150946 | 150957 | sSelect.pSrc = &sFrom; |
| 150947 | 150958 | sFrom.nSrc = 1; |
| | @@ -177852,11 +177863,13 @@ |
| 177852 | 177863 | } |
| 177853 | 177864 | #endif |
| 177854 | 177865 | |
| 177855 | 177866 | /* Experimentally determine if high-precision floating point is |
| 177856 | 177867 | ** available. */ |
| 177868 | +#ifndef SQLITE_OMIT_WSD |
| 177857 | 177869 | sqlite3Config.bUseLongDouble = hasHighPrecisionDouble(rc); |
| 177870 | +#endif |
| 177858 | 177871 | |
| 177859 | 177872 | return rc; |
| 177860 | 177873 | } |
| 177861 | 177874 | |
| 177862 | 177875 | /* |
| | @@ -187833,31 +187846,40 @@ |
| 187833 | 187846 | |
| 187834 | 187847 | /* |
| 187835 | 187848 | ** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual |
| 187836 | 187849 | ** table. |
| 187837 | 187850 | */ |
| 187838 | | -static int fts3Integrity(sqlite3_vtab *pVtab, char **pzErr){ |
| 187851 | +static int fts3Integrity( |
| 187852 | + sqlite3_vtab *pVtab, /* The virtual table to be checked */ |
| 187853 | + const char *zSchema, /* Name of schema in which pVtab lives */ |
| 187854 | + const char *zTabname, /* Name of the pVTab table */ |
| 187855 | + int isQuick, /* True if this is a quick_check */ |
| 187856 | + char **pzErr /* Write error message here */ |
| 187857 | +){ |
| 187839 | 187858 | Fts3Table *p = (Fts3Table*)pVtab; |
| 187840 | 187859 | char *zSql; |
| 187841 | 187860 | int rc; |
| 187842 | 187861 | char *zErr = 0; |
| 187843 | 187862 | |
| 187863 | + assert( pzErr!=0 ); |
| 187864 | + assert( *pzErr==0 ); |
| 187865 | + UNUSED_PARAMETER(isQuick); |
| 187844 | 187866 | zSql = sqlite3_mprintf( |
| 187845 | 187867 | "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');", |
| 187846 | | - p->zDb, p->zName, p->zName); |
| 187868 | + zSchema, zTabname, zTabname); |
| 187847 | 187869 | if( zSql==0 ){ |
| 187848 | 187870 | return SQLITE_NOMEM; |
| 187849 | 187871 | } |
| 187850 | 187872 | rc = sqlite3_exec(p->db, zSql, 0, 0, &zErr); |
| 187851 | 187873 | sqlite3_free(zSql); |
| 187852 | 187874 | if( (rc&0xff)==SQLITE_CORRUPT ){ |
| 187853 | 187875 | *pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s", |
| 187854 | | - p->bFts4 ? 4 : 3, p->zDb, p->zName); |
| 187876 | + p->bFts4 ? 4 : 3, zSchema, zTabname); |
| 187855 | 187877 | }else if( rc!=SQLITE_OK ){ |
| 187856 | 187878 | *pzErr = sqlite3_mprintf("unable to validate the inverted index for" |
| 187857 | 187879 | " FTS%d table %s.%s: %s", |
| 187858 | | - p->bFts4 ? 4 : 3, p->zDb, p->zName, zErr); |
| 187880 | + p->bFts4 ? 4 : 3, zSchema, zTabname, zErr); |
| 187859 | 187881 | } |
| 187860 | 187882 | sqlite3_free(zErr); |
| 187861 | 187883 | return SQLITE_OK; |
| 187862 | 187884 | } |
| 187863 | 187885 | |
| | @@ -209716,11 +209738,11 @@ |
| 209716 | 209738 | } |
| 209717 | 209739 | return 0; |
| 209718 | 209740 | } |
| 209719 | 209741 | |
| 209720 | 209742 | /* Forward declaration */ |
| 209721 | | -static int rtreeIntegrity(sqlite3_vtab*, char**); |
| 209743 | +static int rtreeIntegrity(sqlite3_vtab*, const char*, const char*, int, char**); |
| 209722 | 209744 | |
| 209723 | 209745 | static sqlite3_module rtreeModule = { |
| 209724 | 209746 | 4, /* iVersion */ |
| 209725 | 209747 | rtreeCreate, /* xCreate - create a table */ |
| 209726 | 209748 | rtreeConnect, /* xConnect - connect to an existing table */ |
| | @@ -210571,13 +210593,23 @@ |
| 210571 | 210593 | } |
| 210572 | 210594 | |
| 210573 | 210595 | /* |
| 210574 | 210596 | ** Implementation of the xIntegrity method for Rtree. |
| 210575 | 210597 | */ |
| 210576 | | -static int rtreeIntegrity(sqlite3_vtab *pVtab, char **pzErr){ |
| 210598 | +static int rtreeIntegrity( |
| 210599 | + sqlite3_vtab *pVtab, /* The virtual table to check */ |
| 210600 | + const char *zSchema, /* Schema in which the virtual table lives */ |
| 210601 | + const char *zName, /* Name of the virtual table */ |
| 210602 | + int isQuick, /* True for a quick_check */ |
| 210603 | + char **pzErr /* Write results here */ |
| 210604 | +){ |
| 210577 | 210605 | Rtree *pRtree = (Rtree*)pVtab; |
| 210578 | 210606 | int rc; |
| 210607 | + assert( pzErr!=0 && *pzErr==0 ); |
| 210608 | + UNUSED_PARAMETER(zSchema); |
| 210609 | + UNUSED_PARAMETER(zName); |
| 210610 | + UNUSED_PARAMETER(isQuick); |
| 210579 | 210611 | rc = rtreeCheckTable(pRtree->db, pRtree->zDb, pRtree->zName, pzErr); |
| 210580 | 210612 | if( rc==SQLITE_OK && *pzErr ){ |
| 210581 | 210613 | *pzErr = sqlite3_mprintf("In RTree %s.%s:\n%z", |
| 210582 | 210614 | pRtree->zDb, pRtree->zName, *pzErr); |
| 210583 | 210615 | } |
| | @@ -222168,11 +222200,11 @@ |
| 222168 | 222200 | pSession->nMaxChangesetSize -= sessionVarintLen(nOldCol); |
| 222169 | 222201 | } |
| 222170 | 222202 | } |
| 222171 | 222203 | } |
| 222172 | 222204 | |
| 222173 | | - sqlite3_free(azCol); |
| 222205 | + sqlite3_free((char*)azCol); |
| 222174 | 222206 | return pSession->rc; |
| 222175 | 222207 | } |
| 222176 | 222208 | |
| 222177 | 222209 | /* |
| 222178 | 222210 | ** Session-change object (*pp) contains an old.* record with fewer than |
| | @@ -230436,19 +230468,23 @@ |
| 230436 | 230468 | /************************************************************************* |
| 230437 | 230469 | ** Start of highlight() implementation. |
| 230438 | 230470 | */ |
| 230439 | 230471 | typedef struct HighlightContext HighlightContext; |
| 230440 | 230472 | struct HighlightContext { |
| 230441 | | - CInstIter iter; /* Coalesced Instance Iterator */ |
| 230442 | | - int iPos; /* Current token offset in zIn[] */ |
| 230473 | + /* Constant parameters to fts5HighlightCb() */ |
| 230443 | 230474 | int iRangeStart; /* First token to include */ |
| 230444 | 230475 | int iRangeEnd; /* If non-zero, last token to include */ |
| 230445 | 230476 | const char *zOpen; /* Opening highlight */ |
| 230446 | 230477 | const char *zClose; /* Closing highlight */ |
| 230447 | 230478 | const char *zIn; /* Input text */ |
| 230448 | 230479 | int nIn; /* Size of input text in bytes */ |
| 230449 | | - int iOff; /* Current offset within zIn[] */ |
| 230480 | + |
| 230481 | + /* Variables modified by fts5HighlightCb() */ |
| 230482 | + CInstIter iter; /* Coalesced Instance Iterator */ |
| 230483 | + int iPos; /* Current token offset in zIn[] */ |
| 230484 | + int iOff; /* Have copied up to this offset in zIn[] */ |
| 230485 | + int bOpen; /* True if highlight is open */ |
| 230450 | 230486 | char *zOut; /* Output value */ |
| 230451 | 230487 | }; |
| 230452 | 230488 | |
| 230453 | 230489 | /* |
| 230454 | 230490 | ** Append text to the HighlightContext output string - p->zOut. Argument |
| | @@ -230477,12 +230513,12 @@ |
| 230477 | 230513 | static int fts5HighlightCb( |
| 230478 | 230514 | void *pContext, /* Pointer to HighlightContext object */ |
| 230479 | 230515 | int tflags, /* Mask of FTS5_TOKEN_* flags */ |
| 230480 | 230516 | const char *pToken, /* Buffer containing token */ |
| 230481 | 230517 | int nToken, /* Size of token in bytes */ |
| 230482 | | - int iStartOff, /* Start offset of token */ |
| 230483 | | - int iEndOff /* End offset of token */ |
| 230518 | + int iStartOff, /* Start byte offset of token */ |
| 230519 | + int iEndOff /* End byte offset of token */ |
| 230484 | 230520 | ){ |
| 230485 | 230521 | HighlightContext *p = (HighlightContext*)pContext; |
| 230486 | 230522 | int rc = SQLITE_OK; |
| 230487 | 230523 | int iPos; |
| 230488 | 230524 | |
| | @@ -230494,34 +230530,51 @@ |
| 230494 | 230530 | if( p->iRangeEnd>=0 ){ |
| 230495 | 230531 | if( iPos<p->iRangeStart || iPos>p->iRangeEnd ) return SQLITE_OK; |
| 230496 | 230532 | if( p->iRangeStart && iPos==p->iRangeStart ) p->iOff = iStartOff; |
| 230497 | 230533 | } |
| 230498 | 230534 | |
| 230499 | | - if( iPos==p->iter.iStart ){ |
| 230535 | + /* If the parenthesis is open, and this token is not part of the current |
| 230536 | + ** phrase, and the starting byte offset of this token is past the point |
| 230537 | + ** that has currently been copied into the output buffer, close the |
| 230538 | + ** parenthesis. */ |
| 230539 | + if( p->bOpen |
| 230540 | + && (iPos<=p->iter.iStart || p->iter.iStart<0) |
| 230541 | + && iStartOff>p->iOff |
| 230542 | + ){ |
| 230543 | + fts5HighlightAppend(&rc, p, p->zClose, -1); |
| 230544 | + p->bOpen = 0; |
| 230545 | + } |
| 230546 | + |
| 230547 | + /* If this is the start of a new phrase, and the highlight is not open: |
| 230548 | + ** |
| 230549 | + ** * copy text from the input up to the start of the phrase, and |
| 230550 | + ** * open the highlight. |
| 230551 | + */ |
| 230552 | + if( iPos==p->iter.iStart && p->bOpen==0 ){ |
| 230500 | 230553 | fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iStartOff - p->iOff); |
| 230501 | 230554 | fts5HighlightAppend(&rc, p, p->zOpen, -1); |
| 230502 | 230555 | p->iOff = iStartOff; |
| 230556 | + p->bOpen = 1; |
| 230503 | 230557 | } |
| 230504 | 230558 | |
| 230505 | 230559 | if( iPos==p->iter.iEnd ){ |
| 230506 | | - if( p->iRangeEnd>=0 && p->iter.iStart<p->iRangeStart ){ |
| 230560 | + if( p->bOpen==0 ){ |
| 230561 | + assert( p->iRangeEnd>=0 ); |
| 230507 | 230562 | fts5HighlightAppend(&rc, p, p->zOpen, -1); |
| 230563 | + p->bOpen = 1; |
| 230508 | 230564 | } |
| 230509 | 230565 | fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); |
| 230510 | | - fts5HighlightAppend(&rc, p, p->zClose, -1); |
| 230511 | 230566 | p->iOff = iEndOff; |
| 230567 | + |
| 230512 | 230568 | if( rc==SQLITE_OK ){ |
| 230513 | 230569 | rc = fts5CInstIterNext(&p->iter); |
| 230514 | 230570 | } |
| 230515 | 230571 | } |
| 230516 | 230572 | |
| 230517 | | - if( p->iRangeEnd>=0 && iPos==p->iRangeEnd ){ |
| 230573 | + if( iPos==p->iRangeEnd ){ |
| 230518 | 230574 | fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); |
| 230519 | 230575 | p->iOff = iEndOff; |
| 230520 | | - if( iPos>=p->iter.iStart && iPos<p->iter.iEnd ){ |
| 230521 | | - fts5HighlightAppend(&rc, p, p->zClose, -1); |
| 230522 | | - } |
| 230523 | 230576 | } |
| 230524 | 230577 | |
| 230525 | 230578 | return rc; |
| 230526 | 230579 | } |
| 230527 | 230580 | |
| | @@ -230558,10 +230611,13 @@ |
| 230558 | 230611 | } |
| 230559 | 230612 | |
| 230560 | 230613 | if( rc==SQLITE_OK ){ |
| 230561 | 230614 | rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); |
| 230562 | 230615 | } |
| 230616 | + if( ctx.bOpen ){ |
| 230617 | + fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); |
| 230618 | + } |
| 230563 | 230619 | fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); |
| 230564 | 230620 | |
| 230565 | 230621 | if( rc==SQLITE_OK ){ |
| 230566 | 230622 | sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); |
| 230567 | 230623 | } |
| | @@ -230836,10 +230892,13 @@ |
| 230836 | 230892 | } |
| 230837 | 230893 | |
| 230838 | 230894 | if( rc==SQLITE_OK ){ |
| 230839 | 230895 | rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); |
| 230840 | 230896 | } |
| 230897 | + if( ctx.bOpen ){ |
| 230898 | + fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); |
| 230899 | + } |
| 230841 | 230900 | if( ctx.iRangeEnd>=(nColSize-1) ){ |
| 230842 | 230901 | fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); |
| 230843 | 230902 | }else{ |
| 230844 | 230903 | fts5HighlightAppend(&rc, &ctx, zEllips, -1); |
| 230845 | 230904 | } |
| | @@ -247437,11 +247496,11 @@ |
| 247437 | 247496 | int nArg, /* Number of args */ |
| 247438 | 247497 | sqlite3_value **apUnused /* Function arguments */ |
| 247439 | 247498 | ){ |
| 247440 | 247499 | assert( nArg==0 ); |
| 247441 | 247500 | UNUSED_PARAM2(nArg, apUnused); |
| 247442 | | - sqlite3_result_text(pCtx, "fts5: 2023-10-23 23:34:53 9d388267e4e6724e2df333fe09d509e87defcfe984c5c2ebe031152d320812d0", -1, SQLITE_TRANSIENT); |
| 247501 | + sqlite3_result_text(pCtx, "fts5: 2023-10-29 20:05:18 ddc6ead6453e0f98943bd07aedd90d47bc2e9e9e27b008d493491168bea2b3f1", -1, SQLITE_TRANSIENT); |
| 247443 | 247502 | } |
| 247444 | 247503 | |
| 247445 | 247504 | /* |
| 247446 | 247505 | ** Return true if zName is the extension on one of the shadow tables used |
| 247447 | 247506 | ** by this module. |
| | @@ -247460,29 +247519,37 @@ |
| 247460 | 247519 | /* |
| 247461 | 247520 | ** Run an integrity check on the FTS5 data structures. Return a string |
| 247462 | 247521 | ** if anything is found amiss. Return a NULL pointer if everything is |
| 247463 | 247522 | ** OK. |
| 247464 | 247523 | */ |
| 247465 | | -static int fts5Integrity(sqlite3_vtab *pVtab, char **pzErr){ |
| 247524 | +static int fts5Integrity( |
| 247525 | + sqlite3_vtab *pVtab, /* the FTS5 virtual table to check */ |
| 247526 | + const char *zSchema, /* Name of schema in which this table lives */ |
| 247527 | + const char *zTabname, /* Name of the table itself */ |
| 247528 | + int isQuick, /* True if this is a quick-check */ |
| 247529 | + char **pzErr /* Write error message here */ |
| 247530 | +){ |
| 247466 | 247531 | Fts5FullTable *pTab = (Fts5FullTable*)pVtab; |
| 247467 | 247532 | Fts5Config *pConfig = pTab->p.pConfig; |
| 247468 | 247533 | char *zSql; |
| 247469 | 247534 | char *zErr = 0; |
| 247470 | 247535 | int rc; |
| 247536 | + assert( pzErr!=0 && *pzErr==0 ); |
| 247537 | + UNUSED_PARAM(isQuick); |
| 247471 | 247538 | zSql = sqlite3_mprintf( |
| 247472 | 247539 | "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');", |
| 247473 | | - pConfig->zDb, pConfig->zName, pConfig->zName); |
| 247540 | + zSchema, zTabname, pConfig->zName); |
| 247474 | 247541 | if( zSql==0 ) return SQLITE_NOMEM; |
| 247475 | 247542 | rc = sqlite3_exec(pConfig->db, zSql, 0, 0, &zErr); |
| 247476 | 247543 | sqlite3_free(zSql); |
| 247477 | 247544 | if( (rc&0xff)==SQLITE_CORRUPT ){ |
| 247478 | 247545 | *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s", |
| 247479 | | - pConfig->zDb, pConfig->zName); |
| 247546 | + zSchema, zTabname); |
| 247480 | 247547 | }else if( rc!=SQLITE_OK ){ |
| 247481 | 247548 | *pzErr = sqlite3_mprintf("unable to validate the inverted index for" |
| 247482 | 247549 | " FTS5 table %s.%s: %s", |
| 247483 | | - pConfig->zDb, pConfig->zName, zErr); |
| 247550 | + zSchema, zTabname, zErr); |
| 247484 | 247551 | } |
| 247485 | 247552 | sqlite3_free(zErr); |
| 247486 | 247553 | return SQLITE_OK; |
| 247487 | 247554 | } |
| 247488 | 247555 | |
| 247489 | 247556 | |