| | @@ -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 | | -** 27d4a89a5ff96b7b7fc5dc9650e1269f7c7e. |
| 21 | +** bcac937526d9a6ef914a74b4d6757fa91cd7. |
| 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.45.0" |
| 463 | 463 | #define SQLITE_VERSION_NUMBER 3045000 |
| 464 | | -#define SQLITE_SOURCE_ID "2023-12-14 16:34:47 27d4a89a5ff96b7b7fc5dc9650e1269f7c7edf91de9b9aafce40be9ecc8b95e9" |
| 464 | +#define SQLITE_SOURCE_ID "2024-01-01 19:20:00 bcac937526d9a6ef914a74b4d6757fa91cd74edab871bcd934fde4a2f9b6debd" |
| 465 | 465 | |
| 466 | 466 | /* |
| 467 | 467 | ** CAPI3REF: Run-Time Library Version Numbers |
| 468 | 468 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 469 | 469 | ** |
| | @@ -8350,13 +8350,15 @@ |
| 8350 | 8350 | ** can enter.)^ If the same thread tries to enter any mutex other |
| 8351 | 8351 | ** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined. |
| 8352 | 8352 | ** |
| 8353 | 8353 | ** ^(Some systems (for example, Windows 95) do not support the operation |
| 8354 | 8354 | ** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() |
| 8355 | | -** will always return SQLITE_BUSY. The SQLite core only ever uses |
| 8356 | | -** sqlite3_mutex_try() as an optimization so this is acceptable |
| 8357 | | -** behavior.)^ |
| 8355 | +** will always return SQLITE_BUSY. In most cases the SQLite core only uses |
| 8356 | +** sqlite3_mutex_try() as an optimization, so this is acceptable |
| 8357 | +** behavior. The exceptions are unix builds that set the |
| 8358 | +** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working |
| 8359 | +** sqlite3_mutex_try() is required.)^ |
| 8358 | 8360 | ** |
| 8359 | 8361 | ** ^The sqlite3_mutex_leave() routine exits a mutex that was |
| 8360 | 8362 | ** previously entered by the same thread. The behavior |
| 8361 | 8363 | ** is undefined if the mutex is not currently entered by the |
| 8362 | 8364 | ** calling thread or is not currently allocated. |
| | @@ -13125,23 +13127,28 @@ |
| 13125 | 13127 | ** |
| 13126 | 13128 | ** This function may be quite inefficient if used with an FTS5 table |
| 13127 | 13129 | ** created with the "columnsize=0" option. |
| 13128 | 13130 | ** |
| 13129 | 13131 | ** xColumnText: |
| 13130 | | -** This function attempts to retrieve the text of column iCol of the |
| 13131 | | -** current document. If successful, (*pz) is set to point to a buffer |
| 13132 | +** If parameter iCol is less than zero, or greater than or equal to the |
| 13133 | +** number of columns in the table, SQLITE_RANGE is returned. |
| 13134 | +** |
| 13135 | +** Otherwise, this function attempts to retrieve the text of column iCol of |
| 13136 | +** the current document. If successful, (*pz) is set to point to a buffer |
| 13132 | 13137 | ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes |
| 13133 | 13138 | ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, |
| 13134 | 13139 | ** if an error occurs, an SQLite error code is returned and the final values |
| 13135 | 13140 | ** of (*pz) and (*pn) are undefined. |
| 13136 | 13141 | ** |
| 13137 | 13142 | ** xPhraseCount: |
| 13138 | 13143 | ** Returns the number of phrases in the current query expression. |
| 13139 | 13144 | ** |
| 13140 | 13145 | ** xPhraseSize: |
| 13141 | | -** Returns the number of tokens in phrase iPhrase of the query. Phrases |
| 13142 | | -** are numbered starting from zero. |
| 13146 | +** If parameter iCol is less than zero, or greater than or equal to the |
| 13147 | +** number of phrases in the current query, as returned by xPhraseCount, |
| 13148 | +** 0 is returned. Otherwise, this function returns the number of tokens in |
| 13149 | +** phrase iPhrase of the query. Phrases are numbered starting from zero. |
| 13143 | 13150 | ** |
| 13144 | 13151 | ** xInstCount: |
| 13145 | 13152 | ** Set *pnInst to the total number of occurrences of all phrases within |
| 13146 | 13153 | ** the query within the current row. Return SQLITE_OK if successful, or |
| 13147 | 13154 | ** an error code (i.e. SQLITE_NOMEM) if an error occurs. |
| | @@ -13153,16 +13160,17 @@ |
| 13153 | 13160 | ** |
| 13154 | 13161 | ** xInst: |
| 13155 | 13162 | ** Query for the details of phrase match iIdx within the current row. |
| 13156 | 13163 | ** Phrase matches are numbered starting from zero, so the iIdx argument |
| 13157 | 13164 | ** should be greater than or equal to zero and smaller than the value |
| 13158 | | -** output by xInstCount(). |
| 13165 | +** output by xInstCount(). If iIdx is less than zero or greater than |
| 13166 | +** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. |
| 13159 | 13167 | ** |
| 13160 | | -** Usually, output parameter *piPhrase is set to the phrase number, *piCol |
| 13168 | +** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol |
| 13161 | 13169 | ** to the column in which it occurs and *piOff the token offset of the |
| 13162 | | -** first token of the phrase. Returns SQLITE_OK if successful, or an error |
| 13163 | | -** code (i.e. SQLITE_NOMEM) if an error occurs. |
| 13170 | +** first token of the phrase. SQLITE_OK is returned if successful, or an |
| 13171 | +** error code (i.e. SQLITE_NOMEM) if an error occurs. |
| 13164 | 13172 | ** |
| 13165 | 13173 | ** This API can be quite slow if used with an FTS5 table created with the |
| 13166 | 13174 | ** "detail=none" or "detail=column" option. |
| 13167 | 13175 | ** |
| 13168 | 13176 | ** xRowid: |
| | @@ -13183,10 +13191,14 @@ |
| 13183 | 13191 | ** row visited, the callback function passed as the fourth argument |
| 13184 | 13192 | ** is invoked. The context and API objects passed to the callback |
| 13185 | 13193 | ** function may be used to access the properties of each matched row. |
| 13186 | 13194 | ** Invoking Api.xUserData() returns a copy of the pointer passed as |
| 13187 | 13195 | ** the third argument to pUserData. |
| 13196 | +** |
| 13197 | +** If parameter iPhrase is less than zero, or greater than or equal to |
| 13198 | +** the number of phrases in the query, as returned by xPhraseCount(), |
| 13199 | +** this function returns SQLITE_RANGE. |
| 13188 | 13200 | ** |
| 13189 | 13201 | ** If the callback function returns any value other than SQLITE_OK, the |
| 13190 | 13202 | ** query is abandoned and the xQueryPhrase function returns immediately. |
| 13191 | 13203 | ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. |
| 13192 | 13204 | ** Otherwise, the error code is propagated upwards. |
| | @@ -13304,22 +13316,30 @@ |
| 13304 | 13316 | ** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken) |
| 13305 | 13317 | ** This is used to access token iToken of phrase iPhrase of the current |
| 13306 | 13318 | ** query. Before returning, output parameter *ppToken is set to point |
| 13307 | 13319 | ** to a buffer containing the requested token, and *pnToken to the |
| 13308 | 13320 | ** size of this buffer in bytes. |
| 13321 | +** |
| 13322 | +** If iPhrase or iToken are less than zero, or if iPhrase is greater than |
| 13323 | +** or equal to the number of phrases in the query as reported by |
| 13324 | +** xPhraseCount(), or if iToken is equal to or greater than the number of |
| 13325 | +** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken |
| 13326 | + are both zeroed. |
| 13309 | 13327 | ** |
| 13310 | 13328 | ** The output text is not a copy of the query text that specified the |
| 13311 | 13329 | ** token. It is the output of the tokenizer module. For tokendata=1 |
| 13312 | 13330 | ** tables, this includes any embedded 0x00 and trailing data. |
| 13313 | 13331 | ** |
| 13314 | 13332 | ** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken) |
| 13315 | 13333 | ** This is used to access token iToken of phrase hit iIdx within the |
| 13316 | | -** current row. Output variable (*ppToken) is set to point to a buffer |
| 13317 | | -** containing the matching document token, and (*pnToken) to the size |
| 13318 | | -** of that buffer in bytes. This API is not available if the specified |
| 13319 | | -** token matches a prefix query term. In that case both output variables |
| 13320 | | -** are always set to 0. |
| 13334 | +** current row. If iIdx is less than zero or greater than or equal to the |
| 13335 | +** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise, |
| 13336 | +** output variable (*ppToken) is set to point to a buffer containing the |
| 13337 | +** matching document token, and (*pnToken) to the size of that buffer in |
| 13338 | +** bytes. This API is not available if the specified token matches a |
| 13339 | +** prefix query term. In that case both output variables are always set |
| 13340 | +** to 0. |
| 13321 | 13341 | ** |
| 13322 | 13342 | ** The output text is not a copy of the document text that was tokenized. |
| 13323 | 13343 | ** It is the output of the tokenizer module. For tokendata=1 tables, this |
| 13324 | 13344 | ** includes any embedded 0x00 and trailing data. |
| 13325 | 13345 | ** |
| | @@ -13991,10 +14011,23 @@ |
| 13991 | 14011 | #if defined(_MSC_VER) && !defined(SQLITE_OMIT_SEH) |
| 13992 | 14012 | # define SQLITE_USE_SEH 1 |
| 13993 | 14013 | #else |
| 13994 | 14014 | # undef SQLITE_USE_SEH |
| 13995 | 14015 | #endif |
| 14016 | + |
| 14017 | +/* |
| 14018 | +** Enable SQLITE_DIRECT_OVERFLOW_READ, unless the build explicitly |
| 14019 | +** disables it using -DSQLITE_DIRECT_OVERFLOW_READ=0 |
| 14020 | +*/ |
| 14021 | +#if defined(SQLITE_DIRECT_OVERFLOW_READ) && SQLITE_DIRECT_OVERFLOW_READ+1==1 |
| 14022 | + /* Disable if -DSQLITE_DIRECT_OVERFLOW_READ=0 */ |
| 14023 | +# undef SQLITE_DIRECT_OVERFLOW_READ |
| 14024 | +#else |
| 14025 | + /* In all other cases, enable */ |
| 14026 | +# define SQLITE_DIRECT_OVERFLOW_READ 1 |
| 14027 | +#endif |
| 14028 | + |
| 13996 | 14029 | |
| 13997 | 14030 | /* |
| 13998 | 14031 | ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. |
| 13999 | 14032 | ** 0 means mutexes are permanently disable and the library is never |
| 14000 | 14033 | ** threadsafe. 1 means the library is serialized which is the highest |
| | @@ -15874,11 +15907,11 @@ |
| 15874 | 15907 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); |
| 15875 | 15908 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*); |
| 15876 | 15909 | SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); |
| 15877 | 15910 | SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); |
| 15878 | 15911 | SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); |
| 15879 | | -SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); |
| 15912 | +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, u64*); |
| 15880 | 15913 | SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); |
| 15881 | 15914 | SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); |
| 15882 | 15915 | |
| 15883 | 15916 | /* Functions used to truncate the database file. */ |
| 15884 | 15917 | SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); |
| | @@ -18629,10 +18662,11 @@ |
| 18629 | 18662 | unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ |
| 18630 | 18663 | unsigned isResized:1; /* True if resizeIndexObject() has been called */ |
| 18631 | 18664 | unsigned isCovering:1; /* True if this is a covering index */ |
| 18632 | 18665 | unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ |
| 18633 | 18666 | unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ |
| 18667 | + unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */ |
| 18634 | 18668 | unsigned bNoQuery:1; /* Do not use this index to optimize queries */ |
| 18635 | 18669 | unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ |
| 18636 | 18670 | unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */ |
| 18637 | 18671 | unsigned bHasExpr:1; /* Index contains an expression, either a literal |
| 18638 | 18672 | ** expression, or a reference to a VIRTUAL column */ |
| | @@ -24028,11 +24062,11 @@ |
| 24028 | 24062 | /* no break */ deliberate_fall_through |
| 24029 | 24063 | case SQLITE_DBSTATUS_CACHE_HIT: |
| 24030 | 24064 | case SQLITE_DBSTATUS_CACHE_MISS: |
| 24031 | 24065 | case SQLITE_DBSTATUS_CACHE_WRITE:{ |
| 24032 | 24066 | int i; |
| 24033 | | - int nRet = 0; |
| 24067 | + u64 nRet = 0; |
| 24034 | 24068 | assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); |
| 24035 | 24069 | assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 ); |
| 24036 | 24070 | |
| 24037 | 24071 | for(i=0; i<db->nDb; i++){ |
| 24038 | 24072 | if( db->aDb[i].pBt ){ |
| | @@ -24041,11 +24075,11 @@ |
| 24041 | 24075 | } |
| 24042 | 24076 | } |
| 24043 | 24077 | *pHighwater = 0; /* IMP: R-42420-56072 */ |
| 24044 | 24078 | /* IMP: R-54100-20147 */ |
| 24045 | 24079 | /* IMP: R-29431-39229 */ |
| 24046 | | - *pCurrent = nRet; |
| 24080 | + *pCurrent = (int)nRet & 0x7fffffff; |
| 24047 | 24081 | break; |
| 24048 | 24082 | } |
| 24049 | 24083 | |
| 24050 | 24084 | /* Set *pCurrent to non-zero if there are unresolved deferred foreign |
| 24051 | 24085 | ** key constraints. Set *pCurrent to zero if all foreign key constraints |
| | @@ -34677,11 +34711,11 @@ |
| 34677 | 34711 | ** Load the sqlite3.iSysErrno field if that is an appropriate thing |
| 34678 | 34712 | ** to do based on the SQLite error code in rc. |
| 34679 | 34713 | */ |
| 34680 | 34714 | SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){ |
| 34681 | 34715 | if( rc==SQLITE_IOERR_NOMEM ) return; |
| 34682 | | -#ifdef SQLITE_USE_SEH |
| 34716 | +#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) |
| 34683 | 34717 | if( rc==SQLITE_IOERR_IN_PAGE ){ |
| 34684 | 34718 | int ii; |
| 34685 | 34719 | int iErr; |
| 34686 | 34720 | sqlite3BtreeEnterAll(db); |
| 34687 | 34721 | for(ii=0; ii<db->nDb; ii++){ |
| | @@ -42365,13 +42399,19 @@ |
| 42365 | 42399 | struct flock f; /* The posix advisory locking structure */ |
| 42366 | 42400 | int rc = SQLITE_OK; /* Result code form fcntl() */ |
| 42367 | 42401 | |
| 42368 | 42402 | pShmNode = pFile->pInode->pShmNode; |
| 42369 | 42403 | |
| 42370 | | - /* Assert that the correct mutex or mutexes are held. */ |
| 42371 | | - if( pShmNode->nRef==0 ){ |
| 42372 | | - assert( ofst==UNIX_SHM_DMS && n==1 && unixMutexHeld() ); |
| 42404 | + /* Assert that the parameters are within expected range and that the |
| 42405 | + ** correct mutex or mutexes are held. */ |
| 42406 | + assert( pShmNode->nRef>=0 ); |
| 42407 | + assert( (ofst==UNIX_SHM_DMS && n==1) |
| 42408 | + || (ofst>=UNIX_SHM_BASE && ofst+n<=(UNIX_SHM_BASE+SQLITE_SHM_NLOCK)) |
| 42409 | + ); |
| 42410 | + if( ofst==UNIX_SHM_DMS ){ |
| 42411 | + assert( pShmNode->nRef>0 || unixMutexHeld() ); |
| 42412 | + assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); |
| 42373 | 42413 | }else{ |
| 42374 | 42414 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 42375 | 42415 | int ii; |
| 42376 | 42416 | for(ii=ofst-UNIX_SHM_BASE; ii<ofst-UNIX_SHM_BASE+n; ii++){ |
| 42377 | 42417 | assert( sqlite3_mutex_held(pShmNode->aMutex[ii]) ); |
| | @@ -57333,11 +57373,11 @@ |
| 57333 | 57373 | i64 journalSizeLimit; /* Size limit for persistent journal files */ |
| 57334 | 57374 | char *zFilename; /* Name of the database file */ |
| 57335 | 57375 | char *zJournal; /* Name of the journal file */ |
| 57336 | 57376 | int (*xBusyHandler)(void*); /* Function to call when busy */ |
| 57337 | 57377 | void *pBusyHandlerArg; /* Context argument for xBusyHandler */ |
| 57338 | | - int aStat[4]; /* Total cache hits, misses, writes, spills */ |
| 57378 | + u32 aStat[4]; /* Total cache hits, misses, writes, spills */ |
| 57339 | 57379 | #ifdef SQLITE_TEST |
| 57340 | 57380 | int nRead; /* Database pages read */ |
| 57341 | 57381 | #endif |
| 57342 | 57382 | void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ |
| 57343 | 57383 | int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */ |
| | @@ -63477,15 +63517,15 @@ |
| 63477 | 63517 | a[1] = sqlite3PcachePagecount(pPager->pPCache); |
| 63478 | 63518 | a[2] = sqlite3PcacheGetCachesize(pPager->pPCache); |
| 63479 | 63519 | a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; |
| 63480 | 63520 | a[4] = pPager->eState; |
| 63481 | 63521 | a[5] = pPager->errCode; |
| 63482 | | - a[6] = pPager->aStat[PAGER_STAT_HIT]; |
| 63483 | | - a[7] = pPager->aStat[PAGER_STAT_MISS]; |
| 63522 | + a[6] = (int)pPager->aStat[PAGER_STAT_HIT] & 0x7fffffff; |
| 63523 | + a[7] = (int)pPager->aStat[PAGER_STAT_MISS] & 0x7fffffff; |
| 63484 | 63524 | a[8] = 0; /* Used to be pPager->nOvfl */ |
| 63485 | 63525 | a[9] = pPager->nRead; |
| 63486 | | - a[10] = pPager->aStat[PAGER_STAT_WRITE]; |
| 63526 | + a[10] = (int)pPager->aStat[PAGER_STAT_WRITE] & 0x7fffffff; |
| 63487 | 63527 | return a; |
| 63488 | 63528 | } |
| 63489 | 63529 | #endif |
| 63490 | 63530 | |
| 63491 | 63531 | /* |
| | @@ -63497,11 +63537,11 @@ |
| 63497 | 63537 | ** Before returning, *pnVal is incremented by the |
| 63498 | 63538 | ** current cache hit or miss count, according to the value of eStat. If the |
| 63499 | 63539 | ** reset parameter is non-zero, the cache hit or miss count is zeroed before |
| 63500 | 63540 | ** returning. |
| 63501 | 63541 | */ |
| 63502 | | -SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){ |
| 63542 | +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, u64 *pnVal){ |
| 63503 | 63543 | |
| 63504 | 63544 | assert( eStat==SQLITE_DBSTATUS_CACHE_HIT |
| 63505 | 63545 | || eStat==SQLITE_DBSTATUS_CACHE_MISS |
| 63506 | 63546 | || eStat==SQLITE_DBSTATUS_CACHE_WRITE |
| 63507 | 63547 | || eStat==SQLITE_DBSTATUS_CACHE_WRITE+1 |
| | @@ -64437,11 +64477,11 @@ |
| 64437 | 64477 | assert( pPager->eState>=PAGER_READER ); |
| 64438 | 64478 | return sqlite3WalFramesize(pPager->pWal); |
| 64439 | 64479 | } |
| 64440 | 64480 | #endif |
| 64441 | 64481 | |
| 64442 | | -#ifdef SQLITE_USE_SEH |
| 64482 | +#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) |
| 64443 | 64483 | SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){ |
| 64444 | 64484 | return sqlite3WalSystemErrno(pPager->pWal); |
| 64445 | 64485 | } |
| 64446 | 64486 | #endif |
| 64447 | 64487 | |
| | @@ -106789,10 +106829,11 @@ |
| 106789 | 106829 | sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); |
| 106790 | 106830 | } |
| 106791 | 106831 | sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); |
| 106792 | 106832 | pParse->checkSchema = 1; |
| 106793 | 106833 | pTopNC->nNcErr++; |
| 106834 | + eNewExprOp = TK_NULL; |
| 106794 | 106835 | } |
| 106795 | 106836 | assert( pFJMatch==0 ); |
| 106796 | 106837 | |
| 106797 | 106838 | /* Remove all substructure from pExpr */ |
| 106798 | 106839 | if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ |
| | @@ -110976,13 +111017,14 @@ |
| 110976 | 111017 | case TK_BLOB: |
| 110977 | 111018 | return 0; |
| 110978 | 111019 | case TK_COLUMN: |
| 110979 | 111020 | assert( ExprUseYTab(p) ); |
| 110980 | 111021 | return ExprHasProperty(p, EP_CanBeNull) || |
| 110981 | | - p->y.pTab==0 || /* Reference to column of index on expression */ |
| 111022 | + NEVER(p->y.pTab==0) || /* Reference to column of index on expr */ |
| 110982 | 111023 | (p->iColumn>=0 |
| 110983 | 111024 | && p->y.pTab->aCol!=0 /* Possible due to prior error */ |
| 111025 | + && ALWAYS(p->iColumn<p->y.pTab->nCol) |
| 110984 | 111026 | && p->y.pTab->aCol[p->iColumn].notNull==0); |
| 110985 | 111027 | default: |
| 110986 | 111028 | return 1; |
| 110987 | 111029 | } |
| 110988 | 111030 | } |
| | @@ -113560,12 +113602,14 @@ |
| 113560 | 113602 | assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); |
| 113561 | 113603 | if( pParse->pVdbe==0 ) return; |
| 113562 | 113604 | inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); |
| 113563 | 113605 | if( inReg!=target ){ |
| 113564 | 113606 | u8 op; |
| 113565 | | - if( ALWAYS(pExpr) |
| 113566 | | - && (ExprHasProperty(pExpr,EP_Subquery) || pExpr->op==TK_REGISTER) |
| 113607 | + Expr *pX = sqlite3ExprSkipCollateAndLikely(pExpr); |
| 113608 | + testcase( pX!=pExpr ); |
| 113609 | + if( ALWAYS(pX) |
| 113610 | + && (ExprHasProperty(pX,EP_Subquery) || pX->op==TK_REGISTER) |
| 113567 | 113611 | ){ |
| 113568 | 113612 | op = OP_Copy; |
| 113569 | 113613 | }else{ |
| 113570 | 113614 | op = OP_SCopy; |
| 113571 | 113615 | } |
| | @@ -117825,13 +117869,13 @@ |
| 117825 | 117869 | ** information. |
| 117826 | 117870 | */ |
| 117827 | 117871 | typedef struct StatAccum StatAccum; |
| 117828 | 117872 | typedef struct StatSample StatSample; |
| 117829 | 117873 | struct StatSample { |
| 117830 | | - tRowcnt *anEq; /* sqlite_stat4.nEq */ |
| 117831 | 117874 | tRowcnt *anDLt; /* sqlite_stat4.nDLt */ |
| 117832 | 117875 | #ifdef SQLITE_ENABLE_STAT4 |
| 117876 | + tRowcnt *anEq; /* sqlite_stat4.nEq */ |
| 117833 | 117877 | tRowcnt *anLt; /* sqlite_stat4.nLt */ |
| 117834 | 117878 | union { |
| 117835 | 117879 | i64 iRowid; /* Rowid in main table of the key */ |
| 117836 | 117880 | u8 *aRowid; /* Key for WITHOUT ROWID tables */ |
| 117837 | 117881 | } u; |
| | @@ -117985,13 +118029,13 @@ |
| 117985 | 118029 | assert( nKeyCol<=nCol ); |
| 117986 | 118030 | assert( nKeyCol>0 ); |
| 117987 | 118031 | |
| 117988 | 118032 | /* Allocate the space required for the StatAccum object */ |
| 117989 | 118033 | n = sizeof(*p) |
| 117990 | | - + sizeof(tRowcnt)*nColUp /* StatAccum.anEq */ |
| 117991 | | - + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */ |
| 118034 | + + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */ |
| 117992 | 118035 | #ifdef SQLITE_ENABLE_STAT4 |
| 118036 | + n += sizeof(tRowcnt)*nColUp; /* StatAccum.anEq */ |
| 117993 | 118037 | if( mxSample ){ |
| 117994 | 118038 | n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */ |
| 117995 | 118039 | + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */ |
| 117996 | 118040 | + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample); |
| 117997 | 118041 | } |
| | @@ -118008,13 +118052,13 @@ |
| 118008 | 118052 | p->nLimit = sqlite3_value_int64(argv[3]); |
| 118009 | 118053 | p->nCol = nCol; |
| 118010 | 118054 | p->nKeyCol = nKeyCol; |
| 118011 | 118055 | p->nSkipAhead = 0; |
| 118012 | 118056 | p->current.anDLt = (tRowcnt*)&p[1]; |
| 118013 | | - p->current.anEq = &p->current.anDLt[nColUp]; |
| 118014 | 118057 | |
| 118015 | 118058 | #ifdef SQLITE_ENABLE_STAT4 |
| 118059 | + p->current.anEq = &p->current.anDLt[nColUp]; |
| 118016 | 118060 | p->mxSample = p->nLimit==0 ? mxSample : 0; |
| 118017 | 118061 | if( mxSample ){ |
| 118018 | 118062 | u8 *pSpace; /* Allocated space not yet assigned */ |
| 118019 | 118063 | int i; /* Used to iterate through p->aSample[] */ |
| 118020 | 118064 | |
| | @@ -118277,28 +118321,32 @@ |
| 118277 | 118321 | assert( p->nCol>0 ); |
| 118278 | 118322 | assert( iChng<p->nCol ); |
| 118279 | 118323 | |
| 118280 | 118324 | if( p->nRow==0 ){ |
| 118281 | 118325 | /* This is the first call to this function. Do initialization. */ |
| 118326 | +#ifdef SQLITE_ENABLE_STAT4 |
| 118282 | 118327 | for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1; |
| 118328 | +#endif |
| 118283 | 118329 | }else{ |
| 118284 | 118330 | /* Second and subsequent calls get processed here */ |
| 118285 | 118331 | #ifdef SQLITE_ENABLE_STAT4 |
| 118286 | 118332 | if( p->mxSample ) samplePushPrevious(p, iChng); |
| 118287 | 118333 | #endif |
| 118288 | 118334 | |
| 118289 | 118335 | /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply |
| 118290 | 118336 | ** to the current row of the index. */ |
| 118337 | +#ifdef SQLITE_ENABLE_STAT4 |
| 118291 | 118338 | for(i=0; i<iChng; i++){ |
| 118292 | 118339 | p->current.anEq[i]++; |
| 118293 | 118340 | } |
| 118341 | +#endif |
| 118294 | 118342 | for(i=iChng; i<p->nCol; i++){ |
| 118295 | 118343 | p->current.anDLt[i]++; |
| 118296 | 118344 | #ifdef SQLITE_ENABLE_STAT4 |
| 118297 | 118345 | if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i]; |
| 118298 | | -#endif |
| 118299 | 118346 | p->current.anEq[i] = 1; |
| 118347 | +#endif |
| 118300 | 118348 | } |
| 118301 | 118349 | } |
| 118302 | 118350 | |
| 118303 | 118351 | p->nRow++; |
| 118304 | 118352 | #ifdef SQLITE_ENABLE_STAT4 |
| | @@ -118428,11 +118476,13 @@ |
| 118428 | 118476 | for(i=0; i<p->nKeyCol; i++){ |
| 118429 | 118477 | u64 nDistinct = p->current.anDLt[i] + 1; |
| 118430 | 118478 | u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; |
| 118431 | 118479 | if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1; |
| 118432 | 118480 | sqlite3_str_appendf(&sStat, " %llu", iVal); |
| 118481 | +#ifdef SQLITE_ENABLE_STAT4 |
| 118433 | 118482 | assert( p->current.anEq[i] ); |
| 118483 | +#endif |
| 118434 | 118484 | } |
| 118435 | 118485 | sqlite3ResultStrAccum(context, &sStat); |
| 118436 | 118486 | } |
| 118437 | 118487 | #ifdef SQLITE_ENABLE_STAT4 |
| 118438 | 118488 | else if( eCall==STAT_GET_ROWID ){ |
| | @@ -119117,10 +119167,20 @@ |
| 119117 | 119167 | } |
| 119118 | 119168 | #endif |
| 119119 | 119169 | while( z[0]!=0 && z[0]!=' ' ) z++; |
| 119120 | 119170 | while( z[0]==' ' ) z++; |
| 119121 | 119171 | } |
| 119172 | + |
| 119173 | + /* Set the bLowQual flag if the peak number of rows obtained |
| 119174 | + ** from a full equality match is so large that a full table scan |
| 119175 | + ** seems likely to be faster than using the index. |
| 119176 | + */ |
| 119177 | + if( aLog[0] > 66 /* Index has more than 100 rows */ |
| 119178 | + && aLog[0] <= aLog[nOut-1] /* And only a single value seen */ |
| 119179 | + ){ |
| 119180 | + pIndex->bLowQual = 1; |
| 119181 | + } |
| 119122 | 119182 | } |
| 119123 | 119183 | } |
| 119124 | 119184 | |
| 119125 | 119185 | /* |
| 119126 | 119186 | ** This callback is invoked once for each index when reading the |
| | @@ -148743,11 +148803,11 @@ |
| 148743 | 148803 | pSub->pPrior = 0; |
| 148744 | 148804 | pSub->pNext = 0; |
| 148745 | 148805 | pSub->selFlags |= SF_Aggregate; |
| 148746 | 148806 | pSub->selFlags &= ~SF_Compound; |
| 148747 | 148807 | pSub->nSelectRow = 0; |
| 148748 | | - sqlite3ExprListDelete(db, pSub->pEList); |
| 148808 | + sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList); |
| 148749 | 148809 | pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount; |
| 148750 | 148810 | pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm); |
| 148751 | 148811 | pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0); |
| 148752 | 148812 | sqlite3PExprAddSelect(pParse, pTerm, pSub); |
| 148753 | 148813 | if( pExpr==0 ){ |
| | @@ -154295,11 +154355,10 @@ |
| 154295 | 154355 | assert( sqlite3BtreeHoldsAllMutexes(db) ); |
| 154296 | 154356 | assert( sqlite3_mutex_held(db->mutex) ); |
| 154297 | 154357 | |
| 154298 | 154358 | if( p ){ |
| 154299 | 154359 | db->pDisconnect = 0; |
| 154300 | | - sqlite3ExpirePreparedStatements(db, 0); |
| 154301 | 154360 | do { |
| 154302 | 154361 | VTable *pNext = p->pNext; |
| 154303 | 154362 | sqlite3VtabUnlock(p); |
| 154304 | 154363 | p = pNext; |
| 154305 | 154364 | }while( p ); |
| | @@ -155861,11 +155920,11 @@ |
| 155861 | 155920 | */ |
| 155862 | 155921 | SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet*,int); |
| 155863 | 155922 | #ifdef WHERETRACE_ENABLED |
| 155864 | 155923 | SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC); |
| 155865 | 155924 | SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm); |
| 155866 | | -SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC); |
| 155925 | +SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC); |
| 155867 | 155926 | #endif |
| 155868 | 155927 | SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm( |
| 155869 | 155928 | WhereClause *pWC, /* The WHERE clause to be searched */ |
| 155870 | 155929 | int iCur, /* Cursor number of LHS */ |
| 155871 | 155930 | int iColumn, /* Column number of LHS */ |
| | @@ -162890,21 +162949,38 @@ |
| 162890 | 162949 | #endif |
| 162891 | 162950 | |
| 162892 | 162951 | #ifdef WHERETRACE_ENABLED |
| 162893 | 162952 | /* |
| 162894 | 162953 | ** Print a WhereLoop object for debugging purposes |
| 162954 | +** |
| 162955 | +** Format example: |
| 162956 | +** |
| 162957 | +** .--- Position in WHERE clause rSetup, rRun, nOut ---. |
| 162958 | +** | | |
| 162959 | +** | .--- selfMask nTerm ------. | |
| 162960 | +** | | | | |
| 162961 | +** | | .-- prereq Idx wsFlags----. | | |
| 162962 | +** | | | Name | | | |
| 162963 | +** | | | __|__ nEq ---. ___|__ | __|__ |
| 162964 | +** | / \ / \ / \ | / \ / \ / \ |
| 162965 | +** 1.002.001 t2.t2xy 2 f 010241 N 2 cost 0,56,31 |
| 162895 | 162966 | */ |
| 162896 | | -SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){ |
| 162897 | | - WhereInfo *pWInfo = pWC->pWInfo; |
| 162898 | | - int nb = 1+(pWInfo->pTabList->nSrc+3)/4; |
| 162899 | | - SrcItem *pItem = pWInfo->pTabList->a + p->iTab; |
| 162900 | | - Table *pTab = pItem->pTab; |
| 162901 | | - Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; |
| 162902 | | - sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, |
| 162903 | | - p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); |
| 162904 | | - sqlite3DebugPrintf(" %12s", |
| 162905 | | - pItem->zAlias ? pItem->zAlias : pTab->zName); |
| 162967 | +SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){ |
| 162968 | + if( pWC ){ |
| 162969 | + WhereInfo *pWInfo = pWC->pWInfo; |
| 162970 | + int nb = 1+(pWInfo->pTabList->nSrc+3)/4; |
| 162971 | + SrcItem *pItem = pWInfo->pTabList->a + p->iTab; |
| 162972 | + Table *pTab = pItem->pTab; |
| 162973 | + Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; |
| 162974 | + sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, |
| 162975 | + p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); |
| 162976 | + sqlite3DebugPrintf(" %12s", |
| 162977 | + pItem->zAlias ? pItem->zAlias : pTab->zName); |
| 162978 | + }else{ |
| 162979 | + sqlite3DebugPrintf("%c%2d.%03llx.%03llx %c%d", |
| 162980 | + p->cId, p->iTab, p->maskSelf, p->prereq & 0xfff, p->cId, p->iTab); |
| 162981 | + } |
| 162906 | 162982 | if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ |
| 162907 | 162983 | const char *zName; |
| 162908 | 162984 | if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ |
| 162909 | 162985 | if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){ |
| 162910 | 162986 | int i = sqlite3Strlen30(zName) - 1; |
| | @@ -162936,10 +163012,19 @@ |
| 162936 | 163012 | int i; |
| 162937 | 163013 | for(i=0; i<p->nLTerm; i++){ |
| 162938 | 163014 | sqlite3WhereTermPrint(p->aLTerm[i], i); |
| 162939 | 163015 | } |
| 162940 | 163016 | } |
| 163017 | +} |
| 163018 | +SQLITE_PRIVATE void sqlite3ShowWhereLoop(const WhereLoop *p){ |
| 163019 | + if( p ) sqlite3WhereLoopPrint(p, 0); |
| 163020 | +} |
| 163021 | +SQLITE_PRIVATE void sqlite3ShowWhereLoopList(const WhereLoop *p){ |
| 163022 | + while( p ){ |
| 163023 | + sqlite3ShowWhereLoop(p); |
| 163024 | + p = p->pNextLoop; |
| 163025 | + } |
| 162941 | 163026 | } |
| 162942 | 163027 | #endif |
| 162943 | 163028 | |
| 162944 | 163029 | /* |
| 162945 | 163030 | ** Convert bulk memory into a valid WhereLoop that can be passed |
| | @@ -163049,50 +163134,64 @@ |
| 163049 | 163134 | } |
| 163050 | 163135 | sqlite3DbNNFreeNN(db, pWInfo); |
| 163051 | 163136 | } |
| 163052 | 163137 | |
| 163053 | 163138 | /* |
| 163054 | | -** Return TRUE if all of the following are true: |
| 163055 | | -** |
| 163056 | | -** (1) X has the same or lower cost, or returns the same or fewer rows, |
| 163057 | | -** than Y. |
| 163058 | | -** (2) X uses fewer WHERE clause terms than Y |
| 163059 | | -** (3) Every WHERE clause term used by X is also used by Y |
| 163060 | | -** (4) X skips at least as many columns as Y |
| 163061 | | -** (5) If X is a covering index, than Y is too |
| 163062 | | -** |
| 163063 | | -** Conditions (2) and (3) mean that X is a "proper subset" of Y. |
| 163064 | | -** If X is a proper subset of Y then Y is a better choice and ought |
| 163065 | | -** to have a lower cost. This routine returns TRUE when that cost |
| 163066 | | -** relationship is inverted and needs to be adjusted. Constraint (4) |
| 163067 | | -** was added because if X uses skip-scan less than Y it still might |
| 163068 | | -** deserve a lower cost even if it is a proper subset of Y. Constraint (5) |
| 163069 | | -** was added because a covering index probably deserves to have a lower cost |
| 163070 | | -** than a non-covering index even if it is a proper subset. |
| 163139 | +** Return TRUE if X is a proper subset of Y but is of equal or less cost. |
| 163140 | +** In other words, return true if all constraints of X are also part of Y |
| 163141 | +** and Y has additional constraints that might speed the search that X lacks |
| 163142 | +** but the cost of running X is not more than the cost of running Y. |
| 163143 | +** |
| 163144 | +** In other words, return true if the cost relationwship between X and Y |
| 163145 | +** is inverted and needs to be adjusted. |
| 163146 | +** |
| 163147 | +** Case 1: |
| 163148 | +** |
| 163149 | +** (1a) X and Y use the same index. |
| 163150 | +** (1b) X has fewer == terms than Y |
| 163151 | +** (1c) Neither X nor Y use skip-scan |
| 163152 | +** (1d) X does not have a a greater cost than Y |
| 163153 | +** |
| 163154 | +** Case 2: |
| 163155 | +** |
| 163156 | +** (2a) X has the same or lower cost, or returns the same or fewer rows, |
| 163157 | +** than Y. |
| 163158 | +** (2b) X uses fewer WHERE clause terms than Y |
| 163159 | +** (2c) Every WHERE clause term used by X is also used by Y |
| 163160 | +** (2d) X skips at least as many columns as Y |
| 163161 | +** (2e) If X is a covering index, than Y is too |
| 163071 | 163162 | */ |
| 163072 | 163163 | static int whereLoopCheaperProperSubset( |
| 163073 | 163164 | const WhereLoop *pX, /* First WhereLoop to compare */ |
| 163074 | 163165 | const WhereLoop *pY /* Compare against this WhereLoop */ |
| 163075 | 163166 | ){ |
| 163076 | 163167 | int i, j; |
| 163168 | + if( pX->rRun>pY->rRun && pX->nOut>pY->nOut ) return 0; /* (1d) and (2a) */ |
| 163169 | + assert( (pX->wsFlags & WHERE_VIRTUALTABLE)==0 ); |
| 163170 | + assert( (pY->wsFlags & WHERE_VIRTUALTABLE)==0 ); |
| 163171 | + if( pX->u.btree.nEq < pY->u.btree.nEq /* (1b) */ |
| 163172 | + && pX->u.btree.pIndex==pY->u.btree.pIndex /* (1a) */ |
| 163173 | + && pX->nSkip==0 && pY->nSkip==0 /* (1c) */ |
| 163174 | + ){ |
| 163175 | + return 1; /* Case 1 is true */ |
| 163176 | + } |
| 163077 | 163177 | if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){ |
| 163078 | | - return 0; /* X is not a subset of Y */ |
| 163178 | + return 0; /* (2b) */ |
| 163079 | 163179 | } |
| 163080 | | - if( pX->rRun>pY->rRun && pX->nOut>pY->nOut ) return 0; |
| 163081 | | - if( pY->nSkip > pX->nSkip ) return 0; |
| 163180 | + if( pY->nSkip > pX->nSkip ) return 0; /* (2d) */ |
| 163082 | 163181 | for(i=pX->nLTerm-1; i>=0; i--){ |
| 163083 | 163182 | if( pX->aLTerm[i]==0 ) continue; |
| 163084 | 163183 | for(j=pY->nLTerm-1; j>=0; j--){ |
| 163085 | 163184 | if( pY->aLTerm[j]==pX->aLTerm[i] ) break; |
| 163086 | 163185 | } |
| 163087 | | - if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */ |
| 163186 | + if( j<0 ) return 0; /* (2c) */ |
| 163088 | 163187 | } |
| 163089 | 163188 | if( (pX->wsFlags&WHERE_IDX_ONLY)!=0 |
| 163090 | 163189 | && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){ |
| 163091 | | - return 0; /* Constraint (5) */ |
| 163190 | + return 0; /* (2e) */ |
| 163092 | 163191 | } |
| 163093 | | - return 1; /* All conditions meet */ |
| 163192 | + return 1; /* Case 2 is true */ |
| 163094 | 163193 | } |
| 163095 | 163194 | |
| 163096 | 163195 | /* |
| 163097 | 163196 | ** Try to adjust the cost and number of output rows of WhereLoop pTemplate |
| 163098 | 163197 | ** upwards or downwards so that: |
| | @@ -163578,11 +163677,14 @@ |
| 163578 | 163677 | opMask = WO_LT|WO_LE; |
| 163579 | 163678 | }else{ |
| 163580 | 163679 | assert( pNew->u.btree.nBtm==0 ); |
| 163581 | 163680 | opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; |
| 163582 | 163681 | } |
| 163583 | | - if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); |
| 163682 | + if( pProbe->bUnordered || pProbe->bLowQual ){ |
| 163683 | + if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); |
| 163684 | + if( pProbe->bLowQual ) opMask &= ~(WO_EQ|WO_IN|WO_IS); |
| 163685 | + } |
| 163584 | 163686 | |
| 163585 | 163687 | assert( pNew->u.btree.nEq<pProbe->nColumn ); |
| 163586 | 163688 | assert( pNew->u.btree.nEq<pProbe->nKeyCol |
| 163587 | 163689 | || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY ); |
| 163588 | 163690 | |
| | @@ -166683,11 +166785,14 @@ |
| 166683 | 166785 | ** struct, the contents of WhereInfo.a[], the WhereClause structure |
| 166684 | 166786 | ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte |
| 166685 | 166787 | ** field (type Bitmask) it must be aligned on an 8-byte boundary on |
| 166686 | 166788 | ** some architectures. Hence the ROUND8() below. |
| 166687 | 166789 | */ |
| 166688 | | - nByteWInfo = ROUND8P(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); |
| 166790 | + nByteWInfo = ROUND8P(sizeof(WhereInfo)); |
| 166791 | + if( nTabList>1 ){ |
| 166792 | + nByteWInfo = ROUND8P(nByteWInfo + (nTabList-1)*sizeof(WhereLevel)); |
| 166793 | + } |
| 166689 | 166794 | pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); |
| 166690 | 166795 | if( db->mallocFailed ){ |
| 166691 | 166796 | sqlite3DbFree(db, pWInfo); |
| 166692 | 166797 | pWInfo = 0; |
| 166693 | 166798 | goto whereBeginError; |
| | @@ -167245,10 +167350,15 @@ |
| 167245 | 167350 | whereBeginError: |
| 167246 | 167351 | if( pWInfo ){ |
| 167247 | 167352 | pParse->nQueryLoop = pWInfo->savedNQueryLoop; |
| 167248 | 167353 | whereInfoFree(db, pWInfo); |
| 167249 | 167354 | } |
| 167355 | +#ifdef WHERETRACE_ENABLED |
| 167356 | + /* Prevent harmless compiler warnings about debugging routines |
| 167357 | + ** being declared but never used */ |
| 167358 | + sqlite3ShowWhereLoopList(0); |
| 167359 | +#endif /* WHERETRACE_ENABLED */ |
| 167250 | 167360 | return 0; |
| 167251 | 167361 | } |
| 167252 | 167362 | |
| 167253 | 167363 | /* |
| 167254 | 167364 | ** Part of sqlite3WhereEnd() will rewrite opcodes to reference the |
| | @@ -203027,13 +203137,13 @@ |
| 203027 | 203137 | ** The original design stored all JSON as pure text, canonical RFC-8259. |
| 203028 | 203138 | ** Support for JSON-5 extensions was added with version 3.42.0 (2023-05-16). |
| 203029 | 203139 | ** All generated JSON text still conforms strictly to RFC-8259, but text |
| 203030 | 203140 | ** with JSON-5 extensions is accepted as input. |
| 203031 | 203141 | ** |
| 203032 | | -** Beginning with version 3.45.0 (pending), these routines also accept |
| 203033 | | -** BLOB values that have JSON encoded using a binary representation we |
| 203034 | | -** call JSONB. The name JSONB comes from PostgreSQL, however the on-disk |
| 203142 | +** Beginning with version 3.45.0 (circa 2024-01-01), these routines also |
| 203143 | +** accept BLOB values that have JSON encoded using a binary representation |
| 203144 | +** called "JSONB". The name JSONB comes from PostgreSQL, however the on-disk |
| 203035 | 203145 | ** format SQLite JSONB is completely different and incompatible with |
| 203036 | 203146 | ** PostgreSQL JSONB. |
| 203037 | 203147 | ** |
| 203038 | 203148 | ** Decoding and interpreting JSONB is still O(N) where N is the size of |
| 203039 | 203149 | ** the input, the same as text JSON. However, the constant of proportionality |
| | @@ -203120,10 +203230,13 @@ |
| 203120 | 203230 | ** code is between 0 and 12 and that the total size of the element |
| 203121 | 203231 | ** (header plus payload) is the same as the size of the BLOB. If those |
| 203122 | 203232 | ** checks are true, the BLOB is assumed to be JSONB and processing continues. |
| 203123 | 203233 | ** Errors are only raised if some other miscoding is discovered during |
| 203124 | 203234 | ** processing. |
| 203235 | +** |
| 203236 | +** Additional information can be found in the doc/jsonb.md file of the |
| 203237 | +** canonical SQLite source tree. |
| 203125 | 203238 | */ |
| 203126 | 203239 | #ifndef SQLITE_OMIT_JSON |
| 203127 | 203240 | /* #include "sqliteInt.h" */ |
| 203128 | 203241 | |
| 203129 | 203242 | /* JSONB element types |
| | @@ -203218,18 +203331,26 @@ |
| 203218 | 203331 | ** Magic number used for the JSON parse cache in sqlite3_get_auxdata() |
| 203219 | 203332 | */ |
| 203220 | 203333 | #define JSON_CACHE_ID (-429938) /* Cache entry */ |
| 203221 | 203334 | #define JSON_CACHE_SIZE 4 /* Max number of cache entries */ |
| 203222 | 203335 | |
| 203336 | +/* |
| 203337 | +** jsonUnescapeOneChar() returns this invalid code point if it encounters |
| 203338 | +** a syntax error. |
| 203339 | +*/ |
| 203340 | +#define JSON_INVALID_CHAR 0x99999 |
| 203341 | + |
| 203223 | 203342 | /* A cache mapping JSON text into JSONB blobs. |
| 203224 | 203343 | ** |
| 203225 | 203344 | ** Each cache entry is a JsonParse object with the following restrictions: |
| 203226 | 203345 | ** |
| 203227 | 203346 | ** * The bReadOnly flag must be set |
| 203228 | 203347 | ** |
| 203229 | 203348 | ** * The aBlob[] array must be owned by the JsonParse object. In other |
| 203230 | 203349 | ** words, nBlobAlloc must be non-zero. |
| 203350 | +** |
| 203351 | +** * eEdit and delta must be zero. |
| 203231 | 203352 | ** |
| 203232 | 203353 | ** * zJson must be an RCStr. In other words bJsonIsRCStr must be true. |
| 203233 | 203354 | */ |
| 203234 | 203355 | struct JsonCache { |
| 203235 | 203356 | sqlite3 *db; /* Database connection */ |
| | @@ -203286,27 +203407,27 @@ |
| 203286 | 203407 | ** |
| 203287 | 203408 | ** 3. Zero or more changes are made to aBlob[] (via json_remove() or |
| 203288 | 203409 | ** json_replace() or json_patch() or similar). |
| 203289 | 203410 | ** |
| 203290 | 203411 | ** 4. New JSON text is generated from the aBlob[] for output. This step |
| 203291 | | -** is skipped the function is one of the jsonb_* functions that returns |
| 203292 | | -** JSONB instead of text JSON. |
| 203412 | +** is skipped if the function is one of the jsonb_* functions that |
| 203413 | +** returns JSONB instead of text JSON. |
| 203293 | 203414 | */ |
| 203294 | 203415 | struct JsonParse { |
| 203295 | 203416 | u8 *aBlob; /* JSONB representation of JSON value */ |
| 203296 | 203417 | u32 nBlob; /* Bytes of aBlob[] actually used */ |
| 203297 | 203418 | u32 nBlobAlloc; /* Bytes allocated to aBlob[]. 0 if aBlob is external */ |
| 203298 | 203419 | char *zJson; /* Json text used for parsing */ |
| 203299 | 203420 | int nJson; /* Length of the zJson string in bytes */ |
| 203421 | + u32 nJPRef; /* Number of references to this object */ |
| 203422 | + u32 iErr; /* Error location in zJson[] */ |
| 203300 | 203423 | u16 iDepth; /* Nesting depth */ |
| 203301 | 203424 | u8 nErr; /* Number of errors seen */ |
| 203302 | 203425 | u8 oom; /* Set to true if out of memory */ |
| 203303 | 203426 | u8 bJsonIsRCStr; /* True if zJson is an RCStr */ |
| 203304 | 203427 | u8 hasNonstd; /* True if input uses non-standard features like JSON5 */ |
| 203305 | 203428 | u8 bReadOnly; /* Do not modify. */ |
| 203306 | | - u32 nJPRef; /* Number of references to this object */ |
| 203307 | | - u32 iErr; /* Error location in zJson[] */ |
| 203308 | 203429 | /* Search and edit information. See jsonLookupStep() */ |
| 203309 | 203430 | u8 eEdit; /* Edit operation to apply */ |
| 203310 | 203431 | int delta; /* Size change due to the edit */ |
| 203311 | 203432 | u32 nIns; /* Number of bytes to insert */ |
| 203312 | 203433 | u32 iLabel; /* Location of label if search landed on an object value */ |
| | @@ -203341,11 +203462,11 @@ |
| 203341 | 203462 | /************************************************************************** |
| 203342 | 203463 | ** Forward references |
| 203343 | 203464 | **************************************************************************/ |
| 203344 | 203465 | static void jsonReturnStringAsBlob(JsonString*); |
| 203345 | 203466 | static int jsonFuncArgMightBeBinary(sqlite3_value *pJson); |
| 203346 | | -static u32 jsonXlateBlobToText(const JsonParse*,u32,JsonString*); |
| 203467 | +static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*); |
| 203347 | 203468 | static void jsonReturnParse(sqlite3_context*,JsonParse*); |
| 203348 | 203469 | static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32); |
| 203349 | 203470 | static void jsonParseFree(JsonParse*); |
| 203350 | 203471 | static u32 jsonbPayloadSize(const JsonParse*, u32, u32*); |
| 203351 | 203472 | static u32 jsonUnescapeOneChar(const char*, u32, u32*); |
| | @@ -203381,10 +203502,11 @@ |
| 203381 | 203502 | ){ |
| 203382 | 203503 | JsonCache *p; |
| 203383 | 203504 | |
| 203384 | 203505 | assert( pParse->zJson!=0 ); |
| 203385 | 203506 | assert( pParse->bJsonIsRCStr ); |
| 203507 | + assert( pParse->delta==0 ); |
| 203386 | 203508 | p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); |
| 203387 | 203509 | if( p==0 ){ |
| 203388 | 203510 | sqlite3 *db = sqlite3_context_db_handle(ctx); |
| 203389 | 203511 | p = sqlite3DbMallocZero(db, sizeof(*p)); |
| 203390 | 203512 | if( p==0 ) return SQLITE_NOMEM; |
| | @@ -203453,10 +203575,11 @@ |
| 203453 | 203575 | JsonParse *tmp = p->a[i]; |
| 203454 | 203576 | memmove(&p->a[i], &p->a[i+1], (p->nUsed-i-1)*sizeof(tmp)); |
| 203455 | 203577 | p->a[p->nUsed-1] = tmp; |
| 203456 | 203578 | i = p->nUsed - 1; |
| 203457 | 203579 | } |
| 203580 | + assert( p->a[i]->delta==0 ); |
| 203458 | 203581 | return p->a[i]; |
| 203459 | 203582 | }else{ |
| 203460 | 203583 | return 0; |
| 203461 | 203584 | } |
| 203462 | 203585 | } |
| | @@ -203621,12 +203744,37 @@ |
| 203621 | 203744 | if( z==0 ) return; |
| 203622 | 203745 | if( (N+p->nUsed+2 >= p->nAlloc) && jsonStringGrow(p,N+2)!=0 ) return; |
| 203623 | 203746 | p->zBuf[p->nUsed++] = '"'; |
| 203624 | 203747 | while( 1 /*exit-by-break*/ ){ |
| 203625 | 203748 | k = 0; |
| 203626 | | - while( k+1<N && jsonIsOk[z[k]] && jsonIsOk[z[k+1]] ){ k += 2; } /* <--, */ |
| 203627 | | - while( k<N && jsonIsOk[z[k]] ){ k++; } /* <-- loop unwound for speed */ |
| 203749 | + /* The following while() is the 4-way unwound equivalent of |
| 203750 | + ** |
| 203751 | + ** while( k<N && jsonIsOk[z[k]] ){ k++; } |
| 203752 | + */ |
| 203753 | + while( 1 /* Exit by break */ ){ |
| 203754 | + if( k+3>=N ){ |
| 203755 | + while( k<N && jsonIsOk[z[k]] ){ k++; } |
| 203756 | + break; |
| 203757 | + } |
| 203758 | + if( !jsonIsOk[z[k]] ){ |
| 203759 | + break; |
| 203760 | + } |
| 203761 | + if( !jsonIsOk[z[k+1]] ){ |
| 203762 | + k += 1; |
| 203763 | + break; |
| 203764 | + } |
| 203765 | + if( !jsonIsOk[z[k+2]] ){ |
| 203766 | + k += 2; |
| 203767 | + break; |
| 203768 | + } |
| 203769 | + if( !jsonIsOk[z[k+3]] ){ |
| 203770 | + k += 3; |
| 203771 | + break; |
| 203772 | + }else{ |
| 203773 | + k += 4; |
| 203774 | + } |
| 203775 | + } |
| 203628 | 203776 | if( k>=N ){ |
| 203629 | 203777 | if( k>0 ){ |
| 203630 | 203778 | memcpy(&p->zBuf[p->nUsed], z, k); |
| 203631 | 203779 | p->nUsed += k; |
| 203632 | 203780 | } |
| | @@ -203714,11 +203862,11 @@ |
| 203714 | 203862 | if( jsonFuncArgMightBeBinary(pValue) ){ |
| 203715 | 203863 | JsonParse px; |
| 203716 | 203864 | memset(&px, 0, sizeof(px)); |
| 203717 | 203865 | px.aBlob = (u8*)sqlite3_value_blob(pValue); |
| 203718 | 203866 | px.nBlob = sqlite3_value_bytes(pValue); |
| 203719 | | - jsonXlateBlobToText(&px, 0, p); |
| 203867 | + jsonTranslateBlobToText(&px, 0, p); |
| 203720 | 203868 | }else if( p->eErr==0 ){ |
| 203721 | 203869 | sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); |
| 203722 | 203870 | p->eErr = JSTRING_ERR; |
| 203723 | 203871 | jsonStringReset(p); |
| 203724 | 203872 | } |
| | @@ -204231,18 +204379,14 @@ |
| 204231 | 204379 | ** then set *pOp to JSONB_TEXTJ and return true. If not, do not make |
| 204232 | 204380 | ** any changes to *pOp and return false. |
| 204233 | 204381 | */ |
| 204234 | 204382 | static int jsonIs4HexB(const char *z, int *pOp){ |
| 204235 | 204383 | if( z[0]!='u' ) return 0; |
| 204236 | | - if( !sqlite3Isxdigit(z[1]) ) return 0; |
| 204237 | | - if( !sqlite3Isxdigit(z[2]) ) return 0; |
| 204238 | | - if( !sqlite3Isxdigit(z[3]) ) return 0; |
| 204239 | | - if( !sqlite3Isxdigit(z[4]) ) return 0; |
| 204384 | + if( !jsonIs4Hex(&z[1]) ) return 0; |
| 204240 | 204385 | *pOp = JSONB_TEXTJ; |
| 204241 | 204386 | return 1; |
| 204242 | 204387 | } |
| 204243 | | - |
| 204244 | 204388 | |
| 204245 | 204389 | /* |
| 204246 | 204390 | ** Check a single element of the JSONB in pParse for validity. |
| 204247 | 204391 | ** |
| 204248 | 204392 | ** The element to be checked starts at offset i and must end at on the |
| | @@ -204384,11 +204528,11 @@ |
| 204384 | 204528 | }else if( x!=JSONB_TEXT5 ){ |
| 204385 | 204529 | return j+1; |
| 204386 | 204530 | }else{ |
| 204387 | 204531 | u32 c = 0; |
| 204388 | 204532 | u32 szC = jsonUnescapeOneChar((const char*)&z[j], k-j, &c); |
| 204389 | | - if( c==0xfffd ) return j+1; |
| 204533 | + if( c==JSON_INVALID_CHAR ) return j+1; |
| 204390 | 204534 | j += szC - 1; |
| 204391 | 204535 | } |
| 204392 | 204536 | } |
| 204393 | 204537 | j++; |
| 204394 | 204538 | } |
| | @@ -204456,11 +204600,11 @@ |
| 204456 | 204600 | ** -2 '}' seen \ |
| 204457 | 204601 | ** -3 ']' seen \___ For these returns, pParse->iErr is set to |
| 204458 | 204602 | ** -4 ',' seen / the index in zJson[] of the seen character |
| 204459 | 204603 | ** -5 ':' seen / |
| 204460 | 204604 | */ |
| 204461 | | -static int jsonXlateTextToBlob(JsonParse *pParse, u32 i){ |
| 204605 | +static int jsonTranslateTextToBlob(JsonParse *pParse, u32 i){ |
| 204462 | 204606 | char c; |
| 204463 | 204607 | u32 j; |
| 204464 | 204608 | u32 iThis, iStart; |
| 204465 | 204609 | int x; |
| 204466 | 204610 | u8 t; |
| | @@ -204476,11 +204620,11 @@ |
| 204476 | 204620 | return -1; |
| 204477 | 204621 | } |
| 204478 | 204622 | iStart = pParse->nBlob; |
| 204479 | 204623 | for(j=i+1;;j++){ |
| 204480 | 204624 | u32 iBlob = pParse->nBlob; |
| 204481 | | - x = jsonXlateTextToBlob(pParse, j); |
| 204625 | + x = jsonTranslateTextToBlob(pParse, j); |
| 204482 | 204626 | if( x<=0 ){ |
| 204483 | 204627 | int op; |
| 204484 | 204628 | if( x==(-2) ){ |
| 204485 | 204629 | j = pParse->iErr; |
| 204486 | 204630 | if( pParse->nBlob!=(u32)iStart ) pParse->hasNonstd = 1; |
| | @@ -204522,19 +204666,19 @@ |
| 204522 | 204666 | if( z[j]==':' ){ |
| 204523 | 204667 | j++; |
| 204524 | 204668 | goto parse_object_value; |
| 204525 | 204669 | } |
| 204526 | 204670 | } |
| 204527 | | - x = jsonXlateTextToBlob(pParse, j); |
| 204671 | + x = jsonTranslateTextToBlob(pParse, j); |
| 204528 | 204672 | if( x!=(-5) ){ |
| 204529 | 204673 | if( x!=(-1) ) pParse->iErr = j; |
| 204530 | 204674 | return -1; |
| 204531 | 204675 | } |
| 204532 | 204676 | j = pParse->iErr+1; |
| 204533 | 204677 | } |
| 204534 | 204678 | parse_object_value: |
| 204535 | | - x = jsonXlateTextToBlob(pParse, j); |
| 204679 | + x = jsonTranslateTextToBlob(pParse, j); |
| 204536 | 204680 | if( x<=0 ){ |
| 204537 | 204681 | if( x!=(-1) ) pParse->iErr = j; |
| 204538 | 204682 | return -1; |
| 204539 | 204683 | } |
| 204540 | 204684 | j = x; |
| | @@ -204549,11 +204693,11 @@ |
| 204549 | 204693 | continue; |
| 204550 | 204694 | }else if( z[j]=='}' ){ |
| 204551 | 204695 | break; |
| 204552 | 204696 | } |
| 204553 | 204697 | } |
| 204554 | | - x = jsonXlateTextToBlob(pParse, j); |
| 204698 | + x = jsonTranslateTextToBlob(pParse, j); |
| 204555 | 204699 | if( x==(-4) ){ |
| 204556 | 204700 | j = pParse->iErr; |
| 204557 | 204701 | continue; |
| 204558 | 204702 | } |
| 204559 | 204703 | if( x==(-2) ){ |
| | @@ -204577,11 +204721,11 @@ |
| 204577 | 204721 | if( ++pParse->iDepth > JSON_MAX_DEPTH ){ |
| 204578 | 204722 | pParse->iErr = i; |
| 204579 | 204723 | return -1; |
| 204580 | 204724 | } |
| 204581 | 204725 | for(j=i+1;;j++){ |
| 204582 | | - x = jsonXlateTextToBlob(pParse, j); |
| 204726 | + x = jsonTranslateTextToBlob(pParse, j); |
| 204583 | 204727 | if( x<=0 ){ |
| 204584 | 204728 | if( x==(-3) ){ |
| 204585 | 204729 | j = pParse->iErr; |
| 204586 | 204730 | if( pParse->nBlob!=iStart ) pParse->hasNonstd = 1; |
| 204587 | 204731 | break; |
| | @@ -204601,11 +204745,11 @@ |
| 204601 | 204745 | continue; |
| 204602 | 204746 | }else if( z[j]==']' ){ |
| 204603 | 204747 | break; |
| 204604 | 204748 | } |
| 204605 | 204749 | } |
| 204606 | | - x = jsonXlateTextToBlob(pParse, j); |
| 204750 | + x = jsonTranslateTextToBlob(pParse, j); |
| 204607 | 204751 | if( x==(-4) ){ |
| 204608 | 204752 | j = pParse->iErr; |
| 204609 | 204753 | continue; |
| 204610 | 204754 | } |
| 204611 | 204755 | if( x==(-3) ){ |
| | @@ -204924,11 +205068,11 @@ |
| 204924 | 205068 | JsonParse *pParse, /* Initialize and fill this JsonParse object */ |
| 204925 | 205069 | sqlite3_context *pCtx /* Report errors here */ |
| 204926 | 205070 | ){ |
| 204927 | 205071 | int i; |
| 204928 | 205072 | const char *zJson = pParse->zJson; |
| 204929 | | - i = jsonXlateTextToBlob(pParse, 0); |
| 205073 | + i = jsonTranslateTextToBlob(pParse, 0); |
| 204930 | 205074 | if( pParse->oom ) i = -1; |
| 204931 | 205075 | if( i>0 ){ |
| 204932 | 205076 | #ifdef SQLITE_DEBUG |
| 204933 | 205077 | assert( pParse->iDepth==0 ); |
| 204934 | 205078 | if( sqlite3Config.bJsonSelfcheck ){ |
| | @@ -204969,11 +205113,11 @@ |
| 204969 | 205113 | JsonParse px; |
| 204970 | 205114 | memset(&px, 0, sizeof(px)); |
| 204971 | 205115 | jsonStringTerminate(pStr); |
| 204972 | 205116 | px.zJson = pStr->zBuf; |
| 204973 | 205117 | px.nJson = pStr->nUsed; |
| 204974 | | - (void)jsonXlateTextToBlob(&px, 0); |
| 205118 | + (void)jsonTranslateTextToBlob(&px, 0); |
| 204975 | 205119 | if( px.oom ){ |
| 204976 | 205120 | sqlite3_free(px.aBlob); |
| 204977 | 205121 | sqlite3_result_error_nomem(pStr->pCtx); |
| 204978 | 205122 | }else{ |
| 204979 | 205123 | assert( px.nBlobAlloc>0 ); |
| | @@ -205057,11 +205201,11 @@ |
| 205057 | 205201 | ** are detected. So a malformed JSONB input might either result |
| 205058 | 205202 | ** in an error, or in incorrect JSON. |
| 205059 | 205203 | ** |
| 205060 | 205204 | ** The pOut->eErr JSTRING_OOM flag is set on a OOM. |
| 205061 | 205205 | */ |
| 205062 | | -static u32 jsonXlateBlobToText( |
| 205206 | +static u32 jsonTranslateBlobToText( |
| 205063 | 205207 | const JsonParse *pParse, /* the complete parse of the JSON */ |
| 205064 | 205208 | u32 i, /* Start rendering at this index */ |
| 205065 | 205209 | JsonString *pOut /* Write JSON here */ |
| 205066 | 205210 | ){ |
| 205067 | 205211 | u32 sz, n, j, iEnd; |
| | @@ -205228,11 +205372,11 @@ |
| 205228 | 205372 | case JSONB_ARRAY: { |
| 205229 | 205373 | jsonAppendChar(pOut, '['); |
| 205230 | 205374 | j = i+n; |
| 205231 | 205375 | iEnd = j+sz; |
| 205232 | 205376 | while( j<iEnd ){ |
| 205233 | | - j = jsonXlateBlobToText(pParse, j, pOut); |
| 205377 | + j = jsonTranslateBlobToText(pParse, j, pOut); |
| 205234 | 205378 | jsonAppendChar(pOut, ','); |
| 205235 | 205379 | } |
| 205236 | 205380 | if( sz>0 ) pOut->nUsed--; |
| 205237 | 205381 | jsonAppendChar(pOut, ']'); |
| 205238 | 205382 | break; |
| | @@ -205241,11 +205385,11 @@ |
| 205241 | 205385 | int x = 0; |
| 205242 | 205386 | jsonAppendChar(pOut, '{'); |
| 205243 | 205387 | j = i+n; |
| 205244 | 205388 | iEnd = j+sz; |
| 205245 | 205389 | while( j<iEnd ){ |
| 205246 | | - j = jsonXlateBlobToText(pParse, j, pOut); |
| 205390 | + j = jsonTranslateBlobToText(pParse, j, pOut); |
| 205247 | 205391 | jsonAppendChar(pOut, (x++ & 1) ? ',' : ':'); |
| 205248 | 205392 | } |
| 205249 | 205393 | if( x & 1 ) pOut->eErr |= JSTRING_MALFORMED; |
| 205250 | 205394 | if( sz>0 ) pOut->nUsed--; |
| 205251 | 205395 | jsonAppendChar(pOut, '}'); |
| | @@ -205394,23 +205538,27 @@ |
| 205394 | 205538 | |
| 205395 | 205539 | /* |
| 205396 | 205540 | ** Input z[0..n] defines JSON escape sequence including the leading '\\'. |
| 205397 | 205541 | ** Decode that escape sequence into a single character. Write that |
| 205398 | 205542 | ** character into *piOut. Return the number of bytes in the escape sequence. |
| 205543 | +** |
| 205544 | +** If there is a syntax error of some kind (for example too few characters |
| 205545 | +** after the '\\' to complete the encoding) then *piOut is set to |
| 205546 | +** JSON_INVALID_CHAR. |
| 205399 | 205547 | */ |
| 205400 | 205548 | static u32 jsonUnescapeOneChar(const char *z, u32 n, u32 *piOut){ |
| 205401 | 205549 | assert( n>0 ); |
| 205402 | 205550 | assert( z[0]=='\\' ); |
| 205403 | 205551 | if( n<2 ){ |
| 205404 | | - *piOut = 0xFFFD; |
| 205552 | + *piOut = JSON_INVALID_CHAR; |
| 205405 | 205553 | return n; |
| 205406 | 205554 | } |
| 205407 | 205555 | switch( (u8)z[1] ){ |
| 205408 | 205556 | case 'u': { |
| 205409 | 205557 | u32 v, vlo; |
| 205410 | 205558 | if( n<6 ){ |
| 205411 | | - *piOut = 0xFFFD; |
| 205559 | + *piOut = JSON_INVALID_CHAR; |
| 205412 | 205560 | return n; |
| 205413 | 205561 | } |
| 205414 | 205562 | v = jsonHexToInt4(&z[2]); |
| 205415 | 205563 | if( (v & 0xfc00)==0xd800 |
| 205416 | 205564 | && n>=12 |
| | @@ -205436,11 +205584,11 @@ |
| 205436 | 205584 | case '"': |
| 205437 | 205585 | case '/': |
| 205438 | 205586 | case '\\':{ *piOut = z[1]; return 2; } |
| 205439 | 205587 | case 'x': { |
| 205440 | 205588 | if( n<4 ){ |
| 205441 | | - *piOut = 0xFFFD; |
| 205589 | + *piOut = JSON_INVALID_CHAR; |
| 205442 | 205590 | return n; |
| 205443 | 205591 | } |
| 205444 | 205592 | *piOut = (jsonHexToInt(z[2])<<4) | jsonHexToInt(z[3]); |
| 205445 | 205593 | return 4; |
| 205446 | 205594 | } |
| | @@ -205447,11 +205595,11 @@ |
| 205447 | 205595 | case 0xe2: |
| 205448 | 205596 | case '\r': |
| 205449 | 205597 | case '\n': { |
| 205450 | 205598 | u32 nSkip = jsonBytesToBypass(z, n); |
| 205451 | 205599 | if( nSkip==0 ){ |
| 205452 | | - *piOut = 0xFFFD; |
| 205600 | + *piOut = JSON_INVALID_CHAR; |
| 205453 | 205601 | return n; |
| 205454 | 205602 | }else if( nSkip==n ){ |
| 205455 | 205603 | *piOut = 0; |
| 205456 | 205604 | return n; |
| 205457 | 205605 | }else if( z[nSkip]=='\\' ){ |
| | @@ -205460,11 +205608,11 @@ |
| 205460 | 205608 | int sz = sqlite3Utf8ReadLimited((u8*)&z[nSkip], n-nSkip, piOut); |
| 205461 | 205609 | return nSkip + sz; |
| 205462 | 205610 | } |
| 205463 | 205611 | } |
| 205464 | 205612 | default: { |
| 205465 | | - *piOut = 0xFFFD; |
| 205613 | + *piOut = JSON_INVALID_CHAR; |
| 205466 | 205614 | return 2; |
| 205467 | 205615 | } |
| 205468 | 205616 | } |
| 205469 | 205617 | } |
| 205470 | 205618 | |
| | @@ -205823,11 +205971,11 @@ |
| 205823 | 205971 | if( NEVER(aBlob==0) ) return; |
| 205824 | 205972 | memset(&x, 0, sizeof(x)); |
| 205825 | 205973 | x.aBlob = (u8*)aBlob; |
| 205826 | 205974 | x.nBlob = nBlob; |
| 205827 | 205975 | jsonStringInit(&s, ctx); |
| 205828 | | - jsonXlateBlobToText(&x, 0, &s); |
| 205976 | + jsonTranslateBlobToText(&x, 0, &s); |
| 205829 | 205977 | jsonReturnString(&s, 0, 0); |
| 205830 | 205978 | } |
| 205831 | 205979 | |
| 205832 | 205980 | |
| 205833 | 205981 | /* |
| | @@ -205934,21 +206082,21 @@ |
| 205934 | 206082 | if( c=='\\' ){ |
| 205935 | 206083 | u32 v; |
| 205936 | 206084 | u32 szEscape = jsonUnescapeOneChar(&z[iIn], sz-iIn, &v); |
| 205937 | 206085 | if( v<=0x7f ){ |
| 205938 | 206086 | zOut[iOut++] = (char)v; |
| 205939 | | - }else if( v==0xfffd ){ |
| 205940 | | - /* Silently ignore illegal unicode */ |
| 205941 | 206087 | }else if( v<=0x7ff ){ |
| 205942 | 206088 | assert( szEscape>=2 ); |
| 205943 | 206089 | zOut[iOut++] = (char)(0xc0 | (v>>6)); |
| 205944 | 206090 | zOut[iOut++] = 0x80 | (v&0x3f); |
| 205945 | 206091 | }else if( v<0x10000 ){ |
| 205946 | 206092 | assert( szEscape>=3 ); |
| 205947 | 206093 | zOut[iOut++] = 0xe0 | (v>>12); |
| 205948 | 206094 | zOut[iOut++] = 0x80 | ((v>>6)&0x3f); |
| 205949 | 206095 | zOut[iOut++] = 0x80 | (v&0x3f); |
| 206096 | + }else if( v==JSON_INVALID_CHAR ){ |
| 206097 | + /* Silently ignore illegal unicode */ |
| 205950 | 206098 | }else{ |
| 205951 | 206099 | assert( szEscape>=4 ); |
| 205952 | 206100 | zOut[iOut++] = 0xf0 | (v>>18); |
| 205953 | 206101 | zOut[iOut++] = 0x80 | ((v>>12)&0x3f); |
| 205954 | 206102 | zOut[iOut++] = 0x80 | ((v>>6)&0x3f); |
| | @@ -206046,17 +206194,33 @@ |
| 206046 | 206194 | }else{ |
| 206047 | 206195 | jsonBlobAppendNode(pParse, JSONB_TEXTRAW, nJson, zJson); |
| 206048 | 206196 | } |
| 206049 | 206197 | break; |
| 206050 | 206198 | } |
| 206051 | | - case SQLITE_FLOAT: |
| 206199 | + case SQLITE_FLOAT: { |
| 206200 | + double r = sqlite3_value_double(pArg); |
| 206201 | + if( NEVER(sqlite3IsNaN(r)) ){ |
| 206202 | + jsonBlobAppendNode(pParse, JSONB_NULL, 0, 0); |
| 206203 | + }else{ |
| 206204 | + int n = sqlite3_value_bytes(pArg); |
| 206205 | + const char *z = (const char*)sqlite3_value_text(pArg); |
| 206206 | + if( z==0 ) return 1; |
| 206207 | + if( z[0]=='I' ){ |
| 206208 | + jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999"); |
| 206209 | + }else if( z[0]=='-' && z[1]=='I' ){ |
| 206210 | + jsonBlobAppendNode(pParse, JSONB_FLOAT, 6, "-9e999"); |
| 206211 | + }else{ |
| 206212 | + jsonBlobAppendNode(pParse, JSONB_FLOAT, n, z); |
| 206213 | + } |
| 206214 | + } |
| 206215 | + break; |
| 206216 | + } |
| 206052 | 206217 | case SQLITE_INTEGER: { |
| 206053 | 206218 | int n = sqlite3_value_bytes(pArg); |
| 206054 | 206219 | const char *z = (const char*)sqlite3_value_text(pArg); |
| 206055 | | - int e = eType==SQLITE_INTEGER ? JSONB_INT : JSONB_FLOAT; |
| 206056 | 206220 | if( z==0 ) return 1; |
| 206057 | | - jsonBlobAppendNode(pParse, e, n, z); |
| 206221 | + jsonBlobAppendNode(pParse, JSONB_INT, n, z); |
| 206058 | 206222 | break; |
| 206059 | 206223 | } |
| 206060 | 206224 | } |
| 206061 | 206225 | if( pParse->oom ){ |
| 206062 | 206226 | sqlite3_result_error_nomem(ctx); |
| | @@ -206153,15 +206317,10 @@ |
| 206153 | 206317 | }else{ |
| 206154 | 206318 | jsonBadPathError(ctx, zPath); |
| 206155 | 206319 | } |
| 206156 | 206320 | return; |
| 206157 | 206321 | } |
| 206158 | | - |
| 206159 | | -/* |
| 206160 | | -** Make a copy of a JsonParse object. The copy will be editable. |
| 206161 | | -*/ |
| 206162 | | - |
| 206163 | 206322 | |
| 206164 | 206323 | /* |
| 206165 | 206324 | ** Generate a JsonParse object, containing valid JSONB in aBlob and nBlob, |
| 206166 | 206325 | ** from the SQL function argument pArg. Return a pointer to the new |
| 206167 | 206326 | ** JsonParse object. |
| | @@ -206313,11 +206472,12 @@ |
| 206313 | 206472 | sqlite3_result_blob(ctx, p->aBlob, p->nBlob, SQLITE_TRANSIENT); |
| 206314 | 206473 | } |
| 206315 | 206474 | }else{ |
| 206316 | 206475 | JsonString s; |
| 206317 | 206476 | jsonStringInit(&s, ctx); |
| 206318 | | - jsonXlateBlobToText(p, 0, &s); |
| 206477 | + p->delta = 0; |
| 206478 | + jsonTranslateBlobToText(p, 0, &s); |
| 206319 | 206479 | jsonReturnString(&s, p, ctx); |
| 206320 | 206480 | sqlite3_result_subtype(ctx, JSON_SUBTYPE); |
| 206321 | 206481 | } |
| 206322 | 206482 | } |
| 206323 | 206483 | |
| | @@ -206333,29 +206493,32 @@ |
| 206333 | 206493 | */ |
| 206334 | 206494 | static void jsonDebugPrintBlob( |
| 206335 | 206495 | JsonParse *pParse, /* JSON content */ |
| 206336 | 206496 | u32 iStart, /* Start rendering here */ |
| 206337 | 206497 | u32 iEnd, /* Do not render this byte or any byte after this one */ |
| 206338 | | - int nIndent /* Indent by this many spaces */ |
| 206498 | + int nIndent, /* Indent by this many spaces */ |
| 206499 | + sqlite3_str *pOut /* Generate output into this sqlite3_str object */ |
| 206339 | 206500 | ){ |
| 206340 | 206501 | while( iStart<iEnd ){ |
| 206341 | 206502 | u32 i, n, nn, sz = 0; |
| 206342 | 206503 | int showContent = 1; |
| 206343 | 206504 | u8 x = pParse->aBlob[iStart] & 0x0f; |
| 206344 | 206505 | u32 savedNBlob = pParse->nBlob; |
| 206345 | | - printf("%5d:%*s", iStart, nIndent, ""); |
| 206506 | + sqlite3_str_appendf(pOut, "%5d:%*s", iStart, nIndent, ""); |
| 206346 | 206507 | if( pParse->nBlobAlloc>pParse->nBlob ){ |
| 206347 | 206508 | pParse->nBlob = pParse->nBlobAlloc; |
| 206348 | 206509 | } |
| 206349 | 206510 | nn = n = jsonbPayloadSize(pParse, iStart, &sz); |
| 206350 | 206511 | if( nn==0 ) nn = 1; |
| 206351 | 206512 | if( sz>0 && x<JSONB_ARRAY ){ |
| 206352 | 206513 | nn += sz; |
| 206353 | 206514 | } |
| 206354 | | - for(i=0; i<nn; i++) printf(" %02x", pParse->aBlob[iStart+i]); |
| 206515 | + for(i=0; i<nn; i++){ |
| 206516 | + sqlite3_str_appendf(pOut, " %02x", pParse->aBlob[iStart+i]); |
| 206517 | + } |
| 206355 | 206518 | if( n==0 ){ |
| 206356 | | - printf(" ERROR invalid node size\n"); |
| 206519 | + sqlite3_str_appendf(pOut, " ERROR invalid node size\n"); |
| 206357 | 206520 | iStart = n==0 ? iStart+1 : iEnd; |
| 206358 | 206521 | continue; |
| 206359 | 206522 | } |
| 206360 | 206523 | pParse->nBlob = savedNBlob; |
| 206361 | 206524 | if( iStart+n+sz>iEnd ){ |
| | @@ -206366,59 +206529,61 @@ |
| 206366 | 206529 | }else{ |
| 206367 | 206530 | iEnd = pParse->nBlob; |
| 206368 | 206531 | } |
| 206369 | 206532 | } |
| 206370 | 206533 | } |
| 206371 | | - printf(" <-- "); |
| 206534 | + sqlite3_str_appendall(pOut," <-- "); |
| 206372 | 206535 | switch( x ){ |
| 206373 | | - case JSONB_NULL: printf("null"); break; |
| 206374 | | - case JSONB_TRUE: printf("true"); break; |
| 206375 | | - case JSONB_FALSE: printf("false"); break; |
| 206376 | | - case JSONB_INT: printf("int"); break; |
| 206377 | | - case JSONB_INT5: printf("int5"); break; |
| 206378 | | - case JSONB_FLOAT: printf("float"); break; |
| 206379 | | - case JSONB_FLOAT5: printf("float5"); break; |
| 206380 | | - case JSONB_TEXT: printf("text"); break; |
| 206381 | | - case JSONB_TEXTJ: printf("textj"); break; |
| 206382 | | - case JSONB_TEXT5: printf("text5"); break; |
| 206383 | | - case JSONB_TEXTRAW: printf("textraw"); break; |
| 206536 | + case JSONB_NULL: sqlite3_str_appendall(pOut,"null"); break; |
| 206537 | + case JSONB_TRUE: sqlite3_str_appendall(pOut,"true"); break; |
| 206538 | + case JSONB_FALSE: sqlite3_str_appendall(pOut,"false"); break; |
| 206539 | + case JSONB_INT: sqlite3_str_appendall(pOut,"int"); break; |
| 206540 | + case JSONB_INT5: sqlite3_str_appendall(pOut,"int5"); break; |
| 206541 | + case JSONB_FLOAT: sqlite3_str_appendall(pOut,"float"); break; |
| 206542 | + case JSONB_FLOAT5: sqlite3_str_appendall(pOut,"float5"); break; |
| 206543 | + case JSONB_TEXT: sqlite3_str_appendall(pOut,"text"); break; |
| 206544 | + case JSONB_TEXTJ: sqlite3_str_appendall(pOut,"textj"); break; |
| 206545 | + case JSONB_TEXT5: sqlite3_str_appendall(pOut,"text5"); break; |
| 206546 | + case JSONB_TEXTRAW: sqlite3_str_appendall(pOut,"textraw"); break; |
| 206384 | 206547 | case JSONB_ARRAY: { |
| 206385 | | - printf("array, %u bytes\n", sz); |
| 206386 | | - jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2); |
| 206548 | + sqlite3_str_appendf(pOut,"array, %u bytes\n", sz); |
| 206549 | + jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut); |
| 206387 | 206550 | showContent = 0; |
| 206388 | 206551 | break; |
| 206389 | 206552 | } |
| 206390 | 206553 | case JSONB_OBJECT: { |
| 206391 | | - printf("object, %u bytes\n", sz); |
| 206392 | | - jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2); |
| 206554 | + sqlite3_str_appendf(pOut, "object, %u bytes\n", sz); |
| 206555 | + jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut); |
| 206393 | 206556 | showContent = 0; |
| 206394 | 206557 | break; |
| 206395 | 206558 | } |
| 206396 | 206559 | default: { |
| 206397 | | - printf("ERROR: unknown node type\n"); |
| 206560 | + sqlite3_str_appendall(pOut, "ERROR: unknown node type\n"); |
| 206398 | 206561 | showContent = 0; |
| 206399 | 206562 | break; |
| 206400 | 206563 | } |
| 206401 | 206564 | } |
| 206402 | 206565 | if( showContent ){ |
| 206403 | 206566 | if( sz==0 && x<=JSONB_FALSE ){ |
| 206404 | | - printf("\n"); |
| 206567 | + sqlite3_str_append(pOut, "\n", 1); |
| 206405 | 206568 | }else{ |
| 206406 | 206569 | u32 i; |
| 206407 | | - printf(": \""); |
| 206570 | + sqlite3_str_appendall(pOut, ": \""); |
| 206408 | 206571 | for(i=iStart+n; i<iStart+n+sz; i++){ |
| 206409 | 206572 | u8 c = pParse->aBlob[i]; |
| 206410 | 206573 | if( c<0x20 || c>=0x7f ) c = '.'; |
| 206411 | | - putchar(c); |
| 206574 | + sqlite3_str_append(pOut, (char*)&c, 1); |
| 206412 | 206575 | } |
| 206413 | | - printf("\"\n"); |
| 206576 | + sqlite3_str_append(pOut, "\"\n", 2); |
| 206414 | 206577 | } |
| 206415 | 206578 | } |
| 206416 | 206579 | iStart += n + sz; |
| 206417 | 206580 | } |
| 206418 | 206581 | } |
| 206419 | 206582 | static void jsonShowParse(JsonParse *pParse){ |
| 206583 | + sqlite3_str out; |
| 206584 | + char zBuf[1000]; |
| 206420 | 206585 | if( pParse==0 ){ |
| 206421 | 206586 | printf("NULL pointer\n"); |
| 206422 | 206587 | return; |
| 206423 | 206588 | }else{ |
| 206424 | 206589 | printf("nBlobAlloc = %u\n", pParse->nBlobAlloc); |
| | @@ -206425,31 +206590,42 @@ |
| 206425 | 206590 | printf("nBlob = %u\n", pParse->nBlob); |
| 206426 | 206591 | printf("delta = %d\n", pParse->delta); |
| 206427 | 206592 | if( pParse->nBlob==0 ) return; |
| 206428 | 206593 | printf("content (bytes 0..%u):\n", pParse->nBlob-1); |
| 206429 | 206594 | } |
| 206430 | | - jsonDebugPrintBlob(pParse, 0, pParse->nBlob, 0); |
| 206595 | + sqlite3StrAccumInit(&out, 0, zBuf, sizeof(zBuf), 1000000); |
| 206596 | + jsonDebugPrintBlob(pParse, 0, pParse->nBlob, 0, &out); |
| 206597 | + printf("%s", sqlite3_str_value(&out)); |
| 206598 | + sqlite3_str_reset(&out); |
| 206431 | 206599 | } |
| 206432 | 206600 | #endif /* SQLITE_DEBUG */ |
| 206433 | 206601 | |
| 206434 | 206602 | #ifdef SQLITE_DEBUG |
| 206435 | 206603 | /* |
| 206436 | 206604 | ** SQL function: json_parse(JSON) |
| 206437 | 206605 | ** |
| 206438 | | -** Parse JSON using jsonParseFuncArg(). Then print a dump of that |
| 206439 | | -** parse on standard output. |
| 206606 | +** Parse JSON using jsonParseFuncArg(). Return text that is a |
| 206607 | +** human-readable dump of the binary JSONB for the input parameter. |
| 206440 | 206608 | */ |
| 206441 | 206609 | static void jsonParseFunc( |
| 206442 | 206610 | sqlite3_context *ctx, |
| 206443 | 206611 | int argc, |
| 206444 | 206612 | sqlite3_value **argv |
| 206445 | 206613 | ){ |
| 206446 | 206614 | JsonParse *p; /* The parse */ |
| 206615 | + sqlite3_str out; |
| 206447 | 206616 | |
| 206448 | | - assert( argc==1 ); |
| 206617 | + assert( argc>=1 ); |
| 206618 | + sqlite3StrAccumInit(&out, 0, 0, 0, 1000000); |
| 206449 | 206619 | p = jsonParseFuncArg(ctx, argv[0], 0); |
| 206450 | | - jsonShowParse(p); |
| 206620 | + if( p==0 ) return; |
| 206621 | + if( argc==1 ){ |
| 206622 | + jsonDebugPrintBlob(p, 0, p->nBlob, 0, &out); |
| 206623 | + sqlite3_result_text64(ctx, out.zText, out.nChar, sqlite3_free, SQLITE_UTF8); |
| 206624 | + }else{ |
| 206625 | + jsonShowParse(p); |
| 206626 | + } |
| 206451 | 206627 | jsonParseFree(p); |
| 206452 | 206628 | } |
| 206453 | 206629 | #endif /* SQLITE_DEBUG */ |
| 206454 | 206630 | |
| 206455 | 206631 | /**************************************************************************** |
| | @@ -206641,11 +206817,11 @@ |
| 206641 | 206817 | } |
| 206642 | 206818 | if( j<p->nBlob ){ |
| 206643 | 206819 | if( argc==2 ){ |
| 206644 | 206820 | if( flags & JSON_JSON ){ |
| 206645 | 206821 | jsonStringInit(&jx, ctx); |
| 206646 | | - jsonXlateBlobToText(p, j, &jx); |
| 206822 | + jsonTranslateBlobToText(p, j, &jx); |
| 206647 | 206823 | jsonReturnString(&jx, 0, 0); |
| 206648 | 206824 | jsonStringReset(&jx); |
| 206649 | 206825 | assert( (flags & JSON_BLOB)==0 ); |
| 206650 | 206826 | sqlite3_result_subtype(ctx, JSON_SUBTYPE); |
| 206651 | 206827 | }else{ |
| | @@ -206656,11 +206832,11 @@ |
| 206656 | 206832 | sqlite3_result_subtype(ctx, JSON_SUBTYPE); |
| 206657 | 206833 | } |
| 206658 | 206834 | } |
| 206659 | 206835 | }else{ |
| 206660 | 206836 | jsonAppendSeparator(&jx); |
| 206661 | | - jsonXlateBlobToText(p, j, &jx); |
| 206837 | + jsonTranslateBlobToText(p, j, &jx); |
| 206662 | 206838 | } |
| 206663 | 206839 | }else if( j==JSON_LOOKUP_NOTFOUND ){ |
| 206664 | 206840 | if( argc==2 ){ |
| 206665 | 206841 | goto json_extract_error; /* Return NULL if not found */ |
| 206666 | 206842 | }else{ |
| | @@ -229267,23 +229443,28 @@ |
| 229267 | 229443 | ** |
| 229268 | 229444 | ** This function may be quite inefficient if used with an FTS5 table |
| 229269 | 229445 | ** created with the "columnsize=0" option. |
| 229270 | 229446 | ** |
| 229271 | 229447 | ** xColumnText: |
| 229272 | | -** This function attempts to retrieve the text of column iCol of the |
| 229273 | | -** current document. If successful, (*pz) is set to point to a buffer |
| 229448 | +** If parameter iCol is less than zero, or greater than or equal to the |
| 229449 | +** number of columns in the table, SQLITE_RANGE is returned. |
| 229450 | +** |
| 229451 | +** Otherwise, this function attempts to retrieve the text of column iCol of |
| 229452 | +** the current document. If successful, (*pz) is set to point to a buffer |
| 229274 | 229453 | ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes |
| 229275 | 229454 | ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, |
| 229276 | 229455 | ** if an error occurs, an SQLite error code is returned and the final values |
| 229277 | 229456 | ** of (*pz) and (*pn) are undefined. |
| 229278 | 229457 | ** |
| 229279 | 229458 | ** xPhraseCount: |
| 229280 | 229459 | ** Returns the number of phrases in the current query expression. |
| 229281 | 229460 | ** |
| 229282 | 229461 | ** xPhraseSize: |
| 229283 | | -** Returns the number of tokens in phrase iPhrase of the query. Phrases |
| 229284 | | -** are numbered starting from zero. |
| 229462 | +** If parameter iCol is less than zero, or greater than or equal to the |
| 229463 | +** number of phrases in the current query, as returned by xPhraseCount, |
| 229464 | +** 0 is returned. Otherwise, this function returns the number of tokens in |
| 229465 | +** phrase iPhrase of the query. Phrases are numbered starting from zero. |
| 229285 | 229466 | ** |
| 229286 | 229467 | ** xInstCount: |
| 229287 | 229468 | ** Set *pnInst to the total number of occurrences of all phrases within |
| 229288 | 229469 | ** the query within the current row. Return SQLITE_OK if successful, or |
| 229289 | 229470 | ** an error code (i.e. SQLITE_NOMEM) if an error occurs. |
| | @@ -229295,16 +229476,17 @@ |
| 229295 | 229476 | ** |
| 229296 | 229477 | ** xInst: |
| 229297 | 229478 | ** Query for the details of phrase match iIdx within the current row. |
| 229298 | 229479 | ** Phrase matches are numbered starting from zero, so the iIdx argument |
| 229299 | 229480 | ** should be greater than or equal to zero and smaller than the value |
| 229300 | | -** output by xInstCount(). |
| 229481 | +** output by xInstCount(). If iIdx is less than zero or greater than |
| 229482 | +** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. |
| 229301 | 229483 | ** |
| 229302 | | -** Usually, output parameter *piPhrase is set to the phrase number, *piCol |
| 229484 | +** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol |
| 229303 | 229485 | ** to the column in which it occurs and *piOff the token offset of the |
| 229304 | | -** first token of the phrase. Returns SQLITE_OK if successful, or an error |
| 229305 | | -** code (i.e. SQLITE_NOMEM) if an error occurs. |
| 229486 | +** first token of the phrase. SQLITE_OK is returned if successful, or an |
| 229487 | +** error code (i.e. SQLITE_NOMEM) if an error occurs. |
| 229306 | 229488 | ** |
| 229307 | 229489 | ** This API can be quite slow if used with an FTS5 table created with the |
| 229308 | 229490 | ** "detail=none" or "detail=column" option. |
| 229309 | 229491 | ** |
| 229310 | 229492 | ** xRowid: |
| | @@ -229325,10 +229507,14 @@ |
| 229325 | 229507 | ** row visited, the callback function passed as the fourth argument |
| 229326 | 229508 | ** is invoked. The context and API objects passed to the callback |
| 229327 | 229509 | ** function may be used to access the properties of each matched row. |
| 229328 | 229510 | ** Invoking Api.xUserData() returns a copy of the pointer passed as |
| 229329 | 229511 | ** the third argument to pUserData. |
| 229512 | +** |
| 229513 | +** If parameter iPhrase is less than zero, or greater than or equal to |
| 229514 | +** the number of phrases in the query, as returned by xPhraseCount(), |
| 229515 | +** this function returns SQLITE_RANGE. |
| 229330 | 229516 | ** |
| 229331 | 229517 | ** If the callback function returns any value other than SQLITE_OK, the |
| 229332 | 229518 | ** query is abandoned and the xQueryPhrase function returns immediately. |
| 229333 | 229519 | ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. |
| 229334 | 229520 | ** Otherwise, the error code is propagated upwards. |
| | @@ -229446,22 +229632,30 @@ |
| 229446 | 229632 | ** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken) |
| 229447 | 229633 | ** This is used to access token iToken of phrase iPhrase of the current |
| 229448 | 229634 | ** query. Before returning, output parameter *ppToken is set to point |
| 229449 | 229635 | ** to a buffer containing the requested token, and *pnToken to the |
| 229450 | 229636 | ** size of this buffer in bytes. |
| 229637 | +** |
| 229638 | +** If iPhrase or iToken are less than zero, or if iPhrase is greater than |
| 229639 | +** or equal to the number of phrases in the query as reported by |
| 229640 | +** xPhraseCount(), or if iToken is equal to or greater than the number of |
| 229641 | +** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken |
| 229642 | + are both zeroed. |
| 229451 | 229643 | ** |
| 229452 | 229644 | ** The output text is not a copy of the query text that specified the |
| 229453 | 229645 | ** token. It is the output of the tokenizer module. For tokendata=1 |
| 229454 | 229646 | ** tables, this includes any embedded 0x00 and trailing data. |
| 229455 | 229647 | ** |
| 229456 | 229648 | ** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken) |
| 229457 | 229649 | ** This is used to access token iToken of phrase hit iIdx within the |
| 229458 | | -** current row. Output variable (*ppToken) is set to point to a buffer |
| 229459 | | -** containing the matching document token, and (*pnToken) to the size |
| 229460 | | -** of that buffer in bytes. This API is not available if the specified |
| 229461 | | -** token matches a prefix query term. In that case both output variables |
| 229462 | | -** are always set to 0. |
| 229650 | +** current row. If iIdx is less than zero or greater than or equal to the |
| 229651 | +** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise, |
| 229652 | +** output variable (*ppToken) is set to point to a buffer containing the |
| 229653 | +** matching document token, and (*pnToken) to the size of that buffer in |
| 229654 | +** bytes. This API is not available if the specified token matches a |
| 229655 | +** prefix query term. In that case both output variables are always set |
| 229656 | +** to 0. |
| 229463 | 229657 | ** |
| 229464 | 229658 | ** The output text is not a copy of the document text that was tokenized. |
| 229465 | 229659 | ** It is the output of the tokenizer module. For tokendata=1 tables, this |
| 229466 | 229660 | ** includes any embedded 0x00 and trailing data. |
| 229467 | 229661 | ** |
| | @@ -232433,12 +232627,14 @@ |
| 232433 | 232627 | memset(&ctx, 0, sizeof(HighlightContext)); |
| 232434 | 232628 | ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); |
| 232435 | 232629 | ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); |
| 232436 | 232630 | ctx.iRangeEnd = -1; |
| 232437 | 232631 | rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn); |
| 232438 | | - |
| 232439 | | - if( ctx.zIn ){ |
| 232632 | + if( rc==SQLITE_RANGE ){ |
| 232633 | + sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC); |
| 232634 | + rc = SQLITE_OK; |
| 232635 | + }else if( ctx.zIn ){ |
| 232440 | 232636 | if( rc==SQLITE_OK ){ |
| 232441 | 232637 | rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter); |
| 232442 | 232638 | } |
| 232443 | 232639 | |
| 232444 | 232640 | if( rc==SQLITE_OK ){ |
| | @@ -236273,15 +236469,19 @@ |
| 236273 | 236469 | Fts5Expr *pExpr, |
| 236274 | 236470 | int iPhrase, |
| 236275 | 236471 | Fts5Expr **ppNew |
| 236276 | 236472 | ){ |
| 236277 | 236473 | int rc = SQLITE_OK; /* Return code */ |
| 236278 | | - Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */ |
| 236474 | + Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */ |
| 236279 | 236475 | Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ |
| 236280 | 236476 | TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */ |
| 236281 | | - pOrig = pExpr->apExprPhrase[iPhrase]; |
| 236282 | | - pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); |
| 236477 | + if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){ |
| 236478 | + rc = SQLITE_RANGE; |
| 236479 | + }else{ |
| 236480 | + pOrig = pExpr->apExprPhrase[iPhrase]; |
| 236481 | + pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); |
| 236482 | + } |
| 236283 | 236483 | if( rc==SQLITE_OK ){ |
| 236284 | 236484 | pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, |
| 236285 | 236485 | sizeof(Fts5ExprPhrase*)); |
| 236286 | 236486 | } |
| 236287 | 236487 | if( rc==SQLITE_OK ){ |
| | @@ -236290,11 +236490,11 @@ |
| 236290 | 236490 | } |
| 236291 | 236491 | if( rc==SQLITE_OK ){ |
| 236292 | 236492 | pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc, |
| 236293 | 236493 | sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*)); |
| 236294 | 236494 | } |
| 236295 | | - if( rc==SQLITE_OK ){ |
| 236495 | + if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){ |
| 236296 | 236496 | Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset; |
| 236297 | 236497 | if( pColsetOrig ){ |
| 236298 | 236498 | sqlite3_int64 nByte; |
| 236299 | 236499 | Fts5Colset *pColset; |
| 236300 | 236500 | nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int); |
| | @@ -236304,29 +236504,31 @@ |
| 236304 | 236504 | } |
| 236305 | 236505 | pNew->pRoot->pNear->pColset = pColset; |
| 236306 | 236506 | } |
| 236307 | 236507 | } |
| 236308 | 236508 | |
| 236309 | | - if( pOrig->nTerm ){ |
| 236310 | | - int i; /* Used to iterate through phrase terms */ |
| 236311 | | - sCtx.pConfig = pExpr->pConfig; |
| 236312 | | - for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){ |
| 236313 | | - int tflags = 0; |
| 236314 | | - Fts5ExprTerm *p; |
| 236315 | | - for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ |
| 236316 | | - rc = fts5ParseTokenize((void*)&sCtx, tflags, p->pTerm,p->nFullTerm,0,0); |
| 236317 | | - tflags = FTS5_TOKEN_COLOCATED; |
| 236318 | | - } |
| 236319 | | - if( rc==SQLITE_OK ){ |
| 236320 | | - sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; |
| 236321 | | - sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst; |
| 236322 | | - } |
| 236323 | | - } |
| 236324 | | - }else{ |
| 236325 | | - /* This happens when parsing a token or quoted phrase that contains |
| 236326 | | - ** no token characters at all. (e.g ... MATCH '""'). */ |
| 236327 | | - sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase)); |
| 236509 | + if( rc==SQLITE_OK ){ |
| 236510 | + if( pOrig->nTerm ){ |
| 236511 | + int i; /* Used to iterate through phrase terms */ |
| 236512 | + sCtx.pConfig = pExpr->pConfig; |
| 236513 | + for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){ |
| 236514 | + int tflags = 0; |
| 236515 | + Fts5ExprTerm *p; |
| 236516 | + for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ |
| 236517 | + rc = fts5ParseTokenize((void*)&sCtx,tflags,p->pTerm,p->nFullTerm,0,0); |
| 236518 | + tflags = FTS5_TOKEN_COLOCATED; |
| 236519 | + } |
| 236520 | + if( rc==SQLITE_OK ){ |
| 236521 | + sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; |
| 236522 | + sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst; |
| 236523 | + } |
| 236524 | + } |
| 236525 | + }else{ |
| 236526 | + /* This happens when parsing a token or quoted phrase that contains |
| 236527 | + ** no token characters at all. (e.g ... MATCH '""'). */ |
| 236528 | + sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase)); |
| 236529 | + } |
| 236328 | 236530 | } |
| 236329 | 236531 | |
| 236330 | 236532 | if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){ |
| 236331 | 236533 | /* All the allocations succeeded. Put the expression object together. */ |
| 236332 | 236534 | pNew->pIndex = pExpr->pIndex; |
| | @@ -239776,13 +239978,13 @@ |
| 239776 | 239978 | for(iOff=pLvl->iOff; iOff<pData->nn; iOff++){ |
| 239777 | 239979 | if( pData->p[iOff] ) break; |
| 239778 | 239980 | } |
| 239779 | 239981 | |
| 239780 | 239982 | if( iOff<pData->nn ){ |
| 239781 | | - i64 iVal; |
| 239983 | + u64 iVal; |
| 239782 | 239984 | pLvl->iLeafPgno += (iOff - pLvl->iOff) + 1; |
| 239783 | | - iOff += fts5GetVarint(&pData->p[iOff], (u64*)&iVal); |
| 239985 | + iOff += fts5GetVarint(&pData->p[iOff], &iVal); |
| 239784 | 239986 | pLvl->iRowid += iVal; |
| 239785 | 239987 | pLvl->iOff = iOff; |
| 239786 | 239988 | }else{ |
| 239787 | 239989 | pLvl->bEof = 1; |
| 239788 | 239990 | } |
| | @@ -246173,20 +246375,20 @@ |
| 246173 | 246375 | fts5DataRelease(pLeaf); |
| 246174 | 246376 | } |
| 246175 | 246377 | } |
| 246176 | 246378 | |
| 246177 | 246379 | static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){ |
| 246178 | | - int iTermOff = 0; |
| 246380 | + i64 iTermOff = 0; |
| 246179 | 246381 | int ii; |
| 246180 | 246382 | |
| 246181 | 246383 | Fts5Buffer buf1 = {0,0,0}; |
| 246182 | 246384 | Fts5Buffer buf2 = {0,0,0}; |
| 246183 | 246385 | |
| 246184 | 246386 | ii = pLeaf->szLeaf; |
| 246185 | 246387 | while( ii<pLeaf->nn && p->rc==SQLITE_OK ){ |
| 246186 | 246388 | int res; |
| 246187 | | - int iOff; |
| 246389 | + i64 iOff; |
| 246188 | 246390 | int nIncr; |
| 246189 | 246391 | |
| 246190 | 246392 | ii += fts5GetVarint32(&pLeaf->p[ii], nIncr); |
| 246191 | 246393 | iTermOff += nIncr; |
| 246192 | 246394 | iOff = iTermOff; |
| | @@ -249207,11 +249409,14 @@ |
| 249207 | 249409 | const char **pz, |
| 249208 | 249410 | int *pn |
| 249209 | 249411 | ){ |
| 249210 | 249412 | int rc = SQLITE_OK; |
| 249211 | 249413 | Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; |
| 249212 | | - if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab)) |
| 249414 | + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); |
| 249415 | + if( iCol<0 || iCol>=pTab->pConfig->nCol ){ |
| 249416 | + rc = SQLITE_RANGE; |
| 249417 | + }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab)) |
| 249213 | 249418 | || pCsr->ePlan==FTS5_PLAN_SPECIAL |
| 249214 | 249419 | ){ |
| 249215 | 249420 | *pz = 0; |
| 249216 | 249421 | *pn = 0; |
| 249217 | 249422 | }else{ |
| | @@ -249232,12 +249437,13 @@ |
| 249232 | 249437 | ){ |
| 249233 | 249438 | Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig; |
| 249234 | 249439 | int rc = SQLITE_OK; |
| 249235 | 249440 | int bLive = (pCsr->pSorter==0); |
| 249236 | 249441 | |
| 249237 | | - if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){ |
| 249238 | | - |
| 249442 | + if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){ |
| 249443 | + rc = SQLITE_RANGE; |
| 249444 | + }else if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){ |
| 249239 | 249445 | if( pConfig->eDetail!=FTS5_DETAIL_FULL ){ |
| 249240 | 249446 | Fts5PoslistPopulator *aPopulator; |
| 249241 | 249447 | int i; |
| 249242 | 249448 | aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive); |
| 249243 | 249449 | if( aPopulator==0 ) rc = SQLITE_NOMEM; |
| | @@ -249257,18 +249463,24 @@ |
| 249257 | 249463 | } |
| 249258 | 249464 | } |
| 249259 | 249465 | CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST); |
| 249260 | 249466 | } |
| 249261 | 249467 | |
| 249262 | | - if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){ |
| 249263 | | - Fts5Sorter *pSorter = pCsr->pSorter; |
| 249264 | | - int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]); |
| 249265 | | - *pn = pSorter->aIdx[iPhrase] - i1; |
| 249266 | | - *pa = &pSorter->aPoslist[i1]; |
| 249468 | + if( rc==SQLITE_OK ){ |
| 249469 | + if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){ |
| 249470 | + Fts5Sorter *pSorter = pCsr->pSorter; |
| 249471 | + int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]); |
| 249472 | + *pn = pSorter->aIdx[iPhrase] - i1; |
| 249473 | + *pa = &pSorter->aPoslist[i1]; |
| 249474 | + }else{ |
| 249475 | + *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa); |
| 249476 | + } |
| 249267 | 249477 | }else{ |
| 249268 | | - *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa); |
| 249478 | + *pa = 0; |
| 249479 | + *pn = 0; |
| 249269 | 249480 | } |
| 249481 | + |
| 249270 | 249482 | |
| 249271 | 249483 | return rc; |
| 249272 | 249484 | } |
| 249273 | 249485 | |
| 249274 | 249486 | /* |
| | @@ -250223,11 +250435,11 @@ |
| 250223 | 250435 | int nArg, /* Number of args */ |
| 250224 | 250436 | sqlite3_value **apUnused /* Function arguments */ |
| 250225 | 250437 | ){ |
| 250226 | 250438 | assert( nArg==0 ); |
| 250227 | 250439 | UNUSED_PARAM2(nArg, apUnused); |
| 250228 | | - sqlite3_result_text(pCtx, "fts5: 2023-12-14 16:34:47 27d4a89a5ff96b7b7fc5dc9650e1269f7c7edf91de9b9aafce40be9ecc8b95e9", -1, SQLITE_TRANSIENT); |
| 250440 | + sqlite3_result_text(pCtx, "fts5: 2023-12-29 19:03:01 4b70b94616ef37bac969051eee3ea6913a28f30520cdd4fc3a19e848f2cf12b7", -1, SQLITE_TRANSIENT); |
| 250229 | 250441 | } |
| 250230 | 250442 | |
| 250231 | 250443 | /* |
| 250232 | 250444 | ** Return true if zName is the extension on one of the shadow tables used |
| 250233 | 250445 | ** by this module. |
| 250234 | 250446 | |