Fossil SCM
Update the built-in SQLite to the latest 3.7.4 beta.
Commit
6c7332141811955273d5f93c5dbc13d4e8dbee5f
Parent
ac5e8fb4c09f22d…
2 files changed
+771
-320
+29
-10
+771
-320
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -650,11 +650,11 @@ | ||
| 650 | 650 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 651 | 651 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 652 | 652 | */ |
| 653 | 653 | #define SQLITE_VERSION "3.7.4" |
| 654 | 654 | #define SQLITE_VERSION_NUMBER 3007004 |
| 655 | -#define SQLITE_SOURCE_ID "2010-11-16 23:10:26 fd5b2f23dd5111d2f0934dd828bae36b755024c1" | |
| 655 | +#define SQLITE_SOURCE_ID "2010-11-26 16:49:59 c412f61229b6ab1ac90b932afd56f7c5e3ba1cfe" | |
| 656 | 656 | |
| 657 | 657 | /* |
| 658 | 658 | ** CAPI3REF: Run-Time Library Version Numbers |
| 659 | 659 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 660 | 660 | ** |
| @@ -1083,10 +1083,22 @@ | ||
| 1083 | 1083 | ** sync operation only needs to flush data to mass storage. Inode |
| 1084 | 1084 | ** information need not be flushed. If the lower four bits of the flag |
| 1085 | 1085 | ** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. |
| 1086 | 1086 | ** If the lower four bits equal SQLITE_SYNC_FULL, that means |
| 1087 | 1087 | ** to use Mac OS X style fullsync instead of fsync(). |
| 1088 | +** | |
| 1089 | +** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags | |
| 1090 | +** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL | |
| 1091 | +** settings. The [synchronous pragma] determines when calls to the | |
| 1092 | +** xSync VFS method occur and applies uniformly across all platforms. | |
| 1093 | +** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how | |
| 1094 | +** energetic or rigorous or forceful the sync operations are and | |
| 1095 | +** only make a difference on Mac OSX for the default SQLite code. | |
| 1096 | +** (Third-party VFS implementations might also make the distinction | |
| 1097 | +** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the | |
| 1098 | +** operating systems natively supported by SQLite, only Mac OSX | |
| 1099 | +** cares about the difference.) | |
| 1088 | 1100 | */ |
| 1089 | 1101 | #define SQLITE_SYNC_NORMAL 0x00002 |
| 1090 | 1102 | #define SQLITE_SYNC_FULL 0x00003 |
| 1091 | 1103 | #define SQLITE_SYNC_DATAONLY 0x00010 |
| 1092 | 1104 | |
| @@ -1251,10 +1263,12 @@ | ||
| 1251 | 1263 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 1252 | 1264 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 1253 | 1265 | #define SQLITE_LAST_ERRNO 4 |
| 1254 | 1266 | #define SQLITE_FCNTL_SIZE_HINT 5 |
| 1255 | 1267 | #define SQLITE_FCNTL_CHUNK_SIZE 6 |
| 1268 | +#define SQLITE_FCNTL_FILE_POINTER 7 | |
| 1269 | + | |
| 1256 | 1270 | |
| 1257 | 1271 | /* |
| 1258 | 1272 | ** CAPI3REF: Mutex Handle |
| 1259 | 1273 | ** |
| 1260 | 1274 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -3178,18 +3192,17 @@ | ||
| 3178 | 3192 | |
| 3179 | 3193 | /* |
| 3180 | 3194 | ** CAPI3REF: Determine If An SQL Statement Writes The Database |
| 3181 | 3195 | ** |
| 3182 | 3196 | ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if |
| 3183 | -** the [prepared statement] X is guaranteed to leave the database file | |
| 3184 | -** unmodified. ^If the sqlite3_stmt_readonly(X) interface returns false (zero) | |
| 3185 | -** then evaluating the statement might change the database file, but this | |
| 3186 | -** is not guaranteed as the write operation might be conditional and the | |
| 3187 | -** condition might not be met. ^If X is a NULL pointer then | |
| 3188 | -** sqlite3_stmt_readonly(X) returns true. If X is a non-NULL pointer but | |
| 3189 | -** is not a pointer to a valid, unfinalized prepared statement, then the | |
| 3190 | -** behavior is undefined and probably harmful. | |
| 3197 | +** the [prepared statement] X is [SELECT] statement and false (zero) if | |
| 3198 | +** X is an [INSERT], [UPDATE], [DELETE], CREATE, DROP, [ANALYZE], | |
| 3199 | +** [ALTER], or [REINDEX] statement. | |
| 3200 | +** If X is a NULL pointer or any other kind of statement, including but | |
| 3201 | +** not limited to [ATTACH], [DETACH], [COMMIT], [ROLLBACK], [RELEASE], | |
| 3202 | +** [SAVEPOINT], [PRAGMA], or [VACUUM] the result of sqlite3_stmt_readonly(X) is | |
| 3203 | +** undefined. | |
| 3191 | 3204 | */ |
| 3192 | 3205 | SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); |
| 3193 | 3206 | |
| 3194 | 3207 | /* |
| 3195 | 3208 | ** CAPI3REF: Dynamically Typed Value Object |
| @@ -5781,19 +5794,25 @@ | ||
| 5781 | 5794 | ** CAPI3REF: Low-Level Control Of Database Files |
| 5782 | 5795 | ** |
| 5783 | 5796 | ** ^The [sqlite3_file_control()] interface makes a direct call to the |
| 5784 | 5797 | ** xFileControl method for the [sqlite3_io_methods] object associated |
| 5785 | 5798 | ** with a particular database identified by the second argument. ^The |
| 5786 | -** name of the database "main" for the main database or "temp" for the | |
| 5799 | +** name of the database is "main" for the main database or "temp" for the | |
| 5787 | 5800 | ** TEMP database, or the name that appears after the AS keyword for |
| 5788 | 5801 | ** databases that are added using the [ATTACH] SQL command. |
| 5789 | 5802 | ** ^A NULL pointer can be used in place of "main" to refer to the |
| 5790 | 5803 | ** main database file. |
| 5791 | 5804 | ** ^The third and fourth parameters to this routine |
| 5792 | 5805 | ** are passed directly through to the second and third parameters of |
| 5793 | 5806 | ** the xFileControl method. ^The return value of the xFileControl |
| 5794 | 5807 | ** method becomes the return value of this routine. |
| 5808 | +** | |
| 5809 | +** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes | |
| 5810 | +** a pointer to the underlying [sqlite3_file] object to be written into | |
| 5811 | +** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER | |
| 5812 | +** case is a short-circuit path which does not actually invoke the | |
| 5813 | +** underlying sqlite3_io_methods.xFileControl method. | |
| 5795 | 5814 | ** |
| 5796 | 5815 | ** ^If the second parameter (zDbName) does not match the name of any |
| 5797 | 5816 | ** open database file, then SQLITE_ERROR is returned. ^This error |
| 5798 | 5817 | ** code is not remembered and will not be recalled by [sqlite3_errcode()] |
| 5799 | 5818 | ** or [sqlite3_errmsg()]. The underlying xFileControl method might |
| @@ -7460,11 +7479,11 @@ | ||
| 7460 | 7479 | #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ |
| 7461 | 7480 | #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ |
| 7462 | 7481 | |
| 7463 | 7482 | SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); |
| 7464 | 7483 | SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); |
| 7465 | -SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); | |
| 7484 | +SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); | |
| 7466 | 7485 | SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); |
| 7467 | 7486 | SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); |
| 7468 | 7487 | SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); |
| 7469 | 7488 | SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); |
| 7470 | 7489 | SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); |
| @@ -7944,16 +7963,16 @@ | ||
| 7944 | 7963 | #define OP_VColumn 129 |
| 7945 | 7964 | #define OP_VNext 131 |
| 7946 | 7965 | #define OP_VRename 132 |
| 7947 | 7966 | #define OP_VUpdate 133 |
| 7948 | 7967 | #define OP_Pagecount 134 |
| 7949 | -#define OP_Trace 135 | |
| 7950 | -#define OP_Noop 136 | |
| 7951 | -#define OP_Explain 137 | |
| 7968 | +#define OP_MaxPgcnt 135 | |
| 7969 | +#define OP_Trace 136 | |
| 7970 | +#define OP_Noop 137 | |
| 7971 | +#define OP_Explain 138 | |
| 7952 | 7972 | |
| 7953 | 7973 | /* The following opcode values are never used */ |
| 7954 | -#define OP_NotUsed_138 138 | |
| 7955 | 7974 | #define OP_NotUsed_139 139 |
| 7956 | 7975 | #define OP_NotUsed_140 140 |
| 7957 | 7976 | |
| 7958 | 7977 | |
| 7959 | 7978 | /* Properties such as "out2" or "jump" that are specified in |
| @@ -7982,11 +8001,11 @@ | ||
| 7982 | 8001 | /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x02,\ |
| 7983 | 8002 | /* 96 */ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 7984 | 8003 | /* 104 */ 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01,\ |
| 7985 | 8004 | /* 112 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\ |
| 7986 | 8005 | /* 120 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 7987 | -/* 128 */ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00,\ | |
| 8006 | +/* 128 */ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x02,\ | |
| 7988 | 8007 | /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\ |
| 7989 | 8008 | /* 144 */ 0x04, 0x04,} |
| 7990 | 8009 | |
| 7991 | 8010 | /************** End of opcodes.h *********************************************/ |
| 7992 | 8011 | /************** Continuing where we left off in vdbe.h ***********************/ |
| @@ -8167,11 +8186,11 @@ | ||
| 8167 | 8186 | /* Functions used to configure a Pager object. */ |
| 8168 | 8187 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 8169 | 8188 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| 8170 | 8189 | SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); |
| 8171 | 8190 | SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); |
| 8172 | -SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int); | |
| 8191 | +SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int); | |
| 8173 | 8192 | SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); |
| 8174 | 8193 | SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); |
| 8175 | 8194 | SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); |
| 8176 | 8195 | SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); |
| 8177 | 8196 | SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); |
| @@ -9032,17 +9051,18 @@ | ||
| 9032 | 9051 | ** accessing read-only databases */ |
| 9033 | 9052 | #define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */ |
| 9034 | 9053 | #define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */ |
| 9035 | 9054 | #define SQLITE_LegacyFileFmt 0x00100000 /* Create new databases in format 1 */ |
| 9036 | 9055 | #define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */ |
| 9037 | -#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ | |
| 9056 | +#define SQLITE_CkptFullFSync 0x00400000 /* Use full fsync for checkpoint */ | |
| 9038 | 9057 | #define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */ |
| 9039 | 9058 | #define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */ |
| 9040 | 9059 | #define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */ |
| 9041 | 9060 | #define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */ |
| 9042 | 9061 | #define SQLITE_AutoIndex 0x08000000 /* Enable automatic indexes */ |
| 9043 | 9062 | #define SQLITE_PreferBuiltin 0x10000000 /* Preference to built-in funcs */ |
| 9063 | +#define SQLITE_LoadExtension 0x20000000 /* Enable load_extension */ | |
| 9044 | 9064 | |
| 9045 | 9065 | /* |
| 9046 | 9066 | ** Bits of the sqlite3.flags field that are used by the |
| 9047 | 9067 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface. |
| 9048 | 9068 | ** These must be the low-order bits of the flags field. |
| @@ -10957,10 +10977,11 @@ | ||
| 10957 | 10977 | SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); |
| 10958 | 10978 | SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*); |
| 10959 | 10979 | SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); |
| 10960 | 10980 | SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); |
| 10961 | 10981 | SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); |
| 10982 | +SQLITE_PRIVATE int sqlite3Atoi(const char*); | |
| 10962 | 10983 | SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); |
| 10963 | 10984 | SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); |
| 10964 | 10985 | SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**); |
| 10965 | 10986 | |
| 10966 | 10987 | /* |
| @@ -20458,10 +20479,20 @@ | ||
| 20458 | 20479 | v = -v; |
| 20459 | 20480 | } |
| 20460 | 20481 | *pValue = (int)v; |
| 20461 | 20482 | return 1; |
| 20462 | 20483 | } |
| 20484 | + | |
| 20485 | +/* | |
| 20486 | +** Return a 32-bit integer value extracted from a string. If the | |
| 20487 | +** string is not an integer, just return 0. | |
| 20488 | +*/ | |
| 20489 | +SQLITE_PRIVATE int sqlite3Atoi(const char *z){ | |
| 20490 | + int x = 0; | |
| 20491 | + if( z ) sqlite3GetInt32(z, &x); | |
| 20492 | + return x; | |
| 20493 | +} | |
| 20463 | 20494 | |
| 20464 | 20495 | /* |
| 20465 | 20496 | ** The variable-length integer encoding is as follows: |
| 20466 | 20497 | ** |
| 20467 | 20498 | ** KEY: |
| @@ -21388,14 +21419,14 @@ | ||
| 21388 | 21419 | /* 130 */ "Real", |
| 21389 | 21420 | /* 131 */ "VNext", |
| 21390 | 21421 | /* 132 */ "VRename", |
| 21391 | 21422 | /* 133 */ "VUpdate", |
| 21392 | 21423 | /* 134 */ "Pagecount", |
| 21393 | - /* 135 */ "Trace", | |
| 21394 | - /* 136 */ "Noop", | |
| 21395 | - /* 137 */ "Explain", | |
| 21396 | - /* 138 */ "NotUsed_138", | |
| 21424 | + /* 135 */ "MaxPgcnt", | |
| 21425 | + /* 136 */ "Trace", | |
| 21426 | + /* 137 */ "Noop", | |
| 21427 | + /* 138 */ "Explain", | |
| 21397 | 21428 | /* 139 */ "NotUsed_139", |
| 21398 | 21429 | /* 140 */ "NotUsed_140", |
| 21399 | 21430 | /* 141 */ "ToText", |
| 21400 | 21431 | /* 142 */ "ToBlob", |
| 21401 | 21432 | /* 143 */ "ToNumeric", |
| @@ -27946,11 +27977,11 @@ | ||
| 27946 | 27977 | static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){ |
| 27947 | 27978 | static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; |
| 27948 | 27979 | #if defined(NO_GETTOD) |
| 27949 | 27980 | time_t t; |
| 27950 | 27981 | time(&t); |
| 27951 | - *piNow = ((sqlite3_int64)i)*1000 + unixEpoch; | |
| 27982 | + *piNow = ((sqlite3_int64)t)*1000 + unixEpoch; | |
| 27952 | 27983 | #elif OS_VXWORKS |
| 27953 | 27984 | struct timespec sNow; |
| 27954 | 27985 | clock_gettime(CLOCK_REALTIME, &sNow); |
| 27955 | 27986 | *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000; |
| 27956 | 27987 | #else |
| @@ -35273,11 +35304,12 @@ | ||
| 35273 | 35304 | u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ |
| 35274 | 35305 | u8 useJournal; /* Use a rollback journal on this file */ |
| 35275 | 35306 | u8 noReadlock; /* Do not bother to obtain readlocks */ |
| 35276 | 35307 | u8 noSync; /* Do not sync the journal if true */ |
| 35277 | 35308 | u8 fullSync; /* Do extra syncs of the journal for robustness */ |
| 35278 | - u8 sync_flags; /* One of SYNC_NORMAL or SYNC_FULL */ | |
| 35309 | + u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ | |
| 35310 | + u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ | |
| 35279 | 35311 | u8 tempFile; /* zFilename is a temporary file */ |
| 35280 | 35312 | u8 readOnly; /* True for a read-only database */ |
| 35281 | 35313 | u8 memDb; /* True to inhibit all file I/O */ |
| 35282 | 35314 | |
| 35283 | 35315 | /************************************************************************** |
| @@ -35957,11 +35989,11 @@ | ||
| 35957 | 35989 | }else{ |
| 35958 | 35990 | static const char zeroHdr[28] = {0}; |
| 35959 | 35991 | rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0); |
| 35960 | 35992 | } |
| 35961 | 35993 | if( rc==SQLITE_OK && !pPager->noSync ){ |
| 35962 | - rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags); | |
| 35994 | + rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags); | |
| 35963 | 35995 | } |
| 35964 | 35996 | |
| 35965 | 35997 | /* At this point the transaction is committed but the write lock |
| 35966 | 35998 | ** is still held on the file. If there is a size limit configured for |
| 35967 | 35999 | ** the persistent journal and the journal file currently consumes more |
| @@ -37409,11 +37441,11 @@ | ||
| 37409 | 37441 | testcase( rc!=SQLITE_OK ); |
| 37410 | 37442 | } |
| 37411 | 37443 | if( rc==SQLITE_OK && !pPager->noSync |
| 37412 | 37444 | && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) |
| 37413 | 37445 | ){ |
| 37414 | - rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); | |
| 37446 | + rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); | |
| 37415 | 37447 | } |
| 37416 | 37448 | if( rc==SQLITE_OK ){ |
| 37417 | 37449 | rc = pager_end_transaction(pPager, zMaster[0]!='\0'); |
| 37418 | 37450 | testcase( rc!=SQLITE_OK ); |
| 37419 | 37451 | } |
| @@ -37583,17 +37615,17 @@ | ||
| 37583 | 37615 | static int pagerWalFrames( |
| 37584 | 37616 | Pager *pPager, /* Pager object */ |
| 37585 | 37617 | PgHdr *pList, /* List of frames to log */ |
| 37586 | 37618 | Pgno nTruncate, /* Database size after this commit */ |
| 37587 | 37619 | int isCommit, /* True if this is a commit */ |
| 37588 | - int sync_flags /* Flags to pass to OsSync() (or 0) */ | |
| 37620 | + int syncFlags /* Flags to pass to OsSync() (or 0) */ | |
| 37589 | 37621 | ){ |
| 37590 | 37622 | int rc; /* Return code */ |
| 37591 | 37623 | |
| 37592 | 37624 | assert( pPager->pWal ); |
| 37593 | 37625 | rc = sqlite3WalFrames(pPager->pWal, |
| 37594 | - pPager->pageSize, pList, nTruncate, isCommit, sync_flags | |
| 37626 | + pPager->pageSize, pList, nTruncate, isCommit, syncFlags | |
| 37595 | 37627 | ); |
| 37596 | 37628 | if( rc==SQLITE_OK && pPager->pBackup ){ |
| 37597 | 37629 | PgHdr *p; |
| 37598 | 37630 | for(p=pList; p; p=p->pDirty){ |
| 37599 | 37631 | sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); |
| @@ -37918,19 +37950,54 @@ | ||
| 37918 | 37950 | ** of the journal header - being written in between the two |
| 37919 | 37951 | ** syncs). If we assume that writing a |
| 37920 | 37952 | ** single disk sector is atomic, then this mode provides |
| 37921 | 37953 | ** assurance that the journal will not be corrupted to the |
| 37922 | 37954 | ** point of causing damage to the database during rollback. |
| 37955 | +** | |
| 37956 | +** The above is for a rollback-journal mode. For WAL mode, OFF continues | |
| 37957 | +** to mean that no syncs ever occur. NORMAL means that the WAL is synced | |
| 37958 | +** prior to the start of checkpoint and that the database file is synced | |
| 37959 | +** at the conclusion of the checkpoint if the entire content of the WAL | |
| 37960 | +** was written back into the database. But no sync operations occur for | |
| 37961 | +** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL | |
| 37962 | +** file is synced following each commit operation, in addition to the | |
| 37963 | +** syncs associated with NORMAL. | |
| 37964 | +** | |
| 37965 | +** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The | |
| 37966 | +** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync | |
| 37967 | +** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an | |
| 37968 | +** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL | |
| 37969 | +** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the | |
| 37970 | +** synchronous=FULL versus synchronous=NORMAL setting determines when | |
| 37971 | +** the xSync primitive is called and is relevant to all platforms. | |
| 37923 | 37972 | ** |
| 37924 | 37973 | ** Numeric values associated with these states are OFF==1, NORMAL=2, |
| 37925 | 37974 | ** and FULL=3. |
| 37926 | 37975 | */ |
| 37927 | 37976 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 37928 | -SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){ | |
| 37977 | +SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel( | |
| 37978 | + Pager *pPager, /* The pager to set safety level for */ | |
| 37979 | + int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */ | |
| 37980 | + int bFullFsync, /* PRAGMA fullfsync */ | |
| 37981 | + int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */ | |
| 37982 | +){ | |
| 37983 | + assert( level>=1 && level<=3 ); | |
| 37929 | 37984 | pPager->noSync = (level==1 || pPager->tempFile) ?1:0; |
| 37930 | 37985 | pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0; |
| 37931 | - pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL); | |
| 37986 | + if( pPager->noSync ){ | |
| 37987 | + pPager->syncFlags = 0; | |
| 37988 | + pPager->ckptSyncFlags = 0; | |
| 37989 | + }else if( bFullFsync ){ | |
| 37990 | + pPager->syncFlags = SQLITE_SYNC_FULL; | |
| 37991 | + pPager->ckptSyncFlags = SQLITE_SYNC_FULL; | |
| 37992 | + }else if( bCkptFullFsync ){ | |
| 37993 | + pPager->syncFlags = SQLITE_SYNC_NORMAL; | |
| 37994 | + pPager->ckptSyncFlags = SQLITE_SYNC_FULL; | |
| 37995 | + }else{ | |
| 37996 | + pPager->syncFlags = SQLITE_SYNC_NORMAL; | |
| 37997 | + pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; | |
| 37998 | + } | |
| 37932 | 37999 | } |
| 37933 | 38000 | #endif |
| 37934 | 38001 | |
| 37935 | 38002 | /* |
| 37936 | 38003 | ** The following global variable is incremented whenever the library |
| @@ -38105,13 +38172,12 @@ | ||
| 38105 | 38172 | */ |
| 38106 | 38173 | SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ |
| 38107 | 38174 | if( mxPage>0 ){ |
| 38108 | 38175 | pPager->mxPgno = mxPage; |
| 38109 | 38176 | } |
| 38110 | - if( pPager->eState!=PAGER_OPEN && pPager->mxPgno<pPager->dbSize ){ | |
| 38111 | - pPager->mxPgno = pPager->dbSize; | |
| 38112 | - } | |
| 38177 | + assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */ | |
| 38178 | + assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */ | |
| 38113 | 38179 | return pPager->mxPgno; |
| 38114 | 38180 | } |
| 38115 | 38181 | |
| 38116 | 38182 | /* |
| 38117 | 38183 | ** The following set of routines are used to disable the simulated |
| @@ -38312,14 +38378,11 @@ | ||
| 38312 | 38378 | disable_simulated_io_errors(); |
| 38313 | 38379 | sqlite3BeginBenignMalloc(); |
| 38314 | 38380 | /* pPager->errCode = 0; */ |
| 38315 | 38381 | pPager->exclusiveMode = 0; |
| 38316 | 38382 | #ifndef SQLITE_OMIT_WAL |
| 38317 | - sqlite3WalClose(pPager->pWal, | |
| 38318 | - (pPager->noSync ? 0 : pPager->sync_flags), | |
| 38319 | - pPager->pageSize, pTmp | |
| 38320 | - ); | |
| 38383 | + sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); | |
| 38321 | 38384 | pPager->pWal = 0; |
| 38322 | 38385 | #endif |
| 38323 | 38386 | pager_reset(pPager); |
| 38324 | 38387 | if( MEMDB ){ |
| 38325 | 38388 | pager_unlock(pPager); |
| @@ -38481,11 +38544,11 @@ | ||
| 38481 | 38544 | ** and never needs to be updated. |
| 38482 | 38545 | */ |
| 38483 | 38546 | if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ |
| 38484 | 38547 | PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); |
| 38485 | 38548 | IOTRACE(("JSYNC %p\n", pPager)) |
| 38486 | - rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags); | |
| 38549 | + rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags); | |
| 38487 | 38550 | if( rc!=SQLITE_OK ) return rc; |
| 38488 | 38551 | } |
| 38489 | 38552 | IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr)); |
| 38490 | 38553 | rc = sqlite3OsWrite( |
| 38491 | 38554 | pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr |
| @@ -38493,12 +38556,12 @@ | ||
| 38493 | 38556 | if( rc!=SQLITE_OK ) return rc; |
| 38494 | 38557 | } |
| 38495 | 38558 | if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ |
| 38496 | 38559 | PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); |
| 38497 | 38560 | IOTRACE(("JSYNC %p\n", pPager)) |
| 38498 | - rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| | |
| 38499 | - (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) | |
| 38561 | + rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags| | |
| 38562 | + (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) | |
| 38500 | 38563 | ); |
| 38501 | 38564 | if( rc!=SQLITE_OK ) return rc; |
| 38502 | 38565 | } |
| 38503 | 38566 | |
| 38504 | 38567 | pPager->journalHdr = pPager->journalOff; |
| @@ -39084,11 +39147,12 @@ | ||
| 39084 | 39147 | pPager->memDb = (u8)memDb; |
| 39085 | 39148 | pPager->readOnly = (u8)readOnly; |
| 39086 | 39149 | assert( useJournal || pPager->tempFile ); |
| 39087 | 39150 | pPager->noSync = pPager->tempFile; |
| 39088 | 39151 | pPager->fullSync = pPager->noSync ?0:1; |
| 39089 | - pPager->sync_flags = SQLITE_SYNC_NORMAL; | |
| 39152 | + pPager->syncFlags = pPager->noSync ? 0 : SQLITE_SYNC_NORMAL; | |
| 39153 | + pPager->ckptSyncFlags = pPager->syncFlags; | |
| 39090 | 39154 | /* pPager->pFirst = 0; */ |
| 39091 | 39155 | /* pPager->pFirstSynced = 0; */ |
| 39092 | 39156 | /* pPager->pLast = 0; */ |
| 39093 | 39157 | pPager->nExtra = (u16)nExtra; |
| 39094 | 39158 | pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; |
| @@ -40207,23 +40271,23 @@ | ||
| 40207 | 40271 | } |
| 40208 | 40272 | return rc; |
| 40209 | 40273 | } |
| 40210 | 40274 | |
| 40211 | 40275 | /* |
| 40212 | -** Sync the pager file to disk. This is a no-op for in-memory files | |
| 40276 | +** Sync the database file to disk. This is a no-op for in-memory databases | |
| 40213 | 40277 | ** or pages with the Pager.noSync flag set. |
| 40214 | 40278 | ** |
| 40215 | -** If successful, or called on a pager for which it is a no-op, this | |
| 40279 | +** If successful, or if called on a pager for which it is a no-op, this | |
| 40216 | 40280 | ** function returns SQLITE_OK. Otherwise, an IO error code is returned. |
| 40217 | 40281 | */ |
| 40218 | 40282 | SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){ |
| 40219 | 40283 | int rc; /* Return code */ |
| 40220 | 40284 | assert( !MEMDB ); |
| 40221 | 40285 | if( pPager->noSync ){ |
| 40222 | 40286 | rc = SQLITE_OK; |
| 40223 | 40287 | }else{ |
| 40224 | - rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); | |
| 40288 | + rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); | |
| 40225 | 40289 | } |
| 40226 | 40290 | return rc; |
| 40227 | 40291 | } |
| 40228 | 40292 | |
| 40229 | 40293 | /* |
| @@ -40308,11 +40372,11 @@ | ||
| 40308 | 40372 | }else{ |
| 40309 | 40373 | if( pagerUseWal(pPager) ){ |
| 40310 | 40374 | PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); |
| 40311 | 40375 | if( pList ){ |
| 40312 | 40376 | rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1, |
| 40313 | - (pPager->fullSync ? pPager->sync_flags : 0) | |
| 40377 | + (pPager->fullSync ? pPager->syncFlags : 0) | |
| 40314 | 40378 | ); |
| 40315 | 40379 | } |
| 40316 | 40380 | if( rc==SQLITE_OK ){ |
| 40317 | 40381 | sqlite3PcacheCleanAll(pPager->pPCache); |
| 40318 | 40382 | } |
| @@ -40439,11 +40503,11 @@ | ||
| 40439 | 40503 | if( rc!=SQLITE_OK ) goto commit_phase_one_exit; |
| 40440 | 40504 | } |
| 40441 | 40505 | |
| 40442 | 40506 | /* Finally, sync the database file. */ |
| 40443 | 40507 | if( !pPager->noSync && !noSync ){ |
| 40444 | - rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); | |
| 40508 | + rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); | |
| 40445 | 40509 | } |
| 40446 | 40510 | IOTRACE(("DBSYNC %p\n", pPager)) |
| 40447 | 40511 | } |
| 40448 | 40512 | } |
| 40449 | 40513 | |
| @@ -41180,14 +41244,12 @@ | ||
| 41180 | 41244 | */ |
| 41181 | 41245 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager){ |
| 41182 | 41246 | int rc = SQLITE_OK; |
| 41183 | 41247 | if( pPager->pWal ){ |
| 41184 | 41248 | u8 *zBuf = (u8 *)pPager->pTmpSpace; |
| 41185 | - rc = sqlite3WalCheckpoint(pPager->pWal, | |
| 41186 | - (pPager->noSync ? 0 : pPager->sync_flags), | |
| 41187 | - pPager->pageSize, zBuf | |
| 41188 | - ); | |
| 41249 | + rc = sqlite3WalCheckpoint(pPager->pWal, pPager->ckptSyncFlags, | |
| 41250 | + pPager->pageSize, zBuf); | |
| 41189 | 41251 | } |
| 41190 | 41252 | return rc; |
| 41191 | 41253 | } |
| 41192 | 41254 | |
| 41193 | 41255 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ |
| @@ -41335,14 +41397,12 @@ | ||
| 41335 | 41397 | ** the database file, the log and log-summary files will be deleted. |
| 41336 | 41398 | */ |
| 41337 | 41399 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 41338 | 41400 | rc = pagerExclusiveLock(pPager); |
| 41339 | 41401 | if( rc==SQLITE_OK ){ |
| 41340 | - rc = sqlite3WalClose(pPager->pWal, | |
| 41341 | - (pPager->noSync ? 0 : pPager->sync_flags), | |
| 41342 | - pPager->pageSize, (u8*)pPager->pTmpSpace | |
| 41343 | - ); | |
| 41402 | + rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, | |
| 41403 | + pPager->pageSize, (u8*)pPager->pTmpSpace); | |
| 41344 | 41404 | pPager->pWal = 0; |
| 41345 | 41405 | } |
| 41346 | 41406 | } |
| 41347 | 41407 | return rc; |
| 41348 | 41408 | } |
| @@ -47231,15 +47291,21 @@ | ||
| 47231 | 47291 | ** there is a high probability of damage) Level 2 is the default. There |
| 47232 | 47292 | ** is a very low but non-zero probability of damage. Level 3 reduces the |
| 47233 | 47293 | ** probability of damage to near zero but with a write performance reduction. |
| 47234 | 47294 | */ |
| 47235 | 47295 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 47236 | -SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ | |
| 47296 | +SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel( | |
| 47297 | + Btree *p, /* The btree to set the safety level on */ | |
| 47298 | + int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */ | |
| 47299 | + int fullSync, /* PRAGMA fullfsync. */ | |
| 47300 | + int ckptFullSync /* PRAGMA checkpoint_fullfync */ | |
| 47301 | +){ | |
| 47237 | 47302 | BtShared *pBt = p->pBt; |
| 47238 | 47303 | assert( sqlite3_mutex_held(p->db->mutex) ); |
| 47304 | + assert( level>=1 && level<=3 ); | |
| 47239 | 47305 | sqlite3BtreeEnter(p); |
| 47240 | - sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync); | |
| 47306 | + sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync, ckptFullSync); | |
| 47241 | 47307 | sqlite3BtreeLeave(p); |
| 47242 | 47308 | return SQLITE_OK; |
| 47243 | 47309 | } |
| 47244 | 47310 | #endif |
| 47245 | 47311 | |
| @@ -59986,17 +60052,17 @@ | ||
| 59986 | 60052 | /* |
| 59987 | 60053 | ** Try to convert the type of a function argument or a result column |
| 59988 | 60054 | ** into a numeric representation. Use either INTEGER or REAL whichever |
| 59989 | 60055 | ** is appropriate. But only do the conversion if it is possible without |
| 59990 | 60056 | ** loss of information and return the revised type of the argument. |
| 59991 | -** | |
| 59992 | -** This is an EXPERIMENTAL api and is subject to change or removal. | |
| 59993 | 60057 | */ |
| 59994 | 60058 | SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ |
| 59995 | 60059 | Mem *pMem = (Mem*)pVal; |
| 59996 | - applyNumericAffinity(pMem); | |
| 59997 | - sqlite3VdbeMemStoreType(pMem); | |
| 60060 | + if( pMem->type==SQLITE_TEXT ){ | |
| 60061 | + applyNumericAffinity(pMem); | |
| 60062 | + sqlite3VdbeMemStoreType(pMem); | |
| 60063 | + } | |
| 59998 | 60064 | return pMem->type; |
| 59999 | 60065 | } |
| 60000 | 60066 | |
| 60001 | 60067 | /* |
| 60002 | 60068 | ** Exported version of applyAffinity(). This one works on sqlite3_value*, |
| @@ -66078,10 +66144,36 @@ | ||
| 66078 | 66144 | case OP_Pagecount: { /* out2-prerelease */ |
| 66079 | 66145 | pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt); |
| 66080 | 66146 | break; |
| 66081 | 66147 | } |
| 66082 | 66148 | #endif |
| 66149 | + | |
| 66150 | + | |
| 66151 | +#ifndef SQLITE_OMIT_PAGER_PRAGMAS | |
| 66152 | +/* Opcode: MaxPgcnt P1 P2 P3 * * | |
| 66153 | +** | |
| 66154 | +** Try to set the maximum page count for database P1 to the value in P3. | |
| 66155 | +** Do not let the maximum page count fall below the current page count and | |
| 66156 | +** do not change the maximum page count value if P3==0. | |
| 66157 | +** | |
| 66158 | +** Store the maximum page count after the change in register P2. | |
| 66159 | +*/ | |
| 66160 | +case OP_MaxPgcnt: { /* out2-prerelease */ | |
| 66161 | + unsigned int newMax; | |
| 66162 | + Btree *pBt; | |
| 66163 | + | |
| 66164 | + pBt = db->aDb[pOp->p1].pBt; | |
| 66165 | + newMax = 0; | |
| 66166 | + if( pOp->p3 ){ | |
| 66167 | + newMax = sqlite3BtreeLastPage(pBt); | |
| 66168 | + if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3; | |
| 66169 | + } | |
| 66170 | + pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax); | |
| 66171 | + break; | |
| 66172 | +} | |
| 66173 | +#endif | |
| 66174 | + | |
| 66083 | 66175 | |
| 66084 | 66176 | #ifndef SQLITE_OMIT_TRACE |
| 66085 | 66177 | /* Opcode: Trace * * * P4 * |
| 66086 | 66178 | ** |
| 66087 | 66179 | ** If tracing is enabled (by the sqlite3_trace()) interface, then |
| @@ -85223,11 +85315,11 @@ | ||
| 85223 | 85315 | static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; |
| 85224 | 85316 | static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; |
| 85225 | 85317 | static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; |
| 85226 | 85318 | int i, n; |
| 85227 | 85319 | if( sqlite3Isdigit(*z) ){ |
| 85228 | - return (u8)atoi(z); | |
| 85320 | + return (u8)sqlite3Atoi(z); | |
| 85229 | 85321 | } |
| 85230 | 85322 | n = sqlite3Strlen30(z); |
| 85231 | 85323 | for(i=0; i<ArraySize(iLength); i++){ |
| 85232 | 85324 | if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){ |
| 85233 | 85325 | return iValue[i]; |
| @@ -85264,11 +85356,11 @@ | ||
| 85264 | 85356 | static int getAutoVacuum(const char *z){ |
| 85265 | 85357 | int i; |
| 85266 | 85358 | if( 0==sqlite3StrICmp(z, "none") ) return BTREE_AUTOVACUUM_NONE; |
| 85267 | 85359 | if( 0==sqlite3StrICmp(z, "full") ) return BTREE_AUTOVACUUM_FULL; |
| 85268 | 85360 | if( 0==sqlite3StrICmp(z, "incremental") ) return BTREE_AUTOVACUUM_INCR; |
| 85269 | - i = atoi(z); | |
| 85361 | + i = sqlite3Atoi(z); | |
| 85270 | 85362 | return (u8)((i>=0&&i<=2)?i:0); |
| 85271 | 85363 | } |
| 85272 | 85364 | #endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ |
| 85273 | 85365 | |
| 85274 | 85366 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| @@ -85360,10 +85452,11 @@ | ||
| 85360 | 85452 | { "short_column_names", SQLITE_ShortColNames }, |
| 85361 | 85453 | { "count_changes", SQLITE_CountRows }, |
| 85362 | 85454 | { "empty_result_callbacks", SQLITE_NullCallback }, |
| 85363 | 85455 | { "legacy_file_format", SQLITE_LegacyFileFmt }, |
| 85364 | 85456 | { "fullfsync", SQLITE_FullFSync }, |
| 85457 | + { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, | |
| 85365 | 85458 | { "reverse_unordered_selects", SQLITE_ReverseOrder }, |
| 85366 | 85459 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX |
| 85367 | 85460 | { "automatic_index", SQLITE_AutoIndex }, |
| 85368 | 85461 | #endif |
| 85369 | 85462 | #ifdef SQLITE_DEBUG |
| @@ -85571,11 +85664,11 @@ | ||
| 85571 | 85664 | addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); |
| 85572 | 85665 | sqlite3VdbeChangeP1(v, addr, iDb); |
| 85573 | 85666 | sqlite3VdbeChangeP1(v, addr+1, iDb); |
| 85574 | 85667 | sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE); |
| 85575 | 85668 | }else{ |
| 85576 | - int size = atoi(zRight); | |
| 85669 | + int size = sqlite3Atoi(zRight); | |
| 85577 | 85670 | if( size<0 ) size = -size; |
| 85578 | 85671 | sqlite3BeginWriteOperation(pParse, 0, iDb); |
| 85579 | 85672 | sqlite3VdbeAddOp2(v, OP_Integer, size, 1); |
| 85580 | 85673 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); |
| 85581 | 85674 | pDb->pSchema->cache_size = size; |
| @@ -85600,39 +85693,17 @@ | ||
| 85600 | 85693 | returnSingleInt(pParse, "page_size", size); |
| 85601 | 85694 | }else{ |
| 85602 | 85695 | /* Malloc may fail when setting the page-size, as there is an internal |
| 85603 | 85696 | ** buffer that the pager module resizes using sqlite3_realloc(). |
| 85604 | 85697 | */ |
| 85605 | - db->nextPagesize = atoi(zRight); | |
| 85698 | + db->nextPagesize = sqlite3Atoi(zRight); | |
| 85606 | 85699 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
| 85607 | 85700 | db->mallocFailed = 1; |
| 85608 | 85701 | } |
| 85609 | 85702 | } |
| 85610 | 85703 | }else |
| 85611 | 85704 | |
| 85612 | - /* | |
| 85613 | - ** PRAGMA [database.]max_page_count | |
| 85614 | - ** PRAGMA [database.]max_page_count=N | |
| 85615 | - ** | |
| 85616 | - ** The first form reports the current setting for the | |
| 85617 | - ** maximum number of pages in the database file. The | |
| 85618 | - ** second form attempts to change this setting. Both | |
| 85619 | - ** forms return the current setting. | |
| 85620 | - */ | |
| 85621 | - if( sqlite3StrICmp(zLeft,"max_page_count")==0 ){ | |
| 85622 | - Btree *pBt = pDb->pBt; | |
| 85623 | - int newMax = 0; | |
| 85624 | - assert( pBt!=0 ); | |
| 85625 | - if( zRight ){ | |
| 85626 | - newMax = atoi(zRight); | |
| 85627 | - } | |
| 85628 | - if( ALWAYS(pBt) ){ | |
| 85629 | - newMax = sqlite3BtreeMaxPageCount(pBt, newMax); | |
| 85630 | - } | |
| 85631 | - returnSingleInt(pParse, "max_page_count", newMax); | |
| 85632 | - }else | |
| 85633 | - | |
| 85634 | 85705 | /* |
| 85635 | 85706 | ** PRAGMA [database.]secure_delete |
| 85636 | 85707 | ** PRAGMA [database.]secure_delete=ON/OFF |
| 85637 | 85708 | ** |
| 85638 | 85709 | ** The first form reports the current setting for the |
| @@ -85655,23 +85726,37 @@ | ||
| 85655 | 85726 | b = sqlite3BtreeSecureDelete(pBt, b); |
| 85656 | 85727 | returnSingleInt(pParse, "secure_delete", b); |
| 85657 | 85728 | }else |
| 85658 | 85729 | |
| 85659 | 85730 | /* |
| 85731 | + ** PRAGMA [database.]max_page_count | |
| 85732 | + ** PRAGMA [database.]max_page_count=N | |
| 85733 | + ** | |
| 85734 | + ** The first form reports the current setting for the | |
| 85735 | + ** maximum number of pages in the database file. The | |
| 85736 | + ** second form attempts to change this setting. Both | |
| 85737 | + ** forms return the current setting. | |
| 85738 | + ** | |
| 85660 | 85739 | ** PRAGMA [database.]page_count |
| 85661 | 85740 | ** |
| 85662 | 85741 | ** Return the number of pages in the specified database. |
| 85663 | 85742 | */ |
| 85664 | - if( sqlite3StrICmp(zLeft,"page_count")==0 ){ | |
| 85743 | + if( sqlite3StrICmp(zLeft,"page_count")==0 | |
| 85744 | + || sqlite3StrICmp(zLeft,"max_page_count")==0 | |
| 85745 | + ){ | |
| 85665 | 85746 | int iReg; |
| 85666 | 85747 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 85667 | 85748 | sqlite3CodeVerifySchema(pParse, iDb); |
| 85668 | 85749 | iReg = ++pParse->nMem; |
| 85669 | - sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); | |
| 85750 | + if( zLeft[0]=='p' ){ | |
| 85751 | + sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); | |
| 85752 | + }else{ | |
| 85753 | + sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, sqlite3Atoi(zRight)); | |
| 85754 | + } | |
| 85670 | 85755 | sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); |
| 85671 | 85756 | sqlite3VdbeSetNumCols(v, 1); |
| 85672 | - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "page_count", SQLITE_STATIC); | |
| 85757 | + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); | |
| 85673 | 85758 | }else |
| 85674 | 85759 | |
| 85675 | 85760 | /* |
| 85676 | 85761 | ** PRAGMA [database.]locking_mode |
| 85677 | 85762 | ** PRAGMA [database.]locking_mode = (normal|exclusive) |
| @@ -85889,11 +85974,11 @@ | ||
| 85889 | 85974 | if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ |
| 85890 | 85975 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 85891 | 85976 | if( !zRight ){ |
| 85892 | 85977 | returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); |
| 85893 | 85978 | }else{ |
| 85894 | - int size = atoi(zRight); | |
| 85979 | + int size = sqlite3Atoi(zRight); | |
| 85895 | 85980 | if( size<0 ) size = -size; |
| 85896 | 85981 | pDb->pSchema->cache_size = size; |
| 85897 | 85982 | sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
| 85898 | 85983 | } |
| 85899 | 85984 | }else |
| @@ -86282,11 +86367,11 @@ | ||
| 86282 | 86367 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); |
| 86283 | 86368 | |
| 86284 | 86369 | /* Set the maximum error count */ |
| 86285 | 86370 | mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
| 86286 | 86371 | if( zRight ){ |
| 86287 | - mxErr = atoi(zRight); | |
| 86372 | + sqlite3GetInt32(zRight, &mxErr); | |
| 86288 | 86373 | if( mxErr<=0 ){ |
| 86289 | 86374 | mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
| 86290 | 86375 | } |
| 86291 | 86376 | } |
| 86292 | 86377 | sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */ |
| @@ -86539,11 +86624,11 @@ | ||
| 86539 | 86624 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 86540 | 86625 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| 86541 | 86626 | }; |
| 86542 | 86627 | int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); |
| 86543 | 86628 | sqlite3VdbeChangeP1(v, addr, iDb); |
| 86544 | - sqlite3VdbeChangeP1(v, addr+1, atoi(zRight)); | |
| 86629 | + sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight)); | |
| 86545 | 86630 | sqlite3VdbeChangeP1(v, addr+2, iDb); |
| 86546 | 86631 | sqlite3VdbeChangeP2(v, addr+2, iCookie); |
| 86547 | 86632 | }else{ |
| 86548 | 86633 | /* Read the specified cookie value */ |
| 86549 | 86634 | static const VdbeOpList readCookie[] = { |
| @@ -86600,12 +86685,11 @@ | ||
| 86600 | 86685 | ** after accumulating N frames in the log. Or query for the current value |
| 86601 | 86686 | ** of N. |
| 86602 | 86687 | */ |
| 86603 | 86688 | if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){ |
| 86604 | 86689 | if( zRight ){ |
| 86605 | - int nAuto = atoi(zRight); | |
| 86606 | - sqlite3_wal_autocheckpoint(db, nAuto); | |
| 86690 | + sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); | |
| 86607 | 86691 | } |
| 86608 | 86692 | returnSingleInt(pParse, "wal_autocheckpoint", |
| 86609 | 86693 | db->xWalCallback==sqlite3WalDefaultHook ? |
| 86610 | 86694 | SQLITE_PTR_TO_INT(db->pWalArg) : 0); |
| 86611 | 86695 | }else |
| @@ -86691,11 +86775,12 @@ | ||
| 86691 | 86775 | ** setting changed. |
| 86692 | 86776 | */ |
| 86693 | 86777 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 86694 | 86778 | if( db->autoCommit ){ |
| 86695 | 86779 | sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, |
| 86696 | - (db->flags&SQLITE_FullFSync)!=0); | |
| 86780 | + (db->flags&SQLITE_FullFSync)!=0, | |
| 86781 | + (db->flags&SQLITE_CkptFullFSync)!=0); | |
| 86697 | 86782 | } |
| 86698 | 86783 | #endif |
| 86699 | 86784 | pragma_out: |
| 86700 | 86785 | sqlite3DbFree(db, zLeft); |
| 86701 | 86786 | sqlite3DbFree(db, zRight); |
| @@ -86783,11 +86868,11 @@ | ||
| 86783 | 86868 | sqlite3_stmt *pStmt; |
| 86784 | 86869 | TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ |
| 86785 | 86870 | |
| 86786 | 86871 | assert( db->init.busy ); |
| 86787 | 86872 | db->init.iDb = iDb; |
| 86788 | - db->init.newTnum = atoi(argv[1]); | |
| 86873 | + db->init.newTnum = sqlite3Atoi(argv[1]); | |
| 86789 | 86874 | db->init.orphanTrigger = 0; |
| 86790 | 86875 | TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); |
| 86791 | 86876 | rc = db->errCode; |
| 86792 | 86877 | assert( (rc&0xFF)==(rcp&0xFF) ); |
| 86793 | 86878 | db->init.iDb = 0; |
| @@ -99731,11 +99816,11 @@ | ||
| 99731 | 99816 | ** loop below generates code for a single nested loop of the VM |
| 99732 | 99817 | ** program. |
| 99733 | 99818 | */ |
| 99734 | 99819 | notReady = ~(Bitmask)0; |
| 99735 | 99820 | for(i=0; i<nTabList; i++){ |
| 99736 | - WhereLevel *pLevel = &pWInfo->a[i]; | |
| 99821 | + pLevel = &pWInfo->a[i]; | |
| 99737 | 99822 | explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags); |
| 99738 | 99823 | notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady); |
| 99739 | 99824 | pWInfo->iContinue = pLevel->addrCont; |
| 99740 | 99825 | } |
| 99741 | 99826 | |
| @@ -106890,11 +106975,14 @@ | ||
| 106890 | 106975 | sqlite3BtreeEnter(pBtree); |
| 106891 | 106976 | pPager = sqlite3BtreePager(pBtree); |
| 106892 | 106977 | assert( pPager!=0 ); |
| 106893 | 106978 | fd = sqlite3PagerFile(pPager); |
| 106894 | 106979 | assert( fd!=0 ); |
| 106895 | - if( fd->pMethods ){ | |
| 106980 | + if( op==SQLITE_FCNTL_FILE_POINTER ){ | |
| 106981 | + *(sqlite3_file**)pArg = fd; | |
| 106982 | + rc = SQLITE_OK; | |
| 106983 | + }else if( fd->pMethods ){ | |
| 106896 | 106984 | rc = sqlite3OsFileControl(fd, op, pArg); |
| 106897 | 106985 | } |
| 106898 | 106986 | sqlite3BtreeLeave(pBtree); |
| 106899 | 106987 | } |
| 106900 | 106988 | } |
| @@ -108194,19 +108282,23 @@ | ||
| 108194 | 108282 | i16 eSearch; /* Search strategy (see below) */ |
| 108195 | 108283 | u8 isEof; /* True if at End Of Results */ |
| 108196 | 108284 | u8 isRequireSeek; /* True if must seek pStmt to %_content row */ |
| 108197 | 108285 | sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ |
| 108198 | 108286 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 108287 | + int nPhrase; /* Number of matchable phrases in query */ | |
| 108199 | 108288 | Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ |
| 108200 | 108289 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 108201 | 108290 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 108202 | 108291 | char *aDoclist; /* List of docids for full-text queries */ |
| 108203 | 108292 | int nDoclist; /* Size of buffer at aDoclist */ |
| 108204 | - int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ | |
| 108205 | - u32 *aMatchinfo; /* Information about most recent match */ | |
| 108206 | 108293 | int eEvalmode; /* An FTS3_EVAL_XX constant */ |
| 108207 | 108294 | int nRowAvg; /* Average size of database rows, in pages */ |
| 108295 | + | |
| 108296 | + int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ | |
| 108297 | + u32 *aMatchinfo; /* Information about most recent match */ | |
| 108298 | + int nMatchinfo; /* Number of elements in aMatchinfo[] */ | |
| 108299 | + char *zMatchinfo; /* Matchinfo specification */ | |
| 108208 | 108300 | }; |
| 108209 | 108301 | |
| 108210 | 108302 | #define FTS3_EVAL_FILTER 0 |
| 108211 | 108303 | #define FTS3_EVAL_NEXT 1 |
| 108212 | 108304 | #define FTS3_EVAL_MATCHINFO 2 |
| @@ -108309,25 +108401,26 @@ | ||
| 108309 | 108401 | /* fts3_write.c */ |
| 108310 | 108402 | SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); |
| 108311 | 108403 | SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *); |
| 108312 | 108404 | SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *); |
| 108313 | 108405 | SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *); |
| 108314 | -SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64, | |
| 108406 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, sqlite3_int64, | |
| 108315 | 108407 | sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); |
| 108316 | 108408 | SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**); |
| 108317 | -SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *); | |
| 108409 | +SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *); | |
| 108318 | 108410 | SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate( |
| 108319 | 108411 | Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, |
| 108320 | 108412 | int (*)(Fts3Table *, void *, char *, int, char *, int), void * |
| 108321 | 108413 | ); |
| 108322 | 108414 | SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(Fts3Cursor *, Fts3SegReader *, int *); |
| 108323 | 108415 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
| 108324 | -SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*); | |
| 108325 | -SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*); | |
| 108326 | 108416 | SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); |
| 108327 | 108417 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*); |
| 108328 | 108418 | |
| 108419 | +SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); | |
| 108420 | +SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); | |
| 108421 | + | |
| 108329 | 108422 | SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *); |
| 108330 | 108423 | SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int); |
| 108331 | 108424 | SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *); |
| 108332 | 108425 | SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *); |
| 108333 | 108426 | SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *, int *); |
| @@ -108371,11 +108464,11 @@ | ||
| 108371 | 108464 | /* fts3_snippet.c */ |
| 108372 | 108465 | SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); |
| 108373 | 108466 | SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, |
| 108374 | 108467 | const char *, const char *, int, int |
| 108375 | 108468 | ); |
| 108376 | -SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *); | |
| 108469 | +SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); | |
| 108377 | 108470 | |
| 108378 | 108471 | /* fts3_expr.c */ |
| 108379 | 108472 | SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, |
| 108380 | 108473 | char **, int, int, const char *, int, Fts3Expr ** |
| 108381 | 108474 | ); |
| @@ -108684,46 +108777,10 @@ | ||
| 108684 | 108777 | ); |
| 108685 | 108778 | } |
| 108686 | 108779 | return rc; |
| 108687 | 108780 | } |
| 108688 | 108781 | |
| 108689 | -/* | |
| 108690 | -** An sqlite3_exec() callback for fts3TableExists. | |
| 108691 | -*/ | |
| 108692 | -static int fts3TableExistsCallback(void *pArg, int n, char **pp1, char **pp2){ | |
| 108693 | - UNUSED_PARAMETER(n); | |
| 108694 | - UNUSED_PARAMETER(pp1); | |
| 108695 | - UNUSED_PARAMETER(pp2); | |
| 108696 | - *(int*)pArg = 1; | |
| 108697 | - return 1; | |
| 108698 | -} | |
| 108699 | - | |
| 108700 | -/* | |
| 108701 | -** Determine if a table currently exists in the database. | |
| 108702 | -*/ | |
| 108703 | -static void fts3TableExists( | |
| 108704 | - int *pRc, /* Success code */ | |
| 108705 | - sqlite3 *db, /* The database connection to test */ | |
| 108706 | - const char *zDb, /* ATTACHed database within the connection */ | |
| 108707 | - const char *zName, /* Name of the FTS3 table */ | |
| 108708 | - const char *zSuffix, /* Shadow table extension */ | |
| 108709 | - u8 *pResult /* Write results here */ | |
| 108710 | -){ | |
| 108711 | - int rc = SQLITE_OK; | |
| 108712 | - int res = 0; | |
| 108713 | - char *zSql; | |
| 108714 | - if( *pRc ) return; | |
| 108715 | - zSql = sqlite3_mprintf( | |
| 108716 | - "SELECT 1 FROM %Q.sqlite_master WHERE name='%q%s'", | |
| 108717 | - zDb, zName, zSuffix | |
| 108718 | - ); | |
| 108719 | - rc = sqlite3_exec(db, zSql, fts3TableExistsCallback, &res, 0); | |
| 108720 | - sqlite3_free(zSql); | |
| 108721 | - *pResult = (u8)(res & 0xff); | |
| 108722 | - if( rc!=SQLITE_ABORT ) *pRc = rc; | |
| 108723 | -} | |
| 108724 | - | |
| 108725 | 108782 | /* |
| 108726 | 108783 | ** Store the current database page-size in bytes in p->nPgsz. |
| 108727 | 108784 | ** |
| 108728 | 108785 | ** If *pRc is non-zero when this function is called, it is a no-op. |
| 108729 | 108786 | ** Otherwise, if an error occurs, an SQLite error code is stored in *pRc |
| @@ -109137,11 +109194,10 @@ | ||
| 109137 | 109194 | ** a prefix. |
| 109138 | 109195 | ** |
| 109139 | 109196 | ** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK. |
| 109140 | 109197 | */ |
| 109141 | 109198 | static int fts3ScanInteriorNode( |
| 109142 | - Fts3Table *p, /* Virtual table handle */ | |
| 109143 | 109199 | const char *zTerm, /* Term to select leaves for */ |
| 109144 | 109200 | int nTerm, /* Size of term zTerm in bytes */ |
| 109145 | 109201 | const char *zNode, /* Buffer containing segment interior node */ |
| 109146 | 109202 | int nNode, /* Size of buffer at zNode */ |
| 109147 | 109203 | sqlite3_int64 *piFirst, /* OUT: Selected child node */ |
| @@ -109272,11 +109328,11 @@ | ||
| 109272 | 109328 | int iHeight; /* Height of this node in tree */ |
| 109273 | 109329 | |
| 109274 | 109330 | assert( piLeaf || piLeaf2 ); |
| 109275 | 109331 | |
| 109276 | 109332 | sqlite3Fts3GetVarint32(zNode, &iHeight); |
| 109277 | - rc = fts3ScanInteriorNode(p, zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); | |
| 109333 | + rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); | |
| 109278 | 109334 | assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); |
| 109279 | 109335 | |
| 109280 | 109336 | if( rc==SQLITE_OK && iHeight>1 ){ |
| 109281 | 109337 | char *zBlob = 0; /* Blob read from %_segments table */ |
| 109282 | 109338 | int nBlob; /* Size of zBlob in bytes */ |
| @@ -110071,11 +110127,11 @@ | ||
| 110071 | 110127 | */ |
| 110072 | 110128 | static void fts3SegReaderArrayFree(Fts3SegReaderArray *pArray){ |
| 110073 | 110129 | if( pArray ){ |
| 110074 | 110130 | int i; |
| 110075 | 110131 | for(i=0; i<pArray->nSegment; i++){ |
| 110076 | - sqlite3Fts3SegReaderFree(0, pArray->apSegment[i]); | |
| 110132 | + sqlite3Fts3SegReaderFree(pArray->apSegment[i]); | |
| 110077 | 110133 | } |
| 110078 | 110134 | sqlite3_free(pArray); |
| 110079 | 110135 | } |
| 110080 | 110136 | } |
| 110081 | 110137 | |
| @@ -110089,11 +110145,11 @@ | ||
| 110089 | 110145 | int nNew = (pArray ? pArray->nAlloc+16 : 16); |
| 110090 | 110146 | pArray = (Fts3SegReaderArray *)sqlite3_realloc(pArray, |
| 110091 | 110147 | sizeof(Fts3SegReaderArray) + (nNew-1) * sizeof(Fts3SegReader*) |
| 110092 | 110148 | ); |
| 110093 | 110149 | if( !pArray ){ |
| 110094 | - sqlite3Fts3SegReaderFree(0, pNew); | |
| 110150 | + sqlite3Fts3SegReaderFree(pNew); | |
| 110095 | 110151 | return SQLITE_NOMEM; |
| 110096 | 110152 | } |
| 110097 | 110153 | if( nNew==16 ){ |
| 110098 | 110154 | pArray->nSegment = 0; |
| 110099 | 110155 | pArray->nCost = 0; |
| @@ -110142,18 +110198,18 @@ | ||
| 110142 | 110198 | if( sqlite3_column_int64(pStmt, 1)==0 ){ |
| 110143 | 110199 | /* The entire segment is stored on the root node (which must be a |
| 110144 | 110200 | ** leaf). Do not bother inspecting any data in this case, just |
| 110145 | 110201 | ** create a Fts3SegReader to scan the single leaf. |
| 110146 | 110202 | */ |
| 110147 | - rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew); | |
| 110203 | + rc = sqlite3Fts3SegReaderNew(iAge, 0, 0, 0, zRoot, nRoot, &pNew); | |
| 110148 | 110204 | }else{ |
| 110149 | 110205 | sqlite3_int64 i1; /* First leaf that may contain zTerm */ |
| 110150 | 110206 | sqlite3_int64 i2; /* Final leaf that may contain zTerm */ |
| 110151 | 110207 | rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1, (isPrefix?&i2:0)); |
| 110152 | 110208 | if( isPrefix==0 ) i2 = i1; |
| 110153 | 110209 | if( rc==SQLITE_OK ){ |
| 110154 | - rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew); | |
| 110210 | + rc = sqlite3Fts3SegReaderNew(iAge, i1, i2, 0, 0, 0, &pNew); | |
| 110155 | 110211 | } |
| 110156 | 110212 | } |
| 110157 | 110213 | assert( (pNew==0)==(rc!=SQLITE_OK) ); |
| 110158 | 110214 | |
| 110159 | 110215 | /* If a new Fts3SegReader was allocated, add it to the array. */ |
| @@ -110369,13 +110425,13 @@ | ||
| 110369 | 110425 | } |
| 110370 | 110426 | } |
| 110371 | 110427 | |
| 110372 | 110428 | for(ii=0; ii<pPhrase->nToken; ii++){ |
| 110373 | 110429 | Fts3PhraseToken *pTok; /* Token to find doclist for */ |
| 110374 | - int iTok; /* The token being queried this iteration */ | |
| 110375 | - char *pList; /* Pointer to token doclist */ | |
| 110376 | - int nList; /* Size of buffer at pList */ | |
| 110430 | + int iTok = 0; /* The token being queried this iteration */ | |
| 110431 | + char *pList = 0; /* Pointer to token doclist */ | |
| 110432 | + int nList = 0; /* Size of buffer at pList */ | |
| 110377 | 110433 | |
| 110378 | 110434 | /* Select a token to process. If this is an xFilter() call, then tokens |
| 110379 | 110435 | ** are processed in order from least to most costly. Otherwise, tokens |
| 110380 | 110436 | ** are processed in the order in which they occur in the phrase. |
| 110381 | 110437 | */ |
| @@ -110413,12 +110469,13 @@ | ||
| 110413 | 110469 | } |
| 110414 | 110470 | |
| 110415 | 110471 | if( pCsr->eEvalmode==FTS3_EVAL_NEXT && pTok->pDeferred ){ |
| 110416 | 110472 | rc = fts3DeferredTermSelect(pTok->pDeferred, isTermPos, &nList, &pList); |
| 110417 | 110473 | }else{ |
| 110418 | - assert( pTok->pArray ); | |
| 110419 | - rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList); | |
| 110474 | + if( pTok->pArray ){ | |
| 110475 | + rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList); | |
| 110476 | + } | |
| 110420 | 110477 | pTok->bFulltext = 1; |
| 110421 | 110478 | } |
| 110422 | 110479 | assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pArray==0 ); |
| 110423 | 110480 | if( rc!=SQLITE_OK ) break; |
| 110424 | 110481 | |
| @@ -110635,18 +110692,21 @@ | ||
| 110635 | 110692 | /* |
| 110636 | 110693 | ** Return the sum of the costs of all tokens in the expression pExpr. This |
| 110637 | 110694 | ** function must be called after Fts3SegReaderArrays have been allocated |
| 110638 | 110695 | ** for all tokens using fts3ExprAllocateSegReaders(). |
| 110639 | 110696 | */ |
| 110640 | -int fts3ExprCost(Fts3Expr *pExpr){ | |
| 110697 | +static int fts3ExprCost(Fts3Expr *pExpr){ | |
| 110641 | 110698 | int nCost; /* Return value */ |
| 110642 | 110699 | if( pExpr->eType==FTSQUERY_PHRASE ){ |
| 110643 | 110700 | Fts3Phrase *pPhrase = pExpr->pPhrase; |
| 110644 | 110701 | int ii; |
| 110645 | 110702 | nCost = 0; |
| 110646 | 110703 | for(ii=0; ii<pPhrase->nToken; ii++){ |
| 110647 | - nCost += pPhrase->aToken[ii].pArray->nCost; | |
| 110704 | + Fts3SegReaderArray *pArray = pPhrase->aToken[ii].pArray; | |
| 110705 | + if( pArray ){ | |
| 110706 | + nCost += pPhrase->aToken[ii].pArray->nCost; | |
| 110707 | + } | |
| 110648 | 110708 | } |
| 110649 | 110709 | }else{ |
| 110650 | 110710 | nCost = fts3ExprCost(pExpr->pLeft) + fts3ExprCost(pExpr->pRight); |
| 110651 | 110711 | } |
| 110652 | 110712 | return nCost; |
| @@ -110670,11 +110730,11 @@ | ||
| 110670 | 110730 | if( pExpr->eType==FTSQUERY_AND ){ |
| 110671 | 110731 | fts3ExprAssignCosts(pExpr->pLeft, ppExprCost); |
| 110672 | 110732 | fts3ExprAssignCosts(pExpr->pRight, ppExprCost); |
| 110673 | 110733 | }else{ |
| 110674 | 110734 | (*ppExprCost)->pExpr = pExpr; |
| 110675 | - (*ppExprCost)->nCost = fts3ExprCost(pExpr);; | |
| 110735 | + (*ppExprCost)->nCost = fts3ExprCost(pExpr); | |
| 110676 | 110736 | (*ppExprCost)++; |
| 110677 | 110737 | } |
| 110678 | 110738 | } |
| 110679 | 110739 | |
| 110680 | 110740 | /* |
| @@ -111388,13 +111448,17 @@ | ||
| 111388 | 111448 | sqlite3_context *pContext, /* SQLite function call context */ |
| 111389 | 111449 | int nVal, /* Size of argument array */ |
| 111390 | 111450 | sqlite3_value **apVal /* Array of arguments */ |
| 111391 | 111451 | ){ |
| 111392 | 111452 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 111393 | - assert( nVal==1 ); | |
| 111453 | + assert( nVal==1 || nVal==2 ); | |
| 111394 | 111454 | if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){ |
| 111395 | - sqlite3Fts3Matchinfo(pContext, pCsr); | |
| 111455 | + const char *zArg = 0; | |
| 111456 | + if( nVal>1 ){ | |
| 111457 | + zArg = (const char *)sqlite3_value_text(apVal[1]); | |
| 111458 | + } | |
| 111459 | + sqlite3Fts3Matchinfo(pContext, pCsr, zArg); | |
| 111396 | 111460 | } |
| 111397 | 111461 | } |
| 111398 | 111462 | |
| 111399 | 111463 | /* |
| 111400 | 111464 | ** This routine implements the xFindFunction method for the FTS3 |
| @@ -111579,10 +111643,11 @@ | ||
| 111579 | 111643 | if( SQLITE_OK==rc |
| 111580 | 111644 | && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) |
| 111581 | 111645 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) |
| 111582 | 111646 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) |
| 111583 | 111647 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1)) |
| 111648 | + && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2)) | |
| 111584 | 111649 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) |
| 111585 | 111650 | ){ |
| 111586 | 111651 | rc = sqlite3_create_module_v2( |
| 111587 | 111652 | db, "fts3", &fts3Module, (void *)pHash, hashDestroy |
| 111588 | 111653 | ); |
| @@ -112020,11 +112085,10 @@ | ||
| 112020 | 112085 | |
| 112021 | 112086 | /* Check for an open bracket. */ |
| 112022 | 112087 | if( sqlite3_fts3_enable_parentheses ){ |
| 112023 | 112088 | if( *zInput=='(' ){ |
| 112024 | 112089 | int nConsumed; |
| 112025 | - int rc; | |
| 112026 | 112090 | pParse->nNest++; |
| 112027 | 112091 | rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed); |
| 112028 | 112092 | if( rc==SQLITE_OK && !*ppExpr ){ |
| 112029 | 112093 | rc = SQLITE_DONE; |
| 112030 | 112094 | } |
| @@ -113267,11 +113331,11 @@ | ||
| 113267 | 113331 | */ |
| 113268 | 113332 | static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ |
| 113269 | 113333 | int i, j; |
| 113270 | 113334 | char zReverse[28]; |
| 113271 | 113335 | char *z, *z2; |
| 113272 | - if( nIn<3 || nIn>=sizeof(zReverse)-7 ){ | |
| 113336 | + if( nIn<3 || nIn>=(int)sizeof(zReverse)-7 ){ | |
| 113273 | 113337 | /* The word is too big or too small for the porter stemmer. |
| 113274 | 113338 | ** Fallback to the copy stemmer */ |
| 113275 | 113339 | copy_stemmer(zIn, nIn, zOut, pnOut); |
| 113276 | 113340 | return; |
| 113277 | 113341 | } |
| @@ -114032,19 +114096,27 @@ | ||
| 114032 | 114096 | if( !zTest || !zTest2 ){ |
| 114033 | 114097 | rc = SQLITE_NOMEM; |
| 114034 | 114098 | } |
| 114035 | 114099 | #endif |
| 114036 | 114100 | |
| 114037 | - if( SQLITE_OK!=rc | |
| 114038 | - || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0)) | |
| 114039 | - || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0)) | |
| 114101 | + if( SQLITE_OK==rc ){ | |
| 114102 | + rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0); | |
| 114103 | + } | |
| 114104 | + if( SQLITE_OK==rc ){ | |
| 114105 | + rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0); | |
| 114106 | + } | |
| 114040 | 114107 | #ifdef SQLITE_TEST |
| 114041 | - || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0)) | |
| 114042 | - || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0)) | |
| 114043 | - || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0)) | |
| 114108 | + if( SQLITE_OK==rc ){ | |
| 114109 | + rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0); | |
| 114110 | + } | |
| 114111 | + if( SQLITE_OK==rc ){ | |
| 114112 | + rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0); | |
| 114113 | + } | |
| 114114 | + if( SQLITE_OK==rc ){ | |
| 114115 | + rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0); | |
| 114116 | + } | |
| 114044 | 114117 | #endif |
| 114045 | - ); | |
| 114046 | 114118 | |
| 114047 | 114119 | #ifdef SQLITE_TEST |
| 114048 | 114120 | sqlite3_free(zTest); |
| 114049 | 114121 | sqlite3_free(zTest2); |
| 114050 | 114122 | #endif |
| @@ -114565,10 +114637,55 @@ | ||
| 114565 | 114637 | } |
| 114566 | 114638 | } |
| 114567 | 114639 | *pp = pStmt; |
| 114568 | 114640 | return rc; |
| 114569 | 114641 | } |
| 114642 | + | |
| 114643 | +static int fts3SelectDocsize( | |
| 114644 | + Fts3Table *pTab, /* FTS3 table handle */ | |
| 114645 | + int eStmt, /* Either SQL_SELECT_DOCSIZE or DOCTOTAL */ | |
| 114646 | + sqlite3_int64 iDocid, /* Docid to bind for SQL_SELECT_DOCSIZE */ | |
| 114647 | + sqlite3_stmt **ppStmt /* OUT: Statement handle */ | |
| 114648 | +){ | |
| 114649 | + sqlite3_stmt *pStmt = 0; /* Statement requested from fts3SqlStmt() */ | |
| 114650 | + int rc; /* Return code */ | |
| 114651 | + | |
| 114652 | + assert( eStmt==SQL_SELECT_DOCSIZE || eStmt==SQL_SELECT_DOCTOTAL ); | |
| 114653 | + | |
| 114654 | + rc = fts3SqlStmt(pTab, eStmt, &pStmt, 0); | |
| 114655 | + if( rc==SQLITE_OK ){ | |
| 114656 | + if( eStmt==SQL_SELECT_DOCSIZE ){ | |
| 114657 | + sqlite3_bind_int64(pStmt, 1, iDocid); | |
| 114658 | + } | |
| 114659 | + rc = sqlite3_step(pStmt); | |
| 114660 | + if( rc!=SQLITE_ROW ){ | |
| 114661 | + rc = sqlite3_reset(pStmt); | |
| 114662 | + if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT; | |
| 114663 | + pStmt = 0; | |
| 114664 | + }else{ | |
| 114665 | + rc = SQLITE_OK; | |
| 114666 | + } | |
| 114667 | + } | |
| 114668 | + | |
| 114669 | + *ppStmt = pStmt; | |
| 114670 | + return rc; | |
| 114671 | +} | |
| 114672 | + | |
| 114673 | +SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal( | |
| 114674 | + Fts3Table *pTab, /* Fts3 table handle */ | |
| 114675 | + sqlite3_stmt **ppStmt /* OUT: Statement handle */ | |
| 114676 | +){ | |
| 114677 | + return fts3SelectDocsize(pTab, SQL_SELECT_DOCTOTAL, 0, ppStmt); | |
| 114678 | +} | |
| 114679 | + | |
| 114680 | +SQLITE_PRIVATE int sqlite3Fts3SelectDocsize( | |
| 114681 | + Fts3Table *pTab, /* Fts3 table handle */ | |
| 114682 | + sqlite3_int64 iDocid, /* Docid to read size data for */ | |
| 114683 | + sqlite3_stmt **ppStmt /* OUT: Statement handle */ | |
| 114684 | +){ | |
| 114685 | + return fts3SelectDocsize(pTab, SQL_SELECT_DOCSIZE, iDocid, ppStmt); | |
| 114686 | +} | |
| 114570 | 114687 | |
| 114571 | 114688 | /* |
| 114572 | 114689 | ** Similar to fts3SqlStmt(). Except, after binding the parameters in |
| 114573 | 114690 | ** array apVal[] to the SQL statement identified by eStmt, the statement |
| 114574 | 114691 | ** is executed. |
| @@ -115382,11 +115499,11 @@ | ||
| 115382 | 115499 | |
| 115383 | 115500 | /* |
| 115384 | 115501 | ** Free all allocations associated with the iterator passed as the |
| 115385 | 115502 | ** second argument. |
| 115386 | 115503 | */ |
| 115387 | -SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *p, Fts3SegReader *pReader){ | |
| 115504 | +SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ | |
| 115388 | 115505 | if( pReader && !fts3SegReaderIsPending(pReader) ){ |
| 115389 | 115506 | sqlite3_free(pReader->zTerm); |
| 115390 | 115507 | if( !fts3SegReaderIsRootOnly(pReader) ){ |
| 115391 | 115508 | sqlite3_free(pReader->aNode); |
| 115392 | 115509 | } |
| @@ -115396,11 +115513,10 @@ | ||
| 115396 | 115513 | |
| 115397 | 115514 | /* |
| 115398 | 115515 | ** Allocate a new SegReader object. |
| 115399 | 115516 | */ |
| 115400 | 115517 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( |
| 115401 | - Fts3Table *p, /* Virtual table handle */ | |
| 115402 | 115518 | int iAge, /* Segment "age". */ |
| 115403 | 115519 | sqlite3_int64 iStartLeaf, /* First leaf to traverse */ |
| 115404 | 115520 | sqlite3_int64 iEndLeaf, /* Final leaf to traverse */ |
| 115405 | 115521 | sqlite3_int64 iEndBlock, /* Final block of segment */ |
| 115406 | 115522 | const char *zRoot, /* Buffer containing root node */ |
| @@ -115437,11 +115553,11 @@ | ||
| 115437 | 115553 | } |
| 115438 | 115554 | |
| 115439 | 115555 | if( rc==SQLITE_OK ){ |
| 115440 | 115556 | *ppReader = pReader; |
| 115441 | 115557 | }else{ |
| 115442 | - sqlite3Fts3SegReaderFree(p, pReader); | |
| 115558 | + sqlite3Fts3SegReaderFree(pReader); | |
| 115443 | 115559 | } |
| 115444 | 115560 | return rc; |
| 115445 | 115561 | } |
| 115446 | 115562 | |
| 115447 | 115563 | /* |
| @@ -115560,16 +115676,15 @@ | ||
| 115560 | 115676 | ** If successful, the Fts3SegReader is left pointing to the first term |
| 115561 | 115677 | ** in the segment and SQLITE_OK is returned. Otherwise, an SQLite error |
| 115562 | 115678 | ** code is returned. |
| 115563 | 115679 | */ |
| 115564 | 115680 | static int fts3SegReaderNew( |
| 115565 | - Fts3Table *p, /* Virtual table handle */ | |
| 115566 | 115681 | sqlite3_stmt *pStmt, /* See above */ |
| 115567 | 115682 | int iAge, /* Segment "age". */ |
| 115568 | 115683 | Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */ |
| 115569 | 115684 | ){ |
| 115570 | - return sqlite3Fts3SegReaderNew(p, iAge, | |
| 115685 | + return sqlite3Fts3SegReaderNew(iAge, | |
| 115571 | 115686 | sqlite3_column_int64(pStmt, 1), |
| 115572 | 115687 | sqlite3_column_int64(pStmt, 2), |
| 115573 | 115688 | sqlite3_column_int64(pStmt, 3), |
| 115574 | 115689 | sqlite3_column_blob(pStmt, 4), |
| 115575 | 115690 | sqlite3_column_bytes(pStmt, 4), |
| @@ -116596,11 +116711,11 @@ | ||
| 116596 | 116711 | assert( SQL_SELECT_LEVEL+1==SQL_SELECT_ALL_LEVEL); |
| 116597 | 116712 | rc = fts3SqlStmt(p, SQL_SELECT_LEVEL+(iLevel<0), &pStmt, 0); |
| 116598 | 116713 | if( rc!=SQLITE_OK ) goto finished; |
| 116599 | 116714 | sqlite3_bind_int(pStmt, 1, iLevel); |
| 116600 | 116715 | for(i=0; SQLITE_ROW==(sqlite3_step(pStmt)); i++){ |
| 116601 | - rc = fts3SegReaderNew(p, pStmt, i, &apSegment[i]); | |
| 116716 | + rc = fts3SegReaderNew(pStmt, i, &apSegment[i]); | |
| 116602 | 116717 | if( rc!=SQLITE_OK ){ |
| 116603 | 116718 | goto finished; |
| 116604 | 116719 | } |
| 116605 | 116720 | } |
| 116606 | 116721 | rc = sqlite3_reset(pStmt); |
| @@ -116626,15 +116741,15 @@ | ||
| 116626 | 116741 | |
| 116627 | 116742 | finished: |
| 116628 | 116743 | fts3SegWriterFree(pWriter); |
| 116629 | 116744 | if( apSegment ){ |
| 116630 | 116745 | for(i=0; i<nSegment; i++){ |
| 116631 | - sqlite3Fts3SegReaderFree(p, apSegment[i]); | |
| 116746 | + sqlite3Fts3SegReaderFree(apSegment[i]); | |
| 116632 | 116747 | } |
| 116633 | 116748 | sqlite3_free(apSegment); |
| 116634 | 116749 | } |
| 116635 | - sqlite3Fts3SegReaderFree(p, pPending); | |
| 116750 | + sqlite3Fts3SegReaderFree(pPending); | |
| 116636 | 116751 | sqlite3_reset(pStmt); |
| 116637 | 116752 | return rc; |
| 116638 | 116753 | } |
| 116639 | 116754 | |
| 116640 | 116755 | |
| @@ -116683,11 +116798,11 @@ | ||
| 116683 | 116798 | */ |
| 116684 | 116799 | if( rc==SQLITE_OK ){ |
| 116685 | 116800 | rc = fts3SegWriterFlush(p, pWriter, 0, idx); |
| 116686 | 116801 | } |
| 116687 | 116802 | fts3SegWriterFree(pWriter); |
| 116688 | - sqlite3Fts3SegReaderFree(p, pReader); | |
| 116803 | + sqlite3Fts3SegReaderFree(pReader); | |
| 116689 | 116804 | |
| 116690 | 116805 | if( rc==SQLITE_OK ){ |
| 116691 | 116806 | sqlite3Fts3PendingTermsClear(p); |
| 116692 | 116807 | } |
| 116693 | 116808 | return rc; |
| @@ -116726,79 +116841,10 @@ | ||
| 116726 | 116841 | assert(j<=nBuf); |
| 116727 | 116842 | a[i] = (u32)(x & 0xffffffff); |
| 116728 | 116843 | } |
| 116729 | 116844 | } |
| 116730 | 116845 | |
| 116731 | -/* | |
| 116732 | -** Fill in the document size auxiliary information for the matchinfo | |
| 116733 | -** structure. The auxiliary information is: | |
| 116734 | -** | |
| 116735 | -** N Total number of documents in the full-text index | |
| 116736 | -** a0 Average length of column 0 over the whole index | |
| 116737 | -** n0 Length of column 0 on the matching row | |
| 116738 | -** ... | |
| 116739 | -** aM Average length of column M over the whole index | |
| 116740 | -** nM Length of column M on the matching row | |
| 116741 | -** | |
| 116742 | -** The fts3MatchinfoDocsizeLocal() routine fills in the nX values. | |
| 116743 | -** The fts3MatchinfoDocsizeGlobal() routine fills in N and the aX values. | |
| 116744 | -*/ | |
| 116745 | -SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor *pCur, u32 *a){ | |
| 116746 | - const char *pBlob; /* The BLOB holding %_docsize info */ | |
| 116747 | - int nBlob; /* Size of the BLOB */ | |
| 116748 | - sqlite3_stmt *pStmt; /* Statement for reading and writing */ | |
| 116749 | - int i, j; /* Loop counters */ | |
| 116750 | - sqlite3_int64 x; /* Varint value */ | |
| 116751 | - int rc; /* Result code from subfunctions */ | |
| 116752 | - Fts3Table *p; /* The FTS table */ | |
| 116753 | - | |
| 116754 | - p = (Fts3Table*)pCur->base.pVtab; | |
| 116755 | - rc = fts3SqlStmt(p, SQL_SELECT_DOCSIZE, &pStmt, 0); | |
| 116756 | - if( rc ){ | |
| 116757 | - return rc; | |
| 116758 | - } | |
| 116759 | - sqlite3_bind_int64(pStmt, 1, pCur->iPrevId); | |
| 116760 | - if( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 116761 | - nBlob = sqlite3_column_bytes(pStmt, 0); | |
| 116762 | - pBlob = (const char*)sqlite3_column_blob(pStmt, 0); | |
| 116763 | - for(i=j=0; i<p->nColumn && j<nBlob; i++){ | |
| 116764 | - j = sqlite3Fts3GetVarint(&pBlob[j], &x); | |
| 116765 | - a[2+i*2] = (u32)(x & 0xffffffff); | |
| 116766 | - } | |
| 116767 | - } | |
| 116768 | - sqlite3_reset(pStmt); | |
| 116769 | - return SQLITE_OK; | |
| 116770 | -} | |
| 116771 | -SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor *pCur, u32 *a){ | |
| 116772 | - const char *pBlob; /* The BLOB holding %_stat info */ | |
| 116773 | - int nBlob; /* Size of the BLOB */ | |
| 116774 | - sqlite3_stmt *pStmt; /* Statement for reading and writing */ | |
| 116775 | - int i, j; /* Loop counters */ | |
| 116776 | - sqlite3_int64 x; /* Varint value */ | |
| 116777 | - int nDoc; /* Number of documents */ | |
| 116778 | - int rc; /* Result code from subfunctions */ | |
| 116779 | - Fts3Table *p; /* The FTS table */ | |
| 116780 | - | |
| 116781 | - p = (Fts3Table*)pCur->base.pVtab; | |
| 116782 | - rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0); | |
| 116783 | - if( rc ){ | |
| 116784 | - return rc; | |
| 116785 | - } | |
| 116786 | - if( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 116787 | - nBlob = sqlite3_column_bytes(pStmt, 0); | |
| 116788 | - pBlob = (const char*)sqlite3_column_blob(pStmt, 0); | |
| 116789 | - j = sqlite3Fts3GetVarint(pBlob, &x); | |
| 116790 | - a[0] = nDoc = (u32)(x & 0xffffffff); | |
| 116791 | - for(i=0; i<p->nColumn && j<nBlob; i++){ | |
| 116792 | - j = sqlite3Fts3GetVarint(&pBlob[j], &x); | |
| 116793 | - a[1+i*2] = ((u32)(x & 0xffffffff) + nDoc/2)/nDoc; | |
| 116794 | - } | |
| 116795 | - } | |
| 116796 | - sqlite3_reset(pStmt); | |
| 116797 | - return SQLITE_OK; | |
| 116798 | -} | |
| 116799 | - | |
| 116800 | 116846 | /* |
| 116801 | 116847 | ** Insert the sizes (in tokens) for each column of the document |
| 116802 | 116848 | ** with docid equal to p->iPrevDocid. The sizes are encoded as |
| 116803 | 116849 | ** a blob of varints. |
| 116804 | 116850 | */ |
| @@ -117217,10 +117263,26 @@ | ||
| 117217 | 117263 | */ |
| 117218 | 117264 | |
| 117219 | 117265 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 117220 | 117266 | |
| 117221 | 117267 | |
| 117268 | +/* | |
| 117269 | +** Characters that may appear in the second argument to matchinfo(). | |
| 117270 | +*/ | |
| 117271 | +#define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */ | |
| 117272 | +#define FTS3_MATCHINFO_NCOL 'c' /* 1 value */ | |
| 117273 | +#define FTS3_MATCHINFO_NDOC 'n' /* 1 value */ | |
| 117274 | +#define FTS3_MATCHINFO_AVGLENGTH 'a' /* nCol values */ | |
| 117275 | +#define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */ | |
| 117276 | +#define FTS3_MATCHINFO_LCS 's' /* nCol values */ | |
| 117277 | +#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ | |
| 117278 | + | |
| 117279 | +/* | |
| 117280 | +** The default value for the second argument to matchinfo(). | |
| 117281 | +*/ | |
| 117282 | +#define FTS3_MATCHINFO_DEFAULT "pcx" | |
| 117283 | + | |
| 117222 | 117284 | |
| 117223 | 117285 | /* |
| 117224 | 117286 | ** Used as an fts3ExprIterate() context when loading phrase doclists to |
| 117225 | 117287 | ** Fts3Expr.aDoclist[]/nDoclist. |
| 117226 | 117288 | */ |
| @@ -117270,10 +117332,12 @@ | ||
| 117270 | 117332 | */ |
| 117271 | 117333 | typedef struct MatchInfo MatchInfo; |
| 117272 | 117334 | struct MatchInfo { |
| 117273 | 117335 | Fts3Cursor *pCursor; /* FTS3 Cursor */ |
| 117274 | 117336 | int nCol; /* Number of columns in table */ |
| 117337 | + int nPhrase; /* Number of matchable phrases in query */ | |
| 117338 | + sqlite3_int64 nDoc; /* Number of docs in database */ | |
| 117275 | 117339 | u32 *aMatchinfo; /* Pre-allocated buffer */ |
| 117276 | 117340 | }; |
| 117277 | 117341 | |
| 117278 | 117342 | |
| 117279 | 117343 | |
| @@ -117470,10 +117534,22 @@ | ||
| 117470 | 117534 | } |
| 117471 | 117535 | if( pnPhrase ) *pnPhrase = sCtx.nPhrase; |
| 117472 | 117536 | if( pnToken ) *pnToken = sCtx.nToken; |
| 117473 | 117537 | return rc; |
| 117474 | 117538 | } |
| 117539 | + | |
| 117540 | +static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ | |
| 117541 | + (*(int *)ctx)++; | |
| 117542 | + UNUSED_PARAMETER(pExpr); | |
| 117543 | + UNUSED_PARAMETER(iPhrase); | |
| 117544 | + return SQLITE_OK; | |
| 117545 | +} | |
| 117546 | +static int fts3ExprPhraseCount(Fts3Expr *pExpr){ | |
| 117547 | + int nPhrase = 0; | |
| 117548 | + (void)fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase); | |
| 117549 | + return nPhrase; | |
| 117550 | +} | |
| 117475 | 117551 | |
| 117476 | 117552 | /* |
| 117477 | 117553 | ** Advance the position list iterator specified by the first two |
| 117478 | 117554 | ** arguments so that it points to the first element with a value greater |
| 117479 | 117555 | ** than or equal to parameter iNext. |
| @@ -117983,24 +118059,46 @@ | ||
| 117983 | 118059 | *pp = pCsr; |
| 117984 | 118060 | } |
| 117985 | 118061 | |
| 117986 | 118062 | /* |
| 117987 | 118063 | ** fts3ExprIterate() callback used to collect the "global" matchinfo stats |
| 117988 | -** for a single query. The "global" stats are those elements of the matchinfo | |
| 117989 | -** array that are constant for all rows returned by the current query. | |
| 118064 | +** for a single query. | |
| 118065 | +** | |
| 118066 | +** fts3ExprIterate() callback to load the 'global' elements of a | |
| 118067 | +** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements | |
| 118068 | +** of the matchinfo array that are constant for all rows returned by the | |
| 118069 | +** current query. | |
| 118070 | +** | |
| 118071 | +** Argument pCtx is actually a pointer to a struct of type MatchInfo. This | |
| 118072 | +** function populates Matchinfo.aMatchinfo[] as follows: | |
| 118073 | +** | |
| 118074 | +** for(iCol=0; iCol<nCol; iCol++){ | |
| 118075 | +** aMatchinfo[3*iPhrase*nCol + 3*iCol + 1] = X; | |
| 118076 | +** aMatchinfo[3*iPhrase*nCol + 3*iCol + 2] = Y; | |
| 118077 | +** } | |
| 118078 | +** | |
| 118079 | +** where X is the number of matches for phrase iPhrase is column iCol of all | |
| 118080 | +** rows of the table. Y is the number of rows for which column iCol contains | |
| 118081 | +** at least one instance of phrase iPhrase. | |
| 118082 | +** | |
| 118083 | +** If the phrase pExpr consists entirely of deferred tokens, then all X and | |
| 118084 | +** Y values are set to nDoc, where nDoc is the number of documents in the | |
| 118085 | +** file system. This is done because the full-text index doclist is required | |
| 118086 | +** to calculate these values properly, and the full-text index doclist is | |
| 118087 | +** not available for deferred tokens. | |
| 117990 | 118088 | */ |
| 117991 | -static int fts3ExprGlobalMatchinfoCb( | |
| 118089 | +static int fts3ExprGlobalHitsCb( | |
| 117992 | 118090 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 117993 | 118091 | int iPhrase, /* Phrase number (numbered from zero) */ |
| 117994 | 118092 | void *pCtx /* Pointer to MatchInfo structure */ |
| 117995 | 118093 | ){ |
| 117996 | 118094 | MatchInfo *p = (MatchInfo *)pCtx; |
| 117997 | 118095 | Fts3Cursor *pCsr = p->pCursor; |
| 117998 | 118096 | char *pIter; |
| 117999 | 118097 | char *pEnd; |
| 118000 | 118098 | char *pFree = 0; |
| 118001 | - const int iStart = 2 + (iPhrase * p->nCol * 3) + 1; | |
| 118099 | + u32 *aOut = &p->aMatchinfo[3*iPhrase*p->nCol]; | |
| 118002 | 118100 | |
| 118003 | 118101 | assert( pExpr->isLoaded ); |
| 118004 | 118102 | assert( pExpr->eType==FTSQUERY_PHRASE ); |
| 118005 | 118103 | |
| 118006 | 118104 | if( pCsr->pDeferred ){ |
| @@ -118014,14 +118112,14 @@ | ||
| 118014 | 118112 | int rc = sqlite3Fts3ExprLoadFtDoclist(pCsr, pExpr, &pFree, &nFree); |
| 118015 | 118113 | if( rc!=SQLITE_OK ) return rc; |
| 118016 | 118114 | pIter = pFree; |
| 118017 | 118115 | pEnd = &pFree[nFree]; |
| 118018 | 118116 | }else{ |
| 118019 | - int nDoc = p->aMatchinfo[2 + 3*p->nCol*p->aMatchinfo[0]]; | |
| 118020 | - for(ii=0; ii<p->nCol; ii++){ | |
| 118021 | - p->aMatchinfo[iStart + ii*3] = nDoc; | |
| 118022 | - p->aMatchinfo[iStart + ii*3 + 1] = nDoc; | |
| 118117 | + int iCol; /* Column index */ | |
| 118118 | + for(iCol=0; iCol<p->nCol; iCol++){ | |
| 118119 | + aOut[iCol*3 + 1] = (u32)p->nDoc; | |
| 118120 | + aOut[iCol*3 + 2] = (u32)p->nDoc; | |
| 118023 | 118121 | } |
| 118024 | 118122 | return SQLITE_OK; |
| 118025 | 118123 | } |
| 118026 | 118124 | }else{ |
| 118027 | 118125 | pIter = pExpr->aDoclist; |
| @@ -118029,32 +118127,32 @@ | ||
| 118029 | 118127 | } |
| 118030 | 118128 | |
| 118031 | 118129 | /* Fill in the global hit count matrix row for this phrase. */ |
| 118032 | 118130 | while( pIter<pEnd ){ |
| 118033 | 118131 | while( *pIter++ & 0x80 ); /* Skip past docid. */ |
| 118034 | - fts3LoadColumnlistCounts(&pIter, &p->aMatchinfo[iStart], 1); | |
| 118132 | + fts3LoadColumnlistCounts(&pIter, &aOut[1], 1); | |
| 118035 | 118133 | } |
| 118036 | 118134 | |
| 118037 | 118135 | sqlite3_free(pFree); |
| 118038 | 118136 | return SQLITE_OK; |
| 118039 | 118137 | } |
| 118040 | 118138 | |
| 118041 | 118139 | /* |
| 118042 | -** fts3ExprIterate() callback used to collect the "local" matchinfo stats | |
| 118043 | -** for a single query. The "local" stats are those elements of the matchinfo | |
| 118140 | +** fts3ExprIterate() callback used to collect the "local" part of the | |
| 118141 | +** FTS3_MATCHINFO_HITS array. The local stats are those elements of the | |
| 118044 | 118142 | ** array that are different for each row returned by the query. |
| 118045 | 118143 | */ |
| 118046 | -static int fts3ExprLocalMatchinfoCb( | |
| 118144 | +static int fts3ExprLocalHitsCb( | |
| 118047 | 118145 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 118048 | 118146 | int iPhrase, /* Phrase number */ |
| 118049 | 118147 | void *pCtx /* Pointer to MatchInfo structure */ |
| 118050 | 118148 | ){ |
| 118051 | 118149 | MatchInfo *p = (MatchInfo *)pCtx; |
| 118052 | 118150 | |
| 118053 | 118151 | if( pExpr->aDoclist ){ |
| 118054 | 118152 | char *pCsr; |
| 118055 | - int iStart = 2 + (iPhrase * p->nCol * 3); | |
| 118153 | + int iStart = iPhrase * p->nCol * 3; | |
| 118056 | 118154 | int i; |
| 118057 | 118155 | |
| 118058 | 118156 | for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0; |
| 118059 | 118157 | |
| 118060 | 118158 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1); |
| @@ -118063,71 +118161,404 @@ | ||
| 118063 | 118161 | } |
| 118064 | 118162 | } |
| 118065 | 118163 | |
| 118066 | 118164 | return SQLITE_OK; |
| 118067 | 118165 | } |
| 118166 | + | |
| 118167 | +static int fts3MatchinfoCheck( | |
| 118168 | + Fts3Table *pTab, | |
| 118169 | + char cArg, | |
| 118170 | + char **pzErr | |
| 118171 | +){ | |
| 118172 | + if( (cArg==FTS3_MATCHINFO_NPHRASE) | |
| 118173 | + || (cArg==FTS3_MATCHINFO_NCOL) | |
| 118174 | + || (cArg==FTS3_MATCHINFO_NDOC && pTab->bHasStat) | |
| 118175 | + || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bHasStat) | |
| 118176 | + || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize) | |
| 118177 | + || (cArg==FTS3_MATCHINFO_LCS) | |
| 118178 | + || (cArg==FTS3_MATCHINFO_HITS) | |
| 118179 | + ){ | |
| 118180 | + return SQLITE_OK; | |
| 118181 | + } | |
| 118182 | + *pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg); | |
| 118183 | + return SQLITE_ERROR; | |
| 118184 | +} | |
| 118185 | + | |
| 118186 | +static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ | |
| 118187 | + int nVal; /* Number of integers output by cArg */ | |
| 118188 | + | |
| 118189 | + switch( cArg ){ | |
| 118190 | + case FTS3_MATCHINFO_NDOC: | |
| 118191 | + case FTS3_MATCHINFO_NPHRASE: | |
| 118192 | + case FTS3_MATCHINFO_NCOL: | |
| 118193 | + nVal = 1; | |
| 118194 | + break; | |
| 118195 | + | |
| 118196 | + case FTS3_MATCHINFO_AVGLENGTH: | |
| 118197 | + case FTS3_MATCHINFO_LENGTH: | |
| 118198 | + case FTS3_MATCHINFO_LCS: | |
| 118199 | + nVal = pInfo->nCol; | |
| 118200 | + break; | |
| 118201 | + | |
| 118202 | + default: | |
| 118203 | + assert( cArg==FTS3_MATCHINFO_HITS ); | |
| 118204 | + nVal = pInfo->nCol * pInfo->nPhrase * 3; | |
| 118205 | + break; | |
| 118206 | + } | |
| 118207 | + | |
| 118208 | + return nVal; | |
| 118209 | +} | |
| 118210 | + | |
| 118211 | +static int fts3MatchinfoSelectDoctotal( | |
| 118212 | + Fts3Table *pTab, | |
| 118213 | + sqlite3_stmt **ppStmt, | |
| 118214 | + sqlite3_int64 *pnDoc, | |
| 118215 | + const char **paLen | |
| 118216 | +){ | |
| 118217 | + sqlite3_stmt *pStmt; | |
| 118218 | + const char *a; | |
| 118219 | + sqlite3_int64 nDoc; | |
| 118220 | + | |
| 118221 | + if( !*ppStmt ){ | |
| 118222 | + int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt); | |
| 118223 | + if( rc!=SQLITE_OK ) return rc; | |
| 118224 | + } | |
| 118225 | + pStmt = *ppStmt; | |
| 118226 | + | |
| 118227 | + a = sqlite3_column_blob(pStmt, 0); | |
| 118228 | + a += sqlite3Fts3GetVarint(a, &nDoc); | |
| 118229 | + *pnDoc = (u32)nDoc; | |
| 118230 | + | |
| 118231 | + if( paLen ) *paLen = a; | |
| 118232 | + return SQLITE_OK; | |
| 118233 | +} | |
| 118234 | + | |
| 118235 | +/* | |
| 118236 | +** An instance of the following structure is used to store state while | |
| 118237 | +** iterating through a multi-column position-list corresponding to the | |
| 118238 | +** hits for a single phrase on a single row in order to calculate the | |
| 118239 | +** values for a matchinfo() FTS3_MATCHINFO_LCS request. | |
| 118240 | +*/ | |
| 118241 | +typedef struct LcsIterator LcsIterator; | |
| 118242 | +struct LcsIterator { | |
| 118243 | + Fts3Expr *pExpr; /* Pointer to phrase expression */ | |
| 118244 | + char *pRead; /* Cursor used to iterate through aDoclist */ | |
| 118245 | + int iPosOffset; /* Tokens count up to end of this phrase */ | |
| 118246 | + int iCol; /* Current column number */ | |
| 118247 | + int iPos; /* Current position */ | |
| 118248 | +}; | |
| 118249 | + | |
| 118250 | +/* | |
| 118251 | +** If LcsIterator.iCol is set to the following value, the iterator has | |
| 118252 | +** finished iterating through all offsets for all columns. | |
| 118253 | +*/ | |
| 118254 | +#define LCS_ITERATOR_FINISHED 0x7FFFFFFF; | |
| 118255 | + | |
| 118256 | +static int fts3MatchinfoLcsCb( | |
| 118257 | + Fts3Expr *pExpr, /* Phrase expression node */ | |
| 118258 | + int iPhrase, /* Phrase number (numbered from zero) */ | |
| 118259 | + void *pCtx /* Pointer to MatchInfo structure */ | |
| 118260 | +){ | |
| 118261 | + LcsIterator *aIter = (LcsIterator *)pCtx; | |
| 118262 | + aIter[iPhrase].pExpr = pExpr; | |
| 118263 | + return SQLITE_OK; | |
| 118264 | +} | |
| 118265 | + | |
| 118266 | +/* | |
| 118267 | +** Advance the iterator passed as an argument to the next position. Return | |
| 118268 | +** 1 if the iterator is at EOF or if it now points to the start of the | |
| 118269 | +** position list for the next column. | |
| 118270 | +*/ | |
| 118271 | +static int fts3LcsIteratorAdvance(LcsIterator *pIter){ | |
| 118272 | + char *pRead = pIter->pRead; | |
| 118273 | + sqlite3_int64 iRead; | |
| 118274 | + int rc = 0; | |
| 118275 | + | |
| 118276 | + pRead += sqlite3Fts3GetVarint(pRead, &iRead); | |
| 118277 | + if( iRead==0 ){ | |
| 118278 | + pIter->iCol = LCS_ITERATOR_FINISHED; | |
| 118279 | + rc = 1; | |
| 118280 | + }else{ | |
| 118281 | + if( iRead==1 ){ | |
| 118282 | + pRead += sqlite3Fts3GetVarint(pRead, &iRead); | |
| 118283 | + pIter->iCol = iRead; | |
| 118284 | + pIter->iPos = pIter->iPosOffset; | |
| 118285 | + pRead += sqlite3Fts3GetVarint(pRead, &iRead); | |
| 118286 | + rc = 1; | |
| 118287 | + } | |
| 118288 | + pIter->iPos += (iRead-2); | |
| 118289 | + } | |
| 118290 | + | |
| 118291 | + pIter->pRead = pRead; | |
| 118292 | + return rc; | |
| 118293 | +} | |
| 118294 | + | |
| 118295 | +/* | |
| 118296 | +** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag. | |
| 118297 | +** | |
| 118298 | +** If the call is successful, the longest-common-substring lengths for each | |
| 118299 | +** column are written into the first nCol elements of the pInfo->aMatchinfo[] | |
| 118300 | +** array before returning. SQLITE_OK is returned in this case. | |
| 118301 | +** | |
| 118302 | +** Otherwise, if an error occurs, an SQLite error code is returned and the | |
| 118303 | +** data written to the first nCol elements of pInfo->aMatchinfo[] is | |
| 118304 | +** undefined. | |
| 118305 | +*/ | |
| 118306 | +static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){ | |
| 118307 | + LcsIterator *aIter; | |
| 118308 | + int i; | |
| 118309 | + int iCol; | |
| 118310 | + int nToken = 0; | |
| 118311 | + | |
| 118312 | + /* Allocate and populate the array of LcsIterator objects. The array | |
| 118313 | + ** contains one element for each matchable phrase in the query. | |
| 118314 | + **/ | |
| 118315 | + aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase); | |
| 118316 | + if( !aIter ) return SQLITE_NOMEM; | |
| 118317 | + memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase); | |
| 118318 | + (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter); | |
| 118319 | + for(i=0; i<pInfo->nPhrase; i++){ | |
| 118320 | + LcsIterator *pIter = &aIter[i]; | |
| 118321 | + nToken -= pIter->pExpr->pPhrase->nToken; | |
| 118322 | + pIter->iPosOffset = nToken; | |
| 118323 | + pIter->pRead = sqlite3Fts3FindPositions(pIter->pExpr, pCsr->iPrevId, -1); | |
| 118324 | + if( pIter->pRead ){ | |
| 118325 | + pIter->iPos = pIter->iPosOffset; | |
| 118326 | + fts3LcsIteratorAdvance(&aIter[i]); | |
| 118327 | + }else{ | |
| 118328 | + pIter->iCol = LCS_ITERATOR_FINISHED; | |
| 118329 | + } | |
| 118330 | + } | |
| 118331 | + | |
| 118332 | + for(iCol=0; iCol<pInfo->nCol; iCol++){ | |
| 118333 | + int nLcs = 0; /* LCS value for this column */ | |
| 118334 | + int nLive = 0; /* Number of iterators in aIter not at EOF */ | |
| 118335 | + | |
| 118336 | + /* Loop through the iterators in aIter[]. Set nLive to the number of | |
| 118337 | + ** iterators that point to a position-list corresponding to column iCol. | |
| 118338 | + */ | |
| 118339 | + for(i=0; i<pInfo->nPhrase; i++){ | |
| 118340 | + assert( aIter[i].iCol>=iCol ); | |
| 118341 | + if( aIter[i].iCol==iCol ) nLive++; | |
| 118342 | + } | |
| 118343 | + | |
| 118344 | + /* The following loop runs until all iterators in aIter[] have finished | |
| 118345 | + ** iterating through positions in column iCol. Exactly one of the | |
| 118346 | + ** iterators is advanced each time the body of the loop is run. | |
| 118347 | + */ | |
| 118348 | + while( nLive>0 ){ | |
| 118349 | + LcsIterator *pAdv = 0; /* The iterator to advance by one position */ | |
| 118350 | + int nThisLcs = 0; /* LCS for the current iterator positions */ | |
| 118351 | + | |
| 118352 | + for(i=0; i<pInfo->nPhrase; i++){ | |
| 118353 | + LcsIterator *pIter = &aIter[i]; | |
| 118354 | + if( iCol!=pIter->iCol ){ | |
| 118355 | + /* This iterator is already at EOF for this column. */ | |
| 118356 | + nThisLcs = 0; | |
| 118357 | + }else{ | |
| 118358 | + if( pAdv==0 || pIter->iPos<pAdv->iPos ){ | |
| 118359 | + pAdv = pIter; | |
| 118360 | + } | |
| 118361 | + if( nThisLcs==0 || pIter->iPos==pIter[-1].iPos ){ | |
| 118362 | + nThisLcs++; | |
| 118363 | + }else{ | |
| 118364 | + nThisLcs = 1; | |
| 118365 | + } | |
| 118366 | + if( nThisLcs>nLcs ) nLcs = nThisLcs; | |
| 118367 | + } | |
| 118368 | + } | |
| 118369 | + if( fts3LcsIteratorAdvance(pAdv) ) nLive--; | |
| 118370 | + } | |
| 118371 | + | |
| 118372 | + pInfo->aMatchinfo[iCol] = nLcs; | |
| 118373 | + } | |
| 118374 | + | |
| 118375 | + sqlite3_free(aIter); | |
| 118376 | + return SQLITE_OK; | |
| 118377 | +} | |
| 118378 | + | |
| 118379 | +/* | |
| 118380 | +** Populate the buffer pInfo->aMatchinfo[] with an array of integers to | |
| 118381 | +** be returned by the matchinfo() function. Argument zArg contains the | |
| 118382 | +** format string passed as the second argument to matchinfo (or the | |
| 118383 | +** default value "pcx" if no second argument was specified). The format | |
| 118384 | +** string has already been validated and the pInfo->aMatchinfo[] array | |
| 118385 | +** is guaranteed to be large enough for the output. | |
| 118386 | +** | |
| 118387 | +** If bGlobal is true, then populate all fields of the matchinfo() output. | |
| 118388 | +** If it is false, then assume that those fields that do not change between | |
| 118389 | +** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS) | |
| 118390 | +** have already been populated. | |
| 118391 | +** | |
| 118392 | +** Return SQLITE_OK if successful, or an SQLite error code if an error | |
| 118393 | +** occurs. If a value other than SQLITE_OK is returned, the state the | |
| 118394 | +** pInfo->aMatchinfo[] buffer is left in is undefined. | |
| 118395 | +*/ | |
| 118396 | +static int fts3MatchinfoValues( | |
| 118397 | + Fts3Cursor *pCsr, /* FTS3 cursor object */ | |
| 118398 | + int bGlobal, /* True to grab the global stats */ | |
| 118399 | + MatchInfo *pInfo, /* Matchinfo context object */ | |
| 118400 | + const char *zArg /* Matchinfo format string */ | |
| 118401 | +){ | |
| 118402 | + int rc = SQLITE_OK; | |
| 118403 | + int i; | |
| 118404 | + Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; | |
| 118405 | + sqlite3_stmt *pSelect = 0; | |
| 118406 | + | |
| 118407 | + for(i=0; rc==SQLITE_OK && zArg[i]; i++){ | |
| 118408 | + | |
| 118409 | + switch( zArg[i] ){ | |
| 118410 | + case FTS3_MATCHINFO_NPHRASE: | |
| 118411 | + if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase; | |
| 118412 | + break; | |
| 118413 | + | |
| 118414 | + case FTS3_MATCHINFO_NCOL: | |
| 118415 | + if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol; | |
| 118416 | + break; | |
| 118417 | + | |
| 118418 | + case FTS3_MATCHINFO_NDOC: | |
| 118419 | + if( bGlobal ){ | |
| 118420 | + sqlite3_int64 nDoc; | |
| 118421 | + rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0); | |
| 118422 | + pInfo->aMatchinfo[0] = (u32)nDoc; | |
| 118423 | + } | |
| 118424 | + break; | |
| 118425 | + | |
| 118426 | + case FTS3_MATCHINFO_AVGLENGTH: | |
| 118427 | + if( bGlobal ){ | |
| 118428 | + sqlite3_int64 nDoc; /* Number of rows in table */ | |
| 118429 | + const char *a; /* Aggregate column length array */ | |
| 118430 | + | |
| 118431 | + rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a); | |
| 118432 | + if( rc==SQLITE_OK ){ | |
| 118433 | + int iCol; | |
| 118434 | + for(iCol=0; iCol<pInfo->nCol; iCol++){ | |
| 118435 | + sqlite3_int64 nToken; | |
| 118436 | + a += sqlite3Fts3GetVarint(a, &nToken); | |
| 118437 | + pInfo->aMatchinfo[iCol] = ((u32)(nToken&0xffffffff)+nDoc/2)/nDoc; | |
| 118438 | + } | |
| 118439 | + } | |
| 118440 | + } | |
| 118441 | + break; | |
| 118442 | + | |
| 118443 | + case FTS3_MATCHINFO_LENGTH: { | |
| 118444 | + sqlite3_stmt *pSelectDocsize = 0; | |
| 118445 | + rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize); | |
| 118446 | + if( rc==SQLITE_OK ){ | |
| 118447 | + int iCol; | |
| 118448 | + const char *a = sqlite3_column_blob(pSelectDocsize, 0); | |
| 118449 | + for(iCol=0; iCol<pInfo->nCol; iCol++){ | |
| 118450 | + sqlite3_int64 nToken; | |
| 118451 | + a += sqlite3Fts3GetVarint(a, &nToken); | |
| 118452 | + pInfo->aMatchinfo[iCol] = (u32)nToken; | |
| 118453 | + } | |
| 118454 | + } | |
| 118455 | + sqlite3_reset(pSelectDocsize); | |
| 118456 | + break; | |
| 118457 | + } | |
| 118458 | + | |
| 118459 | + case FTS3_MATCHINFO_LCS: | |
| 118460 | + rc = fts3ExprLoadDoclists(pCsr, 0, 0); | |
| 118461 | + if( rc==SQLITE_OK ){ | |
| 118462 | + rc = fts3MatchinfoLcs(pCsr, pInfo); | |
| 118463 | + } | |
| 118464 | + break; | |
| 118465 | + | |
| 118466 | + default: { | |
| 118467 | + Fts3Expr *pExpr; | |
| 118468 | + assert( zArg[i]==FTS3_MATCHINFO_HITS ); | |
| 118469 | + pExpr = pCsr->pExpr; | |
| 118470 | + rc = fts3ExprLoadDoclists(pCsr, 0, 0); | |
| 118471 | + if( rc!=SQLITE_OK ) break; | |
| 118472 | + if( bGlobal ){ | |
| 118473 | + if( pCsr->pDeferred ){ | |
| 118474 | + rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0); | |
| 118475 | + if( rc!=SQLITE_OK ) break; | |
| 118476 | + } | |
| 118477 | + rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); | |
| 118478 | + if( rc!=SQLITE_OK ) break; | |
| 118479 | + } | |
| 118480 | + (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); | |
| 118481 | + break; | |
| 118482 | + } | |
| 118483 | + } | |
| 118484 | + | |
| 118485 | + pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]); | |
| 118486 | + } | |
| 118487 | + | |
| 118488 | + sqlite3_reset(pSelect); | |
| 118489 | + return rc; | |
| 118490 | +} | |
| 118491 | + | |
| 118068 | 118492 | |
| 118069 | 118493 | /* |
| 118070 | 118494 | ** Populate pCsr->aMatchinfo[] with data for the current row. The |
| 118071 | 118495 | ** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). |
| 118072 | 118496 | */ |
| 118073 | -static int fts3GetMatchinfo(Fts3Cursor *pCsr){ | |
| 118497 | +static int fts3GetMatchinfo( | |
| 118498 | + Fts3Cursor *pCsr, /* FTS3 Cursor object */ | |
| 118499 | + const char *zArg /* Second argument to matchinfo() function */ | |
| 118500 | +){ | |
| 118074 | 118501 | MatchInfo sInfo; |
| 118075 | 118502 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 118076 | 118503 | int rc = SQLITE_OK; |
| 118504 | + int bGlobal = 0; /* Collect 'global' stats as well as local */ | |
| 118077 | 118505 | |
| 118506 | + memset(&sInfo, 0, sizeof(MatchInfo)); | |
| 118078 | 118507 | sInfo.pCursor = pCsr; |
| 118079 | 118508 | sInfo.nCol = pTab->nColumn; |
| 118080 | 118509 | |
| 118510 | + /* If there is cached matchinfo() data, but the format string for the | |
| 118511 | + ** cache does not match the format string for this request, discard | |
| 118512 | + ** the cached data. */ | |
| 118513 | + if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){ | |
| 118514 | + assert( pCsr->aMatchinfo ); | |
| 118515 | + sqlite3_free(pCsr->aMatchinfo); | |
| 118516 | + pCsr->zMatchinfo = 0; | |
| 118517 | + pCsr->aMatchinfo = 0; | |
| 118518 | + } | |
| 118519 | + | |
| 118520 | + /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the | |
| 118521 | + ** matchinfo function has been called for this query. In this case | |
| 118522 | + ** allocate the array used to accumulate the matchinfo data and | |
| 118523 | + ** initialize those elements that are constant for every row. | |
| 118524 | + */ | |
| 118081 | 118525 | if( pCsr->aMatchinfo==0 ){ |
| 118082 | - /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the | |
| 118083 | - ** matchinfo function has been called for this query. In this case | |
| 118084 | - ** allocate the array used to accumulate the matchinfo data and | |
| 118085 | - ** initialize those elements that are constant for every row. | |
| 118086 | - */ | |
| 118087 | - int nPhrase; /* Number of phrases */ | |
| 118088 | - int nMatchinfo; /* Number of u32 elements in match-info */ | |
| 118089 | - | |
| 118090 | - /* Load doclists for each phrase in the query. */ | |
| 118091 | - rc = fts3ExprLoadDoclists(pCsr, &nPhrase, 0); | |
| 118092 | - if( rc!=SQLITE_OK ){ | |
| 118093 | - return rc; | |
| 118094 | - } | |
| 118095 | - nMatchinfo = 2 + 3*sInfo.nCol*nPhrase; | |
| 118096 | - if( pTab->bHasDocsize ){ | |
| 118097 | - nMatchinfo += 1 + 2*pTab->nColumn; | |
| 118098 | - } | |
| 118099 | - | |
| 118100 | - sInfo.aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo); | |
| 118101 | - if( !sInfo.aMatchinfo ){ | |
| 118102 | - return SQLITE_NOMEM; | |
| 118103 | - } | |
| 118104 | - memset(sInfo.aMatchinfo, 0, sizeof(u32)*nMatchinfo); | |
| 118105 | - | |
| 118106 | - /* First element of match-info is the number of phrases in the query */ | |
| 118107 | - sInfo.aMatchinfo[0] = nPhrase; | |
| 118108 | - sInfo.aMatchinfo[1] = sInfo.nCol; | |
| 118109 | - if( pTab->bHasDocsize ){ | |
| 118110 | - int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; | |
| 118111 | - rc = sqlite3Fts3MatchinfoDocsizeGlobal(pCsr, &sInfo.aMatchinfo[ofst]); | |
| 118112 | - } | |
| 118113 | - (void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo); | |
| 118114 | - pCsr->aMatchinfo = sInfo.aMatchinfo; | |
| 118526 | + int nMatchinfo = 0; /* Number of u32 elements in match-info */ | |
| 118527 | + int nArg; /* Bytes in zArg */ | |
| 118528 | + int i; /* Used to iterate through zArg */ | |
| 118529 | + | |
| 118530 | + /* Determine the number of phrases in the query */ | |
| 118531 | + pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr); | |
| 118532 | + sInfo.nPhrase = pCsr->nPhrase; | |
| 118533 | + | |
| 118534 | + /* Determine the number of integers in the buffer returned by this call. */ | |
| 118535 | + for(i=0; zArg[i]; i++){ | |
| 118536 | + nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]); | |
| 118537 | + } | |
| 118538 | + | |
| 118539 | + /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */ | |
| 118540 | + nArg = strlen(zArg); | |
| 118541 | + pCsr->aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo + nArg + 1); | |
| 118542 | + if( !pCsr->aMatchinfo ) return SQLITE_NOMEM; | |
| 118543 | + | |
| 118544 | + pCsr->zMatchinfo = (char *)&pCsr->aMatchinfo[nMatchinfo]; | |
| 118545 | + pCsr->nMatchinfo = nMatchinfo; | |
| 118546 | + memcpy(pCsr->zMatchinfo, zArg, nArg+1); | |
| 118547 | + memset(pCsr->aMatchinfo, 0, sizeof(u32)*nMatchinfo); | |
| 118115 | 118548 | pCsr->isMatchinfoNeeded = 1; |
| 118549 | + bGlobal = 1; | |
| 118116 | 118550 | } |
| 118117 | 118551 | |
| 118118 | 118552 | sInfo.aMatchinfo = pCsr->aMatchinfo; |
| 118119 | - if( rc==SQLITE_OK && pCsr->isMatchinfoNeeded ){ | |
| 118120 | - (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void*)&sInfo); | |
| 118121 | - if( pTab->bHasDocsize ){ | |
| 118122 | - int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; | |
| 118123 | - rc = sqlite3Fts3MatchinfoDocsizeLocal(pCsr, &sInfo.aMatchinfo[ofst]); | |
| 118124 | - } | |
| 118553 | + sInfo.nPhrase = pCsr->nPhrase; | |
| 118554 | + if( pCsr->isMatchinfoNeeded ){ | |
| 118555 | + rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg); | |
| 118125 | 118556 | pCsr->isMatchinfoNeeded = 0; |
| 118126 | 118557 | } |
| 118127 | 118558 | |
| 118128 | - return SQLITE_OK; | |
| 118559 | + return rc; | |
| 118129 | 118560 | } |
| 118130 | 118561 | |
| 118131 | 118562 | /* |
| 118132 | 118563 | ** Implementation of snippet() function. |
| 118133 | 118564 | */ |
| @@ -118184,11 +118615,11 @@ | ||
| 118184 | 118615 | /* Loop through all columns of the table being considered for snippets. |
| 118185 | 118616 | ** If the iCol argument to this function was negative, this means all |
| 118186 | 118617 | ** columns of the FTS3 table. Otherwise, only column iCol is considered. |
| 118187 | 118618 | */ |
| 118188 | 118619 | for(iRead=0; iRead<pTab->nColumn; iRead++){ |
| 118189 | - SnippetFragment sF; | |
| 118620 | + SnippetFragment sF = {0, 0, 0, 0}; | |
| 118190 | 118621 | int iS; |
| 118191 | 118622 | if( iCol>=0 && iRead!=iCol ) continue; |
| 118192 | 118623 | |
| 118193 | 118624 | /* Find the best snippet of nFToken tokens in column iRead. */ |
| 118194 | 118625 | rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS); |
| @@ -118411,26 +118842,47 @@ | ||
| 118411 | 118842 | } |
| 118412 | 118843 | |
| 118413 | 118844 | /* |
| 118414 | 118845 | ** Implementation of matchinfo() function. |
| 118415 | 118846 | */ |
| 118416 | -SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *pCsr){ | |
| 118847 | +SQLITE_PRIVATE void sqlite3Fts3Matchinfo( | |
| 118848 | + sqlite3_context *pContext, /* Function call context */ | |
| 118849 | + Fts3Cursor *pCsr, /* FTS3 table cursor */ | |
| 118850 | + const char *zArg /* Second arg to matchinfo() function */ | |
| 118851 | +){ | |
| 118852 | + Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; | |
| 118417 | 118853 | int rc; |
| 118854 | + int i; | |
| 118855 | + const char *zFormat; | |
| 118856 | + | |
| 118857 | + if( zArg ){ | |
| 118858 | + for(i=0; zArg[i]; i++){ | |
| 118859 | + char *zErr = 0; | |
| 118860 | + if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){ | |
| 118861 | + sqlite3_result_error(pContext, zErr, -1); | |
| 118862 | + sqlite3_free(zErr); | |
| 118863 | + return; | |
| 118864 | + } | |
| 118865 | + } | |
| 118866 | + zFormat = zArg; | |
| 118867 | + }else{ | |
| 118868 | + zFormat = FTS3_MATCHINFO_DEFAULT; | |
| 118869 | + } | |
| 118870 | + | |
| 118418 | 118871 | if( !pCsr->pExpr ){ |
| 118419 | 118872 | sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); |
| 118420 | 118873 | return; |
| 118421 | 118874 | } |
| 118422 | - rc = fts3GetMatchinfo(pCsr); | |
| 118423 | - sqlite3Fts3SegmentsClose((Fts3Table *)pCsr->base.pVtab ); | |
| 118875 | + | |
| 118876 | + /* Retrieve matchinfo() data. */ | |
| 118877 | + rc = fts3GetMatchinfo(pCsr, zFormat); | |
| 118878 | + sqlite3Fts3SegmentsClose(pTab); | |
| 118879 | + | |
| 118424 | 118880 | if( rc!=SQLITE_OK ){ |
| 118425 | 118881 | sqlite3_result_error_code(pContext, rc); |
| 118426 | 118882 | }else{ |
| 118427 | - Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab; | |
| 118428 | - int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*3); | |
| 118429 | - if( pTab->bHasDocsize ){ | |
| 118430 | - n += sizeof(u32)*(1 + 2*pTab->nColumn); | |
| 118431 | - } | |
| 118883 | + int n = pCsr->nMatchinfo * sizeof(u32); | |
| 118432 | 118884 | sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); |
| 118433 | 118885 | } |
| 118434 | 118886 | } |
| 118435 | 118887 | |
| 118436 | 118888 | #endif |
| @@ -118545,10 +118997,16 @@ | ||
| 118545 | 118997 | #include "sqlite3rtree.h" |
| 118546 | 118998 | typedef sqlite3_int64 i64; |
| 118547 | 118999 | typedef unsigned char u8; |
| 118548 | 119000 | typedef unsigned int u32; |
| 118549 | 119001 | #endif |
| 119002 | + | |
| 119003 | +/* The following macro is used to suppress compiler warnings. | |
| 119004 | +*/ | |
| 119005 | +#ifndef UNUSED_PARAMETER | |
| 119006 | +# define UNUSED_PARAMETER(x) (void)(x) | |
| 119007 | +#endif | |
| 118550 | 119008 | |
| 118551 | 119009 | typedef struct Rtree Rtree; |
| 118552 | 119010 | typedef struct RtreeCursor RtreeCursor; |
| 118553 | 119011 | typedef struct RtreeNode RtreeNode; |
| 118554 | 119012 | typedef struct RtreeCell RtreeCell; |
| @@ -119627,11 +120085,11 @@ | ||
| 119627 | 120085 | /* Check that value is actually a blob. */ |
| 119628 | 120086 | if( !sqlite3_value_type(pValue)==SQLITE_BLOB ) return SQLITE_ERROR; |
| 119629 | 120087 | |
| 119630 | 120088 | /* Check that the blob is roughly the right size. */ |
| 119631 | 120089 | nBlob = sqlite3_value_bytes(pValue); |
| 119632 | - if( nBlob<sizeof(RtreeMatchArg) | |
| 120090 | + if( nBlob<(int)sizeof(RtreeMatchArg) | |
| 119633 | 120091 | || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0 |
| 119634 | 120092 | ){ |
| 119635 | 120093 | return SQLITE_ERROR; |
| 119636 | 120094 | } |
| 119637 | 120095 | |
| @@ -119642,11 +120100,11 @@ | ||
| 119642 | 120100 | memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); |
| 119643 | 120101 | p = (RtreeMatchArg *)&pGeom[1]; |
| 119644 | 120102 | |
| 119645 | 120103 | memcpy(p, sqlite3_value_blob(pValue), nBlob); |
| 119646 | 120104 | if( p->magic!=RTREE_GEOMETRY_MAGIC |
| 119647 | - || nBlob!=(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) | |
| 120105 | + || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) | |
| 119648 | 120106 | ){ |
| 119649 | 120107 | sqlite3_free(pGeom); |
| 119650 | 120108 | return SQLITE_ERROR; |
| 119651 | 120109 | } |
| 119652 | 120110 | |
| @@ -119788,10 +120246,11 @@ | ||
| 119788 | 120246 | int ii, cCol; |
| 119789 | 120247 | |
| 119790 | 120248 | int iIdx = 0; |
| 119791 | 120249 | char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; |
| 119792 | 120250 | memset(zIdxStr, 0, sizeof(zIdxStr)); |
| 120251 | + UNUSED_PARAMETER(tab); | |
| 119793 | 120252 | |
| 119794 | 120253 | assert( pIdxInfo->idxStr==0 ); |
| 119795 | 120254 | for(ii=0; ii<pIdxInfo->nConstraint; ii++){ |
| 119796 | 120255 | struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; |
| 119797 | 120256 | |
| @@ -119961,10 +120420,11 @@ | ||
| 119961 | 120420 | for(ii=0; ii<nCell; ii++){ |
| 119962 | 120421 | #if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 119963 | 120422 | if( ii!=iExclude ) |
| 119964 | 120423 | #else |
| 119965 | 120424 | assert( iExclude==-1 ); |
| 120425 | + UNUSED_PARAMETER(iExclude); | |
| 119966 | 120426 | #endif |
| 119967 | 120427 | { |
| 119968 | 120428 | int jj; |
| 119969 | 120429 | float o = 1.0; |
| 119970 | 120430 | for(jj=0; jj<(pRtree->nDim*2); jj+=2){ |
| @@ -121082,20 +121542,10 @@ | ||
| 121082 | 121542 | rc = sqlite3_reset(pRtree->pWriteRowid); |
| 121083 | 121543 | *piRowid = sqlite3_last_insert_rowid(pRtree->db); |
| 121084 | 121544 | return rc; |
| 121085 | 121545 | } |
| 121086 | 121546 | |
| 121087 | -#ifndef NDEBUG | |
| 121088 | -static int hashIsEmpty(Rtree *pRtree){ | |
| 121089 | - int ii; | |
| 121090 | - for(ii=0; ii<HASHSIZE; ii++){ | |
| 121091 | - assert( !pRtree->aHash[ii] ); | |
| 121092 | - } | |
| 121093 | - return 1; | |
| 121094 | -} | |
| 121095 | -#endif | |
| 121096 | - | |
| 121097 | 121547 | /* |
| 121098 | 121548 | ** The xUpdate method for rtree module virtual tables. |
| 121099 | 121549 | */ |
| 121100 | 121550 | static int rtreeUpdate( |
| 121101 | 121551 | sqlite3_vtab *pVtab, |
| @@ -121557,10 +122007,11 @@ | ||
| 121557 | 122007 | char *zText = 0; |
| 121558 | 122008 | RtreeNode node; |
| 121559 | 122009 | Rtree tree; |
| 121560 | 122010 | int ii; |
| 121561 | 122011 | |
| 122012 | + UNUSED_PARAMETER(nArg); | |
| 121562 | 122013 | memset(&node, 0, sizeof(RtreeNode)); |
| 121563 | 122014 | memset(&tree, 0, sizeof(Rtree)); |
| 121564 | 122015 | tree.nDim = sqlite3_value_int(apArg[0]); |
| 121565 | 122016 | tree.nBytesPerCell = 8 + 8 * tree.nDim; |
| 121566 | 122017 | node.zData = (u8 *)sqlite3_value_blob(apArg[1]); |
| @@ -121590,10 +122041,11 @@ | ||
| 121590 | 122041 | |
| 121591 | 122042 | sqlite3_result_text(ctx, zText, -1, sqlite3_free); |
| 121592 | 122043 | } |
| 121593 | 122044 | |
| 121594 | 122045 | static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ |
| 122046 | + UNUSED_PARAMETER(nArg); | |
| 121595 | 122047 | if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB |
| 121596 | 122048 | || sqlite3_value_bytes(apArg[0])<2 |
| 121597 | 122049 | ){ |
| 121598 | 122050 | sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1); |
| 121599 | 122051 | }else{ |
| @@ -121611,11 +122063,10 @@ | ||
| 121611 | 122063 | const int utf8 = SQLITE_UTF8; |
| 121612 | 122064 | int rc; |
| 121613 | 122065 | |
| 121614 | 122066 | rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); |
| 121615 | 122067 | if( rc==SQLITE_OK ){ |
| 121616 | - int utf8 = SQLITE_UTF8; | |
| 121617 | 122068 | rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); |
| 121618 | 122069 | } |
| 121619 | 122070 | if( rc==SQLITE_OK ){ |
| 121620 | 122071 | void *c = (void *)RTREE_COORD_REAL32; |
| 121621 | 122072 | rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); |
| 121622 | 122073 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -650,11 +650,11 @@ | |
| 650 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 651 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 652 | */ |
| 653 | #define SQLITE_VERSION "3.7.4" |
| 654 | #define SQLITE_VERSION_NUMBER 3007004 |
| 655 | #define SQLITE_SOURCE_ID "2010-11-16 23:10:26 fd5b2f23dd5111d2f0934dd828bae36b755024c1" |
| 656 | |
| 657 | /* |
| 658 | ** CAPI3REF: Run-Time Library Version Numbers |
| 659 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 660 | ** |
| @@ -1083,10 +1083,22 @@ | |
| 1083 | ** sync operation only needs to flush data to mass storage. Inode |
| 1084 | ** information need not be flushed. If the lower four bits of the flag |
| 1085 | ** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. |
| 1086 | ** If the lower four bits equal SQLITE_SYNC_FULL, that means |
| 1087 | ** to use Mac OS X style fullsync instead of fsync(). |
| 1088 | */ |
| 1089 | #define SQLITE_SYNC_NORMAL 0x00002 |
| 1090 | #define SQLITE_SYNC_FULL 0x00003 |
| 1091 | #define SQLITE_SYNC_DATAONLY 0x00010 |
| 1092 | |
| @@ -1251,10 +1263,12 @@ | |
| 1251 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 1252 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 1253 | #define SQLITE_LAST_ERRNO 4 |
| 1254 | #define SQLITE_FCNTL_SIZE_HINT 5 |
| 1255 | #define SQLITE_FCNTL_CHUNK_SIZE 6 |
| 1256 | |
| 1257 | /* |
| 1258 | ** CAPI3REF: Mutex Handle |
| 1259 | ** |
| 1260 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -3178,18 +3192,17 @@ | |
| 3178 | |
| 3179 | /* |
| 3180 | ** CAPI3REF: Determine If An SQL Statement Writes The Database |
| 3181 | ** |
| 3182 | ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if |
| 3183 | ** the [prepared statement] X is guaranteed to leave the database file |
| 3184 | ** unmodified. ^If the sqlite3_stmt_readonly(X) interface returns false (zero) |
| 3185 | ** then evaluating the statement might change the database file, but this |
| 3186 | ** is not guaranteed as the write operation might be conditional and the |
| 3187 | ** condition might not be met. ^If X is a NULL pointer then |
| 3188 | ** sqlite3_stmt_readonly(X) returns true. If X is a non-NULL pointer but |
| 3189 | ** is not a pointer to a valid, unfinalized prepared statement, then the |
| 3190 | ** behavior is undefined and probably harmful. |
| 3191 | */ |
| 3192 | SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); |
| 3193 | |
| 3194 | /* |
| 3195 | ** CAPI3REF: Dynamically Typed Value Object |
| @@ -5781,19 +5794,25 @@ | |
| 5781 | ** CAPI3REF: Low-Level Control Of Database Files |
| 5782 | ** |
| 5783 | ** ^The [sqlite3_file_control()] interface makes a direct call to the |
| 5784 | ** xFileControl method for the [sqlite3_io_methods] object associated |
| 5785 | ** with a particular database identified by the second argument. ^The |
| 5786 | ** name of the database "main" for the main database or "temp" for the |
| 5787 | ** TEMP database, or the name that appears after the AS keyword for |
| 5788 | ** databases that are added using the [ATTACH] SQL command. |
| 5789 | ** ^A NULL pointer can be used in place of "main" to refer to the |
| 5790 | ** main database file. |
| 5791 | ** ^The third and fourth parameters to this routine |
| 5792 | ** are passed directly through to the second and third parameters of |
| 5793 | ** the xFileControl method. ^The return value of the xFileControl |
| 5794 | ** method becomes the return value of this routine. |
| 5795 | ** |
| 5796 | ** ^If the second parameter (zDbName) does not match the name of any |
| 5797 | ** open database file, then SQLITE_ERROR is returned. ^This error |
| 5798 | ** code is not remembered and will not be recalled by [sqlite3_errcode()] |
| 5799 | ** or [sqlite3_errmsg()]. The underlying xFileControl method might |
| @@ -7460,11 +7479,11 @@ | |
| 7460 | #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ |
| 7461 | #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ |
| 7462 | |
| 7463 | SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); |
| 7464 | SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); |
| 7465 | SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); |
| 7466 | SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); |
| 7467 | SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); |
| 7468 | SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); |
| 7469 | SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); |
| 7470 | SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); |
| @@ -7944,16 +7963,16 @@ | |
| 7944 | #define OP_VColumn 129 |
| 7945 | #define OP_VNext 131 |
| 7946 | #define OP_VRename 132 |
| 7947 | #define OP_VUpdate 133 |
| 7948 | #define OP_Pagecount 134 |
| 7949 | #define OP_Trace 135 |
| 7950 | #define OP_Noop 136 |
| 7951 | #define OP_Explain 137 |
| 7952 | |
| 7953 | /* The following opcode values are never used */ |
| 7954 | #define OP_NotUsed_138 138 |
| 7955 | #define OP_NotUsed_139 139 |
| 7956 | #define OP_NotUsed_140 140 |
| 7957 | |
| 7958 | |
| 7959 | /* Properties such as "out2" or "jump" that are specified in |
| @@ -7982,11 +8001,11 @@ | |
| 7982 | /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x02,\ |
| 7983 | /* 96 */ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 7984 | /* 104 */ 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01,\ |
| 7985 | /* 112 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\ |
| 7986 | /* 120 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 7987 | /* 128 */ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00,\ |
| 7988 | /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\ |
| 7989 | /* 144 */ 0x04, 0x04,} |
| 7990 | |
| 7991 | /************** End of opcodes.h *********************************************/ |
| 7992 | /************** Continuing where we left off in vdbe.h ***********************/ |
| @@ -8167,11 +8186,11 @@ | |
| 8167 | /* Functions used to configure a Pager object. */ |
| 8168 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 8169 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| 8170 | SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); |
| 8171 | SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); |
| 8172 | SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int); |
| 8173 | SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); |
| 8174 | SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); |
| 8175 | SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); |
| 8176 | SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); |
| 8177 | SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); |
| @@ -9032,17 +9051,18 @@ | |
| 9032 | ** accessing read-only databases */ |
| 9033 | #define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */ |
| 9034 | #define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */ |
| 9035 | #define SQLITE_LegacyFileFmt 0x00100000 /* Create new databases in format 1 */ |
| 9036 | #define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */ |
| 9037 | #define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ |
| 9038 | #define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */ |
| 9039 | #define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */ |
| 9040 | #define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */ |
| 9041 | #define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */ |
| 9042 | #define SQLITE_AutoIndex 0x08000000 /* Enable automatic indexes */ |
| 9043 | #define SQLITE_PreferBuiltin 0x10000000 /* Preference to built-in funcs */ |
| 9044 | |
| 9045 | /* |
| 9046 | ** Bits of the sqlite3.flags field that are used by the |
| 9047 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface. |
| 9048 | ** These must be the low-order bits of the flags field. |
| @@ -10957,10 +10977,11 @@ | |
| 10957 | SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); |
| 10958 | SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*); |
| 10959 | SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); |
| 10960 | SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); |
| 10961 | SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); |
| 10962 | SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); |
| 10963 | SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); |
| 10964 | SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**); |
| 10965 | |
| 10966 | /* |
| @@ -20458,10 +20479,20 @@ | |
| 20458 | v = -v; |
| 20459 | } |
| 20460 | *pValue = (int)v; |
| 20461 | return 1; |
| 20462 | } |
| 20463 | |
| 20464 | /* |
| 20465 | ** The variable-length integer encoding is as follows: |
| 20466 | ** |
| 20467 | ** KEY: |
| @@ -21388,14 +21419,14 @@ | |
| 21388 | /* 130 */ "Real", |
| 21389 | /* 131 */ "VNext", |
| 21390 | /* 132 */ "VRename", |
| 21391 | /* 133 */ "VUpdate", |
| 21392 | /* 134 */ "Pagecount", |
| 21393 | /* 135 */ "Trace", |
| 21394 | /* 136 */ "Noop", |
| 21395 | /* 137 */ "Explain", |
| 21396 | /* 138 */ "NotUsed_138", |
| 21397 | /* 139 */ "NotUsed_139", |
| 21398 | /* 140 */ "NotUsed_140", |
| 21399 | /* 141 */ "ToText", |
| 21400 | /* 142 */ "ToBlob", |
| 21401 | /* 143 */ "ToNumeric", |
| @@ -27946,11 +27977,11 @@ | |
| 27946 | static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){ |
| 27947 | static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; |
| 27948 | #if defined(NO_GETTOD) |
| 27949 | time_t t; |
| 27950 | time(&t); |
| 27951 | *piNow = ((sqlite3_int64)i)*1000 + unixEpoch; |
| 27952 | #elif OS_VXWORKS |
| 27953 | struct timespec sNow; |
| 27954 | clock_gettime(CLOCK_REALTIME, &sNow); |
| 27955 | *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000; |
| 27956 | #else |
| @@ -35273,11 +35304,12 @@ | |
| 35273 | u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ |
| 35274 | u8 useJournal; /* Use a rollback journal on this file */ |
| 35275 | u8 noReadlock; /* Do not bother to obtain readlocks */ |
| 35276 | u8 noSync; /* Do not sync the journal if true */ |
| 35277 | u8 fullSync; /* Do extra syncs of the journal for robustness */ |
| 35278 | u8 sync_flags; /* One of SYNC_NORMAL or SYNC_FULL */ |
| 35279 | u8 tempFile; /* zFilename is a temporary file */ |
| 35280 | u8 readOnly; /* True for a read-only database */ |
| 35281 | u8 memDb; /* True to inhibit all file I/O */ |
| 35282 | |
| 35283 | /************************************************************************** |
| @@ -35957,11 +35989,11 @@ | |
| 35957 | }else{ |
| 35958 | static const char zeroHdr[28] = {0}; |
| 35959 | rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0); |
| 35960 | } |
| 35961 | if( rc==SQLITE_OK && !pPager->noSync ){ |
| 35962 | rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags); |
| 35963 | } |
| 35964 | |
| 35965 | /* At this point the transaction is committed but the write lock |
| 35966 | ** is still held on the file. If there is a size limit configured for |
| 35967 | ** the persistent journal and the journal file currently consumes more |
| @@ -37409,11 +37441,11 @@ | |
| 37409 | testcase( rc!=SQLITE_OK ); |
| 37410 | } |
| 37411 | if( rc==SQLITE_OK && !pPager->noSync |
| 37412 | && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) |
| 37413 | ){ |
| 37414 | rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); |
| 37415 | } |
| 37416 | if( rc==SQLITE_OK ){ |
| 37417 | rc = pager_end_transaction(pPager, zMaster[0]!='\0'); |
| 37418 | testcase( rc!=SQLITE_OK ); |
| 37419 | } |
| @@ -37583,17 +37615,17 @@ | |
| 37583 | static int pagerWalFrames( |
| 37584 | Pager *pPager, /* Pager object */ |
| 37585 | PgHdr *pList, /* List of frames to log */ |
| 37586 | Pgno nTruncate, /* Database size after this commit */ |
| 37587 | int isCommit, /* True if this is a commit */ |
| 37588 | int sync_flags /* Flags to pass to OsSync() (or 0) */ |
| 37589 | ){ |
| 37590 | int rc; /* Return code */ |
| 37591 | |
| 37592 | assert( pPager->pWal ); |
| 37593 | rc = sqlite3WalFrames(pPager->pWal, |
| 37594 | pPager->pageSize, pList, nTruncate, isCommit, sync_flags |
| 37595 | ); |
| 37596 | if( rc==SQLITE_OK && pPager->pBackup ){ |
| 37597 | PgHdr *p; |
| 37598 | for(p=pList; p; p=p->pDirty){ |
| 37599 | sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); |
| @@ -37918,19 +37950,54 @@ | |
| 37918 | ** of the journal header - being written in between the two |
| 37919 | ** syncs). If we assume that writing a |
| 37920 | ** single disk sector is atomic, then this mode provides |
| 37921 | ** assurance that the journal will not be corrupted to the |
| 37922 | ** point of causing damage to the database during rollback. |
| 37923 | ** |
| 37924 | ** Numeric values associated with these states are OFF==1, NORMAL=2, |
| 37925 | ** and FULL=3. |
| 37926 | */ |
| 37927 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 37928 | SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){ |
| 37929 | pPager->noSync = (level==1 || pPager->tempFile) ?1:0; |
| 37930 | pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0; |
| 37931 | pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL); |
| 37932 | } |
| 37933 | #endif |
| 37934 | |
| 37935 | /* |
| 37936 | ** The following global variable is incremented whenever the library |
| @@ -38105,13 +38172,12 @@ | |
| 38105 | */ |
| 38106 | SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ |
| 38107 | if( mxPage>0 ){ |
| 38108 | pPager->mxPgno = mxPage; |
| 38109 | } |
| 38110 | if( pPager->eState!=PAGER_OPEN && pPager->mxPgno<pPager->dbSize ){ |
| 38111 | pPager->mxPgno = pPager->dbSize; |
| 38112 | } |
| 38113 | return pPager->mxPgno; |
| 38114 | } |
| 38115 | |
| 38116 | /* |
| 38117 | ** The following set of routines are used to disable the simulated |
| @@ -38312,14 +38378,11 @@ | |
| 38312 | disable_simulated_io_errors(); |
| 38313 | sqlite3BeginBenignMalloc(); |
| 38314 | /* pPager->errCode = 0; */ |
| 38315 | pPager->exclusiveMode = 0; |
| 38316 | #ifndef SQLITE_OMIT_WAL |
| 38317 | sqlite3WalClose(pPager->pWal, |
| 38318 | (pPager->noSync ? 0 : pPager->sync_flags), |
| 38319 | pPager->pageSize, pTmp |
| 38320 | ); |
| 38321 | pPager->pWal = 0; |
| 38322 | #endif |
| 38323 | pager_reset(pPager); |
| 38324 | if( MEMDB ){ |
| 38325 | pager_unlock(pPager); |
| @@ -38481,11 +38544,11 @@ | |
| 38481 | ** and never needs to be updated. |
| 38482 | */ |
| 38483 | if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ |
| 38484 | PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); |
| 38485 | IOTRACE(("JSYNC %p\n", pPager)) |
| 38486 | rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags); |
| 38487 | if( rc!=SQLITE_OK ) return rc; |
| 38488 | } |
| 38489 | IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr)); |
| 38490 | rc = sqlite3OsWrite( |
| 38491 | pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr |
| @@ -38493,12 +38556,12 @@ | |
| 38493 | if( rc!=SQLITE_OK ) return rc; |
| 38494 | } |
| 38495 | if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ |
| 38496 | PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); |
| 38497 | IOTRACE(("JSYNC %p\n", pPager)) |
| 38498 | rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| |
| 38499 | (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) |
| 38500 | ); |
| 38501 | if( rc!=SQLITE_OK ) return rc; |
| 38502 | } |
| 38503 | |
| 38504 | pPager->journalHdr = pPager->journalOff; |
| @@ -39084,11 +39147,12 @@ | |
| 39084 | pPager->memDb = (u8)memDb; |
| 39085 | pPager->readOnly = (u8)readOnly; |
| 39086 | assert( useJournal || pPager->tempFile ); |
| 39087 | pPager->noSync = pPager->tempFile; |
| 39088 | pPager->fullSync = pPager->noSync ?0:1; |
| 39089 | pPager->sync_flags = SQLITE_SYNC_NORMAL; |
| 39090 | /* pPager->pFirst = 0; */ |
| 39091 | /* pPager->pFirstSynced = 0; */ |
| 39092 | /* pPager->pLast = 0; */ |
| 39093 | pPager->nExtra = (u16)nExtra; |
| 39094 | pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; |
| @@ -40207,23 +40271,23 @@ | |
| 40207 | } |
| 40208 | return rc; |
| 40209 | } |
| 40210 | |
| 40211 | /* |
| 40212 | ** Sync the pager file to disk. This is a no-op for in-memory files |
| 40213 | ** or pages with the Pager.noSync flag set. |
| 40214 | ** |
| 40215 | ** If successful, or called on a pager for which it is a no-op, this |
| 40216 | ** function returns SQLITE_OK. Otherwise, an IO error code is returned. |
| 40217 | */ |
| 40218 | SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){ |
| 40219 | int rc; /* Return code */ |
| 40220 | assert( !MEMDB ); |
| 40221 | if( pPager->noSync ){ |
| 40222 | rc = SQLITE_OK; |
| 40223 | }else{ |
| 40224 | rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); |
| 40225 | } |
| 40226 | return rc; |
| 40227 | } |
| 40228 | |
| 40229 | /* |
| @@ -40308,11 +40372,11 @@ | |
| 40308 | }else{ |
| 40309 | if( pagerUseWal(pPager) ){ |
| 40310 | PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); |
| 40311 | if( pList ){ |
| 40312 | rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1, |
| 40313 | (pPager->fullSync ? pPager->sync_flags : 0) |
| 40314 | ); |
| 40315 | } |
| 40316 | if( rc==SQLITE_OK ){ |
| 40317 | sqlite3PcacheCleanAll(pPager->pPCache); |
| 40318 | } |
| @@ -40439,11 +40503,11 @@ | |
| 40439 | if( rc!=SQLITE_OK ) goto commit_phase_one_exit; |
| 40440 | } |
| 40441 | |
| 40442 | /* Finally, sync the database file. */ |
| 40443 | if( !pPager->noSync && !noSync ){ |
| 40444 | rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); |
| 40445 | } |
| 40446 | IOTRACE(("DBSYNC %p\n", pPager)) |
| 40447 | } |
| 40448 | } |
| 40449 | |
| @@ -41180,14 +41244,12 @@ | |
| 41180 | */ |
| 41181 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager){ |
| 41182 | int rc = SQLITE_OK; |
| 41183 | if( pPager->pWal ){ |
| 41184 | u8 *zBuf = (u8 *)pPager->pTmpSpace; |
| 41185 | rc = sqlite3WalCheckpoint(pPager->pWal, |
| 41186 | (pPager->noSync ? 0 : pPager->sync_flags), |
| 41187 | pPager->pageSize, zBuf |
| 41188 | ); |
| 41189 | } |
| 41190 | return rc; |
| 41191 | } |
| 41192 | |
| 41193 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ |
| @@ -41335,14 +41397,12 @@ | |
| 41335 | ** the database file, the log and log-summary files will be deleted. |
| 41336 | */ |
| 41337 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 41338 | rc = pagerExclusiveLock(pPager); |
| 41339 | if( rc==SQLITE_OK ){ |
| 41340 | rc = sqlite3WalClose(pPager->pWal, |
| 41341 | (pPager->noSync ? 0 : pPager->sync_flags), |
| 41342 | pPager->pageSize, (u8*)pPager->pTmpSpace |
| 41343 | ); |
| 41344 | pPager->pWal = 0; |
| 41345 | } |
| 41346 | } |
| 41347 | return rc; |
| 41348 | } |
| @@ -47231,15 +47291,21 @@ | |
| 47231 | ** there is a high probability of damage) Level 2 is the default. There |
| 47232 | ** is a very low but non-zero probability of damage. Level 3 reduces the |
| 47233 | ** probability of damage to near zero but with a write performance reduction. |
| 47234 | */ |
| 47235 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 47236 | SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ |
| 47237 | BtShared *pBt = p->pBt; |
| 47238 | assert( sqlite3_mutex_held(p->db->mutex) ); |
| 47239 | sqlite3BtreeEnter(p); |
| 47240 | sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync); |
| 47241 | sqlite3BtreeLeave(p); |
| 47242 | return SQLITE_OK; |
| 47243 | } |
| 47244 | #endif |
| 47245 | |
| @@ -59986,17 +60052,17 @@ | |
| 59986 | /* |
| 59987 | ** Try to convert the type of a function argument or a result column |
| 59988 | ** into a numeric representation. Use either INTEGER or REAL whichever |
| 59989 | ** is appropriate. But only do the conversion if it is possible without |
| 59990 | ** loss of information and return the revised type of the argument. |
| 59991 | ** |
| 59992 | ** This is an EXPERIMENTAL api and is subject to change or removal. |
| 59993 | */ |
| 59994 | SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ |
| 59995 | Mem *pMem = (Mem*)pVal; |
| 59996 | applyNumericAffinity(pMem); |
| 59997 | sqlite3VdbeMemStoreType(pMem); |
| 59998 | return pMem->type; |
| 59999 | } |
| 60000 | |
| 60001 | /* |
| 60002 | ** Exported version of applyAffinity(). This one works on sqlite3_value*, |
| @@ -66078,10 +66144,36 @@ | |
| 66078 | case OP_Pagecount: { /* out2-prerelease */ |
| 66079 | pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt); |
| 66080 | break; |
| 66081 | } |
| 66082 | #endif |
| 66083 | |
| 66084 | #ifndef SQLITE_OMIT_TRACE |
| 66085 | /* Opcode: Trace * * * P4 * |
| 66086 | ** |
| 66087 | ** If tracing is enabled (by the sqlite3_trace()) interface, then |
| @@ -85223,11 +85315,11 @@ | |
| 85223 | static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; |
| 85224 | static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; |
| 85225 | static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; |
| 85226 | int i, n; |
| 85227 | if( sqlite3Isdigit(*z) ){ |
| 85228 | return (u8)atoi(z); |
| 85229 | } |
| 85230 | n = sqlite3Strlen30(z); |
| 85231 | for(i=0; i<ArraySize(iLength); i++){ |
| 85232 | if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){ |
| 85233 | return iValue[i]; |
| @@ -85264,11 +85356,11 @@ | |
| 85264 | static int getAutoVacuum(const char *z){ |
| 85265 | int i; |
| 85266 | if( 0==sqlite3StrICmp(z, "none") ) return BTREE_AUTOVACUUM_NONE; |
| 85267 | if( 0==sqlite3StrICmp(z, "full") ) return BTREE_AUTOVACUUM_FULL; |
| 85268 | if( 0==sqlite3StrICmp(z, "incremental") ) return BTREE_AUTOVACUUM_INCR; |
| 85269 | i = atoi(z); |
| 85270 | return (u8)((i>=0&&i<=2)?i:0); |
| 85271 | } |
| 85272 | #endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ |
| 85273 | |
| 85274 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| @@ -85360,10 +85452,11 @@ | |
| 85360 | { "short_column_names", SQLITE_ShortColNames }, |
| 85361 | { "count_changes", SQLITE_CountRows }, |
| 85362 | { "empty_result_callbacks", SQLITE_NullCallback }, |
| 85363 | { "legacy_file_format", SQLITE_LegacyFileFmt }, |
| 85364 | { "fullfsync", SQLITE_FullFSync }, |
| 85365 | { "reverse_unordered_selects", SQLITE_ReverseOrder }, |
| 85366 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX |
| 85367 | { "automatic_index", SQLITE_AutoIndex }, |
| 85368 | #endif |
| 85369 | #ifdef SQLITE_DEBUG |
| @@ -85571,11 +85664,11 @@ | |
| 85571 | addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); |
| 85572 | sqlite3VdbeChangeP1(v, addr, iDb); |
| 85573 | sqlite3VdbeChangeP1(v, addr+1, iDb); |
| 85574 | sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE); |
| 85575 | }else{ |
| 85576 | int size = atoi(zRight); |
| 85577 | if( size<0 ) size = -size; |
| 85578 | sqlite3BeginWriteOperation(pParse, 0, iDb); |
| 85579 | sqlite3VdbeAddOp2(v, OP_Integer, size, 1); |
| 85580 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); |
| 85581 | pDb->pSchema->cache_size = size; |
| @@ -85600,39 +85693,17 @@ | |
| 85600 | returnSingleInt(pParse, "page_size", size); |
| 85601 | }else{ |
| 85602 | /* Malloc may fail when setting the page-size, as there is an internal |
| 85603 | ** buffer that the pager module resizes using sqlite3_realloc(). |
| 85604 | */ |
| 85605 | db->nextPagesize = atoi(zRight); |
| 85606 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
| 85607 | db->mallocFailed = 1; |
| 85608 | } |
| 85609 | } |
| 85610 | }else |
| 85611 | |
| 85612 | /* |
| 85613 | ** PRAGMA [database.]max_page_count |
| 85614 | ** PRAGMA [database.]max_page_count=N |
| 85615 | ** |
| 85616 | ** The first form reports the current setting for the |
| 85617 | ** maximum number of pages in the database file. The |
| 85618 | ** second form attempts to change this setting. Both |
| 85619 | ** forms return the current setting. |
| 85620 | */ |
| 85621 | if( sqlite3StrICmp(zLeft,"max_page_count")==0 ){ |
| 85622 | Btree *pBt = pDb->pBt; |
| 85623 | int newMax = 0; |
| 85624 | assert( pBt!=0 ); |
| 85625 | if( zRight ){ |
| 85626 | newMax = atoi(zRight); |
| 85627 | } |
| 85628 | if( ALWAYS(pBt) ){ |
| 85629 | newMax = sqlite3BtreeMaxPageCount(pBt, newMax); |
| 85630 | } |
| 85631 | returnSingleInt(pParse, "max_page_count", newMax); |
| 85632 | }else |
| 85633 | |
| 85634 | /* |
| 85635 | ** PRAGMA [database.]secure_delete |
| 85636 | ** PRAGMA [database.]secure_delete=ON/OFF |
| 85637 | ** |
| 85638 | ** The first form reports the current setting for the |
| @@ -85655,23 +85726,37 @@ | |
| 85655 | b = sqlite3BtreeSecureDelete(pBt, b); |
| 85656 | returnSingleInt(pParse, "secure_delete", b); |
| 85657 | }else |
| 85658 | |
| 85659 | /* |
| 85660 | ** PRAGMA [database.]page_count |
| 85661 | ** |
| 85662 | ** Return the number of pages in the specified database. |
| 85663 | */ |
| 85664 | if( sqlite3StrICmp(zLeft,"page_count")==0 ){ |
| 85665 | int iReg; |
| 85666 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 85667 | sqlite3CodeVerifySchema(pParse, iDb); |
| 85668 | iReg = ++pParse->nMem; |
| 85669 | sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); |
| 85670 | sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); |
| 85671 | sqlite3VdbeSetNumCols(v, 1); |
| 85672 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "page_count", SQLITE_STATIC); |
| 85673 | }else |
| 85674 | |
| 85675 | /* |
| 85676 | ** PRAGMA [database.]locking_mode |
| 85677 | ** PRAGMA [database.]locking_mode = (normal|exclusive) |
| @@ -85889,11 +85974,11 @@ | |
| 85889 | if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ |
| 85890 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 85891 | if( !zRight ){ |
| 85892 | returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); |
| 85893 | }else{ |
| 85894 | int size = atoi(zRight); |
| 85895 | if( size<0 ) size = -size; |
| 85896 | pDb->pSchema->cache_size = size; |
| 85897 | sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
| 85898 | } |
| 85899 | }else |
| @@ -86282,11 +86367,11 @@ | |
| 86282 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); |
| 86283 | |
| 86284 | /* Set the maximum error count */ |
| 86285 | mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
| 86286 | if( zRight ){ |
| 86287 | mxErr = atoi(zRight); |
| 86288 | if( mxErr<=0 ){ |
| 86289 | mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
| 86290 | } |
| 86291 | } |
| 86292 | sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */ |
| @@ -86539,11 +86624,11 @@ | |
| 86539 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 86540 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| 86541 | }; |
| 86542 | int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); |
| 86543 | sqlite3VdbeChangeP1(v, addr, iDb); |
| 86544 | sqlite3VdbeChangeP1(v, addr+1, atoi(zRight)); |
| 86545 | sqlite3VdbeChangeP1(v, addr+2, iDb); |
| 86546 | sqlite3VdbeChangeP2(v, addr+2, iCookie); |
| 86547 | }else{ |
| 86548 | /* Read the specified cookie value */ |
| 86549 | static const VdbeOpList readCookie[] = { |
| @@ -86600,12 +86685,11 @@ | |
| 86600 | ** after accumulating N frames in the log. Or query for the current value |
| 86601 | ** of N. |
| 86602 | */ |
| 86603 | if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){ |
| 86604 | if( zRight ){ |
| 86605 | int nAuto = atoi(zRight); |
| 86606 | sqlite3_wal_autocheckpoint(db, nAuto); |
| 86607 | } |
| 86608 | returnSingleInt(pParse, "wal_autocheckpoint", |
| 86609 | db->xWalCallback==sqlite3WalDefaultHook ? |
| 86610 | SQLITE_PTR_TO_INT(db->pWalArg) : 0); |
| 86611 | }else |
| @@ -86691,11 +86775,12 @@ | |
| 86691 | ** setting changed. |
| 86692 | */ |
| 86693 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 86694 | if( db->autoCommit ){ |
| 86695 | sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, |
| 86696 | (db->flags&SQLITE_FullFSync)!=0); |
| 86697 | } |
| 86698 | #endif |
| 86699 | pragma_out: |
| 86700 | sqlite3DbFree(db, zLeft); |
| 86701 | sqlite3DbFree(db, zRight); |
| @@ -86783,11 +86868,11 @@ | |
| 86783 | sqlite3_stmt *pStmt; |
| 86784 | TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ |
| 86785 | |
| 86786 | assert( db->init.busy ); |
| 86787 | db->init.iDb = iDb; |
| 86788 | db->init.newTnum = atoi(argv[1]); |
| 86789 | db->init.orphanTrigger = 0; |
| 86790 | TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); |
| 86791 | rc = db->errCode; |
| 86792 | assert( (rc&0xFF)==(rcp&0xFF) ); |
| 86793 | db->init.iDb = 0; |
| @@ -99731,11 +99816,11 @@ | |
| 99731 | ** loop below generates code for a single nested loop of the VM |
| 99732 | ** program. |
| 99733 | */ |
| 99734 | notReady = ~(Bitmask)0; |
| 99735 | for(i=0; i<nTabList; i++){ |
| 99736 | WhereLevel *pLevel = &pWInfo->a[i]; |
| 99737 | explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags); |
| 99738 | notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady); |
| 99739 | pWInfo->iContinue = pLevel->addrCont; |
| 99740 | } |
| 99741 | |
| @@ -106890,11 +106975,14 @@ | |
| 106890 | sqlite3BtreeEnter(pBtree); |
| 106891 | pPager = sqlite3BtreePager(pBtree); |
| 106892 | assert( pPager!=0 ); |
| 106893 | fd = sqlite3PagerFile(pPager); |
| 106894 | assert( fd!=0 ); |
| 106895 | if( fd->pMethods ){ |
| 106896 | rc = sqlite3OsFileControl(fd, op, pArg); |
| 106897 | } |
| 106898 | sqlite3BtreeLeave(pBtree); |
| 106899 | } |
| 106900 | } |
| @@ -108194,19 +108282,23 @@ | |
| 108194 | i16 eSearch; /* Search strategy (see below) */ |
| 108195 | u8 isEof; /* True if at End Of Results */ |
| 108196 | u8 isRequireSeek; /* True if must seek pStmt to %_content row */ |
| 108197 | sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ |
| 108198 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 108199 | Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ |
| 108200 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 108201 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 108202 | char *aDoclist; /* List of docids for full-text queries */ |
| 108203 | int nDoclist; /* Size of buffer at aDoclist */ |
| 108204 | int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ |
| 108205 | u32 *aMatchinfo; /* Information about most recent match */ |
| 108206 | int eEvalmode; /* An FTS3_EVAL_XX constant */ |
| 108207 | int nRowAvg; /* Average size of database rows, in pages */ |
| 108208 | }; |
| 108209 | |
| 108210 | #define FTS3_EVAL_FILTER 0 |
| 108211 | #define FTS3_EVAL_NEXT 1 |
| 108212 | #define FTS3_EVAL_MATCHINFO 2 |
| @@ -108309,25 +108401,26 @@ | |
| 108309 | /* fts3_write.c */ |
| 108310 | SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); |
| 108311 | SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *); |
| 108312 | SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *); |
| 108313 | SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *); |
| 108314 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64, |
| 108315 | sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); |
| 108316 | SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**); |
| 108317 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *); |
| 108318 | SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate( |
| 108319 | Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, |
| 108320 | int (*)(Fts3Table *, void *, char *, int, char *, int), void * |
| 108321 | ); |
| 108322 | SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(Fts3Cursor *, Fts3SegReader *, int *); |
| 108323 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
| 108324 | SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*); |
| 108325 | SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*); |
| 108326 | SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); |
| 108327 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*); |
| 108328 | |
| 108329 | SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *); |
| 108330 | SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int); |
| 108331 | SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *); |
| 108332 | SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *); |
| 108333 | SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *, int *); |
| @@ -108371,11 +108464,11 @@ | |
| 108371 | /* fts3_snippet.c */ |
| 108372 | SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); |
| 108373 | SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, |
| 108374 | const char *, const char *, int, int |
| 108375 | ); |
| 108376 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *); |
| 108377 | |
| 108378 | /* fts3_expr.c */ |
| 108379 | SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, |
| 108380 | char **, int, int, const char *, int, Fts3Expr ** |
| 108381 | ); |
| @@ -108684,46 +108777,10 @@ | |
| 108684 | ); |
| 108685 | } |
| 108686 | return rc; |
| 108687 | } |
| 108688 | |
| 108689 | /* |
| 108690 | ** An sqlite3_exec() callback for fts3TableExists. |
| 108691 | */ |
| 108692 | static int fts3TableExistsCallback(void *pArg, int n, char **pp1, char **pp2){ |
| 108693 | UNUSED_PARAMETER(n); |
| 108694 | UNUSED_PARAMETER(pp1); |
| 108695 | UNUSED_PARAMETER(pp2); |
| 108696 | *(int*)pArg = 1; |
| 108697 | return 1; |
| 108698 | } |
| 108699 | |
| 108700 | /* |
| 108701 | ** Determine if a table currently exists in the database. |
| 108702 | */ |
| 108703 | static void fts3TableExists( |
| 108704 | int *pRc, /* Success code */ |
| 108705 | sqlite3 *db, /* The database connection to test */ |
| 108706 | const char *zDb, /* ATTACHed database within the connection */ |
| 108707 | const char *zName, /* Name of the FTS3 table */ |
| 108708 | const char *zSuffix, /* Shadow table extension */ |
| 108709 | u8 *pResult /* Write results here */ |
| 108710 | ){ |
| 108711 | int rc = SQLITE_OK; |
| 108712 | int res = 0; |
| 108713 | char *zSql; |
| 108714 | if( *pRc ) return; |
| 108715 | zSql = sqlite3_mprintf( |
| 108716 | "SELECT 1 FROM %Q.sqlite_master WHERE name='%q%s'", |
| 108717 | zDb, zName, zSuffix |
| 108718 | ); |
| 108719 | rc = sqlite3_exec(db, zSql, fts3TableExistsCallback, &res, 0); |
| 108720 | sqlite3_free(zSql); |
| 108721 | *pResult = (u8)(res & 0xff); |
| 108722 | if( rc!=SQLITE_ABORT ) *pRc = rc; |
| 108723 | } |
| 108724 | |
| 108725 | /* |
| 108726 | ** Store the current database page-size in bytes in p->nPgsz. |
| 108727 | ** |
| 108728 | ** If *pRc is non-zero when this function is called, it is a no-op. |
| 108729 | ** Otherwise, if an error occurs, an SQLite error code is stored in *pRc |
| @@ -109137,11 +109194,10 @@ | |
| 109137 | ** a prefix. |
| 109138 | ** |
| 109139 | ** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK. |
| 109140 | */ |
| 109141 | static int fts3ScanInteriorNode( |
| 109142 | Fts3Table *p, /* Virtual table handle */ |
| 109143 | const char *zTerm, /* Term to select leaves for */ |
| 109144 | int nTerm, /* Size of term zTerm in bytes */ |
| 109145 | const char *zNode, /* Buffer containing segment interior node */ |
| 109146 | int nNode, /* Size of buffer at zNode */ |
| 109147 | sqlite3_int64 *piFirst, /* OUT: Selected child node */ |
| @@ -109272,11 +109328,11 @@ | |
| 109272 | int iHeight; /* Height of this node in tree */ |
| 109273 | |
| 109274 | assert( piLeaf || piLeaf2 ); |
| 109275 | |
| 109276 | sqlite3Fts3GetVarint32(zNode, &iHeight); |
| 109277 | rc = fts3ScanInteriorNode(p, zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); |
| 109278 | assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); |
| 109279 | |
| 109280 | if( rc==SQLITE_OK && iHeight>1 ){ |
| 109281 | char *zBlob = 0; /* Blob read from %_segments table */ |
| 109282 | int nBlob; /* Size of zBlob in bytes */ |
| @@ -110071,11 +110127,11 @@ | |
| 110071 | */ |
| 110072 | static void fts3SegReaderArrayFree(Fts3SegReaderArray *pArray){ |
| 110073 | if( pArray ){ |
| 110074 | int i; |
| 110075 | for(i=0; i<pArray->nSegment; i++){ |
| 110076 | sqlite3Fts3SegReaderFree(0, pArray->apSegment[i]); |
| 110077 | } |
| 110078 | sqlite3_free(pArray); |
| 110079 | } |
| 110080 | } |
| 110081 | |
| @@ -110089,11 +110145,11 @@ | |
| 110089 | int nNew = (pArray ? pArray->nAlloc+16 : 16); |
| 110090 | pArray = (Fts3SegReaderArray *)sqlite3_realloc(pArray, |
| 110091 | sizeof(Fts3SegReaderArray) + (nNew-1) * sizeof(Fts3SegReader*) |
| 110092 | ); |
| 110093 | if( !pArray ){ |
| 110094 | sqlite3Fts3SegReaderFree(0, pNew); |
| 110095 | return SQLITE_NOMEM; |
| 110096 | } |
| 110097 | if( nNew==16 ){ |
| 110098 | pArray->nSegment = 0; |
| 110099 | pArray->nCost = 0; |
| @@ -110142,18 +110198,18 @@ | |
| 110142 | if( sqlite3_column_int64(pStmt, 1)==0 ){ |
| 110143 | /* The entire segment is stored on the root node (which must be a |
| 110144 | ** leaf). Do not bother inspecting any data in this case, just |
| 110145 | ** create a Fts3SegReader to scan the single leaf. |
| 110146 | */ |
| 110147 | rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew); |
| 110148 | }else{ |
| 110149 | sqlite3_int64 i1; /* First leaf that may contain zTerm */ |
| 110150 | sqlite3_int64 i2; /* Final leaf that may contain zTerm */ |
| 110151 | rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1, (isPrefix?&i2:0)); |
| 110152 | if( isPrefix==0 ) i2 = i1; |
| 110153 | if( rc==SQLITE_OK ){ |
| 110154 | rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew); |
| 110155 | } |
| 110156 | } |
| 110157 | assert( (pNew==0)==(rc!=SQLITE_OK) ); |
| 110158 | |
| 110159 | /* If a new Fts3SegReader was allocated, add it to the array. */ |
| @@ -110369,13 +110425,13 @@ | |
| 110369 | } |
| 110370 | } |
| 110371 | |
| 110372 | for(ii=0; ii<pPhrase->nToken; ii++){ |
| 110373 | Fts3PhraseToken *pTok; /* Token to find doclist for */ |
| 110374 | int iTok; /* The token being queried this iteration */ |
| 110375 | char *pList; /* Pointer to token doclist */ |
| 110376 | int nList; /* Size of buffer at pList */ |
| 110377 | |
| 110378 | /* Select a token to process. If this is an xFilter() call, then tokens |
| 110379 | ** are processed in order from least to most costly. Otherwise, tokens |
| 110380 | ** are processed in the order in which they occur in the phrase. |
| 110381 | */ |
| @@ -110413,12 +110469,13 @@ | |
| 110413 | } |
| 110414 | |
| 110415 | if( pCsr->eEvalmode==FTS3_EVAL_NEXT && pTok->pDeferred ){ |
| 110416 | rc = fts3DeferredTermSelect(pTok->pDeferred, isTermPos, &nList, &pList); |
| 110417 | }else{ |
| 110418 | assert( pTok->pArray ); |
| 110419 | rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList); |
| 110420 | pTok->bFulltext = 1; |
| 110421 | } |
| 110422 | assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pArray==0 ); |
| 110423 | if( rc!=SQLITE_OK ) break; |
| 110424 | |
| @@ -110635,18 +110692,21 @@ | |
| 110635 | /* |
| 110636 | ** Return the sum of the costs of all tokens in the expression pExpr. This |
| 110637 | ** function must be called after Fts3SegReaderArrays have been allocated |
| 110638 | ** for all tokens using fts3ExprAllocateSegReaders(). |
| 110639 | */ |
| 110640 | int fts3ExprCost(Fts3Expr *pExpr){ |
| 110641 | int nCost; /* Return value */ |
| 110642 | if( pExpr->eType==FTSQUERY_PHRASE ){ |
| 110643 | Fts3Phrase *pPhrase = pExpr->pPhrase; |
| 110644 | int ii; |
| 110645 | nCost = 0; |
| 110646 | for(ii=0; ii<pPhrase->nToken; ii++){ |
| 110647 | nCost += pPhrase->aToken[ii].pArray->nCost; |
| 110648 | } |
| 110649 | }else{ |
| 110650 | nCost = fts3ExprCost(pExpr->pLeft) + fts3ExprCost(pExpr->pRight); |
| 110651 | } |
| 110652 | return nCost; |
| @@ -110670,11 +110730,11 @@ | |
| 110670 | if( pExpr->eType==FTSQUERY_AND ){ |
| 110671 | fts3ExprAssignCosts(pExpr->pLeft, ppExprCost); |
| 110672 | fts3ExprAssignCosts(pExpr->pRight, ppExprCost); |
| 110673 | }else{ |
| 110674 | (*ppExprCost)->pExpr = pExpr; |
| 110675 | (*ppExprCost)->nCost = fts3ExprCost(pExpr);; |
| 110676 | (*ppExprCost)++; |
| 110677 | } |
| 110678 | } |
| 110679 | |
| 110680 | /* |
| @@ -111388,13 +111448,17 @@ | |
| 111388 | sqlite3_context *pContext, /* SQLite function call context */ |
| 111389 | int nVal, /* Size of argument array */ |
| 111390 | sqlite3_value **apVal /* Array of arguments */ |
| 111391 | ){ |
| 111392 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 111393 | assert( nVal==1 ); |
| 111394 | if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){ |
| 111395 | sqlite3Fts3Matchinfo(pContext, pCsr); |
| 111396 | } |
| 111397 | } |
| 111398 | |
| 111399 | /* |
| 111400 | ** This routine implements the xFindFunction method for the FTS3 |
| @@ -111579,10 +111643,11 @@ | |
| 111579 | if( SQLITE_OK==rc |
| 111580 | && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) |
| 111581 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) |
| 111582 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) |
| 111583 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1)) |
| 111584 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) |
| 111585 | ){ |
| 111586 | rc = sqlite3_create_module_v2( |
| 111587 | db, "fts3", &fts3Module, (void *)pHash, hashDestroy |
| 111588 | ); |
| @@ -112020,11 +112085,10 @@ | |
| 112020 | |
| 112021 | /* Check for an open bracket. */ |
| 112022 | if( sqlite3_fts3_enable_parentheses ){ |
| 112023 | if( *zInput=='(' ){ |
| 112024 | int nConsumed; |
| 112025 | int rc; |
| 112026 | pParse->nNest++; |
| 112027 | rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed); |
| 112028 | if( rc==SQLITE_OK && !*ppExpr ){ |
| 112029 | rc = SQLITE_DONE; |
| 112030 | } |
| @@ -113267,11 +113331,11 @@ | |
| 113267 | */ |
| 113268 | static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ |
| 113269 | int i, j; |
| 113270 | char zReverse[28]; |
| 113271 | char *z, *z2; |
| 113272 | if( nIn<3 || nIn>=sizeof(zReverse)-7 ){ |
| 113273 | /* The word is too big or too small for the porter stemmer. |
| 113274 | ** Fallback to the copy stemmer */ |
| 113275 | copy_stemmer(zIn, nIn, zOut, pnOut); |
| 113276 | return; |
| 113277 | } |
| @@ -114032,19 +114096,27 @@ | |
| 114032 | if( !zTest || !zTest2 ){ |
| 114033 | rc = SQLITE_NOMEM; |
| 114034 | } |
| 114035 | #endif |
| 114036 | |
| 114037 | if( SQLITE_OK!=rc |
| 114038 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0)) |
| 114039 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0)) |
| 114040 | #ifdef SQLITE_TEST |
| 114041 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0)) |
| 114042 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0)) |
| 114043 | || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0)) |
| 114044 | #endif |
| 114045 | ); |
| 114046 | |
| 114047 | #ifdef SQLITE_TEST |
| 114048 | sqlite3_free(zTest); |
| 114049 | sqlite3_free(zTest2); |
| 114050 | #endif |
| @@ -114565,10 +114637,55 @@ | |
| 114565 | } |
| 114566 | } |
| 114567 | *pp = pStmt; |
| 114568 | return rc; |
| 114569 | } |
| 114570 | |
| 114571 | /* |
| 114572 | ** Similar to fts3SqlStmt(). Except, after binding the parameters in |
| 114573 | ** array apVal[] to the SQL statement identified by eStmt, the statement |
| 114574 | ** is executed. |
| @@ -115382,11 +115499,11 @@ | |
| 115382 | |
| 115383 | /* |
| 115384 | ** Free all allocations associated with the iterator passed as the |
| 115385 | ** second argument. |
| 115386 | */ |
| 115387 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *p, Fts3SegReader *pReader){ |
| 115388 | if( pReader && !fts3SegReaderIsPending(pReader) ){ |
| 115389 | sqlite3_free(pReader->zTerm); |
| 115390 | if( !fts3SegReaderIsRootOnly(pReader) ){ |
| 115391 | sqlite3_free(pReader->aNode); |
| 115392 | } |
| @@ -115396,11 +115513,10 @@ | |
| 115396 | |
| 115397 | /* |
| 115398 | ** Allocate a new SegReader object. |
| 115399 | */ |
| 115400 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( |
| 115401 | Fts3Table *p, /* Virtual table handle */ |
| 115402 | int iAge, /* Segment "age". */ |
| 115403 | sqlite3_int64 iStartLeaf, /* First leaf to traverse */ |
| 115404 | sqlite3_int64 iEndLeaf, /* Final leaf to traverse */ |
| 115405 | sqlite3_int64 iEndBlock, /* Final block of segment */ |
| 115406 | const char *zRoot, /* Buffer containing root node */ |
| @@ -115437,11 +115553,11 @@ | |
| 115437 | } |
| 115438 | |
| 115439 | if( rc==SQLITE_OK ){ |
| 115440 | *ppReader = pReader; |
| 115441 | }else{ |
| 115442 | sqlite3Fts3SegReaderFree(p, pReader); |
| 115443 | } |
| 115444 | return rc; |
| 115445 | } |
| 115446 | |
| 115447 | /* |
| @@ -115560,16 +115676,15 @@ | |
| 115560 | ** If successful, the Fts3SegReader is left pointing to the first term |
| 115561 | ** in the segment and SQLITE_OK is returned. Otherwise, an SQLite error |
| 115562 | ** code is returned. |
| 115563 | */ |
| 115564 | static int fts3SegReaderNew( |
| 115565 | Fts3Table *p, /* Virtual table handle */ |
| 115566 | sqlite3_stmt *pStmt, /* See above */ |
| 115567 | int iAge, /* Segment "age". */ |
| 115568 | Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */ |
| 115569 | ){ |
| 115570 | return sqlite3Fts3SegReaderNew(p, iAge, |
| 115571 | sqlite3_column_int64(pStmt, 1), |
| 115572 | sqlite3_column_int64(pStmt, 2), |
| 115573 | sqlite3_column_int64(pStmt, 3), |
| 115574 | sqlite3_column_blob(pStmt, 4), |
| 115575 | sqlite3_column_bytes(pStmt, 4), |
| @@ -116596,11 +116711,11 @@ | |
| 116596 | assert( SQL_SELECT_LEVEL+1==SQL_SELECT_ALL_LEVEL); |
| 116597 | rc = fts3SqlStmt(p, SQL_SELECT_LEVEL+(iLevel<0), &pStmt, 0); |
| 116598 | if( rc!=SQLITE_OK ) goto finished; |
| 116599 | sqlite3_bind_int(pStmt, 1, iLevel); |
| 116600 | for(i=0; SQLITE_ROW==(sqlite3_step(pStmt)); i++){ |
| 116601 | rc = fts3SegReaderNew(p, pStmt, i, &apSegment[i]); |
| 116602 | if( rc!=SQLITE_OK ){ |
| 116603 | goto finished; |
| 116604 | } |
| 116605 | } |
| 116606 | rc = sqlite3_reset(pStmt); |
| @@ -116626,15 +116741,15 @@ | |
| 116626 | |
| 116627 | finished: |
| 116628 | fts3SegWriterFree(pWriter); |
| 116629 | if( apSegment ){ |
| 116630 | for(i=0; i<nSegment; i++){ |
| 116631 | sqlite3Fts3SegReaderFree(p, apSegment[i]); |
| 116632 | } |
| 116633 | sqlite3_free(apSegment); |
| 116634 | } |
| 116635 | sqlite3Fts3SegReaderFree(p, pPending); |
| 116636 | sqlite3_reset(pStmt); |
| 116637 | return rc; |
| 116638 | } |
| 116639 | |
| 116640 | |
| @@ -116683,11 +116798,11 @@ | |
| 116683 | */ |
| 116684 | if( rc==SQLITE_OK ){ |
| 116685 | rc = fts3SegWriterFlush(p, pWriter, 0, idx); |
| 116686 | } |
| 116687 | fts3SegWriterFree(pWriter); |
| 116688 | sqlite3Fts3SegReaderFree(p, pReader); |
| 116689 | |
| 116690 | if( rc==SQLITE_OK ){ |
| 116691 | sqlite3Fts3PendingTermsClear(p); |
| 116692 | } |
| 116693 | return rc; |
| @@ -116726,79 +116841,10 @@ | |
| 116726 | assert(j<=nBuf); |
| 116727 | a[i] = (u32)(x & 0xffffffff); |
| 116728 | } |
| 116729 | } |
| 116730 | |
| 116731 | /* |
| 116732 | ** Fill in the document size auxiliary information for the matchinfo |
| 116733 | ** structure. The auxiliary information is: |
| 116734 | ** |
| 116735 | ** N Total number of documents in the full-text index |
| 116736 | ** a0 Average length of column 0 over the whole index |
| 116737 | ** n0 Length of column 0 on the matching row |
| 116738 | ** ... |
| 116739 | ** aM Average length of column M over the whole index |
| 116740 | ** nM Length of column M on the matching row |
| 116741 | ** |
| 116742 | ** The fts3MatchinfoDocsizeLocal() routine fills in the nX values. |
| 116743 | ** The fts3MatchinfoDocsizeGlobal() routine fills in N and the aX values. |
| 116744 | */ |
| 116745 | SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor *pCur, u32 *a){ |
| 116746 | const char *pBlob; /* The BLOB holding %_docsize info */ |
| 116747 | int nBlob; /* Size of the BLOB */ |
| 116748 | sqlite3_stmt *pStmt; /* Statement for reading and writing */ |
| 116749 | int i, j; /* Loop counters */ |
| 116750 | sqlite3_int64 x; /* Varint value */ |
| 116751 | int rc; /* Result code from subfunctions */ |
| 116752 | Fts3Table *p; /* The FTS table */ |
| 116753 | |
| 116754 | p = (Fts3Table*)pCur->base.pVtab; |
| 116755 | rc = fts3SqlStmt(p, SQL_SELECT_DOCSIZE, &pStmt, 0); |
| 116756 | if( rc ){ |
| 116757 | return rc; |
| 116758 | } |
| 116759 | sqlite3_bind_int64(pStmt, 1, pCur->iPrevId); |
| 116760 | if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 116761 | nBlob = sqlite3_column_bytes(pStmt, 0); |
| 116762 | pBlob = (const char*)sqlite3_column_blob(pStmt, 0); |
| 116763 | for(i=j=0; i<p->nColumn && j<nBlob; i++){ |
| 116764 | j = sqlite3Fts3GetVarint(&pBlob[j], &x); |
| 116765 | a[2+i*2] = (u32)(x & 0xffffffff); |
| 116766 | } |
| 116767 | } |
| 116768 | sqlite3_reset(pStmt); |
| 116769 | return SQLITE_OK; |
| 116770 | } |
| 116771 | SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor *pCur, u32 *a){ |
| 116772 | const char *pBlob; /* The BLOB holding %_stat info */ |
| 116773 | int nBlob; /* Size of the BLOB */ |
| 116774 | sqlite3_stmt *pStmt; /* Statement for reading and writing */ |
| 116775 | int i, j; /* Loop counters */ |
| 116776 | sqlite3_int64 x; /* Varint value */ |
| 116777 | int nDoc; /* Number of documents */ |
| 116778 | int rc; /* Result code from subfunctions */ |
| 116779 | Fts3Table *p; /* The FTS table */ |
| 116780 | |
| 116781 | p = (Fts3Table*)pCur->base.pVtab; |
| 116782 | rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0); |
| 116783 | if( rc ){ |
| 116784 | return rc; |
| 116785 | } |
| 116786 | if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 116787 | nBlob = sqlite3_column_bytes(pStmt, 0); |
| 116788 | pBlob = (const char*)sqlite3_column_blob(pStmt, 0); |
| 116789 | j = sqlite3Fts3GetVarint(pBlob, &x); |
| 116790 | a[0] = nDoc = (u32)(x & 0xffffffff); |
| 116791 | for(i=0; i<p->nColumn && j<nBlob; i++){ |
| 116792 | j = sqlite3Fts3GetVarint(&pBlob[j], &x); |
| 116793 | a[1+i*2] = ((u32)(x & 0xffffffff) + nDoc/2)/nDoc; |
| 116794 | } |
| 116795 | } |
| 116796 | sqlite3_reset(pStmt); |
| 116797 | return SQLITE_OK; |
| 116798 | } |
| 116799 | |
| 116800 | /* |
| 116801 | ** Insert the sizes (in tokens) for each column of the document |
| 116802 | ** with docid equal to p->iPrevDocid. The sizes are encoded as |
| 116803 | ** a blob of varints. |
| 116804 | */ |
| @@ -117217,10 +117263,26 @@ | |
| 117217 | */ |
| 117218 | |
| 117219 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 117220 | |
| 117221 | |
| 117222 | |
| 117223 | /* |
| 117224 | ** Used as an fts3ExprIterate() context when loading phrase doclists to |
| 117225 | ** Fts3Expr.aDoclist[]/nDoclist. |
| 117226 | */ |
| @@ -117270,10 +117332,12 @@ | |
| 117270 | */ |
| 117271 | typedef struct MatchInfo MatchInfo; |
| 117272 | struct MatchInfo { |
| 117273 | Fts3Cursor *pCursor; /* FTS3 Cursor */ |
| 117274 | int nCol; /* Number of columns in table */ |
| 117275 | u32 *aMatchinfo; /* Pre-allocated buffer */ |
| 117276 | }; |
| 117277 | |
| 117278 | |
| 117279 | |
| @@ -117470,10 +117534,22 @@ | |
| 117470 | } |
| 117471 | if( pnPhrase ) *pnPhrase = sCtx.nPhrase; |
| 117472 | if( pnToken ) *pnToken = sCtx.nToken; |
| 117473 | return rc; |
| 117474 | } |
| 117475 | |
| 117476 | /* |
| 117477 | ** Advance the position list iterator specified by the first two |
| 117478 | ** arguments so that it points to the first element with a value greater |
| 117479 | ** than or equal to parameter iNext. |
| @@ -117983,24 +118059,46 @@ | |
| 117983 | *pp = pCsr; |
| 117984 | } |
| 117985 | |
| 117986 | /* |
| 117987 | ** fts3ExprIterate() callback used to collect the "global" matchinfo stats |
| 117988 | ** for a single query. The "global" stats are those elements of the matchinfo |
| 117989 | ** array that are constant for all rows returned by the current query. |
| 117990 | */ |
| 117991 | static int fts3ExprGlobalMatchinfoCb( |
| 117992 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 117993 | int iPhrase, /* Phrase number (numbered from zero) */ |
| 117994 | void *pCtx /* Pointer to MatchInfo structure */ |
| 117995 | ){ |
| 117996 | MatchInfo *p = (MatchInfo *)pCtx; |
| 117997 | Fts3Cursor *pCsr = p->pCursor; |
| 117998 | char *pIter; |
| 117999 | char *pEnd; |
| 118000 | char *pFree = 0; |
| 118001 | const int iStart = 2 + (iPhrase * p->nCol * 3) + 1; |
| 118002 | |
| 118003 | assert( pExpr->isLoaded ); |
| 118004 | assert( pExpr->eType==FTSQUERY_PHRASE ); |
| 118005 | |
| 118006 | if( pCsr->pDeferred ){ |
| @@ -118014,14 +118112,14 @@ | |
| 118014 | int rc = sqlite3Fts3ExprLoadFtDoclist(pCsr, pExpr, &pFree, &nFree); |
| 118015 | if( rc!=SQLITE_OK ) return rc; |
| 118016 | pIter = pFree; |
| 118017 | pEnd = &pFree[nFree]; |
| 118018 | }else{ |
| 118019 | int nDoc = p->aMatchinfo[2 + 3*p->nCol*p->aMatchinfo[0]]; |
| 118020 | for(ii=0; ii<p->nCol; ii++){ |
| 118021 | p->aMatchinfo[iStart + ii*3] = nDoc; |
| 118022 | p->aMatchinfo[iStart + ii*3 + 1] = nDoc; |
| 118023 | } |
| 118024 | return SQLITE_OK; |
| 118025 | } |
| 118026 | }else{ |
| 118027 | pIter = pExpr->aDoclist; |
| @@ -118029,32 +118127,32 @@ | |
| 118029 | } |
| 118030 | |
| 118031 | /* Fill in the global hit count matrix row for this phrase. */ |
| 118032 | while( pIter<pEnd ){ |
| 118033 | while( *pIter++ & 0x80 ); /* Skip past docid. */ |
| 118034 | fts3LoadColumnlistCounts(&pIter, &p->aMatchinfo[iStart], 1); |
| 118035 | } |
| 118036 | |
| 118037 | sqlite3_free(pFree); |
| 118038 | return SQLITE_OK; |
| 118039 | } |
| 118040 | |
| 118041 | /* |
| 118042 | ** fts3ExprIterate() callback used to collect the "local" matchinfo stats |
| 118043 | ** for a single query. The "local" stats are those elements of the matchinfo |
| 118044 | ** array that are different for each row returned by the query. |
| 118045 | */ |
| 118046 | static int fts3ExprLocalMatchinfoCb( |
| 118047 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 118048 | int iPhrase, /* Phrase number */ |
| 118049 | void *pCtx /* Pointer to MatchInfo structure */ |
| 118050 | ){ |
| 118051 | MatchInfo *p = (MatchInfo *)pCtx; |
| 118052 | |
| 118053 | if( pExpr->aDoclist ){ |
| 118054 | char *pCsr; |
| 118055 | int iStart = 2 + (iPhrase * p->nCol * 3); |
| 118056 | int i; |
| 118057 | |
| 118058 | for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0; |
| 118059 | |
| 118060 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1); |
| @@ -118063,71 +118161,404 @@ | |
| 118063 | } |
| 118064 | } |
| 118065 | |
| 118066 | return SQLITE_OK; |
| 118067 | } |
| 118068 | |
| 118069 | /* |
| 118070 | ** Populate pCsr->aMatchinfo[] with data for the current row. The |
| 118071 | ** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). |
| 118072 | */ |
| 118073 | static int fts3GetMatchinfo(Fts3Cursor *pCsr){ |
| 118074 | MatchInfo sInfo; |
| 118075 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 118076 | int rc = SQLITE_OK; |
| 118077 | |
| 118078 | sInfo.pCursor = pCsr; |
| 118079 | sInfo.nCol = pTab->nColumn; |
| 118080 | |
| 118081 | if( pCsr->aMatchinfo==0 ){ |
| 118082 | /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the |
| 118083 | ** matchinfo function has been called for this query. In this case |
| 118084 | ** allocate the array used to accumulate the matchinfo data and |
| 118085 | ** initialize those elements that are constant for every row. |
| 118086 | */ |
| 118087 | int nPhrase; /* Number of phrases */ |
| 118088 | int nMatchinfo; /* Number of u32 elements in match-info */ |
| 118089 | |
| 118090 | /* Load doclists for each phrase in the query. */ |
| 118091 | rc = fts3ExprLoadDoclists(pCsr, &nPhrase, 0); |
| 118092 | if( rc!=SQLITE_OK ){ |
| 118093 | return rc; |
| 118094 | } |
| 118095 | nMatchinfo = 2 + 3*sInfo.nCol*nPhrase; |
| 118096 | if( pTab->bHasDocsize ){ |
| 118097 | nMatchinfo += 1 + 2*pTab->nColumn; |
| 118098 | } |
| 118099 | |
| 118100 | sInfo.aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo); |
| 118101 | if( !sInfo.aMatchinfo ){ |
| 118102 | return SQLITE_NOMEM; |
| 118103 | } |
| 118104 | memset(sInfo.aMatchinfo, 0, sizeof(u32)*nMatchinfo); |
| 118105 | |
| 118106 | /* First element of match-info is the number of phrases in the query */ |
| 118107 | sInfo.aMatchinfo[0] = nPhrase; |
| 118108 | sInfo.aMatchinfo[1] = sInfo.nCol; |
| 118109 | if( pTab->bHasDocsize ){ |
| 118110 | int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; |
| 118111 | rc = sqlite3Fts3MatchinfoDocsizeGlobal(pCsr, &sInfo.aMatchinfo[ofst]); |
| 118112 | } |
| 118113 | (void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo); |
| 118114 | pCsr->aMatchinfo = sInfo.aMatchinfo; |
| 118115 | pCsr->isMatchinfoNeeded = 1; |
| 118116 | } |
| 118117 | |
| 118118 | sInfo.aMatchinfo = pCsr->aMatchinfo; |
| 118119 | if( rc==SQLITE_OK && pCsr->isMatchinfoNeeded ){ |
| 118120 | (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void*)&sInfo); |
| 118121 | if( pTab->bHasDocsize ){ |
| 118122 | int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; |
| 118123 | rc = sqlite3Fts3MatchinfoDocsizeLocal(pCsr, &sInfo.aMatchinfo[ofst]); |
| 118124 | } |
| 118125 | pCsr->isMatchinfoNeeded = 0; |
| 118126 | } |
| 118127 | |
| 118128 | return SQLITE_OK; |
| 118129 | } |
| 118130 | |
| 118131 | /* |
| 118132 | ** Implementation of snippet() function. |
| 118133 | */ |
| @@ -118184,11 +118615,11 @@ | |
| 118184 | /* Loop through all columns of the table being considered for snippets. |
| 118185 | ** If the iCol argument to this function was negative, this means all |
| 118186 | ** columns of the FTS3 table. Otherwise, only column iCol is considered. |
| 118187 | */ |
| 118188 | for(iRead=0; iRead<pTab->nColumn; iRead++){ |
| 118189 | SnippetFragment sF; |
| 118190 | int iS; |
| 118191 | if( iCol>=0 && iRead!=iCol ) continue; |
| 118192 | |
| 118193 | /* Find the best snippet of nFToken tokens in column iRead. */ |
| 118194 | rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS); |
| @@ -118411,26 +118842,47 @@ | |
| 118411 | } |
| 118412 | |
| 118413 | /* |
| 118414 | ** Implementation of matchinfo() function. |
| 118415 | */ |
| 118416 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *pCsr){ |
| 118417 | int rc; |
| 118418 | if( !pCsr->pExpr ){ |
| 118419 | sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); |
| 118420 | return; |
| 118421 | } |
| 118422 | rc = fts3GetMatchinfo(pCsr); |
| 118423 | sqlite3Fts3SegmentsClose((Fts3Table *)pCsr->base.pVtab ); |
| 118424 | if( rc!=SQLITE_OK ){ |
| 118425 | sqlite3_result_error_code(pContext, rc); |
| 118426 | }else{ |
| 118427 | Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab; |
| 118428 | int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*3); |
| 118429 | if( pTab->bHasDocsize ){ |
| 118430 | n += sizeof(u32)*(1 + 2*pTab->nColumn); |
| 118431 | } |
| 118432 | sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); |
| 118433 | } |
| 118434 | } |
| 118435 | |
| 118436 | #endif |
| @@ -118545,10 +118997,16 @@ | |
| 118545 | #include "sqlite3rtree.h" |
| 118546 | typedef sqlite3_int64 i64; |
| 118547 | typedef unsigned char u8; |
| 118548 | typedef unsigned int u32; |
| 118549 | #endif |
| 118550 | |
| 118551 | typedef struct Rtree Rtree; |
| 118552 | typedef struct RtreeCursor RtreeCursor; |
| 118553 | typedef struct RtreeNode RtreeNode; |
| 118554 | typedef struct RtreeCell RtreeCell; |
| @@ -119627,11 +120085,11 @@ | |
| 119627 | /* Check that value is actually a blob. */ |
| 119628 | if( !sqlite3_value_type(pValue)==SQLITE_BLOB ) return SQLITE_ERROR; |
| 119629 | |
| 119630 | /* Check that the blob is roughly the right size. */ |
| 119631 | nBlob = sqlite3_value_bytes(pValue); |
| 119632 | if( nBlob<sizeof(RtreeMatchArg) |
| 119633 | || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0 |
| 119634 | ){ |
| 119635 | return SQLITE_ERROR; |
| 119636 | } |
| 119637 | |
| @@ -119642,11 +120100,11 @@ | |
| 119642 | memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); |
| 119643 | p = (RtreeMatchArg *)&pGeom[1]; |
| 119644 | |
| 119645 | memcpy(p, sqlite3_value_blob(pValue), nBlob); |
| 119646 | if( p->magic!=RTREE_GEOMETRY_MAGIC |
| 119647 | || nBlob!=(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) |
| 119648 | ){ |
| 119649 | sqlite3_free(pGeom); |
| 119650 | return SQLITE_ERROR; |
| 119651 | } |
| 119652 | |
| @@ -119788,10 +120246,11 @@ | |
| 119788 | int ii, cCol; |
| 119789 | |
| 119790 | int iIdx = 0; |
| 119791 | char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; |
| 119792 | memset(zIdxStr, 0, sizeof(zIdxStr)); |
| 119793 | |
| 119794 | assert( pIdxInfo->idxStr==0 ); |
| 119795 | for(ii=0; ii<pIdxInfo->nConstraint; ii++){ |
| 119796 | struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; |
| 119797 | |
| @@ -119961,10 +120420,11 @@ | |
| 119961 | for(ii=0; ii<nCell; ii++){ |
| 119962 | #if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 119963 | if( ii!=iExclude ) |
| 119964 | #else |
| 119965 | assert( iExclude==-1 ); |
| 119966 | #endif |
| 119967 | { |
| 119968 | int jj; |
| 119969 | float o = 1.0; |
| 119970 | for(jj=0; jj<(pRtree->nDim*2); jj+=2){ |
| @@ -121082,20 +121542,10 @@ | |
| 121082 | rc = sqlite3_reset(pRtree->pWriteRowid); |
| 121083 | *piRowid = sqlite3_last_insert_rowid(pRtree->db); |
| 121084 | return rc; |
| 121085 | } |
| 121086 | |
| 121087 | #ifndef NDEBUG |
| 121088 | static int hashIsEmpty(Rtree *pRtree){ |
| 121089 | int ii; |
| 121090 | for(ii=0; ii<HASHSIZE; ii++){ |
| 121091 | assert( !pRtree->aHash[ii] ); |
| 121092 | } |
| 121093 | return 1; |
| 121094 | } |
| 121095 | #endif |
| 121096 | |
| 121097 | /* |
| 121098 | ** The xUpdate method for rtree module virtual tables. |
| 121099 | */ |
| 121100 | static int rtreeUpdate( |
| 121101 | sqlite3_vtab *pVtab, |
| @@ -121557,10 +122007,11 @@ | |
| 121557 | char *zText = 0; |
| 121558 | RtreeNode node; |
| 121559 | Rtree tree; |
| 121560 | int ii; |
| 121561 | |
| 121562 | memset(&node, 0, sizeof(RtreeNode)); |
| 121563 | memset(&tree, 0, sizeof(Rtree)); |
| 121564 | tree.nDim = sqlite3_value_int(apArg[0]); |
| 121565 | tree.nBytesPerCell = 8 + 8 * tree.nDim; |
| 121566 | node.zData = (u8 *)sqlite3_value_blob(apArg[1]); |
| @@ -121590,10 +122041,11 @@ | |
| 121590 | |
| 121591 | sqlite3_result_text(ctx, zText, -1, sqlite3_free); |
| 121592 | } |
| 121593 | |
| 121594 | static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ |
| 121595 | if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB |
| 121596 | || sqlite3_value_bytes(apArg[0])<2 |
| 121597 | ){ |
| 121598 | sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1); |
| 121599 | }else{ |
| @@ -121611,11 +122063,10 @@ | |
| 121611 | const int utf8 = SQLITE_UTF8; |
| 121612 | int rc; |
| 121613 | |
| 121614 | rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); |
| 121615 | if( rc==SQLITE_OK ){ |
| 121616 | int utf8 = SQLITE_UTF8; |
| 121617 | rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); |
| 121618 | } |
| 121619 | if( rc==SQLITE_OK ){ |
| 121620 | void *c = (void *)RTREE_COORD_REAL32; |
| 121621 | rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); |
| 121622 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -650,11 +650,11 @@ | |
| 650 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 651 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 652 | */ |
| 653 | #define SQLITE_VERSION "3.7.4" |
| 654 | #define SQLITE_VERSION_NUMBER 3007004 |
| 655 | #define SQLITE_SOURCE_ID "2010-11-26 16:49:59 c412f61229b6ab1ac90b932afd56f7c5e3ba1cfe" |
| 656 | |
| 657 | /* |
| 658 | ** CAPI3REF: Run-Time Library Version Numbers |
| 659 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 660 | ** |
| @@ -1083,10 +1083,22 @@ | |
| 1083 | ** sync operation only needs to flush data to mass storage. Inode |
| 1084 | ** information need not be flushed. If the lower four bits of the flag |
| 1085 | ** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. |
| 1086 | ** If the lower four bits equal SQLITE_SYNC_FULL, that means |
| 1087 | ** to use Mac OS X style fullsync instead of fsync(). |
| 1088 | ** |
| 1089 | ** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags |
| 1090 | ** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL |
| 1091 | ** settings. The [synchronous pragma] determines when calls to the |
| 1092 | ** xSync VFS method occur and applies uniformly across all platforms. |
| 1093 | ** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how |
| 1094 | ** energetic or rigorous or forceful the sync operations are and |
| 1095 | ** only make a difference on Mac OSX for the default SQLite code. |
| 1096 | ** (Third-party VFS implementations might also make the distinction |
| 1097 | ** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the |
| 1098 | ** operating systems natively supported by SQLite, only Mac OSX |
| 1099 | ** cares about the difference.) |
| 1100 | */ |
| 1101 | #define SQLITE_SYNC_NORMAL 0x00002 |
| 1102 | #define SQLITE_SYNC_FULL 0x00003 |
| 1103 | #define SQLITE_SYNC_DATAONLY 0x00010 |
| 1104 | |
| @@ -1251,10 +1263,12 @@ | |
| 1263 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 1264 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 1265 | #define SQLITE_LAST_ERRNO 4 |
| 1266 | #define SQLITE_FCNTL_SIZE_HINT 5 |
| 1267 | #define SQLITE_FCNTL_CHUNK_SIZE 6 |
| 1268 | #define SQLITE_FCNTL_FILE_POINTER 7 |
| 1269 | |
| 1270 | |
| 1271 | /* |
| 1272 | ** CAPI3REF: Mutex Handle |
| 1273 | ** |
| 1274 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -3178,18 +3192,17 @@ | |
| 3192 | |
| 3193 | /* |
| 3194 | ** CAPI3REF: Determine If An SQL Statement Writes The Database |
| 3195 | ** |
| 3196 | ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if |
| 3197 | ** the [prepared statement] X is [SELECT] statement and false (zero) if |
| 3198 | ** X is an [INSERT], [UPDATE], [DELETE], CREATE, DROP, [ANALYZE], |
| 3199 | ** [ALTER], or [REINDEX] statement. |
| 3200 | ** If X is a NULL pointer or any other kind of statement, including but |
| 3201 | ** not limited to [ATTACH], [DETACH], [COMMIT], [ROLLBACK], [RELEASE], |
| 3202 | ** [SAVEPOINT], [PRAGMA], or [VACUUM] the result of sqlite3_stmt_readonly(X) is |
| 3203 | ** undefined. |
| 3204 | */ |
| 3205 | SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); |
| 3206 | |
| 3207 | /* |
| 3208 | ** CAPI3REF: Dynamically Typed Value Object |
| @@ -5781,19 +5794,25 @@ | |
| 5794 | ** CAPI3REF: Low-Level Control Of Database Files |
| 5795 | ** |
| 5796 | ** ^The [sqlite3_file_control()] interface makes a direct call to the |
| 5797 | ** xFileControl method for the [sqlite3_io_methods] object associated |
| 5798 | ** with a particular database identified by the second argument. ^The |
| 5799 | ** name of the database is "main" for the main database or "temp" for the |
| 5800 | ** TEMP database, or the name that appears after the AS keyword for |
| 5801 | ** databases that are added using the [ATTACH] SQL command. |
| 5802 | ** ^A NULL pointer can be used in place of "main" to refer to the |
| 5803 | ** main database file. |
| 5804 | ** ^The third and fourth parameters to this routine |
| 5805 | ** are passed directly through to the second and third parameters of |
| 5806 | ** the xFileControl method. ^The return value of the xFileControl |
| 5807 | ** method becomes the return value of this routine. |
| 5808 | ** |
| 5809 | ** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes |
| 5810 | ** a pointer to the underlying [sqlite3_file] object to be written into |
| 5811 | ** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER |
| 5812 | ** case is a short-circuit path which does not actually invoke the |
| 5813 | ** underlying sqlite3_io_methods.xFileControl method. |
| 5814 | ** |
| 5815 | ** ^If the second parameter (zDbName) does not match the name of any |
| 5816 | ** open database file, then SQLITE_ERROR is returned. ^This error |
| 5817 | ** code is not remembered and will not be recalled by [sqlite3_errcode()] |
| 5818 | ** or [sqlite3_errmsg()]. The underlying xFileControl method might |
| @@ -7460,11 +7479,11 @@ | |
| 7479 | #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ |
| 7480 | #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ |
| 7481 | |
| 7482 | SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); |
| 7483 | SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); |
| 7484 | SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); |
| 7485 | SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); |
| 7486 | SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); |
| 7487 | SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); |
| 7488 | SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); |
| 7489 | SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); |
| @@ -7944,16 +7963,16 @@ | |
| 7963 | #define OP_VColumn 129 |
| 7964 | #define OP_VNext 131 |
| 7965 | #define OP_VRename 132 |
| 7966 | #define OP_VUpdate 133 |
| 7967 | #define OP_Pagecount 134 |
| 7968 | #define OP_MaxPgcnt 135 |
| 7969 | #define OP_Trace 136 |
| 7970 | #define OP_Noop 137 |
| 7971 | #define OP_Explain 138 |
| 7972 | |
| 7973 | /* The following opcode values are never used */ |
| 7974 | #define OP_NotUsed_139 139 |
| 7975 | #define OP_NotUsed_140 140 |
| 7976 | |
| 7977 | |
| 7978 | /* Properties such as "out2" or "jump" that are specified in |
| @@ -7982,11 +8001,11 @@ | |
| 8001 | /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x02,\ |
| 8002 | /* 96 */ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 8003 | /* 104 */ 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01,\ |
| 8004 | /* 112 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\ |
| 8005 | /* 120 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 8006 | /* 128 */ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x02,\ |
| 8007 | /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\ |
| 8008 | /* 144 */ 0x04, 0x04,} |
| 8009 | |
| 8010 | /************** End of opcodes.h *********************************************/ |
| 8011 | /************** Continuing where we left off in vdbe.h ***********************/ |
| @@ -8167,11 +8186,11 @@ | |
| 8186 | /* Functions used to configure a Pager object. */ |
| 8187 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 8188 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| 8189 | SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); |
| 8190 | SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); |
| 8191 | SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int); |
| 8192 | SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); |
| 8193 | SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); |
| 8194 | SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); |
| 8195 | SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); |
| 8196 | SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); |
| @@ -9032,17 +9051,18 @@ | |
| 9051 | ** accessing read-only databases */ |
| 9052 | #define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */ |
| 9053 | #define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */ |
| 9054 | #define SQLITE_LegacyFileFmt 0x00100000 /* Create new databases in format 1 */ |
| 9055 | #define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */ |
| 9056 | #define SQLITE_CkptFullFSync 0x00400000 /* Use full fsync for checkpoint */ |
| 9057 | #define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */ |
| 9058 | #define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */ |
| 9059 | #define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */ |
| 9060 | #define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */ |
| 9061 | #define SQLITE_AutoIndex 0x08000000 /* Enable automatic indexes */ |
| 9062 | #define SQLITE_PreferBuiltin 0x10000000 /* Preference to built-in funcs */ |
| 9063 | #define SQLITE_LoadExtension 0x20000000 /* Enable load_extension */ |
| 9064 | |
| 9065 | /* |
| 9066 | ** Bits of the sqlite3.flags field that are used by the |
| 9067 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface. |
| 9068 | ** These must be the low-order bits of the flags field. |
| @@ -10957,10 +10977,11 @@ | |
| 10977 | SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); |
| 10978 | SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*); |
| 10979 | SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); |
| 10980 | SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); |
| 10981 | SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); |
| 10982 | SQLITE_PRIVATE int sqlite3Atoi(const char*); |
| 10983 | SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); |
| 10984 | SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); |
| 10985 | SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**); |
| 10986 | |
| 10987 | /* |
| @@ -20458,10 +20479,20 @@ | |
| 20479 | v = -v; |
| 20480 | } |
| 20481 | *pValue = (int)v; |
| 20482 | return 1; |
| 20483 | } |
| 20484 | |
| 20485 | /* |
| 20486 | ** Return a 32-bit integer value extracted from a string. If the |
| 20487 | ** string is not an integer, just return 0. |
| 20488 | */ |
| 20489 | SQLITE_PRIVATE int sqlite3Atoi(const char *z){ |
| 20490 | int x = 0; |
| 20491 | if( z ) sqlite3GetInt32(z, &x); |
| 20492 | return x; |
| 20493 | } |
| 20494 | |
| 20495 | /* |
| 20496 | ** The variable-length integer encoding is as follows: |
| 20497 | ** |
| 20498 | ** KEY: |
| @@ -21388,14 +21419,14 @@ | |
| 21419 | /* 130 */ "Real", |
| 21420 | /* 131 */ "VNext", |
| 21421 | /* 132 */ "VRename", |
| 21422 | /* 133 */ "VUpdate", |
| 21423 | /* 134 */ "Pagecount", |
| 21424 | /* 135 */ "MaxPgcnt", |
| 21425 | /* 136 */ "Trace", |
| 21426 | /* 137 */ "Noop", |
| 21427 | /* 138 */ "Explain", |
| 21428 | /* 139 */ "NotUsed_139", |
| 21429 | /* 140 */ "NotUsed_140", |
| 21430 | /* 141 */ "ToText", |
| 21431 | /* 142 */ "ToBlob", |
| 21432 | /* 143 */ "ToNumeric", |
| @@ -27946,11 +27977,11 @@ | |
| 27977 | static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){ |
| 27978 | static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; |
| 27979 | #if defined(NO_GETTOD) |
| 27980 | time_t t; |
| 27981 | time(&t); |
| 27982 | *piNow = ((sqlite3_int64)t)*1000 + unixEpoch; |
| 27983 | #elif OS_VXWORKS |
| 27984 | struct timespec sNow; |
| 27985 | clock_gettime(CLOCK_REALTIME, &sNow); |
| 27986 | *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000; |
| 27987 | #else |
| @@ -35273,11 +35304,12 @@ | |
| 35304 | u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ |
| 35305 | u8 useJournal; /* Use a rollback journal on this file */ |
| 35306 | u8 noReadlock; /* Do not bother to obtain readlocks */ |
| 35307 | u8 noSync; /* Do not sync the journal if true */ |
| 35308 | u8 fullSync; /* Do extra syncs of the journal for robustness */ |
| 35309 | u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ |
| 35310 | u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ |
| 35311 | u8 tempFile; /* zFilename is a temporary file */ |
| 35312 | u8 readOnly; /* True for a read-only database */ |
| 35313 | u8 memDb; /* True to inhibit all file I/O */ |
| 35314 | |
| 35315 | /************************************************************************** |
| @@ -35957,11 +35989,11 @@ | |
| 35989 | }else{ |
| 35990 | static const char zeroHdr[28] = {0}; |
| 35991 | rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0); |
| 35992 | } |
| 35993 | if( rc==SQLITE_OK && !pPager->noSync ){ |
| 35994 | rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags); |
| 35995 | } |
| 35996 | |
| 35997 | /* At this point the transaction is committed but the write lock |
| 35998 | ** is still held on the file. If there is a size limit configured for |
| 35999 | ** the persistent journal and the journal file currently consumes more |
| @@ -37409,11 +37441,11 @@ | |
| 37441 | testcase( rc!=SQLITE_OK ); |
| 37442 | } |
| 37443 | if( rc==SQLITE_OK && !pPager->noSync |
| 37444 | && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) |
| 37445 | ){ |
| 37446 | rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); |
| 37447 | } |
| 37448 | if( rc==SQLITE_OK ){ |
| 37449 | rc = pager_end_transaction(pPager, zMaster[0]!='\0'); |
| 37450 | testcase( rc!=SQLITE_OK ); |
| 37451 | } |
| @@ -37583,17 +37615,17 @@ | |
| 37615 | static int pagerWalFrames( |
| 37616 | Pager *pPager, /* Pager object */ |
| 37617 | PgHdr *pList, /* List of frames to log */ |
| 37618 | Pgno nTruncate, /* Database size after this commit */ |
| 37619 | int isCommit, /* True if this is a commit */ |
| 37620 | int syncFlags /* Flags to pass to OsSync() (or 0) */ |
| 37621 | ){ |
| 37622 | int rc; /* Return code */ |
| 37623 | |
| 37624 | assert( pPager->pWal ); |
| 37625 | rc = sqlite3WalFrames(pPager->pWal, |
| 37626 | pPager->pageSize, pList, nTruncate, isCommit, syncFlags |
| 37627 | ); |
| 37628 | if( rc==SQLITE_OK && pPager->pBackup ){ |
| 37629 | PgHdr *p; |
| 37630 | for(p=pList; p; p=p->pDirty){ |
| 37631 | sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); |
| @@ -37918,19 +37950,54 @@ | |
| 37950 | ** of the journal header - being written in between the two |
| 37951 | ** syncs). If we assume that writing a |
| 37952 | ** single disk sector is atomic, then this mode provides |
| 37953 | ** assurance that the journal will not be corrupted to the |
| 37954 | ** point of causing damage to the database during rollback. |
| 37955 | ** |
| 37956 | ** The above is for a rollback-journal mode. For WAL mode, OFF continues |
| 37957 | ** to mean that no syncs ever occur. NORMAL means that the WAL is synced |
| 37958 | ** prior to the start of checkpoint and that the database file is synced |
| 37959 | ** at the conclusion of the checkpoint if the entire content of the WAL |
| 37960 | ** was written back into the database. But no sync operations occur for |
| 37961 | ** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL |
| 37962 | ** file is synced following each commit operation, in addition to the |
| 37963 | ** syncs associated with NORMAL. |
| 37964 | ** |
| 37965 | ** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The |
| 37966 | ** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync |
| 37967 | ** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an |
| 37968 | ** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL |
| 37969 | ** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the |
| 37970 | ** synchronous=FULL versus synchronous=NORMAL setting determines when |
| 37971 | ** the xSync primitive is called and is relevant to all platforms. |
| 37972 | ** |
| 37973 | ** Numeric values associated with these states are OFF==1, NORMAL=2, |
| 37974 | ** and FULL=3. |
| 37975 | */ |
| 37976 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 37977 | SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel( |
| 37978 | Pager *pPager, /* The pager to set safety level for */ |
| 37979 | int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */ |
| 37980 | int bFullFsync, /* PRAGMA fullfsync */ |
| 37981 | int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */ |
| 37982 | ){ |
| 37983 | assert( level>=1 && level<=3 ); |
| 37984 | pPager->noSync = (level==1 || pPager->tempFile) ?1:0; |
| 37985 | pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0; |
| 37986 | if( pPager->noSync ){ |
| 37987 | pPager->syncFlags = 0; |
| 37988 | pPager->ckptSyncFlags = 0; |
| 37989 | }else if( bFullFsync ){ |
| 37990 | pPager->syncFlags = SQLITE_SYNC_FULL; |
| 37991 | pPager->ckptSyncFlags = SQLITE_SYNC_FULL; |
| 37992 | }else if( bCkptFullFsync ){ |
| 37993 | pPager->syncFlags = SQLITE_SYNC_NORMAL; |
| 37994 | pPager->ckptSyncFlags = SQLITE_SYNC_FULL; |
| 37995 | }else{ |
| 37996 | pPager->syncFlags = SQLITE_SYNC_NORMAL; |
| 37997 | pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; |
| 37998 | } |
| 37999 | } |
| 38000 | #endif |
| 38001 | |
| 38002 | /* |
| 38003 | ** The following global variable is incremented whenever the library |
| @@ -38105,13 +38172,12 @@ | |
| 38172 | */ |
| 38173 | SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ |
| 38174 | if( mxPage>0 ){ |
| 38175 | pPager->mxPgno = mxPage; |
| 38176 | } |
| 38177 | assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */ |
| 38178 | assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */ |
| 38179 | return pPager->mxPgno; |
| 38180 | } |
| 38181 | |
| 38182 | /* |
| 38183 | ** The following set of routines are used to disable the simulated |
| @@ -38312,14 +38378,11 @@ | |
| 38378 | disable_simulated_io_errors(); |
| 38379 | sqlite3BeginBenignMalloc(); |
| 38380 | /* pPager->errCode = 0; */ |
| 38381 | pPager->exclusiveMode = 0; |
| 38382 | #ifndef SQLITE_OMIT_WAL |
| 38383 | sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); |
| 38384 | pPager->pWal = 0; |
| 38385 | #endif |
| 38386 | pager_reset(pPager); |
| 38387 | if( MEMDB ){ |
| 38388 | pager_unlock(pPager); |
| @@ -38481,11 +38544,11 @@ | |
| 38544 | ** and never needs to be updated. |
| 38545 | */ |
| 38546 | if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ |
| 38547 | PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); |
| 38548 | IOTRACE(("JSYNC %p\n", pPager)) |
| 38549 | rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags); |
| 38550 | if( rc!=SQLITE_OK ) return rc; |
| 38551 | } |
| 38552 | IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr)); |
| 38553 | rc = sqlite3OsWrite( |
| 38554 | pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr |
| @@ -38493,12 +38556,12 @@ | |
| 38556 | if( rc!=SQLITE_OK ) return rc; |
| 38557 | } |
| 38558 | if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ |
| 38559 | PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); |
| 38560 | IOTRACE(("JSYNC %p\n", pPager)) |
| 38561 | rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags| |
| 38562 | (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) |
| 38563 | ); |
| 38564 | if( rc!=SQLITE_OK ) return rc; |
| 38565 | } |
| 38566 | |
| 38567 | pPager->journalHdr = pPager->journalOff; |
| @@ -39084,11 +39147,12 @@ | |
| 39147 | pPager->memDb = (u8)memDb; |
| 39148 | pPager->readOnly = (u8)readOnly; |
| 39149 | assert( useJournal || pPager->tempFile ); |
| 39150 | pPager->noSync = pPager->tempFile; |
| 39151 | pPager->fullSync = pPager->noSync ?0:1; |
| 39152 | pPager->syncFlags = pPager->noSync ? 0 : SQLITE_SYNC_NORMAL; |
| 39153 | pPager->ckptSyncFlags = pPager->syncFlags; |
| 39154 | /* pPager->pFirst = 0; */ |
| 39155 | /* pPager->pFirstSynced = 0; */ |
| 39156 | /* pPager->pLast = 0; */ |
| 39157 | pPager->nExtra = (u16)nExtra; |
| 39158 | pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; |
| @@ -40207,23 +40271,23 @@ | |
| 40271 | } |
| 40272 | return rc; |
| 40273 | } |
| 40274 | |
| 40275 | /* |
| 40276 | ** Sync the database file to disk. This is a no-op for in-memory databases |
| 40277 | ** or pages with the Pager.noSync flag set. |
| 40278 | ** |
| 40279 | ** If successful, or if called on a pager for which it is a no-op, this |
| 40280 | ** function returns SQLITE_OK. Otherwise, an IO error code is returned. |
| 40281 | */ |
| 40282 | SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){ |
| 40283 | int rc; /* Return code */ |
| 40284 | assert( !MEMDB ); |
| 40285 | if( pPager->noSync ){ |
| 40286 | rc = SQLITE_OK; |
| 40287 | }else{ |
| 40288 | rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); |
| 40289 | } |
| 40290 | return rc; |
| 40291 | } |
| 40292 | |
| 40293 | /* |
| @@ -40308,11 +40372,11 @@ | |
| 40372 | }else{ |
| 40373 | if( pagerUseWal(pPager) ){ |
| 40374 | PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); |
| 40375 | if( pList ){ |
| 40376 | rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1, |
| 40377 | (pPager->fullSync ? pPager->syncFlags : 0) |
| 40378 | ); |
| 40379 | } |
| 40380 | if( rc==SQLITE_OK ){ |
| 40381 | sqlite3PcacheCleanAll(pPager->pPCache); |
| 40382 | } |
| @@ -40439,11 +40503,11 @@ | |
| 40503 | if( rc!=SQLITE_OK ) goto commit_phase_one_exit; |
| 40504 | } |
| 40505 | |
| 40506 | /* Finally, sync the database file. */ |
| 40507 | if( !pPager->noSync && !noSync ){ |
| 40508 | rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); |
| 40509 | } |
| 40510 | IOTRACE(("DBSYNC %p\n", pPager)) |
| 40511 | } |
| 40512 | } |
| 40513 | |
| @@ -41180,14 +41244,12 @@ | |
| 41244 | */ |
| 41245 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager){ |
| 41246 | int rc = SQLITE_OK; |
| 41247 | if( pPager->pWal ){ |
| 41248 | u8 *zBuf = (u8 *)pPager->pTmpSpace; |
| 41249 | rc = sqlite3WalCheckpoint(pPager->pWal, pPager->ckptSyncFlags, |
| 41250 | pPager->pageSize, zBuf); |
| 41251 | } |
| 41252 | return rc; |
| 41253 | } |
| 41254 | |
| 41255 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ |
| @@ -41335,14 +41397,12 @@ | |
| 41397 | ** the database file, the log and log-summary files will be deleted. |
| 41398 | */ |
| 41399 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 41400 | rc = pagerExclusiveLock(pPager); |
| 41401 | if( rc==SQLITE_OK ){ |
| 41402 | rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, |
| 41403 | pPager->pageSize, (u8*)pPager->pTmpSpace); |
| 41404 | pPager->pWal = 0; |
| 41405 | } |
| 41406 | } |
| 41407 | return rc; |
| 41408 | } |
| @@ -47231,15 +47291,21 @@ | |
| 47291 | ** there is a high probability of damage) Level 2 is the default. There |
| 47292 | ** is a very low but non-zero probability of damage. Level 3 reduces the |
| 47293 | ** probability of damage to near zero but with a write performance reduction. |
| 47294 | */ |
| 47295 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 47296 | SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel( |
| 47297 | Btree *p, /* The btree to set the safety level on */ |
| 47298 | int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */ |
| 47299 | int fullSync, /* PRAGMA fullfsync. */ |
| 47300 | int ckptFullSync /* PRAGMA checkpoint_fullfync */ |
| 47301 | ){ |
| 47302 | BtShared *pBt = p->pBt; |
| 47303 | assert( sqlite3_mutex_held(p->db->mutex) ); |
| 47304 | assert( level>=1 && level<=3 ); |
| 47305 | sqlite3BtreeEnter(p); |
| 47306 | sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync, ckptFullSync); |
| 47307 | sqlite3BtreeLeave(p); |
| 47308 | return SQLITE_OK; |
| 47309 | } |
| 47310 | #endif |
| 47311 | |
| @@ -59986,17 +60052,17 @@ | |
| 60052 | /* |
| 60053 | ** Try to convert the type of a function argument or a result column |
| 60054 | ** into a numeric representation. Use either INTEGER or REAL whichever |
| 60055 | ** is appropriate. But only do the conversion if it is possible without |
| 60056 | ** loss of information and return the revised type of the argument. |
| 60057 | */ |
| 60058 | SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ |
| 60059 | Mem *pMem = (Mem*)pVal; |
| 60060 | if( pMem->type==SQLITE_TEXT ){ |
| 60061 | applyNumericAffinity(pMem); |
| 60062 | sqlite3VdbeMemStoreType(pMem); |
| 60063 | } |
| 60064 | return pMem->type; |
| 60065 | } |
| 60066 | |
| 60067 | /* |
| 60068 | ** Exported version of applyAffinity(). This one works on sqlite3_value*, |
| @@ -66078,10 +66144,36 @@ | |
| 66144 | case OP_Pagecount: { /* out2-prerelease */ |
| 66145 | pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt); |
| 66146 | break; |
| 66147 | } |
| 66148 | #endif |
| 66149 | |
| 66150 | |
| 66151 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 66152 | /* Opcode: MaxPgcnt P1 P2 P3 * * |
| 66153 | ** |
| 66154 | ** Try to set the maximum page count for database P1 to the value in P3. |
| 66155 | ** Do not let the maximum page count fall below the current page count and |
| 66156 | ** do not change the maximum page count value if P3==0. |
| 66157 | ** |
| 66158 | ** Store the maximum page count after the change in register P2. |
| 66159 | */ |
| 66160 | case OP_MaxPgcnt: { /* out2-prerelease */ |
| 66161 | unsigned int newMax; |
| 66162 | Btree *pBt; |
| 66163 | |
| 66164 | pBt = db->aDb[pOp->p1].pBt; |
| 66165 | newMax = 0; |
| 66166 | if( pOp->p3 ){ |
| 66167 | newMax = sqlite3BtreeLastPage(pBt); |
| 66168 | if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3; |
| 66169 | } |
| 66170 | pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax); |
| 66171 | break; |
| 66172 | } |
| 66173 | #endif |
| 66174 | |
| 66175 | |
| 66176 | #ifndef SQLITE_OMIT_TRACE |
| 66177 | /* Opcode: Trace * * * P4 * |
| 66178 | ** |
| 66179 | ** If tracing is enabled (by the sqlite3_trace()) interface, then |
| @@ -85223,11 +85315,11 @@ | |
| 85315 | static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; |
| 85316 | static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; |
| 85317 | static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; |
| 85318 | int i, n; |
| 85319 | if( sqlite3Isdigit(*z) ){ |
| 85320 | return (u8)sqlite3Atoi(z); |
| 85321 | } |
| 85322 | n = sqlite3Strlen30(z); |
| 85323 | for(i=0; i<ArraySize(iLength); i++){ |
| 85324 | if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){ |
| 85325 | return iValue[i]; |
| @@ -85264,11 +85356,11 @@ | |
| 85356 | static int getAutoVacuum(const char *z){ |
| 85357 | int i; |
| 85358 | if( 0==sqlite3StrICmp(z, "none") ) return BTREE_AUTOVACUUM_NONE; |
| 85359 | if( 0==sqlite3StrICmp(z, "full") ) return BTREE_AUTOVACUUM_FULL; |
| 85360 | if( 0==sqlite3StrICmp(z, "incremental") ) return BTREE_AUTOVACUUM_INCR; |
| 85361 | i = sqlite3Atoi(z); |
| 85362 | return (u8)((i>=0&&i<=2)?i:0); |
| 85363 | } |
| 85364 | #endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ |
| 85365 | |
| 85366 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| @@ -85360,10 +85452,11 @@ | |
| 85452 | { "short_column_names", SQLITE_ShortColNames }, |
| 85453 | { "count_changes", SQLITE_CountRows }, |
| 85454 | { "empty_result_callbacks", SQLITE_NullCallback }, |
| 85455 | { "legacy_file_format", SQLITE_LegacyFileFmt }, |
| 85456 | { "fullfsync", SQLITE_FullFSync }, |
| 85457 | { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, |
| 85458 | { "reverse_unordered_selects", SQLITE_ReverseOrder }, |
| 85459 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX |
| 85460 | { "automatic_index", SQLITE_AutoIndex }, |
| 85461 | #endif |
| 85462 | #ifdef SQLITE_DEBUG |
| @@ -85571,11 +85664,11 @@ | |
| 85664 | addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); |
| 85665 | sqlite3VdbeChangeP1(v, addr, iDb); |
| 85666 | sqlite3VdbeChangeP1(v, addr+1, iDb); |
| 85667 | sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE); |
| 85668 | }else{ |
| 85669 | int size = sqlite3Atoi(zRight); |
| 85670 | if( size<0 ) size = -size; |
| 85671 | sqlite3BeginWriteOperation(pParse, 0, iDb); |
| 85672 | sqlite3VdbeAddOp2(v, OP_Integer, size, 1); |
| 85673 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); |
| 85674 | pDb->pSchema->cache_size = size; |
| @@ -85600,39 +85693,17 @@ | |
| 85693 | returnSingleInt(pParse, "page_size", size); |
| 85694 | }else{ |
| 85695 | /* Malloc may fail when setting the page-size, as there is an internal |
| 85696 | ** buffer that the pager module resizes using sqlite3_realloc(). |
| 85697 | */ |
| 85698 | db->nextPagesize = sqlite3Atoi(zRight); |
| 85699 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
| 85700 | db->mallocFailed = 1; |
| 85701 | } |
| 85702 | } |
| 85703 | }else |
| 85704 | |
| 85705 | /* |
| 85706 | ** PRAGMA [database.]secure_delete |
| 85707 | ** PRAGMA [database.]secure_delete=ON/OFF |
| 85708 | ** |
| 85709 | ** The first form reports the current setting for the |
| @@ -85655,23 +85726,37 @@ | |
| 85726 | b = sqlite3BtreeSecureDelete(pBt, b); |
| 85727 | returnSingleInt(pParse, "secure_delete", b); |
| 85728 | }else |
| 85729 | |
| 85730 | /* |
| 85731 | ** PRAGMA [database.]max_page_count |
| 85732 | ** PRAGMA [database.]max_page_count=N |
| 85733 | ** |
| 85734 | ** The first form reports the current setting for the |
| 85735 | ** maximum number of pages in the database file. The |
| 85736 | ** second form attempts to change this setting. Both |
| 85737 | ** forms return the current setting. |
| 85738 | ** |
| 85739 | ** PRAGMA [database.]page_count |
| 85740 | ** |
| 85741 | ** Return the number of pages in the specified database. |
| 85742 | */ |
| 85743 | if( sqlite3StrICmp(zLeft,"page_count")==0 |
| 85744 | || sqlite3StrICmp(zLeft,"max_page_count")==0 |
| 85745 | ){ |
| 85746 | int iReg; |
| 85747 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 85748 | sqlite3CodeVerifySchema(pParse, iDb); |
| 85749 | iReg = ++pParse->nMem; |
| 85750 | if( zLeft[0]=='p' ){ |
| 85751 | sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); |
| 85752 | }else{ |
| 85753 | sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, sqlite3Atoi(zRight)); |
| 85754 | } |
| 85755 | sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); |
| 85756 | sqlite3VdbeSetNumCols(v, 1); |
| 85757 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); |
| 85758 | }else |
| 85759 | |
| 85760 | /* |
| 85761 | ** PRAGMA [database.]locking_mode |
| 85762 | ** PRAGMA [database.]locking_mode = (normal|exclusive) |
| @@ -85889,11 +85974,11 @@ | |
| 85974 | if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ |
| 85975 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 85976 | if( !zRight ){ |
| 85977 | returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); |
| 85978 | }else{ |
| 85979 | int size = sqlite3Atoi(zRight); |
| 85980 | if( size<0 ) size = -size; |
| 85981 | pDb->pSchema->cache_size = size; |
| 85982 | sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
| 85983 | } |
| 85984 | }else |
| @@ -86282,11 +86367,11 @@ | |
| 86367 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); |
| 86368 | |
| 86369 | /* Set the maximum error count */ |
| 86370 | mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
| 86371 | if( zRight ){ |
| 86372 | sqlite3GetInt32(zRight, &mxErr); |
| 86373 | if( mxErr<=0 ){ |
| 86374 | mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
| 86375 | } |
| 86376 | } |
| 86377 | sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */ |
| @@ -86539,11 +86624,11 @@ | |
| 86624 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 86625 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| 86626 | }; |
| 86627 | int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); |
| 86628 | sqlite3VdbeChangeP1(v, addr, iDb); |
| 86629 | sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight)); |
| 86630 | sqlite3VdbeChangeP1(v, addr+2, iDb); |
| 86631 | sqlite3VdbeChangeP2(v, addr+2, iCookie); |
| 86632 | }else{ |
| 86633 | /* Read the specified cookie value */ |
| 86634 | static const VdbeOpList readCookie[] = { |
| @@ -86600,12 +86685,11 @@ | |
| 86685 | ** after accumulating N frames in the log. Or query for the current value |
| 86686 | ** of N. |
| 86687 | */ |
| 86688 | if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){ |
| 86689 | if( zRight ){ |
| 86690 | sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); |
| 86691 | } |
| 86692 | returnSingleInt(pParse, "wal_autocheckpoint", |
| 86693 | db->xWalCallback==sqlite3WalDefaultHook ? |
| 86694 | SQLITE_PTR_TO_INT(db->pWalArg) : 0); |
| 86695 | }else |
| @@ -86691,11 +86775,12 @@ | |
| 86775 | ** setting changed. |
| 86776 | */ |
| 86777 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 86778 | if( db->autoCommit ){ |
| 86779 | sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, |
| 86780 | (db->flags&SQLITE_FullFSync)!=0, |
| 86781 | (db->flags&SQLITE_CkptFullFSync)!=0); |
| 86782 | } |
| 86783 | #endif |
| 86784 | pragma_out: |
| 86785 | sqlite3DbFree(db, zLeft); |
| 86786 | sqlite3DbFree(db, zRight); |
| @@ -86783,11 +86868,11 @@ | |
| 86868 | sqlite3_stmt *pStmt; |
| 86869 | TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ |
| 86870 | |
| 86871 | assert( db->init.busy ); |
| 86872 | db->init.iDb = iDb; |
| 86873 | db->init.newTnum = sqlite3Atoi(argv[1]); |
| 86874 | db->init.orphanTrigger = 0; |
| 86875 | TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); |
| 86876 | rc = db->errCode; |
| 86877 | assert( (rc&0xFF)==(rcp&0xFF) ); |
| 86878 | db->init.iDb = 0; |
| @@ -99731,11 +99816,11 @@ | |
| 99816 | ** loop below generates code for a single nested loop of the VM |
| 99817 | ** program. |
| 99818 | */ |
| 99819 | notReady = ~(Bitmask)0; |
| 99820 | for(i=0; i<nTabList; i++){ |
| 99821 | pLevel = &pWInfo->a[i]; |
| 99822 | explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags); |
| 99823 | notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady); |
| 99824 | pWInfo->iContinue = pLevel->addrCont; |
| 99825 | } |
| 99826 | |
| @@ -106890,11 +106975,14 @@ | |
| 106975 | sqlite3BtreeEnter(pBtree); |
| 106976 | pPager = sqlite3BtreePager(pBtree); |
| 106977 | assert( pPager!=0 ); |
| 106978 | fd = sqlite3PagerFile(pPager); |
| 106979 | assert( fd!=0 ); |
| 106980 | if( op==SQLITE_FCNTL_FILE_POINTER ){ |
| 106981 | *(sqlite3_file**)pArg = fd; |
| 106982 | rc = SQLITE_OK; |
| 106983 | }else if( fd->pMethods ){ |
| 106984 | rc = sqlite3OsFileControl(fd, op, pArg); |
| 106985 | } |
| 106986 | sqlite3BtreeLeave(pBtree); |
| 106987 | } |
| 106988 | } |
| @@ -108194,19 +108282,23 @@ | |
| 108282 | i16 eSearch; /* Search strategy (see below) */ |
| 108283 | u8 isEof; /* True if at End Of Results */ |
| 108284 | u8 isRequireSeek; /* True if must seek pStmt to %_content row */ |
| 108285 | sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ |
| 108286 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 108287 | int nPhrase; /* Number of matchable phrases in query */ |
| 108288 | Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ |
| 108289 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 108290 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 108291 | char *aDoclist; /* List of docids for full-text queries */ |
| 108292 | int nDoclist; /* Size of buffer at aDoclist */ |
| 108293 | int eEvalmode; /* An FTS3_EVAL_XX constant */ |
| 108294 | int nRowAvg; /* Average size of database rows, in pages */ |
| 108295 | |
| 108296 | int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ |
| 108297 | u32 *aMatchinfo; /* Information about most recent match */ |
| 108298 | int nMatchinfo; /* Number of elements in aMatchinfo[] */ |
| 108299 | char *zMatchinfo; /* Matchinfo specification */ |
| 108300 | }; |
| 108301 | |
| 108302 | #define FTS3_EVAL_FILTER 0 |
| 108303 | #define FTS3_EVAL_NEXT 1 |
| 108304 | #define FTS3_EVAL_MATCHINFO 2 |
| @@ -108309,25 +108401,26 @@ | |
| 108401 | /* fts3_write.c */ |
| 108402 | SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); |
| 108403 | SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *); |
| 108404 | SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *); |
| 108405 | SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *); |
| 108406 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, sqlite3_int64, |
| 108407 | sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); |
| 108408 | SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**); |
| 108409 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *); |
| 108410 | SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate( |
| 108411 | Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, |
| 108412 | int (*)(Fts3Table *, void *, char *, int, char *, int), void * |
| 108413 | ); |
| 108414 | SQLITE_PRIVATE int sqlite3Fts3SegReaderCost(Fts3Cursor *, Fts3SegReader *, int *); |
| 108415 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
| 108416 | SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); |
| 108417 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*); |
| 108418 | |
| 108419 | SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); |
| 108420 | SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); |
| 108421 | |
| 108422 | SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *); |
| 108423 | SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int); |
| 108424 | SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *); |
| 108425 | SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *); |
| 108426 | SQLITE_PRIVATE char *sqlite3Fts3DeferredDoclist(Fts3DeferredToken *, int *); |
| @@ -108371,11 +108464,11 @@ | |
| 108464 | /* fts3_snippet.c */ |
| 108465 | SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); |
| 108466 | SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, |
| 108467 | const char *, const char *, int, int |
| 108468 | ); |
| 108469 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); |
| 108470 | |
| 108471 | /* fts3_expr.c */ |
| 108472 | SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, |
| 108473 | char **, int, int, const char *, int, Fts3Expr ** |
| 108474 | ); |
| @@ -108684,46 +108777,10 @@ | |
| 108777 | ); |
| 108778 | } |
| 108779 | return rc; |
| 108780 | } |
| 108781 | |
| 108782 | /* |
| 108783 | ** Store the current database page-size in bytes in p->nPgsz. |
| 108784 | ** |
| 108785 | ** If *pRc is non-zero when this function is called, it is a no-op. |
| 108786 | ** Otherwise, if an error occurs, an SQLite error code is stored in *pRc |
| @@ -109137,11 +109194,10 @@ | |
| 109194 | ** a prefix. |
| 109195 | ** |
| 109196 | ** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK. |
| 109197 | */ |
| 109198 | static int fts3ScanInteriorNode( |
| 109199 | const char *zTerm, /* Term to select leaves for */ |
| 109200 | int nTerm, /* Size of term zTerm in bytes */ |
| 109201 | const char *zNode, /* Buffer containing segment interior node */ |
| 109202 | int nNode, /* Size of buffer at zNode */ |
| 109203 | sqlite3_int64 *piFirst, /* OUT: Selected child node */ |
| @@ -109272,11 +109328,11 @@ | |
| 109328 | int iHeight; /* Height of this node in tree */ |
| 109329 | |
| 109330 | assert( piLeaf || piLeaf2 ); |
| 109331 | |
| 109332 | sqlite3Fts3GetVarint32(zNode, &iHeight); |
| 109333 | rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); |
| 109334 | assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); |
| 109335 | |
| 109336 | if( rc==SQLITE_OK && iHeight>1 ){ |
| 109337 | char *zBlob = 0; /* Blob read from %_segments table */ |
| 109338 | int nBlob; /* Size of zBlob in bytes */ |
| @@ -110071,11 +110127,11 @@ | |
| 110127 | */ |
| 110128 | static void fts3SegReaderArrayFree(Fts3SegReaderArray *pArray){ |
| 110129 | if( pArray ){ |
| 110130 | int i; |
| 110131 | for(i=0; i<pArray->nSegment; i++){ |
| 110132 | sqlite3Fts3SegReaderFree(pArray->apSegment[i]); |
| 110133 | } |
| 110134 | sqlite3_free(pArray); |
| 110135 | } |
| 110136 | } |
| 110137 | |
| @@ -110089,11 +110145,11 @@ | |
| 110145 | int nNew = (pArray ? pArray->nAlloc+16 : 16); |
| 110146 | pArray = (Fts3SegReaderArray *)sqlite3_realloc(pArray, |
| 110147 | sizeof(Fts3SegReaderArray) + (nNew-1) * sizeof(Fts3SegReader*) |
| 110148 | ); |
| 110149 | if( !pArray ){ |
| 110150 | sqlite3Fts3SegReaderFree(pNew); |
| 110151 | return SQLITE_NOMEM; |
| 110152 | } |
| 110153 | if( nNew==16 ){ |
| 110154 | pArray->nSegment = 0; |
| 110155 | pArray->nCost = 0; |
| @@ -110142,18 +110198,18 @@ | |
| 110198 | if( sqlite3_column_int64(pStmt, 1)==0 ){ |
| 110199 | /* The entire segment is stored on the root node (which must be a |
| 110200 | ** leaf). Do not bother inspecting any data in this case, just |
| 110201 | ** create a Fts3SegReader to scan the single leaf. |
| 110202 | */ |
| 110203 | rc = sqlite3Fts3SegReaderNew(iAge, 0, 0, 0, zRoot, nRoot, &pNew); |
| 110204 | }else{ |
| 110205 | sqlite3_int64 i1; /* First leaf that may contain zTerm */ |
| 110206 | sqlite3_int64 i2; /* Final leaf that may contain zTerm */ |
| 110207 | rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1, (isPrefix?&i2:0)); |
| 110208 | if( isPrefix==0 ) i2 = i1; |
| 110209 | if( rc==SQLITE_OK ){ |
| 110210 | rc = sqlite3Fts3SegReaderNew(iAge, i1, i2, 0, 0, 0, &pNew); |
| 110211 | } |
| 110212 | } |
| 110213 | assert( (pNew==0)==(rc!=SQLITE_OK) ); |
| 110214 | |
| 110215 | /* If a new Fts3SegReader was allocated, add it to the array. */ |
| @@ -110369,13 +110425,13 @@ | |
| 110425 | } |
| 110426 | } |
| 110427 | |
| 110428 | for(ii=0; ii<pPhrase->nToken; ii++){ |
| 110429 | Fts3PhraseToken *pTok; /* Token to find doclist for */ |
| 110430 | int iTok = 0; /* The token being queried this iteration */ |
| 110431 | char *pList = 0; /* Pointer to token doclist */ |
| 110432 | int nList = 0; /* Size of buffer at pList */ |
| 110433 | |
| 110434 | /* Select a token to process. If this is an xFilter() call, then tokens |
| 110435 | ** are processed in order from least to most costly. Otherwise, tokens |
| 110436 | ** are processed in the order in which they occur in the phrase. |
| 110437 | */ |
| @@ -110413,12 +110469,13 @@ | |
| 110469 | } |
| 110470 | |
| 110471 | if( pCsr->eEvalmode==FTS3_EVAL_NEXT && pTok->pDeferred ){ |
| 110472 | rc = fts3DeferredTermSelect(pTok->pDeferred, isTermPos, &nList, &pList); |
| 110473 | }else{ |
| 110474 | if( pTok->pArray ){ |
| 110475 | rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList); |
| 110476 | } |
| 110477 | pTok->bFulltext = 1; |
| 110478 | } |
| 110479 | assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pArray==0 ); |
| 110480 | if( rc!=SQLITE_OK ) break; |
| 110481 | |
| @@ -110635,18 +110692,21 @@ | |
| 110692 | /* |
| 110693 | ** Return the sum of the costs of all tokens in the expression pExpr. This |
| 110694 | ** function must be called after Fts3SegReaderArrays have been allocated |
| 110695 | ** for all tokens using fts3ExprAllocateSegReaders(). |
| 110696 | */ |
| 110697 | static int fts3ExprCost(Fts3Expr *pExpr){ |
| 110698 | int nCost; /* Return value */ |
| 110699 | if( pExpr->eType==FTSQUERY_PHRASE ){ |
| 110700 | Fts3Phrase *pPhrase = pExpr->pPhrase; |
| 110701 | int ii; |
| 110702 | nCost = 0; |
| 110703 | for(ii=0; ii<pPhrase->nToken; ii++){ |
| 110704 | Fts3SegReaderArray *pArray = pPhrase->aToken[ii].pArray; |
| 110705 | if( pArray ){ |
| 110706 | nCost += pPhrase->aToken[ii].pArray->nCost; |
| 110707 | } |
| 110708 | } |
| 110709 | }else{ |
| 110710 | nCost = fts3ExprCost(pExpr->pLeft) + fts3ExprCost(pExpr->pRight); |
| 110711 | } |
| 110712 | return nCost; |
| @@ -110670,11 +110730,11 @@ | |
| 110730 | if( pExpr->eType==FTSQUERY_AND ){ |
| 110731 | fts3ExprAssignCosts(pExpr->pLeft, ppExprCost); |
| 110732 | fts3ExprAssignCosts(pExpr->pRight, ppExprCost); |
| 110733 | }else{ |
| 110734 | (*ppExprCost)->pExpr = pExpr; |
| 110735 | (*ppExprCost)->nCost = fts3ExprCost(pExpr); |
| 110736 | (*ppExprCost)++; |
| 110737 | } |
| 110738 | } |
| 110739 | |
| 110740 | /* |
| @@ -111388,13 +111448,17 @@ | |
| 111448 | sqlite3_context *pContext, /* SQLite function call context */ |
| 111449 | int nVal, /* Size of argument array */ |
| 111450 | sqlite3_value **apVal /* Array of arguments */ |
| 111451 | ){ |
| 111452 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 111453 | assert( nVal==1 || nVal==2 ); |
| 111454 | if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){ |
| 111455 | const char *zArg = 0; |
| 111456 | if( nVal>1 ){ |
| 111457 | zArg = (const char *)sqlite3_value_text(apVal[1]); |
| 111458 | } |
| 111459 | sqlite3Fts3Matchinfo(pContext, pCsr, zArg); |
| 111460 | } |
| 111461 | } |
| 111462 | |
| 111463 | /* |
| 111464 | ** This routine implements the xFindFunction method for the FTS3 |
| @@ -111579,10 +111643,11 @@ | |
| 111643 | if( SQLITE_OK==rc |
| 111644 | && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) |
| 111645 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) |
| 111646 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) |
| 111647 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1)) |
| 111648 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2)) |
| 111649 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) |
| 111650 | ){ |
| 111651 | rc = sqlite3_create_module_v2( |
| 111652 | db, "fts3", &fts3Module, (void *)pHash, hashDestroy |
| 111653 | ); |
| @@ -112020,11 +112085,10 @@ | |
| 112085 | |
| 112086 | /* Check for an open bracket. */ |
| 112087 | if( sqlite3_fts3_enable_parentheses ){ |
| 112088 | if( *zInput=='(' ){ |
| 112089 | int nConsumed; |
| 112090 | pParse->nNest++; |
| 112091 | rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed); |
| 112092 | if( rc==SQLITE_OK && !*ppExpr ){ |
| 112093 | rc = SQLITE_DONE; |
| 112094 | } |
| @@ -113267,11 +113331,11 @@ | |
| 113331 | */ |
| 113332 | static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ |
| 113333 | int i, j; |
| 113334 | char zReverse[28]; |
| 113335 | char *z, *z2; |
| 113336 | if( nIn<3 || nIn>=(int)sizeof(zReverse)-7 ){ |
| 113337 | /* The word is too big or too small for the porter stemmer. |
| 113338 | ** Fallback to the copy stemmer */ |
| 113339 | copy_stemmer(zIn, nIn, zOut, pnOut); |
| 113340 | return; |
| 113341 | } |
| @@ -114032,19 +114096,27 @@ | |
| 114096 | if( !zTest || !zTest2 ){ |
| 114097 | rc = SQLITE_NOMEM; |
| 114098 | } |
| 114099 | #endif |
| 114100 | |
| 114101 | if( SQLITE_OK==rc ){ |
| 114102 | rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0); |
| 114103 | } |
| 114104 | if( SQLITE_OK==rc ){ |
| 114105 | rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0); |
| 114106 | } |
| 114107 | #ifdef SQLITE_TEST |
| 114108 | if( SQLITE_OK==rc ){ |
| 114109 | rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0); |
| 114110 | } |
| 114111 | if( SQLITE_OK==rc ){ |
| 114112 | rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0); |
| 114113 | } |
| 114114 | if( SQLITE_OK==rc ){ |
| 114115 | rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0); |
| 114116 | } |
| 114117 | #endif |
| 114118 | |
| 114119 | #ifdef SQLITE_TEST |
| 114120 | sqlite3_free(zTest); |
| 114121 | sqlite3_free(zTest2); |
| 114122 | #endif |
| @@ -114565,10 +114637,55 @@ | |
| 114637 | } |
| 114638 | } |
| 114639 | *pp = pStmt; |
| 114640 | return rc; |
| 114641 | } |
| 114642 | |
| 114643 | static int fts3SelectDocsize( |
| 114644 | Fts3Table *pTab, /* FTS3 table handle */ |
| 114645 | int eStmt, /* Either SQL_SELECT_DOCSIZE or DOCTOTAL */ |
| 114646 | sqlite3_int64 iDocid, /* Docid to bind for SQL_SELECT_DOCSIZE */ |
| 114647 | sqlite3_stmt **ppStmt /* OUT: Statement handle */ |
| 114648 | ){ |
| 114649 | sqlite3_stmt *pStmt = 0; /* Statement requested from fts3SqlStmt() */ |
| 114650 | int rc; /* Return code */ |
| 114651 | |
| 114652 | assert( eStmt==SQL_SELECT_DOCSIZE || eStmt==SQL_SELECT_DOCTOTAL ); |
| 114653 | |
| 114654 | rc = fts3SqlStmt(pTab, eStmt, &pStmt, 0); |
| 114655 | if( rc==SQLITE_OK ){ |
| 114656 | if( eStmt==SQL_SELECT_DOCSIZE ){ |
| 114657 | sqlite3_bind_int64(pStmt, 1, iDocid); |
| 114658 | } |
| 114659 | rc = sqlite3_step(pStmt); |
| 114660 | if( rc!=SQLITE_ROW ){ |
| 114661 | rc = sqlite3_reset(pStmt); |
| 114662 | if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT; |
| 114663 | pStmt = 0; |
| 114664 | }else{ |
| 114665 | rc = SQLITE_OK; |
| 114666 | } |
| 114667 | } |
| 114668 | |
| 114669 | *ppStmt = pStmt; |
| 114670 | return rc; |
| 114671 | } |
| 114672 | |
| 114673 | SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal( |
| 114674 | Fts3Table *pTab, /* Fts3 table handle */ |
| 114675 | sqlite3_stmt **ppStmt /* OUT: Statement handle */ |
| 114676 | ){ |
| 114677 | return fts3SelectDocsize(pTab, SQL_SELECT_DOCTOTAL, 0, ppStmt); |
| 114678 | } |
| 114679 | |
| 114680 | SQLITE_PRIVATE int sqlite3Fts3SelectDocsize( |
| 114681 | Fts3Table *pTab, /* Fts3 table handle */ |
| 114682 | sqlite3_int64 iDocid, /* Docid to read size data for */ |
| 114683 | sqlite3_stmt **ppStmt /* OUT: Statement handle */ |
| 114684 | ){ |
| 114685 | return fts3SelectDocsize(pTab, SQL_SELECT_DOCSIZE, iDocid, ppStmt); |
| 114686 | } |
| 114687 | |
| 114688 | /* |
| 114689 | ** Similar to fts3SqlStmt(). Except, after binding the parameters in |
| 114690 | ** array apVal[] to the SQL statement identified by eStmt, the statement |
| 114691 | ** is executed. |
| @@ -115382,11 +115499,11 @@ | |
| 115499 | |
| 115500 | /* |
| 115501 | ** Free all allocations associated with the iterator passed as the |
| 115502 | ** second argument. |
| 115503 | */ |
| 115504 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ |
| 115505 | if( pReader && !fts3SegReaderIsPending(pReader) ){ |
| 115506 | sqlite3_free(pReader->zTerm); |
| 115507 | if( !fts3SegReaderIsRootOnly(pReader) ){ |
| 115508 | sqlite3_free(pReader->aNode); |
| 115509 | } |
| @@ -115396,11 +115513,10 @@ | |
| 115513 | |
| 115514 | /* |
| 115515 | ** Allocate a new SegReader object. |
| 115516 | */ |
| 115517 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( |
| 115518 | int iAge, /* Segment "age". */ |
| 115519 | sqlite3_int64 iStartLeaf, /* First leaf to traverse */ |
| 115520 | sqlite3_int64 iEndLeaf, /* Final leaf to traverse */ |
| 115521 | sqlite3_int64 iEndBlock, /* Final block of segment */ |
| 115522 | const char *zRoot, /* Buffer containing root node */ |
| @@ -115437,11 +115553,11 @@ | |
| 115553 | } |
| 115554 | |
| 115555 | if( rc==SQLITE_OK ){ |
| 115556 | *ppReader = pReader; |
| 115557 | }else{ |
| 115558 | sqlite3Fts3SegReaderFree(pReader); |
| 115559 | } |
| 115560 | return rc; |
| 115561 | } |
| 115562 | |
| 115563 | /* |
| @@ -115560,16 +115676,15 @@ | |
| 115676 | ** If successful, the Fts3SegReader is left pointing to the first term |
| 115677 | ** in the segment and SQLITE_OK is returned. Otherwise, an SQLite error |
| 115678 | ** code is returned. |
| 115679 | */ |
| 115680 | static int fts3SegReaderNew( |
| 115681 | sqlite3_stmt *pStmt, /* See above */ |
| 115682 | int iAge, /* Segment "age". */ |
| 115683 | Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */ |
| 115684 | ){ |
| 115685 | return sqlite3Fts3SegReaderNew(iAge, |
| 115686 | sqlite3_column_int64(pStmt, 1), |
| 115687 | sqlite3_column_int64(pStmt, 2), |
| 115688 | sqlite3_column_int64(pStmt, 3), |
| 115689 | sqlite3_column_blob(pStmt, 4), |
| 115690 | sqlite3_column_bytes(pStmt, 4), |
| @@ -116596,11 +116711,11 @@ | |
| 116711 | assert( SQL_SELECT_LEVEL+1==SQL_SELECT_ALL_LEVEL); |
| 116712 | rc = fts3SqlStmt(p, SQL_SELECT_LEVEL+(iLevel<0), &pStmt, 0); |
| 116713 | if( rc!=SQLITE_OK ) goto finished; |
| 116714 | sqlite3_bind_int(pStmt, 1, iLevel); |
| 116715 | for(i=0; SQLITE_ROW==(sqlite3_step(pStmt)); i++){ |
| 116716 | rc = fts3SegReaderNew(pStmt, i, &apSegment[i]); |
| 116717 | if( rc!=SQLITE_OK ){ |
| 116718 | goto finished; |
| 116719 | } |
| 116720 | } |
| 116721 | rc = sqlite3_reset(pStmt); |
| @@ -116626,15 +116741,15 @@ | |
| 116741 | |
| 116742 | finished: |
| 116743 | fts3SegWriterFree(pWriter); |
| 116744 | if( apSegment ){ |
| 116745 | for(i=0; i<nSegment; i++){ |
| 116746 | sqlite3Fts3SegReaderFree(apSegment[i]); |
| 116747 | } |
| 116748 | sqlite3_free(apSegment); |
| 116749 | } |
| 116750 | sqlite3Fts3SegReaderFree(pPending); |
| 116751 | sqlite3_reset(pStmt); |
| 116752 | return rc; |
| 116753 | } |
| 116754 | |
| 116755 | |
| @@ -116683,11 +116798,11 @@ | |
| 116798 | */ |
| 116799 | if( rc==SQLITE_OK ){ |
| 116800 | rc = fts3SegWriterFlush(p, pWriter, 0, idx); |
| 116801 | } |
| 116802 | fts3SegWriterFree(pWriter); |
| 116803 | sqlite3Fts3SegReaderFree(pReader); |
| 116804 | |
| 116805 | if( rc==SQLITE_OK ){ |
| 116806 | sqlite3Fts3PendingTermsClear(p); |
| 116807 | } |
| 116808 | return rc; |
| @@ -116726,79 +116841,10 @@ | |
| 116841 | assert(j<=nBuf); |
| 116842 | a[i] = (u32)(x & 0xffffffff); |
| 116843 | } |
| 116844 | } |
| 116845 | |
| 116846 | /* |
| 116847 | ** Insert the sizes (in tokens) for each column of the document |
| 116848 | ** with docid equal to p->iPrevDocid. The sizes are encoded as |
| 116849 | ** a blob of varints. |
| 116850 | */ |
| @@ -117217,10 +117263,26 @@ | |
| 117263 | */ |
| 117264 | |
| 117265 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 117266 | |
| 117267 | |
| 117268 | /* |
| 117269 | ** Characters that may appear in the second argument to matchinfo(). |
| 117270 | */ |
| 117271 | #define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */ |
| 117272 | #define FTS3_MATCHINFO_NCOL 'c' /* 1 value */ |
| 117273 | #define FTS3_MATCHINFO_NDOC 'n' /* 1 value */ |
| 117274 | #define FTS3_MATCHINFO_AVGLENGTH 'a' /* nCol values */ |
| 117275 | #define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */ |
| 117276 | #define FTS3_MATCHINFO_LCS 's' /* nCol values */ |
| 117277 | #define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ |
| 117278 | |
| 117279 | /* |
| 117280 | ** The default value for the second argument to matchinfo(). |
| 117281 | */ |
| 117282 | #define FTS3_MATCHINFO_DEFAULT "pcx" |
| 117283 | |
| 117284 | |
| 117285 | /* |
| 117286 | ** Used as an fts3ExprIterate() context when loading phrase doclists to |
| 117287 | ** Fts3Expr.aDoclist[]/nDoclist. |
| 117288 | */ |
| @@ -117270,10 +117332,12 @@ | |
| 117332 | */ |
| 117333 | typedef struct MatchInfo MatchInfo; |
| 117334 | struct MatchInfo { |
| 117335 | Fts3Cursor *pCursor; /* FTS3 Cursor */ |
| 117336 | int nCol; /* Number of columns in table */ |
| 117337 | int nPhrase; /* Number of matchable phrases in query */ |
| 117338 | sqlite3_int64 nDoc; /* Number of docs in database */ |
| 117339 | u32 *aMatchinfo; /* Pre-allocated buffer */ |
| 117340 | }; |
| 117341 | |
| 117342 | |
| 117343 | |
| @@ -117470,10 +117534,22 @@ | |
| 117534 | } |
| 117535 | if( pnPhrase ) *pnPhrase = sCtx.nPhrase; |
| 117536 | if( pnToken ) *pnToken = sCtx.nToken; |
| 117537 | return rc; |
| 117538 | } |
| 117539 | |
| 117540 | static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 117541 | (*(int *)ctx)++; |
| 117542 | UNUSED_PARAMETER(pExpr); |
| 117543 | UNUSED_PARAMETER(iPhrase); |
| 117544 | return SQLITE_OK; |
| 117545 | } |
| 117546 | static int fts3ExprPhraseCount(Fts3Expr *pExpr){ |
| 117547 | int nPhrase = 0; |
| 117548 | (void)fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase); |
| 117549 | return nPhrase; |
| 117550 | } |
| 117551 | |
| 117552 | /* |
| 117553 | ** Advance the position list iterator specified by the first two |
| 117554 | ** arguments so that it points to the first element with a value greater |
| 117555 | ** than or equal to parameter iNext. |
| @@ -117983,24 +118059,46 @@ | |
| 118059 | *pp = pCsr; |
| 118060 | } |
| 118061 | |
| 118062 | /* |
| 118063 | ** fts3ExprIterate() callback used to collect the "global" matchinfo stats |
| 118064 | ** for a single query. |
| 118065 | ** |
| 118066 | ** fts3ExprIterate() callback to load the 'global' elements of a |
| 118067 | ** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements |
| 118068 | ** of the matchinfo array that are constant for all rows returned by the |
| 118069 | ** current query. |
| 118070 | ** |
| 118071 | ** Argument pCtx is actually a pointer to a struct of type MatchInfo. This |
| 118072 | ** function populates Matchinfo.aMatchinfo[] as follows: |
| 118073 | ** |
| 118074 | ** for(iCol=0; iCol<nCol; iCol++){ |
| 118075 | ** aMatchinfo[3*iPhrase*nCol + 3*iCol + 1] = X; |
| 118076 | ** aMatchinfo[3*iPhrase*nCol + 3*iCol + 2] = Y; |
| 118077 | ** } |
| 118078 | ** |
| 118079 | ** where X is the number of matches for phrase iPhrase is column iCol of all |
| 118080 | ** rows of the table. Y is the number of rows for which column iCol contains |
| 118081 | ** at least one instance of phrase iPhrase. |
| 118082 | ** |
| 118083 | ** If the phrase pExpr consists entirely of deferred tokens, then all X and |
| 118084 | ** Y values are set to nDoc, where nDoc is the number of documents in the |
| 118085 | ** file system. This is done because the full-text index doclist is required |
| 118086 | ** to calculate these values properly, and the full-text index doclist is |
| 118087 | ** not available for deferred tokens. |
| 118088 | */ |
| 118089 | static int fts3ExprGlobalHitsCb( |
| 118090 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 118091 | int iPhrase, /* Phrase number (numbered from zero) */ |
| 118092 | void *pCtx /* Pointer to MatchInfo structure */ |
| 118093 | ){ |
| 118094 | MatchInfo *p = (MatchInfo *)pCtx; |
| 118095 | Fts3Cursor *pCsr = p->pCursor; |
| 118096 | char *pIter; |
| 118097 | char *pEnd; |
| 118098 | char *pFree = 0; |
| 118099 | u32 *aOut = &p->aMatchinfo[3*iPhrase*p->nCol]; |
| 118100 | |
| 118101 | assert( pExpr->isLoaded ); |
| 118102 | assert( pExpr->eType==FTSQUERY_PHRASE ); |
| 118103 | |
| 118104 | if( pCsr->pDeferred ){ |
| @@ -118014,14 +118112,14 @@ | |
| 118112 | int rc = sqlite3Fts3ExprLoadFtDoclist(pCsr, pExpr, &pFree, &nFree); |
| 118113 | if( rc!=SQLITE_OK ) return rc; |
| 118114 | pIter = pFree; |
| 118115 | pEnd = &pFree[nFree]; |
| 118116 | }else{ |
| 118117 | int iCol; /* Column index */ |
| 118118 | for(iCol=0; iCol<p->nCol; iCol++){ |
| 118119 | aOut[iCol*3 + 1] = (u32)p->nDoc; |
| 118120 | aOut[iCol*3 + 2] = (u32)p->nDoc; |
| 118121 | } |
| 118122 | return SQLITE_OK; |
| 118123 | } |
| 118124 | }else{ |
| 118125 | pIter = pExpr->aDoclist; |
| @@ -118029,32 +118127,32 @@ | |
| 118127 | } |
| 118128 | |
| 118129 | /* Fill in the global hit count matrix row for this phrase. */ |
| 118130 | while( pIter<pEnd ){ |
| 118131 | while( *pIter++ & 0x80 ); /* Skip past docid. */ |
| 118132 | fts3LoadColumnlistCounts(&pIter, &aOut[1], 1); |
| 118133 | } |
| 118134 | |
| 118135 | sqlite3_free(pFree); |
| 118136 | return SQLITE_OK; |
| 118137 | } |
| 118138 | |
| 118139 | /* |
| 118140 | ** fts3ExprIterate() callback used to collect the "local" part of the |
| 118141 | ** FTS3_MATCHINFO_HITS array. The local stats are those elements of the |
| 118142 | ** array that are different for each row returned by the query. |
| 118143 | */ |
| 118144 | static int fts3ExprLocalHitsCb( |
| 118145 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 118146 | int iPhrase, /* Phrase number */ |
| 118147 | void *pCtx /* Pointer to MatchInfo structure */ |
| 118148 | ){ |
| 118149 | MatchInfo *p = (MatchInfo *)pCtx; |
| 118150 | |
| 118151 | if( pExpr->aDoclist ){ |
| 118152 | char *pCsr; |
| 118153 | int iStart = iPhrase * p->nCol * 3; |
| 118154 | int i; |
| 118155 | |
| 118156 | for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0; |
| 118157 | |
| 118158 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1); |
| @@ -118063,71 +118161,404 @@ | |
| 118161 | } |
| 118162 | } |
| 118163 | |
| 118164 | return SQLITE_OK; |
| 118165 | } |
| 118166 | |
| 118167 | static int fts3MatchinfoCheck( |
| 118168 | Fts3Table *pTab, |
| 118169 | char cArg, |
| 118170 | char **pzErr |
| 118171 | ){ |
| 118172 | if( (cArg==FTS3_MATCHINFO_NPHRASE) |
| 118173 | || (cArg==FTS3_MATCHINFO_NCOL) |
| 118174 | || (cArg==FTS3_MATCHINFO_NDOC && pTab->bHasStat) |
| 118175 | || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bHasStat) |
| 118176 | || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize) |
| 118177 | || (cArg==FTS3_MATCHINFO_LCS) |
| 118178 | || (cArg==FTS3_MATCHINFO_HITS) |
| 118179 | ){ |
| 118180 | return SQLITE_OK; |
| 118181 | } |
| 118182 | *pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg); |
| 118183 | return SQLITE_ERROR; |
| 118184 | } |
| 118185 | |
| 118186 | static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ |
| 118187 | int nVal; /* Number of integers output by cArg */ |
| 118188 | |
| 118189 | switch( cArg ){ |
| 118190 | case FTS3_MATCHINFO_NDOC: |
| 118191 | case FTS3_MATCHINFO_NPHRASE: |
| 118192 | case FTS3_MATCHINFO_NCOL: |
| 118193 | nVal = 1; |
| 118194 | break; |
| 118195 | |
| 118196 | case FTS3_MATCHINFO_AVGLENGTH: |
| 118197 | case FTS3_MATCHINFO_LENGTH: |
| 118198 | case FTS3_MATCHINFO_LCS: |
| 118199 | nVal = pInfo->nCol; |
| 118200 | break; |
| 118201 | |
| 118202 | default: |
| 118203 | assert( cArg==FTS3_MATCHINFO_HITS ); |
| 118204 | nVal = pInfo->nCol * pInfo->nPhrase * 3; |
| 118205 | break; |
| 118206 | } |
| 118207 | |
| 118208 | return nVal; |
| 118209 | } |
| 118210 | |
| 118211 | static int fts3MatchinfoSelectDoctotal( |
| 118212 | Fts3Table *pTab, |
| 118213 | sqlite3_stmt **ppStmt, |
| 118214 | sqlite3_int64 *pnDoc, |
| 118215 | const char **paLen |
| 118216 | ){ |
| 118217 | sqlite3_stmt *pStmt; |
| 118218 | const char *a; |
| 118219 | sqlite3_int64 nDoc; |
| 118220 | |
| 118221 | if( !*ppStmt ){ |
| 118222 | int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt); |
| 118223 | if( rc!=SQLITE_OK ) return rc; |
| 118224 | } |
| 118225 | pStmt = *ppStmt; |
| 118226 | |
| 118227 | a = sqlite3_column_blob(pStmt, 0); |
| 118228 | a += sqlite3Fts3GetVarint(a, &nDoc); |
| 118229 | *pnDoc = (u32)nDoc; |
| 118230 | |
| 118231 | if( paLen ) *paLen = a; |
| 118232 | return SQLITE_OK; |
| 118233 | } |
| 118234 | |
| 118235 | /* |
| 118236 | ** An instance of the following structure is used to store state while |
| 118237 | ** iterating through a multi-column position-list corresponding to the |
| 118238 | ** hits for a single phrase on a single row in order to calculate the |
| 118239 | ** values for a matchinfo() FTS3_MATCHINFO_LCS request. |
| 118240 | */ |
| 118241 | typedef struct LcsIterator LcsIterator; |
| 118242 | struct LcsIterator { |
| 118243 | Fts3Expr *pExpr; /* Pointer to phrase expression */ |
| 118244 | char *pRead; /* Cursor used to iterate through aDoclist */ |
| 118245 | int iPosOffset; /* Tokens count up to end of this phrase */ |
| 118246 | int iCol; /* Current column number */ |
| 118247 | int iPos; /* Current position */ |
| 118248 | }; |
| 118249 | |
| 118250 | /* |
| 118251 | ** If LcsIterator.iCol is set to the following value, the iterator has |
| 118252 | ** finished iterating through all offsets for all columns. |
| 118253 | */ |
| 118254 | #define LCS_ITERATOR_FINISHED 0x7FFFFFFF; |
| 118255 | |
| 118256 | static int fts3MatchinfoLcsCb( |
| 118257 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 118258 | int iPhrase, /* Phrase number (numbered from zero) */ |
| 118259 | void *pCtx /* Pointer to MatchInfo structure */ |
| 118260 | ){ |
| 118261 | LcsIterator *aIter = (LcsIterator *)pCtx; |
| 118262 | aIter[iPhrase].pExpr = pExpr; |
| 118263 | return SQLITE_OK; |
| 118264 | } |
| 118265 | |
| 118266 | /* |
| 118267 | ** Advance the iterator passed as an argument to the next position. Return |
| 118268 | ** 1 if the iterator is at EOF or if it now points to the start of the |
| 118269 | ** position list for the next column. |
| 118270 | */ |
| 118271 | static int fts3LcsIteratorAdvance(LcsIterator *pIter){ |
| 118272 | char *pRead = pIter->pRead; |
| 118273 | sqlite3_int64 iRead; |
| 118274 | int rc = 0; |
| 118275 | |
| 118276 | pRead += sqlite3Fts3GetVarint(pRead, &iRead); |
| 118277 | if( iRead==0 ){ |
| 118278 | pIter->iCol = LCS_ITERATOR_FINISHED; |
| 118279 | rc = 1; |
| 118280 | }else{ |
| 118281 | if( iRead==1 ){ |
| 118282 | pRead += sqlite3Fts3GetVarint(pRead, &iRead); |
| 118283 | pIter->iCol = iRead; |
| 118284 | pIter->iPos = pIter->iPosOffset; |
| 118285 | pRead += sqlite3Fts3GetVarint(pRead, &iRead); |
| 118286 | rc = 1; |
| 118287 | } |
| 118288 | pIter->iPos += (iRead-2); |
| 118289 | } |
| 118290 | |
| 118291 | pIter->pRead = pRead; |
| 118292 | return rc; |
| 118293 | } |
| 118294 | |
| 118295 | /* |
| 118296 | ** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag. |
| 118297 | ** |
| 118298 | ** If the call is successful, the longest-common-substring lengths for each |
| 118299 | ** column are written into the first nCol elements of the pInfo->aMatchinfo[] |
| 118300 | ** array before returning. SQLITE_OK is returned in this case. |
| 118301 | ** |
| 118302 | ** Otherwise, if an error occurs, an SQLite error code is returned and the |
| 118303 | ** data written to the first nCol elements of pInfo->aMatchinfo[] is |
| 118304 | ** undefined. |
| 118305 | */ |
| 118306 | static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){ |
| 118307 | LcsIterator *aIter; |
| 118308 | int i; |
| 118309 | int iCol; |
| 118310 | int nToken = 0; |
| 118311 | |
| 118312 | /* Allocate and populate the array of LcsIterator objects. The array |
| 118313 | ** contains one element for each matchable phrase in the query. |
| 118314 | **/ |
| 118315 | aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase); |
| 118316 | if( !aIter ) return SQLITE_NOMEM; |
| 118317 | memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase); |
| 118318 | (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter); |
| 118319 | for(i=0; i<pInfo->nPhrase; i++){ |
| 118320 | LcsIterator *pIter = &aIter[i]; |
| 118321 | nToken -= pIter->pExpr->pPhrase->nToken; |
| 118322 | pIter->iPosOffset = nToken; |
| 118323 | pIter->pRead = sqlite3Fts3FindPositions(pIter->pExpr, pCsr->iPrevId, -1); |
| 118324 | if( pIter->pRead ){ |
| 118325 | pIter->iPos = pIter->iPosOffset; |
| 118326 | fts3LcsIteratorAdvance(&aIter[i]); |
| 118327 | }else{ |
| 118328 | pIter->iCol = LCS_ITERATOR_FINISHED; |
| 118329 | } |
| 118330 | } |
| 118331 | |
| 118332 | for(iCol=0; iCol<pInfo->nCol; iCol++){ |
| 118333 | int nLcs = 0; /* LCS value for this column */ |
| 118334 | int nLive = 0; /* Number of iterators in aIter not at EOF */ |
| 118335 | |
| 118336 | /* Loop through the iterators in aIter[]. Set nLive to the number of |
| 118337 | ** iterators that point to a position-list corresponding to column iCol. |
| 118338 | */ |
| 118339 | for(i=0; i<pInfo->nPhrase; i++){ |
| 118340 | assert( aIter[i].iCol>=iCol ); |
| 118341 | if( aIter[i].iCol==iCol ) nLive++; |
| 118342 | } |
| 118343 | |
| 118344 | /* The following loop runs until all iterators in aIter[] have finished |
| 118345 | ** iterating through positions in column iCol. Exactly one of the |
| 118346 | ** iterators is advanced each time the body of the loop is run. |
| 118347 | */ |
| 118348 | while( nLive>0 ){ |
| 118349 | LcsIterator *pAdv = 0; /* The iterator to advance by one position */ |
| 118350 | int nThisLcs = 0; /* LCS for the current iterator positions */ |
| 118351 | |
| 118352 | for(i=0; i<pInfo->nPhrase; i++){ |
| 118353 | LcsIterator *pIter = &aIter[i]; |
| 118354 | if( iCol!=pIter->iCol ){ |
| 118355 | /* This iterator is already at EOF for this column. */ |
| 118356 | nThisLcs = 0; |
| 118357 | }else{ |
| 118358 | if( pAdv==0 || pIter->iPos<pAdv->iPos ){ |
| 118359 | pAdv = pIter; |
| 118360 | } |
| 118361 | if( nThisLcs==0 || pIter->iPos==pIter[-1].iPos ){ |
| 118362 | nThisLcs++; |
| 118363 | }else{ |
| 118364 | nThisLcs = 1; |
| 118365 | } |
| 118366 | if( nThisLcs>nLcs ) nLcs = nThisLcs; |
| 118367 | } |
| 118368 | } |
| 118369 | if( fts3LcsIteratorAdvance(pAdv) ) nLive--; |
| 118370 | } |
| 118371 | |
| 118372 | pInfo->aMatchinfo[iCol] = nLcs; |
| 118373 | } |
| 118374 | |
| 118375 | sqlite3_free(aIter); |
| 118376 | return SQLITE_OK; |
| 118377 | } |
| 118378 | |
| 118379 | /* |
| 118380 | ** Populate the buffer pInfo->aMatchinfo[] with an array of integers to |
| 118381 | ** be returned by the matchinfo() function. Argument zArg contains the |
| 118382 | ** format string passed as the second argument to matchinfo (or the |
| 118383 | ** default value "pcx" if no second argument was specified). The format |
| 118384 | ** string has already been validated and the pInfo->aMatchinfo[] array |
| 118385 | ** is guaranteed to be large enough for the output. |
| 118386 | ** |
| 118387 | ** If bGlobal is true, then populate all fields of the matchinfo() output. |
| 118388 | ** If it is false, then assume that those fields that do not change between |
| 118389 | ** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS) |
| 118390 | ** have already been populated. |
| 118391 | ** |
| 118392 | ** Return SQLITE_OK if successful, or an SQLite error code if an error |
| 118393 | ** occurs. If a value other than SQLITE_OK is returned, the state the |
| 118394 | ** pInfo->aMatchinfo[] buffer is left in is undefined. |
| 118395 | */ |
| 118396 | static int fts3MatchinfoValues( |
| 118397 | Fts3Cursor *pCsr, /* FTS3 cursor object */ |
| 118398 | int bGlobal, /* True to grab the global stats */ |
| 118399 | MatchInfo *pInfo, /* Matchinfo context object */ |
| 118400 | const char *zArg /* Matchinfo format string */ |
| 118401 | ){ |
| 118402 | int rc = SQLITE_OK; |
| 118403 | int i; |
| 118404 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 118405 | sqlite3_stmt *pSelect = 0; |
| 118406 | |
| 118407 | for(i=0; rc==SQLITE_OK && zArg[i]; i++){ |
| 118408 | |
| 118409 | switch( zArg[i] ){ |
| 118410 | case FTS3_MATCHINFO_NPHRASE: |
| 118411 | if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase; |
| 118412 | break; |
| 118413 | |
| 118414 | case FTS3_MATCHINFO_NCOL: |
| 118415 | if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol; |
| 118416 | break; |
| 118417 | |
| 118418 | case FTS3_MATCHINFO_NDOC: |
| 118419 | if( bGlobal ){ |
| 118420 | sqlite3_int64 nDoc; |
| 118421 | rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0); |
| 118422 | pInfo->aMatchinfo[0] = (u32)nDoc; |
| 118423 | } |
| 118424 | break; |
| 118425 | |
| 118426 | case FTS3_MATCHINFO_AVGLENGTH: |
| 118427 | if( bGlobal ){ |
| 118428 | sqlite3_int64 nDoc; /* Number of rows in table */ |
| 118429 | const char *a; /* Aggregate column length array */ |
| 118430 | |
| 118431 | rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a); |
| 118432 | if( rc==SQLITE_OK ){ |
| 118433 | int iCol; |
| 118434 | for(iCol=0; iCol<pInfo->nCol; iCol++){ |
| 118435 | sqlite3_int64 nToken; |
| 118436 | a += sqlite3Fts3GetVarint(a, &nToken); |
| 118437 | pInfo->aMatchinfo[iCol] = ((u32)(nToken&0xffffffff)+nDoc/2)/nDoc; |
| 118438 | } |
| 118439 | } |
| 118440 | } |
| 118441 | break; |
| 118442 | |
| 118443 | case FTS3_MATCHINFO_LENGTH: { |
| 118444 | sqlite3_stmt *pSelectDocsize = 0; |
| 118445 | rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize); |
| 118446 | if( rc==SQLITE_OK ){ |
| 118447 | int iCol; |
| 118448 | const char *a = sqlite3_column_blob(pSelectDocsize, 0); |
| 118449 | for(iCol=0; iCol<pInfo->nCol; iCol++){ |
| 118450 | sqlite3_int64 nToken; |
| 118451 | a += sqlite3Fts3GetVarint(a, &nToken); |
| 118452 | pInfo->aMatchinfo[iCol] = (u32)nToken; |
| 118453 | } |
| 118454 | } |
| 118455 | sqlite3_reset(pSelectDocsize); |
| 118456 | break; |
| 118457 | } |
| 118458 | |
| 118459 | case FTS3_MATCHINFO_LCS: |
| 118460 | rc = fts3ExprLoadDoclists(pCsr, 0, 0); |
| 118461 | if( rc==SQLITE_OK ){ |
| 118462 | rc = fts3MatchinfoLcs(pCsr, pInfo); |
| 118463 | } |
| 118464 | break; |
| 118465 | |
| 118466 | default: { |
| 118467 | Fts3Expr *pExpr; |
| 118468 | assert( zArg[i]==FTS3_MATCHINFO_HITS ); |
| 118469 | pExpr = pCsr->pExpr; |
| 118470 | rc = fts3ExprLoadDoclists(pCsr, 0, 0); |
| 118471 | if( rc!=SQLITE_OK ) break; |
| 118472 | if( bGlobal ){ |
| 118473 | if( pCsr->pDeferred ){ |
| 118474 | rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0); |
| 118475 | if( rc!=SQLITE_OK ) break; |
| 118476 | } |
| 118477 | rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); |
| 118478 | if( rc!=SQLITE_OK ) break; |
| 118479 | } |
| 118480 | (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); |
| 118481 | break; |
| 118482 | } |
| 118483 | } |
| 118484 | |
| 118485 | pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]); |
| 118486 | } |
| 118487 | |
| 118488 | sqlite3_reset(pSelect); |
| 118489 | return rc; |
| 118490 | } |
| 118491 | |
| 118492 | |
| 118493 | /* |
| 118494 | ** Populate pCsr->aMatchinfo[] with data for the current row. The |
| 118495 | ** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). |
| 118496 | */ |
| 118497 | static int fts3GetMatchinfo( |
| 118498 | Fts3Cursor *pCsr, /* FTS3 Cursor object */ |
| 118499 | const char *zArg /* Second argument to matchinfo() function */ |
| 118500 | ){ |
| 118501 | MatchInfo sInfo; |
| 118502 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 118503 | int rc = SQLITE_OK; |
| 118504 | int bGlobal = 0; /* Collect 'global' stats as well as local */ |
| 118505 | |
| 118506 | memset(&sInfo, 0, sizeof(MatchInfo)); |
| 118507 | sInfo.pCursor = pCsr; |
| 118508 | sInfo.nCol = pTab->nColumn; |
| 118509 | |
| 118510 | /* If there is cached matchinfo() data, but the format string for the |
| 118511 | ** cache does not match the format string for this request, discard |
| 118512 | ** the cached data. */ |
| 118513 | if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){ |
| 118514 | assert( pCsr->aMatchinfo ); |
| 118515 | sqlite3_free(pCsr->aMatchinfo); |
| 118516 | pCsr->zMatchinfo = 0; |
| 118517 | pCsr->aMatchinfo = 0; |
| 118518 | } |
| 118519 | |
| 118520 | /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the |
| 118521 | ** matchinfo function has been called for this query. In this case |
| 118522 | ** allocate the array used to accumulate the matchinfo data and |
| 118523 | ** initialize those elements that are constant for every row. |
| 118524 | */ |
| 118525 | if( pCsr->aMatchinfo==0 ){ |
| 118526 | int nMatchinfo = 0; /* Number of u32 elements in match-info */ |
| 118527 | int nArg; /* Bytes in zArg */ |
| 118528 | int i; /* Used to iterate through zArg */ |
| 118529 | |
| 118530 | /* Determine the number of phrases in the query */ |
| 118531 | pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr); |
| 118532 | sInfo.nPhrase = pCsr->nPhrase; |
| 118533 | |
| 118534 | /* Determine the number of integers in the buffer returned by this call. */ |
| 118535 | for(i=0; zArg[i]; i++){ |
| 118536 | nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]); |
| 118537 | } |
| 118538 | |
| 118539 | /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */ |
| 118540 | nArg = strlen(zArg); |
| 118541 | pCsr->aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo + nArg + 1); |
| 118542 | if( !pCsr->aMatchinfo ) return SQLITE_NOMEM; |
| 118543 | |
| 118544 | pCsr->zMatchinfo = (char *)&pCsr->aMatchinfo[nMatchinfo]; |
| 118545 | pCsr->nMatchinfo = nMatchinfo; |
| 118546 | memcpy(pCsr->zMatchinfo, zArg, nArg+1); |
| 118547 | memset(pCsr->aMatchinfo, 0, sizeof(u32)*nMatchinfo); |
| 118548 | pCsr->isMatchinfoNeeded = 1; |
| 118549 | bGlobal = 1; |
| 118550 | } |
| 118551 | |
| 118552 | sInfo.aMatchinfo = pCsr->aMatchinfo; |
| 118553 | sInfo.nPhrase = pCsr->nPhrase; |
| 118554 | if( pCsr->isMatchinfoNeeded ){ |
| 118555 | rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg); |
| 118556 | pCsr->isMatchinfoNeeded = 0; |
| 118557 | } |
| 118558 | |
| 118559 | return rc; |
| 118560 | } |
| 118561 | |
| 118562 | /* |
| 118563 | ** Implementation of snippet() function. |
| 118564 | */ |
| @@ -118184,11 +118615,11 @@ | |
| 118615 | /* Loop through all columns of the table being considered for snippets. |
| 118616 | ** If the iCol argument to this function was negative, this means all |
| 118617 | ** columns of the FTS3 table. Otherwise, only column iCol is considered. |
| 118618 | */ |
| 118619 | for(iRead=0; iRead<pTab->nColumn; iRead++){ |
| 118620 | SnippetFragment sF = {0, 0, 0, 0}; |
| 118621 | int iS; |
| 118622 | if( iCol>=0 && iRead!=iCol ) continue; |
| 118623 | |
| 118624 | /* Find the best snippet of nFToken tokens in column iRead. */ |
| 118625 | rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS); |
| @@ -118411,26 +118842,47 @@ | |
| 118842 | } |
| 118843 | |
| 118844 | /* |
| 118845 | ** Implementation of matchinfo() function. |
| 118846 | */ |
| 118847 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo( |
| 118848 | sqlite3_context *pContext, /* Function call context */ |
| 118849 | Fts3Cursor *pCsr, /* FTS3 table cursor */ |
| 118850 | const char *zArg /* Second arg to matchinfo() function */ |
| 118851 | ){ |
| 118852 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 118853 | int rc; |
| 118854 | int i; |
| 118855 | const char *zFormat; |
| 118856 | |
| 118857 | if( zArg ){ |
| 118858 | for(i=0; zArg[i]; i++){ |
| 118859 | char *zErr = 0; |
| 118860 | if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){ |
| 118861 | sqlite3_result_error(pContext, zErr, -1); |
| 118862 | sqlite3_free(zErr); |
| 118863 | return; |
| 118864 | } |
| 118865 | } |
| 118866 | zFormat = zArg; |
| 118867 | }else{ |
| 118868 | zFormat = FTS3_MATCHINFO_DEFAULT; |
| 118869 | } |
| 118870 | |
| 118871 | if( !pCsr->pExpr ){ |
| 118872 | sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); |
| 118873 | return; |
| 118874 | } |
| 118875 | |
| 118876 | /* Retrieve matchinfo() data. */ |
| 118877 | rc = fts3GetMatchinfo(pCsr, zFormat); |
| 118878 | sqlite3Fts3SegmentsClose(pTab); |
| 118879 | |
| 118880 | if( rc!=SQLITE_OK ){ |
| 118881 | sqlite3_result_error_code(pContext, rc); |
| 118882 | }else{ |
| 118883 | int n = pCsr->nMatchinfo * sizeof(u32); |
| 118884 | sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); |
| 118885 | } |
| 118886 | } |
| 118887 | |
| 118888 | #endif |
| @@ -118545,10 +118997,16 @@ | |
| 118997 | #include "sqlite3rtree.h" |
| 118998 | typedef sqlite3_int64 i64; |
| 118999 | typedef unsigned char u8; |
| 119000 | typedef unsigned int u32; |
| 119001 | #endif |
| 119002 | |
| 119003 | /* The following macro is used to suppress compiler warnings. |
| 119004 | */ |
| 119005 | #ifndef UNUSED_PARAMETER |
| 119006 | # define UNUSED_PARAMETER(x) (void)(x) |
| 119007 | #endif |
| 119008 | |
| 119009 | typedef struct Rtree Rtree; |
| 119010 | typedef struct RtreeCursor RtreeCursor; |
| 119011 | typedef struct RtreeNode RtreeNode; |
| 119012 | typedef struct RtreeCell RtreeCell; |
| @@ -119627,11 +120085,11 @@ | |
| 120085 | /* Check that value is actually a blob. */ |
| 120086 | if( !sqlite3_value_type(pValue)==SQLITE_BLOB ) return SQLITE_ERROR; |
| 120087 | |
| 120088 | /* Check that the blob is roughly the right size. */ |
| 120089 | nBlob = sqlite3_value_bytes(pValue); |
| 120090 | if( nBlob<(int)sizeof(RtreeMatchArg) |
| 120091 | || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0 |
| 120092 | ){ |
| 120093 | return SQLITE_ERROR; |
| 120094 | } |
| 120095 | |
| @@ -119642,11 +120100,11 @@ | |
| 120100 | memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); |
| 120101 | p = (RtreeMatchArg *)&pGeom[1]; |
| 120102 | |
| 120103 | memcpy(p, sqlite3_value_blob(pValue), nBlob); |
| 120104 | if( p->magic!=RTREE_GEOMETRY_MAGIC |
| 120105 | || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) |
| 120106 | ){ |
| 120107 | sqlite3_free(pGeom); |
| 120108 | return SQLITE_ERROR; |
| 120109 | } |
| 120110 | |
| @@ -119788,10 +120246,11 @@ | |
| 120246 | int ii, cCol; |
| 120247 | |
| 120248 | int iIdx = 0; |
| 120249 | char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; |
| 120250 | memset(zIdxStr, 0, sizeof(zIdxStr)); |
| 120251 | UNUSED_PARAMETER(tab); |
| 120252 | |
| 120253 | assert( pIdxInfo->idxStr==0 ); |
| 120254 | for(ii=0; ii<pIdxInfo->nConstraint; ii++){ |
| 120255 | struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; |
| 120256 | |
| @@ -119961,10 +120420,11 @@ | |
| 120420 | for(ii=0; ii<nCell; ii++){ |
| 120421 | #if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 120422 | if( ii!=iExclude ) |
| 120423 | #else |
| 120424 | assert( iExclude==-1 ); |
| 120425 | UNUSED_PARAMETER(iExclude); |
| 120426 | #endif |
| 120427 | { |
| 120428 | int jj; |
| 120429 | float o = 1.0; |
| 120430 | for(jj=0; jj<(pRtree->nDim*2); jj+=2){ |
| @@ -121082,20 +121542,10 @@ | |
| 121542 | rc = sqlite3_reset(pRtree->pWriteRowid); |
| 121543 | *piRowid = sqlite3_last_insert_rowid(pRtree->db); |
| 121544 | return rc; |
| 121545 | } |
| 121546 | |
| 121547 | /* |
| 121548 | ** The xUpdate method for rtree module virtual tables. |
| 121549 | */ |
| 121550 | static int rtreeUpdate( |
| 121551 | sqlite3_vtab *pVtab, |
| @@ -121557,10 +122007,11 @@ | |
| 122007 | char *zText = 0; |
| 122008 | RtreeNode node; |
| 122009 | Rtree tree; |
| 122010 | int ii; |
| 122011 | |
| 122012 | UNUSED_PARAMETER(nArg); |
| 122013 | memset(&node, 0, sizeof(RtreeNode)); |
| 122014 | memset(&tree, 0, sizeof(Rtree)); |
| 122015 | tree.nDim = sqlite3_value_int(apArg[0]); |
| 122016 | tree.nBytesPerCell = 8 + 8 * tree.nDim; |
| 122017 | node.zData = (u8 *)sqlite3_value_blob(apArg[1]); |
| @@ -121590,10 +122041,11 @@ | |
| 122041 | |
| 122042 | sqlite3_result_text(ctx, zText, -1, sqlite3_free); |
| 122043 | } |
| 122044 | |
| 122045 | static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ |
| 122046 | UNUSED_PARAMETER(nArg); |
| 122047 | if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB |
| 122048 | || sqlite3_value_bytes(apArg[0])<2 |
| 122049 | ){ |
| 122050 | sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1); |
| 122051 | }else{ |
| @@ -121611,11 +122063,10 @@ | |
| 122063 | const int utf8 = SQLITE_UTF8; |
| 122064 | int rc; |
| 122065 | |
| 122066 | rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); |
| 122067 | if( rc==SQLITE_OK ){ |
| 122068 | rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); |
| 122069 | } |
| 122070 | if( rc==SQLITE_OK ){ |
| 122071 | void *c = (void *)RTREE_COORD_REAL32; |
| 122072 | rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); |
| 122073 |
+29
-10
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -107,11 +107,11 @@ | ||
| 107 | 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | 109 | */ |
| 110 | 110 | #define SQLITE_VERSION "3.7.4" |
| 111 | 111 | #define SQLITE_VERSION_NUMBER 3007004 |
| 112 | -#define SQLITE_SOURCE_ID "2010-11-16 23:10:26 fd5b2f23dd5111d2f0934dd828bae36b755024c1" | |
| 112 | +#define SQLITE_SOURCE_ID "2010-11-26 16:49:59 c412f61229b6ab1ac90b932afd56f7c5e3ba1cfe" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| @@ -540,10 +540,22 @@ | ||
| 540 | 540 | ** sync operation only needs to flush data to mass storage. Inode |
| 541 | 541 | ** information need not be flushed. If the lower four bits of the flag |
| 542 | 542 | ** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. |
| 543 | 543 | ** If the lower four bits equal SQLITE_SYNC_FULL, that means |
| 544 | 544 | ** to use Mac OS X style fullsync instead of fsync(). |
| 545 | +** | |
| 546 | +** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags | |
| 547 | +** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL | |
| 548 | +** settings. The [synchronous pragma] determines when calls to the | |
| 549 | +** xSync VFS method occur and applies uniformly across all platforms. | |
| 550 | +** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how | |
| 551 | +** energetic or rigorous or forceful the sync operations are and | |
| 552 | +** only make a difference on Mac OSX for the default SQLite code. | |
| 553 | +** (Third-party VFS implementations might also make the distinction | |
| 554 | +** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the | |
| 555 | +** operating systems natively supported by SQLite, only Mac OSX | |
| 556 | +** cares about the difference.) | |
| 545 | 557 | */ |
| 546 | 558 | #define SQLITE_SYNC_NORMAL 0x00002 |
| 547 | 559 | #define SQLITE_SYNC_FULL 0x00003 |
| 548 | 560 | #define SQLITE_SYNC_DATAONLY 0x00010 |
| 549 | 561 | |
| @@ -708,10 +720,12 @@ | ||
| 708 | 720 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 709 | 721 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 710 | 722 | #define SQLITE_LAST_ERRNO 4 |
| 711 | 723 | #define SQLITE_FCNTL_SIZE_HINT 5 |
| 712 | 724 | #define SQLITE_FCNTL_CHUNK_SIZE 6 |
| 725 | +#define SQLITE_FCNTL_FILE_POINTER 7 | |
| 726 | + | |
| 713 | 727 | |
| 714 | 728 | /* |
| 715 | 729 | ** CAPI3REF: Mutex Handle |
| 716 | 730 | ** |
| 717 | 731 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -2635,18 +2649,17 @@ | ||
| 2635 | 2649 | |
| 2636 | 2650 | /* |
| 2637 | 2651 | ** CAPI3REF: Determine If An SQL Statement Writes The Database |
| 2638 | 2652 | ** |
| 2639 | 2653 | ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if |
| 2640 | -** the [prepared statement] X is guaranteed to leave the database file | |
| 2641 | -** unmodified. ^If the sqlite3_stmt_readonly(X) interface returns false (zero) | |
| 2642 | -** then evaluating the statement might change the database file, but this | |
| 2643 | -** is not guaranteed as the write operation might be conditional and the | |
| 2644 | -** condition might not be met. ^If X is a NULL pointer then | |
| 2645 | -** sqlite3_stmt_readonly(X) returns true. If X is a non-NULL pointer but | |
| 2646 | -** is not a pointer to a valid, unfinalized prepared statement, then the | |
| 2647 | -** behavior is undefined and probably harmful. | |
| 2654 | +** the [prepared statement] X is [SELECT] statement and false (zero) if | |
| 2655 | +** X is an [INSERT], [UPDATE], [DELETE], CREATE, DROP, [ANALYZE], | |
| 2656 | +** [ALTER], or [REINDEX] statement. | |
| 2657 | +** If X is a NULL pointer or any other kind of statement, including but | |
| 2658 | +** not limited to [ATTACH], [DETACH], [COMMIT], [ROLLBACK], [RELEASE], | |
| 2659 | +** [SAVEPOINT], [PRAGMA], or [VACUUM] the result of sqlite3_stmt_readonly(X) is | |
| 2660 | +** undefined. | |
| 2648 | 2661 | */ |
| 2649 | 2662 | SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); |
| 2650 | 2663 | |
| 2651 | 2664 | /* |
| 2652 | 2665 | ** CAPI3REF: Dynamically Typed Value Object |
| @@ -5238,19 +5251,25 @@ | ||
| 5238 | 5251 | ** CAPI3REF: Low-Level Control Of Database Files |
| 5239 | 5252 | ** |
| 5240 | 5253 | ** ^The [sqlite3_file_control()] interface makes a direct call to the |
| 5241 | 5254 | ** xFileControl method for the [sqlite3_io_methods] object associated |
| 5242 | 5255 | ** with a particular database identified by the second argument. ^The |
| 5243 | -** name of the database "main" for the main database or "temp" for the | |
| 5256 | +** name of the database is "main" for the main database or "temp" for the | |
| 5244 | 5257 | ** TEMP database, or the name that appears after the AS keyword for |
| 5245 | 5258 | ** databases that are added using the [ATTACH] SQL command. |
| 5246 | 5259 | ** ^A NULL pointer can be used in place of "main" to refer to the |
| 5247 | 5260 | ** main database file. |
| 5248 | 5261 | ** ^The third and fourth parameters to this routine |
| 5249 | 5262 | ** are passed directly through to the second and third parameters of |
| 5250 | 5263 | ** the xFileControl method. ^The return value of the xFileControl |
| 5251 | 5264 | ** method becomes the return value of this routine. |
| 5265 | +** | |
| 5266 | +** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes | |
| 5267 | +** a pointer to the underlying [sqlite3_file] object to be written into | |
| 5268 | +** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER | |
| 5269 | +** case is a short-circuit path which does not actually invoke the | |
| 5270 | +** underlying sqlite3_io_methods.xFileControl method. | |
| 5252 | 5271 | ** |
| 5253 | 5272 | ** ^If the second parameter (zDbName) does not match the name of any |
| 5254 | 5273 | ** open database file, then SQLITE_ERROR is returned. ^This error |
| 5255 | 5274 | ** code is not remembered and will not be recalled by [sqlite3_errcode()] |
| 5256 | 5275 | ** or [sqlite3_errmsg()]. The underlying xFileControl method might |
| 5257 | 5276 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.7.4" |
| 111 | #define SQLITE_VERSION_NUMBER 3007004 |
| 112 | #define SQLITE_SOURCE_ID "2010-11-16 23:10:26 fd5b2f23dd5111d2f0934dd828bae36b755024c1" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -540,10 +540,22 @@ | |
| 540 | ** sync operation only needs to flush data to mass storage. Inode |
| 541 | ** information need not be flushed. If the lower four bits of the flag |
| 542 | ** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. |
| 543 | ** If the lower four bits equal SQLITE_SYNC_FULL, that means |
| 544 | ** to use Mac OS X style fullsync instead of fsync(). |
| 545 | */ |
| 546 | #define SQLITE_SYNC_NORMAL 0x00002 |
| 547 | #define SQLITE_SYNC_FULL 0x00003 |
| 548 | #define SQLITE_SYNC_DATAONLY 0x00010 |
| 549 | |
| @@ -708,10 +720,12 @@ | |
| 708 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 709 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 710 | #define SQLITE_LAST_ERRNO 4 |
| 711 | #define SQLITE_FCNTL_SIZE_HINT 5 |
| 712 | #define SQLITE_FCNTL_CHUNK_SIZE 6 |
| 713 | |
| 714 | /* |
| 715 | ** CAPI3REF: Mutex Handle |
| 716 | ** |
| 717 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -2635,18 +2649,17 @@ | |
| 2635 | |
| 2636 | /* |
| 2637 | ** CAPI3REF: Determine If An SQL Statement Writes The Database |
| 2638 | ** |
| 2639 | ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if |
| 2640 | ** the [prepared statement] X is guaranteed to leave the database file |
| 2641 | ** unmodified. ^If the sqlite3_stmt_readonly(X) interface returns false (zero) |
| 2642 | ** then evaluating the statement might change the database file, but this |
| 2643 | ** is not guaranteed as the write operation might be conditional and the |
| 2644 | ** condition might not be met. ^If X is a NULL pointer then |
| 2645 | ** sqlite3_stmt_readonly(X) returns true. If X is a non-NULL pointer but |
| 2646 | ** is not a pointer to a valid, unfinalized prepared statement, then the |
| 2647 | ** behavior is undefined and probably harmful. |
| 2648 | */ |
| 2649 | SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); |
| 2650 | |
| 2651 | /* |
| 2652 | ** CAPI3REF: Dynamically Typed Value Object |
| @@ -5238,19 +5251,25 @@ | |
| 5238 | ** CAPI3REF: Low-Level Control Of Database Files |
| 5239 | ** |
| 5240 | ** ^The [sqlite3_file_control()] interface makes a direct call to the |
| 5241 | ** xFileControl method for the [sqlite3_io_methods] object associated |
| 5242 | ** with a particular database identified by the second argument. ^The |
| 5243 | ** name of the database "main" for the main database or "temp" for the |
| 5244 | ** TEMP database, or the name that appears after the AS keyword for |
| 5245 | ** databases that are added using the [ATTACH] SQL command. |
| 5246 | ** ^A NULL pointer can be used in place of "main" to refer to the |
| 5247 | ** main database file. |
| 5248 | ** ^The third and fourth parameters to this routine |
| 5249 | ** are passed directly through to the second and third parameters of |
| 5250 | ** the xFileControl method. ^The return value of the xFileControl |
| 5251 | ** method becomes the return value of this routine. |
| 5252 | ** |
| 5253 | ** ^If the second parameter (zDbName) does not match the name of any |
| 5254 | ** open database file, then SQLITE_ERROR is returned. ^This error |
| 5255 | ** code is not remembered and will not be recalled by [sqlite3_errcode()] |
| 5256 | ** or [sqlite3_errmsg()]. The underlying xFileControl method might |
| 5257 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.7.4" |
| 111 | #define SQLITE_VERSION_NUMBER 3007004 |
| 112 | #define SQLITE_SOURCE_ID "2010-11-26 16:49:59 c412f61229b6ab1ac90b932afd56f7c5e3ba1cfe" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -540,10 +540,22 @@ | |
| 540 | ** sync operation only needs to flush data to mass storage. Inode |
| 541 | ** information need not be flushed. If the lower four bits of the flag |
| 542 | ** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. |
| 543 | ** If the lower four bits equal SQLITE_SYNC_FULL, that means |
| 544 | ** to use Mac OS X style fullsync instead of fsync(). |
| 545 | ** |
| 546 | ** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags |
| 547 | ** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL |
| 548 | ** settings. The [synchronous pragma] determines when calls to the |
| 549 | ** xSync VFS method occur and applies uniformly across all platforms. |
| 550 | ** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how |
| 551 | ** energetic or rigorous or forceful the sync operations are and |
| 552 | ** only make a difference on Mac OSX for the default SQLite code. |
| 553 | ** (Third-party VFS implementations might also make the distinction |
| 554 | ** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the |
| 555 | ** operating systems natively supported by SQLite, only Mac OSX |
| 556 | ** cares about the difference.) |
| 557 | */ |
| 558 | #define SQLITE_SYNC_NORMAL 0x00002 |
| 559 | #define SQLITE_SYNC_FULL 0x00003 |
| 560 | #define SQLITE_SYNC_DATAONLY 0x00010 |
| 561 | |
| @@ -708,10 +720,12 @@ | |
| 720 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 721 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 722 | #define SQLITE_LAST_ERRNO 4 |
| 723 | #define SQLITE_FCNTL_SIZE_HINT 5 |
| 724 | #define SQLITE_FCNTL_CHUNK_SIZE 6 |
| 725 | #define SQLITE_FCNTL_FILE_POINTER 7 |
| 726 | |
| 727 | |
| 728 | /* |
| 729 | ** CAPI3REF: Mutex Handle |
| 730 | ** |
| 731 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -2635,18 +2649,17 @@ | |
| 2649 | |
| 2650 | /* |
| 2651 | ** CAPI3REF: Determine If An SQL Statement Writes The Database |
| 2652 | ** |
| 2653 | ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if |
| 2654 | ** the [prepared statement] X is [SELECT] statement and false (zero) if |
| 2655 | ** X is an [INSERT], [UPDATE], [DELETE], CREATE, DROP, [ANALYZE], |
| 2656 | ** [ALTER], or [REINDEX] statement. |
| 2657 | ** If X is a NULL pointer or any other kind of statement, including but |
| 2658 | ** not limited to [ATTACH], [DETACH], [COMMIT], [ROLLBACK], [RELEASE], |
| 2659 | ** [SAVEPOINT], [PRAGMA], or [VACUUM] the result of sqlite3_stmt_readonly(X) is |
| 2660 | ** undefined. |
| 2661 | */ |
| 2662 | SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); |
| 2663 | |
| 2664 | /* |
| 2665 | ** CAPI3REF: Dynamically Typed Value Object |
| @@ -5238,19 +5251,25 @@ | |
| 5251 | ** CAPI3REF: Low-Level Control Of Database Files |
| 5252 | ** |
| 5253 | ** ^The [sqlite3_file_control()] interface makes a direct call to the |
| 5254 | ** xFileControl method for the [sqlite3_io_methods] object associated |
| 5255 | ** with a particular database identified by the second argument. ^The |
| 5256 | ** name of the database is "main" for the main database or "temp" for the |
| 5257 | ** TEMP database, or the name that appears after the AS keyword for |
| 5258 | ** databases that are added using the [ATTACH] SQL command. |
| 5259 | ** ^A NULL pointer can be used in place of "main" to refer to the |
| 5260 | ** main database file. |
| 5261 | ** ^The third and fourth parameters to this routine |
| 5262 | ** are passed directly through to the second and third parameters of |
| 5263 | ** the xFileControl method. ^The return value of the xFileControl |
| 5264 | ** method becomes the return value of this routine. |
| 5265 | ** |
| 5266 | ** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes |
| 5267 | ** a pointer to the underlying [sqlite3_file] object to be written into |
| 5268 | ** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER |
| 5269 | ** case is a short-circuit path which does not actually invoke the |
| 5270 | ** underlying sqlite3_io_methods.xFileControl method. |
| 5271 | ** |
| 5272 | ** ^If the second parameter (zDbName) does not match the name of any |
| 5273 | ** open database file, then SQLITE_ERROR is returned. ^This error |
| 5274 | ** code is not remembered and will not be recalled by [sqlite3_errcode()] |
| 5275 | ** or [sqlite3_errmsg()]. The underlying xFileControl method might |
| 5276 |