Fossil SCM
Pull in the latest version 3.7.11-alpha of SQLite.
Commit
77e36ef611f65ff6639910934f6b1d584fafe537
Parent
73038baaa3028e0…
2 files changed
+623
-263
+51
-6
+623
-263
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -657,11 +657,11 @@ | ||
| 657 | 657 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 658 | 658 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 659 | 659 | */ |
| 660 | 660 | #define SQLITE_VERSION "3.7.11" |
| 661 | 661 | #define SQLITE_VERSION_NUMBER 3007011 |
| 662 | -#define SQLITE_SOURCE_ID "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130" | |
| 662 | +#define SQLITE_SOURCE_ID "2012-03-16 00:28:11 74eadeec34c4b19cf5f8b7f648db3b7ad601a00e" | |
| 663 | 663 | |
| 664 | 664 | /* |
| 665 | 665 | ** CAPI3REF: Run-Time Library Version Numbers |
| 666 | 666 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 667 | 667 | ** |
| @@ -1009,10 +1009,11 @@ | ||
| 1009 | 1009 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 1010 | 1010 | #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) |
| 1011 | 1011 | #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) |
| 1012 | 1012 | #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) |
| 1013 | 1013 | #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) |
| 1014 | +#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) | |
| 1014 | 1015 | |
| 1015 | 1016 | /* |
| 1016 | 1017 | ** CAPI3REF: Flags For File Open Operations |
| 1017 | 1018 | ** |
| 1018 | 1019 | ** These bit values are intended for use in the |
| @@ -1264,31 +1265,35 @@ | ||
| 1264 | 1265 | ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], |
| 1265 | 1266 | ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) |
| 1266 | 1267 | ** into an integer that the pArg argument points to. This capability |
| 1267 | 1268 | ** is used during testing and only needs to be supported when SQLITE_TEST |
| 1268 | 1269 | ** is defined. |
| 1269 | -** | |
| 1270 | +** <ul> | |
| 1271 | +** <li>[[SQLITE_FCNTL_SIZE_HINT]] | |
| 1270 | 1272 | ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS |
| 1271 | 1273 | ** layer a hint of how large the database file will grow to be during the |
| 1272 | 1274 | ** current transaction. This hint is not guaranteed to be accurate but it |
| 1273 | 1275 | ** is often close. The underlying VFS might choose to preallocate database |
| 1274 | 1276 | ** file space based on this hint in order to help writes to the database |
| 1275 | 1277 | ** file run faster. |
| 1276 | 1278 | ** |
| 1279 | +** <li>[[SQLITE_FCNTL_CHUNK_SIZE]] | |
| 1277 | 1280 | ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS |
| 1278 | 1281 | ** extends and truncates the database file in chunks of a size specified |
| 1279 | 1282 | ** by the user. The fourth argument to [sqlite3_file_control()] should |
| 1280 | 1283 | ** point to an integer (type int) containing the new chunk-size to use |
| 1281 | 1284 | ** for the nominated database. Allocating database file space in large |
| 1282 | 1285 | ** chunks (say 1MB at a time), may reduce file-system fragmentation and |
| 1283 | 1286 | ** improve performance on some systems. |
| 1284 | 1287 | ** |
| 1288 | +** <li>[[SQLITE_FCNTL_FILE_POINTER]] | |
| 1285 | 1289 | ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer |
| 1286 | 1290 | ** to the [sqlite3_file] object associated with a particular database |
| 1287 | 1291 | ** connection. See the [sqlite3_file_control()] documentation for |
| 1288 | 1292 | ** additional information. |
| 1289 | 1293 | ** |
| 1294 | +** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] | |
| 1290 | 1295 | ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by |
| 1291 | 1296 | ** SQLite and sent to all VFSes in place of a call to the xSync method |
| 1292 | 1297 | ** when the database connection has [PRAGMA synchronous] set to OFF.)^ |
| 1293 | 1298 | ** Some specialized VFSes need this signal in order to operate correctly |
| 1294 | 1299 | ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most |
| @@ -1295,10 +1300,11 @@ | ||
| 1295 | 1300 | ** VFSes do not need this signal and should silently ignore this opcode. |
| 1296 | 1301 | ** Applications should not call [sqlite3_file_control()] with this |
| 1297 | 1302 | ** opcode as doing so may disrupt the operation of the specialized VFSes |
| 1298 | 1303 | ** that do require it. |
| 1299 | 1304 | ** |
| 1305 | +** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]] | |
| 1300 | 1306 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 1301 | 1307 | ** retry counts and intervals for certain disk I/O operations for the |
| 1302 | 1308 | ** windows [VFS] in order to provide robustness in the presence of |
| 1303 | 1309 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 1304 | 1310 | ** file write, and file delete operations up to 10 times, with a delay |
| @@ -1311,10 +1317,11 @@ | ||
| 1311 | 1317 | ** integer is the delay. If either integer is negative, then the setting |
| 1312 | 1318 | ** is not changed but instead the prior value of that setting is written |
| 1313 | 1319 | ** into the array entry, allowing the current retry settings to be |
| 1314 | 1320 | ** interrogated. The zDbName parameter is ignored. |
| 1315 | 1321 | ** |
| 1322 | +** <li>[[SQLITE_FCNTL_PERSIST_WAL]] | |
| 1316 | 1323 | ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the |
| 1317 | 1324 | ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary |
| 1318 | 1325 | ** write ahead log and shared memory files used for transaction control |
| 1319 | 1326 | ** are automatically deleted when the latest connection to the database |
| 1320 | 1327 | ** closes. Setting persistent WAL mode causes those files to persist after |
| @@ -1325,24 +1332,27 @@ | ||
| 1325 | 1332 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 1326 | 1333 | ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent |
| 1327 | 1334 | ** WAL mode. If the integer is -1, then it is overwritten with the current |
| 1328 | 1335 | ** WAL persistence setting. |
| 1329 | 1336 | ** |
| 1337 | +** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] | |
| 1330 | 1338 | ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the |
| 1331 | 1339 | ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting |
| 1332 | 1340 | ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the |
| 1333 | 1341 | ** xDeviceCharacteristics methods. The fourth parameter to |
| 1334 | 1342 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 1335 | 1343 | ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage |
| 1336 | 1344 | ** mode. If the integer is -1, then it is overwritten with the current |
| 1337 | 1345 | ** zero-damage mode setting. |
| 1338 | 1346 | ** |
| 1347 | +** <li>[[SQLITE_FCNTL_OVERWRITE]] | |
| 1339 | 1348 | ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening |
| 1340 | 1349 | ** a write transaction to indicate that, unless it is rolled back for some |
| 1341 | 1350 | ** reason, the entire database file will be overwritten by the current |
| 1342 | 1351 | ** transaction. This is used by VACUUM operations. |
| 1343 | 1352 | ** |
| 1353 | +** <li>[[SQLITE_FCNTL_VFSNAME]] | |
| 1344 | 1354 | ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of |
| 1345 | 1355 | ** all [VFSes] in the VFS stack. The names are of all VFS shims and the |
| 1346 | 1356 | ** final bottom-level VFS are written into memory obtained from |
| 1347 | 1357 | ** [sqlite3_malloc()] and the result is stored in the char* variable |
| 1348 | 1358 | ** that the fourth parameter of [sqlite3_file_control()] points to. |
| @@ -1349,10 +1359,34 @@ | ||
| 1349 | 1359 | ** The caller is responsible for freeing the memory when done. As with |
| 1350 | 1360 | ** all file-control actions, there is no guarantee that this will actually |
| 1351 | 1361 | ** do anything. Callers should initialize the char* variable to a NULL |
| 1352 | 1362 | ** pointer in case this file-control is not implemented. This file-control |
| 1353 | 1363 | ** is intended for diagnostic use only. |
| 1364 | +** | |
| 1365 | +** <li>[[SQLITE_FCNTL_PRAGMA]] | |
| 1366 | +** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] | |
| 1367 | +** file control is sent to the open [sqlite3_file] object corresponding | |
| 1368 | +** to the database file to which the pragma statement refers. ^The argument | |
| 1369 | +** to the [SQLITE_FCNTL_PRAGMA] file control is an array of | |
| 1370 | +** pointers to strings (char**) in which the second element of the array | |
| 1371 | +** is the name of the pragma and the third element is the argument to the | |
| 1372 | +** pragma or NULL if the pragma has no argument. ^The handler for an | |
| 1373 | +** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element | |
| 1374 | +** of the char** argument point to a string obtained from [sqlite3_mprintf()] | |
| 1375 | +** or the equivalent and that string will become the result of the pragma or | |
| 1376 | +** the error message if the pragma fails. ^If the | |
| 1377 | +** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal | |
| 1378 | +** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] | |
| 1379 | +** file control returns [SQLITE_OK], then the parser assumes that the | |
| 1380 | +** VFS has handled the PRAGMA itself and the parser generates a no-op | |
| 1381 | +** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns | |
| 1382 | +** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means | |
| 1383 | +** that the VFS encountered an error while handling the [PRAGMA] and the | |
| 1384 | +** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] | |
| 1385 | +** file control occurs at the beginning of pragma statement analysis and so | |
| 1386 | +** it is able to override built-in [PRAGMA] statements. | |
| 1387 | +** </ul> | |
| 1354 | 1388 | */ |
| 1355 | 1389 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 1356 | 1390 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 1357 | 1391 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 1358 | 1392 | #define SQLITE_LAST_ERRNO 4 |
| @@ -1363,10 +1397,11 @@ | ||
| 1363 | 1397 | #define SQLITE_FCNTL_WIN32_AV_RETRY 9 |
| 1364 | 1398 | #define SQLITE_FCNTL_PERSIST_WAL 10 |
| 1365 | 1399 | #define SQLITE_FCNTL_OVERWRITE 11 |
| 1366 | 1400 | #define SQLITE_FCNTL_VFSNAME 12 |
| 1367 | 1401 | #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 |
| 1402 | +#define SQLITE_FCNTL_PRAGMA 14 | |
| 1368 | 1403 | |
| 1369 | 1404 | /* |
| 1370 | 1405 | ** CAPI3REF: Mutex Handle |
| 1371 | 1406 | ** |
| 1372 | 1407 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -5012,10 +5047,19 @@ | ||
| 5012 | 5047 | ** will be an absolute pathname, even if the filename used |
| 5013 | 5048 | ** to open the database originally was a URI or relative pathname. |
| 5014 | 5049 | */ |
| 5015 | 5050 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); |
| 5016 | 5051 | |
| 5052 | +/* | |
| 5053 | +** CAPI3REF: Determine if a database is read-only | |
| 5054 | +** | |
| 5055 | +** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N | |
| 5056 | +** of connection D is read-only, 0 if it is read/write, or -1 if N is not | |
| 5057 | +** the name of a database on connection D. | |
| 5058 | +*/ | |
| 5059 | +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); | |
| 5060 | + | |
| 5017 | 5061 | /* |
| 5018 | 5062 | ** CAPI3REF: Find the next prepared statement |
| 5019 | 5063 | ** |
| 5020 | 5064 | ** ^This interface returns a pointer to the next [prepared statement] after |
| 5021 | 5065 | ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL |
| @@ -7137,15 +7181,16 @@ | ||
| 7137 | 7181 | |
| 7138 | 7182 | |
| 7139 | 7183 | /* |
| 7140 | 7184 | ** CAPI3REF: String Comparison |
| 7141 | 7185 | ** |
| 7142 | -** ^The [sqlite3_strnicmp()] API allows applications and extensions to | |
| 7143 | -** compare the contents of two buffers containing UTF-8 strings in a | |
| 7144 | -** case-independent fashion, using the same definition of case independence | |
| 7145 | -** that SQLite uses internally when comparing identifiers. | |
| 7186 | +** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications | |
| 7187 | +** and extensions to compare the contents of two buffers containing UTF-8 | |
| 7188 | +** strings in a case-independent fashion, using the same definition of "case | |
| 7189 | +** independence" that SQLite uses internally when comparing identifiers. | |
| 7146 | 7190 | */ |
| 7191 | +SQLITE_API int sqlite3_stricmp(const char *, const char *); | |
| 7147 | 7192 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 7148 | 7193 | |
| 7149 | 7194 | /* |
| 7150 | 7195 | ** CAPI3REF: Error Logging Interface |
| 7151 | 7196 | ** |
| @@ -8204,11 +8249,11 @@ | ||
| 8204 | 8249 | SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); |
| 8205 | 8250 | SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); |
| 8206 | 8251 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); |
| 8207 | 8252 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); |
| 8208 | 8253 | SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); |
| 8209 | -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*); | |
| 8254 | +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int); | |
| 8210 | 8255 | SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); |
| 8211 | 8256 | SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); |
| 8212 | 8257 | SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); |
| 8213 | 8258 | SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); |
| 8214 | 8259 | SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); |
| @@ -8944,10 +8989,13 @@ | ||
| 8944 | 8989 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); |
| 8945 | 8990 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 8946 | 8991 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 8947 | 8992 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 8948 | 8993 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); |
| 8994 | +#ifdef SQLITE_ENABLE_ZIPVFS | |
| 8995 | +SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); | |
| 8996 | +#endif | |
| 8949 | 8997 | |
| 8950 | 8998 | /* Functions used to query pager state and configuration. */ |
| 8951 | 8999 | SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); |
| 8952 | 9000 | SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| 8953 | 9001 | SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); |
| @@ -11415,11 +11463,11 @@ | ||
| 11415 | 11463 | #endif |
| 11416 | 11464 | |
| 11417 | 11465 | /* |
| 11418 | 11466 | ** Internal function prototypes |
| 11419 | 11467 | */ |
| 11420 | -SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *); | |
| 11468 | +#define sqlite3StrICmp sqlite3_stricmp | |
| 11421 | 11469 | SQLITE_PRIVATE int sqlite3Strlen30(const char*); |
| 11422 | 11470 | #define sqlite3StrNICmp sqlite3_strnicmp |
| 11423 | 11471 | |
| 11424 | 11472 | SQLITE_PRIVATE int sqlite3MallocInit(void); |
| 11425 | 11473 | SQLITE_PRIVATE void sqlite3MallocEnd(void); |
| @@ -11563,10 +11611,11 @@ | ||
| 11563 | 11611 | SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*); |
| 11564 | 11612 | SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); |
| 11565 | 11613 | SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*); |
| 11566 | 11614 | SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, |
| 11567 | 11615 | sqlite3_vfs**,char**,char **); |
| 11616 | +SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); | |
| 11568 | 11617 | SQLITE_PRIVATE int sqlite3CodeOnce(Parse *); |
| 11569 | 11618 | |
| 11570 | 11619 | SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32); |
| 11571 | 11620 | SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32); |
| 11572 | 11621 | SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); |
| @@ -11662,11 +11711,11 @@ | ||
| 11662 | 11711 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); |
| 11663 | 11712 | SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); |
| 11664 | 11713 | SQLITE_PRIVATE void sqlite3PrngSaveState(void); |
| 11665 | 11714 | SQLITE_PRIVATE void sqlite3PrngRestoreState(void); |
| 11666 | 11715 | SQLITE_PRIVATE void sqlite3PrngResetState(void); |
| 11667 | -SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*); | |
| 11716 | +SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); | |
| 11668 | 11717 | SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); |
| 11669 | 11718 | SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); |
| 11670 | 11719 | SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int); |
| 11671 | 11720 | SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*); |
| 11672 | 11721 | SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*); |
| @@ -21216,11 +21265,11 @@ | ||
| 21216 | 21265 | ** applications and extensions to compare the contents of two buffers |
| 21217 | 21266 | ** containing UTF-8 strings in a case-independent fashion, using the same |
| 21218 | 21267 | ** definition of case independence that SQLite uses internally when |
| 21219 | 21268 | ** comparing identifiers. |
| 21220 | 21269 | */ |
| 21221 | -SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){ | |
| 21270 | +SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){ | |
| 21222 | 21271 | register unsigned char *a, *b; |
| 21223 | 21272 | a = (unsigned char *)zLeft; |
| 21224 | 21273 | b = (unsigned char *)zRight; |
| 21225 | 21274 | while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } |
| 21226 | 21275 | return UpperToLower[*a] - UpperToLower[*b]; |
| @@ -25494,11 +25543,11 @@ | ||
| 25494 | 25543 | ** recover the hot journals. |
| 25495 | 25544 | */ |
| 25496 | 25545 | static int robust_open(const char *z, int f, mode_t m){ |
| 25497 | 25546 | int rc; |
| 25498 | 25547 | mode_t m2; |
| 25499 | - mode_t origM; | |
| 25548 | + mode_t origM = 0; | |
| 25500 | 25549 | if( m==0 ){ |
| 25501 | 25550 | m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; |
| 25502 | 25551 | }else{ |
| 25503 | 25552 | m2 = m; |
| 25504 | 25553 | origM = osUmask(0); |
| @@ -38302,10 +38351,11 @@ | ||
| 38302 | 38351 | # define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 38303 | 38352 | # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 |
| 38304 | 38353 | # define sqlite3WalCallback(z) 0 |
| 38305 | 38354 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 38306 | 38355 | # define sqlite3WalHeapMemory(z) 0 |
| 38356 | +# define sqlite3WalFramesize(z) 0 | |
| 38307 | 38357 | #else |
| 38308 | 38358 | |
| 38309 | 38359 | #define WAL_SAVEPOINT_NDATA 4 |
| 38310 | 38360 | |
| 38311 | 38361 | /* Connection to a write-ahead log (WAL) file. |
| @@ -38382,10 +38432,17 @@ | ||
| 38382 | 38432 | /* Return true if the argument is non-NULL and the WAL module is using |
| 38383 | 38433 | ** heap-memory for the wal-index. Otherwise, if the argument is NULL or the |
| 38384 | 38434 | ** WAL module is using shared-memory, return false. |
| 38385 | 38435 | */ |
| 38386 | 38436 | SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); |
| 38437 | + | |
| 38438 | +#ifdef SQLITE_ENABLE_ZIPVFS | |
| 38439 | +/* If the WAL file is not empty, return the number of bytes of content | |
| 38440 | +** stored in each frame (i.e. the db page-size when the WAL was created). | |
| 38441 | +*/ | |
| 38442 | +SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal); | |
| 38443 | +#endif | |
| 38387 | 38444 | |
| 38388 | 38445 | #endif /* ifndef SQLITE_OMIT_WAL */ |
| 38389 | 38446 | #endif /* _WAL_H_ */ |
| 38390 | 38447 | |
| 38391 | 38448 | /************** End of wal.h *************************************************/ |
| @@ -45237,10 +45294,24 @@ | ||
| 45237 | 45294 | pPager->pWal = 0; |
| 45238 | 45295 | } |
| 45239 | 45296 | } |
| 45240 | 45297 | return rc; |
| 45241 | 45298 | } |
| 45299 | + | |
| 45300 | +#ifdef SQLITE_ENABLE_ZIPVFS | |
| 45301 | +/* | |
| 45302 | +** A read-lock must be held on the pager when this function is called. If | |
| 45303 | +** the pager is in WAL mode and the WAL file currently contains one or more | |
| 45304 | +** frames, return the size in bytes of the page images stored within the | |
| 45305 | +** WAL frames. Otherwise, if this is not a WAL database or the WAL file | |
| 45306 | +** is empty, return 0. | |
| 45307 | +*/ | |
| 45308 | +SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ | |
| 45309 | + assert( pPager->eState==PAGER_READER ); | |
| 45310 | + return sqlite3WalFramesize(pPager->pWal); | |
| 45311 | +} | |
| 45312 | +#endif | |
| 45242 | 45313 | |
| 45243 | 45314 | #ifdef SQLITE_HAS_CODEC |
| 45244 | 45315 | /* |
| 45245 | 45316 | ** This function is called by the wal module when writing page content |
| 45246 | 45317 | ** into the log file. |
| @@ -47657,11 +47728,11 @@ | ||
| 47657 | 47728 | testcase( sz<=32768 ); |
| 47658 | 47729 | testcase( sz>=65536 ); |
| 47659 | 47730 | iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; |
| 47660 | 47731 | *pInWal = 1; |
| 47661 | 47732 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ |
| 47662 | - return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset); | |
| 47733 | + return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset); | |
| 47663 | 47734 | } |
| 47664 | 47735 | |
| 47665 | 47736 | *pInWal = 0; |
| 47666 | 47737 | return SQLITE_OK; |
| 47667 | 47738 | } |
| @@ -48327,10 +48398,22 @@ | ||
| 48327 | 48398 | ** WAL module is using shared-memory, return false. |
| 48328 | 48399 | */ |
| 48329 | 48400 | SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ |
| 48330 | 48401 | return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ); |
| 48331 | 48402 | } |
| 48403 | + | |
| 48404 | +#ifdef SQLITE_ENABLE_ZIPVFS | |
| 48405 | +/* | |
| 48406 | +** If the argument is not NULL, it points to a Wal object that holds a | |
| 48407 | +** read-lock. This function returns the database page-size if it is known, | |
| 48408 | +** or zero if it is not (or if pWal is NULL). | |
| 48409 | +*/ | |
| 48410 | +SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){ | |
| 48411 | + assert( pWal==0 || pWal->readLock>=0 ); | |
| 48412 | + return (pWal ? pWal->szPage : 0); | |
| 48413 | +} | |
| 48414 | +#endif | |
| 48332 | 48415 | |
| 48333 | 48416 | #endif /* #ifndef SQLITE_OMIT_WAL */ |
| 48334 | 48417 | |
| 48335 | 48418 | /************** End of wal.c *************************************************/ |
| 48336 | 48419 | /************** Begin file btmutex.c *****************************************/ |
| @@ -51320,11 +51403,11 @@ | ||
| 51320 | 51403 | |
| 51321 | 51404 | /* Rollback any active transaction and free the handle structure. |
| 51322 | 51405 | ** The call to sqlite3BtreeRollback() drops any table-locks held by |
| 51323 | 51406 | ** this handle. |
| 51324 | 51407 | */ |
| 51325 | - sqlite3BtreeRollback(p); | |
| 51408 | + sqlite3BtreeRollback(p, SQLITE_OK); | |
| 51326 | 51409 | sqlite3BtreeLeave(p); |
| 51327 | 51410 | |
| 51328 | 51411 | /* If there are still other outstanding references to the shared-btree |
| 51329 | 51412 | ** structure, return now. The remainder of this procedure cleans |
| 51330 | 51413 | ** up the shared-btree. |
| @@ -52558,10 +52641,11 @@ | ||
| 52558 | 52641 | ** save the state of the cursor. The cursor must be |
| 52559 | 52642 | ** invalidated. |
| 52560 | 52643 | */ |
| 52561 | 52644 | SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ |
| 52562 | 52645 | BtCursor *p; |
| 52646 | + if( pBtree==0 ) return; | |
| 52563 | 52647 | sqlite3BtreeEnter(pBtree); |
| 52564 | 52648 | for(p=pBtree->pBt->pCursor; p; p=p->pNext){ |
| 52565 | 52649 | int i; |
| 52566 | 52650 | sqlite3BtreeClearCursor(p); |
| 52567 | 52651 | p->eState = CURSOR_FAULT; |
| @@ -52581,29 +52665,24 @@ | ||
| 52581 | 52665 | ** in an error. |
| 52582 | 52666 | ** |
| 52583 | 52667 | ** This will release the write lock on the database file. If there |
| 52584 | 52668 | ** are no active cursors, it also releases the read lock. |
| 52585 | 52669 | */ |
| 52586 | -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p){ | |
| 52670 | +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){ | |
| 52587 | 52671 | int rc; |
| 52588 | 52672 | BtShared *pBt = p->pBt; |
| 52589 | 52673 | MemPage *pPage1; |
| 52590 | 52674 | |
| 52591 | 52675 | sqlite3BtreeEnter(p); |
| 52592 | - rc = saveAllCursors(pBt, 0, 0); | |
| 52593 | -#ifndef SQLITE_OMIT_SHARED_CACHE | |
| 52594 | - if( rc!=SQLITE_OK ){ | |
| 52595 | - /* This is a horrible situation. An IO or malloc() error occurred whilst | |
| 52596 | - ** trying to save cursor positions. If this is an automatic rollback (as | |
| 52597 | - ** the result of a constraint, malloc() failure or IO error) then | |
| 52598 | - ** the cache may be internally inconsistent (not contain valid trees) so | |
| 52599 | - ** we cannot simply return the error to the caller. Instead, abort | |
| 52600 | - ** all queries that may be using any of the cursors that failed to save. | |
| 52601 | - */ | |
| 52602 | - sqlite3BtreeTripAllCursors(p, rc); | |
| 52603 | - } | |
| 52604 | -#endif | |
| 52676 | + if( tripCode==SQLITE_OK ){ | |
| 52677 | + rc = tripCode = saveAllCursors(pBt, 0, 0); | |
| 52678 | + }else{ | |
| 52679 | + rc = SQLITE_OK; | |
| 52680 | + } | |
| 52681 | + if( tripCode ){ | |
| 52682 | + sqlite3BtreeTripAllCursors(p, tripCode); | |
| 52683 | + } | |
| 52605 | 52684 | btreeIntegrity(p); |
| 52606 | 52685 | |
| 52607 | 52686 | if( p->inTrans==TRANS_WRITE ){ |
| 52608 | 52687 | int rc2; |
| 52609 | 52688 | |
| @@ -58121,11 +58200,11 @@ | ||
| 58121 | 58200 | } |
| 58122 | 58201 | *pp = p->pNext; |
| 58123 | 58202 | } |
| 58124 | 58203 | |
| 58125 | 58204 | /* If a transaction is still open on the Btree, roll it back. */ |
| 58126 | - sqlite3BtreeRollback(p->pDest); | |
| 58205 | + sqlite3BtreeRollback(p->pDest, SQLITE_OK); | |
| 58127 | 58206 | |
| 58128 | 58207 | /* Set the error code of the destination database handle. */ |
| 58129 | 58208 | rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; |
| 58130 | 58209 | sqlite3Error(p->pDestDb, rc, 0); |
| 58131 | 58210 | |
| @@ -61431,36 +61510,10 @@ | ||
| 61431 | 61510 | } |
| 61432 | 61511 | #else |
| 61433 | 61512 | #define checkActiveVdbeCnt(x) |
| 61434 | 61513 | #endif |
| 61435 | 61514 | |
| 61436 | -/* | |
| 61437 | -** For every Btree that in database connection db which | |
| 61438 | -** has been modified, "trip" or invalidate each cursor in | |
| 61439 | -** that Btree might have been modified so that the cursor | |
| 61440 | -** can never be used again. This happens when a rollback | |
| 61441 | -*** occurs. We have to trip all the other cursors, even | |
| 61442 | -** cursor from other VMs in different database connections, | |
| 61443 | -** so that none of them try to use the data at which they | |
| 61444 | -** were pointing and which now may have been changed due | |
| 61445 | -** to the rollback. | |
| 61446 | -** | |
| 61447 | -** Remember that a rollback can delete tables complete and | |
| 61448 | -** reorder rootpages. So it is not sufficient just to save | |
| 61449 | -** the state of the cursor. We have to invalidate the cursor | |
| 61450 | -** so that it is never used again. | |
| 61451 | -*/ | |
| 61452 | -static void invalidateCursorsOnModifiedBtrees(sqlite3 *db){ | |
| 61453 | - int i; | |
| 61454 | - for(i=0; i<db->nDb; i++){ | |
| 61455 | - Btree *p = db->aDb[i].pBt; | |
| 61456 | - if( p && sqlite3BtreeIsInTrans(p) ){ | |
| 61457 | - sqlite3BtreeTripAllCursors(p, SQLITE_ABORT); | |
| 61458 | - } | |
| 61459 | - } | |
| 61460 | -} | |
| 61461 | - | |
| 61462 | 61515 | /* |
| 61463 | 61516 | ** If the Vdbe passed as the first argument opened a statement-transaction, |
| 61464 | 61517 | ** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or |
| 61465 | 61518 | ** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement |
| 61466 | 61519 | ** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the |
| @@ -61621,12 +61674,11 @@ | ||
| 61621 | 61674 | eStatementOp = SAVEPOINT_ROLLBACK; |
| 61622 | 61675 | }else{ |
| 61623 | 61676 | /* We are forced to roll back the active transaction. Before doing |
| 61624 | 61677 | ** so, abort any other statements this handle currently has active. |
| 61625 | 61678 | */ |
| 61626 | - invalidateCursorsOnModifiedBtrees(db); | |
| 61627 | - sqlite3RollbackAll(db); | |
| 61679 | + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); | |
| 61628 | 61680 | sqlite3CloseSavepoints(db); |
| 61629 | 61681 | db->autoCommit = 1; |
| 61630 | 61682 | } |
| 61631 | 61683 | } |
| 61632 | 61684 | } |
| @@ -61664,27 +61716,26 @@ | ||
| 61664 | 61716 | if( rc==SQLITE_BUSY && p->readOnly ){ |
| 61665 | 61717 | sqlite3VdbeLeave(p); |
| 61666 | 61718 | return SQLITE_BUSY; |
| 61667 | 61719 | }else if( rc!=SQLITE_OK ){ |
| 61668 | 61720 | p->rc = rc; |
| 61669 | - sqlite3RollbackAll(db); | |
| 61721 | + sqlite3RollbackAll(db, SQLITE_OK); | |
| 61670 | 61722 | }else{ |
| 61671 | 61723 | db->nDeferredCons = 0; |
| 61672 | 61724 | sqlite3CommitInternalChanges(db); |
| 61673 | 61725 | } |
| 61674 | 61726 | }else{ |
| 61675 | - sqlite3RollbackAll(db); | |
| 61727 | + sqlite3RollbackAll(db, SQLITE_OK); | |
| 61676 | 61728 | } |
| 61677 | 61729 | db->nStatement = 0; |
| 61678 | 61730 | }else if( eStatementOp==0 ){ |
| 61679 | 61731 | if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ |
| 61680 | 61732 | eStatementOp = SAVEPOINT_RELEASE; |
| 61681 | 61733 | }else if( p->errorAction==OE_Abort ){ |
| 61682 | 61734 | eStatementOp = SAVEPOINT_ROLLBACK; |
| 61683 | 61735 | }else{ |
| 61684 | - invalidateCursorsOnModifiedBtrees(db); | |
| 61685 | - sqlite3RollbackAll(db); | |
| 61736 | + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); | |
| 61686 | 61737 | sqlite3CloseSavepoints(db); |
| 61687 | 61738 | db->autoCommit = 1; |
| 61688 | 61739 | } |
| 61689 | 61740 | } |
| 61690 | 61741 | |
| @@ -61700,12 +61751,11 @@ | ||
| 61700 | 61751 | if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){ |
| 61701 | 61752 | p->rc = rc; |
| 61702 | 61753 | sqlite3DbFree(db, p->zErrMsg); |
| 61703 | 61754 | p->zErrMsg = 0; |
| 61704 | 61755 | } |
| 61705 | - invalidateCursorsOnModifiedBtrees(db); | |
| 61706 | - sqlite3RollbackAll(db); | |
| 61756 | + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); | |
| 61707 | 61757 | sqlite3CloseSavepoints(db); |
| 61708 | 61758 | db->autoCommit = 1; |
| 61709 | 61759 | } |
| 61710 | 61760 | } |
| 61711 | 61761 | |
| @@ -67513,20 +67563,16 @@ | ||
| 67513 | 67563 | u.ar.iSavepoint++; |
| 67514 | 67564 | } |
| 67515 | 67565 | if( !u.ar.pSavepoint ){ |
| 67516 | 67566 | sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName); |
| 67517 | 67567 | rc = SQLITE_ERROR; |
| 67518 | - }else if( | |
| 67519 | - db->writeVdbeCnt>0 || (u.ar.p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1) | |
| 67520 | - ){ | |
| 67568 | + }else if( db->writeVdbeCnt>0 && u.ar.p1==SAVEPOINT_RELEASE ){ | |
| 67521 | 67569 | /* It is not possible to release (commit) a savepoint if there are |
| 67522 | - ** active write statements. It is not possible to rollback a savepoint | |
| 67523 | - ** if there are any active statements at all. | |
| 67570 | + ** active write statements. | |
| 67524 | 67571 | */ |
| 67525 | 67572 | sqlite3SetString(&p->zErrMsg, db, |
| 67526 | - "cannot %s savepoint - SQL statements in progress", | |
| 67527 | - (u.ar.p1==SAVEPOINT_ROLLBACK ? "rollback": "release") | |
| 67573 | + "cannot release savepoint - SQL statements in progress" | |
| 67528 | 67574 | ); |
| 67529 | 67575 | rc = SQLITE_BUSY; |
| 67530 | 67576 | }else{ |
| 67531 | 67577 | |
| 67532 | 67578 | /* Determine whether or not this is a transaction savepoint. If so, |
| @@ -67547,10 +67593,13 @@ | ||
| 67547 | 67593 | } |
| 67548 | 67594 | db->isTransactionSavepoint = 0; |
| 67549 | 67595 | rc = p->rc; |
| 67550 | 67596 | }else{ |
| 67551 | 67597 | u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1; |
| 67598 | + for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){ | |
| 67599 | + sqlite3BtreeTripAllCursors(db->aDb[u.ar.ii].pBt, SQLITE_ABORT); | |
| 67600 | + } | |
| 67552 | 67601 | for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){ |
| 67553 | 67602 | rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint); |
| 67554 | 67603 | if( rc!=SQLITE_OK ){ |
| 67555 | 67604 | goto abort_due_to_error; |
| 67556 | 67605 | } |
| @@ -67617,29 +67666,32 @@ | ||
| 67617 | 67666 | u.as.turnOnAC = u.as.desiredAutoCommit && !db->autoCommit; |
| 67618 | 67667 | assert( u.as.desiredAutoCommit==1 || u.as.desiredAutoCommit==0 ); |
| 67619 | 67668 | assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 ); |
| 67620 | 67669 | assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ |
| 67621 | 67670 | |
| 67671 | +#if 0 | |
| 67622 | 67672 | if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){ |
| 67623 | 67673 | /* If this instruction implements a ROLLBACK and other VMs are |
| 67624 | 67674 | ** still running, and a transaction is active, return an error indicating |
| 67625 | 67675 | ** that the other VMs must complete first. |
| 67626 | 67676 | */ |
| 67627 | 67677 | sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - " |
| 67628 | 67678 | "SQL statements in progress"); |
| 67629 | 67679 | rc = SQLITE_BUSY; |
| 67630 | - }else if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){ | |
| 67680 | + }else | |
| 67681 | +#endif | |
| 67682 | + if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){ | |
| 67631 | 67683 | /* If this instruction implements a COMMIT and other VMs are writing |
| 67632 | 67684 | ** return an error indicating that the other VMs must complete first. |
| 67633 | 67685 | */ |
| 67634 | 67686 | sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - " |
| 67635 | 67687 | "SQL statements in progress"); |
| 67636 | 67688 | rc = SQLITE_BUSY; |
| 67637 | 67689 | }else if( u.as.desiredAutoCommit!=db->autoCommit ){ |
| 67638 | 67690 | if( u.as.iRollback ){ |
| 67639 | 67691 | assert( u.as.desiredAutoCommit==1 ); |
| 67640 | - sqlite3RollbackAll(db); | |
| 67692 | + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); | |
| 67641 | 67693 | db->autoCommit = 1; |
| 67642 | 67694 | }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ |
| 67643 | 67695 | goto vdbe_return; |
| 67644 | 67696 | }else{ |
| 67645 | 67697 | db->autoCommit = (u8)u.as.desiredAutoCommit; |
| @@ -68701,11 +68753,11 @@ | ||
| 68701 | 68753 | u.bg.v = 1; /* IMP: R-61914-48074 */ |
| 68702 | 68754 | }else{ |
| 68703 | 68755 | assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) ); |
| 68704 | 68756 | rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v); |
| 68705 | 68757 | assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ |
| 68706 | - if( u.bg.v==MAX_ROWID ){ | |
| 68758 | + if( u.bg.v>=MAX_ROWID ){ | |
| 68707 | 68759 | u.bg.pC->useRandomRowid = 1; |
| 68708 | 68760 | }else{ |
| 68709 | 68761 | u.bg.v++; /* IMP: R-29538-34987 */ |
| 68710 | 68762 | } |
| 68711 | 68763 | } |
| @@ -92317,13 +92369,16 @@ | ||
| 92317 | 92369 | char *zLeft = 0; /* Nul-terminated UTF-8 string <id> */ |
| 92318 | 92370 | char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */ |
| 92319 | 92371 | const char *zDb = 0; /* The database name */ |
| 92320 | 92372 | Token *pId; /* Pointer to <id> token */ |
| 92321 | 92373 | int iDb; /* Database index for <database> */ |
| 92322 | - sqlite3 *db = pParse->db; | |
| 92323 | - Db *pDb; | |
| 92324 | - Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); | |
| 92374 | + char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ | |
| 92375 | + int rc; /* return value form SQLITE_FCNTL_PRAGMA */ | |
| 92376 | + sqlite3 *db = pParse->db; /* The database connection */ | |
| 92377 | + Db *pDb; /* The specific database being pragmaed */ | |
| 92378 | + Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); /* Prepared statement */ | |
| 92379 | + | |
| 92325 | 92380 | if( v==0 ) return; |
| 92326 | 92381 | sqlite3VdbeRunOnlyOnce(v); |
| 92327 | 92382 | pParse->nMem = 2; |
| 92328 | 92383 | |
| 92329 | 92384 | /* Interpret the [database.] part of the pragma statement. iDb is the |
| @@ -92350,10 +92405,38 @@ | ||
| 92350 | 92405 | assert( pId2 ); |
| 92351 | 92406 | zDb = pId2->n>0 ? pDb->zName : 0; |
| 92352 | 92407 | if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ |
| 92353 | 92408 | goto pragma_out; |
| 92354 | 92409 | } |
| 92410 | + | |
| 92411 | + /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS | |
| 92412 | + ** connection. If it returns SQLITE_OK, then assume that the VFS | |
| 92413 | + ** handled the pragma and generate a no-op prepared statement. | |
| 92414 | + */ | |
| 92415 | + aFcntl[0] = 0; | |
| 92416 | + aFcntl[1] = zLeft; | |
| 92417 | + aFcntl[2] = zRight; | |
| 92418 | + aFcntl[3] = 0; | |
| 92419 | + rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); | |
| 92420 | + if( rc==SQLITE_OK ){ | |
| 92421 | + if( aFcntl[0] ){ | |
| 92422 | + int mem = ++pParse->nMem; | |
| 92423 | + sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0); | |
| 92424 | + sqlite3VdbeSetNumCols(v, 1); | |
| 92425 | + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC); | |
| 92426 | + sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); | |
| 92427 | + sqlite3_free(aFcntl[0]); | |
| 92428 | + } | |
| 92429 | + }else if( rc!=SQLITE_NOTFOUND ){ | |
| 92430 | + if( aFcntl[0] ){ | |
| 92431 | + sqlite3ErrorMsg(pParse, "%s", aFcntl[0]); | |
| 92432 | + sqlite3_free(aFcntl[0]); | |
| 92433 | + } | |
| 92434 | + pParse->nErr++; | |
| 92435 | + pParse->rc = rc; | |
| 92436 | + }else | |
| 92437 | + | |
| 92355 | 92438 | |
| 92356 | 92439 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
| 92357 | 92440 | /* |
| 92358 | 92441 | ** PRAGMA [database.]default_cache_size |
| 92359 | 92442 | ** PRAGMA [database.]default_cache_size=N |
| @@ -92637,11 +92720,11 @@ | ||
| 92637 | 92720 | /* Call SetAutoVacuum() to set initialize the internal auto and |
| 92638 | 92721 | ** incr-vacuum flags. This is required in case this connection |
| 92639 | 92722 | ** creates the database file. It is important that it is created |
| 92640 | 92723 | ** as an auto-vacuum capable db. |
| 92641 | 92724 | */ |
| 92642 | - int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); | |
| 92725 | + rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); | |
| 92643 | 92726 | if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ |
| 92644 | 92727 | /* When setting the auto_vacuum mode to either "full" or |
| 92645 | 92728 | ** "incremental", write the value of meta[6] in the database |
| 92646 | 92729 | ** file. Before writing to meta[6], check that meta[3] indicates |
| 92647 | 92730 | ** that this really is an auto-vacuum capable database. |
| @@ -92755,11 +92838,10 @@ | ||
| 92755 | 92838 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
| 92756 | 92839 | } |
| 92757 | 92840 | }else{ |
| 92758 | 92841 | #ifndef SQLITE_OMIT_WSD |
| 92759 | 92842 | if( zRight[0] ){ |
| 92760 | - int rc; | |
| 92761 | 92843 | int res; |
| 92762 | 92844 | rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); |
| 92763 | 92845 | if( rc!=SQLITE_OK || res==0 ){ |
| 92764 | 92846 | sqlite3ErrorMsg(pParse, "not a writable directory"); |
| 92765 | 92847 | goto pragma_out; |
| @@ -95671,11 +95753,11 @@ | ||
| 95671 | 95753 | int nCol; /* Number of columns in the result set */ |
| 95672 | 95754 | Expr *p; /* Expression for a single result column */ |
| 95673 | 95755 | char *zName; /* Column name */ |
| 95674 | 95756 | int nName; /* Size of name in zName[] */ |
| 95675 | 95757 | |
| 95676 | - *pnCol = nCol = pEList->nExpr; | |
| 95758 | + *pnCol = nCol = pEList ? pEList->nExpr : 0; | |
| 95677 | 95759 | aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); |
| 95678 | 95760 | if( aCol==0 ) return SQLITE_NOMEM; |
| 95679 | 95761 | for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
| 95680 | 95762 | /* Get an appropriate name for the column |
| 95681 | 95763 | */ |
| @@ -101201,10 +101283,22 @@ | ||
| 101201 | 101283 | char *zKey; |
| 101202 | 101284 | sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); |
| 101203 | 101285 | if( nKey ) db->nextPagesize = 0; |
| 101204 | 101286 | } |
| 101205 | 101287 | #endif |
| 101288 | + | |
| 101289 | + rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); | |
| 101290 | + if( rc!=SQLITE_OK ) goto end_of_vacuum; | |
| 101291 | + | |
| 101292 | + /* Begin a transaction and take an exclusive lock on the main database | |
| 101293 | + ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, | |
| 101294 | + ** to ensure that we do not try to change the page-size on a WAL database. | |
| 101295 | + */ | |
| 101296 | + rc = execSql(db, pzErrMsg, "BEGIN;"); | |
| 101297 | + if( rc!=SQLITE_OK ) goto end_of_vacuum; | |
| 101298 | + rc = sqlite3BtreeBeginTrans(pMain, 2); | |
| 101299 | + if( rc!=SQLITE_OK ) goto end_of_vacuum; | |
| 101206 | 101300 | |
| 101207 | 101301 | /* Do not attempt to change the page size for a WAL database */ |
| 101208 | 101302 | if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain)) |
| 101209 | 101303 | ==PAGER_JOURNALMODE_WAL ){ |
| 101210 | 101304 | db->nextPagesize = 0; |
| @@ -101215,24 +101309,16 @@ | ||
| 101215 | 101309 | || NEVER(db->mallocFailed) |
| 101216 | 101310 | ){ |
| 101217 | 101311 | rc = SQLITE_NOMEM; |
| 101218 | 101312 | goto end_of_vacuum; |
| 101219 | 101313 | } |
| 101220 | - rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); | |
| 101221 | - if( rc!=SQLITE_OK ){ | |
| 101222 | - goto end_of_vacuum; | |
| 101223 | - } | |
| 101224 | 101314 | |
| 101225 | 101315 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 101226 | 101316 | sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : |
| 101227 | 101317 | sqlite3BtreeGetAutoVacuum(pMain)); |
| 101228 | 101318 | #endif |
| 101229 | 101319 | |
| 101230 | - /* Begin a transaction */ | |
| 101231 | - rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;"); | |
| 101232 | - if( rc!=SQLITE_OK ) goto end_of_vacuum; | |
| 101233 | - | |
| 101234 | 101320 | /* Query the schema of the main database. Create a mirror schema |
| 101235 | 101321 | ** in the temporary database. |
| 101236 | 101322 | */ |
| 101237 | 101323 | rc = execExecSql(db, pzErrMsg, |
| 101238 | 101324 | "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " |
| @@ -105543,11 +105629,13 @@ | ||
| 105543 | 105629 | } |
| 105544 | 105630 | |
| 105545 | 105631 | /* If there is a DISTINCT qualifier and this index will scan rows in |
| 105546 | 105632 | ** order of the DISTINCT expressions, clear bDist and set the appropriate |
| 105547 | 105633 | ** flags in wsFlags. */ |
| 105548 | - if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){ | |
| 105634 | + if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) | |
| 105635 | + && (wsFlags & WHERE_COLUMN_IN)==0 | |
| 105636 | + ){ | |
| 105549 | 105637 | bDist = 0; |
| 105550 | 105638 | wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT; |
| 105551 | 105639 | } |
| 105552 | 105640 | |
| 105553 | 105641 | /* If currently calculating the cost of using an index (not the IPK |
| @@ -106240,12 +106328,11 @@ | ||
| 106240 | 106328 | */ |
| 106241 | 106329 | static Bitmask codeOneLoopStart( |
| 106242 | 106330 | WhereInfo *pWInfo, /* Complete information about the WHERE clause */ |
| 106243 | 106331 | int iLevel, /* Which level of pWInfo->a[] should be coded */ |
| 106244 | 106332 | u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ |
| 106245 | - Bitmask notReady, /* Which tables are currently available */ | |
| 106246 | - Expr *pWhere /* Complete WHERE clause */ | |
| 106333 | + Bitmask notReady /* Which tables are currently available */ | |
| 106247 | 106334 | ){ |
| 106248 | 106335 | int j, k; /* Loop counters */ |
| 106249 | 106336 | int iCur; /* The VDBE cursor for the table */ |
| 106250 | 106337 | int addrNxt; /* Where to jump to continue with the next IN case */ |
| 106251 | 106338 | int omitTable; /* True if we use the index only */ |
| @@ -106780,14 +106867,29 @@ | ||
| 106780 | 106867 | |
| 106781 | 106868 | /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y |
| 106782 | 106869 | ** Then for every term xN, evaluate as the subexpression: xN AND z |
| 106783 | 106870 | ** That way, terms in y that are factored into the disjunction will |
| 106784 | 106871 | ** be picked up by the recursive calls to sqlite3WhereBegin() below. |
| 106872 | + ** | |
| 106873 | + ** Actually, each subexpression is converted to "xN AND w" where w is | |
| 106874 | + ** the "interesting" terms of z - terms that did not originate in the | |
| 106875 | + ** ON or USING clause of a LEFT JOIN, and terms that are usable as | |
| 106876 | + ** indices. | |
| 106785 | 106877 | */ |
| 106786 | 106878 | if( pWC->nTerm>1 ){ |
| 106787 | - pAndExpr = sqlite3ExprAlloc(pParse->db, TK_AND, 0, 0); | |
| 106788 | - pAndExpr->pRight = pWhere; | |
| 106879 | + int iTerm; | |
| 106880 | + for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ | |
| 106881 | + Expr *pExpr = pWC->a[iTerm].pExpr; | |
| 106882 | + if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; | |
| 106883 | + if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue; | |
| 106884 | + if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; | |
| 106885 | + pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); | |
| 106886 | + pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr); | |
| 106887 | + } | |
| 106888 | + if( pAndExpr ){ | |
| 106889 | + pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); | |
| 106890 | + } | |
| 106789 | 106891 | } |
| 106790 | 106892 | |
| 106791 | 106893 | for(ii=0; ii<pOrWc->nTerm; ii++){ |
| 106792 | 106894 | WhereTerm *pOrTerm = &pOrWc->a[ii]; |
| 106793 | 106895 | if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){ |
| @@ -106825,11 +106927,14 @@ | ||
| 106825 | 106927 | /* Finish the loop through table entries that match term pOrTerm. */ |
| 106826 | 106928 | sqlite3WhereEnd(pSubWInfo); |
| 106827 | 106929 | } |
| 106828 | 106930 | } |
| 106829 | 106931 | } |
| 106830 | - sqlite3DbFree(pParse->db, pAndExpr); | |
| 106932 | + if( pAndExpr ){ | |
| 106933 | + pAndExpr->pLeft = 0; | |
| 106934 | + sqlite3ExprDelete(pParse->db, pAndExpr); | |
| 106935 | + } | |
| 106831 | 106936 | sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); |
| 106832 | 106937 | sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); |
| 106833 | 106938 | sqlite3VdbeResolveLabel(v, iLoopBody); |
| 106834 | 106939 | |
| 106835 | 106940 | if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab); |
| @@ -107481,11 +107586,11 @@ | ||
| 107481 | 107586 | */ |
| 107482 | 107587 | notReady = ~(Bitmask)0; |
| 107483 | 107588 | for(i=0; i<nTabList; i++){ |
| 107484 | 107589 | pLevel = &pWInfo->a[i]; |
| 107485 | 107590 | explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags); |
| 107486 | - notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady, pWhere); | |
| 107591 | + notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady); | |
| 107487 | 107592 | pWInfo->iContinue = pLevel->addrCont; |
| 107488 | 107593 | } |
| 107489 | 107594 | |
| 107490 | 107595 | #ifdef SQLITE_TEST /* For testing and debugging use only */ |
| 107491 | 107596 | /* Record in the query plan information about the current table |
| @@ -113174,23 +113279,27 @@ | ||
| 113174 | 113279 | sqlite3_free(db); |
| 113175 | 113280 | return SQLITE_OK; |
| 113176 | 113281 | } |
| 113177 | 113282 | |
| 113178 | 113283 | /* |
| 113179 | -** Rollback all database files. | |
| 113284 | +** Rollback all database files. If tripCode is not SQLITE_OK, then | |
| 113285 | +** any open cursors are invalidated ("tripped" - as in "tripping a circuit | |
| 113286 | +** breaker") and made to return tripCode if there are any further | |
| 113287 | +** attempts to use that cursor. | |
| 113180 | 113288 | */ |
| 113181 | -SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){ | |
| 113289 | +SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ | |
| 113182 | 113290 | int i; |
| 113183 | 113291 | int inTrans = 0; |
| 113184 | 113292 | assert( sqlite3_mutex_held(db->mutex) ); |
| 113185 | 113293 | sqlite3BeginBenignMalloc(); |
| 113186 | 113294 | for(i=0; i<db->nDb; i++){ |
| 113187 | - if( db->aDb[i].pBt ){ | |
| 113188 | - if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ | |
| 113295 | + Btree *p = db->aDb[i].pBt; | |
| 113296 | + if( p ){ | |
| 113297 | + if( sqlite3BtreeIsInTrans(p) ){ | |
| 113189 | 113298 | inTrans = 1; |
| 113190 | 113299 | } |
| 113191 | - sqlite3BtreeRollback(db->aDb[i].pBt); | |
| 113300 | + sqlite3BtreeRollback(p, tripCode); | |
| 113192 | 113301 | db->aDb[i].inTrans = 0; |
| 113193 | 113302 | } |
| 113194 | 113303 | } |
| 113195 | 113304 | sqlite3VtabRollback(db); |
| 113196 | 113305 | sqlite3EndBenignMalloc(); |
| @@ -113241,16 +113350,25 @@ | ||
| 113241 | 113350 | /* SQLITE_AUTH */ "authorization denied", |
| 113242 | 113351 | /* SQLITE_FORMAT */ "auxiliary database format error", |
| 113243 | 113352 | /* SQLITE_RANGE */ "bind or column index out of range", |
| 113244 | 113353 | /* SQLITE_NOTADB */ "file is encrypted or is not a database", |
| 113245 | 113354 | }; |
| 113246 | - rc &= 0xff; | |
| 113247 | - if( ALWAYS(rc>=0) && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){ | |
| 113248 | - return aMsg[rc]; | |
| 113249 | - }else{ | |
| 113250 | - return "unknown error"; | |
| 113355 | + const char *zErr = "unknown error"; | |
| 113356 | + switch( rc ){ | |
| 113357 | + case SQLITE_ABORT_ROLLBACK: { | |
| 113358 | + zErr = "abort due to ROLLBACK"; | |
| 113359 | + break; | |
| 113360 | + } | |
| 113361 | + default: { | |
| 113362 | + rc &= 0xff; | |
| 113363 | + if( ALWAYS(rc>=0) && rc<ArraySize(aMsg) && aMsg[rc]!=0 ){ | |
| 113364 | + zErr = aMsg[rc]; | |
| 113365 | + } | |
| 113366 | + break; | |
| 113367 | + } | |
| 113251 | 113368 | } |
| 113369 | + return zErr; | |
| 113252 | 113370 | } |
| 113253 | 113371 | |
| 113254 | 113372 | /* |
| 113255 | 113373 | ** This routine implements a busy callback that sleeps and tries |
| 113256 | 113374 | ** again until a timeout value is reached. The timeout value is |
| @@ -113624,13 +113742,12 @@ | ||
| 113624 | 113742 | sqlite3_mutex_leave(db->mutex); |
| 113625 | 113743 | return pOld; |
| 113626 | 113744 | } |
| 113627 | 113745 | #endif /* SQLITE_OMIT_TRACE */ |
| 113628 | 113746 | |
| 113629 | -/*** EXPERIMENTAL *** | |
| 113630 | -** | |
| 113631 | -** Register a function to be invoked when a transaction comments. | |
| 113747 | +/* | |
| 113748 | +** Register a function to be invoked when a transaction commits. | |
| 113632 | 113749 | ** If the invoked function returns non-zero, then the commit becomes a |
| 113633 | 113750 | ** rollback. |
| 113634 | 113751 | */ |
| 113635 | 113752 | SQLITE_API void *sqlite3_commit_hook( |
| 113636 | 113753 | sqlite3 *db, /* Attach the hook to this database */ |
| @@ -115017,39 +115134,31 @@ | ||
| 115017 | 115134 | /* |
| 115018 | 115135 | ** Invoke the xFileControl method on a particular database. |
| 115019 | 115136 | */ |
| 115020 | 115137 | SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ |
| 115021 | 115138 | int rc = SQLITE_ERROR; |
| 115022 | - int iDb; | |
| 115139 | + Btree *pBtree; | |
| 115140 | + | |
| 115023 | 115141 | sqlite3_mutex_enter(db->mutex); |
| 115024 | - if( zDbName==0 ){ | |
| 115025 | - iDb = 0; | |
| 115026 | - }else{ | |
| 115027 | - for(iDb=0; iDb<db->nDb; iDb++){ | |
| 115028 | - if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break; | |
| 115029 | - } | |
| 115030 | - } | |
| 115031 | - if( iDb<db->nDb ){ | |
| 115032 | - Btree *pBtree = db->aDb[iDb].pBt; | |
| 115033 | - if( pBtree ){ | |
| 115034 | - Pager *pPager; | |
| 115035 | - sqlite3_file *fd; | |
| 115036 | - sqlite3BtreeEnter(pBtree); | |
| 115037 | - pPager = sqlite3BtreePager(pBtree); | |
| 115038 | - assert( pPager!=0 ); | |
| 115039 | - fd = sqlite3PagerFile(pPager); | |
| 115040 | - assert( fd!=0 ); | |
| 115041 | - if( op==SQLITE_FCNTL_FILE_POINTER ){ | |
| 115042 | - *(sqlite3_file**)pArg = fd; | |
| 115043 | - rc = SQLITE_OK; | |
| 115044 | - }else if( fd->pMethods ){ | |
| 115045 | - rc = sqlite3OsFileControl(fd, op, pArg); | |
| 115046 | - }else{ | |
| 115047 | - rc = SQLITE_NOTFOUND; | |
| 115048 | - } | |
| 115049 | - sqlite3BtreeLeave(pBtree); | |
| 115050 | - } | |
| 115142 | + pBtree = sqlite3DbNameToBtree(db, zDbName); | |
| 115143 | + if( pBtree ){ | |
| 115144 | + Pager *pPager; | |
| 115145 | + sqlite3_file *fd; | |
| 115146 | + sqlite3BtreeEnter(pBtree); | |
| 115147 | + pPager = sqlite3BtreePager(pBtree); | |
| 115148 | + assert( pPager!=0 ); | |
| 115149 | + fd = sqlite3PagerFile(pPager); | |
| 115150 | + assert( fd!=0 ); | |
| 115151 | + if( op==SQLITE_FCNTL_FILE_POINTER ){ | |
| 115152 | + *(sqlite3_file**)pArg = fd; | |
| 115153 | + rc = SQLITE_OK; | |
| 115154 | + }else if( fd->pMethods ){ | |
| 115155 | + rc = sqlite3OsFileControl(fd, op, pArg); | |
| 115156 | + }else{ | |
| 115157 | + rc = SQLITE_NOTFOUND; | |
| 115158 | + } | |
| 115159 | + sqlite3BtreeLeave(pBtree); | |
| 115051 | 115160 | } |
| 115052 | 115161 | sqlite3_mutex_leave(db->mutex); |
| 115053 | 115162 | return rc; |
| 115054 | 115163 | } |
| 115055 | 115164 | |
| @@ -115339,23 +115448,42 @@ | ||
| 115339 | 115448 | if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){ |
| 115340 | 115449 | bDflt = v; |
| 115341 | 115450 | } |
| 115342 | 115451 | return bDflt; |
| 115343 | 115452 | } |
| 115453 | + | |
| 115454 | +/* | |
| 115455 | +** Return the Btree pointer identified by zDbName. Return NULL if not found. | |
| 115456 | +*/ | |
| 115457 | +SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ | |
| 115458 | + int i; | |
| 115459 | + for(i=0; i<db->nDb; i++){ | |
| 115460 | + if( db->aDb[i].pBt | |
| 115461 | + && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0) | |
| 115462 | + ){ | |
| 115463 | + return db->aDb[i].pBt; | |
| 115464 | + } | |
| 115465 | + } | |
| 115466 | + return 0; | |
| 115467 | +} | |
| 115344 | 115468 | |
| 115345 | 115469 | /* |
| 115346 | 115470 | ** Return the filename of the database associated with a database |
| 115347 | 115471 | ** connection. |
| 115348 | 115472 | */ |
| 115349 | 115473 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
| 115350 | - int i; | |
| 115351 | - for(i=0; i<db->nDb; i++){ | |
| 115352 | - if( db->aDb[i].pBt && sqlite3StrICmp(zDbName, db->aDb[i].zName)==0 ){ | |
| 115353 | - return sqlite3BtreeGetFilename(db->aDb[i].pBt); | |
| 115354 | - } | |
| 115355 | - } | |
| 115356 | - return 0; | |
| 115474 | + Btree *pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 115475 | + return pBt ? sqlite3BtreeGetFilename(pBt) : 0; | |
| 115476 | +} | |
| 115477 | + | |
| 115478 | +/* | |
| 115479 | +** Return 1 if database is read-only or 0 if read/write. Return -1 if | |
| 115480 | +** no such database exists. | |
| 115481 | +*/ | |
| 115482 | +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ | |
| 115483 | + Btree *pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 115484 | + return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1; | |
| 115357 | 115485 | } |
| 115358 | 115486 | |
| 115359 | 115487 | /************** End of main.c ************************************************/ |
| 115360 | 115488 | /************** Begin file notify.c ******************************************/ |
| 115361 | 115489 | /* |
| @@ -115977,14 +116105,10 @@ | ||
| 115977 | 116105 | ** we simply write the new doclist. Segment merges overwrite older |
| 115978 | 116106 | ** data for a particular docid with newer data, so deletes or updates |
| 115979 | 116107 | ** will eventually overtake the earlier data and knock it out. The |
| 115980 | 116108 | ** query logic likewise merges doclists so that newer data knocks out |
| 115981 | 116109 | ** older data. |
| 115982 | -** | |
| 115983 | -** TODO(shess) Provide a VACUUM type operation to clear out all | |
| 115984 | -** deletions and duplications. This would basically be a forced merge | |
| 115985 | -** into a single segment. | |
| 115986 | 116110 | */ |
| 115987 | 116111 | |
| 115988 | 116112 | /************** Include fts3Int.h in the middle of fts3.c ********************/ |
| 115989 | 116113 | /************** Begin file fts3Int.h *****************************************/ |
| 115990 | 116114 | /* |
| @@ -116076,11 +116200,11 @@ | ||
| 116076 | 116200 | typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; |
| 116077 | 116201 | |
| 116078 | 116202 | struct sqlite3_tokenizer_module { |
| 116079 | 116203 | |
| 116080 | 116204 | /* |
| 116081 | - ** Structure version. Should always be set to 0. | |
| 116205 | + ** Structure version. Should always be set to 0 or 1. | |
| 116082 | 116206 | */ |
| 116083 | 116207 | int iVersion; |
| 116084 | 116208 | |
| 116085 | 116209 | /* |
| 116086 | 116210 | ** Create a new tokenizer. The values in the argv[] array are the |
| @@ -116157,10 +116281,19 @@ | ||
| 116157 | 116281 | const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ |
| 116158 | 116282 | int *piStartOffset, /* OUT: Byte offset of token in input buffer */ |
| 116159 | 116283 | int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ |
| 116160 | 116284 | int *piPosition /* OUT: Number of tokens returned before this one */ |
| 116161 | 116285 | ); |
| 116286 | + | |
| 116287 | + /*********************************************************************** | |
| 116288 | + ** Methods below this point are only available if iVersion>=1. | |
| 116289 | + */ | |
| 116290 | + | |
| 116291 | + /* | |
| 116292 | + ** Configure the language id of a tokenizer cursor. | |
| 116293 | + */ | |
| 116294 | + int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid); | |
| 116162 | 116295 | }; |
| 116163 | 116296 | |
| 116164 | 116297 | struct sqlite3_tokenizer { |
| 116165 | 116298 | const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ |
| 116166 | 116299 | /* Tokenizer implementations will typically add additional fields */ |
| @@ -116448,15 +116581,16 @@ | ||
| 116448 | 116581 | const char *zName; /* virtual table name */ |
| 116449 | 116582 | int nColumn; /* number of named columns in virtual table */ |
| 116450 | 116583 | char **azColumn; /* column names. malloced */ |
| 116451 | 116584 | sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ |
| 116452 | 116585 | char *zContentTbl; /* content=xxx option, or NULL */ |
| 116586 | + char *zLanguageid; /* languageid=xxx option, or NULL */ | |
| 116453 | 116587 | |
| 116454 | 116588 | /* Precompiled statements used by the implementation. Each of these |
| 116455 | 116589 | ** statements is run and reset within a single virtual table API call. |
| 116456 | 116590 | */ |
| 116457 | - sqlite3_stmt *aStmt[27]; | |
| 116591 | + sqlite3_stmt *aStmt[28]; | |
| 116458 | 116592 | |
| 116459 | 116593 | char *zReadExprlist; |
| 116460 | 116594 | char *zWriteExprlist; |
| 116461 | 116595 | |
| 116462 | 116596 | int nNodeSize; /* Soft limit for node size */ |
| @@ -116467,16 +116601,16 @@ | ||
| 116467 | 116601 | char *zSegmentsTbl; /* Name of %_segments table */ |
| 116468 | 116602 | sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ |
| 116469 | 116603 | |
| 116470 | 116604 | /* TODO: Fix the first paragraph of this comment. |
| 116471 | 116605 | ** |
| 116472 | - ** The following hash table is used to buffer pending index updates during | |
| 116473 | - ** transactions. Variable nPendingData estimates the memory size of the | |
| 116474 | - ** pending data, including hash table overhead, but not malloc overhead. | |
| 116475 | - ** When nPendingData exceeds nMaxPendingData, the buffer is flushed | |
| 116476 | - ** automatically. Variable iPrevDocid is the docid of the most recently | |
| 116477 | - ** inserted record. | |
| 116606 | + ** The following array of hash tables is used to buffer pending index | |
| 116607 | + ** updates during transactions. Variable nPendingData estimates the memory | |
| 116608 | + ** size of the pending data, including hash table overhead, not including | |
| 116609 | + ** malloc overhead. When nPendingData exceeds nMaxPendingData, the buffer | |
| 116610 | + ** is flushed automatically. Variable iPrevDocid is the docid of the most | |
| 116611 | + ** recently inserted record. | |
| 116478 | 116612 | ** |
| 116479 | 116613 | ** A single FTS4 table may have multiple full-text indexes. For each index |
| 116480 | 116614 | ** there is an entry in the aIndex[] array. Index 0 is an index of all the |
| 116481 | 116615 | ** terms that appear in the document set. Each subsequent index in aIndex[] |
| 116482 | 116616 | ** is an index of prefixes of a specific length. |
| @@ -116487,16 +116621,17 @@ | ||
| 116487 | 116621 | Fts3Hash hPending; /* Pending terms table for this index */ |
| 116488 | 116622 | } *aIndex; |
| 116489 | 116623 | int nMaxPendingData; /* Max pending data before flush to disk */ |
| 116490 | 116624 | int nPendingData; /* Current bytes of pending data */ |
| 116491 | 116625 | sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ |
| 116626 | + int iPrevLangid; /* Langid of recently inserted document */ | |
| 116492 | 116627 | |
| 116493 | 116628 | #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) |
| 116494 | 116629 | /* State variables used for validating that the transaction control |
| 116495 | 116630 | ** methods of the virtual table are called at appropriate times. These |
| 116496 | - ** values do not contribution to the FTS computation; they are used for | |
| 116497 | - ** verifying the SQLite core. | |
| 116631 | + ** values do not contribute to FTS functionality; they are used for | |
| 116632 | + ** verifying the operation of the SQLite core. | |
| 116498 | 116633 | */ |
| 116499 | 116634 | int inTransaction; /* True after xBegin but before xCommit/xRollback */ |
| 116500 | 116635 | int mxSavepoint; /* Largest valid xSavepoint integer */ |
| 116501 | 116636 | #endif |
| 116502 | 116637 | }; |
| @@ -116511,10 +116646,11 @@ | ||
| 116511 | 116646 | i16 eSearch; /* Search strategy (see below) */ |
| 116512 | 116647 | u8 isEof; /* True if at End Of Results */ |
| 116513 | 116648 | u8 isRequireSeek; /* True if must seek pStmt to %_content row */ |
| 116514 | 116649 | sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ |
| 116515 | 116650 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 116651 | + int iLangid; /* Language being queried for */ | |
| 116516 | 116652 | int nPhrase; /* Number of matchable phrases in query */ |
| 116517 | 116653 | Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ |
| 116518 | 116654 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 116519 | 116655 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 116520 | 116656 | char *aDoclist; /* List of docids for full-text queries */ |
| @@ -116662,11 +116798,11 @@ | ||
| 116662 | 116798 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64, |
| 116663 | 116799 | sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); |
| 116664 | 116800 | SQLITE_PRIVATE int sqlite3Fts3SegReaderPending( |
| 116665 | 116801 | Fts3Table*,int,const char*,int,int,Fts3SegReader**); |
| 116666 | 116802 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *); |
| 116667 | -SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **); | |
| 116803 | +SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **); | |
| 116668 | 116804 | SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); |
| 116669 | 116805 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*); |
| 116670 | 116806 | |
| 116671 | 116807 | SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); |
| 116672 | 116808 | SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); |
| @@ -116683,12 +116819,12 @@ | ||
| 116683 | 116819 | |
| 116684 | 116820 | SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*); |
| 116685 | 116821 | SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *); |
| 116686 | 116822 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *); |
| 116687 | 116823 | |
| 116688 | -SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( | |
| 116689 | - Fts3Table *, int, int, const char *, int, int, int, Fts3MultiSegReader *); | |
| 116824 | +SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *, | |
| 116825 | + int, int, int, const char *, int, int, int, Fts3MultiSegReader *); | |
| 116690 | 116826 | |
| 116691 | 116827 | /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ |
| 116692 | 116828 | #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 |
| 116693 | 116829 | #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 |
| 116694 | 116830 | #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 |
| @@ -116751,18 +116887,22 @@ | ||
| 116751 | 116887 | const char *, const char *, int, int |
| 116752 | 116888 | ); |
| 116753 | 116889 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); |
| 116754 | 116890 | |
| 116755 | 116891 | /* fts3_expr.c */ |
| 116756 | -SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, | |
| 116892 | +SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, | |
| 116757 | 116893 | char **, int, int, int, const char *, int, Fts3Expr ** |
| 116758 | 116894 | ); |
| 116759 | 116895 | SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); |
| 116760 | 116896 | #ifdef SQLITE_TEST |
| 116761 | 116897 | SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); |
| 116762 | 116898 | SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); |
| 116763 | 116899 | #endif |
| 116900 | + | |
| 116901 | +SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int, | |
| 116902 | + sqlite3_tokenizer_cursor ** | |
| 116903 | +); | |
| 116764 | 116904 | |
| 116765 | 116905 | /* fts3_aux.c */ |
| 116766 | 116906 | SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db); |
| 116767 | 116907 | |
| 116768 | 116908 | SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *); |
| @@ -116954,10 +117094,11 @@ | ||
| 116954 | 117094 | } |
| 116955 | 117095 | sqlite3_free(p->zSegmentsTbl); |
| 116956 | 117096 | sqlite3_free(p->zReadExprlist); |
| 116957 | 117097 | sqlite3_free(p->zWriteExprlist); |
| 116958 | 117098 | sqlite3_free(p->zContentTbl); |
| 117099 | + sqlite3_free(p->zLanguageid); | |
| 116959 | 117100 | |
| 116960 | 117101 | /* Invoke the tokenizer destructor to free the tokenizer. */ |
| 116961 | 117102 | p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
| 116962 | 117103 | |
| 116963 | 117104 | sqlite3_free(p); |
| @@ -117030,11 +117171,13 @@ | ||
| 117030 | 117171 | if( *pRc==SQLITE_OK ){ |
| 117031 | 117172 | int i; /* Iterator variable */ |
| 117032 | 117173 | int rc; /* Return code */ |
| 117033 | 117174 | char *zSql; /* SQL statement passed to declare_vtab() */ |
| 117034 | 117175 | char *zCols; /* List of user defined columns */ |
| 117176 | + const char *zLanguageid; | |
| 117035 | 117177 | |
| 117178 | + zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid"); | |
| 117036 | 117179 | sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); |
| 117037 | 117180 | |
| 117038 | 117181 | /* Create a list of user columns for the virtual table */ |
| 117039 | 117182 | zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]); |
| 117040 | 117183 | for(i=1; zCols && i<p->nColumn; i++){ |
| @@ -117041,11 +117184,12 @@ | ||
| 117041 | 117184 | zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]); |
| 117042 | 117185 | } |
| 117043 | 117186 | |
| 117044 | 117187 | /* Create the whole "CREATE TABLE" statement to pass to SQLite */ |
| 117045 | 117188 | zSql = sqlite3_mprintf( |
| 117046 | - "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN)", zCols, p->zName | |
| 117189 | + "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)", | |
| 117190 | + zCols, p->zName, zLanguageid | |
| 117047 | 117191 | ); |
| 117048 | 117192 | if( !zCols || !zSql ){ |
| 117049 | 117193 | rc = SQLITE_NOMEM; |
| 117050 | 117194 | }else{ |
| 117051 | 117195 | rc = sqlite3_declare_vtab(p->db, zSql); |
| @@ -117070,18 +117214,22 @@ | ||
| 117070 | 117214 | int rc = SQLITE_OK; /* Return code */ |
| 117071 | 117215 | int i; /* Iterator variable */ |
| 117072 | 117216 | sqlite3 *db = p->db; /* The database connection */ |
| 117073 | 117217 | |
| 117074 | 117218 | if( p->zContentTbl==0 ){ |
| 117219 | + const char *zLanguageid = p->zLanguageid; | |
| 117075 | 117220 | char *zContentCols; /* Columns of %_content table */ |
| 117076 | 117221 | |
| 117077 | 117222 | /* Create a list of user columns for the content table */ |
| 117078 | 117223 | zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); |
| 117079 | 117224 | for(i=0; zContentCols && i<p->nColumn; i++){ |
| 117080 | 117225 | char *z = p->azColumn[i]; |
| 117081 | 117226 | zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); |
| 117082 | 117227 | } |
| 117228 | + if( zLanguageid && zContentCols ){ | |
| 117229 | + zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid); | |
| 117230 | + } | |
| 117083 | 117231 | if( zContentCols==0 ) rc = SQLITE_NOMEM; |
| 117084 | 117232 | |
| 117085 | 117233 | /* Create the content table */ |
| 117086 | 117234 | fts3DbExec(&rc, db, |
| 117087 | 117235 | "CREATE TABLE %Q.'%q_content'(%s)", |
| @@ -117277,18 +117425,24 @@ | ||
| 117277 | 117425 | } |
| 117278 | 117426 | fts3Appendf(pRc, &zRet, "docid"); |
| 117279 | 117427 | for(i=0; i<p->nColumn; i++){ |
| 117280 | 117428 | fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]); |
| 117281 | 117429 | } |
| 117430 | + if( p->zLanguageid ){ | |
| 117431 | + fts3Appendf(pRc, &zRet, ", x.%Q", "langid"); | |
| 117432 | + } | |
| 117282 | 117433 | sqlite3_free(zFree); |
| 117283 | 117434 | }else{ |
| 117284 | 117435 | fts3Appendf(pRc, &zRet, "rowid"); |
| 117285 | 117436 | for(i=0; i<p->nColumn; i++){ |
| 117286 | 117437 | fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]); |
| 117287 | 117438 | } |
| 117439 | + if( p->zLanguageid ){ | |
| 117440 | + fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid); | |
| 117441 | + } | |
| 117288 | 117442 | } |
| 117289 | - fts3Appendf(pRc, &zRet, "FROM '%q'.'%q%s' AS x", | |
| 117443 | + fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x", | |
| 117290 | 117444 | p->zDb, |
| 117291 | 117445 | (p->zContentTbl ? p->zContentTbl : p->zName), |
| 117292 | 117446 | (p->zContentTbl ? "" : "_content") |
| 117293 | 117447 | ); |
| 117294 | 117448 | return zRet; |
| @@ -117327,10 +117481,13 @@ | ||
| 117327 | 117481 | } |
| 117328 | 117482 | fts3Appendf(pRc, &zRet, "?"); |
| 117329 | 117483 | for(i=0; i<p->nColumn; i++){ |
| 117330 | 117484 | fts3Appendf(pRc, &zRet, ",%s(?)", zFunction); |
| 117331 | 117485 | } |
| 117486 | + if( p->zLanguageid ){ | |
| 117487 | + fts3Appendf(pRc, &zRet, ", ?"); | |
| 117488 | + } | |
| 117332 | 117489 | sqlite3_free(zFree); |
| 117333 | 117490 | return zRet; |
| 117334 | 117491 | } |
| 117335 | 117492 | |
| 117336 | 117493 | /* |
| @@ -117542,10 +117699,11 @@ | ||
| 117542 | 117699 | int bDescIdx = 0; /* True to store descending indexes */ |
| 117543 | 117700 | char *zPrefix = 0; /* Prefix parameter value (or NULL) */ |
| 117544 | 117701 | char *zCompress = 0; /* compress=? parameter (or NULL) */ |
| 117545 | 117702 | char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ |
| 117546 | 117703 | char *zContent = 0; /* content=? parameter (or NULL) */ |
| 117704 | + char *zLanguageid = 0; /* languageid=? parameter (or NULL) */ | |
| 117547 | 117705 | |
| 117548 | 117706 | assert( strlen(argv[0])==4 ); |
| 117549 | 117707 | assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4) |
| 117550 | 117708 | || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4) |
| 117551 | 117709 | ); |
| @@ -117591,11 +117749,12 @@ | ||
| 117591 | 117749 | { "matchinfo", 9 }, /* 0 -> MATCHINFO */ |
| 117592 | 117750 | { "prefix", 6 }, /* 1 -> PREFIX */ |
| 117593 | 117751 | { "compress", 8 }, /* 2 -> COMPRESS */ |
| 117594 | 117752 | { "uncompress", 10 }, /* 3 -> UNCOMPRESS */ |
| 117595 | 117753 | { "order", 5 }, /* 4 -> ORDER */ |
| 117596 | - { "content", 7 } /* 5 -> CONTENT */ | |
| 117754 | + { "content", 7 }, /* 5 -> CONTENT */ | |
| 117755 | + { "languageid", 10 } /* 6 -> LANGUAGEID */ | |
| 117597 | 117756 | }; |
| 117598 | 117757 | |
| 117599 | 117758 | int iOpt; |
| 117600 | 117759 | if( !zVal ){ |
| 117601 | 117760 | rc = SQLITE_NOMEM; |
| @@ -117645,16 +117804,22 @@ | ||
| 117645 | 117804 | rc = SQLITE_ERROR; |
| 117646 | 117805 | } |
| 117647 | 117806 | bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); |
| 117648 | 117807 | break; |
| 117649 | 117808 | |
| 117650 | - default: /* CONTENT */ | |
| 117651 | - assert( iOpt==5 ); | |
| 117652 | - sqlite3_free(zUncompress); | |
| 117809 | + case 5: /* CONTENT */ | |
| 117810 | + sqlite3_free(zContent); | |
| 117653 | 117811 | zContent = zVal; |
| 117654 | 117812 | zVal = 0; |
| 117655 | 117813 | break; |
| 117814 | + | |
| 117815 | + case 6: /* LANGUAGEID */ | |
| 117816 | + assert( iOpt==6 ); | |
| 117817 | + sqlite3_free(zLanguageid); | |
| 117818 | + zLanguageid = zVal; | |
| 117819 | + zVal = 0; | |
| 117820 | + break; | |
| 117656 | 117821 | } |
| 117657 | 117822 | } |
| 117658 | 117823 | sqlite3_free(zVal); |
| 117659 | 117824 | } |
| 117660 | 117825 | } |
| @@ -117680,12 +117845,24 @@ | ||
| 117680 | 117845 | zUncompress = 0; |
| 117681 | 117846 | if( nCol==0 ){ |
| 117682 | 117847 | sqlite3_free((void*)aCol); |
| 117683 | 117848 | aCol = 0; |
| 117684 | 117849 | rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); |
| 117850 | + | |
| 117851 | + /* If a languageid= option was specified, remove the language id | |
| 117852 | + ** column from the aCol[] array. */ | |
| 117853 | + if( rc==SQLITE_OK && zLanguageid ){ | |
| 117854 | + int j; | |
| 117855 | + for(j=0; j<nCol; j++){ | |
| 117856 | + if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){ | |
| 117857 | + memmove(&aCol[j], &aCol[j+1], (nCol-j) * sizeof(aCol[0])); | |
| 117858 | + nCol--; | |
| 117859 | + break; | |
| 117860 | + } | |
| 117861 | + } | |
| 117862 | + } | |
| 117685 | 117863 | } |
| 117686 | - assert( rc!=SQLITE_OK || nCol>0 ); | |
| 117687 | 117864 | } |
| 117688 | 117865 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 117689 | 117866 | |
| 117690 | 117867 | if( nCol==0 ){ |
| 117691 | 117868 | assert( nString==0 ); |
| @@ -117728,11 +117905,13 @@ | ||
| 117728 | 117905 | p->nMaxPendingData = FTS3_MAX_PENDING_DATA; |
| 117729 | 117906 | p->bHasDocsize = (isFts4 && bNoDocsize==0); |
| 117730 | 117907 | p->bHasStat = isFts4; |
| 117731 | 117908 | p->bDescIdx = bDescIdx; |
| 117732 | 117909 | p->zContentTbl = zContent; |
| 117910 | + p->zLanguageid = zLanguageid; | |
| 117733 | 117911 | zContent = 0; |
| 117912 | + zLanguageid = 0; | |
| 117734 | 117913 | TESTONLY( p->inTransaction = -1 ); |
| 117735 | 117914 | TESTONLY( p->mxSavepoint = -1 ); |
| 117736 | 117915 | |
| 117737 | 117916 | p->aIndex = (struct Fts3Index *)&p->azColumn[nCol]; |
| 117738 | 117917 | memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex); |
| @@ -117791,10 +117970,11 @@ | ||
| 117791 | 117970 | sqlite3_free(zPrefix); |
| 117792 | 117971 | sqlite3_free(aIndex); |
| 117793 | 117972 | sqlite3_free(zCompress); |
| 117794 | 117973 | sqlite3_free(zUncompress); |
| 117795 | 117974 | sqlite3_free(zContent); |
| 117975 | + sqlite3_free(zLanguageid); | |
| 117796 | 117976 | sqlite3_free((void *)aCol); |
| 117797 | 117977 | if( rc!=SQLITE_OK ){ |
| 117798 | 117978 | if( p ){ |
| 117799 | 117979 | fts3DisconnectMethod((sqlite3_vtab *)p); |
| 117800 | 117980 | }else if( pTokenizer ){ |
| @@ -117842,10 +118022,11 @@ | ||
| 117842 | 118022 | */ |
| 117843 | 118023 | static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ |
| 117844 | 118024 | Fts3Table *p = (Fts3Table *)pVTab; |
| 117845 | 118025 | int i; /* Iterator variable */ |
| 117846 | 118026 | int iCons = -1; /* Index of constraint to use */ |
| 118027 | + int iLangidCons = -1; /* Index of langid=x constraint, if present */ | |
| 117847 | 118028 | |
| 117848 | 118029 | /* By default use a full table scan. This is an expensive option, |
| 117849 | 118030 | ** so search through the constraints to see if a more efficient |
| 117850 | 118031 | ** strategy is possible. |
| 117851 | 118032 | */ |
| @@ -117854,11 +118035,12 @@ | ||
| 117854 | 118035 | for(i=0; i<pInfo->nConstraint; i++){ |
| 117855 | 118036 | struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i]; |
| 117856 | 118037 | if( pCons->usable==0 ) continue; |
| 117857 | 118038 | |
| 117858 | 118039 | /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */ |
| 117859 | - if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ | |
| 118040 | + if( iCons<0 | |
| 118041 | + && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ | |
| 117860 | 118042 | && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 ) |
| 117861 | 118043 | ){ |
| 117862 | 118044 | pInfo->idxNum = FTS3_DOCID_SEARCH; |
| 117863 | 118045 | pInfo->estimatedCost = 1.0; |
| 117864 | 118046 | iCons = i; |
| @@ -117877,18 +118059,27 @@ | ||
| 117877 | 118059 | && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn |
| 117878 | 118060 | ){ |
| 117879 | 118061 | pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn; |
| 117880 | 118062 | pInfo->estimatedCost = 2.0; |
| 117881 | 118063 | iCons = i; |
| 117882 | - break; | |
| 118064 | + } | |
| 118065 | + | |
| 118066 | + /* Equality constraint on the langid column */ | |
| 118067 | + if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ | |
| 118068 | + && pCons->iColumn==p->nColumn + 2 | |
| 118069 | + ){ | |
| 118070 | + iLangidCons = i; | |
| 117883 | 118071 | } |
| 117884 | 118072 | } |
| 117885 | 118073 | |
| 117886 | 118074 | if( iCons>=0 ){ |
| 117887 | 118075 | pInfo->aConstraintUsage[iCons].argvIndex = 1; |
| 117888 | 118076 | pInfo->aConstraintUsage[iCons].omit = 1; |
| 117889 | 118077 | } |
| 118078 | + if( iLangidCons>=0 ){ | |
| 118079 | + pInfo->aConstraintUsage[iLangidCons].argvIndex = 2; | |
| 118080 | + } | |
| 117890 | 118081 | |
| 117891 | 118082 | /* Regardless of the strategy selected, FTS can deliver rows in rowid (or |
| 117892 | 118083 | ** docid) order. Both ascending and descending are possible. |
| 117893 | 118084 | */ |
| 117894 | 118085 | if( pInfo->nOrderBy==1 ){ |
| @@ -119034,10 +119225,11 @@ | ||
| 119034 | 119225 | ** This function returns SQLITE_OK if successful, or an SQLite error code |
| 119035 | 119226 | ** otherwise. |
| 119036 | 119227 | */ |
| 119037 | 119228 | static int fts3SegReaderCursor( |
| 119038 | 119229 | Fts3Table *p, /* FTS3 table handle */ |
| 119230 | + int iLangid, /* Language id */ | |
| 119039 | 119231 | int iIndex, /* Index to search (from 0 to p->nIndex-1) */ |
| 119040 | 119232 | int iLevel, /* Level of segments to scan */ |
| 119041 | 119233 | const char *zTerm, /* Term to query for */ |
| 119042 | 119234 | int nTerm, /* Size of zTerm in bytes */ |
| 119043 | 119235 | int isPrefix, /* True for a prefix search */ |
| @@ -119062,11 +119254,11 @@ | ||
| 119062 | 119254 | } |
| 119063 | 119255 | } |
| 119064 | 119256 | |
| 119065 | 119257 | if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
| 119066 | 119258 | if( rc==SQLITE_OK ){ |
| 119067 | - rc = sqlite3Fts3AllSegdirs(p, iIndex, iLevel, &pStmt); | |
| 119259 | + rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); | |
| 119068 | 119260 | } |
| 119069 | 119261 | |
| 119070 | 119262 | while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ |
| 119071 | 119263 | Fts3SegReader *pSeg = 0; |
| 119072 | 119264 | |
| @@ -119107,10 +119299,11 @@ | ||
| 119107 | 119299 | ** Set up a cursor object for iterating through a full-text index or a |
| 119108 | 119300 | ** single level therein. |
| 119109 | 119301 | */ |
| 119110 | 119302 | SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( |
| 119111 | 119303 | Fts3Table *p, /* FTS3 table handle */ |
| 119304 | + int iLangid, | |
| 119112 | 119305 | int iIndex, /* Index to search (from 0 to p->nIndex-1) */ |
| 119113 | 119306 | int iLevel, /* Level of segments to scan */ |
| 119114 | 119307 | const char *zTerm, /* Term to query for */ |
| 119115 | 119308 | int nTerm, /* Size of zTerm in bytes */ |
| 119116 | 119309 | int isPrefix, /* True for a prefix search */ |
| @@ -119131,11 +119324,11 @@ | ||
| 119131 | 119324 | assert( isScan==0 || p->aIndex==0 ); |
| 119132 | 119325 | |
| 119133 | 119326 | memset(pCsr, 0, sizeof(Fts3MultiSegReader)); |
| 119134 | 119327 | |
| 119135 | 119328 | return fts3SegReaderCursor( |
| 119136 | - p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr | |
| 119329 | + p, iLangid, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr | |
| 119137 | 119330 | ); |
| 119138 | 119331 | } |
| 119139 | 119332 | |
| 119140 | 119333 | /* |
| 119141 | 119334 | ** In addition to its current configuration, have the Fts3MultiSegReader |
| @@ -119143,15 +119336,18 @@ | ||
| 119143 | 119336 | ** |
| 119144 | 119337 | ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. |
| 119145 | 119338 | */ |
| 119146 | 119339 | static int fts3SegReaderCursorAddZero( |
| 119147 | 119340 | Fts3Table *p, /* FTS virtual table handle */ |
| 119341 | + int iLangid, | |
| 119148 | 119342 | const char *zTerm, /* Term to scan doclist of */ |
| 119149 | 119343 | int nTerm, /* Number of bytes in zTerm */ |
| 119150 | 119344 | Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */ |
| 119151 | 119345 | ){ |
| 119152 | - return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr); | |
| 119346 | + return fts3SegReaderCursor(p, | |
| 119347 | + iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr | |
| 119348 | + ); | |
| 119153 | 119349 | } |
| 119154 | 119350 | |
| 119155 | 119351 | /* |
| 119156 | 119352 | ** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or, |
| 119157 | 119353 | ** if isPrefix is true, to scan the doclist for all terms for which |
| @@ -119183,32 +119379,35 @@ | ||
| 119183 | 119379 | |
| 119184 | 119380 | if( isPrefix ){ |
| 119185 | 119381 | for(i=1; bFound==0 && i<p->nIndex; i++){ |
| 119186 | 119382 | if( p->aIndex[i].nPrefix==nTerm ){ |
| 119187 | 119383 | bFound = 1; |
| 119188 | - rc = sqlite3Fts3SegReaderCursor( | |
| 119189 | - p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr); | |
| 119384 | + rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, | |
| 119385 | + i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr | |
| 119386 | + ); | |
| 119190 | 119387 | pSegcsr->bLookup = 1; |
| 119191 | 119388 | } |
| 119192 | 119389 | } |
| 119193 | 119390 | |
| 119194 | 119391 | for(i=1; bFound==0 && i<p->nIndex; i++){ |
| 119195 | 119392 | if( p->aIndex[i].nPrefix==nTerm+1 ){ |
| 119196 | 119393 | bFound = 1; |
| 119197 | - rc = sqlite3Fts3SegReaderCursor( | |
| 119198 | - p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr | |
| 119394 | + rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, | |
| 119395 | + i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr | |
| 119199 | 119396 | ); |
| 119200 | 119397 | if( rc==SQLITE_OK ){ |
| 119201 | - rc = fts3SegReaderCursorAddZero(p, zTerm, nTerm, pSegcsr); | |
| 119398 | + rc = fts3SegReaderCursorAddZero( | |
| 119399 | + p, pCsr->iLangid, zTerm, nTerm, pSegcsr | |
| 119400 | + ); | |
| 119202 | 119401 | } |
| 119203 | 119402 | } |
| 119204 | 119403 | } |
| 119205 | 119404 | } |
| 119206 | 119405 | |
| 119207 | 119406 | if( bFound==0 ){ |
| 119208 | - rc = sqlite3Fts3SegReaderCursor( | |
| 119209 | - p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr | |
| 119407 | + rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, | |
| 119408 | + 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr | |
| 119210 | 119409 | ); |
| 119211 | 119410 | pSegcsr->bLookup = !isPrefix; |
| 119212 | 119411 | } |
| 119213 | 119412 | } |
| 119214 | 119413 | |
| @@ -119359,11 +119558,11 @@ | ||
| 119359 | 119558 | |
| 119360 | 119559 | UNUSED_PARAMETER(idxStr); |
| 119361 | 119560 | UNUSED_PARAMETER(nVal); |
| 119362 | 119561 | |
| 119363 | 119562 | assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); |
| 119364 | - assert( nVal==0 || nVal==1 ); | |
| 119563 | + assert( nVal==0 || nVal==1 || nVal==2 ); | |
| 119365 | 119564 | assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) ); |
| 119366 | 119565 | assert( p->pSegments==0 ); |
| 119367 | 119566 | |
| 119368 | 119567 | /* In case the cursor has been used before, clear it now. */ |
| 119369 | 119568 | sqlite3_finalize(pCsr->pStmt); |
| @@ -119384,12 +119583,15 @@ | ||
| 119384 | 119583 | |
| 119385 | 119584 | if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 119386 | 119585 | return SQLITE_NOMEM; |
| 119387 | 119586 | } |
| 119388 | 119587 | |
| 119389 | - rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->bHasStat, | |
| 119390 | - p->nColumn, iCol, zQuery, -1, &pCsr->pExpr | |
| 119588 | + pCsr->iLangid = 0; | |
| 119589 | + if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]); | |
| 119590 | + | |
| 119591 | + rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, | |
| 119592 | + p->azColumn, p->bHasStat, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr | |
| 119391 | 119593 | ); |
| 119392 | 119594 | if( rc!=SQLITE_OK ){ |
| 119393 | 119595 | if( rc==SQLITE_ERROR ){ |
| 119394 | 119596 | static const char *zErr = "malformed MATCH expression: [%s]"; |
| 119395 | 119597 | p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery); |
| @@ -119456,37 +119658,56 @@ | ||
| 119456 | 119658 | } |
| 119457 | 119659 | |
| 119458 | 119660 | /* |
| 119459 | 119661 | ** This is the xColumn method, called by SQLite to request a value from |
| 119460 | 119662 | ** the row that the supplied cursor currently points to. |
| 119663 | +** | |
| 119664 | +** If: | |
| 119665 | +** | |
| 119666 | +** (iCol < p->nColumn) -> The value of the iCol'th user column. | |
| 119667 | +** (iCol == p->nColumn) -> Magic column with the same name as the table. | |
| 119668 | +** (iCol == p->nColumn+1) -> Docid column | |
| 119669 | +** (iCol == p->nColumn+2) -> Langid column | |
| 119461 | 119670 | */ |
| 119462 | 119671 | static int fts3ColumnMethod( |
| 119463 | 119672 | sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ |
| 119464 | - sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */ | |
| 119673 | + sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ | |
| 119465 | 119674 | int iCol /* Index of column to read value from */ |
| 119466 | 119675 | ){ |
| 119467 | 119676 | int rc = SQLITE_OK; /* Return Code */ |
| 119468 | 119677 | Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; |
| 119469 | 119678 | Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
| 119470 | 119679 | |
| 119471 | 119680 | /* The column value supplied by SQLite must be in range. */ |
| 119472 | - assert( iCol>=0 && iCol<=p->nColumn+1 ); | |
| 119681 | + assert( iCol>=0 && iCol<=p->nColumn+2 ); | |
| 119473 | 119682 | |
| 119474 | 119683 | if( iCol==p->nColumn+1 ){ |
| 119475 | 119684 | /* This call is a request for the "docid" column. Since "docid" is an |
| 119476 | 119685 | ** alias for "rowid", use the xRowid() method to obtain the value. |
| 119477 | 119686 | */ |
| 119478 | - sqlite3_result_int64(pContext, pCsr->iPrevId); | |
| 119687 | + sqlite3_result_int64(pCtx, pCsr->iPrevId); | |
| 119479 | 119688 | }else if( iCol==p->nColumn ){ |
| 119480 | 119689 | /* The extra column whose name is the same as the table. |
| 119481 | - ** Return a blob which is a pointer to the cursor. | |
| 119482 | - */ | |
| 119483 | - sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); | |
| 119690 | + ** Return a blob which is a pointer to the cursor. */ | |
| 119691 | + sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); | |
| 119692 | + }else if( iCol==p->nColumn+2 && pCsr->pExpr ){ | |
| 119693 | + sqlite3_result_int64(pCtx, pCsr->iLangid); | |
| 119484 | 119694 | }else{ |
| 119695 | + /* The requested column is either a user column (one that contains | |
| 119696 | + ** indexed data), or the language-id column. */ | |
| 119485 | 119697 | rc = fts3CursorSeek(0, pCsr); |
| 119486 | - if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){ | |
| 119487 | - sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1)); | |
| 119698 | + | |
| 119699 | + if( rc==SQLITE_OK ){ | |
| 119700 | + if( iCol==p->nColumn+2 ){ | |
| 119701 | + int iLangid = 0; | |
| 119702 | + if( p->zLanguageid ){ | |
| 119703 | + iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1); | |
| 119704 | + } | |
| 119705 | + sqlite3_result_int(pCtx, iLangid); | |
| 119706 | + }else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){ | |
| 119707 | + sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); | |
| 119708 | + } | |
| 119488 | 119709 | } |
| 119489 | 119710 | } |
| 119490 | 119711 | |
| 119491 | 119712 | assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
| 119492 | 119713 | return rc; |
| @@ -121958,11 +122179,11 @@ | ||
| 121958 | 122179 | pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx])); |
| 121959 | 122180 | pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]); |
| 121960 | 122181 | if( pCsr->zStop==0 ) return SQLITE_NOMEM; |
| 121961 | 122182 | } |
| 121962 | 122183 | |
| 121963 | - rc = sqlite3Fts3SegReaderCursor(pFts3, 0, FTS3_SEGCURSOR_ALL, | |
| 122184 | + rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL, | |
| 121964 | 122185 | pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr |
| 121965 | 122186 | ); |
| 121966 | 122187 | if( rc==SQLITE_OK ){ |
| 121967 | 122188 | rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter); |
| 121968 | 122189 | } |
| @@ -122150,10 +122371,11 @@ | ||
| 122150 | 122371 | ** zero. |
| 122151 | 122372 | */ |
| 122152 | 122373 | typedef struct ParseContext ParseContext; |
| 122153 | 122374 | struct ParseContext { |
| 122154 | 122375 | sqlite3_tokenizer *pTokenizer; /* Tokenizer module */ |
| 122376 | + int iLangid; /* Language id used with tokenizer */ | |
| 122155 | 122377 | const char **azCol; /* Array of column names for fts3 table */ |
| 122156 | 122378 | int bFts4; /* True to allow FTS4-only syntax */ |
| 122157 | 122379 | int nCol; /* Number of entries in azCol[] */ |
| 122158 | 122380 | int iDefaultCol; /* Default column to query */ |
| 122159 | 122381 | int isNot; /* True if getNextNode() sees a unary - */ |
| @@ -122185,10 +122407,37 @@ | ||
| 122185 | 122407 | void *pRet = sqlite3_malloc(nByte); |
| 122186 | 122408 | if( pRet ) memset(pRet, 0, nByte); |
| 122187 | 122409 | return pRet; |
| 122188 | 122410 | } |
| 122189 | 122411 | |
| 122412 | +SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer( | |
| 122413 | + sqlite3_tokenizer *pTokenizer, | |
| 122414 | + int iLangid, | |
| 122415 | + const char *z, | |
| 122416 | + int n, | |
| 122417 | + sqlite3_tokenizer_cursor **ppCsr | |
| 122418 | +){ | |
| 122419 | + sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; | |
| 122420 | + sqlite3_tokenizer_cursor *pCsr = 0; | |
| 122421 | + int rc; | |
| 122422 | + | |
| 122423 | + rc = pModule->xOpen(pTokenizer, z, n, &pCsr); | |
| 122424 | + assert( rc==SQLITE_OK || pCsr==0 ); | |
| 122425 | + if( rc==SQLITE_OK ){ | |
| 122426 | + pCsr->pTokenizer = pTokenizer; | |
| 122427 | + if( pModule->iVersion>=1 ){ | |
| 122428 | + rc = pModule->xLanguageid(pCsr, iLangid); | |
| 122429 | + if( rc!=SQLITE_OK ){ | |
| 122430 | + pModule->xClose(pCsr); | |
| 122431 | + pCsr = 0; | |
| 122432 | + } | |
| 122433 | + } | |
| 122434 | + } | |
| 122435 | + *ppCsr = pCsr; | |
| 122436 | + return rc; | |
| 122437 | +} | |
| 122438 | + | |
| 122190 | 122439 | |
| 122191 | 122440 | /* |
| 122192 | 122441 | ** Extract the next token from buffer z (length n) using the tokenizer |
| 122193 | 122442 | ** and other information (column names etc.) in pParse. Create an Fts3Expr |
| 122194 | 122443 | ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this |
| @@ -122212,19 +122461,17 @@ | ||
| 122212 | 122461 | int rc; |
| 122213 | 122462 | sqlite3_tokenizer_cursor *pCursor; |
| 122214 | 122463 | Fts3Expr *pRet = 0; |
| 122215 | 122464 | int nConsumed = 0; |
| 122216 | 122465 | |
| 122217 | - rc = pModule->xOpen(pTokenizer, z, n, &pCursor); | |
| 122466 | + rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); | |
| 122218 | 122467 | if( rc==SQLITE_OK ){ |
| 122219 | 122468 | const char *zToken; |
| 122220 | 122469 | int nToken, iStart, iEnd, iPosition; |
| 122221 | 122470 | int nByte; /* total space to allocate */ |
| 122222 | 122471 | |
| 122223 | - pCursor->pTokenizer = pTokenizer; | |
| 122224 | 122472 | rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); |
| 122225 | - | |
| 122226 | 122473 | if( rc==SQLITE_OK ){ |
| 122227 | 122474 | nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; |
| 122228 | 122475 | pRet = (Fts3Expr *)fts3MallocZero(nByte); |
| 122229 | 122476 | if( !pRet ){ |
| 122230 | 122477 | rc = SQLITE_NOMEM; |
| @@ -122326,14 +122573,14 @@ | ||
| 122326 | 122573 | ** |
| 122327 | 122574 | ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below, |
| 122328 | 122575 | ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase |
| 122329 | 122576 | ** structures. |
| 122330 | 122577 | */ |
| 122331 | - rc = pModule->xOpen(pTokenizer, zInput, nInput, &pCursor); | |
| 122578 | + rc = sqlite3Fts3OpenTokenizer( | |
| 122579 | + pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); | |
| 122332 | 122580 | if( rc==SQLITE_OK ){ |
| 122333 | 122581 | int ii; |
| 122334 | - pCursor->pTokenizer = pTokenizer; | |
| 122335 | 122582 | for(ii=0; rc==SQLITE_OK; ii++){ |
| 122336 | 122583 | const char *zByte; |
| 122337 | 122584 | int nByte, iBegin, iEnd, iPos; |
| 122338 | 122585 | rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos); |
| 122339 | 122586 | if( rc==SQLITE_OK ){ |
| @@ -122803,10 +123050,11 @@ | ||
| 122803 | 123050 | ** specified as part of the query string), or -1 if tokens may by default |
| 122804 | 123051 | ** match any table column. |
| 122805 | 123052 | */ |
| 122806 | 123053 | SQLITE_PRIVATE int sqlite3Fts3ExprParse( |
| 122807 | 123054 | sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ |
| 123055 | + int iLangid, /* Language id for tokenizer */ | |
| 122808 | 123056 | char **azCol, /* Array of column names for fts3 table */ |
| 122809 | 123057 | int bFts4, /* True to allow FTS4-only syntax */ |
| 122810 | 123058 | int nCol, /* Number of entries in azCol[] */ |
| 122811 | 123059 | int iDefaultCol, /* Default column to query */ |
| 122812 | 123060 | const char *z, int n, /* Text of MATCH query */ |
| @@ -122813,15 +123061,17 @@ | ||
| 122813 | 123061 | Fts3Expr **ppExpr /* OUT: Parsed query structure */ |
| 122814 | 123062 | ){ |
| 122815 | 123063 | int nParsed; |
| 122816 | 123064 | int rc; |
| 122817 | 123065 | ParseContext sParse; |
| 123066 | + | |
| 123067 | + memset(&sParse, 0, sizeof(ParseContext)); | |
| 122818 | 123068 | sParse.pTokenizer = pTokenizer; |
| 123069 | + sParse.iLangid = iLangid; | |
| 122819 | 123070 | sParse.azCol = (const char **)azCol; |
| 122820 | 123071 | sParse.nCol = nCol; |
| 122821 | 123072 | sParse.iDefaultCol = iDefaultCol; |
| 122822 | - sParse.nNest = 0; | |
| 122823 | 123073 | sParse.bFts4 = bFts4; |
| 122824 | 123074 | if( z==0 ){ |
| 122825 | 123075 | *ppExpr = 0; |
| 122826 | 123076 | return SQLITE_OK; |
| 122827 | 123077 | } |
| @@ -123008,11 +123258,11 @@ | ||
| 123008 | 123258 | for(ii=0; ii<nCol; ii++){ |
| 123009 | 123259 | azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); |
| 123010 | 123260 | } |
| 123011 | 123261 | |
| 123012 | 123262 | rc = sqlite3Fts3ExprParse( |
| 123013 | - pTokenizer, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr | |
| 123263 | + pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr | |
| 123014 | 123264 | ); |
| 123015 | 123265 | if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ |
| 123016 | 123266 | sqlite3_result_error(context, "Error parsing expression", -1); |
| 123017 | 123267 | }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){ |
| 123018 | 123268 | sqlite3_result_error_nomem(context); |
| @@ -124057,10 +124307,11 @@ | ||
| 124057 | 124307 | porterCreate, |
| 124058 | 124308 | porterDestroy, |
| 124059 | 124309 | porterOpen, |
| 124060 | 124310 | porterClose, |
| 124061 | 124311 | porterNext, |
| 124312 | + 0 | |
| 124062 | 124313 | }; |
| 124063 | 124314 | |
| 124064 | 124315 | /* |
| 124065 | 124316 | ** Allocate a new porter tokenizer. Return a pointer to the new |
| 124066 | 124317 | ** tokenizer in *ppModule |
| @@ -124362,15 +124613,14 @@ | ||
| 124362 | 124613 | if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){ |
| 124363 | 124614 | zErr = "error in xCreate()"; |
| 124364 | 124615 | goto finish; |
| 124365 | 124616 | } |
| 124366 | 124617 | pTokenizer->pModule = p; |
| 124367 | - if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){ | |
| 124618 | + if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){ | |
| 124368 | 124619 | zErr = "error in xOpen()"; |
| 124369 | 124620 | goto finish; |
| 124370 | 124621 | } |
| 124371 | - pCsr->pTokenizer = pTokenizer; | |
| 124372 | 124622 | |
| 124373 | 124623 | while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ |
| 124374 | 124624 | Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); |
| 124375 | 124625 | Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); |
| 124376 | 124626 | zToken = &zInput[iStart]; |
| @@ -124782,10 +125032,11 @@ | ||
| 124782 | 125032 | simpleCreate, |
| 124783 | 125033 | simpleDestroy, |
| 124784 | 125034 | simpleOpen, |
| 124785 | 125035 | simpleClose, |
| 124786 | 125036 | simpleNext, |
| 125037 | + 0, | |
| 124787 | 125038 | }; |
| 124788 | 125039 | |
| 124789 | 125040 | /* |
| 124790 | 125041 | ** Allocate a new simple tokenizer. Return a pointer to the new |
| 124791 | 125042 | ** tokenizer in *ppModule |
| @@ -125031,10 +125282,12 @@ | ||
| 125031 | 125282 | #define SQL_SELECT_ALL_PREFIX_LEVEL 24 |
| 125032 | 125283 | #define SQL_DELETE_ALL_TERMS_SEGDIR 25 |
| 125033 | 125284 | |
| 125034 | 125285 | #define SQL_DELETE_SEGDIR_RANGE 26 |
| 125035 | 125286 | |
| 125287 | +#define SQL_SELECT_ALL_LANGID 27 | |
| 125288 | + | |
| 125036 | 125289 | /* |
| 125037 | 125290 | ** This function is used to obtain an SQLite prepared statement handle |
| 125038 | 125291 | ** for the statement identified by the second argument. If successful, |
| 125039 | 125292 | ** *pp is set to the requested statement handle and SQLITE_OK returned. |
| 125040 | 125293 | ** Otherwise, an SQLite error code is returned and *pp is set to 0. |
| @@ -125084,10 +125337,11 @@ | ||
| 125084 | 125337 | /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)", |
| 125085 | 125338 | /* 24 */ "", |
| 125086 | 125339 | /* 25 */ "", |
| 125087 | 125340 | |
| 125088 | 125341 | /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", |
| 125342 | +/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'", | |
| 125089 | 125343 | |
| 125090 | 125344 | }; |
| 125091 | 125345 | int rc = SQLITE_OK; |
| 125092 | 125346 | sqlite3_stmt *pStmt; |
| 125093 | 125347 | |
| @@ -125229,10 +125483,23 @@ | ||
| 125229 | 125483 | rc = SQLITE_OK; |
| 125230 | 125484 | } |
| 125231 | 125485 | |
| 125232 | 125486 | return rc; |
| 125233 | 125487 | } |
| 125488 | + | |
| 125489 | +static sqlite3_int64 getAbsoluteLevel( | |
| 125490 | + Fts3Table *p, | |
| 125491 | + int iLangid, | |
| 125492 | + int iIndex, | |
| 125493 | + int iLevel | |
| 125494 | +){ | |
| 125495 | + assert( iLangid>=0 ); | |
| 125496 | + assert( p->nIndex>0 ); | |
| 125497 | + assert( iIndex>=0 && iIndex<p->nIndex ); | |
| 125498 | + return (iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL + iLevel; | |
| 125499 | +} | |
| 125500 | + | |
| 125234 | 125501 | |
| 125235 | 125502 | /* |
| 125236 | 125503 | ** Set *ppStmt to a statement handle that may be used to iterate through |
| 125237 | 125504 | ** all rows in the %_segdir table, from oldest to newest. If successful, |
| 125238 | 125505 | ** return SQLITE_OK. If an error occurs while preparing the statement, |
| @@ -125249,10 +125516,11 @@ | ||
| 125249 | 125516 | ** 3: end_block |
| 125250 | 125517 | ** 4: root |
| 125251 | 125518 | */ |
| 125252 | 125519 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs( |
| 125253 | 125520 | Fts3Table *p, /* FTS3 table */ |
| 125521 | + int iLangid, /* Language being queried */ | |
| 125254 | 125522 | int iIndex, /* Index for p->aIndex[] */ |
| 125255 | 125523 | int iLevel, /* Level to select */ |
| 125256 | 125524 | sqlite3_stmt **ppStmt /* OUT: Compiled statement */ |
| 125257 | 125525 | ){ |
| 125258 | 125526 | int rc; |
| @@ -125264,18 +125532,20 @@ | ||
| 125264 | 125532 | |
| 125265 | 125533 | if( iLevel<0 ){ |
| 125266 | 125534 | /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */ |
| 125267 | 125535 | rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0); |
| 125268 | 125536 | if( rc==SQLITE_OK ){ |
| 125269 | - sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL); | |
| 125270 | - sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL-1); | |
| 125537 | + sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); | |
| 125538 | + sqlite3_bind_int(pStmt, 2, | |
| 125539 | + getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) | |
| 125540 | + ); | |
| 125271 | 125541 | } |
| 125272 | 125542 | }else{ |
| 125273 | 125543 | /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */ |
| 125274 | 125544 | rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); |
| 125275 | 125545 | if( rc==SQLITE_OK ){ |
| 125276 | - sqlite3_bind_int(pStmt, 1, iLevel+iIndex*FTS3_SEGDIR_MAXLEVEL); | |
| 125546 | + sqlite3_bind_int(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)); | |
| 125277 | 125547 | } |
| 125278 | 125548 | } |
| 125279 | 125549 | *ppStmt = pStmt; |
| 125280 | 125550 | return rc; |
| 125281 | 125551 | } |
| @@ -125437,10 +125707,11 @@ | ||
| 125437 | 125707 | ** |
| 125438 | 125708 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. |
| 125439 | 125709 | */ |
| 125440 | 125710 | static int fts3PendingTermsAdd( |
| 125441 | 125711 | Fts3Table *p, /* Table into which text will be inserted */ |
| 125712 | + int iLangid, /* Language id to use */ | |
| 125442 | 125713 | const char *zText, /* Text of document to be inserted */ |
| 125443 | 125714 | int iCol, /* Column into which text is being inserted */ |
| 125444 | 125715 | u32 *pnWord /* OUT: Number of tokens inserted */ |
| 125445 | 125716 | ){ |
| 125446 | 125717 | int rc; |
| @@ -125466,15 +125737,14 @@ | ||
| 125466 | 125737 | if( zText==0 ){ |
| 125467 | 125738 | *pnWord = 0; |
| 125468 | 125739 | return SQLITE_OK; |
| 125469 | 125740 | } |
| 125470 | 125741 | |
| 125471 | - rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr); | |
| 125742 | + rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr); | |
| 125472 | 125743 | if( rc!=SQLITE_OK ){ |
| 125473 | 125744 | return rc; |
| 125474 | 125745 | } |
| 125475 | - pCsr->pTokenizer = pTokenizer; | |
| 125476 | 125746 | |
| 125477 | 125747 | xNext = pModule->xNext; |
| 125478 | 125748 | while( SQLITE_OK==rc |
| 125479 | 125749 | && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) |
| 125480 | 125750 | ){ |
| @@ -125513,22 +125783,32 @@ | ||
| 125513 | 125783 | /* |
| 125514 | 125784 | ** Calling this function indicates that subsequent calls to |
| 125515 | 125785 | ** fts3PendingTermsAdd() are to add term/position-list pairs for the |
| 125516 | 125786 | ** contents of the document with docid iDocid. |
| 125517 | 125787 | */ |
| 125518 | -static int fts3PendingTermsDocid(Fts3Table *p, sqlite_int64 iDocid){ | |
| 125788 | +static int fts3PendingTermsDocid( | |
| 125789 | + Fts3Table *p, /* Full-text table handle */ | |
| 125790 | + int iLangid, /* Language id of row being written */ | |
| 125791 | + sqlite_int64 iDocid /* Docid of row being written */ | |
| 125792 | +){ | |
| 125793 | + assert( iLangid>=0 ); | |
| 125794 | + | |
| 125519 | 125795 | /* TODO(shess) Explore whether partially flushing the buffer on |
| 125520 | 125796 | ** forced-flush would provide better performance. I suspect that if |
| 125521 | 125797 | ** we ordered the doclists by size and flushed the largest until the |
| 125522 | 125798 | ** buffer was half empty, that would let the less frequent terms |
| 125523 | 125799 | ** generate longer doclists. |
| 125524 | 125800 | */ |
| 125525 | - if( iDocid<=p->iPrevDocid || p->nPendingData>p->nMaxPendingData ){ | |
| 125801 | + if( iDocid<=p->iPrevDocid | |
| 125802 | + || p->iPrevLangid!=iLangid | |
| 125803 | + || p->nPendingData>p->nMaxPendingData | |
| 125804 | + ){ | |
| 125526 | 125805 | int rc = sqlite3Fts3PendingTermsFlush(p); |
| 125527 | 125806 | if( rc!=SQLITE_OK ) return rc; |
| 125528 | 125807 | } |
| 125529 | 125808 | p->iPrevDocid = iDocid; |
| 125809 | + p->iPrevLangid = iLangid; | |
| 125530 | 125810 | return SQLITE_OK; |
| 125531 | 125811 | } |
| 125532 | 125812 | |
| 125533 | 125813 | /* |
| 125534 | 125814 | ** Discard the contents of the pending-terms hash tables. |
| @@ -125553,15 +125833,20 @@ | ||
| 125553 | 125833 | ** pendingTerms hash table. |
| 125554 | 125834 | ** |
| 125555 | 125835 | ** Argument apVal is the same as the similarly named argument passed to |
| 125556 | 125836 | ** fts3InsertData(). Parameter iDocid is the docid of the new row. |
| 125557 | 125837 | */ |
| 125558 | -static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){ | |
| 125838 | +static int fts3InsertTerms( | |
| 125839 | + Fts3Table *p, | |
| 125840 | + int iLangid, | |
| 125841 | + sqlite3_value **apVal, | |
| 125842 | + u32 *aSz | |
| 125843 | +){ | |
| 125559 | 125844 | int i; /* Iterator variable */ |
| 125560 | 125845 | for(i=2; i<p->nColumn+2; i++){ |
| 125561 | 125846 | const char *zText = (const char *)sqlite3_value_text(apVal[i]); |
| 125562 | - int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]); | |
| 125847 | + int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]); | |
| 125563 | 125848 | if( rc!=SQLITE_OK ){ |
| 125564 | 125849 | return rc; |
| 125565 | 125850 | } |
| 125566 | 125851 | aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]); |
| 125567 | 125852 | } |
| @@ -125578,10 +125863,11 @@ | ||
| 125578 | 125863 | ** apVal[2] Left-most user-defined column |
| 125579 | 125864 | ** ... |
| 125580 | 125865 | ** apVal[p->nColumn+1] Right-most user-defined column |
| 125581 | 125866 | ** apVal[p->nColumn+2] Hidden column with same name as table |
| 125582 | 125867 | ** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid) |
| 125868 | +** apVal[p->nColumn+4] Hidden languageid column | |
| 125583 | 125869 | */ |
| 125584 | 125870 | static int fts3InsertData( |
| 125585 | 125871 | Fts3Table *p, /* Full-text table */ |
| 125586 | 125872 | sqlite3_value **apVal, /* Array of values to insert */ |
| 125587 | 125873 | sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */ |
| @@ -125608,13 +125894,17 @@ | ||
| 125608 | 125894 | ** |
| 125609 | 125895 | ** The statement features N '?' variables, where N is the number of user |
| 125610 | 125896 | ** defined columns in the FTS3 table, plus one for the docid field. |
| 125611 | 125897 | */ |
| 125612 | 125898 | rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]); |
| 125613 | - if( rc!=SQLITE_OK ){ | |
| 125614 | - return rc; | |
| 125899 | + if( rc==SQLITE_OK && p->zLanguageid ){ | |
| 125900 | + rc = sqlite3_bind_int( | |
| 125901 | + pContentInsert, p->nColumn+2, | |
| 125902 | + sqlite3_value_int(apVal[p->nColumn+4]) | |
| 125903 | + ); | |
| 125615 | 125904 | } |
| 125905 | + if( rc!=SQLITE_OK ) return rc; | |
| 125616 | 125906 | |
| 125617 | 125907 | /* There is a quirk here. The users INSERT statement may have specified |
| 125618 | 125908 | ** a value for the "rowid" field, for the "docid" field, or for both. |
| 125619 | 125909 | ** Which is a problem, since "rowid" and "docid" are aliases for the |
| 125620 | 125910 | ** same value. For example: |
| @@ -125669,10 +125959,19 @@ | ||
| 125669 | 125959 | if( p->bHasStat ){ |
| 125670 | 125960 | fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); |
| 125671 | 125961 | } |
| 125672 | 125962 | return rc; |
| 125673 | 125963 | } |
| 125964 | + | |
| 125965 | +/* | |
| 125966 | +** | |
| 125967 | +*/ | |
| 125968 | +static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){ | |
| 125969 | + int iLangid = 0; | |
| 125970 | + if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1); | |
| 125971 | + return iLangid; | |
| 125972 | +} | |
| 125674 | 125973 | |
| 125675 | 125974 | /* |
| 125676 | 125975 | ** The first element in the apVal[] array is assumed to contain the docid |
| 125677 | 125976 | ** (an integer) of a row about to be deleted. Remove all terms from the |
| 125678 | 125977 | ** full-text index. |
| @@ -125689,19 +125988,21 @@ | ||
| 125689 | 125988 | if( *pRC ) return; |
| 125690 | 125989 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); |
| 125691 | 125990 | if( rc==SQLITE_OK ){ |
| 125692 | 125991 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 125693 | 125992 | int i; |
| 125694 | - for(i=1; i<=p->nColumn; i++){ | |
| 125993 | + int iLangid = langidFromSelect(p, pSelect); | |
| 125994 | + rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); | |
| 125995 | + for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ | |
| 125695 | 125996 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 125696 | - rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]); | |
| 125697 | - if( rc!=SQLITE_OK ){ | |
| 125698 | - sqlite3_reset(pSelect); | |
| 125699 | - *pRC = rc; | |
| 125700 | - return; | |
| 125701 | - } | |
| 125997 | + rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]); | |
| 125702 | 125998 | aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); |
| 125999 | + } | |
| 126000 | + if( rc!=SQLITE_OK ){ | |
| 126001 | + sqlite3_reset(pSelect); | |
| 126002 | + *pRC = rc; | |
| 126003 | + return; | |
| 125703 | 126004 | } |
| 125704 | 126005 | } |
| 125705 | 126006 | rc = sqlite3_reset(pSelect); |
| 125706 | 126007 | }else{ |
| 125707 | 126008 | sqlite3_reset(pSelect); |
| @@ -125711,11 +126012,11 @@ | ||
| 125711 | 126012 | |
| 125712 | 126013 | /* |
| 125713 | 126014 | ** Forward declaration to account for the circular dependency between |
| 125714 | 126015 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| 125715 | 126016 | */ |
| 125716 | -static int fts3SegmentMerge(Fts3Table *, int, int); | |
| 126017 | +static int fts3SegmentMerge(Fts3Table *, int, int, int); | |
| 125717 | 126018 | |
| 125718 | 126019 | /* |
| 125719 | 126020 | ** This function allocates a new level iLevel index in the segdir table. |
| 125720 | 126021 | ** Usually, indexes are allocated within a level sequentially starting |
| 125721 | 126022 | ** with 0, so the allocated index is one greater than the value returned |
| @@ -125730,22 +126031,28 @@ | ||
| 125730 | 126031 | ** If successful, *piIdx is set to the allocated index slot and SQLITE_OK |
| 125731 | 126032 | ** returned. Otherwise, an SQLite error code is returned. |
| 125732 | 126033 | */ |
| 125733 | 126034 | static int fts3AllocateSegdirIdx( |
| 125734 | 126035 | Fts3Table *p, |
| 126036 | + int iLangid, /* Language id */ | |
| 125735 | 126037 | int iIndex, /* Index for p->aIndex */ |
| 125736 | 126038 | int iLevel, |
| 125737 | 126039 | int *piIdx |
| 125738 | 126040 | ){ |
| 125739 | 126041 | int rc; /* Return Code */ |
| 125740 | 126042 | sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ |
| 125741 | 126043 | int iNext = 0; /* Result of query pNextIdx */ |
| 125742 | 126044 | |
| 126045 | + assert( iLangid>=0 ); | |
| 126046 | + assert( p->nIndex>=1 ); | |
| 126047 | + | |
| 125743 | 126048 | /* Set variable iNext to the next available segdir index at level iLevel. */ |
| 125744 | 126049 | rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); |
| 125745 | 126050 | if( rc==SQLITE_OK ){ |
| 125746 | - sqlite3_bind_int(pNextIdx, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel); | |
| 126051 | + sqlite3_bind_int64( | |
| 126052 | + pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) | |
| 126053 | + ); | |
| 125747 | 126054 | if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ |
| 125748 | 126055 | iNext = sqlite3_column_int(pNextIdx, 0); |
| 125749 | 126056 | } |
| 125750 | 126057 | rc = sqlite3_reset(pNextIdx); |
| 125751 | 126058 | } |
| @@ -125755,11 +126062,11 @@ | ||
| 125755 | 126062 | ** full, merge all segments in level iLevel into a single iLevel+1 |
| 125756 | 126063 | ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise, |
| 125757 | 126064 | ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext. |
| 125758 | 126065 | */ |
| 125759 | 126066 | if( iNext>=FTS3_MERGE_COUNT ){ |
| 125760 | - rc = fts3SegmentMerge(p, iIndex, iLevel); | |
| 126067 | + rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel); | |
| 125761 | 126068 | *piIdx = 0; |
| 125762 | 126069 | }else{ |
| 125763 | 126070 | *piIdx = iNext; |
| 125764 | 126071 | } |
| 125765 | 126072 | } |
| @@ -126978,11 +127285,16 @@ | ||
| 126978 | 127285 | ** |
| 126979 | 127286 | ** Segment levels are stored in the 'level' column of the %_segdir table. |
| 126980 | 127287 | ** |
| 126981 | 127288 | ** Return SQLITE_OK if successful, or an SQLite error code if not. |
| 126982 | 127289 | */ |
| 126983 | -static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){ | |
| 127290 | +static int fts3SegmentMaxLevel( | |
| 127291 | + Fts3Table *p, | |
| 127292 | + int iLangid, | |
| 127293 | + int iIndex, | |
| 127294 | + int *pnMax | |
| 127295 | +){ | |
| 126984 | 127296 | sqlite3_stmt *pStmt; |
| 126985 | 127297 | int rc; |
| 126986 | 127298 | assert( iIndex>=0 && iIndex<p->nIndex ); |
| 126987 | 127299 | |
| 126988 | 127300 | /* Set pStmt to the compiled version of: |
| @@ -126991,12 +127303,14 @@ | ||
| 126991 | 127303 | ** |
| 126992 | 127304 | ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). |
| 126993 | 127305 | */ |
| 126994 | 127306 | rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); |
| 126995 | 127307 | if( rc!=SQLITE_OK ) return rc; |
| 126996 | - sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL); | |
| 126997 | - sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL - 1); | |
| 127308 | + sqlite3_bind_int(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); | |
| 127309 | + sqlite3_bind_int(pStmt, 2, | |
| 127310 | + getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) | |
| 127311 | + ); | |
| 126998 | 127312 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 126999 | 127313 | *pnMax = sqlite3_column_int(pStmt, 0); |
| 127000 | 127314 | } |
| 127001 | 127315 | return sqlite3_reset(pStmt); |
| 127002 | 127316 | } |
| @@ -127015,10 +127329,11 @@ | ||
| 127015 | 127329 | ** |
| 127016 | 127330 | ** SQLITE_OK is returned if successful, otherwise an SQLite error code. |
| 127017 | 127331 | */ |
| 127018 | 127332 | static int fts3DeleteSegdir( |
| 127019 | 127333 | Fts3Table *p, /* Virtual table handle */ |
| 127334 | + int iLangid, /* Language id */ | |
| 127020 | 127335 | int iIndex, /* Index for p->aIndex */ |
| 127021 | 127336 | int iLevel, /* Level of %_segdir entries to delete */ |
| 127022 | 127337 | Fts3SegReader **apSegment, /* Array of SegReader objects */ |
| 127023 | 127338 | int nReader /* Size of array apSegment */ |
| 127024 | 127339 | ){ |
| @@ -127042,17 +127357,19 @@ | ||
| 127042 | 127357 | |
| 127043 | 127358 | assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL ); |
| 127044 | 127359 | if( iLevel==FTS3_SEGCURSOR_ALL ){ |
| 127045 | 127360 | rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0); |
| 127046 | 127361 | if( rc==SQLITE_OK ){ |
| 127047 | - sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL); | |
| 127048 | - sqlite3_bind_int(pDelete, 2, (iIndex+1) * FTS3_SEGDIR_MAXLEVEL - 1); | |
| 127362 | + sqlite3_bind_int(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); | |
| 127363 | + sqlite3_bind_int(pDelete, 2, | |
| 127364 | + getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) | |
| 127365 | + ); | |
| 127049 | 127366 | } |
| 127050 | 127367 | }else{ |
| 127051 | 127368 | rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0); |
| 127052 | 127369 | if( rc==SQLITE_OK ){ |
| 127053 | - sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel); | |
| 127370 | + sqlite3_bind_int(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel)); | |
| 127054 | 127371 | } |
| 127055 | 127372 | } |
| 127056 | 127373 | |
| 127057 | 127374 | if( rc==SQLITE_OK ){ |
| 127058 | 127375 | sqlite3_step(pDelete); |
| @@ -127517,27 +127834,32 @@ | ||
| 127517 | 127834 | ** If this function is called with iLevel<0, but there is only one |
| 127518 | 127835 | ** segment in the database, SQLITE_DONE is returned immediately. |
| 127519 | 127836 | ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, |
| 127520 | 127837 | ** an SQLite error code is returned. |
| 127521 | 127838 | */ |
| 127522 | -static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){ | |
| 127839 | +static int fts3SegmentMerge( | |
| 127840 | + Fts3Table *p, | |
| 127841 | + int iLangid, /* Language id to merge */ | |
| 127842 | + int iIndex, /* Index in p->aIndex[] to merge */ | |
| 127843 | + int iLevel /* Level to merge */ | |
| 127844 | +){ | |
| 127523 | 127845 | int rc; /* Return code */ |
| 127524 | 127846 | int iIdx = 0; /* Index of new segment */ |
| 127525 | 127847 | int iNewLevel = 0; /* Level/index to create new segment at */ |
| 127526 | 127848 | SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */ |
| 127527 | 127849 | Fts3SegFilter filter; /* Segment term filter condition */ |
| 127528 | - Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ | |
| 127850 | + Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ | |
| 127529 | 127851 | int bIgnoreEmpty = 0; /* True to ignore empty segments */ |
| 127530 | 127852 | |
| 127531 | 127853 | assert( iLevel==FTS3_SEGCURSOR_ALL |
| 127532 | 127854 | || iLevel==FTS3_SEGCURSOR_PENDING |
| 127533 | 127855 | || iLevel>=0 |
| 127534 | 127856 | ); |
| 127535 | 127857 | assert( iLevel<FTS3_SEGDIR_MAXLEVEL ); |
| 127536 | 127858 | assert( iIndex>=0 && iIndex<p->nIndex ); |
| 127537 | 127859 | |
| 127538 | - rc = sqlite3Fts3SegReaderCursor(p, iIndex, iLevel, 0, 0, 1, 0, &csr); | |
| 127860 | + rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr); | |
| 127539 | 127861 | if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished; |
| 127540 | 127862 | |
| 127541 | 127863 | if( iLevel==FTS3_SEGCURSOR_ALL ){ |
| 127542 | 127864 | /* This call is to merge all segments in the database to a single |
| 127543 | 127865 | ** segment. The level of the new segment is equal to the the numerically |
| @@ -127545,28 +127867,28 @@ | ||
| 127545 | 127867 | ** index. The idx of the new segment is always 0. */ |
| 127546 | 127868 | if( csr.nSegment==1 ){ |
| 127547 | 127869 | rc = SQLITE_DONE; |
| 127548 | 127870 | goto finished; |
| 127549 | 127871 | } |
| 127550 | - rc = fts3SegmentMaxLevel(p, iIndex, &iNewLevel); | |
| 127872 | + rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel); | |
| 127551 | 127873 | bIgnoreEmpty = 1; |
| 127552 | 127874 | |
| 127553 | 127875 | }else if( iLevel==FTS3_SEGCURSOR_PENDING ){ |
| 127554 | - iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL; | |
| 127555 | - rc = fts3AllocateSegdirIdx(p, iIndex, 0, &iIdx); | |
| 127876 | + iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0); | |
| 127877 | + rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx); | |
| 127556 | 127878 | }else{ |
| 127557 | 127879 | /* This call is to merge all segments at level iLevel. find the next |
| 127558 | 127880 | ** available segment index at level iLevel+1. The call to |
| 127559 | 127881 | ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to |
| 127560 | 127882 | ** a single iLevel+2 segment if necessary. */ |
| 127561 | - rc = fts3AllocateSegdirIdx(p, iIndex, iLevel+1, &iIdx); | |
| 127562 | - iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL + iLevel+1; | |
| 127883 | + rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx); | |
| 127884 | + iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1); | |
| 127563 | 127885 | } |
| 127564 | 127886 | if( rc!=SQLITE_OK ) goto finished; |
| 127565 | 127887 | assert( csr.nSegment>0 ); |
| 127566 | - assert( iNewLevel>=(iIndex*FTS3_SEGDIR_MAXLEVEL) ); | |
| 127567 | - assert( iNewLevel<((iIndex+1)*FTS3_SEGDIR_MAXLEVEL) ); | |
| 127888 | + assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) ); | |
| 127889 | + assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) ); | |
| 127568 | 127890 | |
| 127569 | 127891 | memset(&filter, 0, sizeof(Fts3SegFilter)); |
| 127570 | 127892 | filter.flags = FTS3_SEGMENT_REQUIRE_POS; |
| 127571 | 127893 | filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0); |
| 127572 | 127894 | |
| @@ -127579,11 +127901,13 @@ | ||
| 127579 | 127901 | } |
| 127580 | 127902 | if( rc!=SQLITE_OK ) goto finished; |
| 127581 | 127903 | assert( pWriter ); |
| 127582 | 127904 | |
| 127583 | 127905 | if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
| 127584 | - rc = fts3DeleteSegdir(p, iIndex, iLevel, csr.apSegment, csr.nSegment); | |
| 127906 | + rc = fts3DeleteSegdir( | |
| 127907 | + p, iLangid, iIndex, iLevel, csr.apSegment, csr.nSegment | |
| 127908 | + ); | |
| 127585 | 127909 | if( rc!=SQLITE_OK ) goto finished; |
| 127586 | 127910 | } |
| 127587 | 127911 | rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx); |
| 127588 | 127912 | |
| 127589 | 127913 | finished: |
| @@ -127598,11 +127922,11 @@ | ||
| 127598 | 127922 | */ |
| 127599 | 127923 | SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ |
| 127600 | 127924 | int rc = SQLITE_OK; |
| 127601 | 127925 | int i; |
| 127602 | 127926 | for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){ |
| 127603 | - rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_PENDING); | |
| 127927 | + rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING); | |
| 127604 | 127928 | if( rc==SQLITE_DONE ) rc = SQLITE_OK; |
| 127605 | 127929 | } |
| 127606 | 127930 | sqlite3Fts3PendingTermsClear(p); |
| 127607 | 127931 | return rc; |
| 127608 | 127932 | } |
| @@ -127753,21 +128077,38 @@ | ||
| 127753 | 128077 | sqlite3_step(pStmt); |
| 127754 | 128078 | *pRC = sqlite3_reset(pStmt); |
| 127755 | 128079 | sqlite3_free(a); |
| 127756 | 128080 | } |
| 127757 | 128081 | |
| 128082 | +/* | |
| 128083 | +** Merge the entire database so that there is one segment for each | |
| 128084 | +** iIndex/iLangid combination. | |
| 128085 | +*/ | |
| 127758 | 128086 | static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ |
| 127759 | - int i; | |
| 127760 | 128087 | int bSeenDone = 0; |
| 127761 | - int rc = SQLITE_OK; | |
| 127762 | - for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){ | |
| 127763 | - rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_ALL); | |
| 127764 | - if( rc==SQLITE_DONE ){ | |
| 127765 | - bSeenDone = 1; | |
| 127766 | - rc = SQLITE_OK; | |
| 127767 | - } | |
| 127768 | - } | |
| 128088 | + int rc; | |
| 128089 | + sqlite3_stmt *pAllLangid = 0; | |
| 128090 | + | |
| 128091 | + rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); | |
| 128092 | + if( rc==SQLITE_OK ){ | |
| 128093 | + int rc2; | |
| 128094 | + sqlite3_bind_int(pAllLangid, 1, p->nIndex); | |
| 128095 | + while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ | |
| 128096 | + int i; | |
| 128097 | + int iLangid = sqlite3_column_int(pAllLangid, 0); | |
| 128098 | + for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){ | |
| 128099 | + rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL); | |
| 128100 | + if( rc==SQLITE_DONE ){ | |
| 128101 | + bSeenDone = 1; | |
| 128102 | + rc = SQLITE_OK; | |
| 128103 | + } | |
| 128104 | + } | |
| 128105 | + } | |
| 128106 | + rc2 = sqlite3_reset(pAllLangid); | |
| 128107 | + if( rc==SQLITE_OK ) rc = rc2; | |
| 128108 | + } | |
| 128109 | + | |
| 127769 | 128110 | sqlite3Fts3SegmentsClose(p); |
| 127770 | 128111 | sqlite3Fts3PendingTermsClear(p); |
| 127771 | 128112 | |
| 127772 | 128113 | return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc; |
| 127773 | 128114 | } |
| @@ -127814,15 +128155,16 @@ | ||
| 127814 | 128155 | } |
| 127815 | 128156 | } |
| 127816 | 128157 | |
| 127817 | 128158 | while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 127818 | 128159 | int iCol; |
| 127819 | - rc = fts3PendingTermsDocid(p, sqlite3_column_int64(pStmt, 0)); | |
| 128160 | + int iLangid = langidFromSelect(p, pStmt); | |
| 128161 | + rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); | |
| 127820 | 128162 | aSz[p->nColumn] = 0; |
| 127821 | 128163 | for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ |
| 127822 | 128164 | const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); |
| 127823 | - rc = fts3PendingTermsAdd(p, z, iCol, &aSz[iCol]); | |
| 128165 | + rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); | |
| 127824 | 128166 | aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); |
| 127825 | 128167 | } |
| 127826 | 128168 | if( p->bHasDocsize ){ |
| 127827 | 128169 | fts3InsertDocsize(&rc, p, aSz); |
| 127828 | 128170 | } |
| @@ -127937,18 +128279,17 @@ | ||
| 127937 | 128279 | |
| 127938 | 128280 | for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){ |
| 127939 | 128281 | const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); |
| 127940 | 128282 | sqlite3_tokenizer_cursor *pTC = 0; |
| 127941 | 128283 | |
| 127942 | - rc = pModule->xOpen(pT, zText, -1, &pTC); | |
| 128284 | + rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); | |
| 127943 | 128285 | while( rc==SQLITE_OK ){ |
| 127944 | 128286 | char const *zToken; /* Buffer containing token */ |
| 127945 | 128287 | int nToken; /* Number of bytes in token */ |
| 127946 | 128288 | int iDum1, iDum2; /* Dummy variables */ |
| 127947 | 128289 | int iPos; /* Position of token in zText */ |
| 127948 | 128290 | |
| 127949 | - pTC->pTokenizer = pT; | |
| 127950 | 128291 | rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos); |
| 127951 | 128292 | for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ |
| 127952 | 128293 | Fts3PhraseToken *pPT = pDef->pToken; |
| 127953 | 128294 | if( (pDef->iCol>=p->nColumn || pDef->iCol==i) |
| 127954 | 128295 | && (pPT->bFirst==0 || iPos==0) |
| @@ -128044,12 +128385,10 @@ | ||
| 128044 | 128385 | ** delete the contents of all three tables and throw away any |
| 128045 | 128386 | ** data in the pendingTerms hash table. */ |
| 128046 | 128387 | rc = fts3DeleteAll(p, 1); |
| 128047 | 128388 | *pnDoc = *pnDoc - 1; |
| 128048 | 128389 | }else{ |
| 128049 | - sqlite3_int64 iRemove = sqlite3_value_int64(pRowid); | |
| 128050 | - rc = fts3PendingTermsDocid(p, iRemove); | |
| 128051 | 128390 | fts3DeleteTerms(&rc, p, pRowid, aSzDel); |
| 128052 | 128391 | if( p->zContentTbl==0 ){ |
| 128053 | 128392 | fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid); |
| 128054 | 128393 | if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1; |
| 128055 | 128394 | }else{ |
| @@ -128064,11 +128403,20 @@ | ||
| 128064 | 128403 | return rc; |
| 128065 | 128404 | } |
| 128066 | 128405 | |
| 128067 | 128406 | /* |
| 128068 | 128407 | ** This function does the work for the xUpdate method of FTS3 virtual |
| 128069 | -** tables. | |
| 128408 | +** tables. The schema of the virtual table being: | |
| 128409 | +** | |
| 128410 | +** CREATE TABLE <table name>( | |
| 128411 | +** <user COLUMns>, | |
| 128412 | +** <table name> HIDDEN, | |
| 128413 | +** docid HIDDEN, | |
| 128414 | +** <langid> HIDDEN | |
| 128415 | +** ); | |
| 128416 | +** | |
| 128417 | +** | |
| 128070 | 128418 | */ |
| 128071 | 128419 | SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( |
| 128072 | 128420 | sqlite3_vtab *pVtab, /* FTS3 vtab object */ |
| 128073 | 128421 | int nArg, /* Size of argument array */ |
| 128074 | 128422 | sqlite3_value **apVal, /* Array of arguments */ |
| @@ -128081,10 +128429,14 @@ | ||
| 128081 | 128429 | u32 *aSzDel; /* Sizes of deleted documents */ |
| 128082 | 128430 | int nChng = 0; /* Net change in number of documents */ |
| 128083 | 128431 | int bInsertDone = 0; |
| 128084 | 128432 | |
| 128085 | 128433 | assert( p->pSegments==0 ); |
| 128434 | + assert( | |
| 128435 | + nArg==1 /* DELETE operations */ | |
| 128436 | + || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */ | |
| 128437 | + ); | |
| 128086 | 128438 | |
| 128087 | 128439 | /* Check for a "special" INSERT operation. One of the form: |
| 128088 | 128440 | ** |
| 128089 | 128441 | ** INSERT INTO xyz(xyz) VALUES('command'); |
| 128090 | 128442 | */ |
| @@ -128093,10 +128445,15 @@ | ||
| 128093 | 128445 | && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL |
| 128094 | 128446 | ){ |
| 128095 | 128447 | rc = fts3SpecialInsert(p, apVal[p->nColumn+2]); |
| 128096 | 128448 | goto update_out; |
| 128097 | 128449 | } |
| 128450 | + | |
| 128451 | + if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ | |
| 128452 | + rc = SQLITE_CONSTRAINT; | |
| 128453 | + goto update_out; | |
| 128454 | + } | |
| 128098 | 128455 | |
| 128099 | 128456 | /* Allocate space to hold the change in document sizes */ |
| 128100 | 128457 | aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 ); |
| 128101 | 128458 | if( aSzIns==0 ){ |
| 128102 | 128459 | rc = SQLITE_NOMEM; |
| @@ -128161,22 +128518,23 @@ | ||
| 128161 | 128518 | isRemove = 1; |
| 128162 | 128519 | } |
| 128163 | 128520 | |
| 128164 | 128521 | /* If this is an INSERT or UPDATE operation, insert the new record. */ |
| 128165 | 128522 | if( nArg>1 && rc==SQLITE_OK ){ |
| 128523 | + int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]); | |
| 128166 | 128524 | if( bInsertDone==0 ){ |
| 128167 | 128525 | rc = fts3InsertData(p, apVal, pRowid); |
| 128168 | 128526 | if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ |
| 128169 | 128527 | rc = FTS_CORRUPT_VTAB; |
| 128170 | 128528 | } |
| 128171 | 128529 | } |
| 128172 | 128530 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ |
| 128173 | - rc = fts3PendingTermsDocid(p, *pRowid); | |
| 128531 | + rc = fts3PendingTermsDocid(p, iLangid, *pRowid); | |
| 128174 | 128532 | } |
| 128175 | 128533 | if( rc==SQLITE_OK ){ |
| 128176 | 128534 | assert( p->iPrevDocid==*pRowid ); |
| 128177 | - rc = fts3InsertTerms(p, apVal, aSzIns); | |
| 128535 | + rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); | |
| 128178 | 128536 | } |
| 128179 | 128537 | if( p->bHasDocsize ){ |
| 128180 | 128538 | fts3InsertDocsize(&rc, p, aSzIns); |
| 128181 | 128539 | } |
| 128182 | 128540 | nChng++; |
| @@ -128749,10 +129107,11 @@ | ||
| 128749 | 129107 | ** is no way for fts3BestSnippet() to know whether or not the document |
| 128750 | 129108 | ** actually contains terms that follow the final highlighted term. |
| 128751 | 129109 | */ |
| 128752 | 129110 | static int fts3SnippetShift( |
| 128753 | 129111 | Fts3Table *pTab, /* FTS3 table snippet comes from */ |
| 129112 | + int iLangid, /* Language id to use in tokenizing */ | |
| 128754 | 129113 | int nSnippet, /* Number of tokens desired for snippet */ |
| 128755 | 129114 | const char *zDoc, /* Document text to extract snippet from */ |
| 128756 | 129115 | int nDoc, /* Size of buffer zDoc in bytes */ |
| 128757 | 129116 | int *piPos, /* IN/OUT: First token of snippet */ |
| 128758 | 129117 | u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */ |
| @@ -128784,15 +129143,14 @@ | ||
| 128784 | 129143 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 128785 | 129144 | |
| 128786 | 129145 | /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) |
| 128787 | 129146 | ** or more tokens in zDoc/nDoc. |
| 128788 | 129147 | */ |
| 128789 | - rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); | |
| 129148 | + rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); | |
| 128790 | 129149 | if( rc!=SQLITE_OK ){ |
| 128791 | 129150 | return rc; |
| 128792 | 129151 | } |
| 128793 | - pC->pTokenizer = pTab->pTokenizer; | |
| 128794 | 129152 | while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ |
| 128795 | 129153 | const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3; |
| 128796 | 129154 | rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); |
| 128797 | 129155 | } |
| 128798 | 129156 | pMod->xClose(pC); |
| @@ -128848,15 +129206,14 @@ | ||
| 128848 | 129206 | } |
| 128849 | 129207 | nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); |
| 128850 | 129208 | |
| 128851 | 129209 | /* Open a token cursor on the document. */ |
| 128852 | 129210 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 128853 | - rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); | |
| 129211 | + rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC); | |
| 128854 | 129212 | if( rc!=SQLITE_OK ){ |
| 128855 | 129213 | return rc; |
| 128856 | 129214 | } |
| 128857 | - pC->pTokenizer = pTab->pTokenizer; | |
| 128858 | 129215 | |
| 128859 | 129216 | while( rc==SQLITE_OK ){ |
| 128860 | 129217 | int iBegin; /* Offset in zDoc of start of token */ |
| 128861 | 129218 | int iFin; /* Offset in zDoc of end of token */ |
| 128862 | 129219 | int isHighlight; /* True for highlighted terms */ |
| @@ -128874,11 +129231,13 @@ | ||
| 128874 | 129231 | } |
| 128875 | 129232 | if( iCurrent<iPos ){ continue; } |
| 128876 | 129233 | |
| 128877 | 129234 | if( !isShiftDone ){ |
| 128878 | 129235 | int n = nDoc - iBegin; |
| 128879 | - rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask); | |
| 129236 | + rc = fts3SnippetShift( | |
| 129237 | + pTab, pCsr->iLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask | |
| 129238 | + ); | |
| 128880 | 129239 | isShiftDone = 1; |
| 128881 | 129240 | |
| 128882 | 129241 | /* Now that the shift has been done, check if the initial "..." are |
| 128883 | 129242 | ** required. They are required if (a) this is not the first fragment, |
| 128884 | 129243 | ** or (b) this fragment does not begin at position 0 of its column. |
| @@ -129607,13 +129966,14 @@ | ||
| 129607 | 129966 | rc = SQLITE_NOMEM; |
| 129608 | 129967 | goto offsets_out; |
| 129609 | 129968 | } |
| 129610 | 129969 | |
| 129611 | 129970 | /* Initialize a tokenizer iterator to iterate through column iCol. */ |
| 129612 | - rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); | |
| 129971 | + rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, | |
| 129972 | + zDoc, nDoc, &pC | |
| 129973 | + ); | |
| 129613 | 129974 | if( rc!=SQLITE_OK ) goto offsets_out; |
| 129614 | - pC->pTokenizer = pTab->pTokenizer; | |
| 129615 | 129975 | |
| 129616 | 129976 | rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); |
| 129617 | 129977 | while( rc==SQLITE_OK ){ |
| 129618 | 129978 | int i; /* Used to loop through terms */ |
| 129619 | 129979 | int iMinPos = 0x7FFFFFFF; /* Position of next token */ |
| 129620 | 129980 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -657,11 +657,11 @@ | |
| 657 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 658 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 659 | */ |
| 660 | #define SQLITE_VERSION "3.7.11" |
| 661 | #define SQLITE_VERSION_NUMBER 3007011 |
| 662 | #define SQLITE_SOURCE_ID "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130" |
| 663 | |
| 664 | /* |
| 665 | ** CAPI3REF: Run-Time Library Version Numbers |
| 666 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 667 | ** |
| @@ -1009,10 +1009,11 @@ | |
| 1009 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 1010 | #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) |
| 1011 | #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) |
| 1012 | #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) |
| 1013 | #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) |
| 1014 | |
| 1015 | /* |
| 1016 | ** CAPI3REF: Flags For File Open Operations |
| 1017 | ** |
| 1018 | ** These bit values are intended for use in the |
| @@ -1264,31 +1265,35 @@ | |
| 1264 | ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], |
| 1265 | ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) |
| 1266 | ** into an integer that the pArg argument points to. This capability |
| 1267 | ** is used during testing and only needs to be supported when SQLITE_TEST |
| 1268 | ** is defined. |
| 1269 | ** |
| 1270 | ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS |
| 1271 | ** layer a hint of how large the database file will grow to be during the |
| 1272 | ** current transaction. This hint is not guaranteed to be accurate but it |
| 1273 | ** is often close. The underlying VFS might choose to preallocate database |
| 1274 | ** file space based on this hint in order to help writes to the database |
| 1275 | ** file run faster. |
| 1276 | ** |
| 1277 | ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS |
| 1278 | ** extends and truncates the database file in chunks of a size specified |
| 1279 | ** by the user. The fourth argument to [sqlite3_file_control()] should |
| 1280 | ** point to an integer (type int) containing the new chunk-size to use |
| 1281 | ** for the nominated database. Allocating database file space in large |
| 1282 | ** chunks (say 1MB at a time), may reduce file-system fragmentation and |
| 1283 | ** improve performance on some systems. |
| 1284 | ** |
| 1285 | ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer |
| 1286 | ** to the [sqlite3_file] object associated with a particular database |
| 1287 | ** connection. See the [sqlite3_file_control()] documentation for |
| 1288 | ** additional information. |
| 1289 | ** |
| 1290 | ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by |
| 1291 | ** SQLite and sent to all VFSes in place of a call to the xSync method |
| 1292 | ** when the database connection has [PRAGMA synchronous] set to OFF.)^ |
| 1293 | ** Some specialized VFSes need this signal in order to operate correctly |
| 1294 | ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most |
| @@ -1295,10 +1300,11 @@ | |
| 1295 | ** VFSes do not need this signal and should silently ignore this opcode. |
| 1296 | ** Applications should not call [sqlite3_file_control()] with this |
| 1297 | ** opcode as doing so may disrupt the operation of the specialized VFSes |
| 1298 | ** that do require it. |
| 1299 | ** |
| 1300 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 1301 | ** retry counts and intervals for certain disk I/O operations for the |
| 1302 | ** windows [VFS] in order to provide robustness in the presence of |
| 1303 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 1304 | ** file write, and file delete operations up to 10 times, with a delay |
| @@ -1311,10 +1317,11 @@ | |
| 1311 | ** integer is the delay. If either integer is negative, then the setting |
| 1312 | ** is not changed but instead the prior value of that setting is written |
| 1313 | ** into the array entry, allowing the current retry settings to be |
| 1314 | ** interrogated. The zDbName parameter is ignored. |
| 1315 | ** |
| 1316 | ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the |
| 1317 | ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary |
| 1318 | ** write ahead log and shared memory files used for transaction control |
| 1319 | ** are automatically deleted when the latest connection to the database |
| 1320 | ** closes. Setting persistent WAL mode causes those files to persist after |
| @@ -1325,24 +1332,27 @@ | |
| 1325 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 1326 | ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent |
| 1327 | ** WAL mode. If the integer is -1, then it is overwritten with the current |
| 1328 | ** WAL persistence setting. |
| 1329 | ** |
| 1330 | ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the |
| 1331 | ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting |
| 1332 | ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the |
| 1333 | ** xDeviceCharacteristics methods. The fourth parameter to |
| 1334 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 1335 | ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage |
| 1336 | ** mode. If the integer is -1, then it is overwritten with the current |
| 1337 | ** zero-damage mode setting. |
| 1338 | ** |
| 1339 | ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening |
| 1340 | ** a write transaction to indicate that, unless it is rolled back for some |
| 1341 | ** reason, the entire database file will be overwritten by the current |
| 1342 | ** transaction. This is used by VACUUM operations. |
| 1343 | ** |
| 1344 | ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of |
| 1345 | ** all [VFSes] in the VFS stack. The names are of all VFS shims and the |
| 1346 | ** final bottom-level VFS are written into memory obtained from |
| 1347 | ** [sqlite3_malloc()] and the result is stored in the char* variable |
| 1348 | ** that the fourth parameter of [sqlite3_file_control()] points to. |
| @@ -1349,10 +1359,34 @@ | |
| 1349 | ** The caller is responsible for freeing the memory when done. As with |
| 1350 | ** all file-control actions, there is no guarantee that this will actually |
| 1351 | ** do anything. Callers should initialize the char* variable to a NULL |
| 1352 | ** pointer in case this file-control is not implemented. This file-control |
| 1353 | ** is intended for diagnostic use only. |
| 1354 | */ |
| 1355 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 1356 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 1357 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 1358 | #define SQLITE_LAST_ERRNO 4 |
| @@ -1363,10 +1397,11 @@ | |
| 1363 | #define SQLITE_FCNTL_WIN32_AV_RETRY 9 |
| 1364 | #define SQLITE_FCNTL_PERSIST_WAL 10 |
| 1365 | #define SQLITE_FCNTL_OVERWRITE 11 |
| 1366 | #define SQLITE_FCNTL_VFSNAME 12 |
| 1367 | #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 |
| 1368 | |
| 1369 | /* |
| 1370 | ** CAPI3REF: Mutex Handle |
| 1371 | ** |
| 1372 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -5012,10 +5047,19 @@ | |
| 5012 | ** will be an absolute pathname, even if the filename used |
| 5013 | ** to open the database originally was a URI or relative pathname. |
| 5014 | */ |
| 5015 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); |
| 5016 | |
| 5017 | /* |
| 5018 | ** CAPI3REF: Find the next prepared statement |
| 5019 | ** |
| 5020 | ** ^This interface returns a pointer to the next [prepared statement] after |
| 5021 | ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL |
| @@ -7137,15 +7181,16 @@ | |
| 7137 | |
| 7138 | |
| 7139 | /* |
| 7140 | ** CAPI3REF: String Comparison |
| 7141 | ** |
| 7142 | ** ^The [sqlite3_strnicmp()] API allows applications and extensions to |
| 7143 | ** compare the contents of two buffers containing UTF-8 strings in a |
| 7144 | ** case-independent fashion, using the same definition of case independence |
| 7145 | ** that SQLite uses internally when comparing identifiers. |
| 7146 | */ |
| 7147 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 7148 | |
| 7149 | /* |
| 7150 | ** CAPI3REF: Error Logging Interface |
| 7151 | ** |
| @@ -8204,11 +8249,11 @@ | |
| 8204 | SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); |
| 8205 | SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); |
| 8206 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); |
| 8207 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); |
| 8208 | SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); |
| 8209 | SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*); |
| 8210 | SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); |
| 8211 | SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); |
| 8212 | SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); |
| 8213 | SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); |
| 8214 | SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); |
| @@ -8944,10 +8989,13 @@ | |
| 8944 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); |
| 8945 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 8946 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 8947 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 8948 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); |
| 8949 | |
| 8950 | /* Functions used to query pager state and configuration. */ |
| 8951 | SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); |
| 8952 | SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| 8953 | SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); |
| @@ -11415,11 +11463,11 @@ | |
| 11415 | #endif |
| 11416 | |
| 11417 | /* |
| 11418 | ** Internal function prototypes |
| 11419 | */ |
| 11420 | SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *); |
| 11421 | SQLITE_PRIVATE int sqlite3Strlen30(const char*); |
| 11422 | #define sqlite3StrNICmp sqlite3_strnicmp |
| 11423 | |
| 11424 | SQLITE_PRIVATE int sqlite3MallocInit(void); |
| 11425 | SQLITE_PRIVATE void sqlite3MallocEnd(void); |
| @@ -11563,10 +11611,11 @@ | |
| 11563 | SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*); |
| 11564 | SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); |
| 11565 | SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*); |
| 11566 | SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, |
| 11567 | sqlite3_vfs**,char**,char **); |
| 11568 | SQLITE_PRIVATE int sqlite3CodeOnce(Parse *); |
| 11569 | |
| 11570 | SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32); |
| 11571 | SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32); |
| 11572 | SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); |
| @@ -11662,11 +11711,11 @@ | |
| 11662 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); |
| 11663 | SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); |
| 11664 | SQLITE_PRIVATE void sqlite3PrngSaveState(void); |
| 11665 | SQLITE_PRIVATE void sqlite3PrngRestoreState(void); |
| 11666 | SQLITE_PRIVATE void sqlite3PrngResetState(void); |
| 11667 | SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*); |
| 11668 | SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); |
| 11669 | SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); |
| 11670 | SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int); |
| 11671 | SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*); |
| 11672 | SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*); |
| @@ -21216,11 +21265,11 @@ | |
| 21216 | ** applications and extensions to compare the contents of two buffers |
| 21217 | ** containing UTF-8 strings in a case-independent fashion, using the same |
| 21218 | ** definition of case independence that SQLite uses internally when |
| 21219 | ** comparing identifiers. |
| 21220 | */ |
| 21221 | SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){ |
| 21222 | register unsigned char *a, *b; |
| 21223 | a = (unsigned char *)zLeft; |
| 21224 | b = (unsigned char *)zRight; |
| 21225 | while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } |
| 21226 | return UpperToLower[*a] - UpperToLower[*b]; |
| @@ -25494,11 +25543,11 @@ | |
| 25494 | ** recover the hot journals. |
| 25495 | */ |
| 25496 | static int robust_open(const char *z, int f, mode_t m){ |
| 25497 | int rc; |
| 25498 | mode_t m2; |
| 25499 | mode_t origM; |
| 25500 | if( m==0 ){ |
| 25501 | m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; |
| 25502 | }else{ |
| 25503 | m2 = m; |
| 25504 | origM = osUmask(0); |
| @@ -38302,10 +38351,11 @@ | |
| 38302 | # define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 38303 | # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 |
| 38304 | # define sqlite3WalCallback(z) 0 |
| 38305 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 38306 | # define sqlite3WalHeapMemory(z) 0 |
| 38307 | #else |
| 38308 | |
| 38309 | #define WAL_SAVEPOINT_NDATA 4 |
| 38310 | |
| 38311 | /* Connection to a write-ahead log (WAL) file. |
| @@ -38382,10 +38432,17 @@ | |
| 38382 | /* Return true if the argument is non-NULL and the WAL module is using |
| 38383 | ** heap-memory for the wal-index. Otherwise, if the argument is NULL or the |
| 38384 | ** WAL module is using shared-memory, return false. |
| 38385 | */ |
| 38386 | SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); |
| 38387 | |
| 38388 | #endif /* ifndef SQLITE_OMIT_WAL */ |
| 38389 | #endif /* _WAL_H_ */ |
| 38390 | |
| 38391 | /************** End of wal.h *************************************************/ |
| @@ -45237,10 +45294,24 @@ | |
| 45237 | pPager->pWal = 0; |
| 45238 | } |
| 45239 | } |
| 45240 | return rc; |
| 45241 | } |
| 45242 | |
| 45243 | #ifdef SQLITE_HAS_CODEC |
| 45244 | /* |
| 45245 | ** This function is called by the wal module when writing page content |
| 45246 | ** into the log file. |
| @@ -47657,11 +47728,11 @@ | |
| 47657 | testcase( sz<=32768 ); |
| 47658 | testcase( sz>=65536 ); |
| 47659 | iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; |
| 47660 | *pInWal = 1; |
| 47661 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ |
| 47662 | return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset); |
| 47663 | } |
| 47664 | |
| 47665 | *pInWal = 0; |
| 47666 | return SQLITE_OK; |
| 47667 | } |
| @@ -48327,10 +48398,22 @@ | |
| 48327 | ** WAL module is using shared-memory, return false. |
| 48328 | */ |
| 48329 | SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ |
| 48330 | return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ); |
| 48331 | } |
| 48332 | |
| 48333 | #endif /* #ifndef SQLITE_OMIT_WAL */ |
| 48334 | |
| 48335 | /************** End of wal.c *************************************************/ |
| 48336 | /************** Begin file btmutex.c *****************************************/ |
| @@ -51320,11 +51403,11 @@ | |
| 51320 | |
| 51321 | /* Rollback any active transaction and free the handle structure. |
| 51322 | ** The call to sqlite3BtreeRollback() drops any table-locks held by |
| 51323 | ** this handle. |
| 51324 | */ |
| 51325 | sqlite3BtreeRollback(p); |
| 51326 | sqlite3BtreeLeave(p); |
| 51327 | |
| 51328 | /* If there are still other outstanding references to the shared-btree |
| 51329 | ** structure, return now. The remainder of this procedure cleans |
| 51330 | ** up the shared-btree. |
| @@ -52558,10 +52641,11 @@ | |
| 52558 | ** save the state of the cursor. The cursor must be |
| 52559 | ** invalidated. |
| 52560 | */ |
| 52561 | SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ |
| 52562 | BtCursor *p; |
| 52563 | sqlite3BtreeEnter(pBtree); |
| 52564 | for(p=pBtree->pBt->pCursor; p; p=p->pNext){ |
| 52565 | int i; |
| 52566 | sqlite3BtreeClearCursor(p); |
| 52567 | p->eState = CURSOR_FAULT; |
| @@ -52581,29 +52665,24 @@ | |
| 52581 | ** in an error. |
| 52582 | ** |
| 52583 | ** This will release the write lock on the database file. If there |
| 52584 | ** are no active cursors, it also releases the read lock. |
| 52585 | */ |
| 52586 | SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p){ |
| 52587 | int rc; |
| 52588 | BtShared *pBt = p->pBt; |
| 52589 | MemPage *pPage1; |
| 52590 | |
| 52591 | sqlite3BtreeEnter(p); |
| 52592 | rc = saveAllCursors(pBt, 0, 0); |
| 52593 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 52594 | if( rc!=SQLITE_OK ){ |
| 52595 | /* This is a horrible situation. An IO or malloc() error occurred whilst |
| 52596 | ** trying to save cursor positions. If this is an automatic rollback (as |
| 52597 | ** the result of a constraint, malloc() failure or IO error) then |
| 52598 | ** the cache may be internally inconsistent (not contain valid trees) so |
| 52599 | ** we cannot simply return the error to the caller. Instead, abort |
| 52600 | ** all queries that may be using any of the cursors that failed to save. |
| 52601 | */ |
| 52602 | sqlite3BtreeTripAllCursors(p, rc); |
| 52603 | } |
| 52604 | #endif |
| 52605 | btreeIntegrity(p); |
| 52606 | |
| 52607 | if( p->inTrans==TRANS_WRITE ){ |
| 52608 | int rc2; |
| 52609 | |
| @@ -58121,11 +58200,11 @@ | |
| 58121 | } |
| 58122 | *pp = p->pNext; |
| 58123 | } |
| 58124 | |
| 58125 | /* If a transaction is still open on the Btree, roll it back. */ |
| 58126 | sqlite3BtreeRollback(p->pDest); |
| 58127 | |
| 58128 | /* Set the error code of the destination database handle. */ |
| 58129 | rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; |
| 58130 | sqlite3Error(p->pDestDb, rc, 0); |
| 58131 | |
| @@ -61431,36 +61510,10 @@ | |
| 61431 | } |
| 61432 | #else |
| 61433 | #define checkActiveVdbeCnt(x) |
| 61434 | #endif |
| 61435 | |
| 61436 | /* |
| 61437 | ** For every Btree that in database connection db which |
| 61438 | ** has been modified, "trip" or invalidate each cursor in |
| 61439 | ** that Btree might have been modified so that the cursor |
| 61440 | ** can never be used again. This happens when a rollback |
| 61441 | *** occurs. We have to trip all the other cursors, even |
| 61442 | ** cursor from other VMs in different database connections, |
| 61443 | ** so that none of them try to use the data at which they |
| 61444 | ** were pointing and which now may have been changed due |
| 61445 | ** to the rollback. |
| 61446 | ** |
| 61447 | ** Remember that a rollback can delete tables complete and |
| 61448 | ** reorder rootpages. So it is not sufficient just to save |
| 61449 | ** the state of the cursor. We have to invalidate the cursor |
| 61450 | ** so that it is never used again. |
| 61451 | */ |
| 61452 | static void invalidateCursorsOnModifiedBtrees(sqlite3 *db){ |
| 61453 | int i; |
| 61454 | for(i=0; i<db->nDb; i++){ |
| 61455 | Btree *p = db->aDb[i].pBt; |
| 61456 | if( p && sqlite3BtreeIsInTrans(p) ){ |
| 61457 | sqlite3BtreeTripAllCursors(p, SQLITE_ABORT); |
| 61458 | } |
| 61459 | } |
| 61460 | } |
| 61461 | |
| 61462 | /* |
| 61463 | ** If the Vdbe passed as the first argument opened a statement-transaction, |
| 61464 | ** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or |
| 61465 | ** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement |
| 61466 | ** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the |
| @@ -61621,12 +61674,11 @@ | |
| 61621 | eStatementOp = SAVEPOINT_ROLLBACK; |
| 61622 | }else{ |
| 61623 | /* We are forced to roll back the active transaction. Before doing |
| 61624 | ** so, abort any other statements this handle currently has active. |
| 61625 | */ |
| 61626 | invalidateCursorsOnModifiedBtrees(db); |
| 61627 | sqlite3RollbackAll(db); |
| 61628 | sqlite3CloseSavepoints(db); |
| 61629 | db->autoCommit = 1; |
| 61630 | } |
| 61631 | } |
| 61632 | } |
| @@ -61664,27 +61716,26 @@ | |
| 61664 | if( rc==SQLITE_BUSY && p->readOnly ){ |
| 61665 | sqlite3VdbeLeave(p); |
| 61666 | return SQLITE_BUSY; |
| 61667 | }else if( rc!=SQLITE_OK ){ |
| 61668 | p->rc = rc; |
| 61669 | sqlite3RollbackAll(db); |
| 61670 | }else{ |
| 61671 | db->nDeferredCons = 0; |
| 61672 | sqlite3CommitInternalChanges(db); |
| 61673 | } |
| 61674 | }else{ |
| 61675 | sqlite3RollbackAll(db); |
| 61676 | } |
| 61677 | db->nStatement = 0; |
| 61678 | }else if( eStatementOp==0 ){ |
| 61679 | if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ |
| 61680 | eStatementOp = SAVEPOINT_RELEASE; |
| 61681 | }else if( p->errorAction==OE_Abort ){ |
| 61682 | eStatementOp = SAVEPOINT_ROLLBACK; |
| 61683 | }else{ |
| 61684 | invalidateCursorsOnModifiedBtrees(db); |
| 61685 | sqlite3RollbackAll(db); |
| 61686 | sqlite3CloseSavepoints(db); |
| 61687 | db->autoCommit = 1; |
| 61688 | } |
| 61689 | } |
| 61690 | |
| @@ -61700,12 +61751,11 @@ | |
| 61700 | if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){ |
| 61701 | p->rc = rc; |
| 61702 | sqlite3DbFree(db, p->zErrMsg); |
| 61703 | p->zErrMsg = 0; |
| 61704 | } |
| 61705 | invalidateCursorsOnModifiedBtrees(db); |
| 61706 | sqlite3RollbackAll(db); |
| 61707 | sqlite3CloseSavepoints(db); |
| 61708 | db->autoCommit = 1; |
| 61709 | } |
| 61710 | } |
| 61711 | |
| @@ -67513,20 +67563,16 @@ | |
| 67513 | u.ar.iSavepoint++; |
| 67514 | } |
| 67515 | if( !u.ar.pSavepoint ){ |
| 67516 | sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName); |
| 67517 | rc = SQLITE_ERROR; |
| 67518 | }else if( |
| 67519 | db->writeVdbeCnt>0 || (u.ar.p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1) |
| 67520 | ){ |
| 67521 | /* It is not possible to release (commit) a savepoint if there are |
| 67522 | ** active write statements. It is not possible to rollback a savepoint |
| 67523 | ** if there are any active statements at all. |
| 67524 | */ |
| 67525 | sqlite3SetString(&p->zErrMsg, db, |
| 67526 | "cannot %s savepoint - SQL statements in progress", |
| 67527 | (u.ar.p1==SAVEPOINT_ROLLBACK ? "rollback": "release") |
| 67528 | ); |
| 67529 | rc = SQLITE_BUSY; |
| 67530 | }else{ |
| 67531 | |
| 67532 | /* Determine whether or not this is a transaction savepoint. If so, |
| @@ -67547,10 +67593,13 @@ | |
| 67547 | } |
| 67548 | db->isTransactionSavepoint = 0; |
| 67549 | rc = p->rc; |
| 67550 | }else{ |
| 67551 | u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1; |
| 67552 | for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){ |
| 67553 | rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint); |
| 67554 | if( rc!=SQLITE_OK ){ |
| 67555 | goto abort_due_to_error; |
| 67556 | } |
| @@ -67617,29 +67666,32 @@ | |
| 67617 | u.as.turnOnAC = u.as.desiredAutoCommit && !db->autoCommit; |
| 67618 | assert( u.as.desiredAutoCommit==1 || u.as.desiredAutoCommit==0 ); |
| 67619 | assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 ); |
| 67620 | assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ |
| 67621 | |
| 67622 | if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){ |
| 67623 | /* If this instruction implements a ROLLBACK and other VMs are |
| 67624 | ** still running, and a transaction is active, return an error indicating |
| 67625 | ** that the other VMs must complete first. |
| 67626 | */ |
| 67627 | sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - " |
| 67628 | "SQL statements in progress"); |
| 67629 | rc = SQLITE_BUSY; |
| 67630 | }else if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){ |
| 67631 | /* If this instruction implements a COMMIT and other VMs are writing |
| 67632 | ** return an error indicating that the other VMs must complete first. |
| 67633 | */ |
| 67634 | sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - " |
| 67635 | "SQL statements in progress"); |
| 67636 | rc = SQLITE_BUSY; |
| 67637 | }else if( u.as.desiredAutoCommit!=db->autoCommit ){ |
| 67638 | if( u.as.iRollback ){ |
| 67639 | assert( u.as.desiredAutoCommit==1 ); |
| 67640 | sqlite3RollbackAll(db); |
| 67641 | db->autoCommit = 1; |
| 67642 | }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ |
| 67643 | goto vdbe_return; |
| 67644 | }else{ |
| 67645 | db->autoCommit = (u8)u.as.desiredAutoCommit; |
| @@ -68701,11 +68753,11 @@ | |
| 68701 | u.bg.v = 1; /* IMP: R-61914-48074 */ |
| 68702 | }else{ |
| 68703 | assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) ); |
| 68704 | rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v); |
| 68705 | assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ |
| 68706 | if( u.bg.v==MAX_ROWID ){ |
| 68707 | u.bg.pC->useRandomRowid = 1; |
| 68708 | }else{ |
| 68709 | u.bg.v++; /* IMP: R-29538-34987 */ |
| 68710 | } |
| 68711 | } |
| @@ -92317,13 +92369,16 @@ | |
| 92317 | char *zLeft = 0; /* Nul-terminated UTF-8 string <id> */ |
| 92318 | char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */ |
| 92319 | const char *zDb = 0; /* The database name */ |
| 92320 | Token *pId; /* Pointer to <id> token */ |
| 92321 | int iDb; /* Database index for <database> */ |
| 92322 | sqlite3 *db = pParse->db; |
| 92323 | Db *pDb; |
| 92324 | Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); |
| 92325 | if( v==0 ) return; |
| 92326 | sqlite3VdbeRunOnlyOnce(v); |
| 92327 | pParse->nMem = 2; |
| 92328 | |
| 92329 | /* Interpret the [database.] part of the pragma statement. iDb is the |
| @@ -92350,10 +92405,38 @@ | |
| 92350 | assert( pId2 ); |
| 92351 | zDb = pId2->n>0 ? pDb->zName : 0; |
| 92352 | if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ |
| 92353 | goto pragma_out; |
| 92354 | } |
| 92355 | |
| 92356 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
| 92357 | /* |
| 92358 | ** PRAGMA [database.]default_cache_size |
| 92359 | ** PRAGMA [database.]default_cache_size=N |
| @@ -92637,11 +92720,11 @@ | |
| 92637 | /* Call SetAutoVacuum() to set initialize the internal auto and |
| 92638 | ** incr-vacuum flags. This is required in case this connection |
| 92639 | ** creates the database file. It is important that it is created |
| 92640 | ** as an auto-vacuum capable db. |
| 92641 | */ |
| 92642 | int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); |
| 92643 | if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ |
| 92644 | /* When setting the auto_vacuum mode to either "full" or |
| 92645 | ** "incremental", write the value of meta[6] in the database |
| 92646 | ** file. Before writing to meta[6], check that meta[3] indicates |
| 92647 | ** that this really is an auto-vacuum capable database. |
| @@ -92755,11 +92838,10 @@ | |
| 92755 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
| 92756 | } |
| 92757 | }else{ |
| 92758 | #ifndef SQLITE_OMIT_WSD |
| 92759 | if( zRight[0] ){ |
| 92760 | int rc; |
| 92761 | int res; |
| 92762 | rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); |
| 92763 | if( rc!=SQLITE_OK || res==0 ){ |
| 92764 | sqlite3ErrorMsg(pParse, "not a writable directory"); |
| 92765 | goto pragma_out; |
| @@ -95671,11 +95753,11 @@ | |
| 95671 | int nCol; /* Number of columns in the result set */ |
| 95672 | Expr *p; /* Expression for a single result column */ |
| 95673 | char *zName; /* Column name */ |
| 95674 | int nName; /* Size of name in zName[] */ |
| 95675 | |
| 95676 | *pnCol = nCol = pEList->nExpr; |
| 95677 | aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); |
| 95678 | if( aCol==0 ) return SQLITE_NOMEM; |
| 95679 | for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
| 95680 | /* Get an appropriate name for the column |
| 95681 | */ |
| @@ -101201,10 +101283,22 @@ | |
| 101201 | char *zKey; |
| 101202 | sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); |
| 101203 | if( nKey ) db->nextPagesize = 0; |
| 101204 | } |
| 101205 | #endif |
| 101206 | |
| 101207 | /* Do not attempt to change the page size for a WAL database */ |
| 101208 | if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain)) |
| 101209 | ==PAGER_JOURNALMODE_WAL ){ |
| 101210 | db->nextPagesize = 0; |
| @@ -101215,24 +101309,16 @@ | |
| 101215 | || NEVER(db->mallocFailed) |
| 101216 | ){ |
| 101217 | rc = SQLITE_NOMEM; |
| 101218 | goto end_of_vacuum; |
| 101219 | } |
| 101220 | rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); |
| 101221 | if( rc!=SQLITE_OK ){ |
| 101222 | goto end_of_vacuum; |
| 101223 | } |
| 101224 | |
| 101225 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 101226 | sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : |
| 101227 | sqlite3BtreeGetAutoVacuum(pMain)); |
| 101228 | #endif |
| 101229 | |
| 101230 | /* Begin a transaction */ |
| 101231 | rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;"); |
| 101232 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 101233 | |
| 101234 | /* Query the schema of the main database. Create a mirror schema |
| 101235 | ** in the temporary database. |
| 101236 | */ |
| 101237 | rc = execExecSql(db, pzErrMsg, |
| 101238 | "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " |
| @@ -105543,11 +105629,13 @@ | |
| 105543 | } |
| 105544 | |
| 105545 | /* If there is a DISTINCT qualifier and this index will scan rows in |
| 105546 | ** order of the DISTINCT expressions, clear bDist and set the appropriate |
| 105547 | ** flags in wsFlags. */ |
| 105548 | if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){ |
| 105549 | bDist = 0; |
| 105550 | wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT; |
| 105551 | } |
| 105552 | |
| 105553 | /* If currently calculating the cost of using an index (not the IPK |
| @@ -106240,12 +106328,11 @@ | |
| 106240 | */ |
| 106241 | static Bitmask codeOneLoopStart( |
| 106242 | WhereInfo *pWInfo, /* Complete information about the WHERE clause */ |
| 106243 | int iLevel, /* Which level of pWInfo->a[] should be coded */ |
| 106244 | u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ |
| 106245 | Bitmask notReady, /* Which tables are currently available */ |
| 106246 | Expr *pWhere /* Complete WHERE clause */ |
| 106247 | ){ |
| 106248 | int j, k; /* Loop counters */ |
| 106249 | int iCur; /* The VDBE cursor for the table */ |
| 106250 | int addrNxt; /* Where to jump to continue with the next IN case */ |
| 106251 | int omitTable; /* True if we use the index only */ |
| @@ -106780,14 +106867,29 @@ | |
| 106780 | |
| 106781 | /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y |
| 106782 | ** Then for every term xN, evaluate as the subexpression: xN AND z |
| 106783 | ** That way, terms in y that are factored into the disjunction will |
| 106784 | ** be picked up by the recursive calls to sqlite3WhereBegin() below. |
| 106785 | */ |
| 106786 | if( pWC->nTerm>1 ){ |
| 106787 | pAndExpr = sqlite3ExprAlloc(pParse->db, TK_AND, 0, 0); |
| 106788 | pAndExpr->pRight = pWhere; |
| 106789 | } |
| 106790 | |
| 106791 | for(ii=0; ii<pOrWc->nTerm; ii++){ |
| 106792 | WhereTerm *pOrTerm = &pOrWc->a[ii]; |
| 106793 | if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){ |
| @@ -106825,11 +106927,14 @@ | |
| 106825 | /* Finish the loop through table entries that match term pOrTerm. */ |
| 106826 | sqlite3WhereEnd(pSubWInfo); |
| 106827 | } |
| 106828 | } |
| 106829 | } |
| 106830 | sqlite3DbFree(pParse->db, pAndExpr); |
| 106831 | sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); |
| 106832 | sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); |
| 106833 | sqlite3VdbeResolveLabel(v, iLoopBody); |
| 106834 | |
| 106835 | if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab); |
| @@ -107481,11 +107586,11 @@ | |
| 107481 | */ |
| 107482 | notReady = ~(Bitmask)0; |
| 107483 | for(i=0; i<nTabList; i++){ |
| 107484 | pLevel = &pWInfo->a[i]; |
| 107485 | explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags); |
| 107486 | notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady, pWhere); |
| 107487 | pWInfo->iContinue = pLevel->addrCont; |
| 107488 | } |
| 107489 | |
| 107490 | #ifdef SQLITE_TEST /* For testing and debugging use only */ |
| 107491 | /* Record in the query plan information about the current table |
| @@ -113174,23 +113279,27 @@ | |
| 113174 | sqlite3_free(db); |
| 113175 | return SQLITE_OK; |
| 113176 | } |
| 113177 | |
| 113178 | /* |
| 113179 | ** Rollback all database files. |
| 113180 | */ |
| 113181 | SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){ |
| 113182 | int i; |
| 113183 | int inTrans = 0; |
| 113184 | assert( sqlite3_mutex_held(db->mutex) ); |
| 113185 | sqlite3BeginBenignMalloc(); |
| 113186 | for(i=0; i<db->nDb; i++){ |
| 113187 | if( db->aDb[i].pBt ){ |
| 113188 | if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ |
| 113189 | inTrans = 1; |
| 113190 | } |
| 113191 | sqlite3BtreeRollback(db->aDb[i].pBt); |
| 113192 | db->aDb[i].inTrans = 0; |
| 113193 | } |
| 113194 | } |
| 113195 | sqlite3VtabRollback(db); |
| 113196 | sqlite3EndBenignMalloc(); |
| @@ -113241,16 +113350,25 @@ | |
| 113241 | /* SQLITE_AUTH */ "authorization denied", |
| 113242 | /* SQLITE_FORMAT */ "auxiliary database format error", |
| 113243 | /* SQLITE_RANGE */ "bind or column index out of range", |
| 113244 | /* SQLITE_NOTADB */ "file is encrypted or is not a database", |
| 113245 | }; |
| 113246 | rc &= 0xff; |
| 113247 | if( ALWAYS(rc>=0) && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){ |
| 113248 | return aMsg[rc]; |
| 113249 | }else{ |
| 113250 | return "unknown error"; |
| 113251 | } |
| 113252 | } |
| 113253 | |
| 113254 | /* |
| 113255 | ** This routine implements a busy callback that sleeps and tries |
| 113256 | ** again until a timeout value is reached. The timeout value is |
| @@ -113624,13 +113742,12 @@ | |
| 113624 | sqlite3_mutex_leave(db->mutex); |
| 113625 | return pOld; |
| 113626 | } |
| 113627 | #endif /* SQLITE_OMIT_TRACE */ |
| 113628 | |
| 113629 | /*** EXPERIMENTAL *** |
| 113630 | ** |
| 113631 | ** Register a function to be invoked when a transaction comments. |
| 113632 | ** If the invoked function returns non-zero, then the commit becomes a |
| 113633 | ** rollback. |
| 113634 | */ |
| 113635 | SQLITE_API void *sqlite3_commit_hook( |
| 113636 | sqlite3 *db, /* Attach the hook to this database */ |
| @@ -115017,39 +115134,31 @@ | |
| 115017 | /* |
| 115018 | ** Invoke the xFileControl method on a particular database. |
| 115019 | */ |
| 115020 | SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ |
| 115021 | int rc = SQLITE_ERROR; |
| 115022 | int iDb; |
| 115023 | sqlite3_mutex_enter(db->mutex); |
| 115024 | if( zDbName==0 ){ |
| 115025 | iDb = 0; |
| 115026 | }else{ |
| 115027 | for(iDb=0; iDb<db->nDb; iDb++){ |
| 115028 | if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break; |
| 115029 | } |
| 115030 | } |
| 115031 | if( iDb<db->nDb ){ |
| 115032 | Btree *pBtree = db->aDb[iDb].pBt; |
| 115033 | if( pBtree ){ |
| 115034 | Pager *pPager; |
| 115035 | sqlite3_file *fd; |
| 115036 | sqlite3BtreeEnter(pBtree); |
| 115037 | pPager = sqlite3BtreePager(pBtree); |
| 115038 | assert( pPager!=0 ); |
| 115039 | fd = sqlite3PagerFile(pPager); |
| 115040 | assert( fd!=0 ); |
| 115041 | if( op==SQLITE_FCNTL_FILE_POINTER ){ |
| 115042 | *(sqlite3_file**)pArg = fd; |
| 115043 | rc = SQLITE_OK; |
| 115044 | }else if( fd->pMethods ){ |
| 115045 | rc = sqlite3OsFileControl(fd, op, pArg); |
| 115046 | }else{ |
| 115047 | rc = SQLITE_NOTFOUND; |
| 115048 | } |
| 115049 | sqlite3BtreeLeave(pBtree); |
| 115050 | } |
| 115051 | } |
| 115052 | sqlite3_mutex_leave(db->mutex); |
| 115053 | return rc; |
| 115054 | } |
| 115055 | |
| @@ -115339,23 +115448,42 @@ | |
| 115339 | if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){ |
| 115340 | bDflt = v; |
| 115341 | } |
| 115342 | return bDflt; |
| 115343 | } |
| 115344 | |
| 115345 | /* |
| 115346 | ** Return the filename of the database associated with a database |
| 115347 | ** connection. |
| 115348 | */ |
| 115349 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
| 115350 | int i; |
| 115351 | for(i=0; i<db->nDb; i++){ |
| 115352 | if( db->aDb[i].pBt && sqlite3StrICmp(zDbName, db->aDb[i].zName)==0 ){ |
| 115353 | return sqlite3BtreeGetFilename(db->aDb[i].pBt); |
| 115354 | } |
| 115355 | } |
| 115356 | return 0; |
| 115357 | } |
| 115358 | |
| 115359 | /************** End of main.c ************************************************/ |
| 115360 | /************** Begin file notify.c ******************************************/ |
| 115361 | /* |
| @@ -115977,14 +116105,10 @@ | |
| 115977 | ** we simply write the new doclist. Segment merges overwrite older |
| 115978 | ** data for a particular docid with newer data, so deletes or updates |
| 115979 | ** will eventually overtake the earlier data and knock it out. The |
| 115980 | ** query logic likewise merges doclists so that newer data knocks out |
| 115981 | ** older data. |
| 115982 | ** |
| 115983 | ** TODO(shess) Provide a VACUUM type operation to clear out all |
| 115984 | ** deletions and duplications. This would basically be a forced merge |
| 115985 | ** into a single segment. |
| 115986 | */ |
| 115987 | |
| 115988 | /************** Include fts3Int.h in the middle of fts3.c ********************/ |
| 115989 | /************** Begin file fts3Int.h *****************************************/ |
| 115990 | /* |
| @@ -116076,11 +116200,11 @@ | |
| 116076 | typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; |
| 116077 | |
| 116078 | struct sqlite3_tokenizer_module { |
| 116079 | |
| 116080 | /* |
| 116081 | ** Structure version. Should always be set to 0. |
| 116082 | */ |
| 116083 | int iVersion; |
| 116084 | |
| 116085 | /* |
| 116086 | ** Create a new tokenizer. The values in the argv[] array are the |
| @@ -116157,10 +116281,19 @@ | |
| 116157 | const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ |
| 116158 | int *piStartOffset, /* OUT: Byte offset of token in input buffer */ |
| 116159 | int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ |
| 116160 | int *piPosition /* OUT: Number of tokens returned before this one */ |
| 116161 | ); |
| 116162 | }; |
| 116163 | |
| 116164 | struct sqlite3_tokenizer { |
| 116165 | const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ |
| 116166 | /* Tokenizer implementations will typically add additional fields */ |
| @@ -116448,15 +116581,16 @@ | |
| 116448 | const char *zName; /* virtual table name */ |
| 116449 | int nColumn; /* number of named columns in virtual table */ |
| 116450 | char **azColumn; /* column names. malloced */ |
| 116451 | sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ |
| 116452 | char *zContentTbl; /* content=xxx option, or NULL */ |
| 116453 | |
| 116454 | /* Precompiled statements used by the implementation. Each of these |
| 116455 | ** statements is run and reset within a single virtual table API call. |
| 116456 | */ |
| 116457 | sqlite3_stmt *aStmt[27]; |
| 116458 | |
| 116459 | char *zReadExprlist; |
| 116460 | char *zWriteExprlist; |
| 116461 | |
| 116462 | int nNodeSize; /* Soft limit for node size */ |
| @@ -116467,16 +116601,16 @@ | |
| 116467 | char *zSegmentsTbl; /* Name of %_segments table */ |
| 116468 | sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ |
| 116469 | |
| 116470 | /* TODO: Fix the first paragraph of this comment. |
| 116471 | ** |
| 116472 | ** The following hash table is used to buffer pending index updates during |
| 116473 | ** transactions. Variable nPendingData estimates the memory size of the |
| 116474 | ** pending data, including hash table overhead, but not malloc overhead. |
| 116475 | ** When nPendingData exceeds nMaxPendingData, the buffer is flushed |
| 116476 | ** automatically. Variable iPrevDocid is the docid of the most recently |
| 116477 | ** inserted record. |
| 116478 | ** |
| 116479 | ** A single FTS4 table may have multiple full-text indexes. For each index |
| 116480 | ** there is an entry in the aIndex[] array. Index 0 is an index of all the |
| 116481 | ** terms that appear in the document set. Each subsequent index in aIndex[] |
| 116482 | ** is an index of prefixes of a specific length. |
| @@ -116487,16 +116621,17 @@ | |
| 116487 | Fts3Hash hPending; /* Pending terms table for this index */ |
| 116488 | } *aIndex; |
| 116489 | int nMaxPendingData; /* Max pending data before flush to disk */ |
| 116490 | int nPendingData; /* Current bytes of pending data */ |
| 116491 | sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ |
| 116492 | |
| 116493 | #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) |
| 116494 | /* State variables used for validating that the transaction control |
| 116495 | ** methods of the virtual table are called at appropriate times. These |
| 116496 | ** values do not contribution to the FTS computation; they are used for |
| 116497 | ** verifying the SQLite core. |
| 116498 | */ |
| 116499 | int inTransaction; /* True after xBegin but before xCommit/xRollback */ |
| 116500 | int mxSavepoint; /* Largest valid xSavepoint integer */ |
| 116501 | #endif |
| 116502 | }; |
| @@ -116511,10 +116646,11 @@ | |
| 116511 | i16 eSearch; /* Search strategy (see below) */ |
| 116512 | u8 isEof; /* True if at End Of Results */ |
| 116513 | u8 isRequireSeek; /* True if must seek pStmt to %_content row */ |
| 116514 | sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ |
| 116515 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 116516 | int nPhrase; /* Number of matchable phrases in query */ |
| 116517 | Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ |
| 116518 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 116519 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 116520 | char *aDoclist; /* List of docids for full-text queries */ |
| @@ -116662,11 +116798,11 @@ | |
| 116662 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64, |
| 116663 | sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); |
| 116664 | SQLITE_PRIVATE int sqlite3Fts3SegReaderPending( |
| 116665 | Fts3Table*,int,const char*,int,int,Fts3SegReader**); |
| 116666 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *); |
| 116667 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **); |
| 116668 | SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); |
| 116669 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*); |
| 116670 | |
| 116671 | SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); |
| 116672 | SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); |
| @@ -116683,12 +116819,12 @@ | |
| 116683 | |
| 116684 | SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*); |
| 116685 | SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *); |
| 116686 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *); |
| 116687 | |
| 116688 | SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( |
| 116689 | Fts3Table *, int, int, const char *, int, int, int, Fts3MultiSegReader *); |
| 116690 | |
| 116691 | /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ |
| 116692 | #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 |
| 116693 | #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 |
| 116694 | #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 |
| @@ -116751,18 +116887,22 @@ | |
| 116751 | const char *, const char *, int, int |
| 116752 | ); |
| 116753 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); |
| 116754 | |
| 116755 | /* fts3_expr.c */ |
| 116756 | SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, |
| 116757 | char **, int, int, int, const char *, int, Fts3Expr ** |
| 116758 | ); |
| 116759 | SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); |
| 116760 | #ifdef SQLITE_TEST |
| 116761 | SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); |
| 116762 | SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); |
| 116763 | #endif |
| 116764 | |
| 116765 | /* fts3_aux.c */ |
| 116766 | SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db); |
| 116767 | |
| 116768 | SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *); |
| @@ -116954,10 +117094,11 @@ | |
| 116954 | } |
| 116955 | sqlite3_free(p->zSegmentsTbl); |
| 116956 | sqlite3_free(p->zReadExprlist); |
| 116957 | sqlite3_free(p->zWriteExprlist); |
| 116958 | sqlite3_free(p->zContentTbl); |
| 116959 | |
| 116960 | /* Invoke the tokenizer destructor to free the tokenizer. */ |
| 116961 | p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
| 116962 | |
| 116963 | sqlite3_free(p); |
| @@ -117030,11 +117171,13 @@ | |
| 117030 | if( *pRc==SQLITE_OK ){ |
| 117031 | int i; /* Iterator variable */ |
| 117032 | int rc; /* Return code */ |
| 117033 | char *zSql; /* SQL statement passed to declare_vtab() */ |
| 117034 | char *zCols; /* List of user defined columns */ |
| 117035 | |
| 117036 | sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); |
| 117037 | |
| 117038 | /* Create a list of user columns for the virtual table */ |
| 117039 | zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]); |
| 117040 | for(i=1; zCols && i<p->nColumn; i++){ |
| @@ -117041,11 +117184,12 @@ | |
| 117041 | zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]); |
| 117042 | } |
| 117043 | |
| 117044 | /* Create the whole "CREATE TABLE" statement to pass to SQLite */ |
| 117045 | zSql = sqlite3_mprintf( |
| 117046 | "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN)", zCols, p->zName |
| 117047 | ); |
| 117048 | if( !zCols || !zSql ){ |
| 117049 | rc = SQLITE_NOMEM; |
| 117050 | }else{ |
| 117051 | rc = sqlite3_declare_vtab(p->db, zSql); |
| @@ -117070,18 +117214,22 @@ | |
| 117070 | int rc = SQLITE_OK; /* Return code */ |
| 117071 | int i; /* Iterator variable */ |
| 117072 | sqlite3 *db = p->db; /* The database connection */ |
| 117073 | |
| 117074 | if( p->zContentTbl==0 ){ |
| 117075 | char *zContentCols; /* Columns of %_content table */ |
| 117076 | |
| 117077 | /* Create a list of user columns for the content table */ |
| 117078 | zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); |
| 117079 | for(i=0; zContentCols && i<p->nColumn; i++){ |
| 117080 | char *z = p->azColumn[i]; |
| 117081 | zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); |
| 117082 | } |
| 117083 | if( zContentCols==0 ) rc = SQLITE_NOMEM; |
| 117084 | |
| 117085 | /* Create the content table */ |
| 117086 | fts3DbExec(&rc, db, |
| 117087 | "CREATE TABLE %Q.'%q_content'(%s)", |
| @@ -117277,18 +117425,24 @@ | |
| 117277 | } |
| 117278 | fts3Appendf(pRc, &zRet, "docid"); |
| 117279 | for(i=0; i<p->nColumn; i++){ |
| 117280 | fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]); |
| 117281 | } |
| 117282 | sqlite3_free(zFree); |
| 117283 | }else{ |
| 117284 | fts3Appendf(pRc, &zRet, "rowid"); |
| 117285 | for(i=0; i<p->nColumn; i++){ |
| 117286 | fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]); |
| 117287 | } |
| 117288 | } |
| 117289 | fts3Appendf(pRc, &zRet, "FROM '%q'.'%q%s' AS x", |
| 117290 | p->zDb, |
| 117291 | (p->zContentTbl ? p->zContentTbl : p->zName), |
| 117292 | (p->zContentTbl ? "" : "_content") |
| 117293 | ); |
| 117294 | return zRet; |
| @@ -117327,10 +117481,13 @@ | |
| 117327 | } |
| 117328 | fts3Appendf(pRc, &zRet, "?"); |
| 117329 | for(i=0; i<p->nColumn; i++){ |
| 117330 | fts3Appendf(pRc, &zRet, ",%s(?)", zFunction); |
| 117331 | } |
| 117332 | sqlite3_free(zFree); |
| 117333 | return zRet; |
| 117334 | } |
| 117335 | |
| 117336 | /* |
| @@ -117542,10 +117699,11 @@ | |
| 117542 | int bDescIdx = 0; /* True to store descending indexes */ |
| 117543 | char *zPrefix = 0; /* Prefix parameter value (or NULL) */ |
| 117544 | char *zCompress = 0; /* compress=? parameter (or NULL) */ |
| 117545 | char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ |
| 117546 | char *zContent = 0; /* content=? parameter (or NULL) */ |
| 117547 | |
| 117548 | assert( strlen(argv[0])==4 ); |
| 117549 | assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4) |
| 117550 | || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4) |
| 117551 | ); |
| @@ -117591,11 +117749,12 @@ | |
| 117591 | { "matchinfo", 9 }, /* 0 -> MATCHINFO */ |
| 117592 | { "prefix", 6 }, /* 1 -> PREFIX */ |
| 117593 | { "compress", 8 }, /* 2 -> COMPRESS */ |
| 117594 | { "uncompress", 10 }, /* 3 -> UNCOMPRESS */ |
| 117595 | { "order", 5 }, /* 4 -> ORDER */ |
| 117596 | { "content", 7 } /* 5 -> CONTENT */ |
| 117597 | }; |
| 117598 | |
| 117599 | int iOpt; |
| 117600 | if( !zVal ){ |
| 117601 | rc = SQLITE_NOMEM; |
| @@ -117645,16 +117804,22 @@ | |
| 117645 | rc = SQLITE_ERROR; |
| 117646 | } |
| 117647 | bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); |
| 117648 | break; |
| 117649 | |
| 117650 | default: /* CONTENT */ |
| 117651 | assert( iOpt==5 ); |
| 117652 | sqlite3_free(zUncompress); |
| 117653 | zContent = zVal; |
| 117654 | zVal = 0; |
| 117655 | break; |
| 117656 | } |
| 117657 | } |
| 117658 | sqlite3_free(zVal); |
| 117659 | } |
| 117660 | } |
| @@ -117680,12 +117845,24 @@ | |
| 117680 | zUncompress = 0; |
| 117681 | if( nCol==0 ){ |
| 117682 | sqlite3_free((void*)aCol); |
| 117683 | aCol = 0; |
| 117684 | rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); |
| 117685 | } |
| 117686 | assert( rc!=SQLITE_OK || nCol>0 ); |
| 117687 | } |
| 117688 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 117689 | |
| 117690 | if( nCol==0 ){ |
| 117691 | assert( nString==0 ); |
| @@ -117728,11 +117905,13 @@ | |
| 117728 | p->nMaxPendingData = FTS3_MAX_PENDING_DATA; |
| 117729 | p->bHasDocsize = (isFts4 && bNoDocsize==0); |
| 117730 | p->bHasStat = isFts4; |
| 117731 | p->bDescIdx = bDescIdx; |
| 117732 | p->zContentTbl = zContent; |
| 117733 | zContent = 0; |
| 117734 | TESTONLY( p->inTransaction = -1 ); |
| 117735 | TESTONLY( p->mxSavepoint = -1 ); |
| 117736 | |
| 117737 | p->aIndex = (struct Fts3Index *)&p->azColumn[nCol]; |
| 117738 | memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex); |
| @@ -117791,10 +117970,11 @@ | |
| 117791 | sqlite3_free(zPrefix); |
| 117792 | sqlite3_free(aIndex); |
| 117793 | sqlite3_free(zCompress); |
| 117794 | sqlite3_free(zUncompress); |
| 117795 | sqlite3_free(zContent); |
| 117796 | sqlite3_free((void *)aCol); |
| 117797 | if( rc!=SQLITE_OK ){ |
| 117798 | if( p ){ |
| 117799 | fts3DisconnectMethod((sqlite3_vtab *)p); |
| 117800 | }else if( pTokenizer ){ |
| @@ -117842,10 +118022,11 @@ | |
| 117842 | */ |
| 117843 | static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ |
| 117844 | Fts3Table *p = (Fts3Table *)pVTab; |
| 117845 | int i; /* Iterator variable */ |
| 117846 | int iCons = -1; /* Index of constraint to use */ |
| 117847 | |
| 117848 | /* By default use a full table scan. This is an expensive option, |
| 117849 | ** so search through the constraints to see if a more efficient |
| 117850 | ** strategy is possible. |
| 117851 | */ |
| @@ -117854,11 +118035,12 @@ | |
| 117854 | for(i=0; i<pInfo->nConstraint; i++){ |
| 117855 | struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i]; |
| 117856 | if( pCons->usable==0 ) continue; |
| 117857 | |
| 117858 | /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */ |
| 117859 | if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ |
| 117860 | && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 ) |
| 117861 | ){ |
| 117862 | pInfo->idxNum = FTS3_DOCID_SEARCH; |
| 117863 | pInfo->estimatedCost = 1.0; |
| 117864 | iCons = i; |
| @@ -117877,18 +118059,27 @@ | |
| 117877 | && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn |
| 117878 | ){ |
| 117879 | pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn; |
| 117880 | pInfo->estimatedCost = 2.0; |
| 117881 | iCons = i; |
| 117882 | break; |
| 117883 | } |
| 117884 | } |
| 117885 | |
| 117886 | if( iCons>=0 ){ |
| 117887 | pInfo->aConstraintUsage[iCons].argvIndex = 1; |
| 117888 | pInfo->aConstraintUsage[iCons].omit = 1; |
| 117889 | } |
| 117890 | |
| 117891 | /* Regardless of the strategy selected, FTS can deliver rows in rowid (or |
| 117892 | ** docid) order. Both ascending and descending are possible. |
| 117893 | */ |
| 117894 | if( pInfo->nOrderBy==1 ){ |
| @@ -119034,10 +119225,11 @@ | |
| 119034 | ** This function returns SQLITE_OK if successful, or an SQLite error code |
| 119035 | ** otherwise. |
| 119036 | */ |
| 119037 | static int fts3SegReaderCursor( |
| 119038 | Fts3Table *p, /* FTS3 table handle */ |
| 119039 | int iIndex, /* Index to search (from 0 to p->nIndex-1) */ |
| 119040 | int iLevel, /* Level of segments to scan */ |
| 119041 | const char *zTerm, /* Term to query for */ |
| 119042 | int nTerm, /* Size of zTerm in bytes */ |
| 119043 | int isPrefix, /* True for a prefix search */ |
| @@ -119062,11 +119254,11 @@ | |
| 119062 | } |
| 119063 | } |
| 119064 | |
| 119065 | if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
| 119066 | if( rc==SQLITE_OK ){ |
| 119067 | rc = sqlite3Fts3AllSegdirs(p, iIndex, iLevel, &pStmt); |
| 119068 | } |
| 119069 | |
| 119070 | while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ |
| 119071 | Fts3SegReader *pSeg = 0; |
| 119072 | |
| @@ -119107,10 +119299,11 @@ | |
| 119107 | ** Set up a cursor object for iterating through a full-text index or a |
| 119108 | ** single level therein. |
| 119109 | */ |
| 119110 | SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( |
| 119111 | Fts3Table *p, /* FTS3 table handle */ |
| 119112 | int iIndex, /* Index to search (from 0 to p->nIndex-1) */ |
| 119113 | int iLevel, /* Level of segments to scan */ |
| 119114 | const char *zTerm, /* Term to query for */ |
| 119115 | int nTerm, /* Size of zTerm in bytes */ |
| 119116 | int isPrefix, /* True for a prefix search */ |
| @@ -119131,11 +119324,11 @@ | |
| 119131 | assert( isScan==0 || p->aIndex==0 ); |
| 119132 | |
| 119133 | memset(pCsr, 0, sizeof(Fts3MultiSegReader)); |
| 119134 | |
| 119135 | return fts3SegReaderCursor( |
| 119136 | p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr |
| 119137 | ); |
| 119138 | } |
| 119139 | |
| 119140 | /* |
| 119141 | ** In addition to its current configuration, have the Fts3MultiSegReader |
| @@ -119143,15 +119336,18 @@ | |
| 119143 | ** |
| 119144 | ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. |
| 119145 | */ |
| 119146 | static int fts3SegReaderCursorAddZero( |
| 119147 | Fts3Table *p, /* FTS virtual table handle */ |
| 119148 | const char *zTerm, /* Term to scan doclist of */ |
| 119149 | int nTerm, /* Number of bytes in zTerm */ |
| 119150 | Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */ |
| 119151 | ){ |
| 119152 | return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr); |
| 119153 | } |
| 119154 | |
| 119155 | /* |
| 119156 | ** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or, |
| 119157 | ** if isPrefix is true, to scan the doclist for all terms for which |
| @@ -119183,32 +119379,35 @@ | |
| 119183 | |
| 119184 | if( isPrefix ){ |
| 119185 | for(i=1; bFound==0 && i<p->nIndex; i++){ |
| 119186 | if( p->aIndex[i].nPrefix==nTerm ){ |
| 119187 | bFound = 1; |
| 119188 | rc = sqlite3Fts3SegReaderCursor( |
| 119189 | p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr); |
| 119190 | pSegcsr->bLookup = 1; |
| 119191 | } |
| 119192 | } |
| 119193 | |
| 119194 | for(i=1; bFound==0 && i<p->nIndex; i++){ |
| 119195 | if( p->aIndex[i].nPrefix==nTerm+1 ){ |
| 119196 | bFound = 1; |
| 119197 | rc = sqlite3Fts3SegReaderCursor( |
| 119198 | p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr |
| 119199 | ); |
| 119200 | if( rc==SQLITE_OK ){ |
| 119201 | rc = fts3SegReaderCursorAddZero(p, zTerm, nTerm, pSegcsr); |
| 119202 | } |
| 119203 | } |
| 119204 | } |
| 119205 | } |
| 119206 | |
| 119207 | if( bFound==0 ){ |
| 119208 | rc = sqlite3Fts3SegReaderCursor( |
| 119209 | p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr |
| 119210 | ); |
| 119211 | pSegcsr->bLookup = !isPrefix; |
| 119212 | } |
| 119213 | } |
| 119214 | |
| @@ -119359,11 +119558,11 @@ | |
| 119359 | |
| 119360 | UNUSED_PARAMETER(idxStr); |
| 119361 | UNUSED_PARAMETER(nVal); |
| 119362 | |
| 119363 | assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); |
| 119364 | assert( nVal==0 || nVal==1 ); |
| 119365 | assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) ); |
| 119366 | assert( p->pSegments==0 ); |
| 119367 | |
| 119368 | /* In case the cursor has been used before, clear it now. */ |
| 119369 | sqlite3_finalize(pCsr->pStmt); |
| @@ -119384,12 +119583,15 @@ | |
| 119384 | |
| 119385 | if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 119386 | return SQLITE_NOMEM; |
| 119387 | } |
| 119388 | |
| 119389 | rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->bHasStat, |
| 119390 | p->nColumn, iCol, zQuery, -1, &pCsr->pExpr |
| 119391 | ); |
| 119392 | if( rc!=SQLITE_OK ){ |
| 119393 | if( rc==SQLITE_ERROR ){ |
| 119394 | static const char *zErr = "malformed MATCH expression: [%s]"; |
| 119395 | p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery); |
| @@ -119456,37 +119658,56 @@ | |
| 119456 | } |
| 119457 | |
| 119458 | /* |
| 119459 | ** This is the xColumn method, called by SQLite to request a value from |
| 119460 | ** the row that the supplied cursor currently points to. |
| 119461 | */ |
| 119462 | static int fts3ColumnMethod( |
| 119463 | sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ |
| 119464 | sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */ |
| 119465 | int iCol /* Index of column to read value from */ |
| 119466 | ){ |
| 119467 | int rc = SQLITE_OK; /* Return Code */ |
| 119468 | Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; |
| 119469 | Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
| 119470 | |
| 119471 | /* The column value supplied by SQLite must be in range. */ |
| 119472 | assert( iCol>=0 && iCol<=p->nColumn+1 ); |
| 119473 | |
| 119474 | if( iCol==p->nColumn+1 ){ |
| 119475 | /* This call is a request for the "docid" column. Since "docid" is an |
| 119476 | ** alias for "rowid", use the xRowid() method to obtain the value. |
| 119477 | */ |
| 119478 | sqlite3_result_int64(pContext, pCsr->iPrevId); |
| 119479 | }else if( iCol==p->nColumn ){ |
| 119480 | /* The extra column whose name is the same as the table. |
| 119481 | ** Return a blob which is a pointer to the cursor. |
| 119482 | */ |
| 119483 | sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); |
| 119484 | }else{ |
| 119485 | rc = fts3CursorSeek(0, pCsr); |
| 119486 | if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){ |
| 119487 | sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1)); |
| 119488 | } |
| 119489 | } |
| 119490 | |
| 119491 | assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
| 119492 | return rc; |
| @@ -121958,11 +122179,11 @@ | |
| 121958 | pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx])); |
| 121959 | pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]); |
| 121960 | if( pCsr->zStop==0 ) return SQLITE_NOMEM; |
| 121961 | } |
| 121962 | |
| 121963 | rc = sqlite3Fts3SegReaderCursor(pFts3, 0, FTS3_SEGCURSOR_ALL, |
| 121964 | pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr |
| 121965 | ); |
| 121966 | if( rc==SQLITE_OK ){ |
| 121967 | rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter); |
| 121968 | } |
| @@ -122150,10 +122371,11 @@ | |
| 122150 | ** zero. |
| 122151 | */ |
| 122152 | typedef struct ParseContext ParseContext; |
| 122153 | struct ParseContext { |
| 122154 | sqlite3_tokenizer *pTokenizer; /* Tokenizer module */ |
| 122155 | const char **azCol; /* Array of column names for fts3 table */ |
| 122156 | int bFts4; /* True to allow FTS4-only syntax */ |
| 122157 | int nCol; /* Number of entries in azCol[] */ |
| 122158 | int iDefaultCol; /* Default column to query */ |
| 122159 | int isNot; /* True if getNextNode() sees a unary - */ |
| @@ -122185,10 +122407,37 @@ | |
| 122185 | void *pRet = sqlite3_malloc(nByte); |
| 122186 | if( pRet ) memset(pRet, 0, nByte); |
| 122187 | return pRet; |
| 122188 | } |
| 122189 | |
| 122190 | |
| 122191 | /* |
| 122192 | ** Extract the next token from buffer z (length n) using the tokenizer |
| 122193 | ** and other information (column names etc.) in pParse. Create an Fts3Expr |
| 122194 | ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this |
| @@ -122212,19 +122461,17 @@ | |
| 122212 | int rc; |
| 122213 | sqlite3_tokenizer_cursor *pCursor; |
| 122214 | Fts3Expr *pRet = 0; |
| 122215 | int nConsumed = 0; |
| 122216 | |
| 122217 | rc = pModule->xOpen(pTokenizer, z, n, &pCursor); |
| 122218 | if( rc==SQLITE_OK ){ |
| 122219 | const char *zToken; |
| 122220 | int nToken, iStart, iEnd, iPosition; |
| 122221 | int nByte; /* total space to allocate */ |
| 122222 | |
| 122223 | pCursor->pTokenizer = pTokenizer; |
| 122224 | rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); |
| 122225 | |
| 122226 | if( rc==SQLITE_OK ){ |
| 122227 | nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; |
| 122228 | pRet = (Fts3Expr *)fts3MallocZero(nByte); |
| 122229 | if( !pRet ){ |
| 122230 | rc = SQLITE_NOMEM; |
| @@ -122326,14 +122573,14 @@ | |
| 122326 | ** |
| 122327 | ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below, |
| 122328 | ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase |
| 122329 | ** structures. |
| 122330 | */ |
| 122331 | rc = pModule->xOpen(pTokenizer, zInput, nInput, &pCursor); |
| 122332 | if( rc==SQLITE_OK ){ |
| 122333 | int ii; |
| 122334 | pCursor->pTokenizer = pTokenizer; |
| 122335 | for(ii=0; rc==SQLITE_OK; ii++){ |
| 122336 | const char *zByte; |
| 122337 | int nByte, iBegin, iEnd, iPos; |
| 122338 | rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos); |
| 122339 | if( rc==SQLITE_OK ){ |
| @@ -122803,10 +123050,11 @@ | |
| 122803 | ** specified as part of the query string), or -1 if tokens may by default |
| 122804 | ** match any table column. |
| 122805 | */ |
| 122806 | SQLITE_PRIVATE int sqlite3Fts3ExprParse( |
| 122807 | sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ |
| 122808 | char **azCol, /* Array of column names for fts3 table */ |
| 122809 | int bFts4, /* True to allow FTS4-only syntax */ |
| 122810 | int nCol, /* Number of entries in azCol[] */ |
| 122811 | int iDefaultCol, /* Default column to query */ |
| 122812 | const char *z, int n, /* Text of MATCH query */ |
| @@ -122813,15 +123061,17 @@ | |
| 122813 | Fts3Expr **ppExpr /* OUT: Parsed query structure */ |
| 122814 | ){ |
| 122815 | int nParsed; |
| 122816 | int rc; |
| 122817 | ParseContext sParse; |
| 122818 | sParse.pTokenizer = pTokenizer; |
| 122819 | sParse.azCol = (const char **)azCol; |
| 122820 | sParse.nCol = nCol; |
| 122821 | sParse.iDefaultCol = iDefaultCol; |
| 122822 | sParse.nNest = 0; |
| 122823 | sParse.bFts4 = bFts4; |
| 122824 | if( z==0 ){ |
| 122825 | *ppExpr = 0; |
| 122826 | return SQLITE_OK; |
| 122827 | } |
| @@ -123008,11 +123258,11 @@ | |
| 123008 | for(ii=0; ii<nCol; ii++){ |
| 123009 | azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); |
| 123010 | } |
| 123011 | |
| 123012 | rc = sqlite3Fts3ExprParse( |
| 123013 | pTokenizer, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr |
| 123014 | ); |
| 123015 | if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ |
| 123016 | sqlite3_result_error(context, "Error parsing expression", -1); |
| 123017 | }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){ |
| 123018 | sqlite3_result_error_nomem(context); |
| @@ -124057,10 +124307,11 @@ | |
| 124057 | porterCreate, |
| 124058 | porterDestroy, |
| 124059 | porterOpen, |
| 124060 | porterClose, |
| 124061 | porterNext, |
| 124062 | }; |
| 124063 | |
| 124064 | /* |
| 124065 | ** Allocate a new porter tokenizer. Return a pointer to the new |
| 124066 | ** tokenizer in *ppModule |
| @@ -124362,15 +124613,14 @@ | |
| 124362 | if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){ |
| 124363 | zErr = "error in xCreate()"; |
| 124364 | goto finish; |
| 124365 | } |
| 124366 | pTokenizer->pModule = p; |
| 124367 | if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){ |
| 124368 | zErr = "error in xOpen()"; |
| 124369 | goto finish; |
| 124370 | } |
| 124371 | pCsr->pTokenizer = pTokenizer; |
| 124372 | |
| 124373 | while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ |
| 124374 | Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); |
| 124375 | Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); |
| 124376 | zToken = &zInput[iStart]; |
| @@ -124782,10 +125032,11 @@ | |
| 124782 | simpleCreate, |
| 124783 | simpleDestroy, |
| 124784 | simpleOpen, |
| 124785 | simpleClose, |
| 124786 | simpleNext, |
| 124787 | }; |
| 124788 | |
| 124789 | /* |
| 124790 | ** Allocate a new simple tokenizer. Return a pointer to the new |
| 124791 | ** tokenizer in *ppModule |
| @@ -125031,10 +125282,12 @@ | |
| 125031 | #define SQL_SELECT_ALL_PREFIX_LEVEL 24 |
| 125032 | #define SQL_DELETE_ALL_TERMS_SEGDIR 25 |
| 125033 | |
| 125034 | #define SQL_DELETE_SEGDIR_RANGE 26 |
| 125035 | |
| 125036 | /* |
| 125037 | ** This function is used to obtain an SQLite prepared statement handle |
| 125038 | ** for the statement identified by the second argument. If successful, |
| 125039 | ** *pp is set to the requested statement handle and SQLITE_OK returned. |
| 125040 | ** Otherwise, an SQLite error code is returned and *pp is set to 0. |
| @@ -125084,10 +125337,11 @@ | |
| 125084 | /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)", |
| 125085 | /* 24 */ "", |
| 125086 | /* 25 */ "", |
| 125087 | |
| 125088 | /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", |
| 125089 | |
| 125090 | }; |
| 125091 | int rc = SQLITE_OK; |
| 125092 | sqlite3_stmt *pStmt; |
| 125093 | |
| @@ -125229,10 +125483,23 @@ | |
| 125229 | rc = SQLITE_OK; |
| 125230 | } |
| 125231 | |
| 125232 | return rc; |
| 125233 | } |
| 125234 | |
| 125235 | /* |
| 125236 | ** Set *ppStmt to a statement handle that may be used to iterate through |
| 125237 | ** all rows in the %_segdir table, from oldest to newest. If successful, |
| 125238 | ** return SQLITE_OK. If an error occurs while preparing the statement, |
| @@ -125249,10 +125516,11 @@ | |
| 125249 | ** 3: end_block |
| 125250 | ** 4: root |
| 125251 | */ |
| 125252 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs( |
| 125253 | Fts3Table *p, /* FTS3 table */ |
| 125254 | int iIndex, /* Index for p->aIndex[] */ |
| 125255 | int iLevel, /* Level to select */ |
| 125256 | sqlite3_stmt **ppStmt /* OUT: Compiled statement */ |
| 125257 | ){ |
| 125258 | int rc; |
| @@ -125264,18 +125532,20 @@ | |
| 125264 | |
| 125265 | if( iLevel<0 ){ |
| 125266 | /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */ |
| 125267 | rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0); |
| 125268 | if( rc==SQLITE_OK ){ |
| 125269 | sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL); |
| 125270 | sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL-1); |
| 125271 | } |
| 125272 | }else{ |
| 125273 | /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */ |
| 125274 | rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); |
| 125275 | if( rc==SQLITE_OK ){ |
| 125276 | sqlite3_bind_int(pStmt, 1, iLevel+iIndex*FTS3_SEGDIR_MAXLEVEL); |
| 125277 | } |
| 125278 | } |
| 125279 | *ppStmt = pStmt; |
| 125280 | return rc; |
| 125281 | } |
| @@ -125437,10 +125707,11 @@ | |
| 125437 | ** |
| 125438 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. |
| 125439 | */ |
| 125440 | static int fts3PendingTermsAdd( |
| 125441 | Fts3Table *p, /* Table into which text will be inserted */ |
| 125442 | const char *zText, /* Text of document to be inserted */ |
| 125443 | int iCol, /* Column into which text is being inserted */ |
| 125444 | u32 *pnWord /* OUT: Number of tokens inserted */ |
| 125445 | ){ |
| 125446 | int rc; |
| @@ -125466,15 +125737,14 @@ | |
| 125466 | if( zText==0 ){ |
| 125467 | *pnWord = 0; |
| 125468 | return SQLITE_OK; |
| 125469 | } |
| 125470 | |
| 125471 | rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr); |
| 125472 | if( rc!=SQLITE_OK ){ |
| 125473 | return rc; |
| 125474 | } |
| 125475 | pCsr->pTokenizer = pTokenizer; |
| 125476 | |
| 125477 | xNext = pModule->xNext; |
| 125478 | while( SQLITE_OK==rc |
| 125479 | && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) |
| 125480 | ){ |
| @@ -125513,22 +125783,32 @@ | |
| 125513 | /* |
| 125514 | ** Calling this function indicates that subsequent calls to |
| 125515 | ** fts3PendingTermsAdd() are to add term/position-list pairs for the |
| 125516 | ** contents of the document with docid iDocid. |
| 125517 | */ |
| 125518 | static int fts3PendingTermsDocid(Fts3Table *p, sqlite_int64 iDocid){ |
| 125519 | /* TODO(shess) Explore whether partially flushing the buffer on |
| 125520 | ** forced-flush would provide better performance. I suspect that if |
| 125521 | ** we ordered the doclists by size and flushed the largest until the |
| 125522 | ** buffer was half empty, that would let the less frequent terms |
| 125523 | ** generate longer doclists. |
| 125524 | */ |
| 125525 | if( iDocid<=p->iPrevDocid || p->nPendingData>p->nMaxPendingData ){ |
| 125526 | int rc = sqlite3Fts3PendingTermsFlush(p); |
| 125527 | if( rc!=SQLITE_OK ) return rc; |
| 125528 | } |
| 125529 | p->iPrevDocid = iDocid; |
| 125530 | return SQLITE_OK; |
| 125531 | } |
| 125532 | |
| 125533 | /* |
| 125534 | ** Discard the contents of the pending-terms hash tables. |
| @@ -125553,15 +125833,20 @@ | |
| 125553 | ** pendingTerms hash table. |
| 125554 | ** |
| 125555 | ** Argument apVal is the same as the similarly named argument passed to |
| 125556 | ** fts3InsertData(). Parameter iDocid is the docid of the new row. |
| 125557 | */ |
| 125558 | static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){ |
| 125559 | int i; /* Iterator variable */ |
| 125560 | for(i=2; i<p->nColumn+2; i++){ |
| 125561 | const char *zText = (const char *)sqlite3_value_text(apVal[i]); |
| 125562 | int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]); |
| 125563 | if( rc!=SQLITE_OK ){ |
| 125564 | return rc; |
| 125565 | } |
| 125566 | aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]); |
| 125567 | } |
| @@ -125578,10 +125863,11 @@ | |
| 125578 | ** apVal[2] Left-most user-defined column |
| 125579 | ** ... |
| 125580 | ** apVal[p->nColumn+1] Right-most user-defined column |
| 125581 | ** apVal[p->nColumn+2] Hidden column with same name as table |
| 125582 | ** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid) |
| 125583 | */ |
| 125584 | static int fts3InsertData( |
| 125585 | Fts3Table *p, /* Full-text table */ |
| 125586 | sqlite3_value **apVal, /* Array of values to insert */ |
| 125587 | sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */ |
| @@ -125608,13 +125894,17 @@ | |
| 125608 | ** |
| 125609 | ** The statement features N '?' variables, where N is the number of user |
| 125610 | ** defined columns in the FTS3 table, plus one for the docid field. |
| 125611 | */ |
| 125612 | rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]); |
| 125613 | if( rc!=SQLITE_OK ){ |
| 125614 | return rc; |
| 125615 | } |
| 125616 | |
| 125617 | /* There is a quirk here. The users INSERT statement may have specified |
| 125618 | ** a value for the "rowid" field, for the "docid" field, or for both. |
| 125619 | ** Which is a problem, since "rowid" and "docid" are aliases for the |
| 125620 | ** same value. For example: |
| @@ -125669,10 +125959,19 @@ | |
| 125669 | if( p->bHasStat ){ |
| 125670 | fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); |
| 125671 | } |
| 125672 | return rc; |
| 125673 | } |
| 125674 | |
| 125675 | /* |
| 125676 | ** The first element in the apVal[] array is assumed to contain the docid |
| 125677 | ** (an integer) of a row about to be deleted. Remove all terms from the |
| 125678 | ** full-text index. |
| @@ -125689,19 +125988,21 @@ | |
| 125689 | if( *pRC ) return; |
| 125690 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); |
| 125691 | if( rc==SQLITE_OK ){ |
| 125692 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 125693 | int i; |
| 125694 | for(i=1; i<=p->nColumn; i++){ |
| 125695 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 125696 | rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]); |
| 125697 | if( rc!=SQLITE_OK ){ |
| 125698 | sqlite3_reset(pSelect); |
| 125699 | *pRC = rc; |
| 125700 | return; |
| 125701 | } |
| 125702 | aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); |
| 125703 | } |
| 125704 | } |
| 125705 | rc = sqlite3_reset(pSelect); |
| 125706 | }else{ |
| 125707 | sqlite3_reset(pSelect); |
| @@ -125711,11 +126012,11 @@ | |
| 125711 | |
| 125712 | /* |
| 125713 | ** Forward declaration to account for the circular dependency between |
| 125714 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| 125715 | */ |
| 125716 | static int fts3SegmentMerge(Fts3Table *, int, int); |
| 125717 | |
| 125718 | /* |
| 125719 | ** This function allocates a new level iLevel index in the segdir table. |
| 125720 | ** Usually, indexes are allocated within a level sequentially starting |
| 125721 | ** with 0, so the allocated index is one greater than the value returned |
| @@ -125730,22 +126031,28 @@ | |
| 125730 | ** If successful, *piIdx is set to the allocated index slot and SQLITE_OK |
| 125731 | ** returned. Otherwise, an SQLite error code is returned. |
| 125732 | */ |
| 125733 | static int fts3AllocateSegdirIdx( |
| 125734 | Fts3Table *p, |
| 125735 | int iIndex, /* Index for p->aIndex */ |
| 125736 | int iLevel, |
| 125737 | int *piIdx |
| 125738 | ){ |
| 125739 | int rc; /* Return Code */ |
| 125740 | sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ |
| 125741 | int iNext = 0; /* Result of query pNextIdx */ |
| 125742 | |
| 125743 | /* Set variable iNext to the next available segdir index at level iLevel. */ |
| 125744 | rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); |
| 125745 | if( rc==SQLITE_OK ){ |
| 125746 | sqlite3_bind_int(pNextIdx, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel); |
| 125747 | if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ |
| 125748 | iNext = sqlite3_column_int(pNextIdx, 0); |
| 125749 | } |
| 125750 | rc = sqlite3_reset(pNextIdx); |
| 125751 | } |
| @@ -125755,11 +126062,11 @@ | |
| 125755 | ** full, merge all segments in level iLevel into a single iLevel+1 |
| 125756 | ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise, |
| 125757 | ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext. |
| 125758 | */ |
| 125759 | if( iNext>=FTS3_MERGE_COUNT ){ |
| 125760 | rc = fts3SegmentMerge(p, iIndex, iLevel); |
| 125761 | *piIdx = 0; |
| 125762 | }else{ |
| 125763 | *piIdx = iNext; |
| 125764 | } |
| 125765 | } |
| @@ -126978,11 +127285,16 @@ | |
| 126978 | ** |
| 126979 | ** Segment levels are stored in the 'level' column of the %_segdir table. |
| 126980 | ** |
| 126981 | ** Return SQLITE_OK if successful, or an SQLite error code if not. |
| 126982 | */ |
| 126983 | static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){ |
| 126984 | sqlite3_stmt *pStmt; |
| 126985 | int rc; |
| 126986 | assert( iIndex>=0 && iIndex<p->nIndex ); |
| 126987 | |
| 126988 | /* Set pStmt to the compiled version of: |
| @@ -126991,12 +127303,14 @@ | |
| 126991 | ** |
| 126992 | ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). |
| 126993 | */ |
| 126994 | rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); |
| 126995 | if( rc!=SQLITE_OK ) return rc; |
| 126996 | sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL); |
| 126997 | sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL - 1); |
| 126998 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 126999 | *pnMax = sqlite3_column_int(pStmt, 0); |
| 127000 | } |
| 127001 | return sqlite3_reset(pStmt); |
| 127002 | } |
| @@ -127015,10 +127329,11 @@ | |
| 127015 | ** |
| 127016 | ** SQLITE_OK is returned if successful, otherwise an SQLite error code. |
| 127017 | */ |
| 127018 | static int fts3DeleteSegdir( |
| 127019 | Fts3Table *p, /* Virtual table handle */ |
| 127020 | int iIndex, /* Index for p->aIndex */ |
| 127021 | int iLevel, /* Level of %_segdir entries to delete */ |
| 127022 | Fts3SegReader **apSegment, /* Array of SegReader objects */ |
| 127023 | int nReader /* Size of array apSegment */ |
| 127024 | ){ |
| @@ -127042,17 +127357,19 @@ | |
| 127042 | |
| 127043 | assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL ); |
| 127044 | if( iLevel==FTS3_SEGCURSOR_ALL ){ |
| 127045 | rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0); |
| 127046 | if( rc==SQLITE_OK ){ |
| 127047 | sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL); |
| 127048 | sqlite3_bind_int(pDelete, 2, (iIndex+1) * FTS3_SEGDIR_MAXLEVEL - 1); |
| 127049 | } |
| 127050 | }else{ |
| 127051 | rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0); |
| 127052 | if( rc==SQLITE_OK ){ |
| 127053 | sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel); |
| 127054 | } |
| 127055 | } |
| 127056 | |
| 127057 | if( rc==SQLITE_OK ){ |
| 127058 | sqlite3_step(pDelete); |
| @@ -127517,27 +127834,32 @@ | |
| 127517 | ** If this function is called with iLevel<0, but there is only one |
| 127518 | ** segment in the database, SQLITE_DONE is returned immediately. |
| 127519 | ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, |
| 127520 | ** an SQLite error code is returned. |
| 127521 | */ |
| 127522 | static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){ |
| 127523 | int rc; /* Return code */ |
| 127524 | int iIdx = 0; /* Index of new segment */ |
| 127525 | int iNewLevel = 0; /* Level/index to create new segment at */ |
| 127526 | SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */ |
| 127527 | Fts3SegFilter filter; /* Segment term filter condition */ |
| 127528 | Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ |
| 127529 | int bIgnoreEmpty = 0; /* True to ignore empty segments */ |
| 127530 | |
| 127531 | assert( iLevel==FTS3_SEGCURSOR_ALL |
| 127532 | || iLevel==FTS3_SEGCURSOR_PENDING |
| 127533 | || iLevel>=0 |
| 127534 | ); |
| 127535 | assert( iLevel<FTS3_SEGDIR_MAXLEVEL ); |
| 127536 | assert( iIndex>=0 && iIndex<p->nIndex ); |
| 127537 | |
| 127538 | rc = sqlite3Fts3SegReaderCursor(p, iIndex, iLevel, 0, 0, 1, 0, &csr); |
| 127539 | if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished; |
| 127540 | |
| 127541 | if( iLevel==FTS3_SEGCURSOR_ALL ){ |
| 127542 | /* This call is to merge all segments in the database to a single |
| 127543 | ** segment. The level of the new segment is equal to the the numerically |
| @@ -127545,28 +127867,28 @@ | |
| 127545 | ** index. The idx of the new segment is always 0. */ |
| 127546 | if( csr.nSegment==1 ){ |
| 127547 | rc = SQLITE_DONE; |
| 127548 | goto finished; |
| 127549 | } |
| 127550 | rc = fts3SegmentMaxLevel(p, iIndex, &iNewLevel); |
| 127551 | bIgnoreEmpty = 1; |
| 127552 | |
| 127553 | }else if( iLevel==FTS3_SEGCURSOR_PENDING ){ |
| 127554 | iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL; |
| 127555 | rc = fts3AllocateSegdirIdx(p, iIndex, 0, &iIdx); |
| 127556 | }else{ |
| 127557 | /* This call is to merge all segments at level iLevel. find the next |
| 127558 | ** available segment index at level iLevel+1. The call to |
| 127559 | ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to |
| 127560 | ** a single iLevel+2 segment if necessary. */ |
| 127561 | rc = fts3AllocateSegdirIdx(p, iIndex, iLevel+1, &iIdx); |
| 127562 | iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL + iLevel+1; |
| 127563 | } |
| 127564 | if( rc!=SQLITE_OK ) goto finished; |
| 127565 | assert( csr.nSegment>0 ); |
| 127566 | assert( iNewLevel>=(iIndex*FTS3_SEGDIR_MAXLEVEL) ); |
| 127567 | assert( iNewLevel<((iIndex+1)*FTS3_SEGDIR_MAXLEVEL) ); |
| 127568 | |
| 127569 | memset(&filter, 0, sizeof(Fts3SegFilter)); |
| 127570 | filter.flags = FTS3_SEGMENT_REQUIRE_POS; |
| 127571 | filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0); |
| 127572 | |
| @@ -127579,11 +127901,13 @@ | |
| 127579 | } |
| 127580 | if( rc!=SQLITE_OK ) goto finished; |
| 127581 | assert( pWriter ); |
| 127582 | |
| 127583 | if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
| 127584 | rc = fts3DeleteSegdir(p, iIndex, iLevel, csr.apSegment, csr.nSegment); |
| 127585 | if( rc!=SQLITE_OK ) goto finished; |
| 127586 | } |
| 127587 | rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx); |
| 127588 | |
| 127589 | finished: |
| @@ -127598,11 +127922,11 @@ | |
| 127598 | */ |
| 127599 | SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ |
| 127600 | int rc = SQLITE_OK; |
| 127601 | int i; |
| 127602 | for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){ |
| 127603 | rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_PENDING); |
| 127604 | if( rc==SQLITE_DONE ) rc = SQLITE_OK; |
| 127605 | } |
| 127606 | sqlite3Fts3PendingTermsClear(p); |
| 127607 | return rc; |
| 127608 | } |
| @@ -127753,21 +128077,38 @@ | |
| 127753 | sqlite3_step(pStmt); |
| 127754 | *pRC = sqlite3_reset(pStmt); |
| 127755 | sqlite3_free(a); |
| 127756 | } |
| 127757 | |
| 127758 | static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ |
| 127759 | int i; |
| 127760 | int bSeenDone = 0; |
| 127761 | int rc = SQLITE_OK; |
| 127762 | for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){ |
| 127763 | rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_ALL); |
| 127764 | if( rc==SQLITE_DONE ){ |
| 127765 | bSeenDone = 1; |
| 127766 | rc = SQLITE_OK; |
| 127767 | } |
| 127768 | } |
| 127769 | sqlite3Fts3SegmentsClose(p); |
| 127770 | sqlite3Fts3PendingTermsClear(p); |
| 127771 | |
| 127772 | return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc; |
| 127773 | } |
| @@ -127814,15 +128155,16 @@ | |
| 127814 | } |
| 127815 | } |
| 127816 | |
| 127817 | while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 127818 | int iCol; |
| 127819 | rc = fts3PendingTermsDocid(p, sqlite3_column_int64(pStmt, 0)); |
| 127820 | aSz[p->nColumn] = 0; |
| 127821 | for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ |
| 127822 | const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); |
| 127823 | rc = fts3PendingTermsAdd(p, z, iCol, &aSz[iCol]); |
| 127824 | aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); |
| 127825 | } |
| 127826 | if( p->bHasDocsize ){ |
| 127827 | fts3InsertDocsize(&rc, p, aSz); |
| 127828 | } |
| @@ -127937,18 +128279,17 @@ | |
| 127937 | |
| 127938 | for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){ |
| 127939 | const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); |
| 127940 | sqlite3_tokenizer_cursor *pTC = 0; |
| 127941 | |
| 127942 | rc = pModule->xOpen(pT, zText, -1, &pTC); |
| 127943 | while( rc==SQLITE_OK ){ |
| 127944 | char const *zToken; /* Buffer containing token */ |
| 127945 | int nToken; /* Number of bytes in token */ |
| 127946 | int iDum1, iDum2; /* Dummy variables */ |
| 127947 | int iPos; /* Position of token in zText */ |
| 127948 | |
| 127949 | pTC->pTokenizer = pT; |
| 127950 | rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos); |
| 127951 | for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ |
| 127952 | Fts3PhraseToken *pPT = pDef->pToken; |
| 127953 | if( (pDef->iCol>=p->nColumn || pDef->iCol==i) |
| 127954 | && (pPT->bFirst==0 || iPos==0) |
| @@ -128044,12 +128385,10 @@ | |
| 128044 | ** delete the contents of all three tables and throw away any |
| 128045 | ** data in the pendingTerms hash table. */ |
| 128046 | rc = fts3DeleteAll(p, 1); |
| 128047 | *pnDoc = *pnDoc - 1; |
| 128048 | }else{ |
| 128049 | sqlite3_int64 iRemove = sqlite3_value_int64(pRowid); |
| 128050 | rc = fts3PendingTermsDocid(p, iRemove); |
| 128051 | fts3DeleteTerms(&rc, p, pRowid, aSzDel); |
| 128052 | if( p->zContentTbl==0 ){ |
| 128053 | fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid); |
| 128054 | if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1; |
| 128055 | }else{ |
| @@ -128064,11 +128403,20 @@ | |
| 128064 | return rc; |
| 128065 | } |
| 128066 | |
| 128067 | /* |
| 128068 | ** This function does the work for the xUpdate method of FTS3 virtual |
| 128069 | ** tables. |
| 128070 | */ |
| 128071 | SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( |
| 128072 | sqlite3_vtab *pVtab, /* FTS3 vtab object */ |
| 128073 | int nArg, /* Size of argument array */ |
| 128074 | sqlite3_value **apVal, /* Array of arguments */ |
| @@ -128081,10 +128429,14 @@ | |
| 128081 | u32 *aSzDel; /* Sizes of deleted documents */ |
| 128082 | int nChng = 0; /* Net change in number of documents */ |
| 128083 | int bInsertDone = 0; |
| 128084 | |
| 128085 | assert( p->pSegments==0 ); |
| 128086 | |
| 128087 | /* Check for a "special" INSERT operation. One of the form: |
| 128088 | ** |
| 128089 | ** INSERT INTO xyz(xyz) VALUES('command'); |
| 128090 | */ |
| @@ -128093,10 +128445,15 @@ | |
| 128093 | && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL |
| 128094 | ){ |
| 128095 | rc = fts3SpecialInsert(p, apVal[p->nColumn+2]); |
| 128096 | goto update_out; |
| 128097 | } |
| 128098 | |
| 128099 | /* Allocate space to hold the change in document sizes */ |
| 128100 | aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 ); |
| 128101 | if( aSzIns==0 ){ |
| 128102 | rc = SQLITE_NOMEM; |
| @@ -128161,22 +128518,23 @@ | |
| 128161 | isRemove = 1; |
| 128162 | } |
| 128163 | |
| 128164 | /* If this is an INSERT or UPDATE operation, insert the new record. */ |
| 128165 | if( nArg>1 && rc==SQLITE_OK ){ |
| 128166 | if( bInsertDone==0 ){ |
| 128167 | rc = fts3InsertData(p, apVal, pRowid); |
| 128168 | if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ |
| 128169 | rc = FTS_CORRUPT_VTAB; |
| 128170 | } |
| 128171 | } |
| 128172 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ |
| 128173 | rc = fts3PendingTermsDocid(p, *pRowid); |
| 128174 | } |
| 128175 | if( rc==SQLITE_OK ){ |
| 128176 | assert( p->iPrevDocid==*pRowid ); |
| 128177 | rc = fts3InsertTerms(p, apVal, aSzIns); |
| 128178 | } |
| 128179 | if( p->bHasDocsize ){ |
| 128180 | fts3InsertDocsize(&rc, p, aSzIns); |
| 128181 | } |
| 128182 | nChng++; |
| @@ -128749,10 +129107,11 @@ | |
| 128749 | ** is no way for fts3BestSnippet() to know whether or not the document |
| 128750 | ** actually contains terms that follow the final highlighted term. |
| 128751 | */ |
| 128752 | static int fts3SnippetShift( |
| 128753 | Fts3Table *pTab, /* FTS3 table snippet comes from */ |
| 128754 | int nSnippet, /* Number of tokens desired for snippet */ |
| 128755 | const char *zDoc, /* Document text to extract snippet from */ |
| 128756 | int nDoc, /* Size of buffer zDoc in bytes */ |
| 128757 | int *piPos, /* IN/OUT: First token of snippet */ |
| 128758 | u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */ |
| @@ -128784,15 +129143,14 @@ | |
| 128784 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 128785 | |
| 128786 | /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) |
| 128787 | ** or more tokens in zDoc/nDoc. |
| 128788 | */ |
| 128789 | rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 128790 | if( rc!=SQLITE_OK ){ |
| 128791 | return rc; |
| 128792 | } |
| 128793 | pC->pTokenizer = pTab->pTokenizer; |
| 128794 | while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ |
| 128795 | const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3; |
| 128796 | rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); |
| 128797 | } |
| 128798 | pMod->xClose(pC); |
| @@ -128848,15 +129206,14 @@ | |
| 128848 | } |
| 128849 | nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); |
| 128850 | |
| 128851 | /* Open a token cursor on the document. */ |
| 128852 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 128853 | rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 128854 | if( rc!=SQLITE_OK ){ |
| 128855 | return rc; |
| 128856 | } |
| 128857 | pC->pTokenizer = pTab->pTokenizer; |
| 128858 | |
| 128859 | while( rc==SQLITE_OK ){ |
| 128860 | int iBegin; /* Offset in zDoc of start of token */ |
| 128861 | int iFin; /* Offset in zDoc of end of token */ |
| 128862 | int isHighlight; /* True for highlighted terms */ |
| @@ -128874,11 +129231,13 @@ | |
| 128874 | } |
| 128875 | if( iCurrent<iPos ){ continue; } |
| 128876 | |
| 128877 | if( !isShiftDone ){ |
| 128878 | int n = nDoc - iBegin; |
| 128879 | rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask); |
| 128880 | isShiftDone = 1; |
| 128881 | |
| 128882 | /* Now that the shift has been done, check if the initial "..." are |
| 128883 | ** required. They are required if (a) this is not the first fragment, |
| 128884 | ** or (b) this fragment does not begin at position 0 of its column. |
| @@ -129607,13 +129966,14 @@ | |
| 129607 | rc = SQLITE_NOMEM; |
| 129608 | goto offsets_out; |
| 129609 | } |
| 129610 | |
| 129611 | /* Initialize a tokenizer iterator to iterate through column iCol. */ |
| 129612 | rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 129613 | if( rc!=SQLITE_OK ) goto offsets_out; |
| 129614 | pC->pTokenizer = pTab->pTokenizer; |
| 129615 | |
| 129616 | rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); |
| 129617 | while( rc==SQLITE_OK ){ |
| 129618 | int i; /* Used to loop through terms */ |
| 129619 | int iMinPos = 0x7FFFFFFF; /* Position of next token */ |
| 129620 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -657,11 +657,11 @@ | |
| 657 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 658 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 659 | */ |
| 660 | #define SQLITE_VERSION "3.7.11" |
| 661 | #define SQLITE_VERSION_NUMBER 3007011 |
| 662 | #define SQLITE_SOURCE_ID "2012-03-16 00:28:11 74eadeec34c4b19cf5f8b7f648db3b7ad601a00e" |
| 663 | |
| 664 | /* |
| 665 | ** CAPI3REF: Run-Time Library Version Numbers |
| 666 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 667 | ** |
| @@ -1009,10 +1009,11 @@ | |
| 1009 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 1010 | #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) |
| 1011 | #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) |
| 1012 | #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) |
| 1013 | #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) |
| 1014 | #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) |
| 1015 | |
| 1016 | /* |
| 1017 | ** CAPI3REF: Flags For File Open Operations |
| 1018 | ** |
| 1019 | ** These bit values are intended for use in the |
| @@ -1264,31 +1265,35 @@ | |
| 1265 | ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], |
| 1266 | ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) |
| 1267 | ** into an integer that the pArg argument points to. This capability |
| 1268 | ** is used during testing and only needs to be supported when SQLITE_TEST |
| 1269 | ** is defined. |
| 1270 | ** <ul> |
| 1271 | ** <li>[[SQLITE_FCNTL_SIZE_HINT]] |
| 1272 | ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS |
| 1273 | ** layer a hint of how large the database file will grow to be during the |
| 1274 | ** current transaction. This hint is not guaranteed to be accurate but it |
| 1275 | ** is often close. The underlying VFS might choose to preallocate database |
| 1276 | ** file space based on this hint in order to help writes to the database |
| 1277 | ** file run faster. |
| 1278 | ** |
| 1279 | ** <li>[[SQLITE_FCNTL_CHUNK_SIZE]] |
| 1280 | ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS |
| 1281 | ** extends and truncates the database file in chunks of a size specified |
| 1282 | ** by the user. The fourth argument to [sqlite3_file_control()] should |
| 1283 | ** point to an integer (type int) containing the new chunk-size to use |
| 1284 | ** for the nominated database. Allocating database file space in large |
| 1285 | ** chunks (say 1MB at a time), may reduce file-system fragmentation and |
| 1286 | ** improve performance on some systems. |
| 1287 | ** |
| 1288 | ** <li>[[SQLITE_FCNTL_FILE_POINTER]] |
| 1289 | ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer |
| 1290 | ** to the [sqlite3_file] object associated with a particular database |
| 1291 | ** connection. See the [sqlite3_file_control()] documentation for |
| 1292 | ** additional information. |
| 1293 | ** |
| 1294 | ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] |
| 1295 | ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by |
| 1296 | ** SQLite and sent to all VFSes in place of a call to the xSync method |
| 1297 | ** when the database connection has [PRAGMA synchronous] set to OFF.)^ |
| 1298 | ** Some specialized VFSes need this signal in order to operate correctly |
| 1299 | ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most |
| @@ -1295,10 +1300,11 @@ | |
| 1300 | ** VFSes do not need this signal and should silently ignore this opcode. |
| 1301 | ** Applications should not call [sqlite3_file_control()] with this |
| 1302 | ** opcode as doing so may disrupt the operation of the specialized VFSes |
| 1303 | ** that do require it. |
| 1304 | ** |
| 1305 | ** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]] |
| 1306 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 1307 | ** retry counts and intervals for certain disk I/O operations for the |
| 1308 | ** windows [VFS] in order to provide robustness in the presence of |
| 1309 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 1310 | ** file write, and file delete operations up to 10 times, with a delay |
| @@ -1311,10 +1317,11 @@ | |
| 1317 | ** integer is the delay. If either integer is negative, then the setting |
| 1318 | ** is not changed but instead the prior value of that setting is written |
| 1319 | ** into the array entry, allowing the current retry settings to be |
| 1320 | ** interrogated. The zDbName parameter is ignored. |
| 1321 | ** |
| 1322 | ** <li>[[SQLITE_FCNTL_PERSIST_WAL]] |
| 1323 | ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the |
| 1324 | ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary |
| 1325 | ** write ahead log and shared memory files used for transaction control |
| 1326 | ** are automatically deleted when the latest connection to the database |
| 1327 | ** closes. Setting persistent WAL mode causes those files to persist after |
| @@ -1325,24 +1332,27 @@ | |
| 1332 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 1333 | ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent |
| 1334 | ** WAL mode. If the integer is -1, then it is overwritten with the current |
| 1335 | ** WAL persistence setting. |
| 1336 | ** |
| 1337 | ** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] |
| 1338 | ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the |
| 1339 | ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting |
| 1340 | ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the |
| 1341 | ** xDeviceCharacteristics methods. The fourth parameter to |
| 1342 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 1343 | ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage |
| 1344 | ** mode. If the integer is -1, then it is overwritten with the current |
| 1345 | ** zero-damage mode setting. |
| 1346 | ** |
| 1347 | ** <li>[[SQLITE_FCNTL_OVERWRITE]] |
| 1348 | ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening |
| 1349 | ** a write transaction to indicate that, unless it is rolled back for some |
| 1350 | ** reason, the entire database file will be overwritten by the current |
| 1351 | ** transaction. This is used by VACUUM operations. |
| 1352 | ** |
| 1353 | ** <li>[[SQLITE_FCNTL_VFSNAME]] |
| 1354 | ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of |
| 1355 | ** all [VFSes] in the VFS stack. The names are of all VFS shims and the |
| 1356 | ** final bottom-level VFS are written into memory obtained from |
| 1357 | ** [sqlite3_malloc()] and the result is stored in the char* variable |
| 1358 | ** that the fourth parameter of [sqlite3_file_control()] points to. |
| @@ -1349,10 +1359,34 @@ | |
| 1359 | ** The caller is responsible for freeing the memory when done. As with |
| 1360 | ** all file-control actions, there is no guarantee that this will actually |
| 1361 | ** do anything. Callers should initialize the char* variable to a NULL |
| 1362 | ** pointer in case this file-control is not implemented. This file-control |
| 1363 | ** is intended for diagnostic use only. |
| 1364 | ** |
| 1365 | ** <li>[[SQLITE_FCNTL_PRAGMA]] |
| 1366 | ** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] |
| 1367 | ** file control is sent to the open [sqlite3_file] object corresponding |
| 1368 | ** to the database file to which the pragma statement refers. ^The argument |
| 1369 | ** to the [SQLITE_FCNTL_PRAGMA] file control is an array of |
| 1370 | ** pointers to strings (char**) in which the second element of the array |
| 1371 | ** is the name of the pragma and the third element is the argument to the |
| 1372 | ** pragma or NULL if the pragma has no argument. ^The handler for an |
| 1373 | ** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element |
| 1374 | ** of the char** argument point to a string obtained from [sqlite3_mprintf()] |
| 1375 | ** or the equivalent and that string will become the result of the pragma or |
| 1376 | ** the error message if the pragma fails. ^If the |
| 1377 | ** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal |
| 1378 | ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] |
| 1379 | ** file control returns [SQLITE_OK], then the parser assumes that the |
| 1380 | ** VFS has handled the PRAGMA itself and the parser generates a no-op |
| 1381 | ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns |
| 1382 | ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means |
| 1383 | ** that the VFS encountered an error while handling the [PRAGMA] and the |
| 1384 | ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] |
| 1385 | ** file control occurs at the beginning of pragma statement analysis and so |
| 1386 | ** it is able to override built-in [PRAGMA] statements. |
| 1387 | ** </ul> |
| 1388 | */ |
| 1389 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 1390 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 1391 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 1392 | #define SQLITE_LAST_ERRNO 4 |
| @@ -1363,10 +1397,11 @@ | |
| 1397 | #define SQLITE_FCNTL_WIN32_AV_RETRY 9 |
| 1398 | #define SQLITE_FCNTL_PERSIST_WAL 10 |
| 1399 | #define SQLITE_FCNTL_OVERWRITE 11 |
| 1400 | #define SQLITE_FCNTL_VFSNAME 12 |
| 1401 | #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 |
| 1402 | #define SQLITE_FCNTL_PRAGMA 14 |
| 1403 | |
| 1404 | /* |
| 1405 | ** CAPI3REF: Mutex Handle |
| 1406 | ** |
| 1407 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -5012,10 +5047,19 @@ | |
| 5047 | ** will be an absolute pathname, even if the filename used |
| 5048 | ** to open the database originally was a URI or relative pathname. |
| 5049 | */ |
| 5050 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); |
| 5051 | |
| 5052 | /* |
| 5053 | ** CAPI3REF: Determine if a database is read-only |
| 5054 | ** |
| 5055 | ** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N |
| 5056 | ** of connection D is read-only, 0 if it is read/write, or -1 if N is not |
| 5057 | ** the name of a database on connection D. |
| 5058 | */ |
| 5059 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); |
| 5060 | |
| 5061 | /* |
| 5062 | ** CAPI3REF: Find the next prepared statement |
| 5063 | ** |
| 5064 | ** ^This interface returns a pointer to the next [prepared statement] after |
| 5065 | ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL |
| @@ -7137,15 +7181,16 @@ | |
| 7181 | |
| 7182 | |
| 7183 | /* |
| 7184 | ** CAPI3REF: String Comparison |
| 7185 | ** |
| 7186 | ** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications |
| 7187 | ** and extensions to compare the contents of two buffers containing UTF-8 |
| 7188 | ** strings in a case-independent fashion, using the same definition of "case |
| 7189 | ** independence" that SQLite uses internally when comparing identifiers. |
| 7190 | */ |
| 7191 | SQLITE_API int sqlite3_stricmp(const char *, const char *); |
| 7192 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 7193 | |
| 7194 | /* |
| 7195 | ** CAPI3REF: Error Logging Interface |
| 7196 | ** |
| @@ -8204,11 +8249,11 @@ | |
| 8249 | SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); |
| 8250 | SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); |
| 8251 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); |
| 8252 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); |
| 8253 | SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); |
| 8254 | SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int); |
| 8255 | SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); |
| 8256 | SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); |
| 8257 | SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); |
| 8258 | SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); |
| 8259 | SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); |
| @@ -8944,10 +8989,13 @@ | |
| 8989 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); |
| 8990 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 8991 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 8992 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 8993 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); |
| 8994 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 8995 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 8996 | #endif |
| 8997 | |
| 8998 | /* Functions used to query pager state and configuration. */ |
| 8999 | SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); |
| 9000 | SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| 9001 | SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); |
| @@ -11415,11 +11463,11 @@ | |
| 11463 | #endif |
| 11464 | |
| 11465 | /* |
| 11466 | ** Internal function prototypes |
| 11467 | */ |
| 11468 | #define sqlite3StrICmp sqlite3_stricmp |
| 11469 | SQLITE_PRIVATE int sqlite3Strlen30(const char*); |
| 11470 | #define sqlite3StrNICmp sqlite3_strnicmp |
| 11471 | |
| 11472 | SQLITE_PRIVATE int sqlite3MallocInit(void); |
| 11473 | SQLITE_PRIVATE void sqlite3MallocEnd(void); |
| @@ -11563,10 +11611,11 @@ | |
| 11611 | SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*); |
| 11612 | SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); |
| 11613 | SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*); |
| 11614 | SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, |
| 11615 | sqlite3_vfs**,char**,char **); |
| 11616 | SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); |
| 11617 | SQLITE_PRIVATE int sqlite3CodeOnce(Parse *); |
| 11618 | |
| 11619 | SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32); |
| 11620 | SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32); |
| 11621 | SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); |
| @@ -11662,11 +11711,11 @@ | |
| 11711 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); |
| 11712 | SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); |
| 11713 | SQLITE_PRIVATE void sqlite3PrngSaveState(void); |
| 11714 | SQLITE_PRIVATE void sqlite3PrngRestoreState(void); |
| 11715 | SQLITE_PRIVATE void sqlite3PrngResetState(void); |
| 11716 | SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); |
| 11717 | SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); |
| 11718 | SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); |
| 11719 | SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int); |
| 11720 | SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*); |
| 11721 | SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*); |
| @@ -21216,11 +21265,11 @@ | |
| 21265 | ** applications and extensions to compare the contents of two buffers |
| 21266 | ** containing UTF-8 strings in a case-independent fashion, using the same |
| 21267 | ** definition of case independence that SQLite uses internally when |
| 21268 | ** comparing identifiers. |
| 21269 | */ |
| 21270 | SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){ |
| 21271 | register unsigned char *a, *b; |
| 21272 | a = (unsigned char *)zLeft; |
| 21273 | b = (unsigned char *)zRight; |
| 21274 | while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } |
| 21275 | return UpperToLower[*a] - UpperToLower[*b]; |
| @@ -25494,11 +25543,11 @@ | |
| 25543 | ** recover the hot journals. |
| 25544 | */ |
| 25545 | static int robust_open(const char *z, int f, mode_t m){ |
| 25546 | int rc; |
| 25547 | mode_t m2; |
| 25548 | mode_t origM = 0; |
| 25549 | if( m==0 ){ |
| 25550 | m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; |
| 25551 | }else{ |
| 25552 | m2 = m; |
| 25553 | origM = osUmask(0); |
| @@ -38302,10 +38351,11 @@ | |
| 38351 | # define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 38352 | # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 |
| 38353 | # define sqlite3WalCallback(z) 0 |
| 38354 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 38355 | # define sqlite3WalHeapMemory(z) 0 |
| 38356 | # define sqlite3WalFramesize(z) 0 |
| 38357 | #else |
| 38358 | |
| 38359 | #define WAL_SAVEPOINT_NDATA 4 |
| 38360 | |
| 38361 | /* Connection to a write-ahead log (WAL) file. |
| @@ -38382,10 +38432,17 @@ | |
| 38432 | /* Return true if the argument is non-NULL and the WAL module is using |
| 38433 | ** heap-memory for the wal-index. Otherwise, if the argument is NULL or the |
| 38434 | ** WAL module is using shared-memory, return false. |
| 38435 | */ |
| 38436 | SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); |
| 38437 | |
| 38438 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 38439 | /* If the WAL file is not empty, return the number of bytes of content |
| 38440 | ** stored in each frame (i.e. the db page-size when the WAL was created). |
| 38441 | */ |
| 38442 | SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal); |
| 38443 | #endif |
| 38444 | |
| 38445 | #endif /* ifndef SQLITE_OMIT_WAL */ |
| 38446 | #endif /* _WAL_H_ */ |
| 38447 | |
| 38448 | /************** End of wal.h *************************************************/ |
| @@ -45237,10 +45294,24 @@ | |
| 45294 | pPager->pWal = 0; |
| 45295 | } |
| 45296 | } |
| 45297 | return rc; |
| 45298 | } |
| 45299 | |
| 45300 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 45301 | /* |
| 45302 | ** A read-lock must be held on the pager when this function is called. If |
| 45303 | ** the pager is in WAL mode and the WAL file currently contains one or more |
| 45304 | ** frames, return the size in bytes of the page images stored within the |
| 45305 | ** WAL frames. Otherwise, if this is not a WAL database or the WAL file |
| 45306 | ** is empty, return 0. |
| 45307 | */ |
| 45308 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ |
| 45309 | assert( pPager->eState==PAGER_READER ); |
| 45310 | return sqlite3WalFramesize(pPager->pWal); |
| 45311 | } |
| 45312 | #endif |
| 45313 | |
| 45314 | #ifdef SQLITE_HAS_CODEC |
| 45315 | /* |
| 45316 | ** This function is called by the wal module when writing page content |
| 45317 | ** into the log file. |
| @@ -47657,11 +47728,11 @@ | |
| 47728 | testcase( sz<=32768 ); |
| 47729 | testcase( sz>=65536 ); |
| 47730 | iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; |
| 47731 | *pInWal = 1; |
| 47732 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ |
| 47733 | return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset); |
| 47734 | } |
| 47735 | |
| 47736 | *pInWal = 0; |
| 47737 | return SQLITE_OK; |
| 47738 | } |
| @@ -48327,10 +48398,22 @@ | |
| 48398 | ** WAL module is using shared-memory, return false. |
| 48399 | */ |
| 48400 | SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ |
| 48401 | return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ); |
| 48402 | } |
| 48403 | |
| 48404 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 48405 | /* |
| 48406 | ** If the argument is not NULL, it points to a Wal object that holds a |
| 48407 | ** read-lock. This function returns the database page-size if it is known, |
| 48408 | ** or zero if it is not (or if pWal is NULL). |
| 48409 | */ |
| 48410 | SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){ |
| 48411 | assert( pWal==0 || pWal->readLock>=0 ); |
| 48412 | return (pWal ? pWal->szPage : 0); |
| 48413 | } |
| 48414 | #endif |
| 48415 | |
| 48416 | #endif /* #ifndef SQLITE_OMIT_WAL */ |
| 48417 | |
| 48418 | /************** End of wal.c *************************************************/ |
| 48419 | /************** Begin file btmutex.c *****************************************/ |
| @@ -51320,11 +51403,11 @@ | |
| 51403 | |
| 51404 | /* Rollback any active transaction and free the handle structure. |
| 51405 | ** The call to sqlite3BtreeRollback() drops any table-locks held by |
| 51406 | ** this handle. |
| 51407 | */ |
| 51408 | sqlite3BtreeRollback(p, SQLITE_OK); |
| 51409 | sqlite3BtreeLeave(p); |
| 51410 | |
| 51411 | /* If there are still other outstanding references to the shared-btree |
| 51412 | ** structure, return now. The remainder of this procedure cleans |
| 51413 | ** up the shared-btree. |
| @@ -52558,10 +52641,11 @@ | |
| 52641 | ** save the state of the cursor. The cursor must be |
| 52642 | ** invalidated. |
| 52643 | */ |
| 52644 | SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ |
| 52645 | BtCursor *p; |
| 52646 | if( pBtree==0 ) return; |
| 52647 | sqlite3BtreeEnter(pBtree); |
| 52648 | for(p=pBtree->pBt->pCursor; p; p=p->pNext){ |
| 52649 | int i; |
| 52650 | sqlite3BtreeClearCursor(p); |
| 52651 | p->eState = CURSOR_FAULT; |
| @@ -52581,29 +52665,24 @@ | |
| 52665 | ** in an error. |
| 52666 | ** |
| 52667 | ** This will release the write lock on the database file. If there |
| 52668 | ** are no active cursors, it also releases the read lock. |
| 52669 | */ |
| 52670 | SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){ |
| 52671 | int rc; |
| 52672 | BtShared *pBt = p->pBt; |
| 52673 | MemPage *pPage1; |
| 52674 | |
| 52675 | sqlite3BtreeEnter(p); |
| 52676 | if( tripCode==SQLITE_OK ){ |
| 52677 | rc = tripCode = saveAllCursors(pBt, 0, 0); |
| 52678 | }else{ |
| 52679 | rc = SQLITE_OK; |
| 52680 | } |
| 52681 | if( tripCode ){ |
| 52682 | sqlite3BtreeTripAllCursors(p, tripCode); |
| 52683 | } |
| 52684 | btreeIntegrity(p); |
| 52685 | |
| 52686 | if( p->inTrans==TRANS_WRITE ){ |
| 52687 | int rc2; |
| 52688 | |
| @@ -58121,11 +58200,11 @@ | |
| 58200 | } |
| 58201 | *pp = p->pNext; |
| 58202 | } |
| 58203 | |
| 58204 | /* If a transaction is still open on the Btree, roll it back. */ |
| 58205 | sqlite3BtreeRollback(p->pDest, SQLITE_OK); |
| 58206 | |
| 58207 | /* Set the error code of the destination database handle. */ |
| 58208 | rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; |
| 58209 | sqlite3Error(p->pDestDb, rc, 0); |
| 58210 | |
| @@ -61431,36 +61510,10 @@ | |
| 61510 | } |
| 61511 | #else |
| 61512 | #define checkActiveVdbeCnt(x) |
| 61513 | #endif |
| 61514 | |
| 61515 | /* |
| 61516 | ** If the Vdbe passed as the first argument opened a statement-transaction, |
| 61517 | ** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or |
| 61518 | ** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement |
| 61519 | ** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the |
| @@ -61621,12 +61674,11 @@ | |
| 61674 | eStatementOp = SAVEPOINT_ROLLBACK; |
| 61675 | }else{ |
| 61676 | /* We are forced to roll back the active transaction. Before doing |
| 61677 | ** so, abort any other statements this handle currently has active. |
| 61678 | */ |
| 61679 | sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); |
| 61680 | sqlite3CloseSavepoints(db); |
| 61681 | db->autoCommit = 1; |
| 61682 | } |
| 61683 | } |
| 61684 | } |
| @@ -61664,27 +61716,26 @@ | |
| 61716 | if( rc==SQLITE_BUSY && p->readOnly ){ |
| 61717 | sqlite3VdbeLeave(p); |
| 61718 | return SQLITE_BUSY; |
| 61719 | }else if( rc!=SQLITE_OK ){ |
| 61720 | p->rc = rc; |
| 61721 | sqlite3RollbackAll(db, SQLITE_OK); |
| 61722 | }else{ |
| 61723 | db->nDeferredCons = 0; |
| 61724 | sqlite3CommitInternalChanges(db); |
| 61725 | } |
| 61726 | }else{ |
| 61727 | sqlite3RollbackAll(db, SQLITE_OK); |
| 61728 | } |
| 61729 | db->nStatement = 0; |
| 61730 | }else if( eStatementOp==0 ){ |
| 61731 | if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ |
| 61732 | eStatementOp = SAVEPOINT_RELEASE; |
| 61733 | }else if( p->errorAction==OE_Abort ){ |
| 61734 | eStatementOp = SAVEPOINT_ROLLBACK; |
| 61735 | }else{ |
| 61736 | sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); |
| 61737 | sqlite3CloseSavepoints(db); |
| 61738 | db->autoCommit = 1; |
| 61739 | } |
| 61740 | } |
| 61741 | |
| @@ -61700,12 +61751,11 @@ | |
| 61751 | if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){ |
| 61752 | p->rc = rc; |
| 61753 | sqlite3DbFree(db, p->zErrMsg); |
| 61754 | p->zErrMsg = 0; |
| 61755 | } |
| 61756 | sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); |
| 61757 | sqlite3CloseSavepoints(db); |
| 61758 | db->autoCommit = 1; |
| 61759 | } |
| 61760 | } |
| 61761 | |
| @@ -67513,20 +67563,16 @@ | |
| 67563 | u.ar.iSavepoint++; |
| 67564 | } |
| 67565 | if( !u.ar.pSavepoint ){ |
| 67566 | sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName); |
| 67567 | rc = SQLITE_ERROR; |
| 67568 | }else if( db->writeVdbeCnt>0 && u.ar.p1==SAVEPOINT_RELEASE ){ |
| 67569 | /* It is not possible to release (commit) a savepoint if there are |
| 67570 | ** active write statements. |
| 67571 | */ |
| 67572 | sqlite3SetString(&p->zErrMsg, db, |
| 67573 | "cannot release savepoint - SQL statements in progress" |
| 67574 | ); |
| 67575 | rc = SQLITE_BUSY; |
| 67576 | }else{ |
| 67577 | |
| 67578 | /* Determine whether or not this is a transaction savepoint. If so, |
| @@ -67547,10 +67593,13 @@ | |
| 67593 | } |
| 67594 | db->isTransactionSavepoint = 0; |
| 67595 | rc = p->rc; |
| 67596 | }else{ |
| 67597 | u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1; |
| 67598 | for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){ |
| 67599 | sqlite3BtreeTripAllCursors(db->aDb[u.ar.ii].pBt, SQLITE_ABORT); |
| 67600 | } |
| 67601 | for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){ |
| 67602 | rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint); |
| 67603 | if( rc!=SQLITE_OK ){ |
| 67604 | goto abort_due_to_error; |
| 67605 | } |
| @@ -67617,29 +67666,32 @@ | |
| 67666 | u.as.turnOnAC = u.as.desiredAutoCommit && !db->autoCommit; |
| 67667 | assert( u.as.desiredAutoCommit==1 || u.as.desiredAutoCommit==0 ); |
| 67668 | assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 ); |
| 67669 | assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ |
| 67670 | |
| 67671 | #if 0 |
| 67672 | if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){ |
| 67673 | /* If this instruction implements a ROLLBACK and other VMs are |
| 67674 | ** still running, and a transaction is active, return an error indicating |
| 67675 | ** that the other VMs must complete first. |
| 67676 | */ |
| 67677 | sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - " |
| 67678 | "SQL statements in progress"); |
| 67679 | rc = SQLITE_BUSY; |
| 67680 | }else |
| 67681 | #endif |
| 67682 | if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){ |
| 67683 | /* If this instruction implements a COMMIT and other VMs are writing |
| 67684 | ** return an error indicating that the other VMs must complete first. |
| 67685 | */ |
| 67686 | sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - " |
| 67687 | "SQL statements in progress"); |
| 67688 | rc = SQLITE_BUSY; |
| 67689 | }else if( u.as.desiredAutoCommit!=db->autoCommit ){ |
| 67690 | if( u.as.iRollback ){ |
| 67691 | assert( u.as.desiredAutoCommit==1 ); |
| 67692 | sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); |
| 67693 | db->autoCommit = 1; |
| 67694 | }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ |
| 67695 | goto vdbe_return; |
| 67696 | }else{ |
| 67697 | db->autoCommit = (u8)u.as.desiredAutoCommit; |
| @@ -68701,11 +68753,11 @@ | |
| 68753 | u.bg.v = 1; /* IMP: R-61914-48074 */ |
| 68754 | }else{ |
| 68755 | assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) ); |
| 68756 | rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v); |
| 68757 | assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ |
| 68758 | if( u.bg.v>=MAX_ROWID ){ |
| 68759 | u.bg.pC->useRandomRowid = 1; |
| 68760 | }else{ |
| 68761 | u.bg.v++; /* IMP: R-29538-34987 */ |
| 68762 | } |
| 68763 | } |
| @@ -92317,13 +92369,16 @@ | |
| 92369 | char *zLeft = 0; /* Nul-terminated UTF-8 string <id> */ |
| 92370 | char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */ |
| 92371 | const char *zDb = 0; /* The database name */ |
| 92372 | Token *pId; /* Pointer to <id> token */ |
| 92373 | int iDb; /* Database index for <database> */ |
| 92374 | char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ |
| 92375 | int rc; /* return value form SQLITE_FCNTL_PRAGMA */ |
| 92376 | sqlite3 *db = pParse->db; /* The database connection */ |
| 92377 | Db *pDb; /* The specific database being pragmaed */ |
| 92378 | Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); /* Prepared statement */ |
| 92379 | |
| 92380 | if( v==0 ) return; |
| 92381 | sqlite3VdbeRunOnlyOnce(v); |
| 92382 | pParse->nMem = 2; |
| 92383 | |
| 92384 | /* Interpret the [database.] part of the pragma statement. iDb is the |
| @@ -92350,10 +92405,38 @@ | |
| 92405 | assert( pId2 ); |
| 92406 | zDb = pId2->n>0 ? pDb->zName : 0; |
| 92407 | if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ |
| 92408 | goto pragma_out; |
| 92409 | } |
| 92410 | |
| 92411 | /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS |
| 92412 | ** connection. If it returns SQLITE_OK, then assume that the VFS |
| 92413 | ** handled the pragma and generate a no-op prepared statement. |
| 92414 | */ |
| 92415 | aFcntl[0] = 0; |
| 92416 | aFcntl[1] = zLeft; |
| 92417 | aFcntl[2] = zRight; |
| 92418 | aFcntl[3] = 0; |
| 92419 | rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); |
| 92420 | if( rc==SQLITE_OK ){ |
| 92421 | if( aFcntl[0] ){ |
| 92422 | int mem = ++pParse->nMem; |
| 92423 | sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0); |
| 92424 | sqlite3VdbeSetNumCols(v, 1); |
| 92425 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC); |
| 92426 | sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); |
| 92427 | sqlite3_free(aFcntl[0]); |
| 92428 | } |
| 92429 | }else if( rc!=SQLITE_NOTFOUND ){ |
| 92430 | if( aFcntl[0] ){ |
| 92431 | sqlite3ErrorMsg(pParse, "%s", aFcntl[0]); |
| 92432 | sqlite3_free(aFcntl[0]); |
| 92433 | } |
| 92434 | pParse->nErr++; |
| 92435 | pParse->rc = rc; |
| 92436 | }else |
| 92437 | |
| 92438 | |
| 92439 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
| 92440 | /* |
| 92441 | ** PRAGMA [database.]default_cache_size |
| 92442 | ** PRAGMA [database.]default_cache_size=N |
| @@ -92637,11 +92720,11 @@ | |
| 92720 | /* Call SetAutoVacuum() to set initialize the internal auto and |
| 92721 | ** incr-vacuum flags. This is required in case this connection |
| 92722 | ** creates the database file. It is important that it is created |
| 92723 | ** as an auto-vacuum capable db. |
| 92724 | */ |
| 92725 | rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); |
| 92726 | if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ |
| 92727 | /* When setting the auto_vacuum mode to either "full" or |
| 92728 | ** "incremental", write the value of meta[6] in the database |
| 92729 | ** file. Before writing to meta[6], check that meta[3] indicates |
| 92730 | ** that this really is an auto-vacuum capable database. |
| @@ -92755,11 +92838,10 @@ | |
| 92838 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
| 92839 | } |
| 92840 | }else{ |
| 92841 | #ifndef SQLITE_OMIT_WSD |
| 92842 | if( zRight[0] ){ |
| 92843 | int res; |
| 92844 | rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); |
| 92845 | if( rc!=SQLITE_OK || res==0 ){ |
| 92846 | sqlite3ErrorMsg(pParse, "not a writable directory"); |
| 92847 | goto pragma_out; |
| @@ -95671,11 +95753,11 @@ | |
| 95753 | int nCol; /* Number of columns in the result set */ |
| 95754 | Expr *p; /* Expression for a single result column */ |
| 95755 | char *zName; /* Column name */ |
| 95756 | int nName; /* Size of name in zName[] */ |
| 95757 | |
| 95758 | *pnCol = nCol = pEList ? pEList->nExpr : 0; |
| 95759 | aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); |
| 95760 | if( aCol==0 ) return SQLITE_NOMEM; |
| 95761 | for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
| 95762 | /* Get an appropriate name for the column |
| 95763 | */ |
| @@ -101201,10 +101283,22 @@ | |
| 101283 | char *zKey; |
| 101284 | sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); |
| 101285 | if( nKey ) db->nextPagesize = 0; |
| 101286 | } |
| 101287 | #endif |
| 101288 | |
| 101289 | rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); |
| 101290 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 101291 | |
| 101292 | /* Begin a transaction and take an exclusive lock on the main database |
| 101293 | ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, |
| 101294 | ** to ensure that we do not try to change the page-size on a WAL database. |
| 101295 | */ |
| 101296 | rc = execSql(db, pzErrMsg, "BEGIN;"); |
| 101297 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 101298 | rc = sqlite3BtreeBeginTrans(pMain, 2); |
| 101299 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 101300 | |
| 101301 | /* Do not attempt to change the page size for a WAL database */ |
| 101302 | if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain)) |
| 101303 | ==PAGER_JOURNALMODE_WAL ){ |
| 101304 | db->nextPagesize = 0; |
| @@ -101215,24 +101309,16 @@ | |
| 101309 | || NEVER(db->mallocFailed) |
| 101310 | ){ |
| 101311 | rc = SQLITE_NOMEM; |
| 101312 | goto end_of_vacuum; |
| 101313 | } |
| 101314 | |
| 101315 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 101316 | sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : |
| 101317 | sqlite3BtreeGetAutoVacuum(pMain)); |
| 101318 | #endif |
| 101319 | |
| 101320 | /* Query the schema of the main database. Create a mirror schema |
| 101321 | ** in the temporary database. |
| 101322 | */ |
| 101323 | rc = execExecSql(db, pzErrMsg, |
| 101324 | "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " |
| @@ -105543,11 +105629,13 @@ | |
| 105629 | } |
| 105630 | |
| 105631 | /* If there is a DISTINCT qualifier and this index will scan rows in |
| 105632 | ** order of the DISTINCT expressions, clear bDist and set the appropriate |
| 105633 | ** flags in wsFlags. */ |
| 105634 | if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) |
| 105635 | && (wsFlags & WHERE_COLUMN_IN)==0 |
| 105636 | ){ |
| 105637 | bDist = 0; |
| 105638 | wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT; |
| 105639 | } |
| 105640 | |
| 105641 | /* If currently calculating the cost of using an index (not the IPK |
| @@ -106240,12 +106328,11 @@ | |
| 106328 | */ |
| 106329 | static Bitmask codeOneLoopStart( |
| 106330 | WhereInfo *pWInfo, /* Complete information about the WHERE clause */ |
| 106331 | int iLevel, /* Which level of pWInfo->a[] should be coded */ |
| 106332 | u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ |
| 106333 | Bitmask notReady /* Which tables are currently available */ |
| 106334 | ){ |
| 106335 | int j, k; /* Loop counters */ |
| 106336 | int iCur; /* The VDBE cursor for the table */ |
| 106337 | int addrNxt; /* Where to jump to continue with the next IN case */ |
| 106338 | int omitTable; /* True if we use the index only */ |
| @@ -106780,14 +106867,29 @@ | |
| 106867 | |
| 106868 | /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y |
| 106869 | ** Then for every term xN, evaluate as the subexpression: xN AND z |
| 106870 | ** That way, terms in y that are factored into the disjunction will |
| 106871 | ** be picked up by the recursive calls to sqlite3WhereBegin() below. |
| 106872 | ** |
| 106873 | ** Actually, each subexpression is converted to "xN AND w" where w is |
| 106874 | ** the "interesting" terms of z - terms that did not originate in the |
| 106875 | ** ON or USING clause of a LEFT JOIN, and terms that are usable as |
| 106876 | ** indices. |
| 106877 | */ |
| 106878 | if( pWC->nTerm>1 ){ |
| 106879 | int iTerm; |
| 106880 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 106881 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 106882 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 106883 | if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue; |
| 106884 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 106885 | pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); |
| 106886 | pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr); |
| 106887 | } |
| 106888 | if( pAndExpr ){ |
| 106889 | pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); |
| 106890 | } |
| 106891 | } |
| 106892 | |
| 106893 | for(ii=0; ii<pOrWc->nTerm; ii++){ |
| 106894 | WhereTerm *pOrTerm = &pOrWc->a[ii]; |
| 106895 | if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){ |
| @@ -106825,11 +106927,14 @@ | |
| 106927 | /* Finish the loop through table entries that match term pOrTerm. */ |
| 106928 | sqlite3WhereEnd(pSubWInfo); |
| 106929 | } |
| 106930 | } |
| 106931 | } |
| 106932 | if( pAndExpr ){ |
| 106933 | pAndExpr->pLeft = 0; |
| 106934 | sqlite3ExprDelete(pParse->db, pAndExpr); |
| 106935 | } |
| 106936 | sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); |
| 106937 | sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); |
| 106938 | sqlite3VdbeResolveLabel(v, iLoopBody); |
| 106939 | |
| 106940 | if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab); |
| @@ -107481,11 +107586,11 @@ | |
| 107586 | */ |
| 107587 | notReady = ~(Bitmask)0; |
| 107588 | for(i=0; i<nTabList; i++){ |
| 107589 | pLevel = &pWInfo->a[i]; |
| 107590 | explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags); |
| 107591 | notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady); |
| 107592 | pWInfo->iContinue = pLevel->addrCont; |
| 107593 | } |
| 107594 | |
| 107595 | #ifdef SQLITE_TEST /* For testing and debugging use only */ |
| 107596 | /* Record in the query plan information about the current table |
| @@ -113174,23 +113279,27 @@ | |
| 113279 | sqlite3_free(db); |
| 113280 | return SQLITE_OK; |
| 113281 | } |
| 113282 | |
| 113283 | /* |
| 113284 | ** Rollback all database files. If tripCode is not SQLITE_OK, then |
| 113285 | ** any open cursors are invalidated ("tripped" - as in "tripping a circuit |
| 113286 | ** breaker") and made to return tripCode if there are any further |
| 113287 | ** attempts to use that cursor. |
| 113288 | */ |
| 113289 | SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ |
| 113290 | int i; |
| 113291 | int inTrans = 0; |
| 113292 | assert( sqlite3_mutex_held(db->mutex) ); |
| 113293 | sqlite3BeginBenignMalloc(); |
| 113294 | for(i=0; i<db->nDb; i++){ |
| 113295 | Btree *p = db->aDb[i].pBt; |
| 113296 | if( p ){ |
| 113297 | if( sqlite3BtreeIsInTrans(p) ){ |
| 113298 | inTrans = 1; |
| 113299 | } |
| 113300 | sqlite3BtreeRollback(p, tripCode); |
| 113301 | db->aDb[i].inTrans = 0; |
| 113302 | } |
| 113303 | } |
| 113304 | sqlite3VtabRollback(db); |
| 113305 | sqlite3EndBenignMalloc(); |
| @@ -113241,16 +113350,25 @@ | |
| 113350 | /* SQLITE_AUTH */ "authorization denied", |
| 113351 | /* SQLITE_FORMAT */ "auxiliary database format error", |
| 113352 | /* SQLITE_RANGE */ "bind or column index out of range", |
| 113353 | /* SQLITE_NOTADB */ "file is encrypted or is not a database", |
| 113354 | }; |
| 113355 | const char *zErr = "unknown error"; |
| 113356 | switch( rc ){ |
| 113357 | case SQLITE_ABORT_ROLLBACK: { |
| 113358 | zErr = "abort due to ROLLBACK"; |
| 113359 | break; |
| 113360 | } |
| 113361 | default: { |
| 113362 | rc &= 0xff; |
| 113363 | if( ALWAYS(rc>=0) && rc<ArraySize(aMsg) && aMsg[rc]!=0 ){ |
| 113364 | zErr = aMsg[rc]; |
| 113365 | } |
| 113366 | break; |
| 113367 | } |
| 113368 | } |
| 113369 | return zErr; |
| 113370 | } |
| 113371 | |
| 113372 | /* |
| 113373 | ** This routine implements a busy callback that sleeps and tries |
| 113374 | ** again until a timeout value is reached. The timeout value is |
| @@ -113624,13 +113742,12 @@ | |
| 113742 | sqlite3_mutex_leave(db->mutex); |
| 113743 | return pOld; |
| 113744 | } |
| 113745 | #endif /* SQLITE_OMIT_TRACE */ |
| 113746 | |
| 113747 | /* |
| 113748 | ** Register a function to be invoked when a transaction commits. |
| 113749 | ** If the invoked function returns non-zero, then the commit becomes a |
| 113750 | ** rollback. |
| 113751 | */ |
| 113752 | SQLITE_API void *sqlite3_commit_hook( |
| 113753 | sqlite3 *db, /* Attach the hook to this database */ |
| @@ -115017,39 +115134,31 @@ | |
| 115134 | /* |
| 115135 | ** Invoke the xFileControl method on a particular database. |
| 115136 | */ |
| 115137 | SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ |
| 115138 | int rc = SQLITE_ERROR; |
| 115139 | Btree *pBtree; |
| 115140 | |
| 115141 | sqlite3_mutex_enter(db->mutex); |
| 115142 | pBtree = sqlite3DbNameToBtree(db, zDbName); |
| 115143 | if( pBtree ){ |
| 115144 | Pager *pPager; |
| 115145 | sqlite3_file *fd; |
| 115146 | sqlite3BtreeEnter(pBtree); |
| 115147 | pPager = sqlite3BtreePager(pBtree); |
| 115148 | assert( pPager!=0 ); |
| 115149 | fd = sqlite3PagerFile(pPager); |
| 115150 | assert( fd!=0 ); |
| 115151 | if( op==SQLITE_FCNTL_FILE_POINTER ){ |
| 115152 | *(sqlite3_file**)pArg = fd; |
| 115153 | rc = SQLITE_OK; |
| 115154 | }else if( fd->pMethods ){ |
| 115155 | rc = sqlite3OsFileControl(fd, op, pArg); |
| 115156 | }else{ |
| 115157 | rc = SQLITE_NOTFOUND; |
| 115158 | } |
| 115159 | sqlite3BtreeLeave(pBtree); |
| 115160 | } |
| 115161 | sqlite3_mutex_leave(db->mutex); |
| 115162 | return rc; |
| 115163 | } |
| 115164 | |
| @@ -115339,23 +115448,42 @@ | |
| 115448 | if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){ |
| 115449 | bDflt = v; |
| 115450 | } |
| 115451 | return bDflt; |
| 115452 | } |
| 115453 | |
| 115454 | /* |
| 115455 | ** Return the Btree pointer identified by zDbName. Return NULL if not found. |
| 115456 | */ |
| 115457 | SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ |
| 115458 | int i; |
| 115459 | for(i=0; i<db->nDb; i++){ |
| 115460 | if( db->aDb[i].pBt |
| 115461 | && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0) |
| 115462 | ){ |
| 115463 | return db->aDb[i].pBt; |
| 115464 | } |
| 115465 | } |
| 115466 | return 0; |
| 115467 | } |
| 115468 | |
| 115469 | /* |
| 115470 | ** Return the filename of the database associated with a database |
| 115471 | ** connection. |
| 115472 | */ |
| 115473 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
| 115474 | Btree *pBt = sqlite3DbNameToBtree(db, zDbName); |
| 115475 | return pBt ? sqlite3BtreeGetFilename(pBt) : 0; |
| 115476 | } |
| 115477 | |
| 115478 | /* |
| 115479 | ** Return 1 if database is read-only or 0 if read/write. Return -1 if |
| 115480 | ** no such database exists. |
| 115481 | */ |
| 115482 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ |
| 115483 | Btree *pBt = sqlite3DbNameToBtree(db, zDbName); |
| 115484 | return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1; |
| 115485 | } |
| 115486 | |
| 115487 | /************** End of main.c ************************************************/ |
| 115488 | /************** Begin file notify.c ******************************************/ |
| 115489 | /* |
| @@ -115977,14 +116105,10 @@ | |
| 116105 | ** we simply write the new doclist. Segment merges overwrite older |
| 116106 | ** data for a particular docid with newer data, so deletes or updates |
| 116107 | ** will eventually overtake the earlier data and knock it out. The |
| 116108 | ** query logic likewise merges doclists so that newer data knocks out |
| 116109 | ** older data. |
| 116110 | */ |
| 116111 | |
| 116112 | /************** Include fts3Int.h in the middle of fts3.c ********************/ |
| 116113 | /************** Begin file fts3Int.h *****************************************/ |
| 116114 | /* |
| @@ -116076,11 +116200,11 @@ | |
| 116200 | typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; |
| 116201 | |
| 116202 | struct sqlite3_tokenizer_module { |
| 116203 | |
| 116204 | /* |
| 116205 | ** Structure version. Should always be set to 0 or 1. |
| 116206 | */ |
| 116207 | int iVersion; |
| 116208 | |
| 116209 | /* |
| 116210 | ** Create a new tokenizer. The values in the argv[] array are the |
| @@ -116157,10 +116281,19 @@ | |
| 116281 | const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ |
| 116282 | int *piStartOffset, /* OUT: Byte offset of token in input buffer */ |
| 116283 | int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ |
| 116284 | int *piPosition /* OUT: Number of tokens returned before this one */ |
| 116285 | ); |
| 116286 | |
| 116287 | /*********************************************************************** |
| 116288 | ** Methods below this point are only available if iVersion>=1. |
| 116289 | */ |
| 116290 | |
| 116291 | /* |
| 116292 | ** Configure the language id of a tokenizer cursor. |
| 116293 | */ |
| 116294 | int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid); |
| 116295 | }; |
| 116296 | |
| 116297 | struct sqlite3_tokenizer { |
| 116298 | const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ |
| 116299 | /* Tokenizer implementations will typically add additional fields */ |
| @@ -116448,15 +116581,16 @@ | |
| 116581 | const char *zName; /* virtual table name */ |
| 116582 | int nColumn; /* number of named columns in virtual table */ |
| 116583 | char **azColumn; /* column names. malloced */ |
| 116584 | sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ |
| 116585 | char *zContentTbl; /* content=xxx option, or NULL */ |
| 116586 | char *zLanguageid; /* languageid=xxx option, or NULL */ |
| 116587 | |
| 116588 | /* Precompiled statements used by the implementation. Each of these |
| 116589 | ** statements is run and reset within a single virtual table API call. |
| 116590 | */ |
| 116591 | sqlite3_stmt *aStmt[28]; |
| 116592 | |
| 116593 | char *zReadExprlist; |
| 116594 | char *zWriteExprlist; |
| 116595 | |
| 116596 | int nNodeSize; /* Soft limit for node size */ |
| @@ -116467,16 +116601,16 @@ | |
| 116601 | char *zSegmentsTbl; /* Name of %_segments table */ |
| 116602 | sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ |
| 116603 | |
| 116604 | /* TODO: Fix the first paragraph of this comment. |
| 116605 | ** |
| 116606 | ** The following array of hash tables is used to buffer pending index |
| 116607 | ** updates during transactions. Variable nPendingData estimates the memory |
| 116608 | ** size of the pending data, including hash table overhead, not including |
| 116609 | ** malloc overhead. When nPendingData exceeds nMaxPendingData, the buffer |
| 116610 | ** is flushed automatically. Variable iPrevDocid is the docid of the most |
| 116611 | ** recently inserted record. |
| 116612 | ** |
| 116613 | ** A single FTS4 table may have multiple full-text indexes. For each index |
| 116614 | ** there is an entry in the aIndex[] array. Index 0 is an index of all the |
| 116615 | ** terms that appear in the document set. Each subsequent index in aIndex[] |
| 116616 | ** is an index of prefixes of a specific length. |
| @@ -116487,16 +116621,17 @@ | |
| 116621 | Fts3Hash hPending; /* Pending terms table for this index */ |
| 116622 | } *aIndex; |
| 116623 | int nMaxPendingData; /* Max pending data before flush to disk */ |
| 116624 | int nPendingData; /* Current bytes of pending data */ |
| 116625 | sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ |
| 116626 | int iPrevLangid; /* Langid of recently inserted document */ |
| 116627 | |
| 116628 | #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) |
| 116629 | /* State variables used for validating that the transaction control |
| 116630 | ** methods of the virtual table are called at appropriate times. These |
| 116631 | ** values do not contribute to FTS functionality; they are used for |
| 116632 | ** verifying the operation of the SQLite core. |
| 116633 | */ |
| 116634 | int inTransaction; /* True after xBegin but before xCommit/xRollback */ |
| 116635 | int mxSavepoint; /* Largest valid xSavepoint integer */ |
| 116636 | #endif |
| 116637 | }; |
| @@ -116511,10 +116646,11 @@ | |
| 116646 | i16 eSearch; /* Search strategy (see below) */ |
| 116647 | u8 isEof; /* True if at End Of Results */ |
| 116648 | u8 isRequireSeek; /* True if must seek pStmt to %_content row */ |
| 116649 | sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ |
| 116650 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 116651 | int iLangid; /* Language being queried for */ |
| 116652 | int nPhrase; /* Number of matchable phrases in query */ |
| 116653 | Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ |
| 116654 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 116655 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 116656 | char *aDoclist; /* List of docids for full-text queries */ |
| @@ -116662,11 +116798,11 @@ | |
| 116798 | SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64, |
| 116799 | sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); |
| 116800 | SQLITE_PRIVATE int sqlite3Fts3SegReaderPending( |
| 116801 | Fts3Table*,int,const char*,int,int,Fts3SegReader**); |
| 116802 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *); |
| 116803 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **); |
| 116804 | SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); |
| 116805 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*); |
| 116806 | |
| 116807 | SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); |
| 116808 | SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); |
| @@ -116683,12 +116819,12 @@ | |
| 116819 | |
| 116820 | SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*); |
| 116821 | SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *); |
| 116822 | SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *); |
| 116823 | |
| 116824 | SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *, |
| 116825 | int, int, int, const char *, int, int, int, Fts3MultiSegReader *); |
| 116826 | |
| 116827 | /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ |
| 116828 | #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 |
| 116829 | #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 |
| 116830 | #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 |
| @@ -116751,18 +116887,22 @@ | |
| 116887 | const char *, const char *, int, int |
| 116888 | ); |
| 116889 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); |
| 116890 | |
| 116891 | /* fts3_expr.c */ |
| 116892 | SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, |
| 116893 | char **, int, int, int, const char *, int, Fts3Expr ** |
| 116894 | ); |
| 116895 | SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); |
| 116896 | #ifdef SQLITE_TEST |
| 116897 | SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); |
| 116898 | SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); |
| 116899 | #endif |
| 116900 | |
| 116901 | SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int, |
| 116902 | sqlite3_tokenizer_cursor ** |
| 116903 | ); |
| 116904 | |
| 116905 | /* fts3_aux.c */ |
| 116906 | SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db); |
| 116907 | |
| 116908 | SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *); |
| @@ -116954,10 +117094,11 @@ | |
| 117094 | } |
| 117095 | sqlite3_free(p->zSegmentsTbl); |
| 117096 | sqlite3_free(p->zReadExprlist); |
| 117097 | sqlite3_free(p->zWriteExprlist); |
| 117098 | sqlite3_free(p->zContentTbl); |
| 117099 | sqlite3_free(p->zLanguageid); |
| 117100 | |
| 117101 | /* Invoke the tokenizer destructor to free the tokenizer. */ |
| 117102 | p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
| 117103 | |
| 117104 | sqlite3_free(p); |
| @@ -117030,11 +117171,13 @@ | |
| 117171 | if( *pRc==SQLITE_OK ){ |
| 117172 | int i; /* Iterator variable */ |
| 117173 | int rc; /* Return code */ |
| 117174 | char *zSql; /* SQL statement passed to declare_vtab() */ |
| 117175 | char *zCols; /* List of user defined columns */ |
| 117176 | const char *zLanguageid; |
| 117177 | |
| 117178 | zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid"); |
| 117179 | sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); |
| 117180 | |
| 117181 | /* Create a list of user columns for the virtual table */ |
| 117182 | zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]); |
| 117183 | for(i=1; zCols && i<p->nColumn; i++){ |
| @@ -117041,11 +117184,12 @@ | |
| 117184 | zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]); |
| 117185 | } |
| 117186 | |
| 117187 | /* Create the whole "CREATE TABLE" statement to pass to SQLite */ |
| 117188 | zSql = sqlite3_mprintf( |
| 117189 | "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)", |
| 117190 | zCols, p->zName, zLanguageid |
| 117191 | ); |
| 117192 | if( !zCols || !zSql ){ |
| 117193 | rc = SQLITE_NOMEM; |
| 117194 | }else{ |
| 117195 | rc = sqlite3_declare_vtab(p->db, zSql); |
| @@ -117070,18 +117214,22 @@ | |
| 117214 | int rc = SQLITE_OK; /* Return code */ |
| 117215 | int i; /* Iterator variable */ |
| 117216 | sqlite3 *db = p->db; /* The database connection */ |
| 117217 | |
| 117218 | if( p->zContentTbl==0 ){ |
| 117219 | const char *zLanguageid = p->zLanguageid; |
| 117220 | char *zContentCols; /* Columns of %_content table */ |
| 117221 | |
| 117222 | /* Create a list of user columns for the content table */ |
| 117223 | zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); |
| 117224 | for(i=0; zContentCols && i<p->nColumn; i++){ |
| 117225 | char *z = p->azColumn[i]; |
| 117226 | zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); |
| 117227 | } |
| 117228 | if( zLanguageid && zContentCols ){ |
| 117229 | zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid); |
| 117230 | } |
| 117231 | if( zContentCols==0 ) rc = SQLITE_NOMEM; |
| 117232 | |
| 117233 | /* Create the content table */ |
| 117234 | fts3DbExec(&rc, db, |
| 117235 | "CREATE TABLE %Q.'%q_content'(%s)", |
| @@ -117277,18 +117425,24 @@ | |
| 117425 | } |
| 117426 | fts3Appendf(pRc, &zRet, "docid"); |
| 117427 | for(i=0; i<p->nColumn; i++){ |
| 117428 | fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]); |
| 117429 | } |
| 117430 | if( p->zLanguageid ){ |
| 117431 | fts3Appendf(pRc, &zRet, ", x.%Q", "langid"); |
| 117432 | } |
| 117433 | sqlite3_free(zFree); |
| 117434 | }else{ |
| 117435 | fts3Appendf(pRc, &zRet, "rowid"); |
| 117436 | for(i=0; i<p->nColumn; i++){ |
| 117437 | fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]); |
| 117438 | } |
| 117439 | if( p->zLanguageid ){ |
| 117440 | fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid); |
| 117441 | } |
| 117442 | } |
| 117443 | fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x", |
| 117444 | p->zDb, |
| 117445 | (p->zContentTbl ? p->zContentTbl : p->zName), |
| 117446 | (p->zContentTbl ? "" : "_content") |
| 117447 | ); |
| 117448 | return zRet; |
| @@ -117327,10 +117481,13 @@ | |
| 117481 | } |
| 117482 | fts3Appendf(pRc, &zRet, "?"); |
| 117483 | for(i=0; i<p->nColumn; i++){ |
| 117484 | fts3Appendf(pRc, &zRet, ",%s(?)", zFunction); |
| 117485 | } |
| 117486 | if( p->zLanguageid ){ |
| 117487 | fts3Appendf(pRc, &zRet, ", ?"); |
| 117488 | } |
| 117489 | sqlite3_free(zFree); |
| 117490 | return zRet; |
| 117491 | } |
| 117492 | |
| 117493 | /* |
| @@ -117542,10 +117699,11 @@ | |
| 117699 | int bDescIdx = 0; /* True to store descending indexes */ |
| 117700 | char *zPrefix = 0; /* Prefix parameter value (or NULL) */ |
| 117701 | char *zCompress = 0; /* compress=? parameter (or NULL) */ |
| 117702 | char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ |
| 117703 | char *zContent = 0; /* content=? parameter (or NULL) */ |
| 117704 | char *zLanguageid = 0; /* languageid=? parameter (or NULL) */ |
| 117705 | |
| 117706 | assert( strlen(argv[0])==4 ); |
| 117707 | assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4) |
| 117708 | || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4) |
| 117709 | ); |
| @@ -117591,11 +117749,12 @@ | |
| 117749 | { "matchinfo", 9 }, /* 0 -> MATCHINFO */ |
| 117750 | { "prefix", 6 }, /* 1 -> PREFIX */ |
| 117751 | { "compress", 8 }, /* 2 -> COMPRESS */ |
| 117752 | { "uncompress", 10 }, /* 3 -> UNCOMPRESS */ |
| 117753 | { "order", 5 }, /* 4 -> ORDER */ |
| 117754 | { "content", 7 }, /* 5 -> CONTENT */ |
| 117755 | { "languageid", 10 } /* 6 -> LANGUAGEID */ |
| 117756 | }; |
| 117757 | |
| 117758 | int iOpt; |
| 117759 | if( !zVal ){ |
| 117760 | rc = SQLITE_NOMEM; |
| @@ -117645,16 +117804,22 @@ | |
| 117804 | rc = SQLITE_ERROR; |
| 117805 | } |
| 117806 | bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); |
| 117807 | break; |
| 117808 | |
| 117809 | case 5: /* CONTENT */ |
| 117810 | sqlite3_free(zContent); |
| 117811 | zContent = zVal; |
| 117812 | zVal = 0; |
| 117813 | break; |
| 117814 | |
| 117815 | case 6: /* LANGUAGEID */ |
| 117816 | assert( iOpt==6 ); |
| 117817 | sqlite3_free(zLanguageid); |
| 117818 | zLanguageid = zVal; |
| 117819 | zVal = 0; |
| 117820 | break; |
| 117821 | } |
| 117822 | } |
| 117823 | sqlite3_free(zVal); |
| 117824 | } |
| 117825 | } |
| @@ -117680,12 +117845,24 @@ | |
| 117845 | zUncompress = 0; |
| 117846 | if( nCol==0 ){ |
| 117847 | sqlite3_free((void*)aCol); |
| 117848 | aCol = 0; |
| 117849 | rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); |
| 117850 | |
| 117851 | /* If a languageid= option was specified, remove the language id |
| 117852 | ** column from the aCol[] array. */ |
| 117853 | if( rc==SQLITE_OK && zLanguageid ){ |
| 117854 | int j; |
| 117855 | for(j=0; j<nCol; j++){ |
| 117856 | if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){ |
| 117857 | memmove(&aCol[j], &aCol[j+1], (nCol-j) * sizeof(aCol[0])); |
| 117858 | nCol--; |
| 117859 | break; |
| 117860 | } |
| 117861 | } |
| 117862 | } |
| 117863 | } |
| 117864 | } |
| 117865 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 117866 | |
| 117867 | if( nCol==0 ){ |
| 117868 | assert( nString==0 ); |
| @@ -117728,11 +117905,13 @@ | |
| 117905 | p->nMaxPendingData = FTS3_MAX_PENDING_DATA; |
| 117906 | p->bHasDocsize = (isFts4 && bNoDocsize==0); |
| 117907 | p->bHasStat = isFts4; |
| 117908 | p->bDescIdx = bDescIdx; |
| 117909 | p->zContentTbl = zContent; |
| 117910 | p->zLanguageid = zLanguageid; |
| 117911 | zContent = 0; |
| 117912 | zLanguageid = 0; |
| 117913 | TESTONLY( p->inTransaction = -1 ); |
| 117914 | TESTONLY( p->mxSavepoint = -1 ); |
| 117915 | |
| 117916 | p->aIndex = (struct Fts3Index *)&p->azColumn[nCol]; |
| 117917 | memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex); |
| @@ -117791,10 +117970,11 @@ | |
| 117970 | sqlite3_free(zPrefix); |
| 117971 | sqlite3_free(aIndex); |
| 117972 | sqlite3_free(zCompress); |
| 117973 | sqlite3_free(zUncompress); |
| 117974 | sqlite3_free(zContent); |
| 117975 | sqlite3_free(zLanguageid); |
| 117976 | sqlite3_free((void *)aCol); |
| 117977 | if( rc!=SQLITE_OK ){ |
| 117978 | if( p ){ |
| 117979 | fts3DisconnectMethod((sqlite3_vtab *)p); |
| 117980 | }else if( pTokenizer ){ |
| @@ -117842,10 +118022,11 @@ | |
| 118022 | */ |
| 118023 | static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ |
| 118024 | Fts3Table *p = (Fts3Table *)pVTab; |
| 118025 | int i; /* Iterator variable */ |
| 118026 | int iCons = -1; /* Index of constraint to use */ |
| 118027 | int iLangidCons = -1; /* Index of langid=x constraint, if present */ |
| 118028 | |
| 118029 | /* By default use a full table scan. This is an expensive option, |
| 118030 | ** so search through the constraints to see if a more efficient |
| 118031 | ** strategy is possible. |
| 118032 | */ |
| @@ -117854,11 +118035,12 @@ | |
| 118035 | for(i=0; i<pInfo->nConstraint; i++){ |
| 118036 | struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i]; |
| 118037 | if( pCons->usable==0 ) continue; |
| 118038 | |
| 118039 | /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */ |
| 118040 | if( iCons<0 |
| 118041 | && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ |
| 118042 | && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 ) |
| 118043 | ){ |
| 118044 | pInfo->idxNum = FTS3_DOCID_SEARCH; |
| 118045 | pInfo->estimatedCost = 1.0; |
| 118046 | iCons = i; |
| @@ -117877,18 +118059,27 @@ | |
| 118059 | && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn |
| 118060 | ){ |
| 118061 | pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn; |
| 118062 | pInfo->estimatedCost = 2.0; |
| 118063 | iCons = i; |
| 118064 | } |
| 118065 | |
| 118066 | /* Equality constraint on the langid column */ |
| 118067 | if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ |
| 118068 | && pCons->iColumn==p->nColumn + 2 |
| 118069 | ){ |
| 118070 | iLangidCons = i; |
| 118071 | } |
| 118072 | } |
| 118073 | |
| 118074 | if( iCons>=0 ){ |
| 118075 | pInfo->aConstraintUsage[iCons].argvIndex = 1; |
| 118076 | pInfo->aConstraintUsage[iCons].omit = 1; |
| 118077 | } |
| 118078 | if( iLangidCons>=0 ){ |
| 118079 | pInfo->aConstraintUsage[iLangidCons].argvIndex = 2; |
| 118080 | } |
| 118081 | |
| 118082 | /* Regardless of the strategy selected, FTS can deliver rows in rowid (or |
| 118083 | ** docid) order. Both ascending and descending are possible. |
| 118084 | */ |
| 118085 | if( pInfo->nOrderBy==1 ){ |
| @@ -119034,10 +119225,11 @@ | |
| 119225 | ** This function returns SQLITE_OK if successful, or an SQLite error code |
| 119226 | ** otherwise. |
| 119227 | */ |
| 119228 | static int fts3SegReaderCursor( |
| 119229 | Fts3Table *p, /* FTS3 table handle */ |
| 119230 | int iLangid, /* Language id */ |
| 119231 | int iIndex, /* Index to search (from 0 to p->nIndex-1) */ |
| 119232 | int iLevel, /* Level of segments to scan */ |
| 119233 | const char *zTerm, /* Term to query for */ |
| 119234 | int nTerm, /* Size of zTerm in bytes */ |
| 119235 | int isPrefix, /* True for a prefix search */ |
| @@ -119062,11 +119254,11 @@ | |
| 119254 | } |
| 119255 | } |
| 119256 | |
| 119257 | if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
| 119258 | if( rc==SQLITE_OK ){ |
| 119259 | rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); |
| 119260 | } |
| 119261 | |
| 119262 | while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ |
| 119263 | Fts3SegReader *pSeg = 0; |
| 119264 | |
| @@ -119107,10 +119299,11 @@ | |
| 119299 | ** Set up a cursor object for iterating through a full-text index or a |
| 119300 | ** single level therein. |
| 119301 | */ |
| 119302 | SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( |
| 119303 | Fts3Table *p, /* FTS3 table handle */ |
| 119304 | int iLangid, |
| 119305 | int iIndex, /* Index to search (from 0 to p->nIndex-1) */ |
| 119306 | int iLevel, /* Level of segments to scan */ |
| 119307 | const char *zTerm, /* Term to query for */ |
| 119308 | int nTerm, /* Size of zTerm in bytes */ |
| 119309 | int isPrefix, /* True for a prefix search */ |
| @@ -119131,11 +119324,11 @@ | |
| 119324 | assert( isScan==0 || p->aIndex==0 ); |
| 119325 | |
| 119326 | memset(pCsr, 0, sizeof(Fts3MultiSegReader)); |
| 119327 | |
| 119328 | return fts3SegReaderCursor( |
| 119329 | p, iLangid, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr |
| 119330 | ); |
| 119331 | } |
| 119332 | |
| 119333 | /* |
| 119334 | ** In addition to its current configuration, have the Fts3MultiSegReader |
| @@ -119143,15 +119336,18 @@ | |
| 119336 | ** |
| 119337 | ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. |
| 119338 | */ |
| 119339 | static int fts3SegReaderCursorAddZero( |
| 119340 | Fts3Table *p, /* FTS virtual table handle */ |
| 119341 | int iLangid, |
| 119342 | const char *zTerm, /* Term to scan doclist of */ |
| 119343 | int nTerm, /* Number of bytes in zTerm */ |
| 119344 | Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */ |
| 119345 | ){ |
| 119346 | return fts3SegReaderCursor(p, |
| 119347 | iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr |
| 119348 | ); |
| 119349 | } |
| 119350 | |
| 119351 | /* |
| 119352 | ** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or, |
| 119353 | ** if isPrefix is true, to scan the doclist for all terms for which |
| @@ -119183,32 +119379,35 @@ | |
| 119379 | |
| 119380 | if( isPrefix ){ |
| 119381 | for(i=1; bFound==0 && i<p->nIndex; i++){ |
| 119382 | if( p->aIndex[i].nPrefix==nTerm ){ |
| 119383 | bFound = 1; |
| 119384 | rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, |
| 119385 | i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr |
| 119386 | ); |
| 119387 | pSegcsr->bLookup = 1; |
| 119388 | } |
| 119389 | } |
| 119390 | |
| 119391 | for(i=1; bFound==0 && i<p->nIndex; i++){ |
| 119392 | if( p->aIndex[i].nPrefix==nTerm+1 ){ |
| 119393 | bFound = 1; |
| 119394 | rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, |
| 119395 | i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr |
| 119396 | ); |
| 119397 | if( rc==SQLITE_OK ){ |
| 119398 | rc = fts3SegReaderCursorAddZero( |
| 119399 | p, pCsr->iLangid, zTerm, nTerm, pSegcsr |
| 119400 | ); |
| 119401 | } |
| 119402 | } |
| 119403 | } |
| 119404 | } |
| 119405 | |
| 119406 | if( bFound==0 ){ |
| 119407 | rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, |
| 119408 | 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr |
| 119409 | ); |
| 119410 | pSegcsr->bLookup = !isPrefix; |
| 119411 | } |
| 119412 | } |
| 119413 | |
| @@ -119359,11 +119558,11 @@ | |
| 119558 | |
| 119559 | UNUSED_PARAMETER(idxStr); |
| 119560 | UNUSED_PARAMETER(nVal); |
| 119561 | |
| 119562 | assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); |
| 119563 | assert( nVal==0 || nVal==1 || nVal==2 ); |
| 119564 | assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) ); |
| 119565 | assert( p->pSegments==0 ); |
| 119566 | |
| 119567 | /* In case the cursor has been used before, clear it now. */ |
| 119568 | sqlite3_finalize(pCsr->pStmt); |
| @@ -119384,12 +119583,15 @@ | |
| 119583 | |
| 119584 | if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 119585 | return SQLITE_NOMEM; |
| 119586 | } |
| 119587 | |
| 119588 | pCsr->iLangid = 0; |
| 119589 | if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]); |
| 119590 | |
| 119591 | rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, |
| 119592 | p->azColumn, p->bHasStat, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr |
| 119593 | ); |
| 119594 | if( rc!=SQLITE_OK ){ |
| 119595 | if( rc==SQLITE_ERROR ){ |
| 119596 | static const char *zErr = "malformed MATCH expression: [%s]"; |
| 119597 | p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery); |
| @@ -119456,37 +119658,56 @@ | |
| 119658 | } |
| 119659 | |
| 119660 | /* |
| 119661 | ** This is the xColumn method, called by SQLite to request a value from |
| 119662 | ** the row that the supplied cursor currently points to. |
| 119663 | ** |
| 119664 | ** If: |
| 119665 | ** |
| 119666 | ** (iCol < p->nColumn) -> The value of the iCol'th user column. |
| 119667 | ** (iCol == p->nColumn) -> Magic column with the same name as the table. |
| 119668 | ** (iCol == p->nColumn+1) -> Docid column |
| 119669 | ** (iCol == p->nColumn+2) -> Langid column |
| 119670 | */ |
| 119671 | static int fts3ColumnMethod( |
| 119672 | sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ |
| 119673 | sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ |
| 119674 | int iCol /* Index of column to read value from */ |
| 119675 | ){ |
| 119676 | int rc = SQLITE_OK; /* Return Code */ |
| 119677 | Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; |
| 119678 | Fts3Table *p = (Fts3Table *)pCursor->pVtab; |
| 119679 | |
| 119680 | /* The column value supplied by SQLite must be in range. */ |
| 119681 | assert( iCol>=0 && iCol<=p->nColumn+2 ); |
| 119682 | |
| 119683 | if( iCol==p->nColumn+1 ){ |
| 119684 | /* This call is a request for the "docid" column. Since "docid" is an |
| 119685 | ** alias for "rowid", use the xRowid() method to obtain the value. |
| 119686 | */ |
| 119687 | sqlite3_result_int64(pCtx, pCsr->iPrevId); |
| 119688 | }else if( iCol==p->nColumn ){ |
| 119689 | /* The extra column whose name is the same as the table. |
| 119690 | ** Return a blob which is a pointer to the cursor. */ |
| 119691 | sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); |
| 119692 | }else if( iCol==p->nColumn+2 && pCsr->pExpr ){ |
| 119693 | sqlite3_result_int64(pCtx, pCsr->iLangid); |
| 119694 | }else{ |
| 119695 | /* The requested column is either a user column (one that contains |
| 119696 | ** indexed data), or the language-id column. */ |
| 119697 | rc = fts3CursorSeek(0, pCsr); |
| 119698 | |
| 119699 | if( rc==SQLITE_OK ){ |
| 119700 | if( iCol==p->nColumn+2 ){ |
| 119701 | int iLangid = 0; |
| 119702 | if( p->zLanguageid ){ |
| 119703 | iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1); |
| 119704 | } |
| 119705 | sqlite3_result_int(pCtx, iLangid); |
| 119706 | }else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){ |
| 119707 | sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); |
| 119708 | } |
| 119709 | } |
| 119710 | } |
| 119711 | |
| 119712 | assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
| 119713 | return rc; |
| @@ -121958,11 +122179,11 @@ | |
| 122179 | pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx])); |
| 122180 | pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]); |
| 122181 | if( pCsr->zStop==0 ) return SQLITE_NOMEM; |
| 122182 | } |
| 122183 | |
| 122184 | rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL, |
| 122185 | pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr |
| 122186 | ); |
| 122187 | if( rc==SQLITE_OK ){ |
| 122188 | rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter); |
| 122189 | } |
| @@ -122150,10 +122371,11 @@ | |
| 122371 | ** zero. |
| 122372 | */ |
| 122373 | typedef struct ParseContext ParseContext; |
| 122374 | struct ParseContext { |
| 122375 | sqlite3_tokenizer *pTokenizer; /* Tokenizer module */ |
| 122376 | int iLangid; /* Language id used with tokenizer */ |
| 122377 | const char **azCol; /* Array of column names for fts3 table */ |
| 122378 | int bFts4; /* True to allow FTS4-only syntax */ |
| 122379 | int nCol; /* Number of entries in azCol[] */ |
| 122380 | int iDefaultCol; /* Default column to query */ |
| 122381 | int isNot; /* True if getNextNode() sees a unary - */ |
| @@ -122185,10 +122407,37 @@ | |
| 122407 | void *pRet = sqlite3_malloc(nByte); |
| 122408 | if( pRet ) memset(pRet, 0, nByte); |
| 122409 | return pRet; |
| 122410 | } |
| 122411 | |
| 122412 | SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer( |
| 122413 | sqlite3_tokenizer *pTokenizer, |
| 122414 | int iLangid, |
| 122415 | const char *z, |
| 122416 | int n, |
| 122417 | sqlite3_tokenizer_cursor **ppCsr |
| 122418 | ){ |
| 122419 | sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; |
| 122420 | sqlite3_tokenizer_cursor *pCsr = 0; |
| 122421 | int rc; |
| 122422 | |
| 122423 | rc = pModule->xOpen(pTokenizer, z, n, &pCsr); |
| 122424 | assert( rc==SQLITE_OK || pCsr==0 ); |
| 122425 | if( rc==SQLITE_OK ){ |
| 122426 | pCsr->pTokenizer = pTokenizer; |
| 122427 | if( pModule->iVersion>=1 ){ |
| 122428 | rc = pModule->xLanguageid(pCsr, iLangid); |
| 122429 | if( rc!=SQLITE_OK ){ |
| 122430 | pModule->xClose(pCsr); |
| 122431 | pCsr = 0; |
| 122432 | } |
| 122433 | } |
| 122434 | } |
| 122435 | *ppCsr = pCsr; |
| 122436 | return rc; |
| 122437 | } |
| 122438 | |
| 122439 | |
| 122440 | /* |
| 122441 | ** Extract the next token from buffer z (length n) using the tokenizer |
| 122442 | ** and other information (column names etc.) in pParse. Create an Fts3Expr |
| 122443 | ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this |
| @@ -122212,19 +122461,17 @@ | |
| 122461 | int rc; |
| 122462 | sqlite3_tokenizer_cursor *pCursor; |
| 122463 | Fts3Expr *pRet = 0; |
| 122464 | int nConsumed = 0; |
| 122465 | |
| 122466 | rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); |
| 122467 | if( rc==SQLITE_OK ){ |
| 122468 | const char *zToken; |
| 122469 | int nToken, iStart, iEnd, iPosition; |
| 122470 | int nByte; /* total space to allocate */ |
| 122471 | |
| 122472 | rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); |
| 122473 | if( rc==SQLITE_OK ){ |
| 122474 | nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; |
| 122475 | pRet = (Fts3Expr *)fts3MallocZero(nByte); |
| 122476 | if( !pRet ){ |
| 122477 | rc = SQLITE_NOMEM; |
| @@ -122326,14 +122573,14 @@ | |
| 122573 | ** |
| 122574 | ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below, |
| 122575 | ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase |
| 122576 | ** structures. |
| 122577 | */ |
| 122578 | rc = sqlite3Fts3OpenTokenizer( |
| 122579 | pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); |
| 122580 | if( rc==SQLITE_OK ){ |
| 122581 | int ii; |
| 122582 | for(ii=0; rc==SQLITE_OK; ii++){ |
| 122583 | const char *zByte; |
| 122584 | int nByte, iBegin, iEnd, iPos; |
| 122585 | rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos); |
| 122586 | if( rc==SQLITE_OK ){ |
| @@ -122803,10 +123050,11 @@ | |
| 123050 | ** specified as part of the query string), or -1 if tokens may by default |
| 123051 | ** match any table column. |
| 123052 | */ |
| 123053 | SQLITE_PRIVATE int sqlite3Fts3ExprParse( |
| 123054 | sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ |
| 123055 | int iLangid, /* Language id for tokenizer */ |
| 123056 | char **azCol, /* Array of column names for fts3 table */ |
| 123057 | int bFts4, /* True to allow FTS4-only syntax */ |
| 123058 | int nCol, /* Number of entries in azCol[] */ |
| 123059 | int iDefaultCol, /* Default column to query */ |
| 123060 | const char *z, int n, /* Text of MATCH query */ |
| @@ -122813,15 +123061,17 @@ | |
| 123061 | Fts3Expr **ppExpr /* OUT: Parsed query structure */ |
| 123062 | ){ |
| 123063 | int nParsed; |
| 123064 | int rc; |
| 123065 | ParseContext sParse; |
| 123066 | |
| 123067 | memset(&sParse, 0, sizeof(ParseContext)); |
| 123068 | sParse.pTokenizer = pTokenizer; |
| 123069 | sParse.iLangid = iLangid; |
| 123070 | sParse.azCol = (const char **)azCol; |
| 123071 | sParse.nCol = nCol; |
| 123072 | sParse.iDefaultCol = iDefaultCol; |
| 123073 | sParse.bFts4 = bFts4; |
| 123074 | if( z==0 ){ |
| 123075 | *ppExpr = 0; |
| 123076 | return SQLITE_OK; |
| 123077 | } |
| @@ -123008,11 +123258,11 @@ | |
| 123258 | for(ii=0; ii<nCol; ii++){ |
| 123259 | azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); |
| 123260 | } |
| 123261 | |
| 123262 | rc = sqlite3Fts3ExprParse( |
| 123263 | pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr |
| 123264 | ); |
| 123265 | if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ |
| 123266 | sqlite3_result_error(context, "Error parsing expression", -1); |
| 123267 | }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){ |
| 123268 | sqlite3_result_error_nomem(context); |
| @@ -124057,10 +124307,11 @@ | |
| 124307 | porterCreate, |
| 124308 | porterDestroy, |
| 124309 | porterOpen, |
| 124310 | porterClose, |
| 124311 | porterNext, |
| 124312 | 0 |
| 124313 | }; |
| 124314 | |
| 124315 | /* |
| 124316 | ** Allocate a new porter tokenizer. Return a pointer to the new |
| 124317 | ** tokenizer in *ppModule |
| @@ -124362,15 +124613,14 @@ | |
| 124613 | if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){ |
| 124614 | zErr = "error in xCreate()"; |
| 124615 | goto finish; |
| 124616 | } |
| 124617 | pTokenizer->pModule = p; |
| 124618 | if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){ |
| 124619 | zErr = "error in xOpen()"; |
| 124620 | goto finish; |
| 124621 | } |
| 124622 | |
| 124623 | while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ |
| 124624 | Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); |
| 124625 | Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); |
| 124626 | zToken = &zInput[iStart]; |
| @@ -124782,10 +125032,11 @@ | |
| 125032 | simpleCreate, |
| 125033 | simpleDestroy, |
| 125034 | simpleOpen, |
| 125035 | simpleClose, |
| 125036 | simpleNext, |
| 125037 | 0, |
| 125038 | }; |
| 125039 | |
| 125040 | /* |
| 125041 | ** Allocate a new simple tokenizer. Return a pointer to the new |
| 125042 | ** tokenizer in *ppModule |
| @@ -125031,10 +125282,12 @@ | |
| 125282 | #define SQL_SELECT_ALL_PREFIX_LEVEL 24 |
| 125283 | #define SQL_DELETE_ALL_TERMS_SEGDIR 25 |
| 125284 | |
| 125285 | #define SQL_DELETE_SEGDIR_RANGE 26 |
| 125286 | |
| 125287 | #define SQL_SELECT_ALL_LANGID 27 |
| 125288 | |
| 125289 | /* |
| 125290 | ** This function is used to obtain an SQLite prepared statement handle |
| 125291 | ** for the statement identified by the second argument. If successful, |
| 125292 | ** *pp is set to the requested statement handle and SQLITE_OK returned. |
| 125293 | ** Otherwise, an SQLite error code is returned and *pp is set to 0. |
| @@ -125084,10 +125337,11 @@ | |
| 125337 | /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)", |
| 125338 | /* 24 */ "", |
| 125339 | /* 25 */ "", |
| 125340 | |
| 125341 | /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", |
| 125342 | /* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'", |
| 125343 | |
| 125344 | }; |
| 125345 | int rc = SQLITE_OK; |
| 125346 | sqlite3_stmt *pStmt; |
| 125347 | |
| @@ -125229,10 +125483,23 @@ | |
| 125483 | rc = SQLITE_OK; |
| 125484 | } |
| 125485 | |
| 125486 | return rc; |
| 125487 | } |
| 125488 | |
| 125489 | static sqlite3_int64 getAbsoluteLevel( |
| 125490 | Fts3Table *p, |
| 125491 | int iLangid, |
| 125492 | int iIndex, |
| 125493 | int iLevel |
| 125494 | ){ |
| 125495 | assert( iLangid>=0 ); |
| 125496 | assert( p->nIndex>0 ); |
| 125497 | assert( iIndex>=0 && iIndex<p->nIndex ); |
| 125498 | return (iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL + iLevel; |
| 125499 | } |
| 125500 | |
| 125501 | |
| 125502 | /* |
| 125503 | ** Set *ppStmt to a statement handle that may be used to iterate through |
| 125504 | ** all rows in the %_segdir table, from oldest to newest. If successful, |
| 125505 | ** return SQLITE_OK. If an error occurs while preparing the statement, |
| @@ -125249,10 +125516,11 @@ | |
| 125516 | ** 3: end_block |
| 125517 | ** 4: root |
| 125518 | */ |
| 125519 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs( |
| 125520 | Fts3Table *p, /* FTS3 table */ |
| 125521 | int iLangid, /* Language being queried */ |
| 125522 | int iIndex, /* Index for p->aIndex[] */ |
| 125523 | int iLevel, /* Level to select */ |
| 125524 | sqlite3_stmt **ppStmt /* OUT: Compiled statement */ |
| 125525 | ){ |
| 125526 | int rc; |
| @@ -125264,18 +125532,20 @@ | |
| 125532 | |
| 125533 | if( iLevel<0 ){ |
| 125534 | /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */ |
| 125535 | rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0); |
| 125536 | if( rc==SQLITE_OK ){ |
| 125537 | sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); |
| 125538 | sqlite3_bind_int(pStmt, 2, |
| 125539 | getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) |
| 125540 | ); |
| 125541 | } |
| 125542 | }else{ |
| 125543 | /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */ |
| 125544 | rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); |
| 125545 | if( rc==SQLITE_OK ){ |
| 125546 | sqlite3_bind_int(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)); |
| 125547 | } |
| 125548 | } |
| 125549 | *ppStmt = pStmt; |
| 125550 | return rc; |
| 125551 | } |
| @@ -125437,10 +125707,11 @@ | |
| 125707 | ** |
| 125708 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. |
| 125709 | */ |
| 125710 | static int fts3PendingTermsAdd( |
| 125711 | Fts3Table *p, /* Table into which text will be inserted */ |
| 125712 | int iLangid, /* Language id to use */ |
| 125713 | const char *zText, /* Text of document to be inserted */ |
| 125714 | int iCol, /* Column into which text is being inserted */ |
| 125715 | u32 *pnWord /* OUT: Number of tokens inserted */ |
| 125716 | ){ |
| 125717 | int rc; |
| @@ -125466,15 +125737,14 @@ | |
| 125737 | if( zText==0 ){ |
| 125738 | *pnWord = 0; |
| 125739 | return SQLITE_OK; |
| 125740 | } |
| 125741 | |
| 125742 | rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr); |
| 125743 | if( rc!=SQLITE_OK ){ |
| 125744 | return rc; |
| 125745 | } |
| 125746 | |
| 125747 | xNext = pModule->xNext; |
| 125748 | while( SQLITE_OK==rc |
| 125749 | && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) |
| 125750 | ){ |
| @@ -125513,22 +125783,32 @@ | |
| 125783 | /* |
| 125784 | ** Calling this function indicates that subsequent calls to |
| 125785 | ** fts3PendingTermsAdd() are to add term/position-list pairs for the |
| 125786 | ** contents of the document with docid iDocid. |
| 125787 | */ |
| 125788 | static int fts3PendingTermsDocid( |
| 125789 | Fts3Table *p, /* Full-text table handle */ |
| 125790 | int iLangid, /* Language id of row being written */ |
| 125791 | sqlite_int64 iDocid /* Docid of row being written */ |
| 125792 | ){ |
| 125793 | assert( iLangid>=0 ); |
| 125794 | |
| 125795 | /* TODO(shess) Explore whether partially flushing the buffer on |
| 125796 | ** forced-flush would provide better performance. I suspect that if |
| 125797 | ** we ordered the doclists by size and flushed the largest until the |
| 125798 | ** buffer was half empty, that would let the less frequent terms |
| 125799 | ** generate longer doclists. |
| 125800 | */ |
| 125801 | if( iDocid<=p->iPrevDocid |
| 125802 | || p->iPrevLangid!=iLangid |
| 125803 | || p->nPendingData>p->nMaxPendingData |
| 125804 | ){ |
| 125805 | int rc = sqlite3Fts3PendingTermsFlush(p); |
| 125806 | if( rc!=SQLITE_OK ) return rc; |
| 125807 | } |
| 125808 | p->iPrevDocid = iDocid; |
| 125809 | p->iPrevLangid = iLangid; |
| 125810 | return SQLITE_OK; |
| 125811 | } |
| 125812 | |
| 125813 | /* |
| 125814 | ** Discard the contents of the pending-terms hash tables. |
| @@ -125553,15 +125833,20 @@ | |
| 125833 | ** pendingTerms hash table. |
| 125834 | ** |
| 125835 | ** Argument apVal is the same as the similarly named argument passed to |
| 125836 | ** fts3InsertData(). Parameter iDocid is the docid of the new row. |
| 125837 | */ |
| 125838 | static int fts3InsertTerms( |
| 125839 | Fts3Table *p, |
| 125840 | int iLangid, |
| 125841 | sqlite3_value **apVal, |
| 125842 | u32 *aSz |
| 125843 | ){ |
| 125844 | int i; /* Iterator variable */ |
| 125845 | for(i=2; i<p->nColumn+2; i++){ |
| 125846 | const char *zText = (const char *)sqlite3_value_text(apVal[i]); |
| 125847 | int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]); |
| 125848 | if( rc!=SQLITE_OK ){ |
| 125849 | return rc; |
| 125850 | } |
| 125851 | aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]); |
| 125852 | } |
| @@ -125578,10 +125863,11 @@ | |
| 125863 | ** apVal[2] Left-most user-defined column |
| 125864 | ** ... |
| 125865 | ** apVal[p->nColumn+1] Right-most user-defined column |
| 125866 | ** apVal[p->nColumn+2] Hidden column with same name as table |
| 125867 | ** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid) |
| 125868 | ** apVal[p->nColumn+4] Hidden languageid column |
| 125869 | */ |
| 125870 | static int fts3InsertData( |
| 125871 | Fts3Table *p, /* Full-text table */ |
| 125872 | sqlite3_value **apVal, /* Array of values to insert */ |
| 125873 | sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */ |
| @@ -125608,13 +125894,17 @@ | |
| 125894 | ** |
| 125895 | ** The statement features N '?' variables, where N is the number of user |
| 125896 | ** defined columns in the FTS3 table, plus one for the docid field. |
| 125897 | */ |
| 125898 | rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]); |
| 125899 | if( rc==SQLITE_OK && p->zLanguageid ){ |
| 125900 | rc = sqlite3_bind_int( |
| 125901 | pContentInsert, p->nColumn+2, |
| 125902 | sqlite3_value_int(apVal[p->nColumn+4]) |
| 125903 | ); |
| 125904 | } |
| 125905 | if( rc!=SQLITE_OK ) return rc; |
| 125906 | |
| 125907 | /* There is a quirk here. The users INSERT statement may have specified |
| 125908 | ** a value for the "rowid" field, for the "docid" field, or for both. |
| 125909 | ** Which is a problem, since "rowid" and "docid" are aliases for the |
| 125910 | ** same value. For example: |
| @@ -125669,10 +125959,19 @@ | |
| 125959 | if( p->bHasStat ){ |
| 125960 | fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); |
| 125961 | } |
| 125962 | return rc; |
| 125963 | } |
| 125964 | |
| 125965 | /* |
| 125966 | ** |
| 125967 | */ |
| 125968 | static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){ |
| 125969 | int iLangid = 0; |
| 125970 | if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1); |
| 125971 | return iLangid; |
| 125972 | } |
| 125973 | |
| 125974 | /* |
| 125975 | ** The first element in the apVal[] array is assumed to contain the docid |
| 125976 | ** (an integer) of a row about to be deleted. Remove all terms from the |
| 125977 | ** full-text index. |
| @@ -125689,19 +125988,21 @@ | |
| 125988 | if( *pRC ) return; |
| 125989 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); |
| 125990 | if( rc==SQLITE_OK ){ |
| 125991 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 125992 | int i; |
| 125993 | int iLangid = langidFromSelect(p, pSelect); |
| 125994 | rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); |
| 125995 | for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ |
| 125996 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 125997 | rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]); |
| 125998 | aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); |
| 125999 | } |
| 126000 | if( rc!=SQLITE_OK ){ |
| 126001 | sqlite3_reset(pSelect); |
| 126002 | *pRC = rc; |
| 126003 | return; |
| 126004 | } |
| 126005 | } |
| 126006 | rc = sqlite3_reset(pSelect); |
| 126007 | }else{ |
| 126008 | sqlite3_reset(pSelect); |
| @@ -125711,11 +126012,11 @@ | |
| 126012 | |
| 126013 | /* |
| 126014 | ** Forward declaration to account for the circular dependency between |
| 126015 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| 126016 | */ |
| 126017 | static int fts3SegmentMerge(Fts3Table *, int, int, int); |
| 126018 | |
| 126019 | /* |
| 126020 | ** This function allocates a new level iLevel index in the segdir table. |
| 126021 | ** Usually, indexes are allocated within a level sequentially starting |
| 126022 | ** with 0, so the allocated index is one greater than the value returned |
| @@ -125730,22 +126031,28 @@ | |
| 126031 | ** If successful, *piIdx is set to the allocated index slot and SQLITE_OK |
| 126032 | ** returned. Otherwise, an SQLite error code is returned. |
| 126033 | */ |
| 126034 | static int fts3AllocateSegdirIdx( |
| 126035 | Fts3Table *p, |
| 126036 | int iLangid, /* Language id */ |
| 126037 | int iIndex, /* Index for p->aIndex */ |
| 126038 | int iLevel, |
| 126039 | int *piIdx |
| 126040 | ){ |
| 126041 | int rc; /* Return Code */ |
| 126042 | sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ |
| 126043 | int iNext = 0; /* Result of query pNextIdx */ |
| 126044 | |
| 126045 | assert( iLangid>=0 ); |
| 126046 | assert( p->nIndex>=1 ); |
| 126047 | |
| 126048 | /* Set variable iNext to the next available segdir index at level iLevel. */ |
| 126049 | rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); |
| 126050 | if( rc==SQLITE_OK ){ |
| 126051 | sqlite3_bind_int64( |
| 126052 | pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) |
| 126053 | ); |
| 126054 | if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ |
| 126055 | iNext = sqlite3_column_int(pNextIdx, 0); |
| 126056 | } |
| 126057 | rc = sqlite3_reset(pNextIdx); |
| 126058 | } |
| @@ -125755,11 +126062,11 @@ | |
| 126062 | ** full, merge all segments in level iLevel into a single iLevel+1 |
| 126063 | ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise, |
| 126064 | ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext. |
| 126065 | */ |
| 126066 | if( iNext>=FTS3_MERGE_COUNT ){ |
| 126067 | rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel); |
| 126068 | *piIdx = 0; |
| 126069 | }else{ |
| 126070 | *piIdx = iNext; |
| 126071 | } |
| 126072 | } |
| @@ -126978,11 +127285,16 @@ | |
| 127285 | ** |
| 127286 | ** Segment levels are stored in the 'level' column of the %_segdir table. |
| 127287 | ** |
| 127288 | ** Return SQLITE_OK if successful, or an SQLite error code if not. |
| 127289 | */ |
| 127290 | static int fts3SegmentMaxLevel( |
| 127291 | Fts3Table *p, |
| 127292 | int iLangid, |
| 127293 | int iIndex, |
| 127294 | int *pnMax |
| 127295 | ){ |
| 127296 | sqlite3_stmt *pStmt; |
| 127297 | int rc; |
| 127298 | assert( iIndex>=0 && iIndex<p->nIndex ); |
| 127299 | |
| 127300 | /* Set pStmt to the compiled version of: |
| @@ -126991,12 +127303,14 @@ | |
| 127303 | ** |
| 127304 | ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). |
| 127305 | */ |
| 127306 | rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); |
| 127307 | if( rc!=SQLITE_OK ) return rc; |
| 127308 | sqlite3_bind_int(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); |
| 127309 | sqlite3_bind_int(pStmt, 2, |
| 127310 | getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) |
| 127311 | ); |
| 127312 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 127313 | *pnMax = sqlite3_column_int(pStmt, 0); |
| 127314 | } |
| 127315 | return sqlite3_reset(pStmt); |
| 127316 | } |
| @@ -127015,10 +127329,11 @@ | |
| 127329 | ** |
| 127330 | ** SQLITE_OK is returned if successful, otherwise an SQLite error code. |
| 127331 | */ |
| 127332 | static int fts3DeleteSegdir( |
| 127333 | Fts3Table *p, /* Virtual table handle */ |
| 127334 | int iLangid, /* Language id */ |
| 127335 | int iIndex, /* Index for p->aIndex */ |
| 127336 | int iLevel, /* Level of %_segdir entries to delete */ |
| 127337 | Fts3SegReader **apSegment, /* Array of SegReader objects */ |
| 127338 | int nReader /* Size of array apSegment */ |
| 127339 | ){ |
| @@ -127042,17 +127357,19 @@ | |
| 127357 | |
| 127358 | assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL ); |
| 127359 | if( iLevel==FTS3_SEGCURSOR_ALL ){ |
| 127360 | rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0); |
| 127361 | if( rc==SQLITE_OK ){ |
| 127362 | sqlite3_bind_int(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); |
| 127363 | sqlite3_bind_int(pDelete, 2, |
| 127364 | getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) |
| 127365 | ); |
| 127366 | } |
| 127367 | }else{ |
| 127368 | rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0); |
| 127369 | if( rc==SQLITE_OK ){ |
| 127370 | sqlite3_bind_int(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel)); |
| 127371 | } |
| 127372 | } |
| 127373 | |
| 127374 | if( rc==SQLITE_OK ){ |
| 127375 | sqlite3_step(pDelete); |
| @@ -127517,27 +127834,32 @@ | |
| 127834 | ** If this function is called with iLevel<0, but there is only one |
| 127835 | ** segment in the database, SQLITE_DONE is returned immediately. |
| 127836 | ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, |
| 127837 | ** an SQLite error code is returned. |
| 127838 | */ |
| 127839 | static int fts3SegmentMerge( |
| 127840 | Fts3Table *p, |
| 127841 | int iLangid, /* Language id to merge */ |
| 127842 | int iIndex, /* Index in p->aIndex[] to merge */ |
| 127843 | int iLevel /* Level to merge */ |
| 127844 | ){ |
| 127845 | int rc; /* Return code */ |
| 127846 | int iIdx = 0; /* Index of new segment */ |
| 127847 | int iNewLevel = 0; /* Level/index to create new segment at */ |
| 127848 | SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */ |
| 127849 | Fts3SegFilter filter; /* Segment term filter condition */ |
| 127850 | Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ |
| 127851 | int bIgnoreEmpty = 0; /* True to ignore empty segments */ |
| 127852 | |
| 127853 | assert( iLevel==FTS3_SEGCURSOR_ALL |
| 127854 | || iLevel==FTS3_SEGCURSOR_PENDING |
| 127855 | || iLevel>=0 |
| 127856 | ); |
| 127857 | assert( iLevel<FTS3_SEGDIR_MAXLEVEL ); |
| 127858 | assert( iIndex>=0 && iIndex<p->nIndex ); |
| 127859 | |
| 127860 | rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr); |
| 127861 | if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished; |
| 127862 | |
| 127863 | if( iLevel==FTS3_SEGCURSOR_ALL ){ |
| 127864 | /* This call is to merge all segments in the database to a single |
| 127865 | ** segment. The level of the new segment is equal to the the numerically |
| @@ -127545,28 +127867,28 @@ | |
| 127867 | ** index. The idx of the new segment is always 0. */ |
| 127868 | if( csr.nSegment==1 ){ |
| 127869 | rc = SQLITE_DONE; |
| 127870 | goto finished; |
| 127871 | } |
| 127872 | rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel); |
| 127873 | bIgnoreEmpty = 1; |
| 127874 | |
| 127875 | }else if( iLevel==FTS3_SEGCURSOR_PENDING ){ |
| 127876 | iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0); |
| 127877 | rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx); |
| 127878 | }else{ |
| 127879 | /* This call is to merge all segments at level iLevel. find the next |
| 127880 | ** available segment index at level iLevel+1. The call to |
| 127881 | ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to |
| 127882 | ** a single iLevel+2 segment if necessary. */ |
| 127883 | rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx); |
| 127884 | iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1); |
| 127885 | } |
| 127886 | if( rc!=SQLITE_OK ) goto finished; |
| 127887 | assert( csr.nSegment>0 ); |
| 127888 | assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) ); |
| 127889 | assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) ); |
| 127890 | |
| 127891 | memset(&filter, 0, sizeof(Fts3SegFilter)); |
| 127892 | filter.flags = FTS3_SEGMENT_REQUIRE_POS; |
| 127893 | filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0); |
| 127894 | |
| @@ -127579,11 +127901,13 @@ | |
| 127901 | } |
| 127902 | if( rc!=SQLITE_OK ) goto finished; |
| 127903 | assert( pWriter ); |
| 127904 | |
| 127905 | if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
| 127906 | rc = fts3DeleteSegdir( |
| 127907 | p, iLangid, iIndex, iLevel, csr.apSegment, csr.nSegment |
| 127908 | ); |
| 127909 | if( rc!=SQLITE_OK ) goto finished; |
| 127910 | } |
| 127911 | rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx); |
| 127912 | |
| 127913 | finished: |
| @@ -127598,11 +127922,11 @@ | |
| 127922 | */ |
| 127923 | SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ |
| 127924 | int rc = SQLITE_OK; |
| 127925 | int i; |
| 127926 | for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){ |
| 127927 | rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING); |
| 127928 | if( rc==SQLITE_DONE ) rc = SQLITE_OK; |
| 127929 | } |
| 127930 | sqlite3Fts3PendingTermsClear(p); |
| 127931 | return rc; |
| 127932 | } |
| @@ -127753,21 +128077,38 @@ | |
| 128077 | sqlite3_step(pStmt); |
| 128078 | *pRC = sqlite3_reset(pStmt); |
| 128079 | sqlite3_free(a); |
| 128080 | } |
| 128081 | |
| 128082 | /* |
| 128083 | ** Merge the entire database so that there is one segment for each |
| 128084 | ** iIndex/iLangid combination. |
| 128085 | */ |
| 128086 | static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ |
| 128087 | int bSeenDone = 0; |
| 128088 | int rc; |
| 128089 | sqlite3_stmt *pAllLangid = 0; |
| 128090 | |
| 128091 | rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); |
| 128092 | if( rc==SQLITE_OK ){ |
| 128093 | int rc2; |
| 128094 | sqlite3_bind_int(pAllLangid, 1, p->nIndex); |
| 128095 | while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ |
| 128096 | int i; |
| 128097 | int iLangid = sqlite3_column_int(pAllLangid, 0); |
| 128098 | for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){ |
| 128099 | rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL); |
| 128100 | if( rc==SQLITE_DONE ){ |
| 128101 | bSeenDone = 1; |
| 128102 | rc = SQLITE_OK; |
| 128103 | } |
| 128104 | } |
| 128105 | } |
| 128106 | rc2 = sqlite3_reset(pAllLangid); |
| 128107 | if( rc==SQLITE_OK ) rc = rc2; |
| 128108 | } |
| 128109 | |
| 128110 | sqlite3Fts3SegmentsClose(p); |
| 128111 | sqlite3Fts3PendingTermsClear(p); |
| 128112 | |
| 128113 | return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc; |
| 128114 | } |
| @@ -127814,15 +128155,16 @@ | |
| 128155 | } |
| 128156 | } |
| 128157 | |
| 128158 | while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 128159 | int iCol; |
| 128160 | int iLangid = langidFromSelect(p, pStmt); |
| 128161 | rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); |
| 128162 | aSz[p->nColumn] = 0; |
| 128163 | for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ |
| 128164 | const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); |
| 128165 | rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); |
| 128166 | aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); |
| 128167 | } |
| 128168 | if( p->bHasDocsize ){ |
| 128169 | fts3InsertDocsize(&rc, p, aSz); |
| 128170 | } |
| @@ -127937,18 +128279,17 @@ | |
| 128279 | |
| 128280 | for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){ |
| 128281 | const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); |
| 128282 | sqlite3_tokenizer_cursor *pTC = 0; |
| 128283 | |
| 128284 | rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); |
| 128285 | while( rc==SQLITE_OK ){ |
| 128286 | char const *zToken; /* Buffer containing token */ |
| 128287 | int nToken; /* Number of bytes in token */ |
| 128288 | int iDum1, iDum2; /* Dummy variables */ |
| 128289 | int iPos; /* Position of token in zText */ |
| 128290 | |
| 128291 | rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos); |
| 128292 | for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ |
| 128293 | Fts3PhraseToken *pPT = pDef->pToken; |
| 128294 | if( (pDef->iCol>=p->nColumn || pDef->iCol==i) |
| 128295 | && (pPT->bFirst==0 || iPos==0) |
| @@ -128044,12 +128385,10 @@ | |
| 128385 | ** delete the contents of all three tables and throw away any |
| 128386 | ** data in the pendingTerms hash table. */ |
| 128387 | rc = fts3DeleteAll(p, 1); |
| 128388 | *pnDoc = *pnDoc - 1; |
| 128389 | }else{ |
| 128390 | fts3DeleteTerms(&rc, p, pRowid, aSzDel); |
| 128391 | if( p->zContentTbl==0 ){ |
| 128392 | fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid); |
| 128393 | if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1; |
| 128394 | }else{ |
| @@ -128064,11 +128403,20 @@ | |
| 128403 | return rc; |
| 128404 | } |
| 128405 | |
| 128406 | /* |
| 128407 | ** This function does the work for the xUpdate method of FTS3 virtual |
| 128408 | ** tables. The schema of the virtual table being: |
| 128409 | ** |
| 128410 | ** CREATE TABLE <table name>( |
| 128411 | ** <user COLUMns>, |
| 128412 | ** <table name> HIDDEN, |
| 128413 | ** docid HIDDEN, |
| 128414 | ** <langid> HIDDEN |
| 128415 | ** ); |
| 128416 | ** |
| 128417 | ** |
| 128418 | */ |
| 128419 | SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( |
| 128420 | sqlite3_vtab *pVtab, /* FTS3 vtab object */ |
| 128421 | int nArg, /* Size of argument array */ |
| 128422 | sqlite3_value **apVal, /* Array of arguments */ |
| @@ -128081,10 +128429,14 @@ | |
| 128429 | u32 *aSzDel; /* Sizes of deleted documents */ |
| 128430 | int nChng = 0; /* Net change in number of documents */ |
| 128431 | int bInsertDone = 0; |
| 128432 | |
| 128433 | assert( p->pSegments==0 ); |
| 128434 | assert( |
| 128435 | nArg==1 /* DELETE operations */ |
| 128436 | || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */ |
| 128437 | ); |
| 128438 | |
| 128439 | /* Check for a "special" INSERT operation. One of the form: |
| 128440 | ** |
| 128441 | ** INSERT INTO xyz(xyz) VALUES('command'); |
| 128442 | */ |
| @@ -128093,10 +128445,15 @@ | |
| 128445 | && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL |
| 128446 | ){ |
| 128447 | rc = fts3SpecialInsert(p, apVal[p->nColumn+2]); |
| 128448 | goto update_out; |
| 128449 | } |
| 128450 | |
| 128451 | if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ |
| 128452 | rc = SQLITE_CONSTRAINT; |
| 128453 | goto update_out; |
| 128454 | } |
| 128455 | |
| 128456 | /* Allocate space to hold the change in document sizes */ |
| 128457 | aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 ); |
| 128458 | if( aSzIns==0 ){ |
| 128459 | rc = SQLITE_NOMEM; |
| @@ -128161,22 +128518,23 @@ | |
| 128518 | isRemove = 1; |
| 128519 | } |
| 128520 | |
| 128521 | /* If this is an INSERT or UPDATE operation, insert the new record. */ |
| 128522 | if( nArg>1 && rc==SQLITE_OK ){ |
| 128523 | int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]); |
| 128524 | if( bInsertDone==0 ){ |
| 128525 | rc = fts3InsertData(p, apVal, pRowid); |
| 128526 | if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ |
| 128527 | rc = FTS_CORRUPT_VTAB; |
| 128528 | } |
| 128529 | } |
| 128530 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ |
| 128531 | rc = fts3PendingTermsDocid(p, iLangid, *pRowid); |
| 128532 | } |
| 128533 | if( rc==SQLITE_OK ){ |
| 128534 | assert( p->iPrevDocid==*pRowid ); |
| 128535 | rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); |
| 128536 | } |
| 128537 | if( p->bHasDocsize ){ |
| 128538 | fts3InsertDocsize(&rc, p, aSzIns); |
| 128539 | } |
| 128540 | nChng++; |
| @@ -128749,10 +129107,11 @@ | |
| 129107 | ** is no way for fts3BestSnippet() to know whether or not the document |
| 129108 | ** actually contains terms that follow the final highlighted term. |
| 129109 | */ |
| 129110 | static int fts3SnippetShift( |
| 129111 | Fts3Table *pTab, /* FTS3 table snippet comes from */ |
| 129112 | int iLangid, /* Language id to use in tokenizing */ |
| 129113 | int nSnippet, /* Number of tokens desired for snippet */ |
| 129114 | const char *zDoc, /* Document text to extract snippet from */ |
| 129115 | int nDoc, /* Size of buffer zDoc in bytes */ |
| 129116 | int *piPos, /* IN/OUT: First token of snippet */ |
| 129117 | u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */ |
| @@ -128784,15 +129143,14 @@ | |
| 129143 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 129144 | |
| 129145 | /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) |
| 129146 | ** or more tokens in zDoc/nDoc. |
| 129147 | */ |
| 129148 | rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); |
| 129149 | if( rc!=SQLITE_OK ){ |
| 129150 | return rc; |
| 129151 | } |
| 129152 | while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ |
| 129153 | const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3; |
| 129154 | rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); |
| 129155 | } |
| 129156 | pMod->xClose(pC); |
| @@ -128848,15 +129206,14 @@ | |
| 129206 | } |
| 129207 | nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); |
| 129208 | |
| 129209 | /* Open a token cursor on the document. */ |
| 129210 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 129211 | rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC); |
| 129212 | if( rc!=SQLITE_OK ){ |
| 129213 | return rc; |
| 129214 | } |
| 129215 | |
| 129216 | while( rc==SQLITE_OK ){ |
| 129217 | int iBegin; /* Offset in zDoc of start of token */ |
| 129218 | int iFin; /* Offset in zDoc of end of token */ |
| 129219 | int isHighlight; /* True for highlighted terms */ |
| @@ -128874,11 +129231,13 @@ | |
| 129231 | } |
| 129232 | if( iCurrent<iPos ){ continue; } |
| 129233 | |
| 129234 | if( !isShiftDone ){ |
| 129235 | int n = nDoc - iBegin; |
| 129236 | rc = fts3SnippetShift( |
| 129237 | pTab, pCsr->iLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask |
| 129238 | ); |
| 129239 | isShiftDone = 1; |
| 129240 | |
| 129241 | /* Now that the shift has been done, check if the initial "..." are |
| 129242 | ** required. They are required if (a) this is not the first fragment, |
| 129243 | ** or (b) this fragment does not begin at position 0 of its column. |
| @@ -129607,13 +129966,14 @@ | |
| 129966 | rc = SQLITE_NOMEM; |
| 129967 | goto offsets_out; |
| 129968 | } |
| 129969 | |
| 129970 | /* Initialize a tokenizer iterator to iterate through column iCol. */ |
| 129971 | rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, |
| 129972 | zDoc, nDoc, &pC |
| 129973 | ); |
| 129974 | if( rc!=SQLITE_OK ) goto offsets_out; |
| 129975 | |
| 129976 | rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); |
| 129977 | while( rc==SQLITE_OK ){ |
| 129978 | int i; /* Used to loop through terms */ |
| 129979 | int iMinPos = 0x7FFFFFFF; /* Position of next token */ |
| 129980 |
+51
-6
| --- 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.11" |
| 111 | 111 | #define SQLITE_VERSION_NUMBER 3007011 |
| 112 | -#define SQLITE_SOURCE_ID "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130" | |
| 112 | +#define SQLITE_SOURCE_ID "2012-03-16 00:28:11 74eadeec34c4b19cf5f8b7f648db3b7ad601a00e" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| @@ -459,10 +459,11 @@ | ||
| 459 | 459 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 460 | 460 | #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) |
| 461 | 461 | #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) |
| 462 | 462 | #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) |
| 463 | 463 | #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) |
| 464 | +#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) | |
| 464 | 465 | |
| 465 | 466 | /* |
| 466 | 467 | ** CAPI3REF: Flags For File Open Operations |
| 467 | 468 | ** |
| 468 | 469 | ** These bit values are intended for use in the |
| @@ -714,31 +715,35 @@ | ||
| 714 | 715 | ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], |
| 715 | 716 | ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) |
| 716 | 717 | ** into an integer that the pArg argument points to. This capability |
| 717 | 718 | ** is used during testing and only needs to be supported when SQLITE_TEST |
| 718 | 719 | ** is defined. |
| 719 | -** | |
| 720 | +** <ul> | |
| 721 | +** <li>[[SQLITE_FCNTL_SIZE_HINT]] | |
| 720 | 722 | ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS |
| 721 | 723 | ** layer a hint of how large the database file will grow to be during the |
| 722 | 724 | ** current transaction. This hint is not guaranteed to be accurate but it |
| 723 | 725 | ** is often close. The underlying VFS might choose to preallocate database |
| 724 | 726 | ** file space based on this hint in order to help writes to the database |
| 725 | 727 | ** file run faster. |
| 726 | 728 | ** |
| 729 | +** <li>[[SQLITE_FCNTL_CHUNK_SIZE]] | |
| 727 | 730 | ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS |
| 728 | 731 | ** extends and truncates the database file in chunks of a size specified |
| 729 | 732 | ** by the user. The fourth argument to [sqlite3_file_control()] should |
| 730 | 733 | ** point to an integer (type int) containing the new chunk-size to use |
| 731 | 734 | ** for the nominated database. Allocating database file space in large |
| 732 | 735 | ** chunks (say 1MB at a time), may reduce file-system fragmentation and |
| 733 | 736 | ** improve performance on some systems. |
| 734 | 737 | ** |
| 738 | +** <li>[[SQLITE_FCNTL_FILE_POINTER]] | |
| 735 | 739 | ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer |
| 736 | 740 | ** to the [sqlite3_file] object associated with a particular database |
| 737 | 741 | ** connection. See the [sqlite3_file_control()] documentation for |
| 738 | 742 | ** additional information. |
| 739 | 743 | ** |
| 744 | +** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] | |
| 740 | 745 | ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by |
| 741 | 746 | ** SQLite and sent to all VFSes in place of a call to the xSync method |
| 742 | 747 | ** when the database connection has [PRAGMA synchronous] set to OFF.)^ |
| 743 | 748 | ** Some specialized VFSes need this signal in order to operate correctly |
| 744 | 749 | ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most |
| @@ -745,10 +750,11 @@ | ||
| 745 | 750 | ** VFSes do not need this signal and should silently ignore this opcode. |
| 746 | 751 | ** Applications should not call [sqlite3_file_control()] with this |
| 747 | 752 | ** opcode as doing so may disrupt the operation of the specialized VFSes |
| 748 | 753 | ** that do require it. |
| 749 | 754 | ** |
| 755 | +** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]] | |
| 750 | 756 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 751 | 757 | ** retry counts and intervals for certain disk I/O operations for the |
| 752 | 758 | ** windows [VFS] in order to provide robustness in the presence of |
| 753 | 759 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 754 | 760 | ** file write, and file delete operations up to 10 times, with a delay |
| @@ -761,10 +767,11 @@ | ||
| 761 | 767 | ** integer is the delay. If either integer is negative, then the setting |
| 762 | 768 | ** is not changed but instead the prior value of that setting is written |
| 763 | 769 | ** into the array entry, allowing the current retry settings to be |
| 764 | 770 | ** interrogated. The zDbName parameter is ignored. |
| 765 | 771 | ** |
| 772 | +** <li>[[SQLITE_FCNTL_PERSIST_WAL]] | |
| 766 | 773 | ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the |
| 767 | 774 | ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary |
| 768 | 775 | ** write ahead log and shared memory files used for transaction control |
| 769 | 776 | ** are automatically deleted when the latest connection to the database |
| 770 | 777 | ** closes. Setting persistent WAL mode causes those files to persist after |
| @@ -775,24 +782,27 @@ | ||
| 775 | 782 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 776 | 783 | ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent |
| 777 | 784 | ** WAL mode. If the integer is -1, then it is overwritten with the current |
| 778 | 785 | ** WAL persistence setting. |
| 779 | 786 | ** |
| 787 | +** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] | |
| 780 | 788 | ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the |
| 781 | 789 | ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting |
| 782 | 790 | ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the |
| 783 | 791 | ** xDeviceCharacteristics methods. The fourth parameter to |
| 784 | 792 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 785 | 793 | ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage |
| 786 | 794 | ** mode. If the integer is -1, then it is overwritten with the current |
| 787 | 795 | ** zero-damage mode setting. |
| 788 | 796 | ** |
| 797 | +** <li>[[SQLITE_FCNTL_OVERWRITE]] | |
| 789 | 798 | ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening |
| 790 | 799 | ** a write transaction to indicate that, unless it is rolled back for some |
| 791 | 800 | ** reason, the entire database file will be overwritten by the current |
| 792 | 801 | ** transaction. This is used by VACUUM operations. |
| 793 | 802 | ** |
| 803 | +** <li>[[SQLITE_FCNTL_VFSNAME]] | |
| 794 | 804 | ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of |
| 795 | 805 | ** all [VFSes] in the VFS stack. The names are of all VFS shims and the |
| 796 | 806 | ** final bottom-level VFS are written into memory obtained from |
| 797 | 807 | ** [sqlite3_malloc()] and the result is stored in the char* variable |
| 798 | 808 | ** that the fourth parameter of [sqlite3_file_control()] points to. |
| @@ -799,10 +809,34 @@ | ||
| 799 | 809 | ** The caller is responsible for freeing the memory when done. As with |
| 800 | 810 | ** all file-control actions, there is no guarantee that this will actually |
| 801 | 811 | ** do anything. Callers should initialize the char* variable to a NULL |
| 802 | 812 | ** pointer in case this file-control is not implemented. This file-control |
| 803 | 813 | ** is intended for diagnostic use only. |
| 814 | +** | |
| 815 | +** <li>[[SQLITE_FCNTL_PRAGMA]] | |
| 816 | +** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] | |
| 817 | +** file control is sent to the open [sqlite3_file] object corresponding | |
| 818 | +** to the database file to which the pragma statement refers. ^The argument | |
| 819 | +** to the [SQLITE_FCNTL_PRAGMA] file control is an array of | |
| 820 | +** pointers to strings (char**) in which the second element of the array | |
| 821 | +** is the name of the pragma and the third element is the argument to the | |
| 822 | +** pragma or NULL if the pragma has no argument. ^The handler for an | |
| 823 | +** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element | |
| 824 | +** of the char** argument point to a string obtained from [sqlite3_mprintf()] | |
| 825 | +** or the equivalent and that string will become the result of the pragma or | |
| 826 | +** the error message if the pragma fails. ^If the | |
| 827 | +** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal | |
| 828 | +** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] | |
| 829 | +** file control returns [SQLITE_OK], then the parser assumes that the | |
| 830 | +** VFS has handled the PRAGMA itself and the parser generates a no-op | |
| 831 | +** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns | |
| 832 | +** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means | |
| 833 | +** that the VFS encountered an error while handling the [PRAGMA] and the | |
| 834 | +** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] | |
| 835 | +** file control occurs at the beginning of pragma statement analysis and so | |
| 836 | +** it is able to override built-in [PRAGMA] statements. | |
| 837 | +** </ul> | |
| 804 | 838 | */ |
| 805 | 839 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 806 | 840 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 807 | 841 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 808 | 842 | #define SQLITE_LAST_ERRNO 4 |
| @@ -813,10 +847,11 @@ | ||
| 813 | 847 | #define SQLITE_FCNTL_WIN32_AV_RETRY 9 |
| 814 | 848 | #define SQLITE_FCNTL_PERSIST_WAL 10 |
| 815 | 849 | #define SQLITE_FCNTL_OVERWRITE 11 |
| 816 | 850 | #define SQLITE_FCNTL_VFSNAME 12 |
| 817 | 851 | #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 |
| 852 | +#define SQLITE_FCNTL_PRAGMA 14 | |
| 818 | 853 | |
| 819 | 854 | /* |
| 820 | 855 | ** CAPI3REF: Mutex Handle |
| 821 | 856 | ** |
| 822 | 857 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -4462,10 +4497,19 @@ | ||
| 4462 | 4497 | ** will be an absolute pathname, even if the filename used |
| 4463 | 4498 | ** to open the database originally was a URI or relative pathname. |
| 4464 | 4499 | */ |
| 4465 | 4500 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); |
| 4466 | 4501 | |
| 4502 | +/* | |
| 4503 | +** CAPI3REF: Determine if a database is read-only | |
| 4504 | +** | |
| 4505 | +** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N | |
| 4506 | +** of connection D is read-only, 0 if it is read/write, or -1 if N is not | |
| 4507 | +** the name of a database on connection D. | |
| 4508 | +*/ | |
| 4509 | +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); | |
| 4510 | + | |
| 4467 | 4511 | /* |
| 4468 | 4512 | ** CAPI3REF: Find the next prepared statement |
| 4469 | 4513 | ** |
| 4470 | 4514 | ** ^This interface returns a pointer to the next [prepared statement] after |
| 4471 | 4515 | ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL |
| @@ -6587,15 +6631,16 @@ | ||
| 6587 | 6631 | |
| 6588 | 6632 | |
| 6589 | 6633 | /* |
| 6590 | 6634 | ** CAPI3REF: String Comparison |
| 6591 | 6635 | ** |
| 6592 | -** ^The [sqlite3_strnicmp()] API allows applications and extensions to | |
| 6593 | -** compare the contents of two buffers containing UTF-8 strings in a | |
| 6594 | -** case-independent fashion, using the same definition of case independence | |
| 6595 | -** that SQLite uses internally when comparing identifiers. | |
| 6636 | +** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications | |
| 6637 | +** and extensions to compare the contents of two buffers containing UTF-8 | |
| 6638 | +** strings in a case-independent fashion, using the same definition of "case | |
| 6639 | +** independence" that SQLite uses internally when comparing identifiers. | |
| 6596 | 6640 | */ |
| 6641 | +SQLITE_API int sqlite3_stricmp(const char *, const char *); | |
| 6597 | 6642 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 6598 | 6643 | |
| 6599 | 6644 | /* |
| 6600 | 6645 | ** CAPI3REF: Error Logging Interface |
| 6601 | 6646 | ** |
| 6602 | 6647 |
| --- 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.11" |
| 111 | #define SQLITE_VERSION_NUMBER 3007011 |
| 112 | #define SQLITE_SOURCE_ID "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -459,10 +459,11 @@ | |
| 459 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 460 | #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) |
| 461 | #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) |
| 462 | #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) |
| 463 | #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) |
| 464 | |
| 465 | /* |
| 466 | ** CAPI3REF: Flags For File Open Operations |
| 467 | ** |
| 468 | ** These bit values are intended for use in the |
| @@ -714,31 +715,35 @@ | |
| 714 | ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], |
| 715 | ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) |
| 716 | ** into an integer that the pArg argument points to. This capability |
| 717 | ** is used during testing and only needs to be supported when SQLITE_TEST |
| 718 | ** is defined. |
| 719 | ** |
| 720 | ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS |
| 721 | ** layer a hint of how large the database file will grow to be during the |
| 722 | ** current transaction. This hint is not guaranteed to be accurate but it |
| 723 | ** is often close. The underlying VFS might choose to preallocate database |
| 724 | ** file space based on this hint in order to help writes to the database |
| 725 | ** file run faster. |
| 726 | ** |
| 727 | ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS |
| 728 | ** extends and truncates the database file in chunks of a size specified |
| 729 | ** by the user. The fourth argument to [sqlite3_file_control()] should |
| 730 | ** point to an integer (type int) containing the new chunk-size to use |
| 731 | ** for the nominated database. Allocating database file space in large |
| 732 | ** chunks (say 1MB at a time), may reduce file-system fragmentation and |
| 733 | ** improve performance on some systems. |
| 734 | ** |
| 735 | ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer |
| 736 | ** to the [sqlite3_file] object associated with a particular database |
| 737 | ** connection. See the [sqlite3_file_control()] documentation for |
| 738 | ** additional information. |
| 739 | ** |
| 740 | ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by |
| 741 | ** SQLite and sent to all VFSes in place of a call to the xSync method |
| 742 | ** when the database connection has [PRAGMA synchronous] set to OFF.)^ |
| 743 | ** Some specialized VFSes need this signal in order to operate correctly |
| 744 | ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most |
| @@ -745,10 +750,11 @@ | |
| 745 | ** VFSes do not need this signal and should silently ignore this opcode. |
| 746 | ** Applications should not call [sqlite3_file_control()] with this |
| 747 | ** opcode as doing so may disrupt the operation of the specialized VFSes |
| 748 | ** that do require it. |
| 749 | ** |
| 750 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 751 | ** retry counts and intervals for certain disk I/O operations for the |
| 752 | ** windows [VFS] in order to provide robustness in the presence of |
| 753 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 754 | ** file write, and file delete operations up to 10 times, with a delay |
| @@ -761,10 +767,11 @@ | |
| 761 | ** integer is the delay. If either integer is negative, then the setting |
| 762 | ** is not changed but instead the prior value of that setting is written |
| 763 | ** into the array entry, allowing the current retry settings to be |
| 764 | ** interrogated. The zDbName parameter is ignored. |
| 765 | ** |
| 766 | ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the |
| 767 | ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary |
| 768 | ** write ahead log and shared memory files used for transaction control |
| 769 | ** are automatically deleted when the latest connection to the database |
| 770 | ** closes. Setting persistent WAL mode causes those files to persist after |
| @@ -775,24 +782,27 @@ | |
| 775 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 776 | ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent |
| 777 | ** WAL mode. If the integer is -1, then it is overwritten with the current |
| 778 | ** WAL persistence setting. |
| 779 | ** |
| 780 | ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the |
| 781 | ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting |
| 782 | ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the |
| 783 | ** xDeviceCharacteristics methods. The fourth parameter to |
| 784 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 785 | ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage |
| 786 | ** mode. If the integer is -1, then it is overwritten with the current |
| 787 | ** zero-damage mode setting. |
| 788 | ** |
| 789 | ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening |
| 790 | ** a write transaction to indicate that, unless it is rolled back for some |
| 791 | ** reason, the entire database file will be overwritten by the current |
| 792 | ** transaction. This is used by VACUUM operations. |
| 793 | ** |
| 794 | ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of |
| 795 | ** all [VFSes] in the VFS stack. The names are of all VFS shims and the |
| 796 | ** final bottom-level VFS are written into memory obtained from |
| 797 | ** [sqlite3_malloc()] and the result is stored in the char* variable |
| 798 | ** that the fourth parameter of [sqlite3_file_control()] points to. |
| @@ -799,10 +809,34 @@ | |
| 799 | ** The caller is responsible for freeing the memory when done. As with |
| 800 | ** all file-control actions, there is no guarantee that this will actually |
| 801 | ** do anything. Callers should initialize the char* variable to a NULL |
| 802 | ** pointer in case this file-control is not implemented. This file-control |
| 803 | ** is intended for diagnostic use only. |
| 804 | */ |
| 805 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 806 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 807 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 808 | #define SQLITE_LAST_ERRNO 4 |
| @@ -813,10 +847,11 @@ | |
| 813 | #define SQLITE_FCNTL_WIN32_AV_RETRY 9 |
| 814 | #define SQLITE_FCNTL_PERSIST_WAL 10 |
| 815 | #define SQLITE_FCNTL_OVERWRITE 11 |
| 816 | #define SQLITE_FCNTL_VFSNAME 12 |
| 817 | #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 |
| 818 | |
| 819 | /* |
| 820 | ** CAPI3REF: Mutex Handle |
| 821 | ** |
| 822 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -4462,10 +4497,19 @@ | |
| 4462 | ** will be an absolute pathname, even if the filename used |
| 4463 | ** to open the database originally was a URI or relative pathname. |
| 4464 | */ |
| 4465 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); |
| 4466 | |
| 4467 | /* |
| 4468 | ** CAPI3REF: Find the next prepared statement |
| 4469 | ** |
| 4470 | ** ^This interface returns a pointer to the next [prepared statement] after |
| 4471 | ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL |
| @@ -6587,15 +6631,16 @@ | |
| 6587 | |
| 6588 | |
| 6589 | /* |
| 6590 | ** CAPI3REF: String Comparison |
| 6591 | ** |
| 6592 | ** ^The [sqlite3_strnicmp()] API allows applications and extensions to |
| 6593 | ** compare the contents of two buffers containing UTF-8 strings in a |
| 6594 | ** case-independent fashion, using the same definition of case independence |
| 6595 | ** that SQLite uses internally when comparing identifiers. |
| 6596 | */ |
| 6597 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 6598 | |
| 6599 | /* |
| 6600 | ** CAPI3REF: Error Logging Interface |
| 6601 | ** |
| 6602 |
| --- 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.11" |
| 111 | #define SQLITE_VERSION_NUMBER 3007011 |
| 112 | #define SQLITE_SOURCE_ID "2012-03-16 00:28:11 74eadeec34c4b19cf5f8b7f648db3b7ad601a00e" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -459,10 +459,11 @@ | |
| 459 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 460 | #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) |
| 461 | #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) |
| 462 | #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) |
| 463 | #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) |
| 464 | #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) |
| 465 | |
| 466 | /* |
| 467 | ** CAPI3REF: Flags For File Open Operations |
| 468 | ** |
| 469 | ** These bit values are intended for use in the |
| @@ -714,31 +715,35 @@ | |
| 715 | ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], |
| 716 | ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) |
| 717 | ** into an integer that the pArg argument points to. This capability |
| 718 | ** is used during testing and only needs to be supported when SQLITE_TEST |
| 719 | ** is defined. |
| 720 | ** <ul> |
| 721 | ** <li>[[SQLITE_FCNTL_SIZE_HINT]] |
| 722 | ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS |
| 723 | ** layer a hint of how large the database file will grow to be during the |
| 724 | ** current transaction. This hint is not guaranteed to be accurate but it |
| 725 | ** is often close. The underlying VFS might choose to preallocate database |
| 726 | ** file space based on this hint in order to help writes to the database |
| 727 | ** file run faster. |
| 728 | ** |
| 729 | ** <li>[[SQLITE_FCNTL_CHUNK_SIZE]] |
| 730 | ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS |
| 731 | ** extends and truncates the database file in chunks of a size specified |
| 732 | ** by the user. The fourth argument to [sqlite3_file_control()] should |
| 733 | ** point to an integer (type int) containing the new chunk-size to use |
| 734 | ** for the nominated database. Allocating database file space in large |
| 735 | ** chunks (say 1MB at a time), may reduce file-system fragmentation and |
| 736 | ** improve performance on some systems. |
| 737 | ** |
| 738 | ** <li>[[SQLITE_FCNTL_FILE_POINTER]] |
| 739 | ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer |
| 740 | ** to the [sqlite3_file] object associated with a particular database |
| 741 | ** connection. See the [sqlite3_file_control()] documentation for |
| 742 | ** additional information. |
| 743 | ** |
| 744 | ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] |
| 745 | ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by |
| 746 | ** SQLite and sent to all VFSes in place of a call to the xSync method |
| 747 | ** when the database connection has [PRAGMA synchronous] set to OFF.)^ |
| 748 | ** Some specialized VFSes need this signal in order to operate correctly |
| 749 | ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most |
| @@ -745,10 +750,11 @@ | |
| 750 | ** VFSes do not need this signal and should silently ignore this opcode. |
| 751 | ** Applications should not call [sqlite3_file_control()] with this |
| 752 | ** opcode as doing so may disrupt the operation of the specialized VFSes |
| 753 | ** that do require it. |
| 754 | ** |
| 755 | ** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]] |
| 756 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 757 | ** retry counts and intervals for certain disk I/O operations for the |
| 758 | ** windows [VFS] in order to provide robustness in the presence of |
| 759 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 760 | ** file write, and file delete operations up to 10 times, with a delay |
| @@ -761,10 +767,11 @@ | |
| 767 | ** integer is the delay. If either integer is negative, then the setting |
| 768 | ** is not changed but instead the prior value of that setting is written |
| 769 | ** into the array entry, allowing the current retry settings to be |
| 770 | ** interrogated. The zDbName parameter is ignored. |
| 771 | ** |
| 772 | ** <li>[[SQLITE_FCNTL_PERSIST_WAL]] |
| 773 | ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the |
| 774 | ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary |
| 775 | ** write ahead log and shared memory files used for transaction control |
| 776 | ** are automatically deleted when the latest connection to the database |
| 777 | ** closes. Setting persistent WAL mode causes those files to persist after |
| @@ -775,24 +782,27 @@ | |
| 782 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 783 | ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent |
| 784 | ** WAL mode. If the integer is -1, then it is overwritten with the current |
| 785 | ** WAL persistence setting. |
| 786 | ** |
| 787 | ** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] |
| 788 | ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the |
| 789 | ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting |
| 790 | ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the |
| 791 | ** xDeviceCharacteristics methods. The fourth parameter to |
| 792 | ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. |
| 793 | ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage |
| 794 | ** mode. If the integer is -1, then it is overwritten with the current |
| 795 | ** zero-damage mode setting. |
| 796 | ** |
| 797 | ** <li>[[SQLITE_FCNTL_OVERWRITE]] |
| 798 | ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening |
| 799 | ** a write transaction to indicate that, unless it is rolled back for some |
| 800 | ** reason, the entire database file will be overwritten by the current |
| 801 | ** transaction. This is used by VACUUM operations. |
| 802 | ** |
| 803 | ** <li>[[SQLITE_FCNTL_VFSNAME]] |
| 804 | ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of |
| 805 | ** all [VFSes] in the VFS stack. The names are of all VFS shims and the |
| 806 | ** final bottom-level VFS are written into memory obtained from |
| 807 | ** [sqlite3_malloc()] and the result is stored in the char* variable |
| 808 | ** that the fourth parameter of [sqlite3_file_control()] points to. |
| @@ -799,10 +809,34 @@ | |
| 809 | ** The caller is responsible for freeing the memory when done. As with |
| 810 | ** all file-control actions, there is no guarantee that this will actually |
| 811 | ** do anything. Callers should initialize the char* variable to a NULL |
| 812 | ** pointer in case this file-control is not implemented. This file-control |
| 813 | ** is intended for diagnostic use only. |
| 814 | ** |
| 815 | ** <li>[[SQLITE_FCNTL_PRAGMA]] |
| 816 | ** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] |
| 817 | ** file control is sent to the open [sqlite3_file] object corresponding |
| 818 | ** to the database file to which the pragma statement refers. ^The argument |
| 819 | ** to the [SQLITE_FCNTL_PRAGMA] file control is an array of |
| 820 | ** pointers to strings (char**) in which the second element of the array |
| 821 | ** is the name of the pragma and the third element is the argument to the |
| 822 | ** pragma or NULL if the pragma has no argument. ^The handler for an |
| 823 | ** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element |
| 824 | ** of the char** argument point to a string obtained from [sqlite3_mprintf()] |
| 825 | ** or the equivalent and that string will become the result of the pragma or |
| 826 | ** the error message if the pragma fails. ^If the |
| 827 | ** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal |
| 828 | ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] |
| 829 | ** file control returns [SQLITE_OK], then the parser assumes that the |
| 830 | ** VFS has handled the PRAGMA itself and the parser generates a no-op |
| 831 | ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns |
| 832 | ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means |
| 833 | ** that the VFS encountered an error while handling the [PRAGMA] and the |
| 834 | ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] |
| 835 | ** file control occurs at the beginning of pragma statement analysis and so |
| 836 | ** it is able to override built-in [PRAGMA] statements. |
| 837 | ** </ul> |
| 838 | */ |
| 839 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 840 | #define SQLITE_GET_LOCKPROXYFILE 2 |
| 841 | #define SQLITE_SET_LOCKPROXYFILE 3 |
| 842 | #define SQLITE_LAST_ERRNO 4 |
| @@ -813,10 +847,11 @@ | |
| 847 | #define SQLITE_FCNTL_WIN32_AV_RETRY 9 |
| 848 | #define SQLITE_FCNTL_PERSIST_WAL 10 |
| 849 | #define SQLITE_FCNTL_OVERWRITE 11 |
| 850 | #define SQLITE_FCNTL_VFSNAME 12 |
| 851 | #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 |
| 852 | #define SQLITE_FCNTL_PRAGMA 14 |
| 853 | |
| 854 | /* |
| 855 | ** CAPI3REF: Mutex Handle |
| 856 | ** |
| 857 | ** The mutex module within SQLite defines [sqlite3_mutex] to be an |
| @@ -4462,10 +4497,19 @@ | |
| 4497 | ** will be an absolute pathname, even if the filename used |
| 4498 | ** to open the database originally was a URI or relative pathname. |
| 4499 | */ |
| 4500 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); |
| 4501 | |
| 4502 | /* |
| 4503 | ** CAPI3REF: Determine if a database is read-only |
| 4504 | ** |
| 4505 | ** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N |
| 4506 | ** of connection D is read-only, 0 if it is read/write, or -1 if N is not |
| 4507 | ** the name of a database on connection D. |
| 4508 | */ |
| 4509 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); |
| 4510 | |
| 4511 | /* |
| 4512 | ** CAPI3REF: Find the next prepared statement |
| 4513 | ** |
| 4514 | ** ^This interface returns a pointer to the next [prepared statement] after |
| 4515 | ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL |
| @@ -6587,15 +6631,16 @@ | |
| 6631 | |
| 6632 | |
| 6633 | /* |
| 6634 | ** CAPI3REF: String Comparison |
| 6635 | ** |
| 6636 | ** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications |
| 6637 | ** and extensions to compare the contents of two buffers containing UTF-8 |
| 6638 | ** strings in a case-independent fashion, using the same definition of "case |
| 6639 | ** independence" that SQLite uses internally when comparing identifiers. |
| 6640 | */ |
| 6641 | SQLITE_API int sqlite3_stricmp(const char *, const char *); |
| 6642 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 6643 | |
| 6644 | /* |
| 6645 | ** CAPI3REF: Error Logging Interface |
| 6646 | ** |
| 6647 |