| | @@ -678,11 +678,11 @@ |
| 678 | 678 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 679 | 679 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 680 | 680 | */ |
| 681 | 681 | #define SQLITE_VERSION "3.7.17" |
| 682 | 682 | #define SQLITE_VERSION_NUMBER 3007017 |
| 683 | | -#define SQLITE_SOURCE_ID "2013-04-25 17:27:08 aabeea98f53edde68f484f1794ae70789dac3889" |
| 683 | +#define SQLITE_SOURCE_ID "2013-05-03 15:23:24 b2efe4f225adc5f4c2e3080bf459cc52fff82e18" |
| 684 | 684 | |
| 685 | 685 | /* |
| 686 | 686 | ** CAPI3REF: Run-Time Library Version Numbers |
| 687 | 687 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 688 | 688 | ** |
| | @@ -2161,11 +2161,13 @@ |
| 2161 | 2161 | ** <dd> ^(This option takes a single argument which is a pointer to an |
| 2162 | 2162 | ** [sqlite3_pcache_methods2] object. SQLite copies of the current |
| 2163 | 2163 | ** page cache implementation into that object.)^ </dd> |
| 2164 | 2164 | ** |
| 2165 | 2165 | ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> |
| 2166 | | -** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a |
| 2166 | +** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite |
| 2167 | +** global [error log]. |
| 2168 | +** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a |
| 2167 | 2169 | ** function with a call signature of void(*)(void*,int,const char*), |
| 2168 | 2170 | ** and a pointer to void. ^If the function pointer is not NULL, it is |
| 2169 | 2171 | ** invoked by [sqlite3_log()] to process each logging event. ^If the |
| 2170 | 2172 | ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. |
| 2171 | 2173 | ** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is |
| | @@ -3096,10 +3098,13 @@ |
| 3096 | 3098 | ** SQL statement text as the statement first begins executing. |
| 3097 | 3099 | ** ^(Additional sqlite3_trace() callbacks might occur |
| 3098 | 3100 | ** as each triggered subprogram is entered. The callbacks for triggers |
| 3099 | 3101 | ** contain a UTF-8 SQL comment that identifies the trigger.)^ |
| 3100 | 3102 | ** |
| 3103 | +** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit |
| 3104 | +** the length of [bound parameter] expansion in the output of sqlite3_trace(). |
| 3105 | +** |
| 3101 | 3106 | ** ^The callback function registered by sqlite3_profile() is invoked |
| 3102 | 3107 | ** as each SQL statement finishes. ^The profile callback contains |
| 3103 | 3108 | ** the original statement text and an estimate of wall-clock time |
| 3104 | 3109 | ** of how long that statement took to run. ^The profile callback |
| 3105 | 3110 | ** time is in units of nanoseconds, however the current implementation |
| | @@ -3634,11 +3639,12 @@ |
| 3634 | 3639 | ** |
| 3635 | 3640 | ** <ol> |
| 3636 | 3641 | ** <li> |
| 3637 | 3642 | ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it |
| 3638 | 3643 | ** always used to do, [sqlite3_step()] will automatically recompile the SQL |
| 3639 | | -** statement and try to run it again. |
| 3644 | +** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY] |
| 3645 | +** retries will occur before sqlite3_step() gives up and returns an error. |
| 3640 | 3646 | ** </li> |
| 3641 | 3647 | ** |
| 3642 | 3648 | ** <li> |
| 3643 | 3649 | ** ^When an error occurs, [sqlite3_step()] will return one of the detailed |
| 3644 | 3650 | ** [error codes] or [extended error codes]. ^The legacy behavior was that |
| | @@ -3838,10 +3844,13 @@ |
| 3838 | 3844 | ** for "?NNN" parameters is the value of NNN. |
| 3839 | 3845 | ** ^The NNN value must be between 1 and the [sqlite3_limit()] |
| 3840 | 3846 | ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). |
| 3841 | 3847 | ** |
| 3842 | 3848 | ** ^The third argument is the value to bind to the parameter. |
| 3849 | +** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16() |
| 3850 | +** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter |
| 3851 | +** is ignored and the end result is the same as sqlite3_bind_null(). |
| 3843 | 3852 | ** |
| 3844 | 3853 | ** ^(In those routines that have a fourth argument, its value is the |
| 3845 | 3854 | ** number of bytes in the parameter. To be clear: the value is the |
| 3846 | 3855 | ** number of <u>bytes</u> in the value, not the number of characters.)^ |
| 3847 | 3856 | ** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() |
| | @@ -7446,11 +7455,11 @@ |
| 7446 | 7455 | SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); |
| 7447 | 7456 | |
| 7448 | 7457 | /* |
| 7449 | 7458 | ** CAPI3REF: Error Logging Interface |
| 7450 | 7459 | ** |
| 7451 | | -** ^The [sqlite3_log()] interface writes a message into the error log |
| 7460 | +** ^The [sqlite3_log()] interface writes a message into the [error log] |
| 7452 | 7461 | ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. |
| 7453 | 7462 | ** ^If logging is enabled, the zFormat string and subsequent arguments are |
| 7454 | 7463 | ** used with [sqlite3_snprintf()] to generate the final output string. |
| 7455 | 7464 | ** |
| 7456 | 7465 | ** The sqlite3_log() interface is intended for use by extensions such as |
| | @@ -8302,11 +8311,11 @@ |
| 8302 | 8311 | #ifndef SQLITE_MAX_MMAP_SIZE |
| 8303 | 8312 | # if defined(__linux__) \ |
| 8304 | 8313 | || defined(_WIN32) \ |
| 8305 | 8314 | || (defined(__APPLE__) && defined(__MACH__)) \ |
| 8306 | 8315 | || defined(__sun) |
| 8307 | | -# define SQLITE_MAX_MMAP_SIZE 2147483648 |
| 8316 | +# define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */ |
| 8308 | 8317 | # else |
| 8309 | 8318 | # define SQLITE_MAX_MMAP_SIZE 0 |
| 8310 | 8319 | # endif |
| 8311 | 8320 | # define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */ |
| 8312 | 8321 | #endif |
| | @@ -8620,10 +8629,11 @@ |
| 8620 | 8629 | #define BTREE_DEFAULT_CACHE_SIZE 3 |
| 8621 | 8630 | #define BTREE_LARGEST_ROOT_PAGE 4 |
| 8622 | 8631 | #define BTREE_TEXT_ENCODING 5 |
| 8623 | 8632 | #define BTREE_USER_VERSION 6 |
| 8624 | 8633 | #define BTREE_INCR_VACUUM 7 |
| 8634 | +#define BTREE_APPLICATION_ID 8 |
| 8625 | 8635 | |
| 8626 | 8636 | /* |
| 8627 | 8637 | ** Values that may be OR'd together to form the second argument of an |
| 8628 | 8638 | ** sqlite3BtreeCursorHints() call. |
| 8629 | 8639 | */ |
| | @@ -22993,11 +23003,11 @@ |
| 22993 | 23003 | #include <fcntl.h> |
| 22994 | 23004 | #include <unistd.h> |
| 22995 | 23005 | /* #include <time.h> */ |
| 22996 | 23006 | #include <sys/time.h> |
| 22997 | 23007 | #include <errno.h> |
| 22998 | | -#ifndef SQLITE_OMIT_WAL |
| 23008 | +#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 |
| 22999 | 23009 | #include <sys/mman.h> |
| 23000 | 23010 | #endif |
| 23001 | 23011 | |
| 23002 | 23012 | |
| 23003 | 23013 | #if SQLITE_ENABLE_LOCKING_STYLE |
| | @@ -26267,52 +26277,65 @@ |
| 26267 | 26277 | /* Unread parts of the buffer must be zero-filled */ |
| 26268 | 26278 | memset(&((char*)pBuf)[got], 0, amt-got); |
| 26269 | 26279 | return SQLITE_IOERR_SHORT_READ; |
| 26270 | 26280 | } |
| 26271 | 26281 | } |
| 26282 | + |
| 26283 | +/* |
| 26284 | +** Attempt to seek the file-descriptor passed as the first argument to |
| 26285 | +** absolute offset iOff, then attempt to write nBuf bytes of data from |
| 26286 | +** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, |
| 26287 | +** return the actual number of bytes written (which may be less than |
| 26288 | +** nBuf). |
| 26289 | +*/ |
| 26290 | +static int seekAndWriteFd( |
| 26291 | + int fd, /* File descriptor to write to */ |
| 26292 | + i64 iOff, /* File offset to begin writing at */ |
| 26293 | + const void *pBuf, /* Copy data from this buffer to the file */ |
| 26294 | + int nBuf, /* Size of buffer pBuf in bytes */ |
| 26295 | + int *piErrno /* OUT: Error number if error occurs */ |
| 26296 | +){ |
| 26297 | + int rc = 0; /* Value returned by system call */ |
| 26298 | + |
| 26299 | + assert( nBuf==(nBuf&0x1ffff) ); |
| 26300 | + nBuf &= 0x1ffff; |
| 26301 | + TIMER_START; |
| 26302 | + |
| 26303 | +#if defined(USE_PREAD) |
| 26304 | + do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); |
| 26305 | +#elif defined(USE_PREAD64) |
| 26306 | + do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); |
| 26307 | +#else |
| 26308 | + do{ |
| 26309 | + i64 iSeek = lseek(fd, iOff, SEEK_SET); |
| 26310 | + SimulateIOError( iSeek-- ); |
| 26311 | + |
| 26312 | + if( iSeek!=iOff ){ |
| 26313 | + if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0); |
| 26314 | + return -1; |
| 26315 | + } |
| 26316 | + rc = osWrite(fd, pBuf, nBuf); |
| 26317 | + }while( rc<0 && errno==EINTR ); |
| 26318 | +#endif |
| 26319 | + |
| 26320 | + TIMER_END; |
| 26321 | + OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED)); |
| 26322 | + |
| 26323 | + if( rc<0 && piErrno ) *piErrno = errno; |
| 26324 | + return rc; |
| 26325 | +} |
| 26326 | + |
| 26272 | 26327 | |
| 26273 | 26328 | /* |
| 26274 | 26329 | ** Seek to the offset in id->offset then read cnt bytes into pBuf. |
| 26275 | 26330 | ** Return the number of bytes actually read. Update the offset. |
| 26276 | 26331 | ** |
| 26277 | 26332 | ** To avoid stomping the errno value on a failed write the lastErrno value |
| 26278 | 26333 | ** is set before returning. |
| 26279 | 26334 | */ |
| 26280 | 26335 | static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ |
| 26281 | | - int got; |
| 26282 | | -#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) |
| 26283 | | - i64 newOffset; |
| 26284 | | -#endif |
| 26285 | | - assert( cnt==(cnt&0x1ffff) ); |
| 26286 | | - cnt &= 0x1ffff; |
| 26287 | | - TIMER_START; |
| 26288 | | -#if defined(USE_PREAD) |
| 26289 | | - do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR ); |
| 26290 | | -#elif defined(USE_PREAD64) |
| 26291 | | - do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR); |
| 26292 | | -#else |
| 26293 | | - do{ |
| 26294 | | - newOffset = lseek(id->h, offset, SEEK_SET); |
| 26295 | | - SimulateIOError( newOffset-- ); |
| 26296 | | - if( newOffset!=offset ){ |
| 26297 | | - if( newOffset == -1 ){ |
| 26298 | | - ((unixFile*)id)->lastErrno = errno; |
| 26299 | | - }else{ |
| 26300 | | - ((unixFile*)id)->lastErrno = 0; |
| 26301 | | - } |
| 26302 | | - return -1; |
| 26303 | | - } |
| 26304 | | - got = osWrite(id->h, pBuf, cnt); |
| 26305 | | - }while( got<0 && errno==EINTR ); |
| 26306 | | -#endif |
| 26307 | | - TIMER_END; |
| 26308 | | - if( got<0 ){ |
| 26309 | | - ((unixFile*)id)->lastErrno = errno; |
| 26310 | | - } |
| 26311 | | - |
| 26312 | | - OSTRACE(("WRITE %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED)); |
| 26313 | | - return got; |
| 26336 | + return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno); |
| 26314 | 26337 | } |
| 26315 | 26338 | |
| 26316 | 26339 | |
| 26317 | 26340 | /* |
| 26318 | 26341 | ** Write data from a buffer into a file. Return SQLITE_OK on success |
| | @@ -27397,28 +27420,36 @@ |
| 27397 | 27420 | } |
| 27398 | 27421 | |
| 27399 | 27422 | if( sStat.st_size<nByte ){ |
| 27400 | 27423 | /* The requested memory region does not exist. If bExtend is set to |
| 27401 | 27424 | ** false, exit early. *pp will be set to NULL and SQLITE_OK returned. |
| 27402 | | - ** |
| 27403 | | - ** Alternatively, if bExtend is true, use ftruncate() to allocate |
| 27404 | | - ** the requested memory region. |
| 27405 | | - */ |
| 27406 | | - if( !bExtend ) goto shmpage_out; |
| 27407 | | -#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
| 27408 | | - if( osFallocate(pShmNode->h, sStat.st_size, nByte)!=0 ){ |
| 27409 | | - rc = unixLogError(SQLITE_IOERR_SHMSIZE, "fallocate", |
| 27410 | | - pShmNode->zFilename); |
| 27411 | | - goto shmpage_out; |
| 27412 | | - } |
| 27413 | | -#else |
| 27414 | | - if( robust_ftruncate(pShmNode->h, nByte) ){ |
| 27415 | | - rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate", |
| 27416 | | - pShmNode->zFilename); |
| 27417 | | - goto shmpage_out; |
| 27418 | | - } |
| 27419 | | -#endif |
| 27425 | + */ |
| 27426 | + if( !bExtend ){ |
| 27427 | + goto shmpage_out; |
| 27428 | + } |
| 27429 | + |
| 27430 | + /* Alternatively, if bExtend is true, extend the file. Do this by |
| 27431 | + ** writing a single byte to the end of each (OS) page being |
| 27432 | + ** allocated or extended. Technically, we need only write to the |
| 27433 | + ** last page in order to extend the file. But writing to all new |
| 27434 | + ** pages forces the OS to allocate them immediately, which reduces |
| 27435 | + ** the chances of SIGBUS while accessing the mapped region later on. |
| 27436 | + */ |
| 27437 | + else{ |
| 27438 | + static const int pgsz = 4096; |
| 27439 | + int iPg; |
| 27440 | + |
| 27441 | + /* Write to the last byte of each newly allocated or extended page */ |
| 27442 | + assert( (nByte % pgsz)==0 ); |
| 27443 | + for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){ |
| 27444 | + if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){ |
| 27445 | + const char *zFile = pShmNode->zFilename; |
| 27446 | + rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); |
| 27447 | + goto shmpage_out; |
| 27448 | + } |
| 27449 | + } |
| 27450 | + } |
| 27420 | 27451 | } |
| 27421 | 27452 | } |
| 27422 | 27453 | |
| 27423 | 27454 | /* Map the requested memory region into this processes address space. */ |
| 27424 | 27455 | apNew = (char **)sqlite3_realloc( |
| | @@ -28341,13 +28372,12 @@ |
| 28341 | 28372 | #if OS_VXWORKS |
| 28342 | 28373 | if( rc!=SQLITE_OK ){ |
| 28343 | 28374 | if( h>=0 ) robust_close(pNew, h, __LINE__); |
| 28344 | 28375 | h = -1; |
| 28345 | 28376 | osUnlink(zFilename); |
| 28346 | | - isDelete = 0; |
| 28377 | + pNew->ctrlFlags |= UNIXFILE_DELETE; |
| 28347 | 28378 | } |
| 28348 | | - if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE; |
| 28349 | 28379 | #endif |
| 28350 | 28380 | if( rc!=SQLITE_OK ){ |
| 28351 | 28381 | if( h>=0 ) robust_close(pNew, h, __LINE__); |
| 28352 | 28382 | }else{ |
| 28353 | 28383 | pNew->pMethod = pLockingStyle; |
| | @@ -38108,10 +38138,11 @@ |
| 38108 | 38138 | # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 |
| 38109 | 38139 | # define sqlite3WalCallback(z) 0 |
| 38110 | 38140 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 38111 | 38141 | # define sqlite3WalHeapMemory(z) 0 |
| 38112 | 38142 | # define sqlite3WalFramesize(z) 0 |
| 38143 | +# define sqlite3WalFindFrame(x,y,z) 0 |
| 38113 | 38144 | #else |
| 38114 | 38145 | |
| 38115 | 38146 | #define WAL_SAVEPOINT_NDATA 4 |
| 38116 | 38147 | |
| 38117 | 38148 | /* Connection to a write-ahead log (WAL) file. |
| | @@ -41052,14 +41083,17 @@ |
| 41052 | 41083 | assert( pPager->tempFile ); |
| 41053 | 41084 | memset(pPg->pData, 0, pPager->pageSize); |
| 41054 | 41085 | return SQLITE_OK; |
| 41055 | 41086 | } |
| 41056 | 41087 | |
| 41088 | +#ifndef SQLITE_OMIT_WAL |
| 41057 | 41089 | if( iFrame ){ |
| 41058 | 41090 | /* Try to pull the page from the write-ahead log. */ |
| 41059 | 41091 | rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData); |
| 41060 | | - }else{ |
| 41092 | + }else |
| 41093 | +#endif |
| 41094 | + { |
| 41061 | 41095 | i64 iOffset = (pgno-1)*(i64)pPager->pageSize; |
| 41062 | 41096 | rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset); |
| 41063 | 41097 | if( rc==SQLITE_IOERR_SHORT_READ ){ |
| 41064 | 41098 | rc = SQLITE_OK; |
| 41065 | 41099 | } |
| | @@ -44108,10 +44142,15 @@ |
| 44108 | 44142 | if( rc==SQLITE_OK ){ |
| 44109 | 44143 | rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); |
| 44110 | 44144 | pPager->aStat[PAGER_STAT_WRITE]++; |
| 44111 | 44145 | } |
| 44112 | 44146 | if( rc==SQLITE_OK ){ |
| 44147 | + /* Update the pager's copy of the change-counter. Otherwise, the |
| 44148 | + ** next time a read transaction is opened the cache will be |
| 44149 | + ** flushed (as the change-counter values will not match). */ |
| 44150 | + const void *pCopy = (const void *)&((const char *)zBuf)[24]; |
| 44151 | + memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers)); |
| 44113 | 44152 | pPager->changeCountDone = 1; |
| 44114 | 44153 | } |
| 44115 | 44154 | }else{ |
| 44116 | 44155 | pPager->changeCountDone = 1; |
| 44117 | 44156 | } |
| | @@ -94790,10 +94829,15 @@ |
| 94790 | 94829 | ** PRAGMA [database.]schema_version |
| 94791 | 94830 | ** PRAGMA [database.]schema_version = <integer> |
| 94792 | 94831 | ** |
| 94793 | 94832 | ** PRAGMA [database.]user_version |
| 94794 | 94833 | ** PRAGMA [database.]user_version = <integer> |
| 94834 | + ** |
| 94835 | + ** PRAGMA [database.]freelist_count = <integer> |
| 94836 | + ** |
| 94837 | + ** PRAGMA [database.]application_id |
| 94838 | + ** PRAGMA [database.]application_id = <integer> |
| 94795 | 94839 | ** |
| 94796 | 94840 | ** The pragma's schema_version and user_version are used to set or get |
| 94797 | 94841 | ** the value of the schema-version and user-version, respectively. Both |
| 94798 | 94842 | ** the schema-version and the user-version are 32-bit signed integers |
| 94799 | 94843 | ** stored in the database header. |
| | @@ -94812,14 +94856,18 @@ |
| 94812 | 94856 | ** applications for any purpose. |
| 94813 | 94857 | */ |
| 94814 | 94858 | if( sqlite3StrICmp(zLeft, "schema_version")==0 |
| 94815 | 94859 | || sqlite3StrICmp(zLeft, "user_version")==0 |
| 94816 | 94860 | || sqlite3StrICmp(zLeft, "freelist_count")==0 |
| 94861 | + || sqlite3StrICmp(zLeft, "application_id")==0 |
| 94817 | 94862 | ){ |
| 94818 | 94863 | int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ |
| 94819 | 94864 | sqlite3VdbeUsesBtree(v, iDb); |
| 94820 | 94865 | switch( zLeft[0] ){ |
| 94866 | + case 'a': case 'A': |
| 94867 | + iCookie = BTREE_APPLICATION_ID; |
| 94868 | + break; |
| 94821 | 94869 | case 'f': case 'F': |
| 94822 | 94870 | iCookie = BTREE_FREE_PAGE_COUNT; |
| 94823 | 94871 | break; |
| 94824 | 94872 | case 's': case 'S': |
| 94825 | 94873 | iCookie = BTREE_SCHEMA_VERSION; |
| | @@ -102982,10 +103030,11 @@ |
| 102982 | 103030 | static const unsigned char aCopy[] = { |
| 102983 | 103031 | BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ |
| 102984 | 103032 | BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ |
| 102985 | 103033 | BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ |
| 102986 | 103034 | BTREE_USER_VERSION, 0, /* Preserve the user version */ |
| 103035 | + BTREE_APPLICATION_ID, 0, /* Preserve the application id */ |
| 102987 | 103036 | }; |
| 102988 | 103037 | |
| 102989 | 103038 | assert( 1==sqlite3BtreeIsInTrans(pTemp) ); |
| 102990 | 103039 | assert( 1==sqlite3BtreeIsInTrans(pMain) ); |
| 102991 | 103040 | |
| | @@ -104849,11 +104898,11 @@ |
| 104849 | 104898 | } |
| 104850 | 104899 | if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){ |
| 104851 | 104900 | continue; |
| 104852 | 104901 | } |
| 104853 | 104902 | } |
| 104854 | | - if( pTerm->prereqRight==0 ){ |
| 104903 | + if( pTerm->prereqRight==0 && (pTerm->eOperator&WO_EQ)!=0 ){ |
| 104855 | 104904 | pResult = pTerm; |
| 104856 | 104905 | goto findTerm_success; |
| 104857 | 104906 | }else if( pResult==0 ){ |
| 104858 | 104907 | pResult = pTerm; |
| 104859 | 104908 | } |
| | @@ -109027,10 +109076,11 @@ |
| 109027 | 109076 | pE = pTerm->pExpr; |
| 109028 | 109077 | assert( !ExprHasProperty(pE, EP_FromJoin) ); |
| 109029 | 109078 | assert( (pTerm->prereqRight & newNotReady)!=0 ); |
| 109030 | 109079 | pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0); |
| 109031 | 109080 | if( pAlt==0 ) continue; |
| 109081 | + if( pAlt->wtFlags & (TERM_CODED) ) continue; |
| 109032 | 109082 | VdbeNoopComment((v, "begin transitive constraint")); |
| 109033 | 109083 | sEq = *pAlt->pExpr; |
| 109034 | 109084 | sEq.pLeft = pE->pLeft; |
| 109035 | 109085 | sqlite3ExprIfFalse(pParse, &sEq, addrCont, SQLITE_JUMPIFNULL); |
| 109036 | 109086 | } |
| | @@ -112374,11 +112424,13 @@ |
| 112374 | 112424 | if( yygotominor.yy347 ){ |
| 112375 | 112425 | struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1]; |
| 112376 | 112426 | struct SrcList_item *pOld = yymsp[-4].minor.yy347->a; |
| 112377 | 112427 | pNew->zName = pOld->zName; |
| 112378 | 112428 | pNew->zDatabase = pOld->zDatabase; |
| 112429 | + pNew->pSelect = pOld->pSelect; |
| 112379 | 112430 | pOld->zName = pOld->zDatabase = 0; |
| 112431 | + pOld->pSelect = 0; |
| 112380 | 112432 | } |
| 112381 | 112433 | sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347); |
| 112382 | 112434 | }else{ |
| 112383 | 112435 | Select *pSubquery; |
| 112384 | 112436 | sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); |
| | @@ -119192,11 +119244,11 @@ |
| 119192 | 119244 | ); |
| 119193 | 119245 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); |
| 119194 | 119246 | |
| 119195 | 119247 | /* fts3_expr.c */ |
| 119196 | 119248 | SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, |
| 119197 | | - char **, int, int, int, const char *, int, Fts3Expr ** |
| 119249 | + char **, int, int, int, const char *, int, Fts3Expr **, char ** |
| 119198 | 119250 | ); |
| 119199 | 119251 | SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); |
| 119200 | 119252 | #ifdef SQLITE_TEST |
| 119201 | 119253 | SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); |
| 119202 | 119254 | SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); |
| | @@ -121916,18 +121968,16 @@ |
| 121916 | 121968 | } |
| 121917 | 121969 | |
| 121918 | 121970 | pCsr->iLangid = 0; |
| 121919 | 121971 | if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]); |
| 121920 | 121972 | |
| 121973 | + assert( p->base.zErrMsg==0 ); |
| 121921 | 121974 | rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, |
| 121922 | | - p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr |
| 121975 | + p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr, |
| 121976 | + &p->base.zErrMsg |
| 121923 | 121977 | ); |
| 121924 | 121978 | if( rc!=SQLITE_OK ){ |
| 121925 | | - if( rc==SQLITE_ERROR ){ |
| 121926 | | - static const char *zErr = "malformed MATCH expression: [%s]"; |
| 121927 | | - p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery); |
| 121928 | | - } |
| 121929 | 121979 | return rc; |
| 121930 | 121980 | } |
| 121931 | 121981 | |
| 121932 | 121982 | rc = sqlite3Fts3ReadLock(p); |
| 121933 | 121983 | if( rc!=SQLITE_OK ) return rc; |
| | @@ -125425,12 +125475,14 @@ |
| 125425 | 125475 | rc = SQLITE_NOMEM; |
| 125426 | 125476 | goto exprparse_out; |
| 125427 | 125477 | } |
| 125428 | 125478 | pNot->eType = FTSQUERY_NOT; |
| 125429 | 125479 | pNot->pRight = p; |
| 125480 | + p->pParent = pNot; |
| 125430 | 125481 | if( pNotBranch ){ |
| 125431 | 125482 | pNot->pLeft = pNotBranch; |
| 125483 | + pNotBranch->pParent = pNot; |
| 125432 | 125484 | } |
| 125433 | 125485 | pNotBranch = pNot; |
| 125434 | 125486 | p = pPrev; |
| 125435 | 125487 | }else{ |
| 125436 | 125488 | int eType = p->eType; |
| | @@ -125514,10 +125566,11 @@ |
| 125514 | 125566 | Fts3Expr *pIter = pNotBranch; |
| 125515 | 125567 | while( pIter->pLeft ){ |
| 125516 | 125568 | pIter = pIter->pLeft; |
| 125517 | 125569 | } |
| 125518 | 125570 | pIter->pLeft = pRet; |
| 125571 | + pRet->pParent = pIter; |
| 125519 | 125572 | pRet = pNotBranch; |
| 125520 | 125573 | } |
| 125521 | 125574 | } |
| 125522 | 125575 | } |
| 125523 | 125576 | *pnConsumed = n - nIn; |
| | @@ -125529,10 +125582,226 @@ |
| 125529 | 125582 | pRet = 0; |
| 125530 | 125583 | } |
| 125531 | 125584 | *ppExpr = pRet; |
| 125532 | 125585 | return rc; |
| 125533 | 125586 | } |
| 125587 | + |
| 125588 | +/* |
| 125589 | +** Return SQLITE_ERROR if the maximum depth of the expression tree passed |
| 125590 | +** as the only argument is more than nMaxDepth. |
| 125591 | +*/ |
| 125592 | +static int fts3ExprCheckDepth(Fts3Expr *p, int nMaxDepth){ |
| 125593 | + int rc = SQLITE_OK; |
| 125594 | + if( p ){ |
| 125595 | + if( nMaxDepth<0 ){ |
| 125596 | + rc = SQLITE_TOOBIG; |
| 125597 | + }else{ |
| 125598 | + rc = fts3ExprCheckDepth(p->pLeft, nMaxDepth-1); |
| 125599 | + if( rc==SQLITE_OK ){ |
| 125600 | + rc = fts3ExprCheckDepth(p->pRight, nMaxDepth-1); |
| 125601 | + } |
| 125602 | + } |
| 125603 | + } |
| 125604 | + return rc; |
| 125605 | +} |
| 125606 | + |
| 125607 | +/* |
| 125608 | +** This function attempts to transform the expression tree at (*pp) to |
| 125609 | +** an equivalent but more balanced form. The tree is modified in place. |
| 125610 | +** If successful, SQLITE_OK is returned and (*pp) set to point to the |
| 125611 | +** new root expression node. |
| 125612 | +** |
| 125613 | +** nMaxDepth is the maximum allowable depth of the balanced sub-tree. |
| 125614 | +** |
| 125615 | +** Otherwise, if an error occurs, an SQLite error code is returned and |
| 125616 | +** expression (*pp) freed. |
| 125617 | +*/ |
| 125618 | +static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){ |
| 125619 | + int rc = SQLITE_OK; /* Return code */ |
| 125620 | + Fts3Expr *pRoot = *pp; /* Initial root node */ |
| 125621 | + Fts3Expr *pFree = 0; /* List of free nodes. Linked by pParent. */ |
| 125622 | + int eType = pRoot->eType; /* Type of node in this tree */ |
| 125623 | + |
| 125624 | + if( nMaxDepth==0 ){ |
| 125625 | + rc = SQLITE_ERROR; |
| 125626 | + } |
| 125627 | + |
| 125628 | + if( rc==SQLITE_OK && (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){ |
| 125629 | + Fts3Expr **apLeaf; |
| 125630 | + apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth); |
| 125631 | + if( 0==apLeaf ){ |
| 125632 | + rc = SQLITE_NOMEM; |
| 125633 | + }else{ |
| 125634 | + memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth); |
| 125635 | + } |
| 125636 | + |
| 125637 | + if( rc==SQLITE_OK ){ |
| 125638 | + int i; |
| 125639 | + Fts3Expr *p; |
| 125640 | + |
| 125641 | + /* Set $p to point to the left-most leaf in the tree of eType nodes. */ |
| 125642 | + for(p=pRoot; p->eType==eType; p=p->pLeft){ |
| 125643 | + assert( p->pParent==0 || p->pParent->pLeft==p ); |
| 125644 | + assert( p->pLeft && p->pRight ); |
| 125645 | + } |
| 125646 | + |
| 125647 | + /* This loop runs once for each leaf in the tree of eType nodes. */ |
| 125648 | + while( 1 ){ |
| 125649 | + int iLvl; |
| 125650 | + Fts3Expr *pParent = p->pParent; /* Current parent of p */ |
| 125651 | + |
| 125652 | + assert( pParent==0 || pParent->pLeft==p ); |
| 125653 | + p->pParent = 0; |
| 125654 | + if( pParent ){ |
| 125655 | + pParent->pLeft = 0; |
| 125656 | + }else{ |
| 125657 | + pRoot = 0; |
| 125658 | + } |
| 125659 | + rc = fts3ExprBalance(&p, nMaxDepth-1); |
| 125660 | + if( rc!=SQLITE_OK ) break; |
| 125661 | + |
| 125662 | + for(iLvl=0; p && iLvl<nMaxDepth; iLvl++){ |
| 125663 | + if( apLeaf[iLvl]==0 ){ |
| 125664 | + apLeaf[iLvl] = p; |
| 125665 | + p = 0; |
| 125666 | + }else{ |
| 125667 | + assert( pFree ); |
| 125668 | + pFree->pLeft = apLeaf[iLvl]; |
| 125669 | + pFree->pRight = p; |
| 125670 | + pFree->pLeft->pParent = pFree; |
| 125671 | + pFree->pRight->pParent = pFree; |
| 125672 | + |
| 125673 | + p = pFree; |
| 125674 | + pFree = pFree->pParent; |
| 125675 | + p->pParent = 0; |
| 125676 | + apLeaf[iLvl] = 0; |
| 125677 | + } |
| 125678 | + } |
| 125679 | + if( p ){ |
| 125680 | + sqlite3Fts3ExprFree(p); |
| 125681 | + rc = SQLITE_TOOBIG; |
| 125682 | + break; |
| 125683 | + } |
| 125684 | + |
| 125685 | + /* If that was the last leaf node, break out of the loop */ |
| 125686 | + if( pParent==0 ) break; |
| 125687 | + |
| 125688 | + /* Set $p to point to the next leaf in the tree of eType nodes */ |
| 125689 | + for(p=pParent->pRight; p->eType==eType; p=p->pLeft); |
| 125690 | + |
| 125691 | + /* Remove pParent from the original tree. */ |
| 125692 | + assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent ); |
| 125693 | + pParent->pRight->pParent = pParent->pParent; |
| 125694 | + if( pParent->pParent ){ |
| 125695 | + pParent->pParent->pLeft = pParent->pRight; |
| 125696 | + }else{ |
| 125697 | + assert( pParent==pRoot ); |
| 125698 | + pRoot = pParent->pRight; |
| 125699 | + } |
| 125700 | + |
| 125701 | + /* Link pParent into the free node list. It will be used as an |
| 125702 | + ** internal node of the new tree. */ |
| 125703 | + pParent->pParent = pFree; |
| 125704 | + pFree = pParent; |
| 125705 | + } |
| 125706 | + |
| 125707 | + if( rc==SQLITE_OK ){ |
| 125708 | + p = 0; |
| 125709 | + for(i=0; i<nMaxDepth; i++){ |
| 125710 | + if( apLeaf[i] ){ |
| 125711 | + if( p==0 ){ |
| 125712 | + p = apLeaf[i]; |
| 125713 | + p->pParent = 0; |
| 125714 | + }else{ |
| 125715 | + pFree->pRight = p; |
| 125716 | + pFree->pLeft = apLeaf[i]; |
| 125717 | + pFree->pLeft->pParent = pFree; |
| 125718 | + pFree->pRight->pParent = pFree; |
| 125719 | + |
| 125720 | + p = pFree; |
| 125721 | + pFree = pFree->pParent; |
| 125722 | + p->pParent = 0; |
| 125723 | + } |
| 125724 | + } |
| 125725 | + } |
| 125726 | + pRoot = p; |
| 125727 | + }else{ |
| 125728 | + /* An error occurred. Delete the contents of the apLeaf[] array |
| 125729 | + ** and pFree list. Everything else is cleaned up by the call to |
| 125730 | + ** sqlite3Fts3ExprFree(pRoot) below. */ |
| 125731 | + Fts3Expr *pDel; |
| 125732 | + for(i=0; i<nMaxDepth; i++){ |
| 125733 | + sqlite3Fts3ExprFree(apLeaf[i]); |
| 125734 | + } |
| 125735 | + while( (pDel=pFree)!=0 ){ |
| 125736 | + pFree = pDel->pParent; |
| 125737 | + sqlite3_free(pDel); |
| 125738 | + } |
| 125739 | + } |
| 125740 | + |
| 125741 | + assert( pFree==0 ); |
| 125742 | + sqlite3_free( apLeaf ); |
| 125743 | + } |
| 125744 | + } |
| 125745 | + |
| 125746 | + if( rc!=SQLITE_OK ){ |
| 125747 | + sqlite3Fts3ExprFree(pRoot); |
| 125748 | + pRoot = 0; |
| 125749 | + } |
| 125750 | + *pp = pRoot; |
| 125751 | + return rc; |
| 125752 | +} |
| 125753 | + |
| 125754 | +/* |
| 125755 | +** This function is similar to sqlite3Fts3ExprParse(), with the following |
| 125756 | +** differences: |
| 125757 | +** |
| 125758 | +** 1. It does not do expression rebalancing. |
| 125759 | +** 2. It does not check that the expression does not exceed the |
| 125760 | +** maximum allowable depth. |
| 125761 | +** 3. Even if it fails, *ppExpr may still be set to point to an |
| 125762 | +** expression tree. It should be deleted using sqlite3Fts3ExprFree() |
| 125763 | +** in this case. |
| 125764 | +*/ |
| 125765 | +static int fts3ExprParseUnbalanced( |
| 125766 | + sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ |
| 125767 | + int iLangid, /* Language id for tokenizer */ |
| 125768 | + char **azCol, /* Array of column names for fts3 table */ |
| 125769 | + int bFts4, /* True to allow FTS4-only syntax */ |
| 125770 | + int nCol, /* Number of entries in azCol[] */ |
| 125771 | + int iDefaultCol, /* Default column to query */ |
| 125772 | + const char *z, int n, /* Text of MATCH query */ |
| 125773 | + Fts3Expr **ppExpr /* OUT: Parsed query structure */ |
| 125774 | +){ |
| 125775 | + int nParsed; |
| 125776 | + int rc; |
| 125777 | + ParseContext sParse; |
| 125778 | + |
| 125779 | + memset(&sParse, 0, sizeof(ParseContext)); |
| 125780 | + sParse.pTokenizer = pTokenizer; |
| 125781 | + sParse.iLangid = iLangid; |
| 125782 | + sParse.azCol = (const char **)azCol; |
| 125783 | + sParse.nCol = nCol; |
| 125784 | + sParse.iDefaultCol = iDefaultCol; |
| 125785 | + sParse.bFts4 = bFts4; |
| 125786 | + if( z==0 ){ |
| 125787 | + *ppExpr = 0; |
| 125788 | + return SQLITE_OK; |
| 125789 | + } |
| 125790 | + if( n<0 ){ |
| 125791 | + n = (int)strlen(z); |
| 125792 | + } |
| 125793 | + rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed); |
| 125794 | + assert( rc==SQLITE_OK || *ppExpr==0 ); |
| 125795 | + |
| 125796 | + /* Check for mismatched parenthesis */ |
| 125797 | + if( rc==SQLITE_OK && sParse.nNest ){ |
| 125798 | + rc = SQLITE_ERROR; |
| 125799 | + } |
| 125800 | + |
| 125801 | + return rc; |
| 125802 | +} |
| 125534 | 125803 | |
| 125535 | 125804 | /* |
| 125536 | 125805 | ** Parameters z and n contain a pointer to and length of a buffer containing |
| 125537 | 125806 | ** an fts3 query expression, respectively. This function attempts to parse the |
| 125538 | 125807 | ** query expression and create a tree of Fts3Expr structures representing the |
| | @@ -125562,53 +125831,78 @@ |
| 125562 | 125831 | char **azCol, /* Array of column names for fts3 table */ |
| 125563 | 125832 | int bFts4, /* True to allow FTS4-only syntax */ |
| 125564 | 125833 | int nCol, /* Number of entries in azCol[] */ |
| 125565 | 125834 | int iDefaultCol, /* Default column to query */ |
| 125566 | 125835 | const char *z, int n, /* Text of MATCH query */ |
| 125567 | | - Fts3Expr **ppExpr /* OUT: Parsed query structure */ |
| 125836 | + Fts3Expr **ppExpr, /* OUT: Parsed query structure */ |
| 125837 | + char **pzErr /* OUT: Error message (sqlite3_malloc) */ |
| 125568 | 125838 | ){ |
| 125569 | | - int nParsed; |
| 125570 | | - int rc; |
| 125571 | | - ParseContext sParse; |
| 125572 | | - |
| 125573 | | - memset(&sParse, 0, sizeof(ParseContext)); |
| 125574 | | - sParse.pTokenizer = pTokenizer; |
| 125575 | | - sParse.iLangid = iLangid; |
| 125576 | | - sParse.azCol = (const char **)azCol; |
| 125577 | | - sParse.nCol = nCol; |
| 125578 | | - sParse.iDefaultCol = iDefaultCol; |
| 125579 | | - sParse.bFts4 = bFts4; |
| 125580 | | - if( z==0 ){ |
| 125581 | | - *ppExpr = 0; |
| 125582 | | - return SQLITE_OK; |
| 125583 | | - } |
| 125584 | | - if( n<0 ){ |
| 125585 | | - n = (int)strlen(z); |
| 125586 | | - } |
| 125587 | | - rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed); |
| 125588 | | - |
| 125589 | | - /* Check for mismatched parenthesis */ |
| 125590 | | - if( rc==SQLITE_OK && sParse.nNest ){ |
| 125591 | | - rc = SQLITE_ERROR; |
| 125839 | + static const int MAX_EXPR_DEPTH = 12; |
| 125840 | + int rc = fts3ExprParseUnbalanced( |
| 125841 | + pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr |
| 125842 | + ); |
| 125843 | + |
| 125844 | + /* Rebalance the expression. And check that its depth does not exceed |
| 125845 | + ** MAX_EXPR_DEPTH. */ |
| 125846 | + if( rc==SQLITE_OK && *ppExpr ){ |
| 125847 | + rc = fts3ExprBalance(ppExpr, MAX_EXPR_DEPTH); |
| 125848 | + if( rc==SQLITE_OK ){ |
| 125849 | + rc = fts3ExprCheckDepth(*ppExpr, MAX_EXPR_DEPTH); |
| 125850 | + } |
| 125851 | + } |
| 125852 | + |
| 125853 | + if( rc!=SQLITE_OK ){ |
| 125592 | 125854 | sqlite3Fts3ExprFree(*ppExpr); |
| 125593 | 125855 | *ppExpr = 0; |
| 125856 | + if( rc==SQLITE_TOOBIG ){ |
| 125857 | + *pzErr = sqlite3_mprintf( |
| 125858 | + "FTS expression tree is too large (maximum depth %d)", MAX_EXPR_DEPTH |
| 125859 | + ); |
| 125860 | + rc = SQLITE_ERROR; |
| 125861 | + }else if( rc==SQLITE_ERROR ){ |
| 125862 | + *pzErr = sqlite3_mprintf("malformed MATCH expression: [%s]", z); |
| 125863 | + } |
| 125594 | 125864 | } |
| 125595 | 125865 | |
| 125596 | 125866 | return rc; |
| 125597 | 125867 | } |
| 125868 | + |
| 125869 | +/* |
| 125870 | +** Free a single node of an expression tree. |
| 125871 | +*/ |
| 125872 | +static void fts3FreeExprNode(Fts3Expr *p){ |
| 125873 | + assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 ); |
| 125874 | + sqlite3Fts3EvalPhraseCleanup(p->pPhrase); |
| 125875 | + sqlite3_free(p->aMI); |
| 125876 | + sqlite3_free(p); |
| 125877 | +} |
| 125598 | 125878 | |
| 125599 | 125879 | /* |
| 125600 | 125880 | ** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse(). |
| 125881 | +** |
| 125882 | +** This function would be simpler if it recursively called itself. But |
| 125883 | +** that would mean passing a sufficiently large expression to ExprParse() |
| 125884 | +** could cause a stack overflow. |
| 125601 | 125885 | */ |
| 125602 | | -SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){ |
| 125603 | | - if( p ){ |
| 125604 | | - assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 ); |
| 125605 | | - sqlite3Fts3ExprFree(p->pLeft); |
| 125606 | | - sqlite3Fts3ExprFree(p->pRight); |
| 125607 | | - sqlite3Fts3EvalPhraseCleanup(p->pPhrase); |
| 125608 | | - sqlite3_free(p->aMI); |
| 125609 | | - sqlite3_free(p); |
| 125886 | +SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *pDel){ |
| 125887 | + Fts3Expr *p; |
| 125888 | + assert( pDel==0 || pDel->pParent==0 ); |
| 125889 | + for(p=pDel; p && (p->pLeft||p->pRight); p=(p->pLeft ? p->pLeft : p->pRight)){ |
| 125890 | + assert( p->pParent==0 || p==p->pParent->pRight || p==p->pParent->pLeft ); |
| 125891 | + } |
| 125892 | + while( p ){ |
| 125893 | + Fts3Expr *pParent = p->pParent; |
| 125894 | + fts3FreeExprNode(p); |
| 125895 | + if( pParent && p==pParent->pLeft && pParent->pRight ){ |
| 125896 | + p = pParent->pRight; |
| 125897 | + while( p && (p->pLeft || p->pRight) ){ |
| 125898 | + assert( p==p->pParent->pRight || p==p->pParent->pLeft ); |
| 125899 | + p = (p->pLeft ? p->pLeft : p->pRight); |
| 125900 | + } |
| 125901 | + }else{ |
| 125902 | + p = pParent; |
| 125903 | + } |
| 125610 | 125904 | } |
| 125611 | 125905 | } |
| 125612 | 125906 | |
| 125613 | 125907 | /**************************************************************************** |
| 125614 | 125908 | ***************************************************************************** |
| | @@ -125656,10 +125950,13 @@ |
| 125656 | 125950 | ** |
| 125657 | 125951 | ** If the second argument is not NULL, then its contents are prepended to |
| 125658 | 125952 | ** the returned expression text and then freed using sqlite3_free(). |
| 125659 | 125953 | */ |
| 125660 | 125954 | static char *exprToString(Fts3Expr *pExpr, char *zBuf){ |
| 125955 | + if( pExpr==0 ){ |
| 125956 | + return sqlite3_mprintf(""); |
| 125957 | + } |
| 125661 | 125958 | switch( pExpr->eType ){ |
| 125662 | 125959 | case FTSQUERY_PHRASE: { |
| 125663 | 125960 | Fts3Phrase *pPhrase = pExpr->pPhrase; |
| 125664 | 125961 | int i; |
| 125665 | 125962 | zBuf = sqlite3_mprintf( |
| | @@ -125763,14 +126060,25 @@ |
| 125763 | 126060 | } |
| 125764 | 126061 | for(ii=0; ii<nCol; ii++){ |
| 125765 | 126062 | azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); |
| 125766 | 126063 | } |
| 125767 | 126064 | |
| 125768 | | - rc = sqlite3Fts3ExprParse( |
| 125769 | | - pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr |
| 125770 | | - ); |
| 126065 | + if( sqlite3_user_data(context) ){ |
| 126066 | + char *zDummy = 0; |
| 126067 | + rc = sqlite3Fts3ExprParse( |
| 126068 | + pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy |
| 126069 | + ); |
| 126070 | + assert( rc==SQLITE_OK || pExpr==0 ); |
| 126071 | + sqlite3_free(zDummy); |
| 126072 | + }else{ |
| 126073 | + rc = fts3ExprParseUnbalanced( |
| 126074 | + pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr |
| 126075 | + ); |
| 126076 | + } |
| 126077 | + |
| 125771 | 126078 | if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ |
| 126079 | + sqlite3Fts3ExprFree(pExpr); |
| 125772 | 126080 | sqlite3_result_error(context, "Error parsing expression", -1); |
| 125773 | 126081 | }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){ |
| 125774 | 126082 | sqlite3_result_error_nomem(context); |
| 125775 | 126083 | }else{ |
| 125776 | 126084 | sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); |
| | @@ -125789,13 +126097,19 @@ |
| 125789 | 126097 | /* |
| 125790 | 126098 | ** Register the query expression parser test function fts3_exprtest() |
| 125791 | 126099 | ** with database connection db. |
| 125792 | 126100 | */ |
| 125793 | 126101 | SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ |
| 125794 | | - return sqlite3_create_function( |
| 126102 | + int rc = sqlite3_create_function( |
| 125795 | 126103 | db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0 |
| 125796 | 126104 | ); |
| 126105 | + if( rc==SQLITE_OK ){ |
| 126106 | + rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", |
| 126107 | + -1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0 |
| 126108 | + ); |
| 126109 | + } |
| 126110 | + return rc; |
| 125797 | 126111 | } |
| 125798 | 126112 | |
| 125799 | 126113 | #endif |
| 125800 | 126114 | #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ |
| 125801 | 126115 | |
| 125802 | 126116 | |