| | @@ -1,8 +1,8 @@ |
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | | -** version 3.7.5. By combining all the individual C code files into this |
| 3 | +** version 3.7.6. By combining all the individual C code files into this |
| 4 | 4 | ** single large file, the entire code can be compiled as a one translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| | @@ -648,13 +648,13 @@ |
| 648 | 648 | ** |
| 649 | 649 | ** See also: [sqlite3_libversion()], |
| 650 | 650 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 651 | 651 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 652 | 652 | */ |
| 653 | | -#define SQLITE_VERSION "3.7.5" |
| 654 | | -#define SQLITE_VERSION_NUMBER 3007005 |
| 655 | | -#define SQLITE_SOURCE_ID "2011-01-25 18:30:51 c17703ec1e604934f8bd5b1f66f34b19d17a6d1f" |
| 653 | +#define SQLITE_VERSION "3.7.6" |
| 654 | +#define SQLITE_VERSION_NUMBER 3007006 |
| 655 | +#define SQLITE_SOURCE_ID "2011-02-16 23:32:24 31fc4ba66e76876b2e7b6b2b74c07f47571938ce" |
| 656 | 656 | |
| 657 | 657 | /* |
| 658 | 658 | ** CAPI3REF: Run-Time Library Version Numbers |
| 659 | 659 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 660 | 660 | ** |
| | @@ -931,11 +931,11 @@ |
| 931 | 931 | #define SQLITE_NOMEM 7 /* A malloc() failed */ |
| 932 | 932 | #define SQLITE_READONLY 8 /* Attempt to write a readonly database */ |
| 933 | 933 | #define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ |
| 934 | 934 | #define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ |
| 935 | 935 | #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ |
| 936 | | -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ |
| 936 | +#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ |
| 937 | 937 | #define SQLITE_FULL 13 /* Insertion failed because database is full */ |
| 938 | 938 | #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ |
| 939 | 939 | #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ |
| 940 | 940 | #define SQLITE_EMPTY 16 /* Database is empty */ |
| 941 | 941 | #define SQLITE_SCHEMA 17 /* The database schema changed */ |
| | @@ -1163,11 +1163,13 @@ |
| 1163 | 1163 | ** locking strategy (for example to use dot-file locks), to inquire |
| 1164 | 1164 | ** about the status of a lock, or to break stale locks. The SQLite |
| 1165 | 1165 | ** core reserves all opcodes less than 100 for its own use. |
| 1166 | 1166 | ** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. |
| 1167 | 1167 | ** Applications that define a custom xFileControl method should use opcodes |
| 1168 | | -** greater than 100 to avoid conflicts. |
| 1168 | +** greater than 100 to avoid conflicts. VFS implementations should |
| 1169 | +** return [SQLITE_NOTFOUND] for file control opcodes that they do not |
| 1170 | +** recognize. |
| 1169 | 1171 | ** |
| 1170 | 1172 | ** The xSectorSize() method returns the sector size of the |
| 1171 | 1173 | ** device that underlies the file. The sector size is the |
| 1172 | 1174 | ** minimum write that can be performed without disturbing |
| 1173 | 1175 | ** other bytes in the file. The xDeviceCharacteristics() |
| | @@ -3210,11 +3212,11 @@ |
| 3210 | 3212 | SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); |
| 3211 | 3213 | |
| 3212 | 3214 | /* |
| 3213 | 3215 | ** CAPI3REF: Determine If An SQL Statement Writes The Database |
| 3214 | 3216 | ** |
| 3215 | | -** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if |
| 3217 | +** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if |
| 3216 | 3218 | ** and only if the [prepared statement] X makes no direct changes to |
| 3217 | 3219 | ** the content of the database file. |
| 3218 | 3220 | ** |
| 3219 | 3221 | ** Note that [application-defined SQL functions] or |
| 3220 | 3222 | ** [virtual tables] might change the database indirectly as a side effect. |
| | @@ -6078,28 +6080,25 @@ |
| 6078 | 6080 | ** checked out.</dd>)^ |
| 6079 | 6081 | ** |
| 6080 | 6082 | ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt> |
| 6081 | 6083 | ** <dd>This parameter returns the number malloc attempts that were |
| 6082 | 6084 | ** satisfied using lookaside memory. Only the high-water value is meaningful; |
| 6083 | | -** the current value is always zero. |
| 6084 | | -** checked out.</dd>)^ |
| 6085 | +** the current value is always zero.)^ |
| 6085 | 6086 | ** |
| 6086 | 6087 | ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt> |
| 6087 | 6088 | ** <dd>This parameter returns the number malloc attempts that might have |
| 6088 | 6089 | ** been satisfied using lookaside memory but failed due to the amount of |
| 6089 | 6090 | ** memory requested being larger than the lookaside slot size. |
| 6090 | 6091 | ** Only the high-water value is meaningful; |
| 6091 | | -** the current value is always zero. |
| 6092 | | -** checked out.</dd>)^ |
| 6092 | +** the current value is always zero.)^ |
| 6093 | 6093 | ** |
| 6094 | 6094 | ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt> |
| 6095 | 6095 | ** <dd>This parameter returns the number malloc attempts that might have |
| 6096 | 6096 | ** been satisfied using lookaside memory but failed due to all lookaside |
| 6097 | 6097 | ** memory already being in use. |
| 6098 | 6098 | ** Only the high-water value is meaningful; |
| 6099 | | -** the current value is always zero. |
| 6100 | | -** checked out.</dd>)^ |
| 6099 | +** the current value is always zero.)^ |
| 6101 | 6100 | ** |
| 6102 | 6101 | ** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt> |
| 6103 | 6102 | ** <dd>This parameter returns the approximate number of of bytes of heap |
| 6104 | 6103 | ** memory used by all pager caches associated with the database connection.)^ |
| 6105 | 6104 | ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. |
| | @@ -6794,12 +6793,105 @@ |
| 6794 | 6793 | ** |
| 6795 | 6794 | ** ^The [wal_checkpoint pragma] can be used to invoke this interface |
| 6796 | 6795 | ** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the |
| 6797 | 6796 | ** [wal_autocheckpoint pragma] can be used to cause this interface to be |
| 6798 | 6797 | ** run whenever the WAL reaches a certain size threshold. |
| 6798 | +** |
| 6799 | +** See also: [sqlite3_wal_checkpoint_v2()] |
| 6799 | 6800 | */ |
| 6800 | 6801 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); |
| 6802 | + |
| 6803 | +/* |
| 6804 | +** CAPI3REF: Checkpoint a database |
| 6805 | +** |
| 6806 | +** Run a checkpoint operation on WAL database zDb attached to database |
| 6807 | +** handle db. The specific operation is determined by the value of the |
| 6808 | +** eMode parameter: |
| 6809 | +** |
| 6810 | +** <dl> |
| 6811 | +** <dt>SQLITE_CHECKPOINT_PASSIVE<dd> |
| 6812 | +** Checkpoint as many frames as possible without waiting for any database |
| 6813 | +** readers or writers to finish. Sync the db file if all frames in the log |
| 6814 | +** are checkpointed. This mode is the same as calling |
| 6815 | +** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked. |
| 6816 | +** |
| 6817 | +** <dt>SQLITE_CHECKPOINT_FULL<dd> |
| 6818 | +** This mode blocks (calls the busy-handler callback) until there is no |
| 6819 | +** database writer and all readers are reading from the most recent database |
| 6820 | +** snapshot. It then checkpoints all frames in the log file and syncs the |
| 6821 | +** database file. This call blocks database writers while it is running, |
| 6822 | +** but not database readers. |
| 6823 | +** |
| 6824 | +** <dt>SQLITE_CHECKPOINT_RESTART<dd> |
| 6825 | +** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after |
| 6826 | +** checkpointing the log file it blocks (calls the busy-handler callback) |
| 6827 | +** until all readers are reading from the database file only. This ensures |
| 6828 | +** that the next client to write to the database file restarts the log file |
| 6829 | +** from the beginning. This call blocks database writers while it is running, |
| 6830 | +** but not database readers. |
| 6831 | +** </dl> |
| 6832 | +** |
| 6833 | +** If pnLog is not NULL, then *pnLog is set to the total number of frames in |
| 6834 | +** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to |
| 6835 | +** the total number of checkpointed frames (including any that were already |
| 6836 | +** checkpointed when this function is called). *pnLog and *pnCkpt may be |
| 6837 | +** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. |
| 6838 | +** If no values are available because of an error, they are both set to -1 |
| 6839 | +** before returning to communicate this to the caller. |
| 6840 | +** |
| 6841 | +** All calls obtain an exclusive "checkpoint" lock on the database file. If |
| 6842 | +** any other process is running a checkpoint operation at the same time, the |
| 6843 | +** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a |
| 6844 | +** busy-handler configured, it will not be invoked in this case. |
| 6845 | +** |
| 6846 | +** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive |
| 6847 | +** "writer" lock on the database file. If the writer lock cannot be obtained |
| 6848 | +** immediately, and a busy-handler is configured, it is invoked and the writer |
| 6849 | +** lock retried until either the busy-handler returns 0 or the lock is |
| 6850 | +** successfully obtained. The busy-handler is also invoked while waiting for |
| 6851 | +** database readers as described above. If the busy-handler returns 0 before |
| 6852 | +** the writer lock is obtained or while waiting for database readers, the |
| 6853 | +** checkpoint operation proceeds from that point in the same way as |
| 6854 | +** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible |
| 6855 | +** without blocking any further. SQLITE_BUSY is returned in this case. |
| 6856 | +** |
| 6857 | +** If parameter zDb is NULL or points to a zero length string, then the |
| 6858 | +** specified operation is attempted on all WAL databases. In this case the |
| 6859 | +** values written to output parameters *pnLog and *pnCkpt are undefined. If |
| 6860 | +** an SQLITE_BUSY error is encountered when processing one or more of the |
| 6861 | +** attached WAL databases, the operation is still attempted on any remaining |
| 6862 | +** attached databases and SQLITE_BUSY is returned to the caller. If any other |
| 6863 | +** error occurs while processing an attached database, processing is abandoned |
| 6864 | +** and the error code returned to the caller immediately. If no error |
| 6865 | +** (SQLITE_BUSY or otherwise) is encountered while processing the attached |
| 6866 | +** databases, SQLITE_OK is returned. |
| 6867 | +** |
| 6868 | +** If database zDb is the name of an attached database that is not in WAL |
| 6869 | +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If |
| 6870 | +** zDb is not NULL (or a zero length string) and is not the name of any |
| 6871 | +** attached database, SQLITE_ERROR is returned to the caller. |
| 6872 | +*/ |
| 6873 | +SQLITE_API int sqlite3_wal_checkpoint_v2( |
| 6874 | + sqlite3 *db, /* Database handle */ |
| 6875 | + const char *zDb, /* Name of attached database (or NULL) */ |
| 6876 | + int eMode, /* SQLITE_CHECKPOINT_* value */ |
| 6877 | + int *pnLog, /* OUT: Size of WAL log in frames */ |
| 6878 | + int *pnCkpt /* OUT: Total number of frames checkpointed */ |
| 6879 | +); |
| 6880 | + |
| 6881 | +/* |
| 6882 | +** CAPI3REF: Checkpoint operation parameters |
| 6883 | +** |
| 6884 | +** These constants can be used as the 3rd parameter to |
| 6885 | +** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] |
| 6886 | +** documentation for additional information about the meaning and use of |
| 6887 | +** each of these values. |
| 6888 | +*/ |
| 6889 | +#define SQLITE_CHECKPOINT_PASSIVE 0 |
| 6890 | +#define SQLITE_CHECKPOINT_FULL 1 |
| 6891 | +#define SQLITE_CHECKPOINT_RESTART 2 |
| 6892 | + |
| 6801 | 6893 | |
| 6802 | 6894 | /* |
| 6803 | 6895 | ** Undo the hack that converts floating point types to integer for |
| 6804 | 6896 | ** builds on processors without floating point support. |
| 6805 | 6897 | */ |
| | @@ -7683,11 +7775,11 @@ |
| 7683 | 7775 | SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int); |
| 7684 | 7776 | SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*); |
| 7685 | 7777 | #endif |
| 7686 | 7778 | |
| 7687 | 7779 | #ifndef SQLITE_OMIT_WAL |
| 7688 | | -SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*); |
| 7780 | +SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); |
| 7689 | 7781 | #endif |
| 7690 | 7782 | |
| 7691 | 7783 | /* |
| 7692 | 7784 | ** If we are not using shared cache, then there is no need to |
| 7693 | 7785 | ** use mutexes to access the BtShared structures. So make the |
| | @@ -8293,11 +8385,11 @@ |
| 8293 | 8385 | SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); |
| 8294 | 8386 | SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); |
| 8295 | 8387 | SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); |
| 8296 | 8388 | SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); |
| 8297 | 8389 | |
| 8298 | | -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager); |
| 8390 | +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); |
| 8299 | 8391 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 8300 | 8392 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 8301 | 8393 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 8302 | 8394 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); |
| 8303 | 8395 | |
| | @@ -11250,11 +11342,11 @@ |
| 11250 | 11342 | SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); |
| 11251 | 11343 | SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); |
| 11252 | 11344 | SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); |
| 11253 | 11345 | SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*); |
| 11254 | 11346 | SQLITE_PRIVATE const char *sqlite3JournalModename(int); |
| 11255 | | -SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int); |
| 11347 | +SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); |
| 11256 | 11348 | SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); |
| 11257 | 11349 | |
| 11258 | 11350 | /* Declarations for functions in fkey.c. All of these are replaced by |
| 11259 | 11351 | ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign |
| 11260 | 11352 | ** key functionality is available. If OMIT_TRIGGER is defined but |
| | @@ -16933,11 +17025,11 @@ |
| 16933 | 17025 | ** <li> SQLITE_MUTEX_STATIC_MASTER |
| 16934 | 17026 | ** <li> SQLITE_MUTEX_STATIC_MEM |
| 16935 | 17027 | ** <li> SQLITE_MUTEX_STATIC_MEM2 |
| 16936 | 17028 | ** <li> SQLITE_MUTEX_STATIC_PRNG |
| 16937 | 17029 | ** <li> SQLITE_MUTEX_STATIC_LRU |
| 16938 | | -** <li> SQLITE_MUTEX_STATIC_LRU2 |
| 17030 | +** <li> SQLITE_MUTEX_STATIC_PMEM |
| 16939 | 17031 | ** </ul> |
| 16940 | 17032 | ** |
| 16941 | 17033 | ** The first two constants cause sqlite3_mutex_alloc() to create |
| 16942 | 17034 | ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE |
| 16943 | 17035 | ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. |
| | @@ -17343,11 +17435,11 @@ |
| 17343 | 17435 | ** <li> SQLITE_MUTEX_STATIC_MASTER |
| 17344 | 17436 | ** <li> SQLITE_MUTEX_STATIC_MEM |
| 17345 | 17437 | ** <li> SQLITE_MUTEX_STATIC_MEM2 |
| 17346 | 17438 | ** <li> SQLITE_MUTEX_STATIC_PRNG |
| 17347 | 17439 | ** <li> SQLITE_MUTEX_STATIC_LRU |
| 17348 | | -** <li> SQLITE_MUTEX_STATIC_LRU2 |
| 17440 | +** <li> SQLITE_MUTEX_STATIC_PMEM |
| 17349 | 17441 | ** </ul> |
| 17350 | 17442 | ** |
| 17351 | 17443 | ** The first two constants cause sqlite3_mutex_alloc() to create |
| 17352 | 17444 | ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE |
| 17353 | 17445 | ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. |
| | @@ -22268,11 +22360,11 @@ |
| 22268 | 22360 | OSTRACE(( "FCNTL_LOCKSTATE %d lock=%d\n", |
| 22269 | 22361 | ((os2File*)id)->h, ((os2File*)id)->locktype )); |
| 22270 | 22362 | return SQLITE_OK; |
| 22271 | 22363 | } |
| 22272 | 22364 | } |
| 22273 | | - return SQLITE_ERROR; |
| 22365 | + return SQLITE_NOTFOUND; |
| 22274 | 22366 | } |
| 22275 | 22367 | |
| 22276 | 22368 | /* |
| 22277 | 22369 | ** Return the sector size in bytes of the underlying block device for |
| 22278 | 22370 | ** the specified file. This is almost always 512 bytes, but may be |
| | @@ -26204,12 +26296,15 @@ |
| 26204 | 26296 | case SQLITE_SET_LOCKPROXYFILE: |
| 26205 | 26297 | case SQLITE_GET_LOCKPROXYFILE: { |
| 26206 | 26298 | return proxyFileControl(id,op,pArg); |
| 26207 | 26299 | } |
| 26208 | 26300 | #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ |
| 26301 | + case SQLITE_FCNTL_SYNC_OMITTED: { |
| 26302 | + return SQLITE_OK; /* A no-op */ |
| 26303 | + } |
| 26209 | 26304 | } |
| 26210 | | - return SQLITE_ERROR; |
| 26305 | + return SQLITE_NOTFOUND; |
| 26211 | 26306 | } |
| 26212 | 26307 | |
| 26213 | 26308 | /* |
| 26214 | 26309 | ** Return the sector size in bytes of the underlying block device for |
| 26215 | 26310 | ** the specified file. This is almost always 512 bytes, but may be |
| | @@ -30792,12 +30887,15 @@ |
| 30792 | 30887 | SimulateIOErrorBenign(1); |
| 30793 | 30888 | winTruncate(id, sz); |
| 30794 | 30889 | SimulateIOErrorBenign(0); |
| 30795 | 30890 | return SQLITE_OK; |
| 30796 | 30891 | } |
| 30892 | + case SQLITE_FCNTL_SYNC_OMITTED: { |
| 30893 | + return SQLITE_OK; |
| 30894 | + } |
| 30797 | 30895 | } |
| 30798 | | - return SQLITE_ERROR; |
| 30896 | + return SQLITE_NOTFOUND; |
| 30799 | 30897 | } |
| 30800 | 30898 | |
| 30801 | 30899 | /* |
| 30802 | 30900 | ** Return the sector size in bytes of the underlying block device for |
| 30803 | 30901 | ** the specified file. This is almost always 512 bytes, but may be |
| | @@ -33465,11 +33563,11 @@ |
| 33465 | 33563 | PGroup *pGroup; /* PGroup this cache belongs to */ |
| 33466 | 33564 | int szPage; /* Size of allocated pages in bytes */ |
| 33467 | 33565 | int bPurgeable; /* True if cache is purgeable */ |
| 33468 | 33566 | unsigned int nMin; /* Minimum number of pages reserved */ |
| 33469 | 33567 | unsigned int nMax; /* Configured "cache_size" value */ |
| 33470 | | - unsigned int mxPinned; /* nMax*9/10 */ |
| 33568 | + unsigned int n90pct; /* nMax*9/10 */ |
| 33471 | 33569 | |
| 33472 | 33570 | /* Hash table of all pages. The following variables may only be accessed |
| 33473 | 33571 | ** when the accessor is holding the PGroup mutex. |
| 33474 | 33572 | */ |
| 33475 | 33573 | unsigned int nRecyclable; /* Number of pages in the LRU list */ |
| | @@ -33619,11 +33717,13 @@ |
| 33619 | 33717 | ** it from sqlite3Malloc instead. |
| 33620 | 33718 | */ |
| 33621 | 33719 | p = sqlite3Malloc(nByte); |
| 33622 | 33720 | if( p ){ |
| 33623 | 33721 | int sz = sqlite3MallocSize(p); |
| 33722 | + sqlite3_mutex_enter(pcache1.mutex); |
| 33624 | 33723 | sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); |
| 33724 | + sqlite3_mutex_leave(pcache1.mutex); |
| 33625 | 33725 | } |
| 33626 | 33726 | sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); |
| 33627 | 33727 | } |
| 33628 | 33728 | return p; |
| 33629 | 33729 | } |
| | @@ -33647,11 +33747,13 @@ |
| 33647 | 33747 | }else{ |
| 33648 | 33748 | int iSize; |
| 33649 | 33749 | assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); |
| 33650 | 33750 | sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
| 33651 | 33751 | iSize = sqlite3MallocSize(p); |
| 33752 | + sqlite3_mutex_enter(pcache1.mutex); |
| 33652 | 33753 | sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize); |
| 33754 | + sqlite3_mutex_leave(pcache1.mutex); |
| 33653 | 33755 | sqlite3_free(p); |
| 33654 | 33756 | } |
| 33655 | 33757 | } |
| 33656 | 33758 | |
| 33657 | 33759 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| | @@ -33990,11 +34092,11 @@ |
| 33990 | 34092 | PGroup *pGroup = pCache->pGroup; |
| 33991 | 34093 | pcache1EnterMutex(pGroup); |
| 33992 | 34094 | pGroup->nMaxPage += (nMax - pCache->nMax); |
| 33993 | 34095 | pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; |
| 33994 | 34096 | pCache->nMax = nMax; |
| 33995 | | - pCache->mxPinned = nMax*9/10; |
| 34097 | + pCache->n90pct = pCache->nMax*9/10; |
| 33996 | 34098 | pcache1EnforceMaxPage(pGroup); |
| 33997 | 34099 | pcache1LeaveMutex(pGroup); |
| 33998 | 34100 | } |
| 33999 | 34101 | } |
| 34000 | 34102 | |
| | @@ -34100,15 +34202,16 @@ |
| 34100 | 34202 | #endif |
| 34101 | 34203 | |
| 34102 | 34204 | |
| 34103 | 34205 | /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ |
| 34104 | 34206 | nPinned = pCache->nPage - pCache->nRecyclable; |
| 34207 | + assert( nPinned>=0 ); |
| 34105 | 34208 | assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); |
| 34106 | | - assert( pCache->mxPinned == pCache->nMax*9/10 ); |
| 34209 | + assert( pCache->n90pct == pCache->nMax*9/10 ); |
| 34107 | 34210 | if( createFlag==1 && ( |
| 34108 | 34211 | nPinned>=pGroup->mxPinned |
| 34109 | | - || nPinned>=(int)pCache->mxPinned |
| 34212 | + || nPinned>=(int)pCache->n90pct |
| 34110 | 34213 | || pcache1UnderMemoryPressure(pCache) |
| 34111 | 34214 | )){ |
| 34112 | 34215 | goto fetch_out; |
| 34113 | 34216 | } |
| 34114 | 34217 | |
| | @@ -34820,26 +34923,26 @@ |
| 34820 | 34923 | #ifndef _WAL_H_ |
| 34821 | 34924 | #define _WAL_H_ |
| 34822 | 34925 | |
| 34823 | 34926 | |
| 34824 | 34927 | #ifdef SQLITE_OMIT_WAL |
| 34825 | | -# define sqlite3WalOpen(x,y,z) 0 |
| 34826 | | -# define sqlite3WalClose(w,x,y,z) 0 |
| 34827 | | -# define sqlite3WalBeginReadTransaction(y,z) 0 |
| 34928 | +# define sqlite3WalOpen(x,y,z) 0 |
| 34929 | +# define sqlite3WalClose(w,x,y,z) 0 |
| 34930 | +# define sqlite3WalBeginReadTransaction(y,z) 0 |
| 34828 | 34931 | # define sqlite3WalEndReadTransaction(z) |
| 34829 | | -# define sqlite3WalRead(v,w,x,y,z) 0 |
| 34830 | | -# define sqlite3WalDbsize(y) 0 |
| 34831 | | -# define sqlite3WalBeginWriteTransaction(y) 0 |
| 34832 | | -# define sqlite3WalEndWriteTransaction(x) 0 |
| 34833 | | -# define sqlite3WalUndo(x,y,z) 0 |
| 34932 | +# define sqlite3WalRead(v,w,x,y,z) 0 |
| 34933 | +# define sqlite3WalDbsize(y) 0 |
| 34934 | +# define sqlite3WalBeginWriteTransaction(y) 0 |
| 34935 | +# define sqlite3WalEndWriteTransaction(x) 0 |
| 34936 | +# define sqlite3WalUndo(x,y,z) 0 |
| 34834 | 34937 | # define sqlite3WalSavepoint(y,z) |
| 34835 | | -# define sqlite3WalSavepointUndo(y,z) 0 |
| 34836 | | -# define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 34837 | | -# define sqlite3WalCheckpoint(u,v,w,x) 0 |
| 34838 | | -# define sqlite3WalCallback(z) 0 |
| 34839 | | -# define sqlite3WalExclusiveMode(y,z) 0 |
| 34840 | | -# define sqlite3WalHeapMemory(z) 0 |
| 34938 | +# define sqlite3WalSavepointUndo(y,z) 0 |
| 34939 | +# define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 34940 | +# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 |
| 34941 | +# define sqlite3WalCallback(z) 0 |
| 34942 | +# define sqlite3WalExclusiveMode(y,z) 0 |
| 34943 | +# define sqlite3WalHeapMemory(z) 0 |
| 34841 | 34944 | #else |
| 34842 | 34945 | |
| 34843 | 34946 | #define WAL_SAVEPOINT_NDATA 4 |
| 34844 | 34947 | |
| 34845 | 34948 | /* Connection to a write-ahead log (WAL) file. |
| | @@ -34886,13 +34989,18 @@ |
| 34886 | 34989 | SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); |
| 34887 | 34990 | |
| 34888 | 34991 | /* Copy pages from the log to the database file */ |
| 34889 | 34992 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 34890 | 34993 | Wal *pWal, /* Write-ahead log connection */ |
| 34994 | + int eMode, /* One of PASSIVE, FULL and RESTART */ |
| 34995 | + int (*xBusy)(void*), /* Function to call when busy */ |
| 34996 | + void *pBusyArg, /* Context argument for xBusyHandler */ |
| 34891 | 34997 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 34892 | 34998 | int nBuf, /* Size of buffer nBuf */ |
| 34893 | | - u8 *zBuf /* Temporary buffer to use */ |
| 34999 | + u8 *zBuf, /* Temporary buffer to use */ |
| 35000 | + int *pnLog, /* OUT: Number of frames in WAL */ |
| 35001 | + int *pnCkpt /* OUT: Number of backfilled frames in WAL */ |
| 34894 | 35002 | ); |
| 34895 | 35003 | |
| 34896 | 35004 | /* Return the value to pass to a sqlite3_wal_hook callback, the |
| 34897 | 35005 | ** number of frames in the WAL at the point of the last commit since |
| 34898 | 35006 | ** sqlite3WalCallback() was called. If no commits have occurred since |
| | @@ -37370,19 +37478,25 @@ |
| 37370 | 37478 | |
| 37371 | 37479 | if( isOpen(pPager->fd) |
| 37372 | 37480 | && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) |
| 37373 | 37481 | ){ |
| 37374 | 37482 | i64 currentSize, newSize; |
| 37483 | + int szPage = pPager->pageSize; |
| 37375 | 37484 | assert( pPager->eLock==EXCLUSIVE_LOCK ); |
| 37376 | 37485 | /* TODO: Is it safe to use Pager.dbFileSize here? */ |
| 37377 | 37486 | rc = sqlite3OsFileSize(pPager->fd, ¤tSize); |
| 37378 | | - newSize = pPager->pageSize*(i64)nPage; |
| 37487 | + newSize = szPage*(i64)nPage; |
| 37379 | 37488 | if( rc==SQLITE_OK && currentSize!=newSize ){ |
| 37380 | 37489 | if( currentSize>newSize ){ |
| 37381 | 37490 | rc = sqlite3OsTruncate(pPager->fd, newSize); |
| 37382 | 37491 | }else{ |
| 37383 | | - rc = sqlite3OsWrite(pPager->fd, "", 1, newSize-1); |
| 37492 | + char *pTmp = pPager->pTmpSpace; |
| 37493 | + memset(pTmp, 0, szPage); |
| 37494 | + testcase( (newSize-szPage) < currentSize ); |
| 37495 | + testcase( (newSize-szPage) == currentSize ); |
| 37496 | + testcase( (newSize-szPage) > currentSize ); |
| 37497 | + rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage); |
| 37384 | 37498 | } |
| 37385 | 37499 | if( rc==SQLITE_OK ){ |
| 37386 | 37500 | pPager->dbFileSize = nPage; |
| 37387 | 37501 | } |
| 37388 | 37502 | } |
| | @@ -37737,10 +37851,32 @@ |
| 37737 | 37851 | PAGERTRACE(("FETCH %d page %d hash(%08x)\n", |
| 37738 | 37852 | PAGERID(pPager), pgno, pager_pagehash(pPg))); |
| 37739 | 37853 | |
| 37740 | 37854 | return rc; |
| 37741 | 37855 | } |
| 37856 | + |
| 37857 | +/* |
| 37858 | +** Update the value of the change-counter at offsets 24 and 92 in |
| 37859 | +** the header and the sqlite version number at offset 96. |
| 37860 | +** |
| 37861 | +** This is an unconditional update. See also the pager_incr_changecounter() |
| 37862 | +** routine which only updates the change-counter if the update is actually |
| 37863 | +** needed, as determined by the pPager->changeCountDone state variable. |
| 37864 | +*/ |
| 37865 | +static void pager_write_changecounter(PgHdr *pPg){ |
| 37866 | + u32 change_counter; |
| 37867 | + |
| 37868 | + /* Increment the value just read and write it back to byte 24. */ |
| 37869 | + change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1; |
| 37870 | + put32bits(((char*)pPg->pData)+24, change_counter); |
| 37871 | + |
| 37872 | + /* Also store the SQLite version number in bytes 96..99 and in |
| 37873 | + ** bytes 92..95 store the change counter for which the version number |
| 37874 | + ** is valid. */ |
| 37875 | + put32bits(((char*)pPg->pData)+92, change_counter); |
| 37876 | + put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER); |
| 37877 | +} |
| 37742 | 37878 | |
| 37743 | 37879 | #ifndef SQLITE_OMIT_WAL |
| 37744 | 37880 | /* |
| 37745 | 37881 | ** This function is invoked once for each page that has already been |
| 37746 | 37882 | ** written into the log file when a WAL transaction is rolled back. |
| | @@ -37808,38 +37944,15 @@ |
| 37808 | 37944 | } |
| 37809 | 37945 | |
| 37810 | 37946 | return rc; |
| 37811 | 37947 | } |
| 37812 | 37948 | |
| 37813 | | - |
| 37814 | | -/* |
| 37815 | | -** Update the value of the change-counter at offsets 24 and 92 in |
| 37816 | | -** the header and the sqlite version number at offset 96. |
| 37817 | | -** |
| 37818 | | -** This is an unconditional update. See also the pager_incr_changecounter() |
| 37819 | | -** routine which only updates the change-counter if the update is actually |
| 37820 | | -** needed, as determined by the pPager->changeCountDone state variable. |
| 37821 | | -*/ |
| 37822 | | -static void pager_write_changecounter(PgHdr *pPg){ |
| 37823 | | - u32 change_counter; |
| 37824 | | - |
| 37825 | | - /* Increment the value just read and write it back to byte 24. */ |
| 37826 | | - change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1; |
| 37827 | | - put32bits(((char*)pPg->pData)+24, change_counter); |
| 37828 | | - |
| 37829 | | - /* Also store the SQLite version number in bytes 96..99 and in |
| 37830 | | - ** bytes 92..95 store the change counter for which the version number |
| 37831 | | - ** is valid. */ |
| 37832 | | - put32bits(((char*)pPg->pData)+92, change_counter); |
| 37833 | | - put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER); |
| 37834 | | -} |
| 37835 | | - |
| 37836 | 37949 | /* |
| 37837 | 37950 | ** This function is a wrapper around sqlite3WalFrames(). As well as logging |
| 37838 | 37951 | ** the contents of the list of pages headed by pList (connected by pDirty), |
| 37839 | 37952 | ** this function notifies any active backup processes that the pages have |
| 37840 | | -** changed. |
| 37953 | +** changed. |
| 37841 | 37954 | ** |
| 37842 | 37955 | ** The list of pages passed into this routine is always sorted by page number. |
| 37843 | 37956 | ** Hence, if page 1 appears anywhere on the list, it will be the first page. |
| 37844 | 37957 | */ |
| 37845 | 37958 | static int pagerWalFrames( |
| | @@ -41487,18 +41600,24 @@ |
| 41487 | 41600 | return &pPager->pBackup; |
| 41488 | 41601 | } |
| 41489 | 41602 | |
| 41490 | 41603 | #ifndef SQLITE_OMIT_WAL |
| 41491 | 41604 | /* |
| 41492 | | -** This function is called when the user invokes "PRAGMA checkpoint". |
| 41605 | +** This function is called when the user invokes "PRAGMA wal_checkpoint", |
| 41606 | +** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() |
| 41607 | +** or wal_blocking_checkpoint() API functions. |
| 41608 | +** |
| 41609 | +** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 41493 | 41610 | */ |
| 41494 | | -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager){ |
| 41611 | +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ |
| 41495 | 41612 | int rc = SQLITE_OK; |
| 41496 | 41613 | if( pPager->pWal ){ |
| 41497 | | - u8 *zBuf = (u8 *)pPager->pTmpSpace; |
| 41498 | | - rc = sqlite3WalCheckpoint(pPager->pWal, pPager->ckptSyncFlags, |
| 41499 | | - pPager->pageSize, zBuf); |
| 41614 | + rc = sqlite3WalCheckpoint(pPager->pWal, eMode, |
| 41615 | + pPager->xBusyHandler, pPager->pBusyHandlerArg, |
| 41616 | + pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 41617 | + pnLog, pnCkpt |
| 41618 | + ); |
| 41500 | 41619 | } |
| 41501 | 41620 | return rc; |
| 41502 | 41621 | } |
| 41503 | 41622 | |
| 41504 | 41623 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ |
| | @@ -43233,10 +43352,38 @@ |
| 43233 | 43352 | walIteratorFree(p); |
| 43234 | 43353 | } |
| 43235 | 43354 | *pp = p; |
| 43236 | 43355 | return rc; |
| 43237 | 43356 | } |
| 43357 | + |
| 43358 | +/* |
| 43359 | +** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and |
| 43360 | +** n. If the attempt fails and parameter xBusy is not NULL, then it is a |
| 43361 | +** busy-handler function. Invoke it and retry the lock until either the |
| 43362 | +** lock is successfully obtained or the busy-handler returns 0. |
| 43363 | +*/ |
| 43364 | +static int walBusyLock( |
| 43365 | + Wal *pWal, /* WAL connection */ |
| 43366 | + int (*xBusy)(void*), /* Function to call when busy */ |
| 43367 | + void *pBusyArg, /* Context argument for xBusyHandler */ |
| 43368 | + int lockIdx, /* Offset of first byte to lock */ |
| 43369 | + int n /* Number of bytes to lock */ |
| 43370 | +){ |
| 43371 | + int rc; |
| 43372 | + do { |
| 43373 | + rc = walLockExclusive(pWal, lockIdx, n); |
| 43374 | + }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) ); |
| 43375 | + return rc; |
| 43376 | +} |
| 43377 | + |
| 43378 | +/* |
| 43379 | +** The cache of the wal-index header must be valid to call this function. |
| 43380 | +** Return the page-size in bytes used by the database. |
| 43381 | +*/ |
| 43382 | +static int walPagesize(Wal *pWal){ |
| 43383 | + return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); |
| 43384 | +} |
| 43238 | 43385 | |
| 43239 | 43386 | /* |
| 43240 | 43387 | ** Copy as much content as we can from the WAL back into the database file |
| 43241 | 43388 | ** in response to an sqlite3_wal_checkpoint() request or the equivalent. |
| 43242 | 43389 | ** |
| | @@ -43267,12 +43414,14 @@ |
| 43267 | 43414 | ** checkpoint is running (in any other thread or process) at the same |
| 43268 | 43415 | ** time. |
| 43269 | 43416 | */ |
| 43270 | 43417 | static int walCheckpoint( |
| 43271 | 43418 | Wal *pWal, /* Wal connection */ |
| 43419 | + int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 43420 | + int (*xBusyCall)(void*), /* Function to call when busy */ |
| 43421 | + void *pBusyArg, /* Context argument for xBusyHandler */ |
| 43272 | 43422 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 43273 | | - int nBuf, /* Size of zBuf in bytes */ |
| 43274 | 43423 | u8 *zBuf /* Temporary buffer to use */ |
| 43275 | 43424 | ){ |
| 43276 | 43425 | int rc; /* Return code */ |
| 43277 | 43426 | int szPage; /* Database page-size */ |
| 43278 | 43427 | WalIterator *pIter = 0; /* Wal iterator context */ |
| | @@ -43280,12 +43429,13 @@ |
| 43280 | 43429 | u32 iFrame = 0; /* Wal frame containing data for iDbpage */ |
| 43281 | 43430 | u32 mxSafeFrame; /* Max frame that can be backfilled */ |
| 43282 | 43431 | u32 mxPage; /* Max database page to write */ |
| 43283 | 43432 | int i; /* Loop counter */ |
| 43284 | 43433 | volatile WalCkptInfo *pInfo; /* The checkpoint status information */ |
| 43434 | + int (*xBusy)(void*) = 0; /* Function to call when waiting for locks */ |
| 43285 | 43435 | |
| 43286 | | - szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); |
| 43436 | + szPage = walPagesize(pWal); |
| 43287 | 43437 | testcase( szPage<=32768 ); |
| 43288 | 43438 | testcase( szPage>=65536 ); |
| 43289 | 43439 | pInfo = walCkptInfo(pWal); |
| 43290 | 43440 | if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK; |
| 43291 | 43441 | |
| | @@ -43294,15 +43444,12 @@ |
| 43294 | 43444 | if( rc!=SQLITE_OK ){ |
| 43295 | 43445 | return rc; |
| 43296 | 43446 | } |
| 43297 | 43447 | assert( pIter ); |
| 43298 | 43448 | |
| 43299 | | - /*** TODO: Move this test out to the caller. Make it an assert() here ***/ |
| 43300 | | - if( szPage!=nBuf ){ |
| 43301 | | - rc = SQLITE_CORRUPT_BKPT; |
| 43302 | | - goto walcheckpoint_out; |
| 43303 | | - } |
| 43449 | + mxPage = pWal->hdr.nPage; |
| 43450 | + if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall; |
| 43304 | 43451 | |
| 43305 | 43452 | /* Compute in mxSafeFrame the index of the last frame of the WAL that is |
| 43306 | 43453 | ** safe to write into the database. Frames beyond mxSafeFrame might |
| 43307 | 43454 | ** overwrite database pages that are in use by active readers and thus |
| 43308 | 43455 | ** cannot be backfilled from the WAL. |
| | @@ -43309,26 +43456,27 @@ |
| 43309 | 43456 | */ |
| 43310 | 43457 | mxSafeFrame = pWal->hdr.mxFrame; |
| 43311 | 43458 | mxPage = pWal->hdr.nPage; |
| 43312 | 43459 | for(i=1; i<WAL_NREADER; i++){ |
| 43313 | 43460 | u32 y = pInfo->aReadMark[i]; |
| 43314 | | - if( mxSafeFrame>=y ){ |
| 43461 | + if( mxSafeFrame>y ){ |
| 43315 | 43462 | assert( y<=pWal->hdr.mxFrame ); |
| 43316 | | - rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1); |
| 43463 | + rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); |
| 43317 | 43464 | if( rc==SQLITE_OK ){ |
| 43318 | 43465 | pInfo->aReadMark[i] = READMARK_NOT_USED; |
| 43319 | 43466 | walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); |
| 43320 | 43467 | }else if( rc==SQLITE_BUSY ){ |
| 43321 | 43468 | mxSafeFrame = y; |
| 43469 | + xBusy = 0; |
| 43322 | 43470 | }else{ |
| 43323 | 43471 | goto walcheckpoint_out; |
| 43324 | 43472 | } |
| 43325 | 43473 | } |
| 43326 | 43474 | } |
| 43327 | 43475 | |
| 43328 | 43476 | if( pInfo->nBackfill<mxSafeFrame |
| 43329 | | - && (rc = walLockExclusive(pWal, WAL_READ_LOCK(0), 1))==SQLITE_OK |
| 43477 | + && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0), 1))==SQLITE_OK |
| 43330 | 43478 | ){ |
| 43331 | 43479 | i64 nSize; /* Current size of database file */ |
| 43332 | 43480 | u32 nBackfill = pInfo->nBackfill; |
| 43333 | 43481 | |
| 43334 | 43482 | /* Sync the WAL to disk */ |
| | @@ -43377,16 +43525,35 @@ |
| 43377 | 43525 | } |
| 43378 | 43526 | } |
| 43379 | 43527 | |
| 43380 | 43528 | /* Release the reader lock held while backfilling */ |
| 43381 | 43529 | walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); |
| 43382 | | - }else if( rc==SQLITE_BUSY ){ |
| 43530 | + } |
| 43531 | + |
| 43532 | + if( rc==SQLITE_BUSY ){ |
| 43383 | 43533 | /* Reset the return code so as not to report a checkpoint failure |
| 43384 | | - ** just because active readers prevent any backfill. |
| 43385 | | - */ |
| 43534 | + ** just because there are active readers. */ |
| 43386 | 43535 | rc = SQLITE_OK; |
| 43387 | 43536 | } |
| 43537 | + |
| 43538 | + /* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal |
| 43539 | + ** file has been copied into the database file, then block until all |
| 43540 | + ** readers have finished using the wal file. This ensures that the next |
| 43541 | + ** process to write to the database restarts the wal file. |
| 43542 | + */ |
| 43543 | + if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 43544 | + assert( pWal->writeLock ); |
| 43545 | + if( pInfo->nBackfill<pWal->hdr.mxFrame ){ |
| 43546 | + rc = SQLITE_BUSY; |
| 43547 | + }else if( eMode==SQLITE_CHECKPOINT_RESTART ){ |
| 43548 | + assert( mxSafeFrame==pWal->hdr.mxFrame ); |
| 43549 | + rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 43550 | + if( rc==SQLITE_OK ){ |
| 43551 | + walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 43552 | + } |
| 43553 | + } |
| 43554 | + } |
| 43388 | 43555 | |
| 43389 | 43556 | walcheckpoint_out: |
| 43390 | 43557 | walIteratorFree(pIter); |
| 43391 | 43558 | return rc; |
| 43392 | 43559 | } |
| | @@ -43415,11 +43582,13 @@ |
| 43415 | 43582 | rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); |
| 43416 | 43583 | if( rc==SQLITE_OK ){ |
| 43417 | 43584 | if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ |
| 43418 | 43585 | pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; |
| 43419 | 43586 | } |
| 43420 | | - rc = sqlite3WalCheckpoint(pWal, sync_flags, nBuf, zBuf); |
| 43587 | + rc = sqlite3WalCheckpoint( |
| 43588 | + pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 |
| 43589 | + ); |
| 43421 | 43590 | if( rc==SQLITE_OK ){ |
| 43422 | 43591 | isDelete = 1; |
| 43423 | 43592 | } |
| 43424 | 43593 | } |
| 43425 | 43594 | |
| | @@ -44330,21 +44499,31 @@ |
| 44330 | 44499 | ** This routine is called to implement sqlite3_wal_checkpoint() and |
| 44331 | 44500 | ** related interfaces. |
| 44332 | 44501 | ** |
| 44333 | 44502 | ** Obtain a CHECKPOINT lock and then backfill as much information as |
| 44334 | 44503 | ** we can from WAL into the database. |
| 44504 | +** |
| 44505 | +** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 44506 | +** callback. In this case this function runs a blocking checkpoint. |
| 44335 | 44507 | */ |
| 44336 | 44508 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 44337 | 44509 | Wal *pWal, /* Wal connection */ |
| 44510 | + int eMode, /* PASSIVE, FULL or RESTART */ |
| 44511 | + int (*xBusy)(void*), /* Function to call when busy */ |
| 44512 | + void *pBusyArg, /* Context argument for xBusyHandler */ |
| 44338 | 44513 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 44339 | 44514 | int nBuf, /* Size of temporary buffer */ |
| 44340 | | - u8 *zBuf /* Temporary buffer to use */ |
| 44515 | + u8 *zBuf, /* Temporary buffer to use */ |
| 44516 | + int *pnLog, /* OUT: Number of frames in WAL */ |
| 44517 | + int *pnCkpt /* OUT: Number of backfilled frames in WAL */ |
| 44341 | 44518 | ){ |
| 44342 | 44519 | int rc; /* Return code */ |
| 44343 | 44520 | int isChanged = 0; /* True if a new wal-index header is loaded */ |
| 44521 | + int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ |
| 44344 | 44522 | |
| 44345 | 44523 | assert( pWal->ckptLock==0 ); |
| 44524 | + assert( pWal->writeLock==0 ); |
| 44346 | 44525 | |
| 44347 | 44526 | WALTRACE(("WAL%p: checkpoint begins\n", pWal)); |
| 44348 | 44527 | rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 44349 | 44528 | if( rc ){ |
| 44350 | 44529 | /* Usually this is SQLITE_BUSY meaning that another thread or process |
| | @@ -44351,16 +44530,50 @@ |
| 44351 | 44530 | ** is already running a checkpoint, or maybe a recovery. But it might |
| 44352 | 44531 | ** also be SQLITE_IOERR. */ |
| 44353 | 44532 | return rc; |
| 44354 | 44533 | } |
| 44355 | 44534 | pWal->ckptLock = 1; |
| 44535 | + |
| 44536 | + /* If this is a blocking-checkpoint, then obtain the write-lock as well |
| 44537 | + ** to prevent any writers from running while the checkpoint is underway. |
| 44538 | + ** This has to be done before the call to walIndexReadHdr() below. |
| 44539 | + ** |
| 44540 | + ** If the writer lock cannot be obtained, then a passive checkpoint is |
| 44541 | + ** run instead. Since the checkpointer is not holding the writer lock, |
| 44542 | + ** there is no point in blocking waiting for any readers. Assuming no |
| 44543 | + ** other error occurs, this function will return SQLITE_BUSY to the caller. |
| 44544 | + */ |
| 44545 | + if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 44546 | + rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); |
| 44547 | + if( rc==SQLITE_OK ){ |
| 44548 | + pWal->writeLock = 1; |
| 44549 | + }else if( rc==SQLITE_BUSY ){ |
| 44550 | + eMode2 = SQLITE_CHECKPOINT_PASSIVE; |
| 44551 | + rc = SQLITE_OK; |
| 44552 | + } |
| 44553 | + } |
| 44554 | + |
| 44555 | + /* Read the wal-index header. */ |
| 44556 | + if( rc==SQLITE_OK ){ |
| 44557 | + rc = walIndexReadHdr(pWal, &isChanged); |
| 44558 | + } |
| 44356 | 44559 | |
| 44357 | 44560 | /* Copy data from the log to the database file. */ |
| 44358 | | - rc = walIndexReadHdr(pWal, &isChanged); |
| 44359 | 44561 | if( rc==SQLITE_OK ){ |
| 44360 | | - rc = walCheckpoint(pWal, sync_flags, nBuf, zBuf); |
| 44562 | + if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 44563 | + rc = SQLITE_CORRUPT_BKPT; |
| 44564 | + }else{ |
| 44565 | + rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf); |
| 44566 | + } |
| 44567 | + |
| 44568 | + /* If no error occurred, set the output variables. */ |
| 44569 | + if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 44570 | + if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| 44571 | + if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); |
| 44572 | + } |
| 44361 | 44573 | } |
| 44574 | + |
| 44362 | 44575 | if( isChanged ){ |
| 44363 | 44576 | /* If a new wal-index header was loaded before the checkpoint was |
| 44364 | 44577 | ** performed, then the pager-cache associated with pWal is now |
| 44365 | 44578 | ** out of date. So zero the cached wal-index header to ensure that |
| 44366 | 44579 | ** next time the pager opens a snapshot on this database it knows that |
| | @@ -44368,14 +44581,15 @@ |
| 44368 | 44581 | */ |
| 44369 | 44582 | memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); |
| 44370 | 44583 | } |
| 44371 | 44584 | |
| 44372 | 44585 | /* Release the locks. */ |
| 44586 | + sqlite3WalEndWriteTransaction(pWal); |
| 44373 | 44587 | walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 44374 | 44588 | pWal->ckptLock = 0; |
| 44375 | 44589 | WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); |
| 44376 | | - return rc; |
| 44590 | + return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); |
| 44377 | 44591 | } |
| 44378 | 44592 | |
| 44379 | 44593 | /* Return the value to pass to a sqlite3_wal_hook callback, the |
| 44380 | 44594 | ** number of frames in the WAL at the point of the last commit since |
| 44381 | 44595 | ** sqlite3WalCallback() was called. If no commits have occurred since |
| | @@ -47851,11 +48065,11 @@ |
| 47851 | 48065 | freeTempSpace(pBt); |
| 47852 | 48066 | rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, |
| 47853 | 48067 | pageSize-usableSize); |
| 47854 | 48068 | return rc; |
| 47855 | 48069 | } |
| 47856 | | - if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPageHeader>nPageFile ){ |
| 48070 | + if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){ |
| 47857 | 48071 | rc = SQLITE_CORRUPT_BKPT; |
| 47858 | 48072 | goto page1_init_failed; |
| 47859 | 48073 | } |
| 47860 | 48074 | if( usableSize<480 ){ |
| 47861 | 48075 | goto page1_init_failed; |
| | @@ -53402,20 +53616,22 @@ |
| 53402 | 53616 | /* |
| 53403 | 53617 | ** Run a checkpoint on the Btree passed as the first argument. |
| 53404 | 53618 | ** |
| 53405 | 53619 | ** Return SQLITE_LOCKED if this or any other connection has an open |
| 53406 | 53620 | ** transaction on the shared-cache the argument Btree is connected to. |
| 53621 | +** |
| 53622 | +** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 53407 | 53623 | */ |
| 53408 | | -SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p){ |
| 53624 | +SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){ |
| 53409 | 53625 | int rc = SQLITE_OK; |
| 53410 | 53626 | if( p ){ |
| 53411 | 53627 | BtShared *pBt = p->pBt; |
| 53412 | 53628 | sqlite3BtreeEnter(p); |
| 53413 | 53629 | if( pBt->inTransaction!=TRANS_NONE ){ |
| 53414 | 53630 | rc = SQLITE_LOCKED; |
| 53415 | 53631 | }else{ |
| 53416 | | - rc = sqlite3PagerCheckpoint(pBt->pPager); |
| 53632 | + rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); |
| 53417 | 53633 | } |
| 53418 | 53634 | sqlite3BtreeLeave(p); |
| 53419 | 53635 | } |
| 53420 | 53636 | return rc; |
| 53421 | 53637 | } |
| | @@ -55371,10 +55587,12 @@ |
| 55371 | 55587 | pVal->u.i = -1 * pVal->u.i; |
| 55372 | 55588 | /* (double)-1 In case of SQLITE_OMIT_FLOATING_POINT... */ |
| 55373 | 55589 | pVal->r = (double)-1 * pVal->r; |
| 55374 | 55590 | sqlite3ValueApplyAffinity(pVal, affinity, enc); |
| 55375 | 55591 | } |
| 55592 | + }else if( op==TK_NULL ){ |
| 55593 | + pVal = sqlite3ValueNew(db); |
| 55376 | 55594 | } |
| 55377 | 55595 | #ifndef SQLITE_OMIT_BLOB_LITERAL |
| 55378 | 55596 | else if( op==TK_BLOB ){ |
| 55379 | 55597 | int nVal; |
| 55380 | 55598 | assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); |
| | @@ -57549,20 +57767,25 @@ |
| 57549 | 57767 | if( !sqlite3VtabInSync(db) |
| 57550 | 57768 | && db->autoCommit |
| 57551 | 57769 | && db->writeVdbeCnt==(p->readOnly==0) |
| 57552 | 57770 | ){ |
| 57553 | 57771 | if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ |
| 57554 | | - if( sqlite3VdbeCheckFk(p, 1) ){ |
| 57555 | | - sqlite3BtreeMutexArrayLeave(&p->aMutex); |
| 57556 | | - return SQLITE_ERROR; |
| 57557 | | - } |
| 57558 | | - /* The auto-commit flag is true, the vdbe program was successful |
| 57559 | | - ** or hit an 'OR FAIL' constraint and there are no deferred foreign |
| 57560 | | - ** key constraints to hold up the transaction. This means a commit |
| 57561 | | - ** is required. */ |
| 57562 | | - rc = vdbeCommit(db, p); |
| 57563 | | - if( rc==SQLITE_BUSY ){ |
| 57772 | + rc = sqlite3VdbeCheckFk(p, 1); |
| 57773 | + if( rc!=SQLITE_OK ){ |
| 57774 | + if( NEVER(p->readOnly) ){ |
| 57775 | + sqlite3BtreeMutexArrayLeave(&p->aMutex); |
| 57776 | + return SQLITE_ERROR; |
| 57777 | + } |
| 57778 | + rc = SQLITE_CONSTRAINT; |
| 57779 | + }else{ |
| 57780 | + /* The auto-commit flag is true, the vdbe program was successful |
| 57781 | + ** or hit an 'OR FAIL' constraint and there are no deferred foreign |
| 57782 | + ** key constraints to hold up the transaction. This means a commit |
| 57783 | + ** is required. */ |
| 57784 | + rc = vdbeCommit(db, p); |
| 57785 | + } |
| 57786 | + if( rc==SQLITE_BUSY && p->readOnly ){ |
| 57564 | 57787 | sqlite3BtreeMutexArrayLeave(&p->aMutex); |
| 57565 | 57788 | return SQLITE_BUSY; |
| 57566 | 57789 | }else if( rc!=SQLITE_OK ){ |
| 57567 | 57790 | p->rc = rc; |
| 57568 | 57791 | sqlite3RollbackAll(db); |
| | @@ -57657,11 +57880,11 @@ |
| 57657 | 57880 | if( db->autoCommit ){ |
| 57658 | 57881 | sqlite3ConnectionUnlocked(db); |
| 57659 | 57882 | } |
| 57660 | 57883 | |
| 57661 | 57884 | assert( db->activeVdbeCnt>0 || db->autoCommit==0 || db->nStatement==0 ); |
| 57662 | | - return SQLITE_OK; |
| 57885 | + return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK); |
| 57663 | 57886 | } |
| 57664 | 57887 | |
| 57665 | 57888 | |
| 57666 | 57889 | /* |
| 57667 | 57890 | ** Each VDBE holds the result of the most recent sqlite3_step() call |
| | @@ -61075,29 +61298,34 @@ |
| 61075 | 61298 | sqlite3_value **apVal; |
| 61076 | 61299 | } cb; |
| 61077 | 61300 | struct OP_AggFinal_stack_vars { |
| 61078 | 61301 | Mem *pMem; |
| 61079 | 61302 | } cc; |
| 61303 | + struct OP_Checkpoint_stack_vars { |
| 61304 | + int i; /* Loop counter */ |
| 61305 | + int aRes[3]; /* Results */ |
| 61306 | + Mem *pMem; /* Write results here */ |
| 61307 | + } cd; |
| 61080 | 61308 | struct OP_JournalMode_stack_vars { |
| 61081 | 61309 | Btree *pBt; /* Btree to change journal mode of */ |
| 61082 | 61310 | Pager *pPager; /* Pager associated with pBt */ |
| 61083 | 61311 | int eNew; /* New journal mode */ |
| 61084 | 61312 | int eOld; /* The old journal mode */ |
| 61085 | 61313 | const char *zFilename; /* Name of database file for pPager */ |
| 61086 | | - } cd; |
| 61314 | + } ce; |
| 61087 | 61315 | struct OP_IncrVacuum_stack_vars { |
| 61088 | 61316 | Btree *pBt; |
| 61089 | | - } ce; |
| 61317 | + } cf; |
| 61090 | 61318 | struct OP_VBegin_stack_vars { |
| 61091 | 61319 | VTable *pVTab; |
| 61092 | | - } cf; |
| 61320 | + } cg; |
| 61093 | 61321 | struct OP_VOpen_stack_vars { |
| 61094 | 61322 | VdbeCursor *pCur; |
| 61095 | 61323 | sqlite3_vtab_cursor *pVtabCursor; |
| 61096 | 61324 | sqlite3_vtab *pVtab; |
| 61097 | 61325 | sqlite3_module *pModule; |
| 61098 | | - } cg; |
| 61326 | + } ch; |
| 61099 | 61327 | struct OP_VFilter_stack_vars { |
| 61100 | 61328 | int nArg; |
| 61101 | 61329 | int iQuery; |
| 61102 | 61330 | const sqlite3_module *pModule; |
| 61103 | 61331 | Mem *pQuery; |
| | @@ -61106,39 +61334,39 @@ |
| 61106 | 61334 | sqlite3_vtab *pVtab; |
| 61107 | 61335 | VdbeCursor *pCur; |
| 61108 | 61336 | int res; |
| 61109 | 61337 | int i; |
| 61110 | 61338 | Mem **apArg; |
| 61111 | | - } ch; |
| 61339 | + } ci; |
| 61112 | 61340 | struct OP_VColumn_stack_vars { |
| 61113 | 61341 | sqlite3_vtab *pVtab; |
| 61114 | 61342 | const sqlite3_module *pModule; |
| 61115 | 61343 | Mem *pDest; |
| 61116 | 61344 | sqlite3_context sContext; |
| 61117 | | - } ci; |
| 61345 | + } cj; |
| 61118 | 61346 | struct OP_VNext_stack_vars { |
| 61119 | 61347 | sqlite3_vtab *pVtab; |
| 61120 | 61348 | const sqlite3_module *pModule; |
| 61121 | 61349 | int res; |
| 61122 | 61350 | VdbeCursor *pCur; |
| 61123 | | - } cj; |
| 61351 | + } ck; |
| 61124 | 61352 | struct OP_VRename_stack_vars { |
| 61125 | 61353 | sqlite3_vtab *pVtab; |
| 61126 | 61354 | Mem *pName; |
| 61127 | | - } ck; |
| 61355 | + } cl; |
| 61128 | 61356 | struct OP_VUpdate_stack_vars { |
| 61129 | 61357 | sqlite3_vtab *pVtab; |
| 61130 | 61358 | sqlite3_module *pModule; |
| 61131 | 61359 | int nArg; |
| 61132 | 61360 | int i; |
| 61133 | 61361 | sqlite_int64 rowid; |
| 61134 | 61362 | Mem **apArg; |
| 61135 | 61363 | Mem *pX; |
| 61136 | | - } cl; |
| 61364 | + } cm; |
| 61137 | 61365 | struct OP_Trace_stack_vars { |
| 61138 | 61366 | char *zTrace; |
| 61139 | | - } cm; |
| 61367 | + } cn; |
| 61140 | 61368 | } u; |
| 61141 | 61369 | /* End automatically generated code |
| 61142 | 61370 | ********************************************************************/ |
| 61143 | 61371 | |
| 61144 | 61372 | assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ |
| | @@ -65894,17 +66122,42 @@ |
| 65894 | 66122 | } |
| 65895 | 66123 | break; |
| 65896 | 66124 | } |
| 65897 | 66125 | |
| 65898 | 66126 | #ifndef SQLITE_OMIT_WAL |
| 65899 | | -/* Opcode: Checkpoint P1 * * * * |
| 66127 | +/* Opcode: Checkpoint P1 P2 P3 * * |
| 65900 | 66128 | ** |
| 65901 | 66129 | ** Checkpoint database P1. This is a no-op if P1 is not currently in |
| 65902 | | -** WAL mode. |
| 66130 | +** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL |
| 66131 | +** or RESTART. Write 1 or 0 into mem[P3] if the checkpoint returns |
| 66132 | +** SQLITE_BUSY or not, respectively. Write the number of pages in the |
| 66133 | +** WAL after the checkpoint into mem[P3+1] and the number of pages |
| 66134 | +** in the WAL that have been checkpointed after the checkpoint |
| 66135 | +** completes into mem[P3+2]. However on an error, mem[P3+1] and |
| 66136 | +** mem[P3+2] are initialized to -1. |
| 65903 | 66137 | */ |
| 65904 | 66138 | case OP_Checkpoint: { |
| 65905 | | - rc = sqlite3Checkpoint(db, pOp->p1); |
| 66139 | +#if 0 /* local variables moved into u.cd */ |
| 66140 | + int i; /* Loop counter */ |
| 66141 | + int aRes[3]; /* Results */ |
| 66142 | + Mem *pMem; /* Write results here */ |
| 66143 | +#endif /* local variables moved into u.cd */ |
| 66144 | + |
| 66145 | + u.cd.aRes[0] = 0; |
| 66146 | + u.cd.aRes[1] = u.cd.aRes[2] = -1; |
| 66147 | + assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE |
| 66148 | + || pOp->p2==SQLITE_CHECKPOINT_FULL |
| 66149 | + || pOp->p2==SQLITE_CHECKPOINT_RESTART |
| 66150 | + ); |
| 66151 | + rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.cd.aRes[1], &u.cd.aRes[2]); |
| 66152 | + if( rc==SQLITE_BUSY ){ |
| 66153 | + rc = SQLITE_OK; |
| 66154 | + u.cd.aRes[0] = 1; |
| 66155 | + } |
| 66156 | + for(u.cd.i=0, u.cd.pMem = &aMem[pOp->p3]; u.cd.i<3; u.cd.i++, u.cd.pMem++){ |
| 66157 | + sqlite3VdbeMemSetInt64(u.cd.pMem, (i64)u.cd.aRes[u.cd.i]); |
| 66158 | + } |
| 65906 | 66159 | break; |
| 65907 | 66160 | }; |
| 65908 | 66161 | #endif |
| 65909 | 66162 | |
| 65910 | 66163 | #ifndef SQLITE_OMIT_PRAGMA |
| | @@ -65918,26 +66171,26 @@ |
| 65918 | 66171 | ** If changing into or out of WAL mode the procedure is more complicated. |
| 65919 | 66172 | ** |
| 65920 | 66173 | ** Write a string containing the final journal-mode to register P2. |
| 65921 | 66174 | */ |
| 65922 | 66175 | case OP_JournalMode: { /* out2-prerelease */ |
| 65923 | | -#if 0 /* local variables moved into u.cd */ |
| 66176 | +#if 0 /* local variables moved into u.ce */ |
| 65924 | 66177 | Btree *pBt; /* Btree to change journal mode of */ |
| 65925 | 66178 | Pager *pPager; /* Pager associated with pBt */ |
| 65926 | 66179 | int eNew; /* New journal mode */ |
| 65927 | 66180 | int eOld; /* The old journal mode */ |
| 65928 | 66181 | const char *zFilename; /* Name of database file for pPager */ |
| 65929 | | -#endif /* local variables moved into u.cd */ |
| 65930 | | - |
| 65931 | | - u.cd.eNew = pOp->p3; |
| 65932 | | - assert( u.cd.eNew==PAGER_JOURNALMODE_DELETE |
| 65933 | | - || u.cd.eNew==PAGER_JOURNALMODE_TRUNCATE |
| 65934 | | - || u.cd.eNew==PAGER_JOURNALMODE_PERSIST |
| 65935 | | - || u.cd.eNew==PAGER_JOURNALMODE_OFF |
| 65936 | | - || u.cd.eNew==PAGER_JOURNALMODE_MEMORY |
| 65937 | | - || u.cd.eNew==PAGER_JOURNALMODE_WAL |
| 65938 | | - || u.cd.eNew==PAGER_JOURNALMODE_QUERY |
| 66182 | +#endif /* local variables moved into u.ce */ |
| 66183 | + |
| 66184 | + u.ce.eNew = pOp->p3; |
| 66185 | + assert( u.ce.eNew==PAGER_JOURNALMODE_DELETE |
| 66186 | + || u.ce.eNew==PAGER_JOURNALMODE_TRUNCATE |
| 66187 | + || u.ce.eNew==PAGER_JOURNALMODE_PERSIST |
| 66188 | + || u.ce.eNew==PAGER_JOURNALMODE_OFF |
| 66189 | + || u.ce.eNew==PAGER_JOURNALMODE_MEMORY |
| 66190 | + || u.ce.eNew==PAGER_JOURNALMODE_WAL |
| 66191 | + || u.ce.eNew==PAGER_JOURNALMODE_QUERY |
| 65939 | 66192 | ); |
| 65940 | 66193 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 65941 | 66194 | |
| 65942 | 66195 | /* This opcode is used in two places: PRAGMA journal_mode and ATTACH. |
| 65943 | 66196 | ** In PRAGMA journal_mode, the sqlite3VdbeUsesBtree() routine is called |
| | @@ -65956,76 +66209,76 @@ |
| 65956 | 66209 | ** database. */ |
| 65957 | 66210 | sqlite3VdbeUsesBtree(p, pOp->p1); |
| 65958 | 66211 | sqlite3VdbeMutexArrayEnter(p); |
| 65959 | 66212 | } |
| 65960 | 66213 | |
| 65961 | | - u.cd.pBt = db->aDb[pOp->p1].pBt; |
| 65962 | | - u.cd.pPager = sqlite3BtreePager(u.cd.pBt); |
| 65963 | | - u.cd.eOld = sqlite3PagerGetJournalMode(u.cd.pPager); |
| 65964 | | - if( u.cd.eNew==PAGER_JOURNALMODE_QUERY ) u.cd.eNew = u.cd.eOld; |
| 65965 | | - if( !sqlite3PagerOkToChangeJournalMode(u.cd.pPager) ) u.cd.eNew = u.cd.eOld; |
| 66214 | + u.ce.pBt = db->aDb[pOp->p1].pBt; |
| 66215 | + u.ce.pPager = sqlite3BtreePager(u.ce.pBt); |
| 66216 | + u.ce.eOld = sqlite3PagerGetJournalMode(u.ce.pPager); |
| 66217 | + if( u.ce.eNew==PAGER_JOURNALMODE_QUERY ) u.ce.eNew = u.ce.eOld; |
| 66218 | + if( !sqlite3PagerOkToChangeJournalMode(u.ce.pPager) ) u.ce.eNew = u.ce.eOld; |
| 65966 | 66219 | |
| 65967 | 66220 | #ifndef SQLITE_OMIT_WAL |
| 65968 | | - u.cd.zFilename = sqlite3PagerFilename(u.cd.pPager); |
| 66221 | + u.ce.zFilename = sqlite3PagerFilename(u.ce.pPager); |
| 65969 | 66222 | |
| 65970 | 66223 | /* Do not allow a transition to journal_mode=WAL for a database |
| 65971 | 66224 | ** in temporary storage or if the VFS does not support shared memory |
| 65972 | 66225 | */ |
| 65973 | | - if( u.cd.eNew==PAGER_JOURNALMODE_WAL |
| 65974 | | - && (u.cd.zFilename[0]==0 /* Temp file */ |
| 65975 | | - || !sqlite3PagerWalSupported(u.cd.pPager)) /* No shared-memory support */ |
| 66226 | + if( u.ce.eNew==PAGER_JOURNALMODE_WAL |
| 66227 | + && (u.ce.zFilename[0]==0 /* Temp file */ |
| 66228 | + || !sqlite3PagerWalSupported(u.ce.pPager)) /* No shared-memory support */ |
| 65976 | 66229 | ){ |
| 65977 | | - u.cd.eNew = u.cd.eOld; |
| 66230 | + u.ce.eNew = u.ce.eOld; |
| 65978 | 66231 | } |
| 65979 | 66232 | |
| 65980 | | - if( (u.cd.eNew!=u.cd.eOld) |
| 65981 | | - && (u.cd.eOld==PAGER_JOURNALMODE_WAL || u.cd.eNew==PAGER_JOURNALMODE_WAL) |
| 66233 | + if( (u.ce.eNew!=u.ce.eOld) |
| 66234 | + && (u.ce.eOld==PAGER_JOURNALMODE_WAL || u.ce.eNew==PAGER_JOURNALMODE_WAL) |
| 65982 | 66235 | ){ |
| 65983 | 66236 | if( !db->autoCommit || db->activeVdbeCnt>1 ){ |
| 65984 | 66237 | rc = SQLITE_ERROR; |
| 65985 | 66238 | sqlite3SetString(&p->zErrMsg, db, |
| 65986 | 66239 | "cannot change %s wal mode from within a transaction", |
| 65987 | | - (u.cd.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") |
| 66240 | + (u.ce.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") |
| 65988 | 66241 | ); |
| 65989 | 66242 | break; |
| 65990 | 66243 | }else{ |
| 65991 | 66244 | |
| 65992 | | - if( u.cd.eOld==PAGER_JOURNALMODE_WAL ){ |
| 66245 | + if( u.ce.eOld==PAGER_JOURNALMODE_WAL ){ |
| 65993 | 66246 | /* If leaving WAL mode, close the log file. If successful, the call |
| 65994 | 66247 | ** to PagerCloseWal() checkpoints and deletes the write-ahead-log |
| 65995 | 66248 | ** file. An EXCLUSIVE lock may still be held on the database file |
| 65996 | 66249 | ** after a successful return. |
| 65997 | 66250 | */ |
| 65998 | | - rc = sqlite3PagerCloseWal(u.cd.pPager); |
| 66251 | + rc = sqlite3PagerCloseWal(u.ce.pPager); |
| 65999 | 66252 | if( rc==SQLITE_OK ){ |
| 66000 | | - sqlite3PagerSetJournalMode(u.cd.pPager, u.cd.eNew); |
| 66253 | + sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew); |
| 66001 | 66254 | } |
| 66002 | | - }else if( u.cd.eOld==PAGER_JOURNALMODE_MEMORY ){ |
| 66255 | + }else if( u.ce.eOld==PAGER_JOURNALMODE_MEMORY ){ |
| 66003 | 66256 | /* Cannot transition directly from MEMORY to WAL. Use mode OFF |
| 66004 | 66257 | ** as an intermediate */ |
| 66005 | | - sqlite3PagerSetJournalMode(u.cd.pPager, PAGER_JOURNALMODE_OFF); |
| 66258 | + sqlite3PagerSetJournalMode(u.ce.pPager, PAGER_JOURNALMODE_OFF); |
| 66006 | 66259 | } |
| 66007 | 66260 | |
| 66008 | 66261 | /* Open a transaction on the database file. Regardless of the journal |
| 66009 | 66262 | ** mode, this transaction always uses a rollback journal. |
| 66010 | 66263 | */ |
| 66011 | | - assert( sqlite3BtreeIsInTrans(u.cd.pBt)==0 ); |
| 66264 | + assert( sqlite3BtreeIsInTrans(u.ce.pBt)==0 ); |
| 66012 | 66265 | if( rc==SQLITE_OK ){ |
| 66013 | | - rc = sqlite3BtreeSetVersion(u.cd.pBt, (u.cd.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1)); |
| 66266 | + rc = sqlite3BtreeSetVersion(u.ce.pBt, (u.ce.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1)); |
| 66014 | 66267 | } |
| 66015 | 66268 | } |
| 66016 | 66269 | } |
| 66017 | 66270 | #endif /* ifndef SQLITE_OMIT_WAL */ |
| 66018 | 66271 | |
| 66019 | 66272 | if( rc ){ |
| 66020 | | - u.cd.eNew = u.cd.eOld; |
| 66273 | + u.ce.eNew = u.ce.eOld; |
| 66021 | 66274 | } |
| 66022 | | - u.cd.eNew = sqlite3PagerSetJournalMode(u.cd.pPager, u.cd.eNew); |
| 66275 | + u.ce.eNew = sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew); |
| 66023 | 66276 | |
| 66024 | 66277 | pOut = &aMem[pOp->p2]; |
| 66025 | 66278 | pOut->flags = MEM_Str|MEM_Static|MEM_Term; |
| 66026 | | - pOut->z = (char *)sqlite3JournalModename(u.cd.eNew); |
| 66279 | + pOut->z = (char *)sqlite3JournalModename(u.ce.eNew); |
| 66027 | 66280 | pOut->n = sqlite3Strlen30(pOut->z); |
| 66028 | 66281 | pOut->enc = SQLITE_UTF8; |
| 66029 | 66282 | sqlite3VdbeChangeEncoding(pOut, encoding); |
| 66030 | 66283 | break; |
| 66031 | 66284 | }; |
| | @@ -66050,18 +66303,18 @@ |
| 66050 | 66303 | ** Perform a single step of the incremental vacuum procedure on |
| 66051 | 66304 | ** the P1 database. If the vacuum has finished, jump to instruction |
| 66052 | 66305 | ** P2. Otherwise, fall through to the next instruction. |
| 66053 | 66306 | */ |
| 66054 | 66307 | case OP_IncrVacuum: { /* jump */ |
| 66055 | | -#if 0 /* local variables moved into u.ce */ |
| 66308 | +#if 0 /* local variables moved into u.cf */ |
| 66056 | 66309 | Btree *pBt; |
| 66057 | | -#endif /* local variables moved into u.ce */ |
| 66310 | +#endif /* local variables moved into u.cf */ |
| 66058 | 66311 | |
| 66059 | 66312 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 66060 | 66313 | assert( (p->btreeMask & (1<<pOp->p1))!=0 ); |
| 66061 | | - u.ce.pBt = db->aDb[pOp->p1].pBt; |
| 66062 | | - rc = sqlite3BtreeIncrVacuum(u.ce.pBt); |
| 66314 | + u.cf.pBt = db->aDb[pOp->p1].pBt; |
| 66315 | + rc = sqlite3BtreeIncrVacuum(u.cf.pBt); |
| 66063 | 66316 | if( rc==SQLITE_DONE ){ |
| 66064 | 66317 | pc = pOp->p2 - 1; |
| 66065 | 66318 | rc = SQLITE_OK; |
| 66066 | 66319 | } |
| 66067 | 66320 | break; |
| | @@ -66127,16 +66380,16 @@ |
| 66127 | 66380 | ** Also, whether or not P4 is set, check that this is not being called from |
| 66128 | 66381 | ** within a callback to a virtual table xSync() method. If it is, the error |
| 66129 | 66382 | ** code will be set to SQLITE_LOCKED. |
| 66130 | 66383 | */ |
| 66131 | 66384 | case OP_VBegin: { |
| 66132 | | -#if 0 /* local variables moved into u.cf */ |
| 66385 | +#if 0 /* local variables moved into u.cg */ |
| 66133 | 66386 | VTable *pVTab; |
| 66134 | | -#endif /* local variables moved into u.cf */ |
| 66135 | | - u.cf.pVTab = pOp->p4.pVtab; |
| 66136 | | - rc = sqlite3VtabBegin(db, u.cf.pVTab); |
| 66137 | | - if( u.cf.pVTab ) importVtabErrMsg(p, u.cf.pVTab->pVtab); |
| 66387 | +#endif /* local variables moved into u.cg */ |
| 66388 | + u.cg.pVTab = pOp->p4.pVtab; |
| 66389 | + rc = sqlite3VtabBegin(db, u.cg.pVTab); |
| 66390 | + if( u.cg.pVTab ) importVtabErrMsg(p, u.cg.pVTab->pVtab); |
| 66138 | 66391 | break; |
| 66139 | 66392 | } |
| 66140 | 66393 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 66141 | 66394 | |
| 66142 | 66395 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| | @@ -66171,36 +66424,36 @@ |
| 66171 | 66424 | ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. |
| 66172 | 66425 | ** P1 is a cursor number. This opcode opens a cursor to the virtual |
| 66173 | 66426 | ** table and stores that cursor in P1. |
| 66174 | 66427 | */ |
| 66175 | 66428 | case OP_VOpen: { |
| 66176 | | -#if 0 /* local variables moved into u.cg */ |
| 66429 | +#if 0 /* local variables moved into u.ch */ |
| 66177 | 66430 | VdbeCursor *pCur; |
| 66178 | 66431 | sqlite3_vtab_cursor *pVtabCursor; |
| 66179 | 66432 | sqlite3_vtab *pVtab; |
| 66180 | 66433 | sqlite3_module *pModule; |
| 66181 | | -#endif /* local variables moved into u.cg */ |
| 66182 | | - |
| 66183 | | - u.cg.pCur = 0; |
| 66184 | | - u.cg.pVtabCursor = 0; |
| 66185 | | - u.cg.pVtab = pOp->p4.pVtab->pVtab; |
| 66186 | | - u.cg.pModule = (sqlite3_module *)u.cg.pVtab->pModule; |
| 66187 | | - assert(u.cg.pVtab && u.cg.pModule); |
| 66188 | | - rc = u.cg.pModule->xOpen(u.cg.pVtab, &u.cg.pVtabCursor); |
| 66189 | | - importVtabErrMsg(p, u.cg.pVtab); |
| 66434 | +#endif /* local variables moved into u.ch */ |
| 66435 | + |
| 66436 | + u.ch.pCur = 0; |
| 66437 | + u.ch.pVtabCursor = 0; |
| 66438 | + u.ch.pVtab = pOp->p4.pVtab->pVtab; |
| 66439 | + u.ch.pModule = (sqlite3_module *)u.ch.pVtab->pModule; |
| 66440 | + assert(u.ch.pVtab && u.ch.pModule); |
| 66441 | + rc = u.ch.pModule->xOpen(u.ch.pVtab, &u.ch.pVtabCursor); |
| 66442 | + importVtabErrMsg(p, u.ch.pVtab); |
| 66190 | 66443 | if( SQLITE_OK==rc ){ |
| 66191 | 66444 | /* Initialize sqlite3_vtab_cursor base class */ |
| 66192 | | - u.cg.pVtabCursor->pVtab = u.cg.pVtab; |
| 66445 | + u.ch.pVtabCursor->pVtab = u.ch.pVtab; |
| 66193 | 66446 | |
| 66194 | 66447 | /* Initialise vdbe cursor object */ |
| 66195 | | - u.cg.pCur = allocateCursor(p, pOp->p1, 0, -1, 0); |
| 66196 | | - if( u.cg.pCur ){ |
| 66197 | | - u.cg.pCur->pVtabCursor = u.cg.pVtabCursor; |
| 66198 | | - u.cg.pCur->pModule = u.cg.pVtabCursor->pVtab->pModule; |
| 66448 | + u.ch.pCur = allocateCursor(p, pOp->p1, 0, -1, 0); |
| 66449 | + if( u.ch.pCur ){ |
| 66450 | + u.ch.pCur->pVtabCursor = u.ch.pVtabCursor; |
| 66451 | + u.ch.pCur->pModule = u.ch.pVtabCursor->pVtab->pModule; |
| 66199 | 66452 | }else{ |
| 66200 | 66453 | db->mallocFailed = 1; |
| 66201 | | - u.cg.pModule->xClose(u.cg.pVtabCursor); |
| 66454 | + u.ch.pModule->xClose(u.ch.pVtabCursor); |
| 66202 | 66455 | } |
| 66203 | 66456 | } |
| 66204 | 66457 | break; |
| 66205 | 66458 | } |
| 66206 | 66459 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| | @@ -66223,11 +66476,11 @@ |
| 66223 | 66476 | ** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. |
| 66224 | 66477 | ** |
| 66225 | 66478 | ** A jump is made to P2 if the result set after filtering would be empty. |
| 66226 | 66479 | */ |
| 66227 | 66480 | case OP_VFilter: { /* jump */ |
| 66228 | | -#if 0 /* local variables moved into u.ch */ |
| 66481 | +#if 0 /* local variables moved into u.ci */ |
| 66229 | 66482 | int nArg; |
| 66230 | 66483 | int iQuery; |
| 66231 | 66484 | const sqlite3_module *pModule; |
| 66232 | 66485 | Mem *pQuery; |
| 66233 | 66486 | Mem *pArgc; |
| | @@ -66235,49 +66488,49 @@ |
| 66235 | 66488 | sqlite3_vtab *pVtab; |
| 66236 | 66489 | VdbeCursor *pCur; |
| 66237 | 66490 | int res; |
| 66238 | 66491 | int i; |
| 66239 | 66492 | Mem **apArg; |
| 66240 | | -#endif /* local variables moved into u.ch */ |
| 66241 | | - |
| 66242 | | - u.ch.pQuery = &aMem[pOp->p3]; |
| 66243 | | - u.ch.pArgc = &u.ch.pQuery[1]; |
| 66244 | | - u.ch.pCur = p->apCsr[pOp->p1]; |
| 66245 | | - assert( memIsValid(u.ch.pQuery) ); |
| 66246 | | - REGISTER_TRACE(pOp->p3, u.ch.pQuery); |
| 66247 | | - assert( u.ch.pCur->pVtabCursor ); |
| 66248 | | - u.ch.pVtabCursor = u.ch.pCur->pVtabCursor; |
| 66249 | | - u.ch.pVtab = u.ch.pVtabCursor->pVtab; |
| 66250 | | - u.ch.pModule = u.ch.pVtab->pModule; |
| 66493 | +#endif /* local variables moved into u.ci */ |
| 66494 | + |
| 66495 | + u.ci.pQuery = &aMem[pOp->p3]; |
| 66496 | + u.ci.pArgc = &u.ci.pQuery[1]; |
| 66497 | + u.ci.pCur = p->apCsr[pOp->p1]; |
| 66498 | + assert( memIsValid(u.ci.pQuery) ); |
| 66499 | + REGISTER_TRACE(pOp->p3, u.ci.pQuery); |
| 66500 | + assert( u.ci.pCur->pVtabCursor ); |
| 66501 | + u.ci.pVtabCursor = u.ci.pCur->pVtabCursor; |
| 66502 | + u.ci.pVtab = u.ci.pVtabCursor->pVtab; |
| 66503 | + u.ci.pModule = u.ci.pVtab->pModule; |
| 66251 | 66504 | |
| 66252 | 66505 | /* Grab the index number and argc parameters */ |
| 66253 | | - assert( (u.ch.pQuery->flags&MEM_Int)!=0 && u.ch.pArgc->flags==MEM_Int ); |
| 66254 | | - u.ch.nArg = (int)u.ch.pArgc->u.i; |
| 66255 | | - u.ch.iQuery = (int)u.ch.pQuery->u.i; |
| 66506 | + assert( (u.ci.pQuery->flags&MEM_Int)!=0 && u.ci.pArgc->flags==MEM_Int ); |
| 66507 | + u.ci.nArg = (int)u.ci.pArgc->u.i; |
| 66508 | + u.ci.iQuery = (int)u.ci.pQuery->u.i; |
| 66256 | 66509 | |
| 66257 | 66510 | /* Invoke the xFilter method */ |
| 66258 | 66511 | { |
| 66259 | | - u.ch.res = 0; |
| 66260 | | - u.ch.apArg = p->apArg; |
| 66261 | | - for(u.ch.i = 0; u.ch.i<u.ch.nArg; u.ch.i++){ |
| 66262 | | - u.ch.apArg[u.ch.i] = &u.ch.pArgc[u.ch.i+1]; |
| 66263 | | - sqlite3VdbeMemStoreType(u.ch.apArg[u.ch.i]); |
| 66512 | + u.ci.res = 0; |
| 66513 | + u.ci.apArg = p->apArg; |
| 66514 | + for(u.ci.i = 0; u.ci.i<u.ci.nArg; u.ci.i++){ |
| 66515 | + u.ci.apArg[u.ci.i] = &u.ci.pArgc[u.ci.i+1]; |
| 66516 | + sqlite3VdbeMemStoreType(u.ci.apArg[u.ci.i]); |
| 66264 | 66517 | } |
| 66265 | 66518 | |
| 66266 | 66519 | p->inVtabMethod = 1; |
| 66267 | | - rc = u.ch.pModule->xFilter(u.ch.pVtabCursor, u.ch.iQuery, pOp->p4.z, u.ch.nArg, u.ch.apArg); |
| 66520 | + rc = u.ci.pModule->xFilter(u.ci.pVtabCursor, u.ci.iQuery, pOp->p4.z, u.ci.nArg, u.ci.apArg); |
| 66268 | 66521 | p->inVtabMethod = 0; |
| 66269 | | - importVtabErrMsg(p, u.ch.pVtab); |
| 66522 | + importVtabErrMsg(p, u.ci.pVtab); |
| 66270 | 66523 | if( rc==SQLITE_OK ){ |
| 66271 | | - u.ch.res = u.ch.pModule->xEof(u.ch.pVtabCursor); |
| 66524 | + u.ci.res = u.ci.pModule->xEof(u.ci.pVtabCursor); |
| 66272 | 66525 | } |
| 66273 | 66526 | |
| 66274 | | - if( u.ch.res ){ |
| 66527 | + if( u.ci.res ){ |
| 66275 | 66528 | pc = pOp->p2 - 1; |
| 66276 | 66529 | } |
| 66277 | 66530 | } |
| 66278 | | - u.ch.pCur->nullRow = 0; |
| 66531 | + u.ci.pCur->nullRow = 0; |
| 66279 | 66532 | |
| 66280 | 66533 | break; |
| 66281 | 66534 | } |
| 66282 | 66535 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 66283 | 66536 | |
| | @@ -66287,55 +66540,55 @@ |
| 66287 | 66540 | ** Store the value of the P2-th column of |
| 66288 | 66541 | ** the row of the virtual-table that the |
| 66289 | 66542 | ** P1 cursor is pointing to into register P3. |
| 66290 | 66543 | */ |
| 66291 | 66544 | case OP_VColumn: { |
| 66292 | | -#if 0 /* local variables moved into u.ci */ |
| 66545 | +#if 0 /* local variables moved into u.cj */ |
| 66293 | 66546 | sqlite3_vtab *pVtab; |
| 66294 | 66547 | const sqlite3_module *pModule; |
| 66295 | 66548 | Mem *pDest; |
| 66296 | 66549 | sqlite3_context sContext; |
| 66297 | | -#endif /* local variables moved into u.ci */ |
| 66550 | +#endif /* local variables moved into u.cj */ |
| 66298 | 66551 | |
| 66299 | 66552 | VdbeCursor *pCur = p->apCsr[pOp->p1]; |
| 66300 | 66553 | assert( pCur->pVtabCursor ); |
| 66301 | 66554 | assert( pOp->p3>0 && pOp->p3<=p->nMem ); |
| 66302 | | - u.ci.pDest = &aMem[pOp->p3]; |
| 66303 | | - memAboutToChange(p, u.ci.pDest); |
| 66555 | + u.cj.pDest = &aMem[pOp->p3]; |
| 66556 | + memAboutToChange(p, u.cj.pDest); |
| 66304 | 66557 | if( pCur->nullRow ){ |
| 66305 | | - sqlite3VdbeMemSetNull(u.ci.pDest); |
| 66558 | + sqlite3VdbeMemSetNull(u.cj.pDest); |
| 66306 | 66559 | break; |
| 66307 | 66560 | } |
| 66308 | | - u.ci.pVtab = pCur->pVtabCursor->pVtab; |
| 66309 | | - u.ci.pModule = u.ci.pVtab->pModule; |
| 66310 | | - assert( u.ci.pModule->xColumn ); |
| 66311 | | - memset(&u.ci.sContext, 0, sizeof(u.ci.sContext)); |
| 66561 | + u.cj.pVtab = pCur->pVtabCursor->pVtab; |
| 66562 | + u.cj.pModule = u.cj.pVtab->pModule; |
| 66563 | + assert( u.cj.pModule->xColumn ); |
| 66564 | + memset(&u.cj.sContext, 0, sizeof(u.cj.sContext)); |
| 66312 | 66565 | |
| 66313 | 66566 | /* The output cell may already have a buffer allocated. Move |
| 66314 | | - ** the current contents to u.ci.sContext.s so in case the user-function |
| 66567 | + ** the current contents to u.cj.sContext.s so in case the user-function |
| 66315 | 66568 | ** can use the already allocated buffer instead of allocating a |
| 66316 | 66569 | ** new one. |
| 66317 | 66570 | */ |
| 66318 | | - sqlite3VdbeMemMove(&u.ci.sContext.s, u.ci.pDest); |
| 66319 | | - MemSetTypeFlag(&u.ci.sContext.s, MEM_Null); |
| 66571 | + sqlite3VdbeMemMove(&u.cj.sContext.s, u.cj.pDest); |
| 66572 | + MemSetTypeFlag(&u.cj.sContext.s, MEM_Null); |
| 66320 | 66573 | |
| 66321 | | - rc = u.ci.pModule->xColumn(pCur->pVtabCursor, &u.ci.sContext, pOp->p2); |
| 66322 | | - importVtabErrMsg(p, u.ci.pVtab); |
| 66323 | | - if( u.ci.sContext.isError ){ |
| 66324 | | - rc = u.ci.sContext.isError; |
| 66574 | + rc = u.cj.pModule->xColumn(pCur->pVtabCursor, &u.cj.sContext, pOp->p2); |
| 66575 | + importVtabErrMsg(p, u.cj.pVtab); |
| 66576 | + if( u.cj.sContext.isError ){ |
| 66577 | + rc = u.cj.sContext.isError; |
| 66325 | 66578 | } |
| 66326 | 66579 | |
| 66327 | 66580 | /* Copy the result of the function to the P3 register. We |
| 66328 | 66581 | ** do this regardless of whether or not an error occurred to ensure any |
| 66329 | | - ** dynamic allocation in u.ci.sContext.s (a Mem struct) is released. |
| 66582 | + ** dynamic allocation in u.cj.sContext.s (a Mem struct) is released. |
| 66330 | 66583 | */ |
| 66331 | | - sqlite3VdbeChangeEncoding(&u.ci.sContext.s, encoding); |
| 66332 | | - sqlite3VdbeMemMove(u.ci.pDest, &u.ci.sContext.s); |
| 66333 | | - REGISTER_TRACE(pOp->p3, u.ci.pDest); |
| 66334 | | - UPDATE_MAX_BLOBSIZE(u.ci.pDest); |
| 66584 | + sqlite3VdbeChangeEncoding(&u.cj.sContext.s, encoding); |
| 66585 | + sqlite3VdbeMemMove(u.cj.pDest, &u.cj.sContext.s); |
| 66586 | + REGISTER_TRACE(pOp->p3, u.cj.pDest); |
| 66587 | + UPDATE_MAX_BLOBSIZE(u.cj.pDest); |
| 66335 | 66588 | |
| 66336 | | - if( sqlite3VdbeMemTooBig(u.ci.pDest) ){ |
| 66589 | + if( sqlite3VdbeMemTooBig(u.cj.pDest) ){ |
| 66337 | 66590 | goto too_big; |
| 66338 | 66591 | } |
| 66339 | 66592 | break; |
| 66340 | 66593 | } |
| 66341 | 66594 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| | @@ -66346,42 +66599,42 @@ |
| 66346 | 66599 | ** Advance virtual table P1 to the next row in its result set and |
| 66347 | 66600 | ** jump to instruction P2. Or, if the virtual table has reached |
| 66348 | 66601 | ** the end of its result set, then fall through to the next instruction. |
| 66349 | 66602 | */ |
| 66350 | 66603 | case OP_VNext: { /* jump */ |
| 66351 | | -#if 0 /* local variables moved into u.cj */ |
| 66604 | +#if 0 /* local variables moved into u.ck */ |
| 66352 | 66605 | sqlite3_vtab *pVtab; |
| 66353 | 66606 | const sqlite3_module *pModule; |
| 66354 | 66607 | int res; |
| 66355 | 66608 | VdbeCursor *pCur; |
| 66356 | | -#endif /* local variables moved into u.cj */ |
| 66609 | +#endif /* local variables moved into u.ck */ |
| 66357 | 66610 | |
| 66358 | | - u.cj.res = 0; |
| 66359 | | - u.cj.pCur = p->apCsr[pOp->p1]; |
| 66360 | | - assert( u.cj.pCur->pVtabCursor ); |
| 66361 | | - if( u.cj.pCur->nullRow ){ |
| 66611 | + u.ck.res = 0; |
| 66612 | + u.ck.pCur = p->apCsr[pOp->p1]; |
| 66613 | + assert( u.ck.pCur->pVtabCursor ); |
| 66614 | + if( u.ck.pCur->nullRow ){ |
| 66362 | 66615 | break; |
| 66363 | 66616 | } |
| 66364 | | - u.cj.pVtab = u.cj.pCur->pVtabCursor->pVtab; |
| 66365 | | - u.cj.pModule = u.cj.pVtab->pModule; |
| 66366 | | - assert( u.cj.pModule->xNext ); |
| 66617 | + u.ck.pVtab = u.ck.pCur->pVtabCursor->pVtab; |
| 66618 | + u.ck.pModule = u.ck.pVtab->pModule; |
| 66619 | + assert( u.ck.pModule->xNext ); |
| 66367 | 66620 | |
| 66368 | 66621 | /* Invoke the xNext() method of the module. There is no way for the |
| 66369 | 66622 | ** underlying implementation to return an error if one occurs during |
| 66370 | 66623 | ** xNext(). Instead, if an error occurs, true is returned (indicating that |
| 66371 | 66624 | ** data is available) and the error code returned when xColumn or |
| 66372 | 66625 | ** some other method is next invoked on the save virtual table cursor. |
| 66373 | 66626 | */ |
| 66374 | 66627 | p->inVtabMethod = 1; |
| 66375 | | - rc = u.cj.pModule->xNext(u.cj.pCur->pVtabCursor); |
| 66628 | + rc = u.ck.pModule->xNext(u.ck.pCur->pVtabCursor); |
| 66376 | 66629 | p->inVtabMethod = 0; |
| 66377 | | - importVtabErrMsg(p, u.cj.pVtab); |
| 66630 | + importVtabErrMsg(p, u.ck.pVtab); |
| 66378 | 66631 | if( rc==SQLITE_OK ){ |
| 66379 | | - u.cj.res = u.cj.pModule->xEof(u.cj.pCur->pVtabCursor); |
| 66632 | + u.ck.res = u.ck.pModule->xEof(u.ck.pCur->pVtabCursor); |
| 66380 | 66633 | } |
| 66381 | 66634 | |
| 66382 | | - if( !u.cj.res ){ |
| 66635 | + if( !u.ck.res ){ |
| 66383 | 66636 | /* If there is data, jump to P2 */ |
| 66384 | 66637 | pc = pOp->p2 - 1; |
| 66385 | 66638 | } |
| 66386 | 66639 | break; |
| 66387 | 66640 | } |
| | @@ -66393,23 +66646,23 @@ |
| 66393 | 66646 | ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. |
| 66394 | 66647 | ** This opcode invokes the corresponding xRename method. The value |
| 66395 | 66648 | ** in register P1 is passed as the zName argument to the xRename method. |
| 66396 | 66649 | */ |
| 66397 | 66650 | case OP_VRename: { |
| 66398 | | -#if 0 /* local variables moved into u.ck */ |
| 66651 | +#if 0 /* local variables moved into u.cl */ |
| 66399 | 66652 | sqlite3_vtab *pVtab; |
| 66400 | 66653 | Mem *pName; |
| 66401 | | -#endif /* local variables moved into u.ck */ |
| 66402 | | - |
| 66403 | | - u.ck.pVtab = pOp->p4.pVtab->pVtab; |
| 66404 | | - u.ck.pName = &aMem[pOp->p1]; |
| 66405 | | - assert( u.ck.pVtab->pModule->xRename ); |
| 66406 | | - assert( memIsValid(u.ck.pName) ); |
| 66407 | | - REGISTER_TRACE(pOp->p1, u.ck.pName); |
| 66408 | | - assert( u.ck.pName->flags & MEM_Str ); |
| 66409 | | - rc = u.ck.pVtab->pModule->xRename(u.ck.pVtab, u.ck.pName->z); |
| 66410 | | - importVtabErrMsg(p, u.ck.pVtab); |
| 66654 | +#endif /* local variables moved into u.cl */ |
| 66655 | + |
| 66656 | + u.cl.pVtab = pOp->p4.pVtab->pVtab; |
| 66657 | + u.cl.pName = &aMem[pOp->p1]; |
| 66658 | + assert( u.cl.pVtab->pModule->xRename ); |
| 66659 | + assert( memIsValid(u.cl.pName) ); |
| 66660 | + REGISTER_TRACE(pOp->p1, u.cl.pName); |
| 66661 | + assert( u.cl.pName->flags & MEM_Str ); |
| 66662 | + rc = u.cl.pVtab->pModule->xRename(u.cl.pVtab, u.cl.pName->z); |
| 66663 | + importVtabErrMsg(p, u.cl.pVtab); |
| 66411 | 66664 | p->expired = 0; |
| 66412 | 66665 | |
| 66413 | 66666 | break; |
| 66414 | 66667 | } |
| 66415 | 66668 | #endif |
| | @@ -66437,39 +66690,39 @@ |
| 66437 | 66690 | ** P1 is a boolean flag. If it is set to true and the xUpdate call |
| 66438 | 66691 | ** is successful, then the value returned by sqlite3_last_insert_rowid() |
| 66439 | 66692 | ** is set to the value of the rowid for the row just inserted. |
| 66440 | 66693 | */ |
| 66441 | 66694 | case OP_VUpdate: { |
| 66442 | | -#if 0 /* local variables moved into u.cl */ |
| 66695 | +#if 0 /* local variables moved into u.cm */ |
| 66443 | 66696 | sqlite3_vtab *pVtab; |
| 66444 | 66697 | sqlite3_module *pModule; |
| 66445 | 66698 | int nArg; |
| 66446 | 66699 | int i; |
| 66447 | 66700 | sqlite_int64 rowid; |
| 66448 | 66701 | Mem **apArg; |
| 66449 | 66702 | Mem *pX; |
| 66450 | | -#endif /* local variables moved into u.cl */ |
| 66703 | +#endif /* local variables moved into u.cm */ |
| 66451 | 66704 | |
| 66452 | | - u.cl.pVtab = pOp->p4.pVtab->pVtab; |
| 66453 | | - u.cl.pModule = (sqlite3_module *)u.cl.pVtab->pModule; |
| 66454 | | - u.cl.nArg = pOp->p2; |
| 66705 | + u.cm.pVtab = pOp->p4.pVtab->pVtab; |
| 66706 | + u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule; |
| 66707 | + u.cm.nArg = pOp->p2; |
| 66455 | 66708 | assert( pOp->p4type==P4_VTAB ); |
| 66456 | | - if( ALWAYS(u.cl.pModule->xUpdate) ){ |
| 66457 | | - u.cl.apArg = p->apArg; |
| 66458 | | - u.cl.pX = &aMem[pOp->p3]; |
| 66459 | | - for(u.cl.i=0; u.cl.i<u.cl.nArg; u.cl.i++){ |
| 66460 | | - assert( memIsValid(u.cl.pX) ); |
| 66461 | | - memAboutToChange(p, u.cl.pX); |
| 66462 | | - sqlite3VdbeMemStoreType(u.cl.pX); |
| 66463 | | - u.cl.apArg[u.cl.i] = u.cl.pX; |
| 66464 | | - u.cl.pX++; |
| 66465 | | - } |
| 66466 | | - rc = u.cl.pModule->xUpdate(u.cl.pVtab, u.cl.nArg, u.cl.apArg, &u.cl.rowid); |
| 66467 | | - importVtabErrMsg(p, u.cl.pVtab); |
| 66709 | + if( ALWAYS(u.cm.pModule->xUpdate) ){ |
| 66710 | + u.cm.apArg = p->apArg; |
| 66711 | + u.cm.pX = &aMem[pOp->p3]; |
| 66712 | + for(u.cm.i=0; u.cm.i<u.cm.nArg; u.cm.i++){ |
| 66713 | + assert( memIsValid(u.cm.pX) ); |
| 66714 | + memAboutToChange(p, u.cm.pX); |
| 66715 | + sqlite3VdbeMemStoreType(u.cm.pX); |
| 66716 | + u.cm.apArg[u.cm.i] = u.cm.pX; |
| 66717 | + u.cm.pX++; |
| 66718 | + } |
| 66719 | + rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid); |
| 66720 | + importVtabErrMsg(p, u.cm.pVtab); |
| 66468 | 66721 | if( rc==SQLITE_OK && pOp->p1 ){ |
| 66469 | | - assert( u.cl.nArg>1 && u.cl.apArg[0] && (u.cl.apArg[0]->flags&MEM_Null) ); |
| 66470 | | - db->lastRowid = u.cl.rowid; |
| 66722 | + assert( u.cm.nArg>1 && u.cm.apArg[0] && (u.cm.apArg[0]->flags&MEM_Null) ); |
| 66723 | + db->lastRowid = u.cm.rowid; |
| 66471 | 66724 | } |
| 66472 | 66725 | p->nChange++; |
| 66473 | 66726 | } |
| 66474 | 66727 | break; |
| 66475 | 66728 | } |
| | @@ -66517,24 +66770,24 @@ |
| 66517 | 66770 | ** |
| 66518 | 66771 | ** If tracing is enabled (by the sqlite3_trace()) interface, then |
| 66519 | 66772 | ** the UTF-8 string contained in P4 is emitted on the trace callback. |
| 66520 | 66773 | */ |
| 66521 | 66774 | case OP_Trace: { |
| 66522 | | -#if 0 /* local variables moved into u.cm */ |
| 66775 | +#if 0 /* local variables moved into u.cn */ |
| 66523 | 66776 | char *zTrace; |
| 66524 | | -#endif /* local variables moved into u.cm */ |
| 66777 | +#endif /* local variables moved into u.cn */ |
| 66525 | 66778 | |
| 66526 | | - u.cm.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); |
| 66527 | | - if( u.cm.zTrace ){ |
| 66779 | + u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); |
| 66780 | + if( u.cn.zTrace ){ |
| 66528 | 66781 | if( db->xTrace ){ |
| 66529 | | - char *z = sqlite3VdbeExpandSql(p, u.cm.zTrace); |
| 66782 | + char *z = sqlite3VdbeExpandSql(p, u.cn.zTrace); |
| 66530 | 66783 | db->xTrace(db->pTraceArg, z); |
| 66531 | 66784 | sqlite3DbFree(db, z); |
| 66532 | 66785 | } |
| 66533 | 66786 | #ifdef SQLITE_DEBUG |
| 66534 | 66787 | if( (db->flags & SQLITE_SqlTrace)!=0 ){ |
| 66535 | | - sqlite3DebugPrintf("SQL-trace: %s\n", u.cm.zTrace); |
| 66788 | + sqlite3DebugPrintf("SQL-trace: %s\n", u.cn.zTrace); |
| 66536 | 66789 | } |
| 66537 | 66790 | #endif /* SQLITE_DEBUG */ |
| 66538 | 66791 | } |
| 66539 | 66792 | break; |
| 66540 | 66793 | } |
| | @@ -69058,11 +69311,11 @@ |
| 69058 | 69311 | ** there is no default collation type, return 0. |
| 69059 | 69312 | */ |
| 69060 | 69313 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ |
| 69061 | 69314 | CollSeq *pColl = 0; |
| 69062 | 69315 | Expr *p = pExpr; |
| 69063 | | - while( ALWAYS(p) ){ |
| 69316 | + while( p ){ |
| 69064 | 69317 | int op; |
| 69065 | 69318 | pColl = p->pColl; |
| 69066 | 69319 | if( pColl ) break; |
| 69067 | 69320 | op = p->op; |
| 69068 | 69321 | if( p->pTab!=0 && ( |
| | @@ -72217,18 +72470,20 @@ |
| 72217 | 72470 | case TK_BETWEEN: { |
| 72218 | 72471 | testcase( jumpIfNull==0 ); |
| 72219 | 72472 | exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull); |
| 72220 | 72473 | break; |
| 72221 | 72474 | } |
| 72475 | +#ifndef SQLITE_OMIT_SUBQUERY |
| 72222 | 72476 | case TK_IN: { |
| 72223 | 72477 | int destIfFalse = sqlite3VdbeMakeLabel(v); |
| 72224 | 72478 | int destIfNull = jumpIfNull ? dest : destIfFalse; |
| 72225 | 72479 | sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); |
| 72226 | 72480 | sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); |
| 72227 | 72481 | sqlite3VdbeResolveLabel(v, destIfFalse); |
| 72228 | 72482 | break; |
| 72229 | 72483 | } |
| 72484 | +#endif |
| 72230 | 72485 | default: { |
| 72231 | 72486 | r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); |
| 72232 | 72487 | sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); |
| 72233 | 72488 | testcase( regFree1==0 ); |
| 72234 | 72489 | testcase( jumpIfNull==0 ); |
| | @@ -72358,10 +72613,11 @@ |
| 72358 | 72613 | case TK_BETWEEN: { |
| 72359 | 72614 | testcase( jumpIfNull==0 ); |
| 72360 | 72615 | exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull); |
| 72361 | 72616 | break; |
| 72362 | 72617 | } |
| 72618 | +#ifndef SQLITE_OMIT_SUBQUERY |
| 72363 | 72619 | case TK_IN: { |
| 72364 | 72620 | if( jumpIfNull ){ |
| 72365 | 72621 | sqlite3ExprCodeIN(pParse, pExpr, dest, dest); |
| 72366 | 72622 | }else{ |
| 72367 | 72623 | int destIfNull = sqlite3VdbeMakeLabel(v); |
| | @@ -72368,10 +72624,11 @@ |
| 72368 | 72624 | sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull); |
| 72369 | 72625 | sqlite3VdbeResolveLabel(v, destIfNull); |
| 72370 | 72626 | } |
| 72371 | 72627 | break; |
| 72372 | 72628 | } |
| 72629 | +#endif |
| 72373 | 72630 | default: { |
| 72374 | 72631 | r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); |
| 72375 | 72632 | sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); |
| 72376 | 72633 | testcase( regFree1==0 ); |
| 72377 | 72634 | testcase( jumpIfNull==0 ); |
| | @@ -74549,13 +74806,15 @@ |
| 74549 | 74806 | goto attach_end; |
| 74550 | 74807 | } |
| 74551 | 74808 | |
| 74552 | 74809 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 74553 | 74810 | if( pAuthArg ){ |
| 74554 | | - char *zAuthArg = pAuthArg->u.zToken; |
| 74555 | | - if( NEVER(zAuthArg==0) ){ |
| 74556 | | - goto attach_end; |
| 74811 | + char *zAuthArg; |
| 74812 | + if( pAuthArg->op==TK_STRING ){ |
| 74813 | + zAuthArg = pAuthArg->u.zToken; |
| 74814 | + }else{ |
| 74815 | + zAuthArg = 0; |
| 74557 | 74816 | } |
| 74558 | 74817 | rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); |
| 74559 | 74818 | if(rc!=SQLITE_OK ){ |
| 74560 | 74819 | goto attach_end; |
| 74561 | 74820 | } |
| | @@ -87034,17 +87293,33 @@ |
| 87034 | 87293 | }else |
| 87035 | 87294 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 87036 | 87295 | |
| 87037 | 87296 | #ifndef SQLITE_OMIT_WAL |
| 87038 | 87297 | /* |
| 87039 | | - ** PRAGMA [database.]wal_checkpoint |
| 87298 | + ** PRAGMA [database.]wal_checkpoint = passive|full|restart |
| 87040 | 87299 | ** |
| 87041 | 87300 | ** Checkpoint the database. |
| 87042 | 87301 | */ |
| 87043 | 87302 | if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0 ){ |
| 87303 | + int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); |
| 87304 | + int eMode = SQLITE_CHECKPOINT_PASSIVE; |
| 87305 | + if( zRight ){ |
| 87306 | + if( sqlite3StrICmp(zRight, "full")==0 ){ |
| 87307 | + eMode = SQLITE_CHECKPOINT_FULL; |
| 87308 | + }else if( sqlite3StrICmp(zRight, "restart")==0 ){ |
| 87309 | + eMode = SQLITE_CHECKPOINT_RESTART; |
| 87310 | + } |
| 87311 | + } |
| 87044 | 87312 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 87045 | | - sqlite3VdbeAddOp3(v, OP_Checkpoint, pId2->z?iDb:SQLITE_MAX_ATTACHED, 0, 0); |
| 87313 | + sqlite3VdbeSetNumCols(v, 3); |
| 87314 | + pParse->nMem = 3; |
| 87315 | + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC); |
| 87316 | + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC); |
| 87317 | + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC); |
| 87318 | + |
| 87319 | + sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); |
| 87320 | + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
| 87046 | 87321 | }else |
| 87047 | 87322 | |
| 87048 | 87323 | /* |
| 87049 | 87324 | ** PRAGMA wal_autocheckpoint |
| 87050 | 87325 | ** PRAGMA wal_autocheckpoint = N |
| | @@ -90670,10 +90945,13 @@ |
| 90670 | 90945 | ** (20) If the sub-query is a compound select, then it must not use |
| 90671 | 90946 | ** an ORDER BY clause. Ticket #3773. We could relax this constraint |
| 90672 | 90947 | ** somewhat by saying that the terms of the ORDER BY clause must |
| 90673 | 90948 | ** appear as unmodified result columns in the outer query. But |
| 90674 | 90949 | ** have other optimizations in mind to deal with that case. |
| 90950 | +** |
| 90951 | +** (21) The subquery does not use LIMIT or the outer query is not |
| 90952 | +** DISTINCT. (See ticket [752e1646fc]). |
| 90675 | 90953 | ** |
| 90676 | 90954 | ** In this routine, the "p" parameter is a pointer to the outer query. |
| 90677 | 90955 | ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query |
| 90678 | 90956 | ** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. |
| 90679 | 90957 | ** |
| | @@ -90739,10 +91017,13 @@ |
| 90739 | 91017 | if( p->pOrderBy && pSub->pOrderBy ){ |
| 90740 | 91018 | return 0; /* Restriction (11) */ |
| 90741 | 91019 | } |
| 90742 | 91020 | if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */ |
| 90743 | 91021 | if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */ |
| 91022 | + if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){ |
| 91023 | + return 0; /* Restriction (21) */ |
| 91024 | + } |
| 90744 | 91025 | |
| 90745 | 91026 | /* OBSOLETE COMMENT 1: |
| 90746 | 91027 | ** Restriction 3: If the subquery is a join, make sure the subquery is |
| 90747 | 91028 | ** not used as the right operand of an outer join. Examples of why this |
| 90748 | 91029 | ** is not allowed: |
| | @@ -95714,10 +95995,11 @@ |
| 95714 | 95995 | ** generating the code that loops through a table looking for applicable |
| 95715 | 95996 | ** rows. Indices are selected and used to speed the search when doing |
| 95716 | 95997 | ** so is applicable. Because this module is responsible for selecting |
| 95717 | 95998 | ** indices, you might also think of this module as the "query optimizer". |
| 95718 | 95999 | */ |
| 96000 | + |
| 95719 | 96001 | |
| 95720 | 96002 | /* |
| 95721 | 96003 | ** Trace output macros |
| 95722 | 96004 | */ |
| 95723 | 96005 | #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) |
| | @@ -95814,10 +96096,15 @@ |
| 95814 | 96096 | #define TERM_CODED 0x04 /* This term is already coded */ |
| 95815 | 96097 | #define TERM_COPIED 0x08 /* Has a child */ |
| 95816 | 96098 | #define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */ |
| 95817 | 96099 | #define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */ |
| 95818 | 96100 | #define TERM_OR_OK 0x40 /* Used during OR-clause processing */ |
| 96101 | +#ifdef SQLITE_ENABLE_STAT2 |
| 96102 | +# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */ |
| 96103 | +#else |
| 96104 | +# define TERM_VNULL 0x00 /* Disabled if not using stat2 */ |
| 96105 | +#endif |
| 95819 | 96106 | |
| 95820 | 96107 | /* |
| 95821 | 96108 | ** An instance of the following structure holds all information about a |
| 95822 | 96109 | ** WHERE clause. Mostly this is a container for one or more WhereTerms. |
| 95823 | 96110 | */ |
| | @@ -95907,10 +96194,11 @@ |
| 95907 | 96194 | #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) |
| 95908 | 96195 | #define WO_MATCH 0x040 |
| 95909 | 96196 | #define WO_ISNULL 0x080 |
| 95910 | 96197 | #define WO_OR 0x100 /* Two or more OR-connected terms */ |
| 95911 | 96198 | #define WO_AND 0x200 /* Two or more AND-connected terms */ |
| 96199 | +#define WO_NOOP 0x800 /* This term does not restrict search space */ |
| 95912 | 96200 | |
| 95913 | 96201 | #define WO_ALL 0xfff /* Mask of all possible WO_* values */ |
| 95914 | 96202 | #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ |
| 95915 | 96203 | |
| 95916 | 96204 | /* |
| | @@ -96757,11 +97045,11 @@ |
| 96757 | 97045 | pWC->a[idxNew].iParent = idxTerm; |
| 96758 | 97046 | pTerm->nChild = 1; |
| 96759 | 97047 | }else{ |
| 96760 | 97048 | sqlite3ExprListDelete(db, pList); |
| 96761 | 97049 | } |
| 96762 | | - pTerm->eOperator = 0; /* case 1 trumps case 2 */ |
| 97050 | + pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ |
| 96763 | 97051 | } |
| 96764 | 97052 | } |
| 96765 | 97053 | } |
| 96766 | 97054 | #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ |
| 96767 | 97055 | |
| | @@ -97021,10 +97309,48 @@ |
| 97021 | 97309 | pNewTerm->prereqAll = pTerm->prereqAll; |
| 97022 | 97310 | } |
| 97023 | 97311 | } |
| 97024 | 97312 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 97025 | 97313 | |
| 97314 | +#ifdef SQLITE_ENABLE_STAT2 |
| 97315 | + /* When sqlite_stat2 histogram data is available an operator of the |
| 97316 | + ** form "x IS NOT NULL" can sometimes be evaluated more efficiently |
| 97317 | + ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a |
| 97318 | + ** virtual term of that form. |
| 97319 | + ** |
| 97320 | + ** Note that the virtual term must be tagged with TERM_VNULL. This |
| 97321 | + ** TERM_VNULL tag will suppress the not-null check at the beginning |
| 97322 | + ** of the loop. Without the TERM_VNULL flag, the not-null check at |
| 97323 | + ** the start of the loop will prevent any results from being returned. |
| 97324 | + */ |
| 97325 | + if( pExpr->op==TK_NOTNULL && pExpr->pLeft->iColumn>=0 ){ |
| 97326 | + Expr *pNewExpr; |
| 97327 | + Expr *pLeft = pExpr->pLeft; |
| 97328 | + int idxNew; |
| 97329 | + WhereTerm *pNewTerm; |
| 97330 | + |
| 97331 | + pNewExpr = sqlite3PExpr(pParse, TK_GT, |
| 97332 | + sqlite3ExprDup(db, pLeft, 0), |
| 97333 | + sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0); |
| 97334 | + |
| 97335 | + idxNew = whereClauseInsert(pWC, pNewExpr, |
| 97336 | + TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); |
| 97337 | + if( idxNew ){ |
| 97338 | + pNewTerm = &pWC->a[idxNew]; |
| 97339 | + pNewTerm->prereqRight = 0; |
| 97340 | + pNewTerm->leftCursor = pLeft->iTable; |
| 97341 | + pNewTerm->u.leftColumn = pLeft->iColumn; |
| 97342 | + pNewTerm->eOperator = WO_GT; |
| 97343 | + pNewTerm->iParent = idxTerm; |
| 97344 | + pTerm = &pWC->a[idxTerm]; |
| 97345 | + pTerm->nChild = 1; |
| 97346 | + pTerm->wtFlags |= TERM_COPIED; |
| 97347 | + pNewTerm->prereqAll = pTerm->prereqAll; |
| 97348 | + } |
| 97349 | + } |
| 97350 | +#endif /* SQLITE_ENABLE_STAT2 */ |
| 97351 | + |
| 97026 | 97352 | /* Prevent ON clause terms of a LEFT JOIN from being used to drive |
| 97027 | 97353 | ** an index for tables to the left of the join. |
| 97028 | 97354 | */ |
| 97029 | 97355 | pTerm->prereqRight |= extraRight; |
| 97030 | 97356 | } |
| | @@ -97073,10 +97399,11 @@ |
| 97073 | 97399 | WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmaps */ |
| 97074 | 97400 | Index *pIdx, /* The index we are testing */ |
| 97075 | 97401 | int base, /* Cursor number for the table to be sorted */ |
| 97076 | 97402 | ExprList *pOrderBy, /* The ORDER BY clause */ |
| 97077 | 97403 | int nEqCol, /* Number of index columns with == constraints */ |
| 97404 | + int wsFlags, /* Index usages flags */ |
| 97078 | 97405 | int *pbRev /* Set to 1 if ORDER BY is DESC */ |
| 97079 | 97406 | ){ |
| 97080 | 97407 | int i, j; /* Loop counters */ |
| 97081 | 97408 | int sortOrder = 0; /* XOR of index and ORDER BY sort direction */ |
| 97082 | 97409 | int nTerm; /* Number of ORDER BY terms */ |
| | @@ -97178,15 +97505,18 @@ |
| 97178 | 97505 | /* All terms of the ORDER BY clause are covered by this index so |
| 97179 | 97506 | ** this index can be used for sorting. */ |
| 97180 | 97507 | return 1; |
| 97181 | 97508 | } |
| 97182 | 97509 | if( pIdx->onError!=OE_None && i==pIdx->nColumn |
| 97510 | + && (wsFlags & WHERE_COLUMN_NULL)==0 |
| 97183 | 97511 | && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){ |
| 97184 | 97512 | /* All terms of this index match some prefix of the ORDER BY clause |
| 97185 | 97513 | ** and the index is UNIQUE and no terms on the tail of the ORDER BY |
| 97186 | 97514 | ** clause reference other tables in a join. If this is all true then |
| 97187 | | - ** the order by clause is superfluous. */ |
| 97515 | + ** the order by clause is superfluous. Not that if the matching |
| 97516 | + ** condition is IS NULL then the result is not necessarily unique |
| 97517 | + ** even on a UNIQUE index, so disallow those cases. */ |
| 97188 | 97518 | return 1; |
| 97189 | 97519 | } |
| 97190 | 97520 | return 0; |
| 97191 | 97521 | } |
| 97192 | 97522 | |
| | @@ -97419,11 +97749,11 @@ |
| 97419 | 97749 | |
| 97420 | 97750 | /* Search for any equality comparison term */ |
| 97421 | 97751 | pWCEnd = &pWC->a[pWC->nTerm]; |
| 97422 | 97752 | for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ |
| 97423 | 97753 | if( termCanDriveIndex(pTerm, pSrc, notReady) ){ |
| 97424 | | - WHERETRACE(("auto-index reduces cost from %.2f to %.2f\n", |
| 97754 | + WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n", |
| 97425 | 97755 | pCost->rCost, costTempIdx)); |
| 97426 | 97756 | pCost->rCost = costTempIdx; |
| 97427 | 97757 | pCost->plan.nRow = logN + 1; |
| 97428 | 97758 | pCost->plan.wsFlags = WHERE_TEMP_INDEX; |
| 97429 | 97759 | pCost->used = pTerm->prereqRight; |
| | @@ -97540,11 +97870,12 @@ |
| 97540 | 97870 | if( (idxCols & cMask)==0 ){ |
| 97541 | 97871 | Expr *pX = pTerm->pExpr; |
| 97542 | 97872 | idxCols |= cMask; |
| 97543 | 97873 | pIdx->aiColumn[n] = pTerm->u.leftColumn; |
| 97544 | 97874 | pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| 97545 | | - pIdx->azColl[n] = pColl->zName; |
| 97875 | + assert( pColl!=0 || pParse->nErr>0 ); |
| 97876 | + pIdx->azColl[n] = pColl ? pColl->zName : "BINARY"; |
| 97546 | 97877 | n++; |
| 97547 | 97878 | } |
| 97548 | 97879 | } |
| 97549 | 97880 | } |
| 97550 | 97881 | assert( (u32)n==pLevel->plan.nEq ); |
| | @@ -97898,15 +98229,22 @@ |
| 97898 | 98229 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 97899 | 98230 | |
| 97900 | 98231 | /* |
| 97901 | 98232 | ** Argument pIdx is a pointer to an index structure that has an array of |
| 97902 | 98233 | ** SQLITE_INDEX_SAMPLES evenly spaced samples of the first indexed column |
| 97903 | | -** stored in Index.aSample. The domain of values stored in said column |
| 97904 | | -** may be thought of as divided into (SQLITE_INDEX_SAMPLES+1) regions. |
| 97905 | | -** Region 0 contains all values smaller than the first sample value. Region |
| 97906 | | -** 1 contains values larger than or equal to the value of the first sample, |
| 97907 | | -** but smaller than the value of the second. And so on. |
| 98234 | +** stored in Index.aSample. These samples divide the domain of values stored |
| 98235 | +** the index into (SQLITE_INDEX_SAMPLES+1) regions. |
| 98236 | +** Region 0 contains all values less than the first sample value. Region |
| 98237 | +** 1 contains values between the first and second samples. Region 2 contains |
| 98238 | +** values between samples 2 and 3. And so on. Region SQLITE_INDEX_SAMPLES |
| 98239 | +** contains values larger than the last sample. |
| 98240 | +** |
| 98241 | +** If the index contains many duplicates of a single value, then it is |
| 98242 | +** possible that two or more adjacent samples can hold the same value. |
| 98243 | +** When that is the case, the smallest possible region code is returned |
| 98244 | +** when roundUp is false and the largest possible region code is returned |
| 98245 | +** when roundUp is true. |
| 97908 | 98246 | ** |
| 97909 | 98247 | ** If successful, this function determines which of the regions value |
| 97910 | 98248 | ** pVal lies in, sets *piRegion to the region index (a value between 0 |
| 97911 | 98249 | ** and SQLITE_INDEX_SAMPLES+1, inclusive) and returns SQLITE_OK. |
| 97912 | 98250 | ** Or, if an OOM occurs while converting text values between encodings, |
| | @@ -97915,22 +98253,34 @@ |
| 97915 | 98253 | #ifdef SQLITE_ENABLE_STAT2 |
| 97916 | 98254 | static int whereRangeRegion( |
| 97917 | 98255 | Parse *pParse, /* Database connection */ |
| 97918 | 98256 | Index *pIdx, /* Index to consider domain of */ |
| 97919 | 98257 | sqlite3_value *pVal, /* Value to consider */ |
| 98258 | + int roundUp, /* Return largest valid region if true */ |
| 97920 | 98259 | int *piRegion /* OUT: Region of domain in which value lies */ |
| 97921 | 98260 | ){ |
| 98261 | + assert( roundUp==0 || roundUp==1 ); |
| 97922 | 98262 | if( ALWAYS(pVal) ){ |
| 97923 | 98263 | IndexSample *aSample = pIdx->aSample; |
| 97924 | 98264 | int i = 0; |
| 97925 | 98265 | int eType = sqlite3_value_type(pVal); |
| 97926 | 98266 | |
| 97927 | 98267 | if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ |
| 97928 | 98268 | double r = sqlite3_value_double(pVal); |
| 97929 | 98269 | for(i=0; i<SQLITE_INDEX_SAMPLES; i++){ |
| 97930 | 98270 | if( aSample[i].eType==SQLITE_NULL ) continue; |
| 97931 | | - if( aSample[i].eType>=SQLITE_TEXT || aSample[i].u.r>r ) break; |
| 98271 | + if( aSample[i].eType>=SQLITE_TEXT ) break; |
| 98272 | + if( roundUp ){ |
| 98273 | + if( aSample[i].u.r>r ) break; |
| 98274 | + }else{ |
| 98275 | + if( aSample[i].u.r>=r ) break; |
| 98276 | + } |
| 98277 | + } |
| 98278 | + }else if( eType==SQLITE_NULL ){ |
| 98279 | + i = 0; |
| 98280 | + if( roundUp ){ |
| 98281 | + while( i<SQLITE_INDEX_SAMPLES && aSample[i].eType==SQLITE_NULL ) i++; |
| 97932 | 98282 | } |
| 97933 | 98283 | }else{ |
| 97934 | 98284 | sqlite3 *db = pParse->db; |
| 97935 | 98285 | CollSeq *pColl; |
| 97936 | 98286 | const u8 *z; |
| | @@ -97957,11 +98307,11 @@ |
| 97957 | 98307 | assert( z && pColl && pColl->xCmp ); |
| 97958 | 98308 | } |
| 97959 | 98309 | n = sqlite3ValueBytes(pVal, pColl->enc); |
| 97960 | 98310 | |
| 97961 | 98311 | for(i=0; i<SQLITE_INDEX_SAMPLES; i++){ |
| 97962 | | - int r; |
| 98312 | + int c; |
| 97963 | 98313 | int eSampletype = aSample[i].eType; |
| 97964 | 98314 | if( eSampletype==SQLITE_NULL || eSampletype<eType ) continue; |
| 97965 | 98315 | if( (eSampletype!=eType) ) break; |
| 97966 | 98316 | #ifndef SQLITE_OMIT_UTF16 |
| 97967 | 98317 | if( pColl->enc!=SQLITE_UTF8 ){ |
| | @@ -97971,18 +98321,18 @@ |
| 97971 | 98321 | ); |
| 97972 | 98322 | if( !zSample ){ |
| 97973 | 98323 | assert( db->mallocFailed ); |
| 97974 | 98324 | return SQLITE_NOMEM; |
| 97975 | 98325 | } |
| 97976 | | - r = pColl->xCmp(pColl->pUser, nSample, zSample, n, z); |
| 98326 | + c = pColl->xCmp(pColl->pUser, nSample, zSample, n, z); |
| 97977 | 98327 | sqlite3DbFree(db, zSample); |
| 97978 | 98328 | }else |
| 97979 | 98329 | #endif |
| 97980 | 98330 | { |
| 97981 | | - r = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z); |
| 98331 | + c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z); |
| 97982 | 98332 | } |
| 97983 | | - if( r>0 ) break; |
| 98333 | + if( c-roundUp>=0 ) break; |
| 97984 | 98334 | } |
| 97985 | 98335 | } |
| 97986 | 98336 | |
| 97987 | 98337 | assert( i>=0 && i<=SQLITE_INDEX_SAMPLES ); |
| 97988 | 98338 | *piRegion = i; |
| | @@ -98061,13 +98411,13 @@ |
| 98061 | 98411 | ** constraints (if any). A return value of 100 indicates that it is expected |
| 98062 | 98412 | ** that the range scan will visit every row (100%) selected by the equality |
| 98063 | 98413 | ** constraints. |
| 98064 | 98414 | ** |
| 98065 | 98415 | ** In the absence of sqlite_stat2 ANALYZE data, each range inequality |
| 98066 | | -** reduces the search space by 2/3rds. Hence a single constraint (x>?) |
| 98067 | | -** results in a return of 33 and a range constraint (x>? AND x<?) results |
| 98068 | | -** in a return of 11. |
| 98416 | +** reduces the search space by 3/4ths. Hence a single constraint (x>?) |
| 98417 | +** results in a return of 25 and a range constraint (x>? AND x<?) results |
| 98418 | +** in a return of 6. |
| 98069 | 98419 | */ |
| 98070 | 98420 | static int whereRangeScanEst( |
| 98071 | 98421 | Parse *pParse, /* Parsing & code generating context */ |
| 98072 | 98422 | Index *p, /* The index containing the range-compared column; "x" */ |
| 98073 | 98423 | int nEq, /* index into p->aCol[] of the range-compared column */ |
| | @@ -98083,73 +98433,209 @@ |
| 98083 | 98433 | sqlite3_value *pLowerVal = 0; |
| 98084 | 98434 | sqlite3_value *pUpperVal = 0; |
| 98085 | 98435 | int iEst; |
| 98086 | 98436 | int iLower = 0; |
| 98087 | 98437 | int iUpper = SQLITE_INDEX_SAMPLES; |
| 98438 | + int roundUpUpper = 0; |
| 98439 | + int roundUpLower = 0; |
| 98088 | 98440 | u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; |
| 98089 | 98441 | |
| 98090 | 98442 | if( pLower ){ |
| 98091 | 98443 | Expr *pExpr = pLower->pExpr->pRight; |
| 98092 | 98444 | rc = valueFromExpr(pParse, pExpr, aff, &pLowerVal); |
| 98445 | + assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE ); |
| 98446 | + roundUpLower = (pLower->eOperator==WO_GT) ?1:0; |
| 98093 | 98447 | } |
| 98094 | 98448 | if( rc==SQLITE_OK && pUpper ){ |
| 98095 | 98449 | Expr *pExpr = pUpper->pExpr->pRight; |
| 98096 | 98450 | rc = valueFromExpr(pParse, pExpr, aff, &pUpperVal); |
| 98451 | + assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE ); |
| 98452 | + roundUpUpper = (pUpper->eOperator==WO_LE) ?1:0; |
| 98097 | 98453 | } |
| 98098 | 98454 | |
| 98099 | 98455 | if( rc!=SQLITE_OK || (pLowerVal==0 && pUpperVal==0) ){ |
| 98100 | 98456 | sqlite3ValueFree(pLowerVal); |
| 98101 | 98457 | sqlite3ValueFree(pUpperVal); |
| 98102 | 98458 | goto range_est_fallback; |
| 98103 | 98459 | }else if( pLowerVal==0 ){ |
| 98104 | | - rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper); |
| 98460 | + rc = whereRangeRegion(pParse, p, pUpperVal, roundUpUpper, &iUpper); |
| 98105 | 98461 | if( pLower ) iLower = iUpper/2; |
| 98106 | 98462 | }else if( pUpperVal==0 ){ |
| 98107 | | - rc = whereRangeRegion(pParse, p, pLowerVal, &iLower); |
| 98463 | + rc = whereRangeRegion(pParse, p, pLowerVal, roundUpLower, &iLower); |
| 98108 | 98464 | if( pUpper ) iUpper = (iLower + SQLITE_INDEX_SAMPLES + 1)/2; |
| 98109 | 98465 | }else{ |
| 98110 | | - rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper); |
| 98466 | + rc = whereRangeRegion(pParse, p, pUpperVal, roundUpUpper, &iUpper); |
| 98111 | 98467 | if( rc==SQLITE_OK ){ |
| 98112 | | - rc = whereRangeRegion(pParse, p, pLowerVal, &iLower); |
| 98468 | + rc = whereRangeRegion(pParse, p, pLowerVal, roundUpLower, &iLower); |
| 98113 | 98469 | } |
| 98114 | 98470 | } |
| 98471 | + WHERETRACE(("range scan regions: %d..%d\n", iLower, iUpper)); |
| 98115 | 98472 | |
| 98116 | 98473 | iEst = iUpper - iLower; |
| 98117 | 98474 | testcase( iEst==SQLITE_INDEX_SAMPLES ); |
| 98118 | 98475 | assert( iEst<=SQLITE_INDEX_SAMPLES ); |
| 98119 | 98476 | if( iEst<1 ){ |
| 98120 | | - iEst = 1; |
| 98477 | + *piEst = 50/SQLITE_INDEX_SAMPLES; |
| 98478 | + }else{ |
| 98479 | + *piEst = (iEst*100)/SQLITE_INDEX_SAMPLES; |
| 98121 | 98480 | } |
| 98122 | | - |
| 98123 | 98481 | sqlite3ValueFree(pLowerVal); |
| 98124 | 98482 | sqlite3ValueFree(pUpperVal); |
| 98125 | | - *piEst = (iEst * 100)/SQLITE_INDEX_SAMPLES; |
| 98126 | 98483 | return rc; |
| 98127 | 98484 | } |
| 98128 | 98485 | range_est_fallback: |
| 98129 | 98486 | #else |
| 98130 | 98487 | UNUSED_PARAMETER(pParse); |
| 98131 | 98488 | UNUSED_PARAMETER(p); |
| 98132 | 98489 | UNUSED_PARAMETER(nEq); |
| 98133 | 98490 | #endif |
| 98134 | 98491 | assert( pLower || pUpper ); |
| 98135 | | - if( pLower && pUpper ){ |
| 98136 | | - *piEst = 11; |
| 98137 | | - }else{ |
| 98138 | | - *piEst = 33; |
| 98139 | | - } |
| 98492 | + *piEst = 100; |
| 98493 | + if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *piEst /= 4; |
| 98494 | + if( pUpper ) *piEst /= 4; |
| 98140 | 98495 | return rc; |
| 98141 | 98496 | } |
| 98142 | 98497 | |
| 98498 | +#ifdef SQLITE_ENABLE_STAT2 |
| 98499 | +/* |
| 98500 | +** Estimate the number of rows that will be returned based on |
| 98501 | +** an equality constraint x=VALUE and where that VALUE occurs in |
| 98502 | +** the histogram data. This only works when x is the left-most |
| 98503 | +** column of an index and sqlite_stat2 histogram data is available |
| 98504 | +** for that index. |
| 98505 | +** |
| 98506 | +** Write the estimated row count into *pnRow and return SQLITE_OK. |
| 98507 | +** If unable to make an estimate, leave *pnRow unchanged and return |
| 98508 | +** non-zero. |
| 98509 | +** |
| 98510 | +** This routine can fail if it is unable to load a collating sequence |
| 98511 | +** required for string comparison, or if unable to allocate memory |
| 98512 | +** for a UTF conversion required for comparison. The error is stored |
| 98513 | +** in the pParse structure. |
| 98514 | +*/ |
| 98515 | +int whereEqualScanEst( |
| 98516 | + Parse *pParse, /* Parsing & code generating context */ |
| 98517 | + Index *p, /* The index whose left-most column is pTerm */ |
| 98518 | + Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ |
| 98519 | + double *pnRow /* Write the revised row estimate here */ |
| 98520 | +){ |
| 98521 | + sqlite3_value *pRhs = 0; /* VALUE on right-hand side of pTerm */ |
| 98522 | + int iLower, iUpper; /* Range of histogram regions containing pRhs */ |
| 98523 | + u8 aff; /* Column affinity */ |
| 98524 | + int rc; /* Subfunction return code */ |
| 98525 | + double nRowEst; /* New estimate of the number of rows */ |
| 98526 | + |
| 98527 | + assert( p->aSample!=0 ); |
| 98528 | + aff = p->pTable->aCol[p->aiColumn[0]].affinity; |
| 98529 | + rc = valueFromExpr(pParse, pExpr, aff, &pRhs); |
| 98530 | + if( rc ) goto whereEqualScanEst_cancel; |
| 98531 | + if( pRhs==0 ) return SQLITE_NOTFOUND; |
| 98532 | + rc = whereRangeRegion(pParse, p, pRhs, 0, &iLower); |
| 98533 | + if( rc ) goto whereEqualScanEst_cancel; |
| 98534 | + rc = whereRangeRegion(pParse, p, pRhs, 1, &iUpper); |
| 98535 | + if( rc ) goto whereEqualScanEst_cancel; |
| 98536 | + WHERETRACE(("equality scan regions: %d..%d\n", iLower, iUpper)); |
| 98537 | + if( iLower>=iUpper ){ |
| 98538 | + nRowEst = p->aiRowEst[0]/(SQLITE_INDEX_SAMPLES*2); |
| 98539 | + if( nRowEst<*pnRow ) *pnRow = nRowEst; |
| 98540 | + }else{ |
| 98541 | + nRowEst = (iUpper-iLower)*p->aiRowEst[0]/SQLITE_INDEX_SAMPLES; |
| 98542 | + *pnRow = nRowEst; |
| 98543 | + } |
| 98544 | + |
| 98545 | +whereEqualScanEst_cancel: |
| 98546 | + sqlite3ValueFree(pRhs); |
| 98547 | + return rc; |
| 98548 | +} |
| 98549 | +#endif /* defined(SQLITE_ENABLE_STAT2) */ |
| 98550 | + |
| 98551 | +#ifdef SQLITE_ENABLE_STAT2 |
| 98552 | +/* |
| 98553 | +** Estimate the number of rows that will be returned based on |
| 98554 | +** an IN constraint where the right-hand side of the IN operator |
| 98555 | +** is a list of values. Example: |
| 98556 | +** |
| 98557 | +** WHERE x IN (1,2,3,4) |
| 98558 | +** |
| 98559 | +** Write the estimated row count into *pnRow and return SQLITE_OK. |
| 98560 | +** If unable to make an estimate, leave *pnRow unchanged and return |
| 98561 | +** non-zero. |
| 98562 | +** |
| 98563 | +** This routine can fail if it is unable to load a collating sequence |
| 98564 | +** required for string comparison, or if unable to allocate memory |
| 98565 | +** for a UTF conversion required for comparison. The error is stored |
| 98566 | +** in the pParse structure. |
| 98567 | +*/ |
| 98568 | +int whereInScanEst( |
| 98569 | + Parse *pParse, /* Parsing & code generating context */ |
| 98570 | + Index *p, /* The index whose left-most column is pTerm */ |
| 98571 | + ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ |
| 98572 | + double *pnRow /* Write the revised row estimate here */ |
| 98573 | +){ |
| 98574 | + sqlite3_value *pVal = 0; /* One value from list */ |
| 98575 | + int iLower, iUpper; /* Range of histogram regions containing pRhs */ |
| 98576 | + u8 aff; /* Column affinity */ |
| 98577 | + int rc = SQLITE_OK; /* Subfunction return code */ |
| 98578 | + double nRowEst; /* New estimate of the number of rows */ |
| 98579 | + int nSpan = 0; /* Number of histogram regions spanned */ |
| 98580 | + int nSingle = 0; /* Histogram regions hit by a single value */ |
| 98581 | + int nNotFound = 0; /* Count of values that are not constants */ |
| 98582 | + int i; /* Loop counter */ |
| 98583 | + u8 aSpan[SQLITE_INDEX_SAMPLES+1]; /* Histogram regions that are spanned */ |
| 98584 | + u8 aSingle[SQLITE_INDEX_SAMPLES+1]; /* Histogram regions hit once */ |
| 98585 | + |
| 98586 | + assert( p->aSample!=0 ); |
| 98587 | + aff = p->pTable->aCol[p->aiColumn[0]].affinity; |
| 98588 | + memset(aSpan, 0, sizeof(aSpan)); |
| 98589 | + memset(aSingle, 0, sizeof(aSingle)); |
| 98590 | + for(i=0; i<pList->nExpr; i++){ |
| 98591 | + sqlite3ValueFree(pVal); |
| 98592 | + rc = valueFromExpr(pParse, pList->a[i].pExpr, aff, &pVal); |
| 98593 | + if( rc ) break; |
| 98594 | + if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){ |
| 98595 | + nNotFound++; |
| 98596 | + continue; |
| 98597 | + } |
| 98598 | + rc = whereRangeRegion(pParse, p, pVal, 0, &iLower); |
| 98599 | + if( rc ) break; |
| 98600 | + rc = whereRangeRegion(pParse, p, pVal, 1, &iUpper); |
| 98601 | + if( rc ) break; |
| 98602 | + if( iLower>=iUpper ){ |
| 98603 | + aSingle[iLower] = 1; |
| 98604 | + }else{ |
| 98605 | + assert( iLower>=0 && iUpper<=SQLITE_INDEX_SAMPLES ); |
| 98606 | + while( iLower<iUpper ) aSpan[iLower++] = 1; |
| 98607 | + } |
| 98608 | + } |
| 98609 | + if( rc==SQLITE_OK ){ |
| 98610 | + for(i=nSpan=0; i<=SQLITE_INDEX_SAMPLES; i++){ |
| 98611 | + if( aSpan[i] ){ |
| 98612 | + nSpan++; |
| 98613 | + }else if( aSingle[i] ){ |
| 98614 | + nSingle++; |
| 98615 | + } |
| 98616 | + } |
| 98617 | + nRowEst = (nSpan*2+nSingle)*p->aiRowEst[0]/(2*SQLITE_INDEX_SAMPLES) |
| 98618 | + + nNotFound*p->aiRowEst[1]; |
| 98619 | + if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0]; |
| 98620 | + *pnRow = nRowEst; |
| 98621 | + WHERETRACE(("IN row estimate: nSpan=%d, nSingle=%d, nNotFound=%d, est=%g\n", |
| 98622 | + nSpan, nSingle, nNotFound, nRowEst)); |
| 98623 | + } |
| 98624 | + sqlite3ValueFree(pVal); |
| 98625 | + return rc; |
| 98626 | +} |
| 98627 | +#endif /* defined(SQLITE_ENABLE_STAT2) */ |
| 98628 | + |
| 98143 | 98629 | |
| 98144 | 98630 | /* |
| 98145 | | -** Find the query plan for accessing a particular table. Write the |
| 98631 | +** Find the best query plan for accessing a particular table. Write the |
| 98146 | 98632 | ** best query plan and its cost into the WhereCost object supplied as the |
| 98147 | 98633 | ** last parameter. |
| 98148 | 98634 | ** |
| 98149 | 98635 | ** The lowest cost plan wins. The cost is an estimate of the amount of |
| 98150 | | -** CPU and disk I/O need to process the request using the selected plan. |
| 98636 | +** CPU and disk I/O needed to process the requested result. |
| 98151 | 98637 | ** Factors that influence cost include: |
| 98152 | 98638 | ** |
| 98153 | 98639 | ** * The estimated number of rows that will be retrieved. (The |
| 98154 | 98640 | ** fewer the better.) |
| 98155 | 98641 | ** |
| | @@ -98164,11 +98650,11 @@ |
| 98164 | 98650 | ** SQLITE_BIG_DBL. If a plan is found that uses the named index, |
| 98165 | 98651 | ** then the cost is calculated in the usual way. |
| 98166 | 98652 | ** |
| 98167 | 98653 | ** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table |
| 98168 | 98654 | ** in the SELECT statement, then no indexes are considered. However, the |
| 98169 | | -** selected plan may still take advantage of the tables built-in rowid |
| 98655 | +** selected plan may still take advantage of the built-in rowid primary key |
| 98170 | 98656 | ** index. |
| 98171 | 98657 | */ |
| 98172 | 98658 | static void bestBtreeIndex( |
| 98173 | 98659 | Parse *pParse, /* The parsing context */ |
| 98174 | 98660 | WhereClause *pWC, /* The WHERE clause */ |
| | @@ -98207,13 +98693,15 @@ |
| 98207 | 98693 | /* An INDEXED BY clause specifies a particular index to use */ |
| 98208 | 98694 | pIdx = pProbe = pSrc->pIndex; |
| 98209 | 98695 | wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE); |
| 98210 | 98696 | eqTermMask = idxEqTermMask; |
| 98211 | 98697 | }else{ |
| 98212 | | - /* There is no INDEXED BY clause. Create a fake Index object to |
| 98213 | | - ** represent the primary key */ |
| 98214 | | - Index *pFirst; /* Any other index on the table */ |
| 98698 | + /* There is no INDEXED BY clause. Create a fake Index object in local |
| 98699 | + ** variable sPk to represent the rowid primary key index. Make this |
| 98700 | + ** fake index the first in a chain of Index objects with all of the real |
| 98701 | + ** indices to follow */ |
| 98702 | + Index *pFirst; /* First of real indices on the table */ |
| 98215 | 98703 | memset(&sPk, 0, sizeof(Index)); |
| 98216 | 98704 | sPk.nColumn = 1; |
| 98217 | 98705 | sPk.aiColumn = &aiColumnPk; |
| 98218 | 98706 | sPk.aiRowEst = aiRowEstPk; |
| 98219 | 98707 | sPk.onError = OE_Replace; |
| | @@ -98220,10 +98708,12 @@ |
| 98220 | 98708 | sPk.pTable = pSrc->pTab; |
| 98221 | 98709 | aiRowEstPk[0] = pSrc->pTab->nRowEst; |
| 98222 | 98710 | aiRowEstPk[1] = 1; |
| 98223 | 98711 | pFirst = pSrc->pTab->pIndex; |
| 98224 | 98712 | if( pSrc->notIndexed==0 ){ |
| 98713 | + /* The real indices of the table are only considered if the |
| 98714 | + ** NOT INDEXED qualifier is omitted from the FROM clause */ |
| 98225 | 98715 | sPk.pNext = pFirst; |
| 98226 | 98716 | } |
| 98227 | 98717 | pProbe = &sPk; |
| 98228 | 98718 | wsFlagMask = ~( |
| 98229 | 98719 | WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE |
| | @@ -98236,20 +98726,23 @@ |
| 98236 | 98726 | */ |
| 98237 | 98727 | for(; pProbe; pIdx=pProbe=pProbe->pNext){ |
| 98238 | 98728 | const unsigned int * const aiRowEst = pProbe->aiRowEst; |
| 98239 | 98729 | double cost; /* Cost of using pProbe */ |
| 98240 | 98730 | double nRow; /* Estimated number of rows in result set */ |
| 98731 | + double log10N; /* base-10 logarithm of nRow (inexact) */ |
| 98241 | 98732 | int rev; /* True to scan in reverse order */ |
| 98242 | 98733 | int wsFlags = 0; |
| 98243 | 98734 | Bitmask used = 0; |
| 98244 | 98735 | |
| 98245 | 98736 | /* The following variables are populated based on the properties of |
| 98246 | | - ** scan being evaluated. They are then used to determine the expected |
| 98737 | + ** index being evaluated. They are then used to determine the expected |
| 98247 | 98738 | ** cost and number of rows returned. |
| 98248 | 98739 | ** |
| 98249 | 98740 | ** nEq: |
| 98250 | 98741 | ** Number of equality terms that can be implemented using the index. |
| 98742 | + ** In other words, the number of initial fields in the index that |
| 98743 | + ** are used in == or IN or NOT NULL constraints of the WHERE clause. |
| 98251 | 98744 | ** |
| 98252 | 98745 | ** nInMul: |
| 98253 | 98746 | ** The "in-multiplier". This is an estimate of how many seek operations |
| 98254 | 98747 | ** SQLite must perform on the index in question. For example, if the |
| 98255 | 98748 | ** WHERE clause is: |
| | @@ -98269,46 +98762,54 @@ |
| 98269 | 98762 | ** the sub-select is assumed to return 25 rows for the purposes of |
| 98270 | 98763 | ** determining nInMul. |
| 98271 | 98764 | ** |
| 98272 | 98765 | ** bInEst: |
| 98273 | 98766 | ** Set to true if there was at least one "x IN (SELECT ...)" term used |
| 98274 | | - ** in determining the value of nInMul. |
| 98767 | + ** in determining the value of nInMul. Note that the RHS of the |
| 98768 | + ** IN operator must be a SELECT, not a value list, for this variable |
| 98769 | + ** to be true. |
| 98275 | 98770 | ** |
| 98276 | 98771 | ** estBound: |
| 98277 | 98772 | ** An estimate on the amount of the table that must be searched. A |
| 98278 | 98773 | ** value of 100 means the entire table is searched. Range constraints |
| 98279 | 98774 | ** might reduce this to a value less than 100 to indicate that only |
| 98280 | 98775 | ** a fraction of the table needs searching. In the absence of |
| 98281 | 98776 | ** sqlite_stat2 ANALYZE data, a single inequality reduces the search |
| 98282 | | - ** space to 1/3rd its original size. So an x>? constraint reduces |
| 98283 | | - ** estBound to 33. Two constraints (x>? AND x<?) reduce estBound to 11. |
| 98777 | + ** space to 1/4rd its original size. So an x>? constraint reduces |
| 98778 | + ** estBound to 25. Two constraints (x>? AND x<?) reduce estBound to 6. |
| 98284 | 98779 | ** |
| 98285 | 98780 | ** bSort: |
| 98286 | 98781 | ** Boolean. True if there is an ORDER BY clause that will require an |
| 98287 | 98782 | ** external sort (i.e. scanning the index being evaluated will not |
| 98288 | 98783 | ** correctly order records). |
| 98289 | 98784 | ** |
| 98290 | 98785 | ** bLookup: |
| 98291 | | - ** Boolean. True if for each index entry visited a lookup on the |
| 98292 | | - ** corresponding table b-tree is required. This is always false |
| 98293 | | - ** for the rowid index. For other indexes, it is true unless all the |
| 98294 | | - ** columns of the table used by the SELECT statement are present in |
| 98295 | | - ** the index (such an index is sometimes described as a covering index). |
| 98786 | + ** Boolean. True if a table lookup is required for each index entry |
| 98787 | + ** visited. In other words, true if this is not a covering index. |
| 98788 | + ** This is always false for the rowid primary key index of a table. |
| 98789 | + ** For other indexes, it is true unless all the columns of the table |
| 98790 | + ** used by the SELECT statement are present in the index (such an |
| 98791 | + ** index is sometimes described as a covering index). |
| 98296 | 98792 | ** For example, given the index on (a, b), the second of the following |
| 98297 | | - ** two queries requires table b-tree lookups, but the first does not. |
| 98793 | + ** two queries requires table b-tree lookups in order to find the value |
| 98794 | + ** of column c, but the first does not because columns a and b are |
| 98795 | + ** both available in the index. |
| 98298 | 98796 | ** |
| 98299 | 98797 | ** SELECT a, b FROM tbl WHERE a = 1; |
| 98300 | 98798 | ** SELECT a, b, c FROM tbl WHERE a = 1; |
| 98301 | 98799 | */ |
| 98302 | | - int nEq; |
| 98303 | | - int bInEst = 0; |
| 98304 | | - int nInMul = 1; |
| 98305 | | - int estBound = 100; |
| 98306 | | - int nBound = 0; /* Number of range constraints seen */ |
| 98307 | | - int bSort = 0; |
| 98308 | | - int bLookup = 0; |
| 98309 | | - WhereTerm *pTerm; /* A single term of the WHERE clause */ |
| 98800 | + int nEq; /* Number of == or IN terms matching index */ |
| 98801 | + int bInEst = 0; /* True if "x IN (SELECT...)" seen */ |
| 98802 | + int nInMul = 1; /* Number of distinct equalities to lookup */ |
| 98803 | + int estBound = 100; /* Estimated reduction in search space */ |
| 98804 | + int nBound = 0; /* Number of range constraints seen */ |
| 98805 | + int bSort = 0; /* True if external sort required */ |
| 98806 | + int bLookup = 0; /* True if not a covering index */ |
| 98807 | + WhereTerm *pTerm; /* A single term of the WHERE clause */ |
| 98808 | +#ifdef SQLITE_ENABLE_STAT2 |
| 98809 | + WhereTerm *pFirstTerm = 0; /* First term matching the index */ |
| 98810 | +#endif |
| 98310 | 98811 | |
| 98311 | 98812 | /* Determine the values of nEq and nInMul */ |
| 98312 | 98813 | for(nEq=0; nEq<pProbe->nColumn; nEq++){ |
| 98313 | 98814 | int j = pProbe->aiColumn[nEq]; |
| 98314 | 98815 | pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx); |
| | @@ -98316,18 +98817,23 @@ |
| 98316 | 98817 | wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ); |
| 98317 | 98818 | if( pTerm->eOperator & WO_IN ){ |
| 98318 | 98819 | Expr *pExpr = pTerm->pExpr; |
| 98319 | 98820 | wsFlags |= WHERE_COLUMN_IN; |
| 98320 | 98821 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 98822 | + /* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */ |
| 98321 | 98823 | nInMul *= 25; |
| 98322 | 98824 | bInEst = 1; |
| 98323 | | - }else if( ALWAYS(pExpr->x.pList) ){ |
| 98324 | | - nInMul *= pExpr->x.pList->nExpr + 1; |
| 98825 | + }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ |
| 98826 | + /* "x IN (value, value, ...)" */ |
| 98827 | + nInMul *= pExpr->x.pList->nExpr; |
| 98325 | 98828 | } |
| 98326 | 98829 | }else if( pTerm->eOperator & WO_ISNULL ){ |
| 98327 | 98830 | wsFlags |= WHERE_COLUMN_NULL; |
| 98328 | 98831 | } |
| 98832 | +#ifdef SQLITE_ENABLE_STAT2 |
| 98833 | + if( nEq==0 && pProbe->aSample ) pFirstTerm = pTerm; |
| 98834 | +#endif |
| 98329 | 98835 | used |= pTerm->prereqRight; |
| 98330 | 98836 | } |
| 98331 | 98837 | |
| 98332 | 98838 | /* Determine the value of estBound. */ |
| 98333 | 98839 | if( nEq<pProbe->nColumn ){ |
| | @@ -98359,12 +98865,13 @@ |
| 98359 | 98865 | /* If there is an ORDER BY clause and the index being considered will |
| 98360 | 98866 | ** naturally scan rows in the required order, set the appropriate flags |
| 98361 | 98867 | ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index |
| 98362 | 98868 | ** will scan rows in a different order, set the bSort variable. */ |
| 98363 | 98869 | if( pOrderBy ){ |
| 98364 | | - if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 |
| 98365 | | - && isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) |
| 98870 | + if( (wsFlags & WHERE_COLUMN_IN)==0 |
| 98871 | + && isSortingIndex(pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, |
| 98872 | + nEq, wsFlags, &rev) |
| 98366 | 98873 | ){ |
| 98367 | 98874 | wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY; |
| 98368 | 98875 | wsFlags |= (rev ? WHERE_REVERSE : 0); |
| 98369 | 98876 | }else{ |
| 98370 | 98877 | bSort = 1; |
| | @@ -98391,44 +98898,101 @@ |
| 98391 | 98898 | bLookup = 1; |
| 98392 | 98899 | } |
| 98393 | 98900 | } |
| 98394 | 98901 | |
| 98395 | 98902 | /* |
| 98396 | | - ** Estimate the number of rows of output. For an IN operator, |
| 98397 | | - ** do not let the estimate exceed half the rows in the table. |
| 98903 | + ** Estimate the number of rows of output. For an "x IN (SELECT...)" |
| 98904 | + ** constraint, do not let the estimate exceed half the rows in the table. |
| 98398 | 98905 | */ |
| 98399 | 98906 | nRow = (double)(aiRowEst[nEq] * nInMul); |
| 98400 | 98907 | if( bInEst && nRow*2>aiRowEst[0] ){ |
| 98401 | 98908 | nRow = aiRowEst[0]/2; |
| 98402 | 98909 | nInMul = (int)(nRow / aiRowEst[nEq]); |
| 98403 | 98910 | } |
| 98404 | 98911 | |
| 98405 | | - /* Assume constant cost to access a row and logarithmic cost to |
| 98406 | | - ** do a binary search. Hence, the initial cost is the number of output |
| 98407 | | - ** rows plus log2(table-size) times the number of binary searches. |
| 98912 | +#ifdef SQLITE_ENABLE_STAT2 |
| 98913 | + /* If the constraint is of the form x=VALUE and histogram |
| 98914 | + ** data is available for column x, then it might be possible |
| 98915 | + ** to get a better estimate on the number of rows based on |
| 98916 | + ** VALUE and how common that value is according to the histogram. |
| 98408 | 98917 | */ |
| 98409 | | - cost = nRow + nInMul*estLog(aiRowEst[0]); |
| 98918 | + if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){ |
| 98919 | + if( pFirstTerm->eOperator==WO_EQ ){ |
| 98920 | + whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow); |
| 98921 | + }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){ |
| 98922 | + whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow); |
| 98923 | + } |
| 98924 | + } |
| 98925 | +#endif /* SQLITE_ENABLE_STAT2 */ |
| 98410 | 98926 | |
| 98411 | | - /* Adjust the number of rows and the cost downward to reflect rows |
| 98927 | + /* Adjust the number of output rows and downward to reflect rows |
| 98412 | 98928 | ** that are excluded by range constraints. |
| 98413 | 98929 | */ |
| 98414 | 98930 | nRow = (nRow * (double)estBound) / (double)100; |
| 98415 | | - cost = (cost * (double)estBound) / (double)100; |
| 98931 | + if( nRow<1 ) nRow = 1; |
| 98416 | 98932 | |
| 98417 | | - /* Add in the estimated cost of sorting the result |
| 98933 | + /* Experiments run on real SQLite databases show that the time needed |
| 98934 | + ** to do a binary search to locate a row in a table or index is roughly |
| 98935 | + ** log10(N) times the time to move from one row to the next row within |
| 98936 | + ** a table or index. The actual times can vary, with the size of |
| 98937 | + ** records being an important factor. Both moves and searches are |
| 98938 | + ** slower with larger records, presumably because fewer records fit |
| 98939 | + ** on one page and hence more pages have to be fetched. |
| 98940 | + ** |
| 98941 | + ** The ANALYZE command and the sqlite_stat1 and sqlite_stat2 tables do |
| 98942 | + ** not give us data on the relative sizes of table and index records. |
| 98943 | + ** So this computation assumes table records are about twice as big |
| 98944 | + ** as index records |
| 98945 | + */ |
| 98946 | + if( (wsFlags & WHERE_NOT_FULLSCAN)==0 ){ |
| 98947 | + /* The cost of a full table scan is a number of move operations equal |
| 98948 | + ** to the number of rows in the table. |
| 98949 | + ** |
| 98950 | + ** We add an additional 4x penalty to full table scans. This causes |
| 98951 | + ** the cost function to err on the side of choosing an index over |
| 98952 | + ** choosing a full scan. This 4x full-scan penalty is an arguable |
| 98953 | + ** decision and one which we expect to revisit in the future. But |
| 98954 | + ** it seems to be working well enough at the moment. |
| 98955 | + */ |
| 98956 | + cost = aiRowEst[0]*4; |
| 98957 | + }else{ |
| 98958 | + log10N = estLog(aiRowEst[0]); |
| 98959 | + cost = nRow; |
| 98960 | + if( pIdx ){ |
| 98961 | + if( bLookup ){ |
| 98962 | + /* For an index lookup followed by a table lookup: |
| 98963 | + ** nInMul index searches to find the start of each index range |
| 98964 | + ** + nRow steps through the index |
| 98965 | + ** + nRow table searches to lookup the table entry using the rowid |
| 98966 | + */ |
| 98967 | + cost += (nInMul + nRow)*log10N; |
| 98968 | + }else{ |
| 98969 | + /* For a covering index: |
| 98970 | + ** nInMul index searches to find the initial entry |
| 98971 | + ** + nRow steps through the index |
| 98972 | + */ |
| 98973 | + cost += nInMul*log10N; |
| 98974 | + } |
| 98975 | + }else{ |
| 98976 | + /* For a rowid primary key lookup: |
| 98977 | + ** nInMult table searches to find the initial entry for each range |
| 98978 | + ** + nRow steps through the table |
| 98979 | + */ |
| 98980 | + cost += nInMul*log10N; |
| 98981 | + } |
| 98982 | + } |
| 98983 | + |
| 98984 | + /* Add in the estimated cost of sorting the result. Actual experimental |
| 98985 | + ** measurements of sorting performance in SQLite show that sorting time |
| 98986 | + ** adds C*N*log10(N) to the cost, where N is the number of rows to be |
| 98987 | + ** sorted and C is a factor between 1.95 and 4.3. We will split the |
| 98988 | + ** difference and select C of 3.0. |
| 98418 | 98989 | */ |
| 98419 | 98990 | if( bSort ){ |
| 98420 | | - cost += cost*estLog(cost); |
| 98991 | + cost += nRow*estLog(nRow)*3; |
| 98421 | 98992 | } |
| 98422 | 98993 | |
| 98423 | | - /* If all information can be taken directly from the index, we avoid |
| 98424 | | - ** doing table lookups. This reduces the cost by half. (Not really - |
| 98425 | | - ** this needs to be fixed.) |
| 98426 | | - */ |
| 98427 | | - if( pIdx && bLookup==0 ){ |
| 98428 | | - cost /= (double)2; |
| 98429 | | - } |
| 98430 | 98994 | /**** Cost of using this index has now been computed ****/ |
| 98431 | 98995 | |
| 98432 | 98996 | /* If there are additional constraints on this table that cannot |
| 98433 | 98997 | ** be used with the current index, but which might lower the number |
| 98434 | 98998 | ** of output rows, adjust the nRow value accordingly. This only |
| | @@ -98465,19 +99029,23 @@ |
| 98465 | 99029 | ** set size by a factor of 10 */ |
| 98466 | 99030 | nRow /= 10; |
| 98467 | 99031 | } |
| 98468 | 99032 | }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){ |
| 98469 | 99033 | if( nSkipRange ){ |
| 98470 | | - /* Ignore the first nBound range constraints since the index |
| 99034 | + /* Ignore the first nSkipRange range constraints since the index |
| 98471 | 99035 | ** has already accounted for these */ |
| 98472 | 99036 | nSkipRange--; |
| 98473 | 99037 | }else{ |
| 98474 | 99038 | /* Assume each additional range constraint reduces the result |
| 98475 | | - ** set size by a factor of 3 */ |
| 99039 | + ** set size by a factor of 3. Indexed range constraints reduce |
| 99040 | + ** the search space by a larger factor: 4. We make indexed range |
| 99041 | + ** more selective intentionally because of the subjective |
| 99042 | + ** observation that indexed range constraints really are more |
| 99043 | + ** selective in practice, on average. */ |
| 98476 | 99044 | nRow /= 3; |
| 98477 | 99045 | } |
| 98478 | | - }else{ |
| 99046 | + }else if( pTerm->eOperator!=WO_NOOP ){ |
| 98479 | 99047 | /* Any other expression lowers the output row count by half */ |
| 98480 | 99048 | nRow /= 2; |
| 98481 | 99049 | } |
| 98482 | 99050 | } |
| 98483 | 99051 | if( nRow<2 ) nRow = 2; |
| | @@ -98484,14 +99052,14 @@ |
| 98484 | 99052 | } |
| 98485 | 99053 | |
| 98486 | 99054 | |
| 98487 | 99055 | WHERETRACE(( |
| 98488 | 99056 | "%s(%s): nEq=%d nInMul=%d estBound=%d bSort=%d bLookup=%d wsFlags=0x%x\n" |
| 98489 | | - " notReady=0x%llx nRow=%.2f cost=%.2f used=0x%llx\n", |
| 99057 | + " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f used=0x%llx\n", |
| 98490 | 99058 | pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"), |
| 98491 | 99059 | nEq, nInMul, estBound, bSort, bLookup, wsFlags, |
| 98492 | | - notReady, nRow, cost, used |
| 99060 | + notReady, log10N, nRow, cost, used |
| 98493 | 99061 | )); |
| 98494 | 99062 | |
| 98495 | 99063 | /* If this index is the best we have seen so far, then record this |
| 98496 | 99064 | ** index and its cost in the pCost structure. |
| 98497 | 99065 | */ |
| | @@ -99311,11 +99879,13 @@ |
| 99311 | 99879 | /* Seek the index cursor to the start of the range. */ |
| 99312 | 99880 | nConstraint = nEq; |
| 99313 | 99881 | if( pRangeStart ){ |
| 99314 | 99882 | Expr *pRight = pRangeStart->pExpr->pRight; |
| 99315 | 99883 | sqlite3ExprCode(pParse, pRight, regBase+nEq); |
| 99316 | | - sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); |
| 99884 | + if( (pRangeStart->wtFlags & TERM_VNULL)==0 ){ |
| 99885 | + sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); |
| 99886 | + } |
| 99317 | 99887 | if( zStartAff ){ |
| 99318 | 99888 | if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){ |
| 99319 | 99889 | /* Since the comparison is to be performed with no conversions |
| 99320 | 99890 | ** applied to the operands, set the affinity to apply to pRight to |
| 99321 | 99891 | ** SQLITE_AFF_NONE. */ |
| | @@ -99350,11 +99920,13 @@ |
| 99350 | 99920 | nConstraint = nEq; |
| 99351 | 99921 | if( pRangeEnd ){ |
| 99352 | 99922 | Expr *pRight = pRangeEnd->pExpr->pRight; |
| 99353 | 99923 | sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); |
| 99354 | 99924 | sqlite3ExprCode(pParse, pRight, regBase+nEq); |
| 99355 | | - sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); |
| 99925 | + if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){ |
| 99926 | + sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); |
| 99927 | + } |
| 99356 | 99928 | if( zEndAff ){ |
| 99357 | 99929 | if( sqlite3CompareAffinity(pRight, zEndAff[nEq])==SQLITE_AFF_NONE){ |
| 99358 | 99930 | /* Since the comparison is to be performed with no conversions |
| 99359 | 99931 | ** applied to the operands, set the affinity to apply to pRight to |
| 99360 | 99932 | ** SQLITE_AFF_NONE. */ |
| | @@ -105802,11 +106374,11 @@ |
| 105802 | 106374 | /* SQLITE_NOMEM */ "out of memory", |
| 105803 | 106375 | /* SQLITE_READONLY */ "attempt to write a readonly database", |
| 105804 | 106376 | /* SQLITE_INTERRUPT */ "interrupted", |
| 105805 | 106377 | /* SQLITE_IOERR */ "disk I/O error", |
| 105806 | 106378 | /* SQLITE_CORRUPT */ "database disk image is malformed", |
| 105807 | | - /* SQLITE_NOTFOUND */ 0, |
| 106379 | + /* SQLITE_NOTFOUND */ "unknown operation", |
| 105808 | 106380 | /* SQLITE_FULL */ "database or disk is full", |
| 105809 | 106381 | /* SQLITE_CANTOPEN */ "unable to open database file", |
| 105810 | 106382 | /* SQLITE_PROTOCOL */ "locking protocol", |
| 105811 | 106383 | /* SQLITE_EMPTY */ "table contains no data", |
| 105812 | 106384 | /* SQLITE_SCHEMA */ "database schema has changed", |
| | @@ -106326,40 +106898,64 @@ |
| 106326 | 106898 | #else |
| 106327 | 106899 | return 0; |
| 106328 | 106900 | #endif |
| 106329 | 106901 | } |
| 106330 | 106902 | |
| 106331 | | - |
| 106332 | 106903 | /* |
| 106333 | | -** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points |
| 106334 | | -** to contains a zero-length string, all attached databases are |
| 106335 | | -** checkpointed. |
| 106904 | +** Checkpoint database zDb. |
| 106336 | 106905 | */ |
| 106337 | | -SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ |
| 106906 | +SQLITE_API int sqlite3_wal_checkpoint_v2( |
| 106907 | + sqlite3 *db, /* Database handle */ |
| 106908 | + const char *zDb, /* Name of attached database (or NULL) */ |
| 106909 | + int eMode, /* SQLITE_CHECKPOINT_* value */ |
| 106910 | + int *pnLog, /* OUT: Size of WAL log in frames */ |
| 106911 | + int *pnCkpt /* OUT: Total number of frames checkpointed */ |
| 106912 | +){ |
| 106338 | 106913 | #ifdef SQLITE_OMIT_WAL |
| 106339 | 106914 | return SQLITE_OK; |
| 106340 | 106915 | #else |
| 106341 | 106916 | int rc; /* Return code */ |
| 106342 | 106917 | int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */ |
| 106918 | + |
| 106919 | + /* Initialize the output variables to -1 in case an error occurs. */ |
| 106920 | + if( pnLog ) *pnLog = -1; |
| 106921 | + if( pnCkpt ) *pnCkpt = -1; |
| 106922 | + |
| 106923 | + assert( SQLITE_CHECKPOINT_FULL>SQLITE_CHECKPOINT_PASSIVE ); |
| 106924 | + assert( SQLITE_CHECKPOINT_FULL<SQLITE_CHECKPOINT_RESTART ); |
| 106925 | + assert( SQLITE_CHECKPOINT_PASSIVE+2==SQLITE_CHECKPOINT_RESTART ); |
| 106926 | + if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_RESTART ){ |
| 106927 | + return SQLITE_MISUSE; |
| 106928 | + } |
| 106343 | 106929 | |
| 106344 | 106930 | sqlite3_mutex_enter(db->mutex); |
| 106345 | 106931 | if( zDb && zDb[0] ){ |
| 106346 | 106932 | iDb = sqlite3FindDbName(db, zDb); |
| 106347 | 106933 | } |
| 106348 | 106934 | if( iDb<0 ){ |
| 106349 | 106935 | rc = SQLITE_ERROR; |
| 106350 | 106936 | sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb); |
| 106351 | 106937 | }else{ |
| 106352 | | - rc = sqlite3Checkpoint(db, iDb); |
| 106938 | + rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
| 106353 | 106939 | sqlite3Error(db, rc, 0); |
| 106354 | 106940 | } |
| 106355 | 106941 | rc = sqlite3ApiExit(db, rc); |
| 106356 | 106942 | sqlite3_mutex_leave(db->mutex); |
| 106357 | 106943 | return rc; |
| 106358 | 106944 | #endif |
| 106359 | 106945 | } |
| 106360 | 106946 | |
| 106947 | + |
| 106948 | +/* |
| 106949 | +** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points |
| 106950 | +** to contains a zero-length string, all attached databases are |
| 106951 | +** checkpointed. |
| 106952 | +*/ |
| 106953 | +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ |
| 106954 | + return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0); |
| 106955 | +} |
| 106956 | + |
| 106361 | 106957 | #ifndef SQLITE_OMIT_WAL |
| 106362 | 106958 | /* |
| 106363 | 106959 | ** Run a checkpoint on database iDb. This is a no-op if database iDb is |
| 106364 | 106960 | ** not currently open in WAL mode. |
| 106365 | 106961 | ** |
| | @@ -106373,24 +106969,35 @@ |
| 106373 | 106969 | ** this function while the checkpoint is running. |
| 106374 | 106970 | ** |
| 106375 | 106971 | ** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are |
| 106376 | 106972 | ** checkpointed. If an error is encountered it is returned immediately - |
| 106377 | 106973 | ** no attempt is made to checkpoint any remaining databases. |
| 106974 | +** |
| 106975 | +** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 106378 | 106976 | */ |
| 106379 | | -SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb){ |
| 106977 | +SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){ |
| 106380 | 106978 | int rc = SQLITE_OK; /* Return code */ |
| 106381 | 106979 | int i; /* Used to iterate through attached dbs */ |
| 106980 | + int bBusy = 0; /* True if SQLITE_BUSY has been encountered */ |
| 106382 | 106981 | |
| 106383 | 106982 | assert( sqlite3_mutex_held(db->mutex) ); |
| 106983 | + assert( !pnLog || *pnLog==-1 ); |
| 106984 | + assert( !pnCkpt || *pnCkpt==-1 ); |
| 106384 | 106985 | |
| 106385 | 106986 | for(i=0; i<db->nDb && rc==SQLITE_OK; i++){ |
| 106386 | 106987 | if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){ |
| 106387 | | - rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt); |
| 106988 | + rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt); |
| 106989 | + pnLog = 0; |
| 106990 | + pnCkpt = 0; |
| 106991 | + if( rc==SQLITE_BUSY ){ |
| 106992 | + bBusy = 1; |
| 106993 | + rc = SQLITE_OK; |
| 106994 | + } |
| 106388 | 106995 | } |
| 106389 | 106996 | } |
| 106390 | 106997 | |
| 106391 | | - return rc; |
| 106998 | + return (rc==SQLITE_OK && bBusy) ? SQLITE_BUSY : rc; |
| 106392 | 106999 | } |
| 106393 | 107000 | #endif /* SQLITE_OMIT_WAL */ |
| 106394 | 107001 | |
| 106395 | 107002 | /* |
| 106396 | 107003 | ** This function returns true if main-memory should be used instead of |
| | @@ -107350,10 +107957,12 @@ |
| 107350 | 107957 | if( op==SQLITE_FCNTL_FILE_POINTER ){ |
| 107351 | 107958 | *(sqlite3_file**)pArg = fd; |
| 107352 | 107959 | rc = SQLITE_OK; |
| 107353 | 107960 | }else if( fd->pMethods ){ |
| 107354 | 107961 | rc = sqlite3OsFileControl(fd, op, pArg); |
| 107962 | + }else{ |
| 107963 | + rc = SQLITE_NOTFOUND; |
| 107355 | 107964 | } |
| 107356 | 107965 | sqlite3BtreeLeave(pBtree); |
| 107357 | 107966 | } |
| 107358 | 107967 | } |
| 107359 | 107968 | sqlite3_mutex_leave(db->mutex); |
| | @@ -108597,11 +109206,11 @@ |
| 108597 | 109206 | typedef struct Fts3PhraseToken Fts3PhraseToken; |
| 108598 | 109207 | |
| 108599 | 109208 | typedef struct Fts3SegFilter Fts3SegFilter; |
| 108600 | 109209 | typedef struct Fts3DeferredToken Fts3DeferredToken; |
| 108601 | 109210 | typedef struct Fts3SegReader Fts3SegReader; |
| 108602 | | -typedef struct Fts3SegReaderArray Fts3SegReaderArray; |
| 109211 | +typedef struct Fts3SegReaderCursor Fts3SegReaderCursor; |
| 108603 | 109212 | |
| 108604 | 109213 | /* |
| 108605 | 109214 | ** A connection to a fulltext index is an instance of the following |
| 108606 | 109215 | ** structure. The xCreate and xConnect methods create an instance |
| 108607 | 109216 | ** of this structure and xDestroy and xDisconnect free that instance. |
| | @@ -108620,10 +109229,13 @@ |
| 108620 | 109229 | /* Precompiled statements used by the implementation. Each of these |
| 108621 | 109230 | ** statements is run and reset within a single virtual table API call. |
| 108622 | 109231 | */ |
| 108623 | 109232 | sqlite3_stmt *aStmt[24]; |
| 108624 | 109233 | |
| 109234 | + char *zReadExprlist; |
| 109235 | + char *zWriteExprlist; |
| 109236 | + |
| 108625 | 109237 | int nNodeSize; /* Soft limit for node size */ |
| 108626 | 109238 | u8 bHasStat; /* True if %_stat table exists */ |
| 108627 | 109239 | u8 bHasDocsize; /* True if %_docsize table exists */ |
| 108628 | 109240 | int nPgsz; /* Page size for host database */ |
| 108629 | 109241 | char *zSegmentsTbl; /* Name of %_segments table */ |
| | @@ -108707,11 +109319,11 @@ |
| 108707 | 109319 | struct Fts3PhraseToken { |
| 108708 | 109320 | char *z; /* Text of the token */ |
| 108709 | 109321 | int n; /* Number of bytes in buffer z */ |
| 108710 | 109322 | int isPrefix; /* True if token ends with a "*" character */ |
| 108711 | 109323 | int bFulltext; /* True if full-text index was used */ |
| 108712 | | - Fts3SegReaderArray *pArray; /* Segment-reader for this token */ |
| 109324 | + Fts3SegReaderCursor *pSegcsr; /* Segment-reader for this token */ |
| 108713 | 109325 | Fts3DeferredToken *pDeferred; /* Deferred token object for this token */ |
| 108714 | 109326 | }; |
| 108715 | 109327 | |
| 108716 | 109328 | struct Fts3Phrase { |
| 108717 | 109329 | /* Variables populated by fts3_expr.c when parsing a MATCH expression */ |
| | @@ -108775,16 +109387,12 @@ |
| 108775 | 109387 | SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *); |
| 108776 | 109388 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, sqlite3_int64, |
| 108777 | 109389 | sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); |
| 108778 | 109390 | SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**); |
| 108779 | 109391 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *); |
| 108780 | | -SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate( |
| 108781 | | - Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, |
| 108782 | | - int (*)(Fts3Table *, void *, char *, int, char *, int), void * |
| 108783 | | -); |
| 108784 | 109392 | SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(Fts3Cursor *, Fts3SegReader *, int *); |
| 108785 | | -SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
| 109393 | +SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, sqlite3_stmt **); |
| 108786 | 109394 | SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); |
| 108787 | 109395 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*); |
| 108788 | 109396 | |
| 108789 | 109397 | SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); |
| 108790 | 109398 | SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); |
| | @@ -108792,26 +109400,54 @@ |
| 108792 | 109400 | SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *); |
| 108793 | 109401 | SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int); |
| 108794 | 109402 | SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *); |
| 108795 | 109403 | SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *); |
| 108796 | 109404 | SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *, int *); |
| 108797 | | - |
| 108798 | 109405 | SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *); |
| 108799 | 109406 | |
| 109407 | +#define FTS3_SEGCURSOR_PENDING -1 |
| 109408 | +#define FTS3_SEGCURSOR_ALL -2 |
| 109409 | + |
| 109410 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3SegReaderCursor*, Fts3SegFilter*); |
| 109411 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3SegReaderCursor *); |
| 109412 | +SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3SegReaderCursor *); |
| 109413 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( |
| 109414 | + Fts3Table *, int, const char *, int, int, int, Fts3SegReaderCursor *); |
| 109415 | + |
| 108800 | 109416 | /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ |
| 108801 | 109417 | #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 |
| 108802 | 109418 | #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 |
| 108803 | 109419 | #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 |
| 108804 | 109420 | #define FTS3_SEGMENT_PREFIX 0x00000008 |
| 109421 | +#define FTS3_SEGMENT_SCAN 0x00000010 |
| 108805 | 109422 | |
| 108806 | 109423 | /* Type passed as 4th argument to SegmentReaderIterate() */ |
| 108807 | 109424 | struct Fts3SegFilter { |
| 108808 | 109425 | const char *zTerm; |
| 108809 | 109426 | int nTerm; |
| 108810 | 109427 | int iCol; |
| 108811 | 109428 | int flags; |
| 108812 | 109429 | }; |
| 109430 | + |
| 109431 | +struct Fts3SegReaderCursor { |
| 109432 | + /* Used internally by sqlite3Fts3SegReaderXXX() calls */ |
| 109433 | + Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */ |
| 109434 | + int nSegment; /* Size of apSegment array */ |
| 109435 | + int nAdvance; /* How many seg-readers to advance */ |
| 109436 | + Fts3SegFilter *pFilter; /* Pointer to filter object */ |
| 109437 | + char *aBuffer; /* Buffer to merge doclists in */ |
| 109438 | + int nBuffer; /* Allocated size of aBuffer[] in bytes */ |
| 109439 | + |
| 109440 | + /* Cost of running this iterator. Used by fts3.c only. */ |
| 109441 | + int nCost; |
| 109442 | + |
| 109443 | + /* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */ |
| 109444 | + char *zTerm; /* Pointer to term buffer */ |
| 109445 | + int nTerm; /* Size of zTerm in bytes */ |
| 109446 | + char *aDoclist; /* Pointer to doclist buffer */ |
| 109447 | + int nDoclist; /* Size of aDoclist[] in bytes */ |
| 109448 | +}; |
| 108813 | 109449 | |
| 108814 | 109450 | /* fts3.c */ |
| 108815 | 109451 | SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); |
| 108816 | 109452 | SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); |
| 108817 | 109453 | SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); |
| | @@ -108845,10 +109481,13 @@ |
| 108845 | 109481 | SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); |
| 108846 | 109482 | #ifdef SQLITE_TEST |
| 108847 | 109483 | SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); |
| 108848 | 109484 | #endif |
| 108849 | 109485 | |
| 109486 | +/* fts3_aux.c */ |
| 109487 | +SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db); |
| 109488 | + |
| 108850 | 109489 | #endif /* _FTSINT_H */ |
| 108851 | 109490 | |
| 108852 | 109491 | /************** End of fts3Int.h *********************************************/ |
| 108853 | 109492 | /************** Continuing where we left off in fts3.c ***********************/ |
| 108854 | 109493 | |
| | @@ -108990,10 +109629,12 @@ |
| 108990 | 109629 | /* Free any prepared statements held */ |
| 108991 | 109630 | for(i=0; i<SizeofArray(p->aStmt); i++){ |
| 108992 | 109631 | sqlite3_finalize(p->aStmt[i]); |
| 108993 | 109632 | } |
| 108994 | 109633 | sqlite3_free(p->zSegmentsTbl); |
| 109634 | + sqlite3_free(p->zReadExprlist); |
| 109635 | + sqlite3_free(p->zWriteExprlist); |
| 108995 | 109636 | |
| 108996 | 109637 | /* Invoke the tokenizer destructor to free the tokenizer. */ |
| 108997 | 109638 | p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
| 108998 | 109639 | |
| 108999 | 109640 | sqlite3_free(p); |
| | @@ -109206,10 +109847,145 @@ |
| 109206 | 109847 | sqlite3Fts3Dequote(zValue); |
| 109207 | 109848 | } |
| 109208 | 109849 | *pzValue = zValue; |
| 109209 | 109850 | return 1; |
| 109210 | 109851 | } |
| 109852 | + |
| 109853 | +/* |
| 109854 | +** Append the output of a printf() style formatting to an existing string. |
| 109855 | +*/ |
| 109856 | +static void fts3Appendf( |
| 109857 | + int *pRc, /* IN/OUT: Error code */ |
| 109858 | + char **pz, /* IN/OUT: Pointer to string buffer */ |
| 109859 | + const char *zFormat, /* Printf format string to append */ |
| 109860 | + ... /* Arguments for printf format string */ |
| 109861 | +){ |
| 109862 | + if( *pRc==SQLITE_OK ){ |
| 109863 | + va_list ap; |
| 109864 | + char *z; |
| 109865 | + va_start(ap, zFormat); |
| 109866 | + z = sqlite3_vmprintf(zFormat, ap); |
| 109867 | + if( z && *pz ){ |
| 109868 | + char *z2 = sqlite3_mprintf("%s%s", *pz, z); |
| 109869 | + sqlite3_free(z); |
| 109870 | + z = z2; |
| 109871 | + } |
| 109872 | + if( z==0 ) *pRc = SQLITE_NOMEM; |
| 109873 | + sqlite3_free(*pz); |
| 109874 | + *pz = z; |
| 109875 | + } |
| 109876 | +} |
| 109877 | + |
| 109878 | +/* |
| 109879 | +** Return a copy of input string zInput enclosed in double-quotes (") and |
| 109880 | +** with all double quote characters escaped. For example: |
| 109881 | +** |
| 109882 | +** fts3QuoteId("un \"zip\"") -> "un \"\"zip\"\"" |
| 109883 | +** |
| 109884 | +** The pointer returned points to memory obtained from sqlite3_malloc(). It |
| 109885 | +** is the callers responsibility to call sqlite3_free() to release this |
| 109886 | +** memory. |
| 109887 | +*/ |
| 109888 | +static char *fts3QuoteId(char const *zInput){ |
| 109889 | + int nRet; |
| 109890 | + char *zRet; |
| 109891 | + nRet = 2 + strlen(zInput)*2 + 1; |
| 109892 | + zRet = sqlite3_malloc(nRet); |
| 109893 | + if( zRet ){ |
| 109894 | + int i; |
| 109895 | + char *z = zRet; |
| 109896 | + *(z++) = '"'; |
| 109897 | + for(i=0; zInput[i]; i++){ |
| 109898 | + if( zInput[i]=='"' ) *(z++) = '"'; |
| 109899 | + *(z++) = zInput[i]; |
| 109900 | + } |
| 109901 | + *(z++) = '"'; |
| 109902 | + *(z++) = '\0'; |
| 109903 | + } |
| 109904 | + return zRet; |
| 109905 | +} |
| 109906 | + |
| 109907 | +/* |
| 109908 | +** Return a list of comma separated SQL expressions that could be used |
| 109909 | +** in a SELECT statement such as the following: |
| 109910 | +** |
| 109911 | +** SELECT <list of expressions> FROM %_content AS x ... |
| 109912 | +** |
| 109913 | +** to return the docid, followed by each column of text data in order |
| 109914 | +** from left to write. If parameter zFunc is not NULL, then instead of |
| 109915 | +** being returned directly each column of text data is passed to an SQL |
| 109916 | +** function named zFunc first. For example, if zFunc is "unzip" and the |
| 109917 | +** table has the three user-defined columns "a", "b", and "c", the following |
| 109918 | +** string is returned: |
| 109919 | +** |
| 109920 | +** "docid, unzip(x.'a'), unzip(x.'b'), unzip(x.'c')" |
| 109921 | +** |
| 109922 | +** The pointer returned points to a buffer allocated by sqlite3_malloc(). It |
| 109923 | +** is the responsibility of the caller to eventually free it. |
| 109924 | +** |
| 109925 | +** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and |
| 109926 | +** a NULL pointer is returned). Otherwise, if an OOM error is encountered |
| 109927 | +** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If |
| 109928 | +** no error occurs, *pRc is left unmodified. |
| 109929 | +*/ |
| 109930 | +static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){ |
| 109931 | + char *zRet = 0; |
| 109932 | + char *zFree = 0; |
| 109933 | + char *zFunction; |
| 109934 | + int i; |
| 109935 | + |
| 109936 | + if( !zFunc ){ |
| 109937 | + zFunction = ""; |
| 109938 | + }else{ |
| 109939 | + zFree = zFunction = fts3QuoteId(zFunc); |
| 109940 | + } |
| 109941 | + fts3Appendf(pRc, &zRet, "docid"); |
| 109942 | + for(i=0; i<p->nColumn; i++){ |
| 109943 | + fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]); |
| 109944 | + } |
| 109945 | + sqlite3_free(zFree); |
| 109946 | + return zRet; |
| 109947 | +} |
| 109948 | + |
| 109949 | +/* |
| 109950 | +** Return a list of N comma separated question marks, where N is the number |
| 109951 | +** of columns in the %_content table (one for the docid plus one for each |
| 109952 | +** user-defined text column). |
| 109953 | +** |
| 109954 | +** If argument zFunc is not NULL, then all but the first question mark |
| 109955 | +** is preceded by zFunc and an open bracket, and followed by a closed |
| 109956 | +** bracket. For example, if zFunc is "zip" and the FTS3 table has three |
| 109957 | +** user-defined text columns, the following string is returned: |
| 109958 | +** |
| 109959 | +** "?, zip(?), zip(?), zip(?)" |
| 109960 | +** |
| 109961 | +** The pointer returned points to a buffer allocated by sqlite3_malloc(). It |
| 109962 | +** is the responsibility of the caller to eventually free it. |
| 109963 | +** |
| 109964 | +** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and |
| 109965 | +** a NULL pointer is returned). Otherwise, if an OOM error is encountered |
| 109966 | +** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If |
| 109967 | +** no error occurs, *pRc is left unmodified. |
| 109968 | +*/ |
| 109969 | +static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){ |
| 109970 | + char *zRet = 0; |
| 109971 | + char *zFree = 0; |
| 109972 | + char *zFunction; |
| 109973 | + int i; |
| 109974 | + |
| 109975 | + if( !zFunc ){ |
| 109976 | + zFunction = ""; |
| 109977 | + }else{ |
| 109978 | + zFree = zFunction = fts3QuoteId(zFunc); |
| 109979 | + } |
| 109980 | + fts3Appendf(pRc, &zRet, "?"); |
| 109981 | + for(i=0; i<p->nColumn; i++){ |
| 109982 | + fts3Appendf(pRc, &zRet, ",%s(?)", zFunction); |
| 109983 | + } |
| 109984 | + sqlite3_free(zFree); |
| 109985 | + return zRet; |
| 109986 | +} |
| 109211 | 109987 | |
| 109212 | 109988 | /* |
| 109213 | 109989 | ** This function is the implementation of both the xConnect and xCreate |
| 109214 | 109990 | ** methods of the FTS3 virtual table. |
| 109215 | 109991 | ** |
| | @@ -109243,10 +110019,13 @@ |
| 109243 | 110019 | int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */ |
| 109244 | 110020 | int bNoDocsize = 0; /* True to omit %_docsize table */ |
| 109245 | 110021 | const char **aCol; /* Array of column names */ |
| 109246 | 110022 | sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ |
| 109247 | 110023 | |
| 110024 | + char *zCompress = 0; |
| 110025 | + char *zUncompress = 0; |
| 110026 | + |
| 109248 | 110027 | assert( strlen(argv[0])==4 ); |
| 109249 | 110028 | assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4) |
| 109250 | 110029 | || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4) |
| 109251 | 110030 | ); |
| 109252 | 110031 | |
| | @@ -109293,10 +110072,16 @@ |
| 109293 | 110072 | bNoDocsize = 1; |
| 109294 | 110073 | }else{ |
| 109295 | 110074 | *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal); |
| 109296 | 110075 | rc = SQLITE_ERROR; |
| 109297 | 110076 | } |
| 110077 | + }else if( nKey==8 && 0==sqlite3_strnicmp(z, "compress", 8) ){ |
| 110078 | + zCompress = zVal; |
| 110079 | + zVal = 0; |
| 110080 | + }else if( nKey==10 && 0==sqlite3_strnicmp(z, "uncompress", 10) ){ |
| 110081 | + zUncompress = zVal; |
| 110082 | + zVal = 0; |
| 109298 | 110083 | }else{ |
| 109299 | 110084 | *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z); |
| 109300 | 110085 | rc = SQLITE_ERROR; |
| 109301 | 110086 | } |
| 109302 | 110087 | sqlite3_free(zVal); |
| | @@ -109366,10 +110151,19 @@ |
| 109366 | 110151 | sqlite3Fts3Dequote(zCsr); |
| 109367 | 110152 | p->azColumn[iCol] = zCsr; |
| 109368 | 110153 | zCsr += n+1; |
| 109369 | 110154 | assert( zCsr <= &((char *)p)[nByte] ); |
| 109370 | 110155 | } |
| 110156 | + |
| 110157 | + if( (zCompress==0)!=(zUncompress==0) ){ |
| 110158 | + char const *zMiss = (zCompress==0 ? "compress" : "uncompress"); |
| 110159 | + rc = SQLITE_ERROR; |
| 110160 | + *pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss); |
| 110161 | + } |
| 110162 | + p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc); |
| 110163 | + p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); |
| 110164 | + if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 109371 | 110165 | |
| 109372 | 110166 | /* If this is an xCreate call, create the underlying tables in the |
| 109373 | 110167 | ** database. TODO: For xConnect(), it could verify that said tables exist. |
| 109374 | 110168 | */ |
| 109375 | 110169 | if( isCreate ){ |
| | @@ -109384,11 +110178,12 @@ |
| 109384 | 110178 | |
| 109385 | 110179 | /* Declare the table schema to SQLite. */ |
| 109386 | 110180 | fts3DeclareVtab(&rc, p); |
| 109387 | 110181 | |
| 109388 | 110182 | fts3_init_out: |
| 109389 | | - |
| 110183 | + sqlite3_free(zCompress); |
| 110184 | + sqlite3_free(zUncompress); |
| 109390 | 110185 | sqlite3_free((void *)aCol); |
| 109391 | 110186 | if( rc!=SQLITE_OK ){ |
| 109392 | 110187 | if( p ){ |
| 109393 | 110188 | fts3DisconnectMethod((sqlite3_vtab *)p); |
| 109394 | 110189 | }else if( pTokenizer ){ |
| | @@ -110477,134 +111272,137 @@ |
| 110477 | 111272 | } |
| 110478 | 111273 | |
| 110479 | 111274 | return SQLITE_OK; |
| 110480 | 111275 | } |
| 110481 | 111276 | |
| 110482 | | -/* |
| 110483 | | -** An Fts3SegReaderArray is used to store an array of Fts3SegReader objects. |
| 110484 | | -** Elements are added to the array using fts3SegReaderArrayAdd(). |
| 110485 | | -*/ |
| 110486 | | -struct Fts3SegReaderArray { |
| 110487 | | - int nSegment; /* Number of valid entries in apSegment[] */ |
| 110488 | | - int nAlloc; /* Allocated size of apSegment[] */ |
| 110489 | | - int nCost; /* The cost of executing SegReaderIterate() */ |
| 110490 | | - Fts3SegReader *apSegment[1]; /* Array of seg-reader objects */ |
| 110491 | | -}; |
| 110492 | | - |
| 110493 | | - |
| 110494 | | -/* |
| 110495 | | -** Free an Fts3SegReaderArray object. Also free all seg-readers in the |
| 110496 | | -** array (using sqlite3Fts3SegReaderFree()). |
| 110497 | | -*/ |
| 110498 | | -static void fts3SegReaderArrayFree(Fts3SegReaderArray *pArray){ |
| 110499 | | - if( pArray ){ |
| 110500 | | - int i; |
| 110501 | | - for(i=0; i<pArray->nSegment; i++){ |
| 110502 | | - sqlite3Fts3SegReaderFree(pArray->apSegment[i]); |
| 110503 | | - } |
| 110504 | | - sqlite3_free(pArray); |
| 110505 | | - } |
| 110506 | | -} |
| 110507 | | - |
| 110508 | | -static int fts3SegReaderArrayAdd( |
| 110509 | | - Fts3SegReaderArray **ppArray, |
| 110510 | | - Fts3SegReader *pNew |
| 110511 | | -){ |
| 110512 | | - Fts3SegReaderArray *pArray = *ppArray; |
| 110513 | | - |
| 110514 | | - if( !pArray || pArray->nAlloc==pArray->nSegment ){ |
| 110515 | | - int nNew = (pArray ? pArray->nAlloc+16 : 16); |
| 110516 | | - pArray = (Fts3SegReaderArray *)sqlite3_realloc(pArray, |
| 110517 | | - sizeof(Fts3SegReaderArray) + (nNew-1) * sizeof(Fts3SegReader*) |
| 110518 | | - ); |
| 110519 | | - if( !pArray ){ |
| 110520 | | - sqlite3Fts3SegReaderFree(pNew); |
| 110521 | | - return SQLITE_NOMEM; |
| 110522 | | - } |
| 110523 | | - if( nNew==16 ){ |
| 110524 | | - pArray->nSegment = 0; |
| 110525 | | - pArray->nCost = 0; |
| 110526 | | - } |
| 110527 | | - pArray->nAlloc = nNew; |
| 110528 | | - *ppArray = pArray; |
| 110529 | | - } |
| 110530 | | - |
| 110531 | | - pArray->apSegment[pArray->nSegment++] = pNew; |
| 110532 | | - return SQLITE_OK; |
| 110533 | | -} |
| 110534 | | - |
| 110535 | | -static int fts3TermSegReaderArray( |
| 111277 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( |
| 111278 | + Fts3Table *p, /* FTS3 table handle */ |
| 111279 | + int iLevel, /* Level of segments to scan */ |
| 111280 | + const char *zTerm, /* Term to query for */ |
| 111281 | + int nTerm, /* Size of zTerm in bytes */ |
| 111282 | + int isPrefix, /* True for a prefix search */ |
| 111283 | + int isScan, /* True to scan from zTerm to EOF */ |
| 111284 | + Fts3SegReaderCursor *pCsr /* Cursor object to populate */ |
| 111285 | +){ |
| 111286 | + int rc = SQLITE_OK; |
| 111287 | + int rc2; |
| 111288 | + int iAge = 0; |
| 111289 | + sqlite3_stmt *pStmt = 0; |
| 111290 | + Fts3SegReader *pPending = 0; |
| 111291 | + |
| 111292 | + assert( iLevel==FTS3_SEGCURSOR_ALL |
| 111293 | + || iLevel==FTS3_SEGCURSOR_PENDING |
| 111294 | + || iLevel>=0 |
| 111295 | + ); |
| 111296 | + assert( FTS3_SEGCURSOR_PENDING<0 ); |
| 111297 | + assert( FTS3_SEGCURSOR_ALL<0 ); |
| 111298 | + assert( iLevel==FTS3_SEGCURSOR_ALL || (zTerm==0 && isPrefix==1) ); |
| 111299 | + assert( isPrefix==0 || isScan==0 ); |
| 111300 | + |
| 111301 | + |
| 111302 | + memset(pCsr, 0, sizeof(Fts3SegReaderCursor)); |
| 111303 | + |
| 111304 | + /* If iLevel is less than 0, include a seg-reader for the pending-terms. */ |
| 111305 | + assert( isScan==0 || fts3HashCount(&p->pendingTerms)==0 ); |
| 111306 | + if( iLevel<0 && isScan==0 ){ |
| 111307 | + rc = sqlite3Fts3SegReaderPending(p, zTerm, nTerm, isPrefix, &pPending); |
| 111308 | + if( rc==SQLITE_OK && pPending ){ |
| 111309 | + int nByte = (sizeof(Fts3SegReader *) * 16); |
| 111310 | + pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte); |
| 111311 | + if( pCsr->apSegment==0 ){ |
| 111312 | + rc = SQLITE_NOMEM; |
| 111313 | + }else{ |
| 111314 | + pCsr->apSegment[0] = pPending; |
| 111315 | + pCsr->nSegment = 1; |
| 111316 | + pPending = 0; |
| 111317 | + } |
| 111318 | + } |
| 111319 | + } |
| 111320 | + |
| 111321 | + if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
| 111322 | + if( rc==SQLITE_OK ){ |
| 111323 | + rc = sqlite3Fts3AllSegdirs(p, iLevel, &pStmt); |
| 111324 | + } |
| 111325 | + while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ |
| 111326 | + |
| 111327 | + /* Read the values returned by the SELECT into local variables. */ |
| 111328 | + sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1); |
| 111329 | + sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2); |
| 111330 | + sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3); |
| 111331 | + int nRoot = sqlite3_column_bytes(pStmt, 4); |
| 111332 | + char const *zRoot = sqlite3_column_blob(pStmt, 4); |
| 111333 | + |
| 111334 | + /* If nSegment is a multiple of 16 the array needs to be extended. */ |
| 111335 | + if( (pCsr->nSegment%16)==0 ){ |
| 111336 | + Fts3SegReader **apNew; |
| 111337 | + int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*); |
| 111338 | + apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte); |
| 111339 | + if( !apNew ){ |
| 111340 | + rc = SQLITE_NOMEM; |
| 111341 | + goto finished; |
| 111342 | + } |
| 111343 | + pCsr->apSegment = apNew; |
| 111344 | + } |
| 111345 | + |
| 111346 | + /* If zTerm is not NULL, and this segment is not stored entirely on its |
| 111347 | + ** root node, the range of leaves scanned can be reduced. Do this. */ |
| 111348 | + if( iStartBlock && zTerm ){ |
| 111349 | + sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0); |
| 111350 | + rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi); |
| 111351 | + if( rc!=SQLITE_OK ) goto finished; |
| 111352 | + if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock; |
| 111353 | + } |
| 111354 | + |
| 111355 | + rc = sqlite3Fts3SegReaderNew(iAge, iStartBlock, iLeavesEndBlock, |
| 111356 | + iEndBlock, zRoot, nRoot, &pCsr->apSegment[pCsr->nSegment] |
| 111357 | + ); |
| 111358 | + if( rc!=SQLITE_OK ) goto finished; |
| 111359 | + pCsr->nSegment++; |
| 111360 | + iAge++; |
| 111361 | + } |
| 111362 | + } |
| 111363 | + |
| 111364 | + finished: |
| 111365 | + rc2 = sqlite3_reset(pStmt); |
| 111366 | + if( rc==SQLITE_DONE ) rc = rc2; |
| 111367 | + sqlite3Fts3SegReaderFree(pPending); |
| 111368 | + |
| 111369 | + return rc; |
| 111370 | +} |
| 111371 | + |
| 111372 | + |
| 111373 | +static int fts3TermSegReaderCursor( |
| 110536 | 111374 | Fts3Cursor *pCsr, /* Virtual table cursor handle */ |
| 110537 | 111375 | const char *zTerm, /* Term to query for */ |
| 110538 | 111376 | int nTerm, /* Size of zTerm in bytes */ |
| 110539 | 111377 | int isPrefix, /* True for a prefix search */ |
| 110540 | | - Fts3SegReaderArray **ppArray /* OUT: Allocated seg-reader array */ |
| 110541 | | -){ |
| 110542 | | - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; |
| 110543 | | - int rc; /* Return code */ |
| 110544 | | - Fts3SegReaderArray *pArray = 0; /* Array object to build */ |
| 110545 | | - Fts3SegReader *pReader = 0; /* Seg-reader to add to pArray */ |
| 110546 | | - sqlite3_stmt *pStmt = 0; /* SQL statement to scan %_segdir table */ |
| 110547 | | - int iAge = 0; /* Used to assign ages to segments */ |
| 110548 | | - |
| 110549 | | - /* Allocate a seg-reader to scan the pending terms, if any. */ |
| 110550 | | - rc = sqlite3Fts3SegReaderPending(p, zTerm, nTerm, isPrefix, &pReader); |
| 110551 | | - if( rc==SQLITE_OK && pReader ) { |
| 110552 | | - rc = fts3SegReaderArrayAdd(&pArray, pReader); |
| 110553 | | - } |
| 110554 | | - |
| 110555 | | - /* Loop through the entire %_segdir table. For each segment, create a |
| 110556 | | - ** Fts3SegReader to iterate through the subset of the segment leaves |
| 110557 | | - ** that may contain a term that matches zTerm/nTerm. For non-prefix |
| 110558 | | - ** searches, this is always a single leaf. For prefix searches, this |
| 110559 | | - ** may be a contiguous block of leaves. |
| 110560 | | - */ |
| 110561 | | - if( rc==SQLITE_OK ){ |
| 110562 | | - rc = sqlite3Fts3AllSegdirs(p, &pStmt); |
| 110563 | | - } |
| 110564 | | - while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ |
| 110565 | | - Fts3SegReader *pNew = 0; |
| 110566 | | - int nRoot = sqlite3_column_bytes(pStmt, 4); |
| 110567 | | - char const *zRoot = sqlite3_column_blob(pStmt, 4); |
| 110568 | | - if( sqlite3_column_int64(pStmt, 1)==0 ){ |
| 110569 | | - /* The entire segment is stored on the root node (which must be a |
| 110570 | | - ** leaf). Do not bother inspecting any data in this case, just |
| 110571 | | - ** create a Fts3SegReader to scan the single leaf. |
| 110572 | | - */ |
| 110573 | | - rc = sqlite3Fts3SegReaderNew(iAge, 0, 0, 0, zRoot, nRoot, &pNew); |
| 110574 | | - }else{ |
| 110575 | | - sqlite3_int64 i1; /* First leaf that may contain zTerm */ |
| 110576 | | - sqlite3_int64 i2; /* Final leaf that may contain zTerm */ |
| 110577 | | - rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1, (isPrefix?&i2:0)); |
| 110578 | | - if( isPrefix==0 ) i2 = i1; |
| 110579 | | - if( rc==SQLITE_OK ){ |
| 110580 | | - rc = sqlite3Fts3SegReaderNew(iAge, i1, i2, 0, 0, 0, &pNew); |
| 110581 | | - } |
| 110582 | | - } |
| 110583 | | - assert( (pNew==0)==(rc!=SQLITE_OK) ); |
| 110584 | | - |
| 110585 | | - /* If a new Fts3SegReader was allocated, add it to the array. */ |
| 110586 | | - if( rc==SQLITE_OK ){ |
| 110587 | | - rc = fts3SegReaderArrayAdd(&pArray, pNew); |
| 110588 | | - } |
| 110589 | | - if( rc==SQLITE_OK ){ |
| 110590 | | - rc = sqlite3Fts3SegReaderCost(pCsr, pNew, &pArray->nCost); |
| 110591 | | - } |
| 110592 | | - iAge++; |
| 110593 | | - } |
| 110594 | | - |
| 110595 | | - if( rc==SQLITE_DONE ){ |
| 110596 | | - rc = sqlite3_reset(pStmt); |
| 110597 | | - }else{ |
| 110598 | | - sqlite3_reset(pStmt); |
| 110599 | | - } |
| 110600 | | - if( rc!=SQLITE_OK ){ |
| 110601 | | - fts3SegReaderArrayFree(pArray); |
| 110602 | | - pArray = 0; |
| 110603 | | - } |
| 110604 | | - *ppArray = pArray; |
| 110605 | | - return rc; |
| 111378 | + Fts3SegReaderCursor **ppSegcsr /* OUT: Allocated seg-reader cursor */ |
| 111379 | +){ |
| 111380 | + Fts3SegReaderCursor *pSegcsr; /* Object to allocate and return */ |
| 111381 | + int rc = SQLITE_NOMEM; /* Return code */ |
| 111382 | + |
| 111383 | + pSegcsr = sqlite3_malloc(sizeof(Fts3SegReaderCursor)); |
| 111384 | + if( pSegcsr ){ |
| 111385 | + Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; |
| 111386 | + int i; |
| 111387 | + int nCost = 0; |
| 111388 | + rc = sqlite3Fts3SegReaderCursor( |
| 111389 | + p, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr); |
| 111390 | + |
| 111391 | + for(i=0; rc==SQLITE_OK && i<pSegcsr->nSegment; i++){ |
| 111392 | + rc = sqlite3Fts3SegReaderCost(pCsr, pSegcsr->apSegment[i], &nCost); |
| 111393 | + } |
| 111394 | + pSegcsr->nCost = nCost; |
| 111395 | + } |
| 111396 | + |
| 111397 | + *ppSegcsr = pSegcsr; |
| 111398 | + return rc; |
| 111399 | +} |
| 111400 | + |
| 111401 | +static void fts3SegReaderCursorFree(Fts3SegReaderCursor *pSegcsr){ |
| 111402 | + sqlite3Fts3SegReaderFinish(pSegcsr); |
| 111403 | + sqlite3_free(pSegcsr); |
| 110606 | 111404 | } |
| 110607 | 111405 | |
| 110608 | 111406 | /* |
| 110609 | 111407 | ** This function retreives the doclist for the specified term (or term |
| 110610 | 111408 | ** prefix) from the database. |
| | @@ -110623,15 +111421,15 @@ |
| 110623 | 111421 | int isReqPos, /* True to include position lists in output */ |
| 110624 | 111422 | int *pnOut, /* OUT: Size of buffer at *ppOut */ |
| 110625 | 111423 | char **ppOut /* OUT: Malloced result buffer */ |
| 110626 | 111424 | ){ |
| 110627 | 111425 | int rc; /* Return code */ |
| 110628 | | - Fts3SegReaderArray *pArray; /* Seg-reader array for this term */ |
| 110629 | | - TermSelect tsc; /* Context object for fts3TermSelectCb() */ |
| 110630 | | - Fts3SegFilter filter; /* Segment term filter configuration */ |
| 111426 | + Fts3SegReaderCursor *pSegcsr; /* Seg-reader cursor for this term */ |
| 111427 | + TermSelect tsc; /* Context object for fts3TermSelectCb() */ |
| 111428 | + Fts3SegFilter filter; /* Segment term filter configuration */ |
| 110631 | 111429 | |
| 110632 | | - pArray = pTok->pArray; |
| 111430 | + pSegcsr = pTok->pSegcsr; |
| 110633 | 111431 | memset(&tsc, 0, sizeof(TermSelect)); |
| 110634 | 111432 | tsc.isReqPos = isReqPos; |
| 110635 | 111433 | |
| 110636 | 111434 | filter.flags = FTS3_SEGMENT_IGNORE_EMPTY |
| 110637 | 111435 | | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0) |
| | @@ -110639,17 +111437,22 @@ |
| 110639 | 111437 | | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0); |
| 110640 | 111438 | filter.iCol = iColumn; |
| 110641 | 111439 | filter.zTerm = pTok->z; |
| 110642 | 111440 | filter.nTerm = pTok->n; |
| 110643 | 111441 | |
| 110644 | | - rc = sqlite3Fts3SegReaderIterate(p, pArray->apSegment, pArray->nSegment, |
| 110645 | | - &filter, fts3TermSelectCb, (void *)&tsc |
| 110646 | | - ); |
| 111442 | + rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter); |
| 111443 | + while( SQLITE_OK==rc |
| 111444 | + && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr)) |
| 111445 | + ){ |
| 111446 | + rc = fts3TermSelectCb(p, (void *)&tsc, |
| 111447 | + pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist |
| 111448 | + ); |
| 111449 | + } |
| 111450 | + |
| 110647 | 111451 | if( rc==SQLITE_OK ){ |
| 110648 | 111452 | rc = fts3TermSelectMerge(&tsc); |
| 110649 | 111453 | } |
| 110650 | | - |
| 110651 | 111454 | if( rc==SQLITE_OK ){ |
| 110652 | 111455 | *ppOut = tsc.aaOutput[0]; |
| 110653 | 111456 | *pnOut = tsc.anOutput[0]; |
| 110654 | 111457 | }else{ |
| 110655 | 111458 | int i; |
| | @@ -110656,12 +111459,12 @@ |
| 110656 | 111459 | for(i=0; i<SizeofArray(tsc.aaOutput); i++){ |
| 110657 | 111460 | sqlite3_free(tsc.aaOutput[i]); |
| 110658 | 111461 | } |
| 110659 | 111462 | } |
| 110660 | 111463 | |
| 110661 | | - fts3SegReaderArrayFree(pArray); |
| 110662 | | - pTok->pArray = 0; |
| 111464 | + fts3SegReaderCursorFree(pSegcsr); |
| 111465 | + pTok->pSegcsr = 0; |
| 110663 | 111466 | return rc; |
| 110664 | 111467 | } |
| 110665 | 111468 | |
| 110666 | 111469 | /* |
| 110667 | 111470 | ** This function counts the total number of docids in the doclist stored |
| | @@ -110780,17 +111583,17 @@ |
| 110780 | 111583 | ** evaluation, only create segment-readers if there are no Fts3DeferredToken |
| 110781 | 111584 | ** objects attached to the phrase-tokens. |
| 110782 | 111585 | */ |
| 110783 | 111586 | for(ii=0; ii<pPhrase->nToken; ii++){ |
| 110784 | 111587 | Fts3PhraseToken *pTok = &pPhrase->aToken[ii]; |
| 110785 | | - if( pTok->pArray==0 ){ |
| 111588 | + if( pTok->pSegcsr==0 ){ |
| 110786 | 111589 | if( (pCsr->eEvalmode==FTS3_EVAL_FILTER) |
| 110787 | 111590 | || (pCsr->eEvalmode==FTS3_EVAL_NEXT && pCsr->pDeferred==0) |
| 110788 | 111591 | || (pCsr->eEvalmode==FTS3_EVAL_MATCHINFO && pTok->bFulltext) |
| 110789 | 111592 | ){ |
| 110790 | | - rc = fts3TermSegReaderArray( |
| 110791 | | - pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pArray |
| 111593 | + rc = fts3TermSegReaderCursor( |
| 111594 | + pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pSegcsr |
| 110792 | 111595 | ); |
| 110793 | 111596 | if( rc!=SQLITE_OK ) return rc; |
| 110794 | 111597 | } |
| 110795 | 111598 | } |
| 110796 | 111599 | } |
| | @@ -110817,14 +111620,14 @@ |
| 110817 | 111620 | int nMinCost = 0x7FFFFFFF; |
| 110818 | 111621 | int jj; |
| 110819 | 111622 | |
| 110820 | 111623 | /* Find the remaining token with the lowest cost. */ |
| 110821 | 111624 | for(jj=0; jj<pPhrase->nToken; jj++){ |
| 110822 | | - Fts3SegReaderArray *pArray = pPhrase->aToken[jj].pArray; |
| 110823 | | - if( pArray && pArray->nCost<nMinCost ){ |
| 111625 | + Fts3SegReaderCursor *pSegcsr = pPhrase->aToken[jj].pSegcsr; |
| 111626 | + if( pSegcsr && pSegcsr->nCost<nMinCost ){ |
| 110824 | 111627 | iTok = jj; |
| 110825 | | - nMinCost = pArray->nCost; |
| 111628 | + nMinCost = pSegcsr->nCost; |
| 110826 | 111629 | } |
| 110827 | 111630 | } |
| 110828 | 111631 | pTok = &pPhrase->aToken[iTok]; |
| 110829 | 111632 | |
| 110830 | 111633 | /* This branch is taken if it is determined that loading the doclist |
| | @@ -110839,16 +111642,16 @@ |
| 110839 | 111642 | } |
| 110840 | 111643 | |
| 110841 | 111644 | if( pCsr->eEvalmode==FTS3_EVAL_NEXT && pTok->pDeferred ){ |
| 110842 | 111645 | rc = fts3DeferredTermSelect(pTok->pDeferred, isTermPos, &nList, &pList); |
| 110843 | 111646 | }else{ |
| 110844 | | - if( pTok->pArray ){ |
| 111647 | + if( pTok->pSegcsr ){ |
| 110845 | 111648 | rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList); |
| 110846 | 111649 | } |
| 110847 | 111650 | pTok->bFulltext = 1; |
| 110848 | 111651 | } |
| 110849 | | - assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pArray==0 ); |
| 111652 | + assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pSegcsr==0 ); |
| 110850 | 111653 | if( rc!=SQLITE_OK ) break; |
| 110851 | 111654 | |
| 110852 | 111655 | if( isFirst ){ |
| 110853 | 111656 | pOut = pList; |
| 110854 | 111657 | nOut = nList; |
| | @@ -111022,13 +111825,13 @@ |
| 111022 | 111825 | Fts3Phrase *pPhrase = pExpr->pPhrase; |
| 111023 | 111826 | int ii; |
| 111024 | 111827 | |
| 111025 | 111828 | for(ii=0; rc==SQLITE_OK && ii<pPhrase->nToken; ii++){ |
| 111026 | 111829 | Fts3PhraseToken *pTok = &pPhrase->aToken[ii]; |
| 111027 | | - if( pTok->pArray==0 ){ |
| 111028 | | - rc = fts3TermSegReaderArray( |
| 111029 | | - pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pArray |
| 111830 | + if( pTok->pSegcsr==0 ){ |
| 111831 | + rc = fts3TermSegReaderCursor( |
| 111832 | + pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pSegcsr |
| 111030 | 111833 | ); |
| 111031 | 111834 | } |
| 111032 | 111835 | } |
| 111033 | 111836 | }else{ |
| 111034 | 111837 | rc = fts3ExprAllocateSegReaders(pCsr, pExpr->pLeft, pnExpr); |
| | @@ -111048,12 +111851,12 @@ |
| 111048 | 111851 | if( pExpr ){ |
| 111049 | 111852 | Fts3Phrase *pPhrase = pExpr->pPhrase; |
| 111050 | 111853 | if( pPhrase ){ |
| 111051 | 111854 | int kk; |
| 111052 | 111855 | for(kk=0; kk<pPhrase->nToken; kk++){ |
| 111053 | | - fts3SegReaderArrayFree(pPhrase->aToken[kk].pArray); |
| 111054 | | - pPhrase->aToken[kk].pArray = 0; |
| 111856 | + fts3SegReaderCursorFree(pPhrase->aToken[kk].pSegcsr); |
| 111857 | + pPhrase->aToken[kk].pSegcsr = 0; |
| 111055 | 111858 | } |
| 111056 | 111859 | } |
| 111057 | 111860 | fts3ExprFreeSegReaders(pExpr->pLeft); |
| 111058 | 111861 | fts3ExprFreeSegReaders(pExpr->pRight); |
| 111059 | 111862 | } |
| | @@ -111069,14 +111872,12 @@ |
| 111069 | 111872 | if( pExpr->eType==FTSQUERY_PHRASE ){ |
| 111070 | 111873 | Fts3Phrase *pPhrase = pExpr->pPhrase; |
| 111071 | 111874 | int ii; |
| 111072 | 111875 | nCost = 0; |
| 111073 | 111876 | for(ii=0; ii<pPhrase->nToken; ii++){ |
| 111074 | | - Fts3SegReaderArray *pArray = pPhrase->aToken[ii].pArray; |
| 111075 | | - if( pArray ){ |
| 111076 | | - nCost += pPhrase->aToken[ii].pArray->nCost; |
| 111077 | | - } |
| 111877 | + Fts3SegReaderCursor *pSegcsr = pPhrase->aToken[ii].pSegcsr; |
| 111878 | + if( pSegcsr ) nCost += pSegcsr->nCost; |
| 111078 | 111879 | } |
| 111079 | 111880 | }else{ |
| 111080 | 111881 | nCost = fts3ExprCost(pExpr->pLeft) + fts3ExprCost(pExpr->pRight); |
| 111081 | 111882 | } |
| 111082 | 111883 | return nCost; |
| | @@ -111414,12 +112215,12 @@ |
| 111414 | 112215 | const char *idxStr, /* Unused */ |
| 111415 | 112216 | int nVal, /* Number of elements in apVal */ |
| 111416 | 112217 | sqlite3_value **apVal /* Arguments for the indexing scheme */ |
| 111417 | 112218 | ){ |
| 111418 | 112219 | const char *azSql[] = { |
| 111419 | | - "SELECT * FROM %Q.'%q_content' WHERE docid = ?", /* non-full-table-scan */ |
| 111420 | | - "SELECT * FROM %Q.'%q_content'", /* full-table-scan */ |
| 112220 | + "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?", /* non-full-scan */ |
| 112221 | + "SELECT %s FROM %Q.'%q_content' AS x ", /* full-scan */ |
| 111421 | 112222 | }; |
| 111422 | 112223 | int rc; /* Return code */ |
| 111423 | 112224 | char *zSql; /* SQL statement used to access %_content */ |
| 111424 | 112225 | Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
| 111425 | 112226 | Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
| | @@ -111470,11 +112271,12 @@ |
| 111470 | 112271 | /* Compile a SELECT statement for this cursor. For a full-table-scan, the |
| 111471 | 112272 | ** statement loops through all rows of the %_content table. For a |
| 111472 | 112273 | ** full-text query or docid lookup, the statement retrieves a single |
| 111473 | 112274 | ** row by docid. |
| 111474 | 112275 | */ |
| 111475 | | - zSql = sqlite3_mprintf(azSql[idxNum==FTS3_FULLSCAN_SEARCH], p->zDb, p->zName); |
| 112276 | + zSql = (char *)azSql[idxNum==FTS3_FULLSCAN_SEARCH]; |
| 112277 | + zSql = sqlite3_mprintf(zSql, p->zReadExprlist, p->zDb, p->zName); |
| 111476 | 112278 | if( !zSql ){ |
| 111477 | 112279 | rc = SQLITE_NOMEM; |
| 111478 | 112280 | }else{ |
| 111479 | 112281 | rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
| 111480 | 112282 | sqlite3_free(zSql); |
| | @@ -111988,10 +112790,13 @@ |
| 111988 | 112790 | #ifdef SQLITE_ENABLE_ICU |
| 111989 | 112791 | const sqlite3_tokenizer_module *pIcu = 0; |
| 111990 | 112792 | sqlite3Fts3IcuTokenizerModule(&pIcu); |
| 111991 | 112793 | #endif |
| 111992 | 112794 | |
| 112795 | + rc = sqlite3Fts3InitAux(db); |
| 112796 | + if( rc!=SQLITE_OK ) return rc; |
| 112797 | + |
| 111993 | 112798 | sqlite3Fts3SimpleTokenizerModule(&pSimple); |
| 111994 | 112799 | sqlite3Fts3PorterTokenizerModule(&pPorter); |
| 111995 | 112800 | |
| 111996 | 112801 | /* Allocate and initialise the hash-table used to store tokenizers. */ |
| 111997 | 112802 | pHash = sqlite3_malloc(sizeof(Fts3Hash)); |
| | @@ -112063,10 +112868,472 @@ |
| 112063 | 112868 | #endif |
| 112064 | 112869 | |
| 112065 | 112870 | #endif |
| 112066 | 112871 | |
| 112067 | 112872 | /************** End of fts3.c ************************************************/ |
| 112873 | +/************** Begin file fts3_aux.c ****************************************/ |
| 112874 | +/* |
| 112875 | +** 2011 Jan 27 |
| 112876 | +** |
| 112877 | +** The author disclaims copyright to this source code. In place of |
| 112878 | +** a legal notice, here is a blessing: |
| 112879 | +** |
| 112880 | +** May you do good and not evil. |
| 112881 | +** May you find forgiveness for yourself and forgive others. |
| 112882 | +** May you share freely, never taking more than you give. |
| 112883 | +** |
| 112884 | +****************************************************************************** |
| 112885 | +** |
| 112886 | +*/ |
| 112887 | + |
| 112888 | +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 112889 | + |
| 112890 | + |
| 112891 | +typedef struct Fts3auxTable Fts3auxTable; |
| 112892 | +typedef struct Fts3auxCursor Fts3auxCursor; |
| 112893 | + |
| 112894 | +struct Fts3auxTable { |
| 112895 | + sqlite3_vtab base; /* Base class used by SQLite core */ |
| 112896 | + Fts3Table *pFts3Tab; |
| 112897 | +}; |
| 112898 | + |
| 112899 | +struct Fts3auxCursor { |
| 112900 | + sqlite3_vtab_cursor base; /* Base class used by SQLite core */ |
| 112901 | + Fts3SegReaderCursor csr; /* Must be right after "base" */ |
| 112902 | + Fts3SegFilter filter; |
| 112903 | + char *zStop; |
| 112904 | + int nStop; /* Byte-length of string zStop */ |
| 112905 | + int isEof; /* True if cursor is at EOF */ |
| 112906 | + sqlite3_int64 iRowid; /* Current rowid */ |
| 112907 | + |
| 112908 | + int iCol; /* Current value of 'col' column */ |
| 112909 | + int nStat; /* Size of aStat[] array */ |
| 112910 | + struct Fts3auxColstats { |
| 112911 | + sqlite3_int64 nDoc; /* 'documents' values for current csr row */ |
| 112912 | + sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */ |
| 112913 | + } *aStat; |
| 112914 | +}; |
| 112915 | + |
| 112916 | +/* |
| 112917 | +** Schema of the terms table. |
| 112918 | +*/ |
| 112919 | +#define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, col, documents, occurrences)" |
| 112920 | + |
| 112921 | +/* |
| 112922 | +** This function does all the work for both the xConnect and xCreate methods. |
| 112923 | +** These tables have no persistent representation of their own, so xConnect |
| 112924 | +** and xCreate are identical operations. |
| 112925 | +*/ |
| 112926 | +static int fts3auxConnectMethod( |
| 112927 | + sqlite3 *db, /* Database connection */ |
| 112928 | + void *pUnused, /* Unused */ |
| 112929 | + int argc, /* Number of elements in argv array */ |
| 112930 | + const char * const *argv, /* xCreate/xConnect argument array */ |
| 112931 | + sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ |
| 112932 | + char **pzErr /* OUT: sqlite3_malloc'd error message */ |
| 112933 | +){ |
| 112934 | + char const *zDb; /* Name of database (e.g. "main") */ |
| 112935 | + char const *zFts3; /* Name of fts3 table */ |
| 112936 | + int nDb; /* Result of strlen(zDb) */ |
| 112937 | + int nFts3; /* Result of strlen(zFts3) */ |
| 112938 | + int nByte; /* Bytes of space to allocate here */ |
| 112939 | + int rc; /* value returned by declare_vtab() */ |
| 112940 | + Fts3auxTable *p; /* Virtual table object to return */ |
| 112941 | + |
| 112942 | + /* The user should specify a single argument - the name of an fts3 table. */ |
| 112943 | + if( argc!=4 ){ |
| 112944 | + *pzErr = sqlite3_mprintf( |
| 112945 | + "wrong number of arguments to fts4aux constructor" |
| 112946 | + ); |
| 112947 | + return SQLITE_ERROR; |
| 112948 | + } |
| 112949 | + |
| 112950 | + zDb = argv[1]; |
| 112951 | + nDb = strlen(zDb); |
| 112952 | + zFts3 = argv[3]; |
| 112953 | + nFts3 = strlen(zFts3); |
| 112954 | + |
| 112955 | + rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA); |
| 112956 | + if( rc!=SQLITE_OK ) return rc; |
| 112957 | + |
| 112958 | + nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2; |
| 112959 | + p = (Fts3auxTable *)sqlite3_malloc(nByte); |
| 112960 | + if( !p ) return SQLITE_NOMEM; |
| 112961 | + memset(p, 0, nByte); |
| 112962 | + |
| 112963 | + p->pFts3Tab = (Fts3Table *)&p[1]; |
| 112964 | + p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1]; |
| 112965 | + p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1]; |
| 112966 | + p->pFts3Tab->db = db; |
| 112967 | + |
| 112968 | + memcpy((char *)p->pFts3Tab->zDb, zDb, nDb); |
| 112969 | + memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3); |
| 112970 | + sqlite3Fts3Dequote((char *)p->pFts3Tab->zName); |
| 112971 | + |
| 112972 | + *ppVtab = (sqlite3_vtab *)p; |
| 112973 | + return SQLITE_OK; |
| 112974 | +} |
| 112975 | + |
| 112976 | +/* |
| 112977 | +** This function does the work for both the xDisconnect and xDestroy methods. |
| 112978 | +** These tables have no persistent representation of their own, so xDisconnect |
| 112979 | +** and xDestroy are identical operations. |
| 112980 | +*/ |
| 112981 | +static int fts3auxDisconnectMethod(sqlite3_vtab *pVtab){ |
| 112982 | + Fts3auxTable *p = (Fts3auxTable *)pVtab; |
| 112983 | + Fts3Table *pFts3 = p->pFts3Tab; |
| 112984 | + int i; |
| 112985 | + |
| 112986 | + /* Free any prepared statements held */ |
| 112987 | + for(i=0; i<SizeofArray(pFts3->aStmt); i++){ |
| 112988 | + sqlite3_finalize(pFts3->aStmt[i]); |
| 112989 | + } |
| 112990 | + sqlite3_free(pFts3->zSegmentsTbl); |
| 112991 | + sqlite3_free(p); |
| 112992 | + return SQLITE_OK; |
| 112993 | +} |
| 112994 | + |
| 112995 | +#define FTS4AUX_EQ_CONSTRAINT 1 |
| 112996 | +#define FTS4AUX_GE_CONSTRAINT 2 |
| 112997 | +#define FTS4AUX_LE_CONSTRAINT 4 |
| 112998 | + |
| 112999 | +/* |
| 113000 | +** xBestIndex - Analyze a WHERE and ORDER BY clause. |
| 113001 | +*/ |
| 113002 | +static int fts3auxBestIndexMethod( |
| 113003 | + sqlite3_vtab *pVTab, |
| 113004 | + sqlite3_index_info *pInfo |
| 113005 | +){ |
| 113006 | + int i; |
| 113007 | + int iEq = -1; |
| 113008 | + int iGe = -1; |
| 113009 | + int iLe = -1; |
| 113010 | + |
| 113011 | + /* This vtab delivers always results in "ORDER BY term ASC" order. */ |
| 113012 | + if( pInfo->nOrderBy==1 |
| 113013 | + && pInfo->aOrderBy[0].iColumn==0 |
| 113014 | + && pInfo->aOrderBy[0].desc==0 |
| 113015 | + ){ |
| 113016 | + pInfo->orderByConsumed = 1; |
| 113017 | + } |
| 113018 | + |
| 113019 | + /* Search for equality and range constraints on the "term" column. */ |
| 113020 | + for(i=0; i<pInfo->nConstraint; i++){ |
| 113021 | + if( pInfo->aConstraint[i].usable && pInfo->aConstraint[i].iColumn==0 ){ |
| 113022 | + int op = pInfo->aConstraint[i].op; |
| 113023 | + if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i; |
| 113024 | + if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i; |
| 113025 | + if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i; |
| 113026 | + if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i; |
| 113027 | + if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i; |
| 113028 | + } |
| 113029 | + } |
| 113030 | + |
| 113031 | + if( iEq>=0 ){ |
| 113032 | + pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT; |
| 113033 | + pInfo->aConstraintUsage[iEq].argvIndex = 1; |
| 113034 | + pInfo->estimatedCost = 5; |
| 113035 | + }else{ |
| 113036 | + pInfo->idxNum = 0; |
| 113037 | + pInfo->estimatedCost = 20000; |
| 113038 | + if( iGe>=0 ){ |
| 113039 | + pInfo->idxNum += FTS4AUX_GE_CONSTRAINT; |
| 113040 | + pInfo->aConstraintUsage[iGe].argvIndex = 1; |
| 113041 | + pInfo->estimatedCost /= 2; |
| 113042 | + } |
| 113043 | + if( iLe>=0 ){ |
| 113044 | + pInfo->idxNum += FTS4AUX_LE_CONSTRAINT; |
| 113045 | + pInfo->aConstraintUsage[iLe].argvIndex = 1 + (iGe>=0); |
| 113046 | + pInfo->estimatedCost /= 2; |
| 113047 | + } |
| 113048 | + } |
| 113049 | + |
| 113050 | + return SQLITE_OK; |
| 113051 | +} |
| 113052 | + |
| 113053 | +/* |
| 113054 | +** xOpen - Open a cursor. |
| 113055 | +*/ |
| 113056 | +static int fts3auxOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ |
| 113057 | + Fts3auxCursor *pCsr; /* Pointer to cursor object to return */ |
| 113058 | + |
| 113059 | + pCsr = (Fts3auxCursor *)sqlite3_malloc(sizeof(Fts3auxCursor)); |
| 113060 | + if( !pCsr ) return SQLITE_NOMEM; |
| 113061 | + memset(pCsr, 0, sizeof(Fts3auxCursor)); |
| 113062 | + |
| 113063 | + *ppCsr = (sqlite3_vtab_cursor *)pCsr; |
| 113064 | + return SQLITE_OK; |
| 113065 | +} |
| 113066 | + |
| 113067 | +/* |
| 113068 | +** xClose - Close a cursor. |
| 113069 | +*/ |
| 113070 | +static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){ |
| 113071 | + Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; |
| 113072 | + Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; |
| 113073 | + |
| 113074 | + sqlite3Fts3SegmentsClose(pFts3); |
| 113075 | + sqlite3Fts3SegReaderFinish(&pCsr->csr); |
| 113076 | + sqlite3_free((void *)pCsr->filter.zTerm); |
| 113077 | + sqlite3_free(pCsr->zStop); |
| 113078 | + sqlite3_free(pCsr->aStat); |
| 113079 | + sqlite3_free(pCsr); |
| 113080 | + return SQLITE_OK; |
| 113081 | +} |
| 113082 | + |
| 113083 | +static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){ |
| 113084 | + if( nSize>pCsr->nStat ){ |
| 113085 | + struct Fts3auxColstats *aNew; |
| 113086 | + aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat, |
| 113087 | + sizeof(struct Fts3auxColstats) * nSize |
| 113088 | + ); |
| 113089 | + if( aNew==0 ) return SQLITE_NOMEM; |
| 113090 | + memset(&aNew[pCsr->nStat], 0, |
| 113091 | + sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat) |
| 113092 | + ); |
| 113093 | + pCsr->aStat = aNew; |
| 113094 | + pCsr->nStat = nSize; |
| 113095 | + } |
| 113096 | + return SQLITE_OK; |
| 113097 | +} |
| 113098 | + |
| 113099 | +/* |
| 113100 | +** xNext - Advance the cursor to the next row, if any. |
| 113101 | +*/ |
| 113102 | +static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){ |
| 113103 | + Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; |
| 113104 | + Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; |
| 113105 | + int rc; |
| 113106 | + |
| 113107 | + /* Increment our pretend rowid value. */ |
| 113108 | + pCsr->iRowid++; |
| 113109 | + |
| 113110 | + for(pCsr->iCol++; pCsr->iCol<pCsr->nStat; pCsr->iCol++){ |
| 113111 | + if( pCsr->aStat[pCsr->iCol].nDoc>0 ) return SQLITE_OK; |
| 113112 | + } |
| 113113 | + |
| 113114 | + rc = sqlite3Fts3SegReaderStep(pFts3, &pCsr->csr); |
| 113115 | + if( rc==SQLITE_ROW ){ |
| 113116 | + int i = 0; |
| 113117 | + int nDoclist = pCsr->csr.nDoclist; |
| 113118 | + char *aDoclist = pCsr->csr.aDoclist; |
| 113119 | + int iCol; |
| 113120 | + |
| 113121 | + int eState = 0; |
| 113122 | + |
| 113123 | + if( pCsr->zStop ){ |
| 113124 | + int n = (pCsr->nStop<pCsr->csr.nTerm) ? pCsr->nStop : pCsr->csr.nTerm; |
| 113125 | + int mc = memcmp(pCsr->zStop, pCsr->csr.zTerm, n); |
| 113126 | + if( mc<0 || (mc==0 && pCsr->csr.nTerm>pCsr->nStop) ){ |
| 113127 | + pCsr->isEof = 1; |
| 113128 | + return SQLITE_OK; |
| 113129 | + } |
| 113130 | + } |
| 113131 | + |
| 113132 | + if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM; |
| 113133 | + memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat); |
| 113134 | + iCol = 0; |
| 113135 | + |
| 113136 | + while( i<nDoclist ){ |
| 113137 | + sqlite3_int64 v = 0; |
| 113138 | + |
| 113139 | + i += sqlite3Fts3GetVarint(&aDoclist[i], &v); |
| 113140 | + switch( eState ){ |
| 113141 | + /* State 0. In this state the integer just read was a docid. */ |
| 113142 | + case 0: |
| 113143 | + pCsr->aStat[0].nDoc++; |
| 113144 | + eState = 1; |
| 113145 | + iCol = 0; |
| 113146 | + break; |
| 113147 | + |
| 113148 | + /* State 1. In this state we are expecting either a 1, indicating |
| 113149 | + ** that the following integer will be a column number, or the |
| 113150 | + ** start of a position list for column 0. |
| 113151 | + ** |
| 113152 | + ** The only difference between state 1 and state 2 is that if the |
| 113153 | + ** integer encountered in state 1 is not 0 or 1, then we need to |
| 113154 | + ** increment the column 0 "nDoc" count for this term. |
| 113155 | + */ |
| 113156 | + case 1: |
| 113157 | + assert( iCol==0 ); |
| 113158 | + if( v>1 ){ |
| 113159 | + pCsr->aStat[1].nDoc++; |
| 113160 | + } |
| 113161 | + eState = 2; |
| 113162 | + /* fall through */ |
| 113163 | + |
| 113164 | + case 2: |
| 113165 | + if( v==0 ){ /* 0x00. Next integer will be a docid. */ |
| 113166 | + eState = 0; |
| 113167 | + }else if( v==1 ){ /* 0x01. Next integer will be a column number. */ |
| 113168 | + eState = 3; |
| 113169 | + }else{ /* 2 or greater. A position. */ |
| 113170 | + pCsr->aStat[iCol+1].nOcc++; |
| 113171 | + pCsr->aStat[0].nOcc++; |
| 113172 | + } |
| 113173 | + break; |
| 113174 | + |
| 113175 | + /* State 3. The integer just read is a column number. */ |
| 113176 | + default: assert( eState==3 ); |
| 113177 | + iCol = (int)v; |
| 113178 | + if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM; |
| 113179 | + pCsr->aStat[iCol+1].nDoc++; |
| 113180 | + eState = 2; |
| 113181 | + break; |
| 113182 | + } |
| 113183 | + } |
| 113184 | + |
| 113185 | + pCsr->iCol = 0; |
| 113186 | + rc = SQLITE_OK; |
| 113187 | + }else{ |
| 113188 | + pCsr->isEof = 1; |
| 113189 | + } |
| 113190 | + return rc; |
| 113191 | +} |
| 113192 | + |
| 113193 | +/* |
| 113194 | +** xFilter - Initialize a cursor to point at the start of its data. |
| 113195 | +*/ |
| 113196 | +static int fts3auxFilterMethod( |
| 113197 | + sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ |
| 113198 | + int idxNum, /* Strategy index */ |
| 113199 | + const char *idxStr, /* Unused */ |
| 113200 | + int nVal, /* Number of elements in apVal */ |
| 113201 | + sqlite3_value **apVal /* Arguments for the indexing scheme */ |
| 113202 | +){ |
| 113203 | + Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; |
| 113204 | + Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; |
| 113205 | + int rc; |
| 113206 | + int isScan; |
| 113207 | + |
| 113208 | + assert( idxStr==0 ); |
| 113209 | + assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0 |
| 113210 | + || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT |
| 113211 | + || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) |
| 113212 | + ); |
| 113213 | + isScan = (idxNum!=FTS4AUX_EQ_CONSTRAINT); |
| 113214 | + |
| 113215 | + /* In case this cursor is being reused, close and zero it. */ |
| 113216 | + testcase(pCsr->filter.zTerm); |
| 113217 | + sqlite3Fts3SegReaderFinish(&pCsr->csr); |
| 113218 | + sqlite3_free((void *)pCsr->filter.zTerm); |
| 113219 | + sqlite3_free(pCsr->aStat); |
| 113220 | + memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr); |
| 113221 | + |
| 113222 | + pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; |
| 113223 | + if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN; |
| 113224 | + |
| 113225 | + if( idxNum&(FTS4AUX_EQ_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ){ |
| 113226 | + const unsigned char *zStr = sqlite3_value_text(apVal[0]); |
| 113227 | + if( zStr ){ |
| 113228 | + pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr); |
| 113229 | + pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]); |
| 113230 | + if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM; |
| 113231 | + } |
| 113232 | + } |
| 113233 | + if( idxNum&FTS4AUX_LE_CONSTRAINT ){ |
| 113234 | + int iIdx = (idxNum&FTS4AUX_GE_CONSTRAINT) ? 1 : 0; |
| 113235 | + pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx])); |
| 113236 | + pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]); |
| 113237 | + if( pCsr->zStop==0 ) return SQLITE_NOMEM; |
| 113238 | + } |
| 113239 | + |
| 113240 | + rc = sqlite3Fts3SegReaderCursor(pFts3, FTS3_SEGCURSOR_ALL, |
| 113241 | + pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr |
| 113242 | + ); |
| 113243 | + if( rc==SQLITE_OK ){ |
| 113244 | + rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter); |
| 113245 | + } |
| 113246 | + |
| 113247 | + if( rc==SQLITE_OK ) rc = fts3auxNextMethod(pCursor); |
| 113248 | + return rc; |
| 113249 | +} |
| 113250 | + |
| 113251 | +/* |
| 113252 | +** xEof - Return true if the cursor is at EOF, or false otherwise. |
| 113253 | +*/ |
| 113254 | +static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){ |
| 113255 | + Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; |
| 113256 | + return pCsr->isEof; |
| 113257 | +} |
| 113258 | + |
| 113259 | +/* |
| 113260 | +** xColumn - Return a column value. |
| 113261 | +*/ |
| 113262 | +static int fts3auxColumnMethod( |
| 113263 | + sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ |
| 113264 | + sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */ |
| 113265 | + int iCol /* Index of column to read value from */ |
| 113266 | +){ |
| 113267 | + Fts3auxCursor *p = (Fts3auxCursor *)pCursor; |
| 113268 | + |
| 113269 | + assert( p->isEof==0 ); |
| 113270 | + if( iCol==0 ){ /* Column "term" */ |
| 113271 | + sqlite3_result_text(pContext, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT); |
| 113272 | + }else if( iCol==1 ){ /* Column "col" */ |
| 113273 | + if( p->iCol ){ |
| 113274 | + sqlite3_result_int(pContext, p->iCol-1); |
| 113275 | + }else{ |
| 113276 | + sqlite3_result_text(pContext, "*", -1, SQLITE_STATIC); |
| 113277 | + } |
| 113278 | + }else if( iCol==2 ){ /* Column "documents" */ |
| 113279 | + sqlite3_result_int64(pContext, p->aStat[p->iCol].nDoc); |
| 113280 | + }else{ /* Column "occurrences" */ |
| 113281 | + sqlite3_result_int64(pContext, p->aStat[p->iCol].nOcc); |
| 113282 | + } |
| 113283 | + |
| 113284 | + return SQLITE_OK; |
| 113285 | +} |
| 113286 | + |
| 113287 | +/* |
| 113288 | +** xRowid - Return the current rowid for the cursor. |
| 113289 | +*/ |
| 113290 | +static int fts3auxRowidMethod( |
| 113291 | + sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ |
| 113292 | + sqlite_int64 *pRowid /* OUT: Rowid value */ |
| 113293 | +){ |
| 113294 | + Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; |
| 113295 | + *pRowid = pCsr->iRowid; |
| 113296 | + return SQLITE_OK; |
| 113297 | +} |
| 113298 | + |
| 113299 | +/* |
| 113300 | +** Register the fts3aux module with database connection db. Return SQLITE_OK |
| 113301 | +** if successful or an error code if sqlite3_create_module() fails. |
| 113302 | +*/ |
| 113303 | +SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){ |
| 113304 | + static const sqlite3_module fts3aux_module = { |
| 113305 | + 0, /* iVersion */ |
| 113306 | + fts3auxConnectMethod, /* xCreate */ |
| 113307 | + fts3auxConnectMethod, /* xConnect */ |
| 113308 | + fts3auxBestIndexMethod, /* xBestIndex */ |
| 113309 | + fts3auxDisconnectMethod, /* xDisconnect */ |
| 113310 | + fts3auxDisconnectMethod, /* xDestroy */ |
| 113311 | + fts3auxOpenMethod, /* xOpen */ |
| 113312 | + fts3auxCloseMethod, /* xClose */ |
| 113313 | + fts3auxFilterMethod, /* xFilter */ |
| 113314 | + fts3auxNextMethod, /* xNext */ |
| 113315 | + fts3auxEofMethod, /* xEof */ |
| 113316 | + fts3auxColumnMethod, /* xColumn */ |
| 113317 | + fts3auxRowidMethod, /* xRowid */ |
| 113318 | + 0, /* xUpdate */ |
| 113319 | + 0, /* xBegin */ |
| 113320 | + 0, /* xSync */ |
| 113321 | + 0, /* xCommit */ |
| 113322 | + 0, /* xRollback */ |
| 113323 | + 0, /* xFindFunction */ |
| 113324 | + 0 /* xRename */ |
| 113325 | + }; |
| 113326 | + int rc; /* Return code */ |
| 113327 | + |
| 113328 | + rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0); |
| 113329 | + return rc; |
| 113330 | +} |
| 113331 | + |
| 113332 | +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ |
| 113333 | + |
| 113334 | +/************** End of fts3_aux.c ********************************************/ |
| 112068 | 113335 | /************** Begin file fts3_expr.c ***************************************/ |
| 112069 | 113336 | /* |
| 112070 | 113337 | ** 2008 Nov 28 |
| 112071 | 113338 | ** |
| 112072 | 113339 | ** The author disclaims copyright to this source code. In place of |
| | @@ -114956,11 +116223,11 @@ |
| 114956 | 116223 | /* 2 */ "DELETE FROM %Q.'%q_content'", |
| 114957 | 116224 | /* 3 */ "DELETE FROM %Q.'%q_segments'", |
| 114958 | 116225 | /* 4 */ "DELETE FROM %Q.'%q_segdir'", |
| 114959 | 116226 | /* 5 */ "DELETE FROM %Q.'%q_docsize'", |
| 114960 | 116227 | /* 6 */ "DELETE FROM %Q.'%q_stat'", |
| 114961 | | -/* 7 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?", |
| 116228 | +/* 7 */ "SELECT %s FROM %Q.'%q_content' AS x WHERE rowid=?", |
| 114962 | 116229 | /* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1", |
| 114963 | 116230 | /* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", |
| 114964 | 116231 | /* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)", |
| 114965 | 116232 | /* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", |
| 114966 | 116233 | |
| | @@ -114973,11 +116240,11 @@ |
| 114973 | 116240 | /* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", |
| 114974 | 116241 | /* 15 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'", |
| 114975 | 116242 | |
| 114976 | 116243 | /* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?", |
| 114977 | 116244 | /* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?", |
| 114978 | | -/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%z)", |
| 116245 | +/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)", |
| 114979 | 116246 | /* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", |
| 114980 | 116247 | /* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", |
| 114981 | 116248 | /* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", |
| 114982 | 116249 | /* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0", |
| 114983 | 116250 | /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)", |
| | @@ -114990,24 +116257,13 @@ |
| 114990 | 116257 | |
| 114991 | 116258 | pStmt = p->aStmt[eStmt]; |
| 114992 | 116259 | if( !pStmt ){ |
| 114993 | 116260 | char *zSql; |
| 114994 | 116261 | if( eStmt==SQL_CONTENT_INSERT ){ |
| 114995 | | - int i; /* Iterator variable */ |
| 114996 | | - char *zVarlist; /* The "?, ?, ..." string */ |
| 114997 | | - zVarlist = (char *)sqlite3_malloc(2*p->nColumn+2); |
| 114998 | | - if( !zVarlist ){ |
| 114999 | | - *pp = 0; |
| 115000 | | - return SQLITE_NOMEM; |
| 115001 | | - } |
| 115002 | | - zVarlist[0] = '?'; |
| 115003 | | - zVarlist[p->nColumn*2+1] = '\0'; |
| 115004 | | - for(i=1; i<=p->nColumn; i++){ |
| 115005 | | - zVarlist[i*2-1] = ','; |
| 115006 | | - zVarlist[i*2] = '?'; |
| 115007 | | - } |
| 115008 | | - zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, zVarlist); |
| 116262 | + zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist); |
| 116263 | + }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){ |
| 116264 | + zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist, p->zDb, p->zName); |
| 115009 | 116265 | }else{ |
| 115010 | 116266 | zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName); |
| 115011 | 116267 | } |
| 115012 | 116268 | if( !zSql ){ |
| 115013 | 116269 | rc = SQLITE_NOMEM; |
| | @@ -115044,11 +116300,11 @@ |
| 115044 | 116300 | if( rc==SQLITE_OK ){ |
| 115045 | 116301 | if( eStmt==SQL_SELECT_DOCSIZE ){ |
| 115046 | 116302 | sqlite3_bind_int64(pStmt, 1, iDocid); |
| 115047 | 116303 | } |
| 115048 | 116304 | rc = sqlite3_step(pStmt); |
| 115049 | | - if( rc!=SQLITE_ROW ){ |
| 116305 | + if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){ |
| 115050 | 116306 | rc = sqlite3_reset(pStmt); |
| 115051 | 116307 | if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT; |
| 115052 | 116308 | pStmt = 0; |
| 115053 | 116309 | }else{ |
| 115054 | 116310 | rc = SQLITE_OK; |
| | @@ -115145,12 +116401,21 @@ |
| 115145 | 116401 | ** 1: start_block |
| 115146 | 116402 | ** 2: leaves_end_block |
| 115147 | 116403 | ** 3: end_block |
| 115148 | 116404 | ** 4: root |
| 115149 | 116405 | */ |
| 115150 | | -SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table *p, sqlite3_stmt **ppStmt){ |
| 115151 | | - return fts3SqlStmt(p, SQL_SELECT_ALL_LEVEL, ppStmt, 0); |
| 116406 | +SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table *p, int iLevel, sqlite3_stmt **ppStmt){ |
| 116407 | + int rc; |
| 116408 | + sqlite3_stmt *pStmt = 0; |
| 116409 | + if( iLevel<0 ){ |
| 116410 | + rc = fts3SqlStmt(p, SQL_SELECT_ALL_LEVEL, &pStmt, 0); |
| 116411 | + }else{ |
| 116412 | + rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); |
| 116413 | + if( rc==SQLITE_OK ) sqlite3_bind_int(pStmt, 1, iLevel); |
| 116414 | + } |
| 116415 | + *ppStmt = pStmt; |
| 116416 | + return rc; |
| 115152 | 116417 | } |
| 115153 | 116418 | |
| 115154 | 116419 | |
| 115155 | 116420 | /* |
| 115156 | 116421 | ** Append a single varint to a PendingList buffer. SQLITE_OK is returned |
| | @@ -115848,20 +117113,22 @@ |
| 115848 | 117113 | ** to right. |
| 115849 | 117114 | */ |
| 115850 | 117115 | sqlite3_stmt *pStmt; |
| 115851 | 117116 | sqlite3_int64 nDoc = 0; |
| 115852 | 117117 | sqlite3_int64 nByte = 0; |
| 117118 | + const char *pEnd; |
| 115853 | 117119 | const char *a; |
| 117120 | + |
| 115854 | 117121 | rc = sqlite3Fts3SelectDoctotal(p, &pStmt); |
| 115855 | | - if( rc ) return rc; |
| 117122 | + if( rc!=SQLITE_OK ) return rc; |
| 115856 | 117123 | a = sqlite3_column_blob(pStmt, 0); |
| 115857 | | - if( a ){ |
| 115858 | | - const char *pEnd = &a[sqlite3_column_bytes(pStmt, 0)]; |
| 115859 | | - a += sqlite3Fts3GetVarint(a, &nDoc); |
| 115860 | | - while( a<pEnd ){ |
| 115861 | | - a += sqlite3Fts3GetVarint(a, &nByte); |
| 115862 | | - } |
| 117124 | + assert( a ); |
| 117125 | + |
| 117126 | + pEnd = &a[sqlite3_column_bytes(pStmt, 0)]; |
| 117127 | + a += sqlite3Fts3GetVarint(a, &nDoc); |
| 117128 | + while( a<pEnd ){ |
| 117129 | + a += sqlite3Fts3GetVarint(a, &nByte); |
| 115863 | 117130 | } |
| 115864 | 117131 | if( nDoc==0 || nByte==0 ){ |
| 115865 | 117132 | sqlite3_reset(pStmt); |
| 115866 | 117133 | return SQLITE_CORRUPT; |
| 115867 | 117134 | } |
| | @@ -116047,46 +117314,10 @@ |
| 116047 | 117314 | } |
| 116048 | 117315 | *ppReader = pReader; |
| 116049 | 117316 | return rc; |
| 116050 | 117317 | } |
| 116051 | 117318 | |
| 116052 | | - |
| 116053 | | -/* |
| 116054 | | -** The second argument to this function is expected to be a statement of |
| 116055 | | -** the form: |
| 116056 | | -** |
| 116057 | | -** SELECT |
| 116058 | | -** idx, -- col 0 |
| 116059 | | -** start_block, -- col 1 |
| 116060 | | -** leaves_end_block, -- col 2 |
| 116061 | | -** end_block, -- col 3 |
| 116062 | | -** root -- col 4 |
| 116063 | | -** FROM %_segdir ... |
| 116064 | | -** |
| 116065 | | -** This function allocates and initializes a Fts3SegReader structure to |
| 116066 | | -** iterate through the terms stored in the segment identified by the |
| 116067 | | -** current row that pStmt is pointing to. |
| 116068 | | -** |
| 116069 | | -** If successful, the Fts3SegReader is left pointing to the first term |
| 116070 | | -** in the segment and SQLITE_OK is returned. Otherwise, an SQLite error |
| 116071 | | -** code is returned. |
| 116072 | | -*/ |
| 116073 | | -static int fts3SegReaderNew( |
| 116074 | | - sqlite3_stmt *pStmt, /* See above */ |
| 116075 | | - int iAge, /* Segment "age". */ |
| 116076 | | - Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */ |
| 116077 | | -){ |
| 116078 | | - return sqlite3Fts3SegReaderNew(iAge, |
| 116079 | | - sqlite3_column_int64(pStmt, 1), |
| 116080 | | - sqlite3_column_int64(pStmt, 2), |
| 116081 | | - sqlite3_column_int64(pStmt, 3), |
| 116082 | | - sqlite3_column_blob(pStmt, 4), |
| 116083 | | - sqlite3_column_bytes(pStmt, 4), |
| 116084 | | - ppReader |
| 116085 | | - ); |
| 116086 | | -} |
| 116087 | | - |
| 116088 | 117319 | /* |
| 116089 | 117320 | ** Compare the entries pointed to by two Fts3SegReader structures. |
| 116090 | 117321 | ** Comparison is as follows: |
| 116091 | 117322 | ** |
| 116092 | 117323 | ** 1) EOF is greater than not EOF. |
| | @@ -116687,29 +117918,10 @@ |
| 116687 | 117918 | rc = sqlite3_reset(pStmt); |
| 116688 | 117919 | } |
| 116689 | 117920 | return rc; |
| 116690 | 117921 | } |
| 116691 | 117922 | |
| 116692 | | -/* |
| 116693 | | -** Set *pnSegment to the number of segments of level iLevel in the database. |
| 116694 | | -** |
| 116695 | | -** Return SQLITE_OK if successful, or an SQLite error code if not. |
| 116696 | | -*/ |
| 116697 | | -static int fts3SegmentCount(Fts3Table *p, int iLevel, int *pnSegment){ |
| 116698 | | - sqlite3_stmt *pStmt; |
| 116699 | | - int rc; |
| 116700 | | - |
| 116701 | | - assert( iLevel>=0 ); |
| 116702 | | - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_COUNT, &pStmt, 0); |
| 116703 | | - if( rc!=SQLITE_OK ) return rc; |
| 116704 | | - sqlite3_bind_int(pStmt, 1, iLevel); |
| 116705 | | - if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 116706 | | - *pnSegment = sqlite3_column_int(pStmt, 0); |
| 116707 | | - } |
| 116708 | | - return sqlite3_reset(pStmt); |
| 116709 | | -} |
| 116710 | | - |
| 116711 | 117923 | /* |
| 116712 | 117924 | ** Set *pnSegment to the total number of segments in the database. Set |
| 116713 | 117925 | ** *pnMax to the largest segment level in the database (segment levels |
| 116714 | 117926 | ** are stored in the 'level' column of the %_segdir table). |
| 116715 | 117927 | ** |
| | @@ -116764,19 +117976,22 @@ |
| 116764 | 117976 | } |
| 116765 | 117977 | if( rc!=SQLITE_OK ){ |
| 116766 | 117978 | return rc; |
| 116767 | 117979 | } |
| 116768 | 117980 | |
| 116769 | | - if( iLevel>=0 ){ |
| 117981 | + if( iLevel==FTS3_SEGCURSOR_ALL ){ |
| 117982 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); |
| 117983 | + }else if( iLevel==FTS3_SEGCURSOR_PENDING ){ |
| 117984 | + sqlite3Fts3PendingTermsClear(p); |
| 117985 | + }else{ |
| 117986 | + assert( iLevel>=0 ); |
| 116770 | 117987 | rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_BY_LEVEL, &pDelete, 0); |
| 116771 | 117988 | if( rc==SQLITE_OK ){ |
| 116772 | 117989 | sqlite3_bind_int(pDelete, 1, iLevel); |
| 116773 | 117990 | sqlite3_step(pDelete); |
| 116774 | 117991 | rc = sqlite3_reset(pDelete); |
| 116775 | 117992 | } |
| 116776 | | - }else{ |
| 116777 | | - fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); |
| 116778 | 117993 | } |
| 116779 | 117994 | |
| 116780 | 117995 | return rc; |
| 116781 | 117996 | } |
| 116782 | 117997 | |
| | @@ -116821,148 +118036,117 @@ |
| 116821 | 118036 | |
| 116822 | 118037 | *ppList = pList; |
| 116823 | 118038 | *pnList = nList; |
| 116824 | 118039 | } |
| 116825 | 118040 | |
| 116826 | | -/* |
| 116827 | | -** sqlite3Fts3SegReaderIterate() callback used when merging multiple |
| 116828 | | -** segments to create a single, larger segment. |
| 116829 | | -*/ |
| 116830 | | -static int fts3MergeCallback( |
| 116831 | | - Fts3Table *p, /* FTS3 Virtual table handle */ |
| 116832 | | - void *pContext, /* Pointer to SegmentWriter* to write with */ |
| 116833 | | - char *zTerm, /* Term to write to the db */ |
| 116834 | | - int nTerm, /* Number of bytes in zTerm */ |
| 116835 | | - char *aDoclist, /* Doclist associated with zTerm */ |
| 116836 | | - int nDoclist /* Number of bytes in doclist */ |
| 116837 | | -){ |
| 116838 | | - SegmentWriter **ppW = (SegmentWriter **)pContext; |
| 116839 | | - return fts3SegWriterAdd(p, ppW, 1, zTerm, nTerm, aDoclist, nDoclist); |
| 116840 | | -} |
| 116841 | | - |
| 116842 | | -/* |
| 116843 | | -** sqlite3Fts3SegReaderIterate() callback used when flushing the contents |
| 116844 | | -** of the pending-terms hash table to the database. |
| 116845 | | -*/ |
| 116846 | | -static int fts3FlushCallback( |
| 116847 | | - Fts3Table *p, /* FTS3 Virtual table handle */ |
| 116848 | | - void *pContext, /* Pointer to SegmentWriter* to write with */ |
| 116849 | | - char *zTerm, /* Term to write to the db */ |
| 116850 | | - int nTerm, /* Number of bytes in zTerm */ |
| 116851 | | - char *aDoclist, /* Doclist associated with zTerm */ |
| 116852 | | - int nDoclist /* Number of bytes in doclist */ |
| 116853 | | -){ |
| 116854 | | - SegmentWriter **ppW = (SegmentWriter **)pContext; |
| 116855 | | - return fts3SegWriterAdd(p, ppW, 0, zTerm, nTerm, aDoclist, nDoclist); |
| 116856 | | -} |
| 116857 | | - |
| 116858 | | -/* |
| 116859 | | -** This function is used to iterate through a contiguous set of terms |
| 116860 | | -** stored in the full-text index. It merges data contained in one or |
| 116861 | | -** more segments to support this. |
| 116862 | | -** |
| 116863 | | -** The second argument is passed an array of pointers to SegReader objects |
| 116864 | | -** allocated with sqlite3Fts3SegReaderNew(). This function merges the range |
| 116865 | | -** of terms selected by each SegReader. If a single term is present in |
| 116866 | | -** more than one segment, the associated doclists are merged. For each |
| 116867 | | -** term and (possibly merged) doclist in the merged range, the callback |
| 116868 | | -** function xFunc is invoked with its arguments set as follows. |
| 116869 | | -** |
| 116870 | | -** arg 0: Copy of 'p' parameter passed to this function |
| 116871 | | -** arg 1: Copy of 'pContext' parameter passed to this function |
| 116872 | | -** arg 2: Pointer to buffer containing term |
| 116873 | | -** arg 3: Size of arg 2 buffer in bytes |
| 116874 | | -** arg 4: Pointer to buffer containing doclist |
| 116875 | | -** arg 5: Size of arg 2 buffer in bytes |
| 116876 | | -** |
| 116877 | | -** The 4th argument to this function is a pointer to a structure of type |
| 116878 | | -** Fts3SegFilter, defined in fts3Int.h. The contents of this structure |
| 116879 | | -** further restrict the range of terms that callbacks are made for and |
| 116880 | | -** modify the behaviour of this function. See comments above structure |
| 116881 | | -** definition for details. |
| 116882 | | -*/ |
| 116883 | | -SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate( |
| 118041 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderStart( |
| 116884 | 118042 | Fts3Table *p, /* Virtual table handle */ |
| 116885 | | - Fts3SegReader **apSegment, /* Array of Fts3SegReader objects */ |
| 116886 | | - int nSegment, /* Size of apSegment array */ |
| 116887 | | - Fts3SegFilter *pFilter, /* Restrictions on range of iteration */ |
| 116888 | | - int (*xFunc)(Fts3Table *, void *, char *, int, char *, int), /* Callback */ |
| 116889 | | - void *pContext /* Callback context (2nd argument) */ |
| 118043 | + Fts3SegReaderCursor *pCsr, /* Cursor object */ |
| 118044 | + Fts3SegFilter *pFilter /* Restrictions on range of iteration */ |
| 116890 | 118045 | ){ |
| 116891 | | - int i; /* Iterator variable */ |
| 116892 | | - char *aBuffer = 0; /* Buffer to merge doclists in */ |
| 116893 | | - int nAlloc = 0; /* Allocated size of aBuffer buffer */ |
| 116894 | | - int rc = SQLITE_OK; /* Return code */ |
| 116895 | | - |
| 116896 | | - int isIgnoreEmpty = (pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY); |
| 116897 | | - int isRequirePos = (pFilter->flags & FTS3_SEGMENT_REQUIRE_POS); |
| 116898 | | - int isColFilter = (pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER); |
| 116899 | | - int isPrefix = (pFilter->flags & FTS3_SEGMENT_PREFIX); |
| 116900 | | - |
| 116901 | | - /* If there are zero segments, this function is a no-op. This scenario |
| 116902 | | - ** comes about only when reading from an empty database. |
| 116903 | | - */ |
| 116904 | | - if( nSegment==0 ) goto finished; |
| 118046 | + int i; |
| 118047 | + |
| 118048 | + /* Initialize the cursor object */ |
| 118049 | + pCsr->pFilter = pFilter; |
| 116905 | 118050 | |
| 116906 | 118051 | /* If the Fts3SegFilter defines a specific term (or term prefix) to search |
| 116907 | 118052 | ** for, then advance each segment iterator until it points to a term of |
| 116908 | 118053 | ** equal or greater value than the specified term. This prevents many |
| 116909 | 118054 | ** unnecessary merge/sort operations for the case where single segment |
| 116910 | 118055 | ** b-tree leaf nodes contain more than one term. |
| 116911 | 118056 | */ |
| 116912 | | - for(i=0; i<nSegment; i++){ |
| 118057 | + for(i=0; i<pCsr->nSegment; i++){ |
| 116913 | 118058 | int nTerm = pFilter->nTerm; |
| 116914 | 118059 | const char *zTerm = pFilter->zTerm; |
| 116915 | | - Fts3SegReader *pSeg = apSegment[i]; |
| 118060 | + Fts3SegReader *pSeg = pCsr->apSegment[i]; |
| 116916 | 118061 | do { |
| 116917 | | - rc = fts3SegReaderNext(p, pSeg); |
| 116918 | | - if( rc!=SQLITE_OK ) goto finished; |
| 118062 | + int rc = fts3SegReaderNext(p, pSeg); |
| 118063 | + if( rc!=SQLITE_OK ) return rc; |
| 116919 | 118064 | }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 ); |
| 116920 | 118065 | } |
| 118066 | + fts3SegReaderSort( |
| 118067 | + pCsr->apSegment, pCsr->nSegment, pCsr->nSegment, fts3SegReaderCmp); |
| 116921 | 118068 | |
| 116922 | | - fts3SegReaderSort(apSegment, nSegment, nSegment, fts3SegReaderCmp); |
| 116923 | | - while( apSegment[0]->aNode ){ |
| 116924 | | - int nTerm = apSegment[0]->nTerm; |
| 116925 | | - char *zTerm = apSegment[0]->zTerm; |
| 116926 | | - int nMerge = 1; |
| 118069 | + return SQLITE_OK; |
| 118070 | +} |
| 118071 | + |
| 118072 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderStep( |
| 118073 | + Fts3Table *p, /* Virtual table handle */ |
| 118074 | + Fts3SegReaderCursor *pCsr /* Cursor object */ |
| 118075 | +){ |
| 118076 | + int rc = SQLITE_OK; |
| 118077 | + |
| 118078 | + int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY); |
| 118079 | + int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS); |
| 118080 | + int isColFilter = (pCsr->pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER); |
| 118081 | + int isPrefix = (pCsr->pFilter->flags & FTS3_SEGMENT_PREFIX); |
| 118082 | + int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN); |
| 118083 | + |
| 118084 | + Fts3SegReader **apSegment = pCsr->apSegment; |
| 118085 | + int nSegment = pCsr->nSegment; |
| 118086 | + Fts3SegFilter *pFilter = pCsr->pFilter; |
| 118087 | + |
| 118088 | + if( pCsr->nSegment==0 ) return SQLITE_OK; |
| 118089 | + |
| 118090 | + do { |
| 118091 | + int nMerge; |
| 118092 | + int i; |
| 118093 | + |
| 118094 | + /* Advance the first pCsr->nAdvance entries in the apSegment[] array |
| 118095 | + ** forward. Then sort the list in order of current term again. |
| 118096 | + */ |
| 118097 | + for(i=0; i<pCsr->nAdvance; i++){ |
| 118098 | + rc = fts3SegReaderNext(p, apSegment[i]); |
| 118099 | + if( rc!=SQLITE_OK ) return rc; |
| 118100 | + } |
| 118101 | + fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp); |
| 118102 | + pCsr->nAdvance = 0; |
| 118103 | + |
| 118104 | + /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */ |
| 118105 | + assert( rc==SQLITE_OK ); |
| 118106 | + if( apSegment[0]->aNode==0 ) break; |
| 118107 | + |
| 118108 | + pCsr->nTerm = apSegment[0]->nTerm; |
| 118109 | + pCsr->zTerm = apSegment[0]->zTerm; |
| 116927 | 118110 | |
| 116928 | 118111 | /* If this is a prefix-search, and if the term that apSegment[0] points |
| 116929 | 118112 | ** to does not share a suffix with pFilter->zTerm/nTerm, then all |
| 116930 | 118113 | ** required callbacks have been made. In this case exit early. |
| 116931 | 118114 | ** |
| 116932 | 118115 | ** Similarly, if this is a search for an exact match, and the first term |
| 116933 | 118116 | ** of segment apSegment[0] is not a match, exit early. |
| 116934 | 118117 | */ |
| 116935 | | - if( pFilter->zTerm ){ |
| 116936 | | - if( nTerm<pFilter->nTerm |
| 116937 | | - || (!isPrefix && nTerm>pFilter->nTerm) |
| 116938 | | - || memcmp(zTerm, pFilter->zTerm, pFilter->nTerm) |
| 116939 | | - ){ |
| 116940 | | - goto finished; |
| 118118 | + if( pFilter->zTerm && !isScan ){ |
| 118119 | + if( pCsr->nTerm<pFilter->nTerm |
| 118120 | + || (!isPrefix && pCsr->nTerm>pFilter->nTerm) |
| 118121 | + || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm) |
| 118122 | + ){ |
| 118123 | + break; |
| 116941 | 118124 | } |
| 116942 | 118125 | } |
| 116943 | 118126 | |
| 118127 | + nMerge = 1; |
| 116944 | 118128 | while( nMerge<nSegment |
| 116945 | 118129 | && apSegment[nMerge]->aNode |
| 116946 | | - && apSegment[nMerge]->nTerm==nTerm |
| 116947 | | - && 0==memcmp(zTerm, apSegment[nMerge]->zTerm, nTerm) |
| 118130 | + && apSegment[nMerge]->nTerm==pCsr->nTerm |
| 118131 | + && 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm) |
| 116948 | 118132 | ){ |
| 116949 | 118133 | nMerge++; |
| 116950 | 118134 | } |
| 116951 | 118135 | |
| 116952 | 118136 | assert( isIgnoreEmpty || (isRequirePos && !isColFilter) ); |
| 116953 | 118137 | if( nMerge==1 && !isIgnoreEmpty ){ |
| 116954 | | - Fts3SegReader *p0 = apSegment[0]; |
| 116955 | | - rc = xFunc(p, pContext, zTerm, nTerm, p0->aDoclist, p0->nDoclist); |
| 116956 | | - if( rc!=SQLITE_OK ) goto finished; |
| 118138 | + pCsr->aDoclist = apSegment[0]->aDoclist; |
| 118139 | + pCsr->nDoclist = apSegment[0]->nDoclist; |
| 118140 | + rc = SQLITE_ROW; |
| 116957 | 118141 | }else{ |
| 116958 | 118142 | int nDoclist = 0; /* Size of doclist */ |
| 116959 | 118143 | sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */ |
| 116960 | 118144 | |
| 116961 | 118145 | /* The current term of the first nMerge entries in the array |
| 116962 | 118146 | ** of Fts3SegReader objects is the same. The doclists must be merged |
| 116963 | | - ** and a single term added to the new segment. |
| 118147 | + ** and a single term returned with the merged doclist. |
| 116964 | 118148 | */ |
| 116965 | 118149 | for(i=0; i<nMerge; i++){ |
| 116966 | 118150 | fts3SegReaderFirstDocid(apSegment[i]); |
| 116967 | 118151 | } |
| 116968 | 118152 | fts3SegReaderSort(apSegment, nMerge, nMerge, fts3SegReaderDoclistCmp); |
| | @@ -116986,57 +118170,60 @@ |
| 116986 | 118170 | fts3ColumnFilter(pFilter->iCol, &pList, &nList); |
| 116987 | 118171 | } |
| 116988 | 118172 | |
| 116989 | 118173 | if( !isIgnoreEmpty || nList>0 ){ |
| 116990 | 118174 | nByte = sqlite3Fts3VarintLen(iDocid-iPrev) + (isRequirePos?nList+1:0); |
| 116991 | | - if( nDoclist+nByte>nAlloc ){ |
| 118175 | + if( nDoclist+nByte>pCsr->nBuffer ){ |
| 116992 | 118176 | char *aNew; |
| 116993 | | - nAlloc = (nDoclist+nByte)*2; |
| 116994 | | - aNew = sqlite3_realloc(aBuffer, nAlloc); |
| 118177 | + pCsr->nBuffer = (nDoclist+nByte)*2; |
| 118178 | + aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer); |
| 116995 | 118179 | if( !aNew ){ |
| 116996 | | - rc = SQLITE_NOMEM; |
| 116997 | | - goto finished; |
| 118180 | + return SQLITE_NOMEM; |
| 116998 | 118181 | } |
| 116999 | | - aBuffer = aNew; |
| 118182 | + pCsr->aBuffer = aNew; |
| 117000 | 118183 | } |
| 117001 | | - nDoclist += sqlite3Fts3PutVarint(&aBuffer[nDoclist], iDocid-iPrev); |
| 118184 | + nDoclist += sqlite3Fts3PutVarint( |
| 118185 | + &pCsr->aBuffer[nDoclist], iDocid-iPrev |
| 118186 | + ); |
| 117002 | 118187 | iPrev = iDocid; |
| 117003 | 118188 | if( isRequirePos ){ |
| 117004 | | - memcpy(&aBuffer[nDoclist], pList, nList); |
| 118189 | + memcpy(&pCsr->aBuffer[nDoclist], pList, nList); |
| 117005 | 118190 | nDoclist += nList; |
| 117006 | | - aBuffer[nDoclist++] = '\0'; |
| 118191 | + pCsr->aBuffer[nDoclist++] = '\0'; |
| 117007 | 118192 | } |
| 117008 | 118193 | } |
| 117009 | 118194 | |
| 117010 | 118195 | fts3SegReaderSort(apSegment, nMerge, j, fts3SegReaderDoclistCmp); |
| 117011 | 118196 | } |
| 117012 | | - |
| 117013 | 118197 | if( nDoclist>0 ){ |
| 117014 | | - rc = xFunc(p, pContext, zTerm, nTerm, aBuffer, nDoclist); |
| 117015 | | - if( rc!=SQLITE_OK ) goto finished; |
| 117016 | | - } |
| 117017 | | - } |
| 117018 | | - |
| 117019 | | - /* If there is a term specified to filter on, and this is not a prefix |
| 117020 | | - ** search, return now. The callback that corresponds to the required |
| 117021 | | - ** term (if such a term exists in the index) has already been made. |
| 117022 | | - */ |
| 117023 | | - if( pFilter->zTerm && !isPrefix ){ |
| 117024 | | - goto finished; |
| 117025 | | - } |
| 117026 | | - |
| 117027 | | - for(i=0; i<nMerge; i++){ |
| 117028 | | - rc = fts3SegReaderNext(p, apSegment[i]); |
| 117029 | | - if( rc!=SQLITE_OK ) goto finished; |
| 117030 | | - } |
| 117031 | | - fts3SegReaderSort(apSegment, nSegment, nMerge, fts3SegReaderCmp); |
| 117032 | | - } |
| 117033 | | - |
| 117034 | | - finished: |
| 117035 | | - sqlite3_free(aBuffer); |
| 118198 | + pCsr->aDoclist = pCsr->aBuffer; |
| 118199 | + pCsr->nDoclist = nDoclist; |
| 118200 | + rc = SQLITE_ROW; |
| 118201 | + } |
| 118202 | + } |
| 118203 | + pCsr->nAdvance = nMerge; |
| 118204 | + }while( rc==SQLITE_OK ); |
| 118205 | + |
| 117036 | 118206 | return rc; |
| 117037 | 118207 | } |
| 118208 | + |
| 118209 | +SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish( |
| 118210 | + Fts3SegReaderCursor *pCsr /* Cursor object */ |
| 118211 | +){ |
| 118212 | + if( pCsr ){ |
| 118213 | + int i; |
| 118214 | + for(i=0; i<pCsr->nSegment; i++){ |
| 118215 | + sqlite3Fts3SegReaderFree(pCsr->apSegment[i]); |
| 118216 | + } |
| 118217 | + sqlite3_free(pCsr->apSegment); |
| 118218 | + sqlite3_free(pCsr->aBuffer); |
| 118219 | + |
| 118220 | + pCsr->nSegment = 0; |
| 118221 | + pCsr->apSegment = 0; |
| 118222 | + pCsr->aBuffer = 0; |
| 118223 | + } |
| 118224 | +} |
| 117038 | 118225 | |
| 117039 | 118226 | /* |
| 117040 | 118227 | ** Merge all level iLevel segments in the database into a single |
| 117041 | 118228 | ** iLevel+1 segment. Or, if iLevel<0, merge all segments into a |
| 117042 | 118229 | ** single segment with a level equal to the numerically largest level |
| | @@ -117046,161 +118233,73 @@ |
| 117046 | 118233 | ** segment in the database, SQLITE_DONE is returned immediately. |
| 117047 | 118234 | ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, |
| 117048 | 118235 | ** an SQLite error code is returned. |
| 117049 | 118236 | */ |
| 117050 | 118237 | static int fts3SegmentMerge(Fts3Table *p, int iLevel){ |
| 117051 | | - int i; /* Iterator variable */ |
| 117052 | 118238 | int rc; /* Return code */ |
| 117053 | | - int iIdx; /* Index of new segment */ |
| 118239 | + int iIdx = 0; /* Index of new segment */ |
| 117054 | 118240 | int iNewLevel = 0; /* Level to create new segment at */ |
| 117055 | | - sqlite3_stmt *pStmt = 0; |
| 117056 | | - SegmentWriter *pWriter = 0; |
| 117057 | | - int nSegment = 0; /* Number of segments being merged */ |
| 117058 | | - Fts3SegReader **apSegment = 0; /* Array of Segment iterators */ |
| 117059 | | - Fts3SegReader *pPending = 0; /* Iterator for pending-terms */ |
| 118241 | + SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */ |
| 117060 | 118242 | Fts3SegFilter filter; /* Segment term filter condition */ |
| 118243 | + Fts3SegReaderCursor csr; /* Cursor to iterate through level(s) */ |
| 117061 | 118244 | |
| 117062 | | - if( iLevel<0 ){ |
| 118245 | + rc = sqlite3Fts3SegReaderCursor(p, iLevel, 0, 0, 1, 0, &csr); |
| 118246 | + if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished; |
| 118247 | + |
| 118248 | + if( iLevel==FTS3_SEGCURSOR_ALL ){ |
| 117063 | 118249 | /* This call is to merge all segments in the database to a single |
| 117064 | 118250 | ** segment. The level of the new segment is equal to the the numerically |
| 117065 | 118251 | ** greatest segment level currently present in the database. The index |
| 117066 | | - ** of the new segment is always 0. |
| 117067 | | - */ |
| 117068 | | - iIdx = 0; |
| 117069 | | - rc = sqlite3Fts3SegReaderPending(p, 0, 0, 1, &pPending); |
| 117070 | | - if( rc!=SQLITE_OK ) goto finished; |
| 117071 | | - rc = fts3SegmentCountMax(p, &nSegment, &iNewLevel); |
| 117072 | | - if( rc!=SQLITE_OK ) goto finished; |
| 117073 | | - nSegment += (pPending!=0); |
| 117074 | | - if( nSegment<=1 ){ |
| 117075 | | - return SQLITE_DONE; |
| 117076 | | - } |
| 118252 | + ** of the new segment is always 0. */ |
| 118253 | + int nDummy; /* TODO: Remove this */ |
| 118254 | + if( csr.nSegment==1 ){ |
| 118255 | + rc = SQLITE_DONE; |
| 118256 | + goto finished; |
| 118257 | + } |
| 118258 | + rc = fts3SegmentCountMax(p, &nDummy, &iNewLevel); |
| 117077 | 118259 | }else{ |
| 117078 | 118260 | /* This call is to merge all segments at level iLevel. Find the next |
| 117079 | 118261 | ** available segment index at level iLevel+1. The call to |
| 117080 | 118262 | ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to |
| 117081 | | - ** a single iLevel+2 segment if necessary. |
| 117082 | | - */ |
| 118263 | + ** a single iLevel+2 segment if necessary. */ |
| 117083 | 118264 | iNewLevel = iLevel+1; |
| 117084 | 118265 | rc = fts3AllocateSegdirIdx(p, iNewLevel, &iIdx); |
| 117085 | | - if( rc!=SQLITE_OK ) goto finished; |
| 117086 | | - rc = fts3SegmentCount(p, iLevel, &nSegment); |
| 117087 | | - if( rc!=SQLITE_OK ) goto finished; |
| 117088 | | - } |
| 117089 | | - assert( nSegment>0 ); |
| 117090 | | - assert( iNewLevel>=0 ); |
| 117091 | | - |
| 117092 | | - /* Allocate space for an array of pointers to segment iterators. */ |
| 117093 | | - apSegment = (Fts3SegReader**)sqlite3_malloc(sizeof(Fts3SegReader *)*nSegment); |
| 117094 | | - if( !apSegment ){ |
| 117095 | | - rc = SQLITE_NOMEM; |
| 117096 | | - goto finished; |
| 117097 | | - } |
| 117098 | | - memset(apSegment, 0, sizeof(Fts3SegReader *)*nSegment); |
| 117099 | | - |
| 117100 | | - /* Allocate a Fts3SegReader structure for each segment being merged. A |
| 117101 | | - ** Fts3SegReader stores the state data required to iterate through all |
| 117102 | | - ** entries on all leaves of a single segment. |
| 117103 | | - */ |
| 117104 | | - assert( SQL_SELECT_LEVEL+1==SQL_SELECT_ALL_LEVEL); |
| 117105 | | - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL+(iLevel<0), &pStmt, 0); |
| 117106 | | - if( rc!=SQLITE_OK ) goto finished; |
| 117107 | | - sqlite3_bind_int(pStmt, 1, iLevel); |
| 117108 | | - for(i=0; SQLITE_ROW==(sqlite3_step(pStmt)); i++){ |
| 117109 | | - rc = fts3SegReaderNew(pStmt, i, &apSegment[i]); |
| 117110 | | - if( rc!=SQLITE_OK ){ |
| 117111 | | - goto finished; |
| 117112 | | - } |
| 117113 | | - } |
| 117114 | | - rc = sqlite3_reset(pStmt); |
| 117115 | | - if( pPending ){ |
| 117116 | | - apSegment[i] = pPending; |
| 117117 | | - pPending = 0; |
| 117118 | | - } |
| 117119 | | - pStmt = 0; |
| 117120 | | - if( rc!=SQLITE_OK ) goto finished; |
| 118266 | + } |
| 118267 | + if( rc!=SQLITE_OK ) goto finished; |
| 118268 | + assert( csr.nSegment>0 ); |
| 118269 | + assert( iNewLevel>=0 ); |
| 117121 | 118270 | |
| 117122 | 118271 | memset(&filter, 0, sizeof(Fts3SegFilter)); |
| 117123 | 118272 | filter.flags = FTS3_SEGMENT_REQUIRE_POS; |
| 117124 | | - filter.flags |= (iLevel<0 ? FTS3_SEGMENT_IGNORE_EMPTY : 0); |
| 117125 | | - rc = sqlite3Fts3SegReaderIterate(p, apSegment, nSegment, |
| 117126 | | - &filter, fts3MergeCallback, (void *)&pWriter |
| 117127 | | - ); |
| 118273 | + filter.flags |= (iLevel==FTS3_SEGCURSOR_ALL ? FTS3_SEGMENT_IGNORE_EMPTY : 0); |
| 118274 | + |
| 118275 | + rc = sqlite3Fts3SegReaderStart(p, &csr, &filter); |
| 118276 | + while( SQLITE_OK==rc ){ |
| 118277 | + rc = sqlite3Fts3SegReaderStep(p, &csr); |
| 118278 | + if( rc!=SQLITE_ROW ) break; |
| 118279 | + rc = fts3SegWriterAdd(p, &pWriter, 1, |
| 118280 | + csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist); |
| 118281 | + } |
| 118282 | + if( rc!=SQLITE_OK ) goto finished; |
| 118283 | + assert( pWriter ); |
| 118284 | + |
| 118285 | + rc = fts3DeleteSegdir(p, iLevel, csr.apSegment, csr.nSegment); |
| 117128 | 118286 | if( rc!=SQLITE_OK ) goto finished; |
| 117129 | | - |
| 117130 | | - rc = fts3DeleteSegdir(p, iLevel, apSegment, nSegment); |
| 117131 | | - if( rc==SQLITE_OK ){ |
| 117132 | | - rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx); |
| 117133 | | - } |
| 118287 | + rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx); |
| 117134 | 118288 | |
| 117135 | 118289 | finished: |
| 117136 | 118290 | fts3SegWriterFree(pWriter); |
| 117137 | | - if( apSegment ){ |
| 117138 | | - for(i=0; i<nSegment; i++){ |
| 117139 | | - sqlite3Fts3SegReaderFree(apSegment[i]); |
| 117140 | | - } |
| 117141 | | - sqlite3_free(apSegment); |
| 117142 | | - } |
| 117143 | | - sqlite3Fts3SegReaderFree(pPending); |
| 117144 | | - sqlite3_reset(pStmt); |
| 118291 | + sqlite3Fts3SegReaderFinish(&csr); |
| 117145 | 118292 | return rc; |
| 117146 | 118293 | } |
| 117147 | 118294 | |
| 117148 | 118295 | |
| 117149 | 118296 | /* |
| 117150 | 118297 | ** Flush the contents of pendingTerms to a level 0 segment. |
| 117151 | 118298 | */ |
| 117152 | 118299 | SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ |
| 117153 | | - int rc; /* Return Code */ |
| 117154 | | - int idx; /* Index of new segment created */ |
| 117155 | | - SegmentWriter *pWriter = 0; /* Used to write the segment */ |
| 117156 | | - Fts3SegReader *pReader = 0; /* Used to iterate through the hash table */ |
| 117157 | | - |
| 117158 | | - /* Allocate a SegReader object to iterate through the contents of the |
| 117159 | | - ** pending-terms table. If an error occurs, or if there are no terms |
| 117160 | | - ** in the pending-terms table, return immediately. |
| 117161 | | - */ |
| 117162 | | - rc = sqlite3Fts3SegReaderPending(p, 0, 0, 1, &pReader); |
| 117163 | | - if( rc!=SQLITE_OK || pReader==0 ){ |
| 117164 | | - return rc; |
| 117165 | | - } |
| 117166 | | - |
| 117167 | | - /* Determine the next index at level 0. If level 0 is already full, this |
| 117168 | | - ** call may merge all existing level 0 segments into a single level 1 |
| 117169 | | - ** segment. |
| 117170 | | - */ |
| 117171 | | - rc = fts3AllocateSegdirIdx(p, 0, &idx); |
| 117172 | | - |
| 117173 | | - /* If no errors have occured, iterate through the contents of the |
| 117174 | | - ** pending-terms hash table using the Fts3SegReader iterator. The callback |
| 117175 | | - ** writes each term (along with its doclist) to the database via the |
| 117176 | | - ** SegmentWriter handle pWriter. |
| 117177 | | - */ |
| 117178 | | - if( rc==SQLITE_OK ){ |
| 117179 | | - void *c = (void *)&pWriter; /* SegReaderIterate() callback context */ |
| 117180 | | - Fts3SegFilter f; /* SegReaderIterate() parameters */ |
| 117181 | | - |
| 117182 | | - memset(&f, 0, sizeof(Fts3SegFilter)); |
| 117183 | | - f.flags = FTS3_SEGMENT_REQUIRE_POS; |
| 117184 | | - rc = sqlite3Fts3SegReaderIterate(p, &pReader, 1, &f, fts3FlushCallback, c); |
| 117185 | | - } |
| 117186 | | - assert( pWriter || rc!=SQLITE_OK ); |
| 117187 | | - |
| 117188 | | - /* If no errors have occured, flush the SegmentWriter object to the |
| 117189 | | - ** database. Then delete the SegmentWriter and Fts3SegReader objects |
| 117190 | | - ** allocated by this function. |
| 117191 | | - */ |
| 117192 | | - if( rc==SQLITE_OK ){ |
| 117193 | | - rc = fts3SegWriterFlush(p, pWriter, 0, idx); |
| 117194 | | - } |
| 117195 | | - fts3SegWriterFree(pWriter); |
| 117196 | | - sqlite3Fts3SegReaderFree(pReader); |
| 117197 | | - |
| 117198 | | - if( rc==SQLITE_OK ){ |
| 117199 | | - sqlite3Fts3PendingTermsClear(p); |
| 117200 | | - } |
| 117201 | | - return rc; |
| 118300 | + return fts3SegmentMerge(p, FTS3_SEGCURSOR_PENDING); |
| 117202 | 118301 | } |
| 117203 | 118302 | |
| 117204 | 118303 | /* |
| 117205 | 118304 | ** Encode N integers as varints into a blob. |
| 117206 | 118305 | */ |
| | @@ -117363,11 +118462,11 @@ |
| 117363 | 118462 | int nVal = sqlite3_value_bytes(pVal); |
| 117364 | 118463 | |
| 117365 | 118464 | if( !zVal ){ |
| 117366 | 118465 | return SQLITE_NOMEM; |
| 117367 | 118466 | }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){ |
| 117368 | | - rc = fts3SegmentMerge(p, -1); |
| 118467 | + rc = fts3SegmentMerge(p, FTS3_SEGCURSOR_ALL); |
| 117369 | 118468 | if( rc==SQLITE_DONE ){ |
| 117370 | 118469 | rc = SQLITE_OK; |
| 117371 | 118470 | }else{ |
| 117372 | 118471 | sqlite3Fts3PendingTermsClear(p); |
| 117373 | 118472 | } |
| | @@ -117621,11 +118720,11 @@ |
| 117621 | 118720 | */ |
| 117622 | 118721 | SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ |
| 117623 | 118722 | int rc; |
| 117624 | 118723 | rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0); |
| 117625 | 118724 | if( rc==SQLITE_OK ){ |
| 117626 | | - rc = fts3SegmentMerge(p, -1); |
| 118725 | + rc = fts3SegmentMerge(p, FTS3_SEGCURSOR_ALL); |
| 117627 | 118726 | if( rc==SQLITE_OK ){ |
| 117628 | 118727 | rc = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); |
| 117629 | 118728 | if( rc==SQLITE_OK ){ |
| 117630 | 118729 | sqlite3Fts3PendingTermsClear(p); |
| 117631 | 118730 | } |
| | @@ -118599,10 +119698,11 @@ |
| 118599 | 119698 | pStmt = *ppStmt; |
| 118600 | 119699 | assert( sqlite3_data_count(pStmt)==1 ); |
| 118601 | 119700 | |
| 118602 | 119701 | a = sqlite3_column_blob(pStmt, 0); |
| 118603 | 119702 | a += sqlite3Fts3GetVarint(a, &nDoc); |
| 119703 | + if( nDoc==0 ) return SQLITE_CORRUPT; |
| 118604 | 119704 | *pnDoc = (u32)nDoc; |
| 118605 | 119705 | |
| 118606 | 119706 | if( paLen ) *paLen = a; |
| 118607 | 119707 | return SQLITE_OK; |
| 118608 | 119708 | } |
| | @@ -118805,13 +119905,15 @@ |
| 118805 | 119905 | |
| 118806 | 119906 | rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a); |
| 118807 | 119907 | if( rc==SQLITE_OK ){ |
| 118808 | 119908 | int iCol; |
| 118809 | 119909 | for(iCol=0; iCol<pInfo->nCol; iCol++){ |
| 119910 | + u32 iVal; |
| 118810 | 119911 | sqlite3_int64 nToken; |
| 118811 | 119912 | a += sqlite3Fts3GetVarint(a, &nToken); |
| 118812 | | - pInfo->aMatchinfo[iCol] = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc); |
| 119913 | + iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc); |
| 119914 | + pInfo->aMatchinfo[iCol] = iVal; |
| 118813 | 119915 | } |
| 118814 | 119916 | } |
| 118815 | 119917 | } |
| 118816 | 119918 | break; |
| 118817 | 119919 | |
| 118818 | 119920 | |