Fossil SCM
Update SQLite to pre-3.6.23.
Commit
1efd09ed4fa52d8f10d719c2e586e06cc36e3472
Parent
63d5a4fe25ee850…
2 files changed
+3890
-2401
+74
-8
+3890
-2401
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | -** version 3.6.22. By combining all the individual C code files into this | |
| 3 | +** version 3.6.23. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a one translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% are more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -305,10 +305,15 @@ | ||
| 305 | 305 | #endif |
| 306 | 306 | #ifdef HAVE_INTTYPES_H |
| 307 | 307 | #include <inttypes.h> |
| 308 | 308 | #endif |
| 309 | 309 | |
| 310 | +/* | |
| 311 | +** The number of samples of an index that SQLite takes in order to | |
| 312 | +** construct a histogram of the table content when running ANALYZE | |
| 313 | +** and with SQLITE_ENABLE_STAT2 | |
| 314 | +*/ | |
| 310 | 315 | #define SQLITE_INDEX_SAMPLES 10 |
| 311 | 316 | |
| 312 | 317 | /* |
| 313 | 318 | ** This macro is used to "hide" some ugliness in casting an int |
| 314 | 319 | ** value to a ptr value under the MSVC 64-bit compiler. Casting |
| @@ -369,27 +374,22 @@ | ||
| 369 | 374 | ** Exactly one of the following macros must be defined in order to |
| 370 | 375 | ** specify which memory allocation subsystem to use. |
| 371 | 376 | ** |
| 372 | 377 | ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() |
| 373 | 378 | ** SQLITE_MEMDEBUG // Debugging version of system malloc() |
| 374 | -** SQLITE_MEMORY_SIZE // internal allocator #1 | |
| 375 | -** SQLITE_MMAP_HEAP_SIZE // internal mmap() allocator | |
| 376 | -** SQLITE_POW2_MEMORY_SIZE // internal power-of-two allocator | |
| 379 | +** | |
| 380 | +** (Historical note: There used to be several other options, but we've | |
| 381 | +** pared it down to just these two.) | |
| 377 | 382 | ** |
| 378 | 383 | ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as |
| 379 | 384 | ** the default. |
| 380 | 385 | */ |
| 381 | -#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\ | |
| 382 | - defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\ | |
| 383 | - defined(SQLITE_POW2_MEMORY_SIZE)>1 | |
| 386 | +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1 | |
| 384 | 387 | # error "At most one of the following compile-time configuration options\ |
| 385 | - is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\ | |
| 386 | - SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE" | |
| 388 | + is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG" | |
| 387 | 389 | #endif |
| 388 | -#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\ | |
| 389 | - defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\ | |
| 390 | - defined(SQLITE_POW2_MEMORY_SIZE)==0 | |
| 390 | +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0 | |
| 391 | 391 | # define SQLITE_SYSTEM_MALLOC 1 |
| 392 | 392 | #endif |
| 393 | 393 | |
| 394 | 394 | /* |
| 395 | 395 | ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the |
| @@ -629,17 +629,17 @@ | ||
| 629 | 629 | ** |
| 630 | 630 | ** See also: [sqlite3_libversion()], |
| 631 | 631 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 632 | 632 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 633 | 633 | */ |
| 634 | -#define SQLITE_VERSION "3.6.22" | |
| 635 | -#define SQLITE_VERSION_NUMBER 3006022 | |
| 636 | -#define SQLITE_SOURCE_ID "2010-01-02 19:02:02 51f7ee844057086789dcfcdcba7daf45343cae62" | |
| 634 | +#define SQLITE_VERSION "3.6.23" | |
| 635 | +#define SQLITE_VERSION_NUMBER 3006023 | |
| 636 | +#define SQLITE_SOURCE_ID "2010-02-26 13:07:37 8f29490da62df07ea922b03cab52b6edd2669edb" | |
| 637 | 637 | |
| 638 | 638 | /* |
| 639 | 639 | ** CAPI3REF: Run-Time Library Version Numbers |
| 640 | -** KEYWORDS: sqlite3_version | |
| 640 | +** KEYWORDS: sqlite3_version, sqlite3_sourceid | |
| 641 | 641 | ** |
| 642 | 642 | ** These interfaces provide the same information as the [SQLITE_VERSION], |
| 643 | 643 | ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| 644 | 644 | ** but are associated with the library instead of the header file. ^(Cautious |
| 645 | 645 | ** programmers might include assert() statements in their application to |
| @@ -657,21 +657,48 @@ | ||
| 657 | 657 | ** macro. ^The sqlite3_libversion() function returns a pointer to the |
| 658 | 658 | ** to the sqlite3_version[] string constant. The sqlite3_libversion() |
| 659 | 659 | ** function is provided for use in DLLs since DLL users usually do not have |
| 660 | 660 | ** direct access to string constants within the DLL. ^The |
| 661 | 661 | ** sqlite3_libversion_number() function returns an integer equal to |
| 662 | -** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function a pointer | |
| 663 | -** to a string constant whose value is the same as the [SQLITE_SOURCE_ID] | |
| 664 | -** C preprocessor macro. | |
| 662 | +** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns | |
| 663 | +** a pointer to a string constant whose value is the same as the | |
| 664 | +** [SQLITE_SOURCE_ID] C preprocessor macro. | |
| 665 | 665 | ** |
| 666 | 666 | ** See also: [sqlite_version()] and [sqlite_source_id()]. |
| 667 | 667 | */ |
| 668 | 668 | SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; |
| 669 | 669 | SQLITE_API const char *sqlite3_libversion(void); |
| 670 | 670 | SQLITE_API const char *sqlite3_sourceid(void); |
| 671 | 671 | SQLITE_API int sqlite3_libversion_number(void); |
| 672 | 672 | |
| 673 | +/* | |
| 674 | +** CAPI3REF: Run-Time Library Compilation Options Diagnostics | |
| 675 | +** KEYWORDS: sqlite3_compileoption_used, sqlite3_compileoption_get | |
| 676 | +** | |
| 677 | +** ^The sqlite3_compileoption_used() function returns 0 or 1 | |
| 678 | +** indicating whether the specified option was defined at | |
| 679 | +** compile time. ^The SQLITE_ prefix may be omitted from the | |
| 680 | +** option name passed to sqlite3_compileoption_used(). | |
| 681 | +** | |
| 682 | +** ^The sqlite3_compileoption_get() function allows interating | |
| 683 | +** over the list of options that were defined at compile time by | |
| 684 | +** returning the N-th compile time option string. ^If N is out of range, | |
| 685 | +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ | |
| 686 | +** prefix is omitted from any strings returned by | |
| 687 | +** sqlite3_compileoption_get(). | |
| 688 | +** | |
| 689 | +** ^Support for the diagnostic functions sqlite3_compileoption_used() | |
| 690 | +** and sqlite3_compileoption_get() may be omitted by specifing the | |
| 691 | +** SQLITE_OMIT_COMPILEOPTION_DIAGS option at compile time. | |
| 692 | +** | |
| 693 | +** See also: [sqlite_compile_option_used()] and [sqlite_compile_option_get()]. | |
| 694 | +*/ | |
| 695 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS | |
| 696 | +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); | |
| 697 | +SQLITE_API const char *sqlite3_compileoption_get(int N); | |
| 698 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ | |
| 699 | + | |
| 673 | 700 | /* |
| 674 | 701 | ** CAPI3REF: Test To See If The Library Is Threadsafe |
| 675 | 702 | ** |
| 676 | 703 | ** ^The sqlite3_threadsafe() function returns zero if and only if |
| 677 | 704 | ** SQLite was compiled mutexing code omitted due to the |
| @@ -959,10 +986,11 @@ | ||
| 959 | 986 | #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ |
| 960 | 987 | #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ |
| 961 | 988 | #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ |
| 962 | 989 | #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ |
| 963 | 990 | #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ |
| 991 | +#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ | |
| 964 | 992 | #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ |
| 965 | 993 | #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ |
| 966 | 994 | #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ |
| 967 | 995 | #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ |
| 968 | 996 | #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ |
| @@ -1440,11 +1468,10 @@ | ||
| 1440 | 1468 | SQLITE_API int sqlite3_os_init(void); |
| 1441 | 1469 | SQLITE_API int sqlite3_os_end(void); |
| 1442 | 1470 | |
| 1443 | 1471 | /* |
| 1444 | 1472 | ** CAPI3REF: Configuring The SQLite Library |
| 1445 | -** EXPERIMENTAL | |
| 1446 | 1473 | ** |
| 1447 | 1474 | ** The sqlite3_config() interface is used to make global configuration |
| 1448 | 1475 | ** changes to SQLite in order to tune SQLite to the specific needs of |
| 1449 | 1476 | ** the application. The default configuration is recommended for most |
| 1450 | 1477 | ** applications and so this routine is usually not necessary. It is |
| @@ -1781,10 +1808,11 @@ | ||
| 1781 | 1808 | #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ |
| 1782 | 1809 | /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ |
| 1783 | 1810 | #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ |
| 1784 | 1811 | #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ |
| 1785 | 1812 | #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ |
| 1813 | +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ | |
| 1786 | 1814 | |
| 1787 | 1815 | /* |
| 1788 | 1816 | ** CAPI3REF: Configuration Options |
| 1789 | 1817 | ** EXPERIMENTAL |
| 1790 | 1818 | ** |
| @@ -4183,10 +4211,11 @@ | ||
| 4183 | 4211 | sqlite3*, |
| 4184 | 4212 | void*, |
| 4185 | 4213 | void(*)(void*,sqlite3*,int eTextRep,const void*) |
| 4186 | 4214 | ); |
| 4187 | 4215 | |
| 4216 | +#if SQLITE_HAS_CODEC | |
| 4188 | 4217 | /* |
| 4189 | 4218 | ** Specify the key for an encrypted database. This routine should be |
| 4190 | 4219 | ** called right after sqlite3_open(). |
| 4191 | 4220 | ** |
| 4192 | 4221 | ** The code to implement this API is not available in the public release |
| @@ -4208,10 +4237,29 @@ | ||
| 4208 | 4237 | SQLITE_API int sqlite3_rekey( |
| 4209 | 4238 | sqlite3 *db, /* Database to be rekeyed */ |
| 4210 | 4239 | const void *pKey, int nKey /* The new key */ |
| 4211 | 4240 | ); |
| 4212 | 4241 | |
| 4242 | +/* | |
| 4243 | +** Specify the activation key for a SEE database. Unless | |
| 4244 | +** activated, none of the SEE routines will work. | |
| 4245 | +*/ | |
| 4246 | +SQLITE_API void sqlite3_activate_see( | |
| 4247 | + const char *zPassPhrase /* Activation phrase */ | |
| 4248 | +); | |
| 4249 | +#endif | |
| 4250 | + | |
| 4251 | +#ifdef SQLITE_ENABLE_CEROD | |
| 4252 | +/* | |
| 4253 | +** Specify the activation key for a CEROD database. Unless | |
| 4254 | +** activated, none of the CEROD routines will work. | |
| 4255 | +*/ | |
| 4256 | +SQLITE_API void sqlite3_activate_cerod( | |
| 4257 | + const char *zPassPhrase /* Activation phrase */ | |
| 4258 | +); | |
| 4259 | +#endif | |
| 4260 | + | |
| 4213 | 4261 | /* |
| 4214 | 4262 | ** CAPI3REF: Suspend Execution For A Short Time |
| 4215 | 4263 | ** |
| 4216 | 4264 | ** ^The sqlite3_sleep() function causes the current thread to suspend execution |
| 4217 | 4265 | ** for at least a number of milliseconds specified in its parameter. |
| @@ -6169,10 +6217,28 @@ | ||
| 6169 | 6217 | ** case-indendent fashion, using the same definition of case independence |
| 6170 | 6218 | ** that SQLite uses internally when comparing identifiers. |
| 6171 | 6219 | */ |
| 6172 | 6220 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 6173 | 6221 | |
| 6222 | +/* | |
| 6223 | +** CAPI3REF: Error Logging Interface | |
| 6224 | +** EXPERIMENTAL | |
| 6225 | +** | |
| 6226 | +** ^The [sqlite3_log()] interface writes a message into the error log | |
| 6227 | +** established by the [SQLITE_CONFIG_ERRORLOG] option to [sqlite3_config()]. | |
| 6228 | +** ^If logging is enabled, the zFormat string and subsequent arguments are | |
| 6229 | +** passed through to [sqlite3_vmprintf()] to generate the final output string. | |
| 6230 | +** | |
| 6231 | +** The sqlite3_log() interface is intended for use by extensions such as | |
| 6232 | +** virtual tables, collating functions, and SQL functions. While there is | |
| 6233 | +** nothing to prevent an application from calling sqlite3_log(), doing so | |
| 6234 | +** is considered bad form. | |
| 6235 | +** | |
| 6236 | +** The zFormat string must not be NULL. | |
| 6237 | +*/ | |
| 6238 | +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); | |
| 6239 | + | |
| 6174 | 6240 | /* |
| 6175 | 6241 | ** Undo the hack that converts floating point types to integer for |
| 6176 | 6242 | ** builds on processors without floating point support. |
| 6177 | 6243 | */ |
| 6178 | 6244 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| @@ -6484,24 +6550,10 @@ | ||
| 6484 | 6550 | #define OMIT_TEMPDB 1 |
| 6485 | 6551 | #else |
| 6486 | 6552 | #define OMIT_TEMPDB 0 |
| 6487 | 6553 | #endif |
| 6488 | 6554 | |
| 6489 | -/* | |
| 6490 | -** If the following macro is set to 1, then NULL values are considered | |
| 6491 | -** distinct when determining whether or not two entries are the same | |
| 6492 | -** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL, | |
| 6493 | -** OCELOT, and Firebird all work. The SQL92 spec explicitly says this | |
| 6494 | -** is the way things are suppose to work. | |
| 6495 | -** | |
| 6496 | -** If the following macro is set to 0, the NULLs are indistinct for | |
| 6497 | -** a UNIQUE index. In this mode, you can only have a single NULL entry | |
| 6498 | -** for a column declared UNIQUE. This is the way Informix and SQL Server | |
| 6499 | -** work. | |
| 6500 | -*/ | |
| 6501 | -#define NULL_DISTINCT_FOR_UNIQUE 1 | |
| 6502 | - | |
| 6503 | 6555 | /* |
| 6504 | 6556 | ** The "file format" number is an integer that is incremented whenever |
| 6505 | 6557 | ** the VDBE-level file format changes. The following macros define the |
| 6506 | 6558 | ** the default file format for new databases and the maximum file format |
| 6507 | 6559 | ** that the library can read. |
| @@ -6509,10 +6561,14 @@ | ||
| 6509 | 6561 | #define SQLITE_MAX_FILE_FORMAT 4 |
| 6510 | 6562 | #ifndef SQLITE_DEFAULT_FILE_FORMAT |
| 6511 | 6563 | # define SQLITE_DEFAULT_FILE_FORMAT 1 |
| 6512 | 6564 | #endif |
| 6513 | 6565 | |
| 6566 | +/* | |
| 6567 | +** Determine whether triggers are recursive by default. This can be | |
| 6568 | +** changed at run-time using a pragma. | |
| 6569 | +*/ | |
| 6514 | 6570 | #ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS |
| 6515 | 6571 | # define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 |
| 6516 | 6572 | #endif |
| 6517 | 6573 | |
| 6518 | 6574 | /* |
| @@ -6753,11 +6809,10 @@ | ||
| 6753 | 6809 | */ |
| 6754 | 6810 | typedef struct AggInfo AggInfo; |
| 6755 | 6811 | typedef struct AuthContext AuthContext; |
| 6756 | 6812 | typedef struct AutoincInfo AutoincInfo; |
| 6757 | 6813 | typedef struct Bitvec Bitvec; |
| 6758 | -typedef struct RowSet RowSet; | |
| 6759 | 6814 | typedef struct CollSeq CollSeq; |
| 6760 | 6815 | typedef struct Column Column; |
| 6761 | 6816 | typedef struct Db Db; |
| 6762 | 6817 | typedef struct Schema Schema; |
| 6763 | 6818 | typedef struct Expr Expr; |
| @@ -6774,20 +6829,21 @@ | ||
| 6774 | 6829 | typedef struct Lookaside Lookaside; |
| 6775 | 6830 | typedef struct LookasideSlot LookasideSlot; |
| 6776 | 6831 | typedef struct Module Module; |
| 6777 | 6832 | typedef struct NameContext NameContext; |
| 6778 | 6833 | typedef struct Parse Parse; |
| 6834 | +typedef struct RowSet RowSet; | |
| 6779 | 6835 | typedef struct Savepoint Savepoint; |
| 6780 | 6836 | typedef struct Select Select; |
| 6781 | 6837 | typedef struct SrcList SrcList; |
| 6782 | 6838 | typedef struct StrAccum StrAccum; |
| 6783 | 6839 | typedef struct Table Table; |
| 6784 | 6840 | typedef struct TableLock TableLock; |
| 6785 | 6841 | typedef struct Token Token; |
| 6842 | +typedef struct Trigger Trigger; | |
| 6786 | 6843 | typedef struct TriggerPrg TriggerPrg; |
| 6787 | 6844 | typedef struct TriggerStep TriggerStep; |
| 6788 | -typedef struct Trigger Trigger; | |
| 6789 | 6845 | typedef struct UnpackedRecord UnpackedRecord; |
| 6790 | 6846 | typedef struct VTable VTable; |
| 6791 | 6847 | typedef struct Walker Walker; |
| 6792 | 6848 | typedef struct WherePlan WherePlan; |
| 6793 | 6849 | typedef struct WhereInfo WhereInfo; |
| @@ -6881,10 +6937,11 @@ | ||
| 6881 | 6937 | SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); |
| 6882 | 6938 | SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); |
| 6883 | 6939 | SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); |
| 6884 | 6940 | SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); |
| 6885 | 6941 | SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); |
| 6942 | +SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); | |
| 6886 | 6943 | SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); |
| 6887 | 6944 | SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); |
| 6888 | 6945 | SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); |
| 6889 | 6946 | SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); |
| 6890 | 6947 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); |
| @@ -7413,10 +7470,11 @@ | ||
| 7413 | 7470 | SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); |
| 7414 | 7471 | SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); |
| 7415 | 7472 | SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); |
| 7416 | 7473 | SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); |
| 7417 | 7474 | SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); |
| 7475 | +SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); | |
| 7418 | 7476 | SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); |
| 7419 | 7477 | SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int); |
| 7420 | 7478 | SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); |
| 7421 | 7479 | SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); |
| 7422 | 7480 | SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); |
| @@ -8186,19 +8244,19 @@ | ||
| 8186 | 8244 | #endif |
| 8187 | 8245 | }; |
| 8188 | 8246 | |
| 8189 | 8247 | /* |
| 8190 | 8248 | ** These macros can be used to test, set, or clear bits in the |
| 8191 | -** Db.flags field. | |
| 8249 | +** Db.pSchema->flags field. | |
| 8192 | 8250 | */ |
| 8193 | 8251 | #define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) |
| 8194 | 8252 | #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) |
| 8195 | 8253 | #define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) |
| 8196 | 8254 | #define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) |
| 8197 | 8255 | |
| 8198 | 8256 | /* |
| 8199 | -** Allowed values for the DB.flags field. | |
| 8257 | +** Allowed values for the DB.pSchema->flags field. | |
| 8200 | 8258 | ** |
| 8201 | 8259 | ** The DB_SchemaLoaded flag is set after the database schema has been |
| 8202 | 8260 | ** read into internal hash tables. |
| 8203 | 8261 | ** |
| 8204 | 8262 | ** DB_UnresetViews means that one or more views have column names that |
| @@ -8258,11 +8316,11 @@ | ||
| 8258 | 8316 | struct FuncDefHash { |
| 8259 | 8317 | FuncDef *a[23]; /* Hash table for functions */ |
| 8260 | 8318 | }; |
| 8261 | 8319 | |
| 8262 | 8320 | /* |
| 8263 | -** Each database is an instance of the following structure. | |
| 8321 | +** Each database connection is an instance of the following structure. | |
| 8264 | 8322 | ** |
| 8265 | 8323 | ** The sqlite.lastRowid records the last insert rowid generated by an |
| 8266 | 8324 | ** insert statement. Inserts on views do not affect its value. Each |
| 8267 | 8325 | ** trigger has its own context, so that lastRowid can be updated inside |
| 8268 | 8326 | ** triggers as usual. The previous value will be restored once the trigger |
| @@ -8297,10 +8355,11 @@ | ||
| 8297 | 8355 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 8298 | 8356 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 8299 | 8357 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 8300 | 8358 | u8 dfltJournalMode; /* Default journal mode for attached dbs */ |
| 8301 | 8359 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| 8360 | + u8 suppressErr; /* Do not issue error messages if true */ | |
| 8302 | 8361 | int nextPagesize; /* Pagesize after VACUUM if >0 */ |
| 8303 | 8362 | int nTable; /* Number of tables in the database */ |
| 8304 | 8363 | CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ |
| 8305 | 8364 | i64 lastRowid; /* ROWID of most recent insert (see above) */ |
| 8306 | 8365 | u32 magic; /* Magic number for detect library misuse */ |
| @@ -9873,10 +9932,12 @@ | ||
| 9873 | 9932 | int isMutexInit; /* True after mutexes are initialized */ |
| 9874 | 9933 | int isMallocInit; /* True after malloc is initialized */ |
| 9875 | 9934 | int isPCacheInit; /* True after malloc is initialized */ |
| 9876 | 9935 | sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ |
| 9877 | 9936 | int nRefInitMutex; /* Number of users of pInitMutex */ |
| 9937 | + void (*xLog)(void*,int,const char*); /* Function for logging */ | |
| 9938 | + void *pLogArg; /* First argument to xLog() */ | |
| 9878 | 9939 | }; |
| 9879 | 9940 | |
| 9880 | 9941 | /* |
| 9881 | 9942 | ** Context pointer passed down through the tree-walk. |
| 9882 | 9943 | */ |
| @@ -9914,20 +9975,31 @@ | ||
| 9914 | 9975 | while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ |
| 9915 | 9976 | } \ |
| 9916 | 9977 | } |
| 9917 | 9978 | |
| 9918 | 9979 | /* |
| 9919 | -** The SQLITE_CORRUPT_BKPT macro can be either a constant (for production | |
| 9920 | -** builds) or a function call (for debugging). If it is a function call, | |
| 9921 | -** it allows the operator to set a breakpoint at the spot where database | |
| 9922 | -** corruption is first detected. | |
| 9980 | +** The SQLITE_*_BKPT macros are substitutes for the error codes with | |
| 9981 | +** the same name but without the _BKPT suffix. These macros invoke | |
| 9982 | +** routines that report the line-number on which the error originated | |
| 9983 | +** using sqlite3_log(). The routines also provide a convenient place | |
| 9984 | +** to set a debugger breakpoint. | |
| 9923 | 9985 | */ |
| 9924 | -#ifdef SQLITE_DEBUG | |
| 9925 | -SQLITE_PRIVATE int sqlite3Corrupt(void); | |
| 9926 | -# define SQLITE_CORRUPT_BKPT sqlite3Corrupt() | |
| 9927 | -#else | |
| 9928 | -# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT | |
| 9986 | +SQLITE_PRIVATE int sqlite3CorruptError(int); | |
| 9987 | +SQLITE_PRIVATE int sqlite3MisuseError(int); | |
| 9988 | +SQLITE_PRIVATE int sqlite3CantopenError(int); | |
| 9989 | +#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) | |
| 9990 | +#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) | |
| 9991 | +#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) | |
| 9992 | + | |
| 9993 | + | |
| 9994 | +/* | |
| 9995 | +** FTS4 is really an extension for FTS3. It is enabled using the | |
| 9996 | +** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all | |
| 9997 | +** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3. | |
| 9998 | +*/ | |
| 9999 | +#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) | |
| 10000 | +# define SQLITE_ENABLE_FTS3 | |
| 9929 | 10001 | #endif |
| 9930 | 10002 | |
| 9931 | 10003 | /* |
| 9932 | 10004 | ** The ctype.h header is needed for non-ASCII systems. It is also |
| 9933 | 10005 | ** needed by FTS3 when FTS3 is included in the amalgamation. |
| @@ -10025,11 +10097,15 @@ | ||
| 10025 | 10097 | |
| 10026 | 10098 | SQLITE_PRIVATE int sqlite3StatusValue(int); |
| 10027 | 10099 | SQLITE_PRIVATE void sqlite3StatusAdd(int, int); |
| 10028 | 10100 | SQLITE_PRIVATE void sqlite3StatusSet(int, int); |
| 10029 | 10101 | |
| 10030 | -SQLITE_PRIVATE int sqlite3IsNaN(double); | |
| 10102 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 10103 | +SQLITE_PRIVATE int sqlite3IsNaN(double); | |
| 10104 | +#else | |
| 10105 | +# define sqlite3IsNaN(X) 0 | |
| 10106 | +#endif | |
| 10031 | 10107 | |
| 10032 | 10108 | SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); |
| 10033 | 10109 | #ifndef SQLITE_OMIT_TRACE |
| 10034 | 10110 | SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); |
| 10035 | 10111 | #endif |
| @@ -10042,11 +10118,10 @@ | ||
| 10042 | 10118 | #if defined(SQLITE_TEST) |
| 10043 | 10119 | SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); |
| 10044 | 10120 | #endif |
| 10045 | 10121 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...); |
| 10046 | 10122 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); |
| 10047 | -SQLITE_PRIVATE void sqlite3ErrorClear(Parse*); | |
| 10048 | 10123 | SQLITE_PRIVATE int sqlite3Dequote(char*); |
| 10049 | 10124 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); |
| 10050 | 10125 | SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); |
| 10051 | 10126 | SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); |
| 10052 | 10127 | SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); |
| @@ -10212,17 +10287,10 @@ | ||
| 10212 | 10287 | SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); |
| 10213 | 10288 | SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); |
| 10214 | 10289 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); |
| 10215 | 10290 | SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); |
| 10216 | 10291 | SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); |
| 10217 | -#ifdef SQLITE_DEBUG | |
| 10218 | -SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3*); | |
| 10219 | -SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3*); | |
| 10220 | -#else | |
| 10221 | -# define sqlite3SafetyOn(A) 0 | |
| 10222 | -# define sqlite3SafetyOff(A) 0 | |
| 10223 | -#endif | |
| 10224 | 10292 | SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); |
| 10225 | 10293 | SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); |
| 10226 | 10294 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); |
| 10227 | 10295 | |
| 10228 | 10296 | #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) |
| @@ -10754,10 +10822,12 @@ | ||
| 10754 | 10822 | 0, /* isMutexInit */ |
| 10755 | 10823 | 0, /* isMallocInit */ |
| 10756 | 10824 | 0, /* isPCacheInit */ |
| 10757 | 10825 | 0, /* pInitMutex */ |
| 10758 | 10826 | 0, /* nRefInitMutex */ |
| 10827 | + 0, /* xLog */ | |
| 10828 | + 0, /* pLogArg */ | |
| 10759 | 10829 | }; |
| 10760 | 10830 | |
| 10761 | 10831 | |
| 10762 | 10832 | /* |
| 10763 | 10833 | ** Hash table for global functions - functions common to all |
| @@ -10878,11 +10948,11 @@ | ||
| 10878 | 10948 | ** then this routine is not threadsafe. |
| 10879 | 10949 | */ |
| 10880 | 10950 | SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ |
| 10881 | 10951 | wsdStatInit; |
| 10882 | 10952 | if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ |
| 10883 | - return SQLITE_MISUSE; | |
| 10953 | + return SQLITE_MISUSE_BKPT; | |
| 10884 | 10954 | } |
| 10885 | 10955 | *pCurrent = wsdStat.nowValue[op]; |
| 10886 | 10956 | *pHighwater = wsdStat.mxValue[op]; |
| 10887 | 10957 | if( resetFlag ){ |
| 10888 | 10958 | wsdStat.mxValue[op] = wsdStat.nowValue[op]; |
| @@ -12007,12 +12077,12 @@ | ||
| 12007 | 12077 | FUNCTION(current_time, 0, 0, 0, ctimeFunc ), |
| 12008 | 12078 | FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), |
| 12009 | 12079 | FUNCTION(current_date, 0, 0, 0, cdateFunc ), |
| 12010 | 12080 | #else |
| 12011 | 12081 | STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc), |
| 12012 | - STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d", 0, currentTimeFunc), | |
| 12013 | - STR_FUNCTION(current_date, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), | |
| 12082 | + STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc), | |
| 12083 | + STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), | |
| 12014 | 12084 | #endif |
| 12015 | 12085 | }; |
| 12016 | 12086 | int i; |
| 12017 | 12087 | FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); |
| 12018 | 12088 | FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs); |
| @@ -12135,15 +12205,15 @@ | ||
| 12135 | 12205 | int flags, |
| 12136 | 12206 | int *pFlagsOut |
| 12137 | 12207 | ){ |
| 12138 | 12208 | int rc; |
| 12139 | 12209 | DO_OS_MALLOC_TEST(0); |
| 12140 | - /* 0x7f1f is a mask of SQLITE_OPEN_ flags that are valid to be passed | |
| 12210 | + /* 0x7f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed | |
| 12141 | 12211 | ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, |
| 12142 | 12212 | ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before |
| 12143 | 12213 | ** reaching the VFS. */ |
| 12144 | - rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f1f, pFlagsOut); | |
| 12214 | + rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f3f, pFlagsOut); | |
| 12145 | 12215 | assert( rc==SQLITE_OK || pFile->pMethods==0 ); |
| 12146 | 12216 | return rc; |
| 12147 | 12217 | } |
| 12148 | 12218 | SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
| 12149 | 12219 | return pVfs->xDelete(pVfs, zPath, dirSync); |
| @@ -12514,10 +12584,13 @@ | ||
| 12514 | 12584 | nByte = ROUND8(nByte); |
| 12515 | 12585 | p = malloc( nByte+8 ); |
| 12516 | 12586 | if( p ){ |
| 12517 | 12587 | p[0] = nByte; |
| 12518 | 12588 | p++; |
| 12589 | + }else{ | |
| 12590 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 12591 | + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); | |
| 12519 | 12592 | } |
| 12520 | 12593 | return (void *)p; |
| 12521 | 12594 | } |
| 12522 | 12595 | |
| 12523 | 12596 | /* |
| @@ -12532,10 +12605,22 @@ | ||
| 12532 | 12605 | sqlite3_int64 *p = (sqlite3_int64*)pPrior; |
| 12533 | 12606 | assert( pPrior!=0 ); |
| 12534 | 12607 | p--; |
| 12535 | 12608 | free(p); |
| 12536 | 12609 | } |
| 12610 | + | |
| 12611 | +/* | |
| 12612 | +** Report the allocated size of a prior return from xMalloc() | |
| 12613 | +** or xRealloc(). | |
| 12614 | +*/ | |
| 12615 | +static int sqlite3MemSize(void *pPrior){ | |
| 12616 | + sqlite3_int64 *p; | |
| 12617 | + if( pPrior==0 ) return 0; | |
| 12618 | + p = (sqlite3_int64*)pPrior; | |
| 12619 | + p--; | |
| 12620 | + return (int)p[0]; | |
| 12621 | +} | |
| 12537 | 12622 | |
| 12538 | 12623 | /* |
| 12539 | 12624 | ** Like realloc(). Resize an allocation previously obtained from |
| 12540 | 12625 | ** sqlite3MemMalloc(). |
| 12541 | 12626 | ** |
| @@ -12547,32 +12632,24 @@ | ||
| 12547 | 12632 | */ |
| 12548 | 12633 | static void *sqlite3MemRealloc(void *pPrior, int nByte){ |
| 12549 | 12634 | sqlite3_int64 *p = (sqlite3_int64*)pPrior; |
| 12550 | 12635 | assert( pPrior!=0 && nByte>0 ); |
| 12551 | 12636 | nByte = ROUND8(nByte); |
| 12552 | - p = (sqlite3_int64*)pPrior; | |
| 12553 | 12637 | p--; |
| 12554 | 12638 | p = realloc(p, nByte+8 ); |
| 12555 | 12639 | if( p ){ |
| 12556 | 12640 | p[0] = nByte; |
| 12557 | 12641 | p++; |
| 12642 | + }else{ | |
| 12643 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 12644 | + sqlite3_log(SQLITE_NOMEM, | |
| 12645 | + "failed memory resize %u to %u bytes", | |
| 12646 | + sqlite3MemSize(pPrior), nByte); | |
| 12558 | 12647 | } |
| 12559 | 12648 | return (void*)p; |
| 12560 | 12649 | } |
| 12561 | 12650 | |
| 12562 | -/* | |
| 12563 | -** Report the allocated size of a prior return from xMalloc() | |
| 12564 | -** or xRealloc(). | |
| 12565 | -*/ | |
| 12566 | -static int sqlite3MemSize(void *pPrior){ | |
| 12567 | - sqlite3_int64 *p; | |
| 12568 | - if( pPrior==0 ) return 0; | |
| 12569 | - p = (sqlite3_int64*)pPrior; | |
| 12570 | - p--; | |
| 12571 | - return (int)p[0]; | |
| 12572 | -} | |
| 12573 | - | |
| 12574 | 12651 | /* |
| 12575 | 12652 | ** Round up a request size to the next valid allocation size. |
| 12576 | 12653 | */ |
| 12577 | 12654 | static int sqlite3MemRoundup(int n){ |
| 12578 | 12655 | return ROUND8(n); |
| @@ -12825,10 +12902,35 @@ | ||
| 12825 | 12902 | ** Round up a request size to the next valid allocation size. |
| 12826 | 12903 | */ |
| 12827 | 12904 | static int sqlite3MemRoundup(int n){ |
| 12828 | 12905 | return ROUND8(n); |
| 12829 | 12906 | } |
| 12907 | + | |
| 12908 | +/* | |
| 12909 | +** Fill a buffer with pseudo-random bytes. This is used to preset | |
| 12910 | +** the content of a new memory allocation to unpredictable values and | |
| 12911 | +** to clear the content of a freed allocation to unpredictable values. | |
| 12912 | +*/ | |
| 12913 | +static void randomFill(char *pBuf, int nByte){ | |
| 12914 | + unsigned int x, y, r; | |
| 12915 | + x = SQLITE_PTR_TO_INT(pBuf); | |
| 12916 | + y = nByte | 1; | |
| 12917 | + while( nByte >= 4 ){ | |
| 12918 | + x = (x>>1) ^ (-(x&1) & 0xd0000001); | |
| 12919 | + y = y*1103515245 + 12345; | |
| 12920 | + r = x ^ y; | |
| 12921 | + *(int*)pBuf = r; | |
| 12922 | + pBuf += 4; | |
| 12923 | + nByte -= 4; | |
| 12924 | + } | |
| 12925 | + while( nByte-- > 0 ){ | |
| 12926 | + x = (x>>1) ^ (-(x&1) & 0xd0000001); | |
| 12927 | + y = y*1103515245 + 12345; | |
| 12928 | + r = x ^ y; | |
| 12929 | + *(pBuf++) = r & 0xff; | |
| 12930 | + } | |
| 12931 | +} | |
| 12830 | 12932 | |
| 12831 | 12933 | /* |
| 12832 | 12934 | ** Allocate nByte bytes of memory. |
| 12833 | 12935 | */ |
| 12834 | 12936 | static void *sqlite3MemMalloc(int nByte){ |
| @@ -12876,11 +12978,12 @@ | ||
| 12876 | 12978 | } |
| 12877 | 12979 | pHdr->iSize = nByte; |
| 12878 | 12980 | adjustStats(nByte, +1); |
| 12879 | 12981 | pInt = (int*)&pHdr[1]; |
| 12880 | 12982 | pInt[nReserve/sizeof(int)] = REARGUARD; |
| 12881 | - memset(pInt, 0x65, nReserve); | |
| 12983 | + randomFill((char*)pInt, nByte); | |
| 12984 | + memset(((char*)pInt)+nByte, 0x65, nReserve-nByte); | |
| 12882 | 12985 | p = (void*)pInt; |
| 12883 | 12986 | } |
| 12884 | 12987 | sqlite3_mutex_leave(mem.mutex); |
| 12885 | 12988 | return p; |
| 12886 | 12989 | } |
| @@ -12912,12 +13015,12 @@ | ||
| 12912 | 13015 | mem.pLast = pHdr->pPrev; |
| 12913 | 13016 | } |
| 12914 | 13017 | z = (char*)pBt; |
| 12915 | 13018 | z -= pHdr->nTitle; |
| 12916 | 13019 | adjustStats(pHdr->iSize, -1); |
| 12917 | - memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + | |
| 12918 | - pHdr->iSize + sizeof(int) + pHdr->nTitle); | |
| 13020 | + randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + | |
| 13021 | + pHdr->iSize + sizeof(int) + pHdr->nTitle); | |
| 12919 | 13022 | free(z); |
| 12920 | 13023 | sqlite3_mutex_leave(mem.mutex); |
| 12921 | 13024 | } |
| 12922 | 13025 | |
| 12923 | 13026 | /* |
| @@ -12936,11 +13039,11 @@ | ||
| 12936 | 13039 | pOldHdr = sqlite3MemsysGetHeader(pPrior); |
| 12937 | 13040 | pNew = sqlite3MemMalloc(nByte); |
| 12938 | 13041 | if( pNew ){ |
| 12939 | 13042 | memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize); |
| 12940 | 13043 | if( nByte>pOldHdr->iSize ){ |
| 12941 | - memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize); | |
| 13044 | + randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize); | |
| 12942 | 13045 | } |
| 12943 | 13046 | sqlite3MemFree(pPrior); |
| 12944 | 13047 | } |
| 12945 | 13048 | return pNew; |
| 12946 | 13049 | } |
| @@ -14017,11 +14120,15 @@ | ||
| 14017 | 14120 | /* Make sure mem5.aiFreelist[iLogsize] contains at least one free |
| 14018 | 14121 | ** block. If not, then split a block of the next larger power of |
| 14019 | 14122 | ** two in order to create a new free block of size iLogsize. |
| 14020 | 14123 | */ |
| 14021 | 14124 | for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){} |
| 14022 | - if( iBin>LOGMAX ) return 0; | |
| 14125 | + if( iBin>LOGMAX ){ | |
| 14126 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 14127 | + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte); | |
| 14128 | + return 0; | |
| 14129 | + } | |
| 14023 | 14130 | i = memsys5UnlinkFirst(iBin); |
| 14024 | 14131 | while( iBin>iLogsize ){ |
| 14025 | 14132 | int newSize; |
| 14026 | 14133 | |
| 14027 | 14134 | iBin--; |
| @@ -15294,11 +15401,20 @@ | ||
| 15294 | 15401 | struct sqlite3_mutex { |
| 15295 | 15402 | CRITICAL_SECTION mutex; /* Mutex controlling the lock */ |
| 15296 | 15403 | int id; /* Mutex type */ |
| 15297 | 15404 | int nRef; /* Number of enterances */ |
| 15298 | 15405 | DWORD owner; /* Thread holding this mutex */ |
| 15406 | +#ifdef SQLITE_DEBUG | |
| 15407 | + int trace; /* True to trace changes */ | |
| 15408 | +#endif | |
| 15299 | 15409 | }; |
| 15410 | +#define SQLITE_W32_MUTEX_INITIALIZER { 0 } | |
| 15411 | +#ifdef SQLITE_DEBUG | |
| 15412 | +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 } | |
| 15413 | +#else | |
| 15414 | +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0 } | |
| 15415 | +#endif | |
| 15300 | 15416 | |
| 15301 | 15417 | /* |
| 15302 | 15418 | ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, |
| 15303 | 15419 | ** or WinCE. Return false (zero) for Win95, Win98, or WinME. |
| 15304 | 15420 | ** |
| @@ -15337,21 +15453,32 @@ | ||
| 15337 | 15453 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are |
| 15338 | 15454 | ** intended for use only inside assert() statements. |
| 15339 | 15455 | */ |
| 15340 | 15456 | static int winMutexHeld(sqlite3_mutex *p){ |
| 15341 | 15457 | return p->nRef!=0 && p->owner==GetCurrentThreadId(); |
| 15458 | +} | |
| 15459 | +static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){ | |
| 15460 | + return p->nRef==0 || p->owner!=tid; | |
| 15342 | 15461 | } |
| 15343 | 15462 | static int winMutexNotheld(sqlite3_mutex *p){ |
| 15344 | - return p->nRef==0 || p->owner!=GetCurrentThreadId(); | |
| 15463 | + DWORD tid = GetCurrentThreadId(); | |
| 15464 | + return winMutexNotheld2(p, tid); | |
| 15345 | 15465 | } |
| 15346 | 15466 | #endif |
| 15347 | 15467 | |
| 15348 | 15468 | |
| 15349 | 15469 | /* |
| 15350 | 15470 | ** Initialize and deinitialize the mutex subsystem. |
| 15351 | 15471 | */ |
| 15352 | -static sqlite3_mutex winMutex_staticMutexes[6]; | |
| 15472 | +static sqlite3_mutex winMutex_staticMutexes[6] = { | |
| 15473 | + SQLITE3_MUTEX_INITIALIZER, | |
| 15474 | + SQLITE3_MUTEX_INITIALIZER, | |
| 15475 | + SQLITE3_MUTEX_INITIALIZER, | |
| 15476 | + SQLITE3_MUTEX_INITIALIZER, | |
| 15477 | + SQLITE3_MUTEX_INITIALIZER, | |
| 15478 | + SQLITE3_MUTEX_INITIALIZER | |
| 15479 | +}; | |
| 15353 | 15480 | static int winMutex_isInit = 0; |
| 15354 | 15481 | /* As winMutexInit() and winMutexEnd() are called as part |
| 15355 | 15482 | ** of the sqlite3_initialize and sqlite3_shutdown() |
| 15356 | 15483 | ** processing, the "interlocked" magic is probably not |
| 15357 | 15484 | ** strictly necessary. |
| @@ -15481,18 +15608,25 @@ | ||
| 15481 | 15608 | ** mutex must be exited an equal number of times before another thread |
| 15482 | 15609 | ** can enter. If the same thread tries to enter any other kind of mutex |
| 15483 | 15610 | ** more than once, the behavior is undefined. |
| 15484 | 15611 | */ |
| 15485 | 15612 | static void winMutexEnter(sqlite3_mutex *p){ |
| 15486 | - assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); | |
| 15613 | + DWORD tid = GetCurrentThreadId(); | |
| 15614 | + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); | |
| 15487 | 15615 | EnterCriticalSection(&p->mutex); |
| 15488 | - p->owner = GetCurrentThreadId(); | |
| 15616 | + p->owner = tid; | |
| 15489 | 15617 | p->nRef++; |
| 15618 | +#ifdef SQLITE_DEBUG | |
| 15619 | + if( p->trace ){ | |
| 15620 | + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); | |
| 15621 | + } | |
| 15622 | +#endif | |
| 15490 | 15623 | } |
| 15491 | 15624 | static int winMutexTry(sqlite3_mutex *p){ |
| 15625 | + DWORD tid = GetCurrentThreadId(); | |
| 15492 | 15626 | int rc = SQLITE_BUSY; |
| 15493 | - assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); | |
| 15627 | + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); | |
| 15494 | 15628 | /* |
| 15495 | 15629 | ** The sqlite3_mutex_try() routine is very rarely used, and when it |
| 15496 | 15630 | ** is used it is merely an optimization. So it is OK for it to always |
| 15497 | 15631 | ** fail. |
| 15498 | 15632 | ** |
| @@ -15502,16 +15636,21 @@ | ||
| 15502 | 15636 | ** For that reason, we will omit this optimization for now. See |
| 15503 | 15637 | ** ticket #2685. |
| 15504 | 15638 | */ |
| 15505 | 15639 | #if 0 |
| 15506 | 15640 | if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){ |
| 15507 | - p->owner = GetCurrentThreadId(); | |
| 15641 | + p->owner = tid; | |
| 15508 | 15642 | p->nRef++; |
| 15509 | 15643 | rc = SQLITE_OK; |
| 15510 | 15644 | } |
| 15511 | 15645 | #else |
| 15512 | 15646 | UNUSED_PARAMETER(p); |
| 15647 | +#endif | |
| 15648 | +#ifdef SQLITE_DEBUG | |
| 15649 | + if( rc==SQLITE_OK && p->trace ){ | |
| 15650 | + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); | |
| 15651 | + } | |
| 15513 | 15652 | #endif |
| 15514 | 15653 | return rc; |
| 15515 | 15654 | } |
| 15516 | 15655 | |
| 15517 | 15656 | /* |
| @@ -15519,15 +15658,21 @@ | ||
| 15519 | 15658 | ** previously entered by the same thread. The behavior |
| 15520 | 15659 | ** is undefined if the mutex is not currently entered or |
| 15521 | 15660 | ** is not currently allocated. SQLite will never do either. |
| 15522 | 15661 | */ |
| 15523 | 15662 | static void winMutexLeave(sqlite3_mutex *p){ |
| 15663 | + DWORD tid = GetCurrentThreadId(); | |
| 15524 | 15664 | assert( p->nRef>0 ); |
| 15525 | - assert( p->owner==GetCurrentThreadId() ); | |
| 15665 | + assert( p->owner==tid ); | |
| 15526 | 15666 | p->nRef--; |
| 15527 | 15667 | assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 15528 | 15668 | LeaveCriticalSection(&p->mutex); |
| 15669 | +#ifdef SQLITE_DEBUG | |
| 15670 | + if( p->trace ){ | |
| 15671 | + printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); | |
| 15672 | + } | |
| 15673 | +#endif | |
| 15529 | 15674 | } |
| 15530 | 15675 | |
| 15531 | 15676 | SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ |
| 15532 | 15677 | static sqlite3_mutex_methods sMutex = { |
| 15533 | 15678 | winMutexInit, |
| @@ -16868,11 +17013,13 @@ | ||
| 16868 | 17013 | } |
| 16869 | 17014 | i = prefix!=0; |
| 16870 | 17015 | while( nPad-- ) bufpt[i++] = '0'; |
| 16871 | 17016 | length = width; |
| 16872 | 17017 | } |
| 16873 | -#endif | |
| 17018 | +#else | |
| 17019 | + length = 0; | |
| 17020 | +#endif /* SQLITE_OMIT_FLOATING_POINT */ | |
| 16874 | 17021 | break; |
| 16875 | 17022 | case etSIZE: |
| 16876 | 17023 | *(va_arg(ap,int*)) = pAccum->nChar; |
| 16877 | 17024 | length = width = 0; |
| 16878 | 17025 | break; |
| @@ -17198,10 +17345,32 @@ | ||
| 17198 | 17345 | sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 17199 | 17346 | va_end(ap); |
| 17200 | 17347 | z = sqlite3StrAccumFinish(&acc); |
| 17201 | 17348 | return z; |
| 17202 | 17349 | } |
| 17350 | + | |
| 17351 | +/* | |
| 17352 | +** Format and write a message to the log if logging is enabled. | |
| 17353 | +*/ | |
| 17354 | +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){ | |
| 17355 | + void (*xLog)(void*, int, const char*); /* The global logger function */ | |
| 17356 | + void *pLogArg; /* First argument to the logger */ | |
| 17357 | + va_list ap; /* Vararg list */ | |
| 17358 | + char *zMsg; /* Complete log message */ | |
| 17359 | + | |
| 17360 | + xLog = sqlite3GlobalConfig.xLog; | |
| 17361 | + if( xLog ){ | |
| 17362 | + va_start(ap, zFormat); | |
| 17363 | + sqlite3BeginBenignMalloc(); | |
| 17364 | + zMsg = sqlite3_vmprintf(zFormat, ap); | |
| 17365 | + sqlite3EndBenignMalloc(); | |
| 17366 | + va_end(ap); | |
| 17367 | + pLogArg = sqlite3GlobalConfig.pLogArg; | |
| 17368 | + xLog(pLogArg, iErrCode, zMsg ? zMsg : zFormat); | |
| 17369 | + sqlite3_free(zMsg); | |
| 17370 | + } | |
| 17371 | +} | |
| 17203 | 17372 | |
| 17204 | 17373 | #if defined(SQLITE_DEBUG) |
| 17205 | 17374 | /* |
| 17206 | 17375 | ** A version of printf() that understands %lld. Used for debugging. |
| 17207 | 17376 | ** The printf() built into some versions of windows does not understand %lld |
| @@ -17721,10 +17890,11 @@ | ||
| 17721 | 17890 | int rc; /* Value to return */ |
| 17722 | 17891 | char *zErrMsg; /* Error message written here */ |
| 17723 | 17892 | u8 explain; /* True if EXPLAIN present on SQL command */ |
| 17724 | 17893 | u8 changeCntOn; /* True to update the change-counter */ |
| 17725 | 17894 | u8 expired; /* True if the VM needs to be recompiled */ |
| 17895 | + u8 runOnlyOnce; /* Automatically expire on reset */ | |
| 17726 | 17896 | u8 minWriteFileFormat; /* Minimum file format for writable database files */ |
| 17727 | 17897 | u8 inVtabMethod; /* See comments above */ |
| 17728 | 17898 | u8 usesStmtJournal; /* True if uses a statement journal */ |
| 17729 | 17899 | u8 readOnly; /* True for read-only statements */ |
| 17730 | 17900 | u8 isPrepareV2; /* True if prepared with prepare_v2() */ |
| @@ -17782,11 +17952,15 @@ | ||
| 17782 | 17952 | SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); |
| 17783 | 17953 | SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); |
| 17784 | 17954 | SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); |
| 17785 | 17955 | SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); |
| 17786 | 17956 | SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); |
| 17787 | -SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); | |
| 17957 | +#ifdef SQLITE_OMIT_FLOATING_POINT | |
| 17958 | +# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 | |
| 17959 | +#else | |
| 17960 | +SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); | |
| 17961 | +#endif | |
| 17788 | 17962 | SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); |
| 17789 | 17963 | SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); |
| 17790 | 17964 | SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); |
| 17791 | 17965 | SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); |
| 17792 | 17966 | SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int); |
| @@ -18388,10 +18562,11 @@ | ||
| 18388 | 18562 | static int dummy = 0; |
| 18389 | 18563 | dummy += x; |
| 18390 | 18564 | } |
| 18391 | 18565 | #endif |
| 18392 | 18566 | |
| 18567 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 18393 | 18568 | /* |
| 18394 | 18569 | ** Return true if the floating point value is Not a Number (NaN). |
| 18395 | 18570 | ** |
| 18396 | 18571 | ** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN. |
| 18397 | 18572 | ** Otherwise, we have our own implementation that works on most systems. |
| @@ -18432,10 +18607,11 @@ | ||
| 18432 | 18607 | rc = isnan(x); |
| 18433 | 18608 | #endif /* SQLITE_HAVE_ISNAN */ |
| 18434 | 18609 | testcase( rc ); |
| 18435 | 18610 | return rc; |
| 18436 | 18611 | } |
| 18612 | +#endif /* SQLITE_OMIT_FLOATING_POINT */ | |
| 18437 | 18613 | |
| 18438 | 18614 | /* |
| 18439 | 18615 | ** Compute a string length that is limited to what can be stored in |
| 18440 | 18616 | ** lower 30 bits of a 32-bit signed integer. |
| 18441 | 18617 | ** |
| @@ -18503,27 +18679,24 @@ | ||
| 18503 | 18679 | ** stored by this function into the database handle using sqlite3Error(). |
| 18504 | 18680 | ** Function sqlite3Error() should be used during statement execution |
| 18505 | 18681 | ** (sqlite3_step() etc.). |
| 18506 | 18682 | */ |
| 18507 | 18683 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ |
| 18684 | + char *zMsg; | |
| 18508 | 18685 | va_list ap; |
| 18509 | 18686 | sqlite3 *db = pParse->db; |
| 18510 | - pParse->nErr++; | |
| 18511 | - sqlite3DbFree(db, pParse->zErrMsg); | |
| 18512 | 18687 | va_start(ap, zFormat); |
| 18513 | - pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap); | |
| 18688 | + zMsg = sqlite3VMPrintf(db, zFormat, ap); | |
| 18514 | 18689 | va_end(ap); |
| 18515 | - pParse->rc = SQLITE_ERROR; | |
| 18516 | -} | |
| 18517 | - | |
| 18518 | -/* | |
| 18519 | -** Clear the error message in pParse, if any | |
| 18520 | -*/ | |
| 18521 | -SQLITE_PRIVATE void sqlite3ErrorClear(Parse *pParse){ | |
| 18522 | - sqlite3DbFree(pParse->db, pParse->zErrMsg); | |
| 18523 | - pParse->zErrMsg = 0; | |
| 18524 | - pParse->nErr = 0; | |
| 18690 | + if( db->suppressErr ){ | |
| 18691 | + sqlite3DbFree(db, zMsg); | |
| 18692 | + }else{ | |
| 18693 | + pParse->nErr++; | |
| 18694 | + sqlite3DbFree(db, pParse->zErrMsg); | |
| 18695 | + pParse->zErrMsg = zMsg; | |
| 18696 | + pParse->rc = SQLITE_ERROR; | |
| 18697 | + } | |
| 18525 | 18698 | } |
| 18526 | 18699 | |
| 18527 | 18700 | /* |
| 18528 | 18701 | ** Convert an SQL-style quoted string into a normal string by removing |
| 18529 | 18702 | ** the quote characters. The conversion is done in-place. If the |
| @@ -18612,10 +18785,11 @@ | ||
| 18612 | 18785 | return 0; |
| 18613 | 18786 | } |
| 18614 | 18787 | z += incr; |
| 18615 | 18788 | *realnum = 0; |
| 18616 | 18789 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18790 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 18617 | 18791 | if( *z=='.' ){ |
| 18618 | 18792 | z += incr; |
| 18619 | 18793 | if( !sqlite3Isdigit(*z) ) return 0; |
| 18620 | 18794 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18621 | 18795 | *realnum = 1; |
| @@ -18625,10 +18799,11 @@ | ||
| 18625 | 18799 | if( *z=='+' || *z=='-' ) z += incr; |
| 18626 | 18800 | if( !sqlite3Isdigit(*z) ) return 0; |
| 18627 | 18801 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18628 | 18802 | *realnum = 1; |
| 18629 | 18803 | } |
| 18804 | +#endif | |
| 18630 | 18805 | return *z==0; |
| 18631 | 18806 | } |
| 18632 | 18807 | |
| 18633 | 18808 | /* |
| 18634 | 18809 | ** The string z[] is an ASCII representation of a real number. |
| @@ -18786,10 +18961,13 @@ | ||
| 18786 | 18961 | static int compare2pow63(const char *zNum){ |
| 18787 | 18962 | int c; |
| 18788 | 18963 | c = memcmp(zNum,"922337203685477580",18)*10; |
| 18789 | 18964 | if( c==0 ){ |
| 18790 | 18965 | c = zNum[18] - '8'; |
| 18966 | + testcase( c==(-1) ); | |
| 18967 | + testcase( c==0 ); | |
| 18968 | + testcase( c==(+1) ); | |
| 18791 | 18969 | } |
| 18792 | 18970 | return c; |
| 18793 | 18971 | } |
| 18794 | 18972 | |
| 18795 | 18973 | |
| @@ -18822,10 +19000,13 @@ | ||
| 18822 | 19000 | while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */ |
| 18823 | 19001 | for(i=0; (c=zNum[i])>='0' && c<='9'; i++){ |
| 18824 | 19002 | v = v*10 + c - '0'; |
| 18825 | 19003 | } |
| 18826 | 19004 | *pNum = neg ? -v : v; |
| 19005 | + testcase( i==18 ); | |
| 19006 | + testcase( i==19 ); | |
| 19007 | + testcase( i==20 ); | |
| 18827 | 19008 | if( c!=0 || (i==0 && zStart==zNum) || i>19 ){ |
| 18828 | 19009 | /* zNum is empty or contains non-numeric text or is longer |
| 18829 | 19010 | ** than 19 digits (thus guaranting that it is too large) */ |
| 18830 | 19011 | return 0; |
| 18831 | 19012 | }else if( i<19 ){ |
| @@ -18865,10 +19046,13 @@ | ||
| 18865 | 19046 | if( negFlag ) neg = 1-neg; |
| 18866 | 19047 | while( *zNum=='0' ){ |
| 18867 | 19048 | zNum++; /* Skip leading zeros. Ticket #2454 */ |
| 18868 | 19049 | } |
| 18869 | 19050 | for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); } |
| 19051 | + testcase( i==18 ); | |
| 19052 | + testcase( i==19 ); | |
| 19053 | + testcase( i==20 ); | |
| 18870 | 19054 | if( i<19 ){ |
| 18871 | 19055 | /* Guaranteed to fit if less than 19 digits */ |
| 18872 | 19056 | return 1; |
| 18873 | 19057 | }else if( i>19 ){ |
| 18874 | 19058 | /* Guaranteed to be too big if greater than 19 digits */ |
| @@ -18905,13 +19089,15 @@ | ||
| 18905 | 19089 | /* The longest decimal representation of a 32 bit integer is 10 digits: |
| 18906 | 19090 | ** |
| 18907 | 19091 | ** 1234567890 |
| 18908 | 19092 | ** 2^31 -> 2147483648 |
| 18909 | 19093 | */ |
| 19094 | + testcase( i==10 ); | |
| 18910 | 19095 | if( i>10 ){ |
| 18911 | 19096 | return 0; |
| 18912 | 19097 | } |
| 19098 | + testcase( v-neg==2147483647 ); | |
| 18913 | 19099 | if( v-neg>2147483647 ){ |
| 18914 | 19100 | return 0; |
| 18915 | 19101 | } |
| 18916 | 19102 | if( neg ){ |
| 18917 | 19103 | v = -v; |
| @@ -19354,68 +19540,21 @@ | ||
| 19354 | 19540 | } |
| 19355 | 19541 | return zBlob; |
| 19356 | 19542 | } |
| 19357 | 19543 | #endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */ |
| 19358 | 19544 | |
| 19359 | - | |
| 19360 | -/* | |
| 19361 | -** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY. | |
| 19362 | -** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN | |
| 19363 | -** when this routine is called. | |
| 19364 | -** | |
| 19365 | -** This routine is called when entering an SQLite API. The SQLITE_MAGIC_OPEN | |
| 19366 | -** value indicates that the database connection passed into the API is | |
| 19367 | -** open and is not being used by another thread. By changing the value | |
| 19368 | -** to SQLITE_MAGIC_BUSY we indicate that the connection is in use. | |
| 19369 | -** sqlite3SafetyOff() below will change the value back to SQLITE_MAGIC_OPEN | |
| 19370 | -** when the API exits. | |
| 19371 | -** | |
| 19372 | -** This routine is a attempt to detect if two threads use the | |
| 19373 | -** same sqlite* pointer at the same time. There is a race | |
| 19374 | -** condition so it is possible that the error is not detected. | |
| 19375 | -** But usually the problem will be seen. The result will be an | |
| 19376 | -** error which can be used to debug the application that is | |
| 19377 | -** using SQLite incorrectly. | |
| 19378 | -** | |
| 19379 | -** Ticket #202: If db->magic is not a valid open value, take care not | |
| 19380 | -** to modify the db structure at all. It could be that db is a stale | |
| 19381 | -** pointer. In other words, it could be that there has been a prior | |
| 19382 | -** call to sqlite3_close(db) and db has been deallocated. And we do | |
| 19383 | -** not want to write into deallocated memory. | |
| 19384 | -*/ | |
| 19385 | -#ifdef SQLITE_DEBUG | |
| 19386 | -SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3 *db){ | |
| 19387 | - if( db->magic==SQLITE_MAGIC_OPEN ){ | |
| 19388 | - db->magic = SQLITE_MAGIC_BUSY; | |
| 19389 | - assert( sqlite3_mutex_held(db->mutex) ); | |
| 19390 | - return 0; | |
| 19391 | - }else if( db->magic==SQLITE_MAGIC_BUSY ){ | |
| 19392 | - db->magic = SQLITE_MAGIC_ERROR; | |
| 19393 | - db->u1.isInterrupted = 1; | |
| 19394 | - } | |
| 19395 | - return 1; | |
| 19396 | -} | |
| 19397 | -#endif | |
| 19398 | - | |
| 19399 | -/* | |
| 19400 | -** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN. | |
| 19401 | -** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY | |
| 19402 | -** when this routine is called. | |
| 19403 | -*/ | |
| 19404 | -#ifdef SQLITE_DEBUG | |
| 19405 | -SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3 *db){ | |
| 19406 | - if( db->magic==SQLITE_MAGIC_BUSY ){ | |
| 19407 | - db->magic = SQLITE_MAGIC_OPEN; | |
| 19408 | - assert( sqlite3_mutex_held(db->mutex) ); | |
| 19409 | - return 0; | |
| 19410 | - }else{ | |
| 19411 | - db->magic = SQLITE_MAGIC_ERROR; | |
| 19412 | - db->u1.isInterrupted = 1; | |
| 19413 | - return 1; | |
| 19414 | - } | |
| 19415 | -} | |
| 19416 | -#endif | |
| 19545 | +/* | |
| 19546 | +** Log an error that is an API call on a connection pointer that should | |
| 19547 | +** not have been used. The "type" of connection pointer is given as the | |
| 19548 | +** argument. The zType is a word like "NULL" or "closed" or "invalid". | |
| 19549 | +*/ | |
| 19550 | +static void logBadConnection(const char *zType){ | |
| 19551 | + sqlite3_log(SQLITE_MISUSE, | |
| 19552 | + "API call with %s database connection pointer", | |
| 19553 | + zType | |
| 19554 | + ); | |
| 19555 | +} | |
| 19417 | 19556 | |
| 19418 | 19557 | /* |
| 19419 | 19558 | ** Check to make sure we have a valid db pointer. This test is not |
| 19420 | 19559 | ** foolproof but it does provide some measure of protection against |
| 19421 | 19560 | ** misuse of the interface such as passing in db pointers that are |
| @@ -19429,17 +19568,20 @@ | ||
| 19429 | 19568 | ** open properly and is not fit for general use but which can be |
| 19430 | 19569 | ** used as an argument to sqlite3_errmsg() or sqlite3_close(). |
| 19431 | 19570 | */ |
| 19432 | 19571 | SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){ |
| 19433 | 19572 | u32 magic; |
| 19434 | - if( db==0 ) return 0; | |
| 19573 | + if( db==0 ){ | |
| 19574 | + logBadConnection("NULL"); | |
| 19575 | + return 0; | |
| 19576 | + } | |
| 19435 | 19577 | magic = db->magic; |
| 19436 | - if( magic!=SQLITE_MAGIC_OPEN | |
| 19437 | -#ifdef SQLITE_DEBUG | |
| 19438 | - && magic!=SQLITE_MAGIC_BUSY | |
| 19439 | -#endif | |
| 19440 | - ){ | |
| 19578 | + if( magic!=SQLITE_MAGIC_OPEN ){ | |
| 19579 | + if( sqlite3SafetyCheckSickOrOk(db) ){ | |
| 19580 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 19581 | + logBadConnection("unopened"); | |
| 19582 | + } | |
| 19441 | 19583 | return 0; |
| 19442 | 19584 | }else{ |
| 19443 | 19585 | return 1; |
| 19444 | 19586 | } |
| 19445 | 19587 | } |
| @@ -19446,12 +19588,17 @@ | ||
| 19446 | 19588 | SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ |
| 19447 | 19589 | u32 magic; |
| 19448 | 19590 | magic = db->magic; |
| 19449 | 19591 | if( magic!=SQLITE_MAGIC_SICK && |
| 19450 | 19592 | magic!=SQLITE_MAGIC_OPEN && |
| 19451 | - magic!=SQLITE_MAGIC_BUSY ) return 0; | |
| 19452 | - return 1; | |
| 19593 | + magic!=SQLITE_MAGIC_BUSY ){ | |
| 19594 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 19595 | + logBadConnection("invalid"); | |
| 19596 | + return 0; | |
| 19597 | + }else{ | |
| 19598 | + return 1; | |
| 19599 | + } | |
| 19453 | 19600 | } |
| 19454 | 19601 | |
| 19455 | 19602 | /************** End of util.c ************************************************/ |
| 19456 | 19603 | /************** Begin file hash.c ********************************************/ |
| 19457 | 19604 | /* |
| @@ -21365,10 +21512,15 @@ | ||
| 21365 | 21512 | # include <sys/param.h> |
| 21366 | 21513 | # include <sys/mount.h> |
| 21367 | 21514 | # endif |
| 21368 | 21515 | #endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
| 21369 | 21516 | |
| 21517 | +/* | |
| 21518 | +** Allowed values of unixFile.fsFlags | |
| 21519 | +*/ | |
| 21520 | +#define SQLITE_FSFLAGS_IS_MSDOS 0x1 | |
| 21521 | + | |
| 21370 | 21522 | /* |
| 21371 | 21523 | ** If we are to be thread-safe, include the pthreads header and define |
| 21372 | 21524 | ** the SQLITE_UNIX_THREADS macro. |
| 21373 | 21525 | */ |
| 21374 | 21526 | #if SQLITE_THREADSAFE |
| @@ -21431,10 +21583,13 @@ | ||
| 21431 | 21583 | UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ |
| 21432 | 21584 | int fileFlags; /* Miscellanous flags */ |
| 21433 | 21585 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 21434 | 21586 | int openFlags; /* The flags specified at open() */ |
| 21435 | 21587 | #endif |
| 21588 | +#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) | |
| 21589 | + unsigned fsFlags; /* cached details from statfs() */ | |
| 21590 | +#endif | |
| 21436 | 21591 | #if SQLITE_THREADSAFE && defined(__linux__) |
| 21437 | 21592 | pthread_t tid; /* The thread that "owns" this unixFile */ |
| 21438 | 21593 | #endif |
| 21439 | 21594 | #if OS_VXWORKS |
| 21440 | 21595 | int isDelete; /* Delete on close if true */ |
| @@ -22198,10 +22353,13 @@ | ||
| 22198 | 22353 | struct unixLockInfo { |
| 22199 | 22354 | struct unixLockKey lockKey; /* The lookup key */ |
| 22200 | 22355 | int cnt; /* Number of SHARED locks held */ |
| 22201 | 22356 | int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ |
| 22202 | 22357 | int nRef; /* Number of pointers to this structure */ |
| 22358 | +#if defined(SQLITE_ENABLE_LOCKING_STYLE) | |
| 22359 | + unsigned long long sharedByte; /* for AFP simulated shared lock */ | |
| 22360 | +#endif | |
| 22203 | 22361 | struct unixLockInfo *pNext; /* List of all unixLockInfo objects */ |
| 22204 | 22362 | struct unixLockInfo *pPrev; /* .... doubly linked */ |
| 22205 | 22363 | }; |
| 22206 | 22364 | |
| 22207 | 22365 | /* |
| @@ -22441,13 +22599,14 @@ | ||
| 22441 | 22599 | ** an ASCII 'S' character which also happens to be the first byte |
| 22442 | 22600 | ** in the header of every SQLite database. In this way, if there |
| 22443 | 22601 | ** is a race condition such that another thread has already populated |
| 22444 | 22602 | ** the first page of the database, no damage is done. |
| 22445 | 22603 | */ |
| 22446 | - if( statbuf.st_size==0 ){ | |
| 22604 | + if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){ | |
| 22447 | 22605 | rc = write(fd, "S", 1); |
| 22448 | 22606 | if( rc!=1 ){ |
| 22607 | + pFile->lastErrno = errno; | |
| 22449 | 22608 | return SQLITE_IOERR; |
| 22450 | 22609 | } |
| 22451 | 22610 | rc = fstat(fd, &statbuf); |
| 22452 | 22611 | if( rc!=0 ){ |
| 22453 | 22612 | pFile->lastErrno = errno; |
| @@ -22483,10 +22642,13 @@ | ||
| 22483 | 22642 | } |
| 22484 | 22643 | memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey)); |
| 22485 | 22644 | pLock->nRef = 1; |
| 22486 | 22645 | pLock->cnt = 0; |
| 22487 | 22646 | pLock->locktype = 0; |
| 22647 | +#if defined(SQLITE_ENABLE_LOCKING_STYLE) | |
| 22648 | + pLock->sharedByte = 0; | |
| 22649 | +#endif | |
| 22488 | 22650 | pLock->pNext = lockList; |
| 22489 | 22651 | pLock->pPrev = 0; |
| 22490 | 22652 | if( lockList ) lockList->pPrev = pLock; |
| 22491 | 22653 | lockList = pLock; |
| 22492 | 22654 | }else{ |
| @@ -22547,11 +22709,11 @@ | ||
| 22547 | 22709 | OSTRACE1("No-transfer, same thread\n"); |
| 22548 | 22710 | return SQLITE_OK; |
| 22549 | 22711 | } |
| 22550 | 22712 | if( pFile->locktype!=NO_LOCK ){ |
| 22551 | 22713 | /* We cannot change ownership while we are holding a lock! */ |
| 22552 | - return SQLITE_MISUSE; | |
| 22714 | + return SQLITE_MISUSE_BKPT; | |
| 22553 | 22715 | } |
| 22554 | 22716 | OSTRACE4("Transfer ownership of %d from %d to %d\n", |
| 22555 | 22717 | pFile->h, pFile->tid, hSelf); |
| 22556 | 22718 | pFile->tid = hSelf; |
| 22557 | 22719 | if (pFile->pLock != NULL) { |
| @@ -22613,66 +22775,10 @@ | ||
| 22613 | 22775 | |
| 22614 | 22776 | unixLeaveMutex(); |
| 22615 | 22777 | OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved); |
| 22616 | 22778 | |
| 22617 | 22779 | *pResOut = reserved; |
| 22618 | - return rc; | |
| 22619 | -} | |
| 22620 | - | |
| 22621 | -/* | |
| 22622 | -** Perform a file locking operation on a range of bytes in a file. | |
| 22623 | -** The "op" parameter should be one of F_RDLCK, F_WRLCK, or F_UNLCK. | |
| 22624 | -** Return 0 on success or -1 for failure. On failure, write the error | |
| 22625 | -** code into *pErrcode. | |
| 22626 | -** | |
| 22627 | -** If the SQLITE_WHOLE_FILE_LOCKING bit is clear, then only lock | |
| 22628 | -** the range of bytes on the locking page between SHARED_FIRST and | |
| 22629 | -** SHARED_SIZE. If SQLITE_WHOLE_FILE_LOCKING is set, then lock all | |
| 22630 | -** bytes from 0 up to but not including PENDING_BYTE, and all bytes | |
| 22631 | -** that follow SHARED_FIRST. | |
| 22632 | -** | |
| 22633 | -** In other words, of SQLITE_WHOLE_FILE_LOCKING if false (the historical | |
| 22634 | -** default case) then only lock a small range of bytes from SHARED_FIRST | |
| 22635 | -** through SHARED_FIRST+SHARED_SIZE-1. But if SQLITE_WHOLE_FILE_LOCKING is | |
| 22636 | -** true then lock every byte in the file except for PENDING_BYTE and | |
| 22637 | -** RESERVED_BYTE. | |
| 22638 | -** | |
| 22639 | -** SQLITE_WHOLE_FILE_LOCKING=true overlaps SQLITE_WHOLE_FILE_LOCKING=false | |
| 22640 | -** and so the locking schemes are compatible. One type of lock will | |
| 22641 | -** effectively exclude the other type. The reason for using the | |
| 22642 | -** SQLITE_WHOLE_FILE_LOCKING=true is that by indicating the full range | |
| 22643 | -** of bytes to be read or written, we give hints to NFS to help it | |
| 22644 | -** maintain cache coherency. On the other hand, whole file locking | |
| 22645 | -** is slower, so we don't want to use it except for NFS. | |
| 22646 | -*/ | |
| 22647 | -static int rangeLock(unixFile *pFile, int op, int *pErrcode){ | |
| 22648 | - struct flock lock; | |
| 22649 | - int rc; | |
| 22650 | - lock.l_type = op; | |
| 22651 | - lock.l_start = SHARED_FIRST; | |
| 22652 | - lock.l_whence = SEEK_SET; | |
| 22653 | - if( (pFile->fileFlags & SQLITE_WHOLE_FILE_LOCKING)==0 ){ | |
| 22654 | - lock.l_len = SHARED_SIZE; | |
| 22655 | - rc = fcntl(pFile->h, F_SETLK, &lock); | |
| 22656 | - *pErrcode = errno; | |
| 22657 | - }else{ | |
| 22658 | - lock.l_len = 0; | |
| 22659 | - rc = fcntl(pFile->h, F_SETLK, &lock); | |
| 22660 | - *pErrcode = errno; | |
| 22661 | - if( NEVER(op==F_UNLCK) || rc!=(-1) ){ | |
| 22662 | - lock.l_start = 0; | |
| 22663 | - lock.l_len = PENDING_BYTE; | |
| 22664 | - rc = fcntl(pFile->h, F_SETLK, &lock); | |
| 22665 | - if( ALWAYS(op!=F_UNLCK) && rc==(-1) ){ | |
| 22666 | - *pErrcode = errno; | |
| 22667 | - lock.l_type = F_UNLCK; | |
| 22668 | - lock.l_start = SHARED_FIRST; | |
| 22669 | - lock.l_len = 0; | |
| 22670 | - fcntl(pFile->h, F_SETLK, &lock); | |
| 22671 | - } | |
| 22672 | - } | |
| 22673 | - } | |
| 22674 | 22780 | return rc; |
| 22675 | 22781 | } |
| 22676 | 22782 | |
| 22677 | 22783 | /* |
| 22678 | 22784 | ** Lock the file with the lock specified by parameter locktype - one |
| @@ -22740,11 +22846,11 @@ | ||
| 22740 | 22846 | int rc = SQLITE_OK; |
| 22741 | 22847 | unixFile *pFile = (unixFile*)id; |
| 22742 | 22848 | struct unixLockInfo *pLock = pFile->pLock; |
| 22743 | 22849 | struct flock lock; |
| 22744 | 22850 | int s = 0; |
| 22745 | - int tErrno; | |
| 22851 | + int tErrno = 0; | |
| 22746 | 22852 | |
| 22747 | 22853 | assert( pFile ); |
| 22748 | 22854 | OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, |
| 22749 | 22855 | locktypeName(locktype), locktypeName(pFile->locktype), |
| 22750 | 22856 | locktypeName(pLock->locktype), pLock->cnt , getpid()); |
| @@ -22836,12 +22942,15 @@ | ||
| 22836 | 22942 | if( locktype==SHARED_LOCK ){ |
| 22837 | 22943 | assert( pLock->cnt==0 ); |
| 22838 | 22944 | assert( pLock->locktype==0 ); |
| 22839 | 22945 | |
| 22840 | 22946 | /* Now get the read-lock */ |
| 22841 | - s = rangeLock(pFile, F_RDLCK, &tErrno); | |
| 22842 | - | |
| 22947 | + lock.l_start = SHARED_FIRST; | |
| 22948 | + lock.l_len = SHARED_SIZE; | |
| 22949 | + if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){ | |
| 22950 | + tErrno = errno; | |
| 22951 | + } | |
| 22843 | 22952 | /* Drop the temporary PENDING lock */ |
| 22844 | 22953 | lock.l_start = PENDING_BYTE; |
| 22845 | 22954 | lock.l_len = 1L; |
| 22846 | 22955 | lock.l_type = F_UNLCK; |
| 22847 | 22956 | if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ |
| @@ -22877,20 +22986,21 @@ | ||
| 22877 | 22986 | assert( 0!=pFile->locktype ); |
| 22878 | 22987 | lock.l_type = F_WRLCK; |
| 22879 | 22988 | switch( locktype ){ |
| 22880 | 22989 | case RESERVED_LOCK: |
| 22881 | 22990 | lock.l_start = RESERVED_BYTE; |
| 22882 | - s = fcntl(pFile->h, F_SETLK, &lock); | |
| 22883 | - tErrno = errno; | |
| 22884 | 22991 | break; |
| 22885 | 22992 | case EXCLUSIVE_LOCK: |
| 22886 | - s = rangeLock(pFile, F_WRLCK, &tErrno); | |
| 22993 | + lock.l_start = SHARED_FIRST; | |
| 22994 | + lock.l_len = SHARED_SIZE; | |
| 22887 | 22995 | break; |
| 22888 | 22996 | default: |
| 22889 | 22997 | assert(0); |
| 22890 | 22998 | } |
| 22999 | + s = fcntl(pFile->h, F_SETLK, &lock); | |
| 22891 | 23000 | if( s==(-1) ){ |
| 23001 | + tErrno = errno; | |
| 22892 | 23002 | rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); |
| 22893 | 23003 | if( IS_LOCK_ERROR(rc) ){ |
| 22894 | 23004 | pFile->lastErrno = tErrno; |
| 22895 | 23005 | } |
| 22896 | 23006 | } |
| @@ -22976,17 +23086,23 @@ | ||
| 22976 | 23086 | ** Lower the locking level on file descriptor pFile to locktype. locktype |
| 22977 | 23087 | ** must be either NO_LOCK or SHARED_LOCK. |
| 22978 | 23088 | ** |
| 22979 | 23089 | ** If the locking level of the file descriptor is already at or below |
| 22980 | 23090 | ** the requested locking level, this routine is a no-op. |
| 23091 | +** | |
| 23092 | +** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED | |
| 23093 | +** the byte range is divided into 2 parts and the first part is unlocked then | |
| 23094 | +** set to a read lock, then the other part is simply unlocked. This works | |
| 23095 | +** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to | |
| 23096 | +** remove the write lock on a region when a read lock is set. | |
| 22981 | 23097 | */ |
| 22982 | -static int unixUnlock(sqlite3_file *id, int locktype){ | |
| 22983 | - unixFile *pFile = (unixFile*)id; /* The open file */ | |
| 22984 | - struct unixLockInfo *pLock; /* Structure describing current lock state */ | |
| 22985 | - struct flock lock; /* Information passed into fcntl() */ | |
| 22986 | - int rc = SQLITE_OK; /* Return code from this interface */ | |
| 22987 | - int h; /* The underlying file descriptor */ | |
| 23098 | +static int _posixUnlock(sqlite3_file *id, int locktype, int handleNFSUnlock){ | |
| 23099 | + unixFile *pFile = (unixFile*)id; | |
| 23100 | + struct unixLockInfo *pLock; | |
| 23101 | + struct flock lock; | |
| 23102 | + int rc = SQLITE_OK; | |
| 23103 | + int h; | |
| 22988 | 23104 | int tErrno; /* Error code from system call errors */ |
| 22989 | 23105 | |
| 22990 | 23106 | assert( pFile ); |
| 22991 | 23107 | OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype, |
| 22992 | 23108 | pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
| @@ -22994,11 +23110,11 @@ | ||
| 22994 | 23110 | assert( locktype<=SHARED_LOCK ); |
| 22995 | 23111 | if( pFile->locktype<=locktype ){ |
| 22996 | 23112 | return SQLITE_OK; |
| 22997 | 23113 | } |
| 22998 | 23114 | if( CHECK_THREADID(pFile) ){ |
| 22999 | - return SQLITE_MISUSE; | |
| 23115 | + return SQLITE_MISUSE_BKPT; | |
| 23000 | 23116 | } |
| 23001 | 23117 | unixEnterMutex(); |
| 23002 | 23118 | h = pFile->h; |
| 23003 | 23119 | pLock = pFile->pLock; |
| 23004 | 23120 | assert( pLock->cnt!=0 ); |
| @@ -23021,18 +23137,72 @@ | ||
| 23021 | 23137 | || pFile->dbUpdate==0 |
| 23022 | 23138 | || pFile->transCntrChng==1 ); |
| 23023 | 23139 | pFile->inNormalWrite = 0; |
| 23024 | 23140 | #endif |
| 23025 | 23141 | |
| 23026 | - | |
| 23142 | + /* downgrading to a shared lock on NFS involves clearing the write lock | |
| 23143 | + ** before establishing the readlock - to avoid a race condition we downgrade | |
| 23144 | + ** the lock in 2 blocks, so that part of the range will be covered by a | |
| 23145 | + ** write lock until the rest is covered by a read lock: | |
| 23146 | + ** 1: [WWWWW] | |
| 23147 | + ** 2: [....W] | |
| 23148 | + ** 3: [RRRRW] | |
| 23149 | + ** 4: [RRRR.] | |
| 23150 | + */ | |
| 23027 | 23151 | if( locktype==SHARED_LOCK ){ |
| 23028 | - if( rangeLock(pFile, F_RDLCK, &tErrno)==(-1) ){ | |
| 23029 | - rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); | |
| 23030 | - if( IS_LOCK_ERROR(rc) ){ | |
| 23031 | - pFile->lastErrno = tErrno; | |
| 23152 | + if( handleNFSUnlock ){ | |
| 23153 | + off_t divSize = SHARED_SIZE - 1; | |
| 23154 | + | |
| 23155 | + lock.l_type = F_UNLCK; | |
| 23156 | + lock.l_whence = SEEK_SET; | |
| 23157 | + lock.l_start = SHARED_FIRST; | |
| 23158 | + lock.l_len = divSize; | |
| 23159 | + if( fcntl(h, F_SETLK, &lock)==(-1) ){ | |
| 23160 | + int tErrno = errno; | |
| 23161 | + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); | |
| 23162 | + if( IS_LOCK_ERROR(rc) ){ | |
| 23163 | + pFile->lastErrno = tErrno; | |
| 23164 | + } | |
| 23165 | + goto end_unlock; | |
| 23032 | 23166 | } |
| 23033 | - goto end_unlock; | |
| 23167 | + lock.l_type = F_RDLCK; | |
| 23168 | + lock.l_whence = SEEK_SET; | |
| 23169 | + lock.l_start = SHARED_FIRST; | |
| 23170 | + lock.l_len = divSize; | |
| 23171 | + if( fcntl(h, F_SETLK, &lock)==(-1) ){ | |
| 23172 | + int tErrno = errno; | |
| 23173 | + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); | |
| 23174 | + if( IS_LOCK_ERROR(rc) ){ | |
| 23175 | + pFile->lastErrno = tErrno; | |
| 23176 | + } | |
| 23177 | + goto end_unlock; | |
| 23178 | + } | |
| 23179 | + lock.l_type = F_UNLCK; | |
| 23180 | + lock.l_whence = SEEK_SET; | |
| 23181 | + lock.l_start = SHARED_FIRST+divSize; | |
| 23182 | + lock.l_len = SHARED_SIZE-divSize; | |
| 23183 | + if( fcntl(h, F_SETLK, &lock)==(-1) ){ | |
| 23184 | + int tErrno = errno; | |
| 23185 | + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); | |
| 23186 | + if( IS_LOCK_ERROR(rc) ){ | |
| 23187 | + pFile->lastErrno = tErrno; | |
| 23188 | + } | |
| 23189 | + goto end_unlock; | |
| 23190 | + } | |
| 23191 | + }else{ | |
| 23192 | + lock.l_type = F_RDLCK; | |
| 23193 | + lock.l_whence = SEEK_SET; | |
| 23194 | + lock.l_start = SHARED_FIRST; | |
| 23195 | + lock.l_len = SHARED_SIZE; | |
| 23196 | + if( fcntl(h, F_SETLK, &lock)==(-1) ){ | |
| 23197 | + int tErrno = errno; | |
| 23198 | + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); | |
| 23199 | + if( IS_LOCK_ERROR(rc) ){ | |
| 23200 | + pFile->lastErrno = tErrno; | |
| 23201 | + } | |
| 23202 | + goto end_unlock; | |
| 23203 | + } | |
| 23034 | 23204 | } |
| 23035 | 23205 | } |
| 23036 | 23206 | lock.l_type = F_UNLCK; |
| 23037 | 23207 | lock.l_whence = SEEK_SET; |
| 23038 | 23208 | lock.l_start = PENDING_BYTE; |
| @@ -23094,10 +23264,21 @@ | ||
| 23094 | 23264 | end_unlock: |
| 23095 | 23265 | unixLeaveMutex(); |
| 23096 | 23266 | if( rc==SQLITE_OK ) pFile->locktype = locktype; |
| 23097 | 23267 | return rc; |
| 23098 | 23268 | } |
| 23269 | + | |
| 23270 | +/* | |
| 23271 | +** Lower the locking level on file descriptor pFile to locktype. locktype | |
| 23272 | +** must be either NO_LOCK or SHARED_LOCK. | |
| 23273 | +** | |
| 23274 | +** If the locking level of the file descriptor is already at or below | |
| 23275 | +** the requested locking level, this routine is a no-op. | |
| 23276 | +*/ | |
| 23277 | +static int unixUnlock(sqlite3_file *id, int locktype){ | |
| 23278 | + return _posixUnlock(id, locktype, 0); | |
| 23279 | +} | |
| 23099 | 23280 | |
| 23100 | 23281 | /* |
| 23101 | 23282 | ** This function performs the parts of the "close file" operation |
| 23102 | 23283 | ** common to all locking schemes. It closes the directory and file |
| 23103 | 23284 | ** handles, if they are valid, and sets all fields of the unixFile |
| @@ -23806,11 +23987,11 @@ | ||
| 23806 | 23987 | /* |
| 23807 | 23988 | ** The afpLockingContext structure contains all afp lock specific state |
| 23808 | 23989 | */ |
| 23809 | 23990 | typedef struct afpLockingContext afpLockingContext; |
| 23810 | 23991 | struct afpLockingContext { |
| 23811 | - unsigned long long sharedByte; | |
| 23992 | + int reserved; | |
| 23812 | 23993 | const char *dbPath; /* Name of the open file */ |
| 23813 | 23994 | }; |
| 23814 | 23995 | |
| 23815 | 23996 | struct ByteRangeLockPB2 |
| 23816 | 23997 | { |
| @@ -23883,13 +24064,18 @@ | ||
| 23883 | 24064 | |
| 23884 | 24065 | SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); |
| 23885 | 24066 | |
| 23886 | 24067 | assert( pFile ); |
| 23887 | 24068 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 24069 | + if( context->reserved ){ | |
| 24070 | + *pResOut = 1; | |
| 24071 | + return SQLITE_OK; | |
| 24072 | + } | |
| 24073 | + unixEnterMutex(); /* Because pFile->pLock is shared across threads */ | |
| 23888 | 24074 | |
| 23889 | 24075 | /* Check if a thread in this process holds such a lock */ |
| 23890 | - if( pFile->locktype>SHARED_LOCK ){ | |
| 24076 | + if( pFile->pLock->locktype>SHARED_LOCK ){ | |
| 23891 | 24077 | reserved = 1; |
| 23892 | 24078 | } |
| 23893 | 24079 | |
| 23894 | 24080 | /* Otherwise see if some other process holds it. |
| 23895 | 24081 | */ |
| @@ -23907,10 +24093,11 @@ | ||
| 23907 | 24093 | if( IS_LOCK_ERROR(lrc) ){ |
| 23908 | 24094 | rc=lrc; |
| 23909 | 24095 | } |
| 23910 | 24096 | } |
| 23911 | 24097 | |
| 24098 | + unixLeaveMutex(); | |
| 23912 | 24099 | OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved); |
| 23913 | 24100 | |
| 23914 | 24101 | *pResOut = reserved; |
| 23915 | 24102 | return rc; |
| 23916 | 24103 | } |
| @@ -23940,15 +24127,17 @@ | ||
| 23940 | 24127 | ** routine to lower a locking level. |
| 23941 | 24128 | */ |
| 23942 | 24129 | static int afpLock(sqlite3_file *id, int locktype){ |
| 23943 | 24130 | int rc = SQLITE_OK; |
| 23944 | 24131 | unixFile *pFile = (unixFile*)id; |
| 24132 | + struct unixLockInfo *pLock = pFile->pLock; | |
| 23945 | 24133 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 23946 | 24134 | |
| 23947 | 24135 | assert( pFile ); |
| 23948 | - OSTRACE5("LOCK %d %s was %s pid=%d (afp)\n", pFile->h, | |
| 23949 | - locktypeName(locktype), locktypeName(pFile->locktype), getpid()); | |
| 24136 | + OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h, | |
| 24137 | + locktypeName(locktype), locktypeName(pFile->locktype), | |
| 24138 | + locktypeName(pLock->locktype), pLock->cnt , getpid()); | |
| 23950 | 24139 | |
| 23951 | 24140 | /* If there is already a lock of this type or more restrictive on the |
| 23952 | 24141 | ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as |
| 23953 | 24142 | ** unixEnterMutex() hasn't been called yet. |
| 23954 | 24143 | */ |
| @@ -23957,10 +24146,13 @@ | ||
| 23957 | 24146 | locktypeName(locktype)); |
| 23958 | 24147 | return SQLITE_OK; |
| 23959 | 24148 | } |
| 23960 | 24149 | |
| 23961 | 24150 | /* Make sure the locking sequence is correct |
| 24151 | + ** (1) We never move from unlocked to anything higher than shared lock. | |
| 24152 | + ** (2) SQLite never explicitly requests a pendig lock. | |
| 24153 | + ** (3) A shared lock is always held when a reserve lock is requested. | |
| 23962 | 24154 | */ |
| 23963 | 24155 | assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); |
| 23964 | 24156 | assert( locktype!=PENDING_LOCK ); |
| 23965 | 24157 | assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); |
| 23966 | 24158 | |
| @@ -23972,10 +24164,36 @@ | ||
| 23972 | 24164 | */ |
| 23973 | 24165 | rc = transferOwnership(pFile); |
| 23974 | 24166 | if( rc!=SQLITE_OK ){ |
| 23975 | 24167 | unixLeaveMutex(); |
| 23976 | 24168 | return rc; |
| 24169 | + } | |
| 24170 | + pLock = pFile->pLock; | |
| 24171 | + | |
| 24172 | + /* If some thread using this PID has a lock via a different unixFile* | |
| 24173 | + ** handle that precludes the requested lock, return BUSY. | |
| 24174 | + */ | |
| 24175 | + if( (pFile->locktype!=pLock->locktype && | |
| 24176 | + (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) | |
| 24177 | + ){ | |
| 24178 | + rc = SQLITE_BUSY; | |
| 24179 | + goto afp_end_lock; | |
| 24180 | + } | |
| 24181 | + | |
| 24182 | + /* If a SHARED lock is requested, and some thread using this PID already | |
| 24183 | + ** has a SHARED or RESERVED lock, then increment reference counts and | |
| 24184 | + ** return SQLITE_OK. | |
| 24185 | + */ | |
| 24186 | + if( locktype==SHARED_LOCK && | |
| 24187 | + (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ | |
| 24188 | + assert( locktype==SHARED_LOCK ); | |
| 24189 | + assert( pFile->locktype==0 ); | |
| 24190 | + assert( pLock->cnt>0 ); | |
| 24191 | + pFile->locktype = SHARED_LOCK; | |
| 24192 | + pLock->cnt++; | |
| 24193 | + pFile->pOpen->nLock++; | |
| 24194 | + goto afp_end_lock; | |
| 23977 | 24195 | } |
| 23978 | 24196 | |
| 23979 | 24197 | /* A PENDING lock is needed before acquiring a SHARED lock and before |
| 23980 | 24198 | ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will |
| 23981 | 24199 | ** be released. |
| @@ -23993,19 +24211,23 @@ | ||
| 23993 | 24211 | |
| 23994 | 24212 | /* If control gets to this point, then actually go ahead and make |
| 23995 | 24213 | ** operating system calls for the specified lock. |
| 23996 | 24214 | */ |
| 23997 | 24215 | if( locktype==SHARED_LOCK ){ |
| 23998 | - int lk, lrc1, lrc2; | |
| 23999 | - int lrc1Errno = 0; | |
| 24216 | + int lrc1, lrc2, lrc1Errno; | |
| 24217 | + long lk, mask; | |
| 24000 | 24218 | |
| 24219 | + assert( pLock->cnt==0 ); | |
| 24220 | + assert( pLock->locktype==0 ); | |
| 24221 | + | |
| 24222 | + mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff; | |
| 24001 | 24223 | /* Now get the read-lock SHARED_LOCK */ |
| 24002 | 24224 | /* note that the quality of the randomness doesn't matter that much */ |
| 24003 | 24225 | lk = random(); |
| 24004 | - context->sharedByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); | |
| 24226 | + pLock->sharedByte = (lk & mask)%(SHARED_SIZE - 1); | |
| 24005 | 24227 | lrc1 = afpSetLock(context->dbPath, pFile, |
| 24006 | - SHARED_FIRST+context->sharedByte, 1, 1); | |
| 24228 | + SHARED_FIRST+pLock->sharedByte, 1, 1); | |
| 24007 | 24229 | if( IS_LOCK_ERROR(lrc1) ){ |
| 24008 | 24230 | lrc1Errno = pFile->lastErrno; |
| 24009 | 24231 | } |
| 24010 | 24232 | /* Drop the temporary PENDING lock */ |
| 24011 | 24233 | lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); |
| @@ -24020,11 +24242,16 @@ | ||
| 24020 | 24242 | } else if( lrc1 != SQLITE_OK ) { |
| 24021 | 24243 | rc = lrc1; |
| 24022 | 24244 | } else { |
| 24023 | 24245 | pFile->locktype = SHARED_LOCK; |
| 24024 | 24246 | pFile->pOpen->nLock++; |
| 24247 | + pLock->cnt = 1; | |
| 24025 | 24248 | } |
| 24249 | + }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ | |
| 24250 | + /* We are trying for an exclusive lock but another thread in this | |
| 24251 | + ** same process is still holding a shared lock. */ | |
| 24252 | + rc = SQLITE_BUSY; | |
| 24026 | 24253 | }else{ |
| 24027 | 24254 | /* The request was for a RESERVED or EXCLUSIVE lock. It is |
| 24028 | 24255 | ** assumed that there is a SHARED or greater lock on the file |
| 24029 | 24256 | ** already. |
| 24030 | 24257 | */ |
| @@ -24031,25 +24258,28 @@ | ||
| 24031 | 24258 | int failed = 0; |
| 24032 | 24259 | assert( 0!=pFile->locktype ); |
| 24033 | 24260 | if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) { |
| 24034 | 24261 | /* Acquire a RESERVED lock */ |
| 24035 | 24262 | failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); |
| 24263 | + if( !failed ){ | |
| 24264 | + context->reserved = 1; | |
| 24265 | + } | |
| 24036 | 24266 | } |
| 24037 | 24267 | if (!failed && locktype == EXCLUSIVE_LOCK) { |
| 24038 | 24268 | /* Acquire an EXCLUSIVE lock */ |
| 24039 | 24269 | |
| 24040 | 24270 | /* Remove the shared lock before trying the range. we'll need to |
| 24041 | 24271 | ** reestablish the shared lock if we can't get the afpUnlock |
| 24042 | 24272 | */ |
| 24043 | 24273 | if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + |
| 24044 | - context->sharedByte, 1, 0)) ){ | |
| 24274 | + pLock->sharedByte, 1, 0)) ){ | |
| 24045 | 24275 | int failed2 = SQLITE_OK; |
| 24046 | 24276 | /* now attemmpt to get the exclusive lock range */ |
| 24047 | 24277 | failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, |
| 24048 | 24278 | SHARED_SIZE, 1); |
| 24049 | 24279 | if( failed && (failed2 = afpSetLock(context->dbPath, pFile, |
| 24050 | - SHARED_FIRST + context->sharedByte, 1, 1)) ){ | |
| 24280 | + SHARED_FIRST + pLock->sharedByte, 1, 1)) ){ | |
| 24051 | 24281 | /* Can't reestablish the shared lock. Sqlite can't deal, this is |
| 24052 | 24282 | ** a critical I/O error |
| 24053 | 24283 | */ |
| 24054 | 24284 | rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : |
| 24055 | 24285 | SQLITE_IOERR_LOCK; |
| @@ -24064,12 +24294,14 @@ | ||
| 24064 | 24294 | } |
| 24065 | 24295 | } |
| 24066 | 24296 | |
| 24067 | 24297 | if( rc==SQLITE_OK ){ |
| 24068 | 24298 | pFile->locktype = locktype; |
| 24299 | + pLock->locktype = locktype; | |
| 24069 | 24300 | }else if( locktype==EXCLUSIVE_LOCK ){ |
| 24070 | 24301 | pFile->locktype = PENDING_LOCK; |
| 24302 | + pLock->locktype = PENDING_LOCK; | |
| 24071 | 24303 | } |
| 24072 | 24304 | |
| 24073 | 24305 | afp_end_lock: |
| 24074 | 24306 | unixLeaveMutex(); |
| 24075 | 24307 | OSTRACE4("LOCK %d %s %s (afp)\n", pFile->h, locktypeName(locktype), |
| @@ -24085,67 +24317,116 @@ | ||
| 24085 | 24317 | ** the requested locking level, this routine is a no-op. |
| 24086 | 24318 | */ |
| 24087 | 24319 | static int afpUnlock(sqlite3_file *id, int locktype) { |
| 24088 | 24320 | int rc = SQLITE_OK; |
| 24089 | 24321 | unixFile *pFile = (unixFile*)id; |
| 24090 | - afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext; | |
| 24322 | + struct unixLockInfo *pLock; | |
| 24323 | + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; | |
| 24324 | + int skipShared = 0; | |
| 24325 | +#ifdef SQLITE_TEST | |
| 24326 | + int h = pFile->h; | |
| 24327 | +#endif | |
| 24091 | 24328 | |
| 24092 | 24329 | assert( pFile ); |
| 24093 | - OSTRACE5("UNLOCK %d %d was %d pid=%d (afp)\n", pFile->h, locktype, | |
| 24094 | - pFile->locktype, getpid()); | |
| 24330 | + OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, locktype, | |
| 24331 | + pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); | |
| 24095 | 24332 | |
| 24096 | 24333 | assert( locktype<=SHARED_LOCK ); |
| 24097 | 24334 | if( pFile->locktype<=locktype ){ |
| 24098 | 24335 | return SQLITE_OK; |
| 24099 | 24336 | } |
| 24100 | 24337 | if( CHECK_THREADID(pFile) ){ |
| 24101 | - return SQLITE_MISUSE; | |
| 24338 | + return SQLITE_MISUSE_BKPT; | |
| 24102 | 24339 | } |
| 24103 | 24340 | unixEnterMutex(); |
| 24341 | + pLock = pFile->pLock; | |
| 24342 | + assert( pLock->cnt!=0 ); | |
| 24104 | 24343 | if( pFile->locktype>SHARED_LOCK ){ |
| 24344 | + assert( pLock->locktype==pFile->locktype ); | |
| 24345 | + SimulateIOErrorBenign(1); | |
| 24346 | + SimulateIOError( h=(-1) ) | |
| 24347 | + SimulateIOErrorBenign(0); | |
| 24348 | + | |
| 24349 | +#ifndef NDEBUG | |
| 24350 | + /* When reducing a lock such that other processes can start | |
| 24351 | + ** reading the database file again, make sure that the | |
| 24352 | + ** transaction counter was updated if any part of the database | |
| 24353 | + ** file changed. If the transaction counter is not updated, | |
| 24354 | + ** other connections to the same file might not realize that | |
| 24355 | + ** the file has changed and hence might not know to flush their | |
| 24356 | + ** cache. The use of a stale cache can lead to database corruption. | |
| 24357 | + */ | |
| 24358 | + assert( pFile->inNormalWrite==0 | |
| 24359 | + || pFile->dbUpdate==0 | |
| 24360 | + || pFile->transCntrChng==1 ); | |
| 24361 | + pFile->inNormalWrite = 0; | |
| 24362 | +#endif | |
| 24105 | 24363 | |
| 24106 | 24364 | if( pFile->locktype==EXCLUSIVE_LOCK ){ |
| 24107 | - rc = afpSetLock(pCtx->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); | |
| 24108 | - if( rc==SQLITE_OK && locktype==SHARED_LOCK ){ | |
| 24365 | + rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); | |
| 24366 | + if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1) ){ | |
| 24109 | 24367 | /* only re-establish the shared lock if necessary */ |
| 24110 | - int sharedLockByte = SHARED_FIRST+pCtx->sharedByte; | |
| 24111 | - rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 1); | |
| 24368 | + int sharedLockByte = SHARED_FIRST+pLock->sharedByte; | |
| 24369 | + rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1); | |
| 24370 | + } else { | |
| 24371 | + skipShared = 1; | |
| 24112 | 24372 | } |
| 24113 | 24373 | } |
| 24114 | 24374 | if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){ |
| 24115 | - rc = afpSetLock(pCtx->dbPath, pFile, PENDING_BYTE, 1, 0); | |
| 24116 | - } | |
| 24117 | - if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK ){ | |
| 24118 | - rc = afpSetLock(pCtx->dbPath, pFile, RESERVED_BYTE, 1, 0); | |
| 24119 | - } | |
| 24120 | - }else if( locktype==NO_LOCK ){ | |
| 24121 | - /* clear the shared lock */ | |
| 24122 | - int sharedLockByte = SHARED_FIRST+pCtx->sharedByte; | |
| 24123 | - rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 0); | |
| 24124 | - } | |
| 24125 | - | |
| 24126 | - if( rc==SQLITE_OK ){ | |
| 24127 | - if( locktype==NO_LOCK ){ | |
| 24128 | - struct unixOpenCnt *pOpen = pFile->pOpen; | |
| 24375 | + rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); | |
| 24376 | + } | |
| 24377 | + if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK && context->reserved ){ | |
| 24378 | + rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); | |
| 24379 | + if( !rc ){ | |
| 24380 | + context->reserved = 0; | |
| 24381 | + } | |
| 24382 | + } | |
| 24383 | + if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1)){ | |
| 24384 | + pLock->locktype = SHARED_LOCK; | |
| 24385 | + } | |
| 24386 | + } | |
| 24387 | + if( rc==SQLITE_OK && locktype==NO_LOCK ){ | |
| 24388 | + | |
| 24389 | + /* Decrement the shared lock counter. Release the lock using an | |
| 24390 | + ** OS call only when all threads in this same process have released | |
| 24391 | + ** the lock. | |
| 24392 | + */ | |
| 24393 | + unsigned long long sharedLockByte = SHARED_FIRST+pLock->sharedByte; | |
| 24394 | + pLock->cnt--; | |
| 24395 | + if( pLock->cnt==0 ){ | |
| 24396 | + SimulateIOErrorBenign(1); | |
| 24397 | + SimulateIOError( h=(-1) ) | |
| 24398 | + SimulateIOErrorBenign(0); | |
| 24399 | + if( !skipShared ){ | |
| 24400 | + rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); | |
| 24401 | + } | |
| 24402 | + if( !rc ){ | |
| 24403 | + pLock->locktype = NO_LOCK; | |
| 24404 | + pFile->locktype = NO_LOCK; | |
| 24405 | + } | |
| 24406 | + } | |
| 24407 | + if( rc==SQLITE_OK ){ | |
| 24408 | + struct unixOpenCnt *pOpen = pFile->pOpen; | |
| 24409 | + | |
| 24129 | 24410 | pOpen->nLock--; |
| 24130 | 24411 | assert( pOpen->nLock>=0 ); |
| 24131 | 24412 | if( pOpen->nLock==0 ){ |
| 24132 | 24413 | rc = closePendingFds(pFile); |
| 24133 | 24414 | } |
| 24134 | 24415 | } |
| 24135 | 24416 | } |
| 24417 | + | |
| 24136 | 24418 | unixLeaveMutex(); |
| 24137 | - if( rc==SQLITE_OK ){ | |
| 24138 | - pFile->locktype = locktype; | |
| 24139 | - } | |
| 24419 | + if( rc==SQLITE_OK ) pFile->locktype = locktype; | |
| 24140 | 24420 | return rc; |
| 24141 | 24421 | } |
| 24142 | 24422 | |
| 24143 | 24423 | /* |
| 24144 | 24424 | ** Close a file & cleanup AFP specific locking context |
| 24145 | 24425 | */ |
| 24146 | 24426 | static int afpClose(sqlite3_file *id) { |
| 24427 | + int rc = SQLITE_OK; | |
| 24147 | 24428 | if( id ){ |
| 24148 | 24429 | unixFile *pFile = (unixFile*)id; |
| 24149 | 24430 | afpUnlock(id, NO_LOCK); |
| 24150 | 24431 | unixEnterMutex(); |
| 24151 | 24432 | if( pFile->pOpen && pFile->pOpen->nLock ){ |
| @@ -24154,16 +24435,17 @@ | ||
| 24154 | 24435 | ** descriptor to pOpen->aPending. It will be automatically closed when |
| 24155 | 24436 | ** the last lock is cleared. |
| 24156 | 24437 | */ |
| 24157 | 24438 | setPendingFd(pFile); |
| 24158 | 24439 | } |
| 24440 | + releaseLockInfo(pFile->pLock); | |
| 24159 | 24441 | releaseOpenCnt(pFile->pOpen); |
| 24160 | 24442 | sqlite3_free(pFile->lockingContext); |
| 24161 | - closeUnixFile(id); | |
| 24443 | + rc = closeUnixFile(id); | |
| 24162 | 24444 | unixLeaveMutex(); |
| 24163 | 24445 | } |
| 24164 | - return SQLITE_OK; | |
| 24446 | + return rc; | |
| 24165 | 24447 | } |
| 24166 | 24448 | |
| 24167 | 24449 | #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ |
| 24168 | 24450 | /* |
| 24169 | 24451 | ** The code above is the AFP lock implementation. The code is specific |
| @@ -24172,10 +24454,33 @@ | ||
| 24172 | 24454 | ** VFS is not available. |
| 24173 | 24455 | ** |
| 24174 | 24456 | ********************* End of the AFP lock implementation ********************** |
| 24175 | 24457 | ******************************************************************************/ |
| 24176 | 24458 | |
| 24459 | +/****************************************************************************** | |
| 24460 | +*************************** Begin NFS Locking ********************************/ | |
| 24461 | + | |
| 24462 | +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE | |
| 24463 | +/* | |
| 24464 | + ** Lower the locking level on file descriptor pFile to locktype. locktype | |
| 24465 | + ** must be either NO_LOCK or SHARED_LOCK. | |
| 24466 | + ** | |
| 24467 | + ** If the locking level of the file descriptor is already at or below | |
| 24468 | + ** the requested locking level, this routine is a no-op. | |
| 24469 | + */ | |
| 24470 | +static int nfsUnlock(sqlite3_file *id, int locktype){ | |
| 24471 | + return _posixUnlock(id, locktype, 1); | |
| 24472 | +} | |
| 24473 | + | |
| 24474 | +#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ | |
| 24475 | +/* | |
| 24476 | +** The code above is the NFS lock implementation. The code is specific | |
| 24477 | +** to MacOSX and does not work on other unix platforms. No alternative | |
| 24478 | +** is available. | |
| 24479 | +** | |
| 24480 | +********************* End of the NFS lock implementation ********************** | |
| 24481 | +******************************************************************************/ | |
| 24177 | 24482 | |
| 24178 | 24483 | /****************************************************************************** |
| 24179 | 24484 | **************** Non-locking sqlite3_file methods ***************************** |
| 24180 | 24485 | ** |
| 24181 | 24486 | ** The next division contains implementations for all methods of the |
| @@ -24198,11 +24503,13 @@ | ||
| 24198 | 24503 | ** To avoid stomping the errno value on a failed read the lastErrno value |
| 24199 | 24504 | ** is set before returning. |
| 24200 | 24505 | */ |
| 24201 | 24506 | static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ |
| 24202 | 24507 | int got; |
| 24508 | +#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) | |
| 24203 | 24509 | i64 newOffset; |
| 24510 | +#endif | |
| 24204 | 24511 | TIMER_START; |
| 24205 | 24512 | #if defined(USE_PREAD) |
| 24206 | 24513 | got = pread(id->h, pBuf, cnt, offset); |
| 24207 | 24514 | SimulateIOError( got = -1 ); |
| 24208 | 24515 | #elif defined(USE_PREAD64) |
| @@ -24272,11 +24579,13 @@ | ||
| 24272 | 24579 | ** To avoid stomping the errno value on a failed write the lastErrno value |
| 24273 | 24580 | ** is set before returning. |
| 24274 | 24581 | */ |
| 24275 | 24582 | static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ |
| 24276 | 24583 | int got; |
| 24584 | +#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) | |
| 24277 | 24585 | i64 newOffset; |
| 24586 | +#endif | |
| 24278 | 24587 | TIMER_START; |
| 24279 | 24588 | #if defined(USE_PREAD) |
| 24280 | 24589 | got = pwrite(id->h, pBuf, cnt, offset); |
| 24281 | 24590 | #elif defined(USE_PREAD64) |
| 24282 | 24591 | got = pwrite64(id->h, pBuf, cnt, offset); |
| @@ -24466,10 +24775,15 @@ | ||
| 24466 | 24775 | ** It'd be better to detect fullfsync support once and avoid |
| 24467 | 24776 | ** the fcntl call every time sync is called. |
| 24468 | 24777 | */ |
| 24469 | 24778 | if( rc ) rc = fsync(fd); |
| 24470 | 24779 | |
| 24780 | +#elif defined(__APPLE__) | |
| 24781 | + /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly | |
| 24782 | + ** so currently we default to the macro that redefines fdatasync to fsync | |
| 24783 | + */ | |
| 24784 | + rc = fsync(fd); | |
| 24471 | 24785 | #else |
| 24472 | 24786 | rc = fdatasync(fd); |
| 24473 | 24787 | #if OS_VXWORKS |
| 24474 | 24788 | if( rc==-1 && errno==ENOTSUP ){ |
| 24475 | 24789 | rc = fsync(fd); |
| @@ -24800,27 +25114,10 @@ | ||
| 24800 | 25114 | afpUnlock, /* xUnlock method */ |
| 24801 | 25115 | afpCheckReservedLock /* xCheckReservedLock method */ |
| 24802 | 25116 | ) |
| 24803 | 25117 | #endif |
| 24804 | 25118 | |
| 24805 | -/* | |
| 24806 | -** The "Whole File Locking" finder returns the same set of methods as | |
| 24807 | -** the posix locking finder. But it also sets the SQLITE_WHOLE_FILE_LOCKING | |
| 24808 | -** flag to force the posix advisory locks to cover the whole file instead | |
| 24809 | -** of just a small span of bytes near the 1GiB boundary. Whole File Locking | |
| 24810 | -** is useful on NFS-mounted files since it helps NFS to maintain cache | |
| 24811 | -** coherency. But it is a detriment to other filesystems since it runs | |
| 24812 | -** slower. | |
| 24813 | -*/ | |
| 24814 | -static const sqlite3_io_methods *posixWflIoFinderImpl(const char*z, unixFile*p){ | |
| 24815 | - UNUSED_PARAMETER(z); | |
| 24816 | - p->fileFlags = SQLITE_WHOLE_FILE_LOCKING; | |
| 24817 | - return &posixIoMethods; | |
| 24818 | -} | |
| 24819 | -static const sqlite3_io_methods | |
| 24820 | - *(*const posixWflIoFinder)(const char*,unixFile *p) = posixWflIoFinderImpl; | |
| 24821 | - | |
| 24822 | 25119 | /* |
| 24823 | 25120 | ** The proxy locking method is a "super-method" in the sense that it |
| 24824 | 25121 | ** opens secondary file descriptors for the conch and lock files and |
| 24825 | 25122 | ** it uses proxy, dot-file, AFP, and flock() locking methods on those |
| 24826 | 25123 | ** secondary files. For this reason, the division that implements |
| @@ -24841,10 +25138,21 @@ | ||
| 24841 | 25138 | proxyUnlock, /* xUnlock method */ |
| 24842 | 25139 | proxyCheckReservedLock /* xCheckReservedLock method */ |
| 24843 | 25140 | ) |
| 24844 | 25141 | #endif |
| 24845 | 25142 | |
| 25143 | +/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */ | |
| 25144 | +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE | |
| 25145 | +IOMETHODS( | |
| 25146 | + nfsIoFinder, /* Finder function name */ | |
| 25147 | + nfsIoMethods, /* sqlite3_io_methods object name */ | |
| 25148 | + unixClose, /* xClose method */ | |
| 25149 | + unixLock, /* xLock method */ | |
| 25150 | + nfsUnlock, /* xUnlock method */ | |
| 25151 | + unixCheckReservedLock /* xCheckReservedLock method */ | |
| 25152 | +) | |
| 25153 | +#endif | |
| 24846 | 25154 | |
| 24847 | 25155 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 24848 | 25156 | /* |
| 24849 | 25157 | ** This "finder" function attempts to determine the best locking strategy |
| 24850 | 25158 | ** for the database file "filePath". It then returns the sqlite3_io_methods |
| @@ -24861,15 +25169,11 @@ | ||
| 24861 | 25169 | const sqlite3_io_methods *pMethods; /* Appropriate locking method */ |
| 24862 | 25170 | } aMap[] = { |
| 24863 | 25171 | { "hfs", &posixIoMethods }, |
| 24864 | 25172 | { "ufs", &posixIoMethods }, |
| 24865 | 25173 | { "afpfs", &afpIoMethods }, |
| 24866 | -#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB | |
| 24867 | 25174 | { "smbfs", &afpIoMethods }, |
| 24868 | -#else | |
| 24869 | - { "smbfs", &flockIoMethods }, | |
| 24870 | -#endif | |
| 24871 | 25175 | { "webdav", &nolockIoMethods }, |
| 24872 | 25176 | { 0, 0 } |
| 24873 | 25177 | }; |
| 24874 | 25178 | int i; |
| 24875 | 25179 | struct statfs fsInfo; |
| @@ -24898,12 +25202,15 @@ | ||
| 24898 | 25202 | lockInfo.l_len = 1; |
| 24899 | 25203 | lockInfo.l_start = 0; |
| 24900 | 25204 | lockInfo.l_whence = SEEK_SET; |
| 24901 | 25205 | lockInfo.l_type = F_RDLCK; |
| 24902 | 25206 | if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { |
| 24903 | - pNew->fileFlags = SQLITE_WHOLE_FILE_LOCKING; | |
| 24904 | - return &posixIoMethods; | |
| 25207 | + if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){ | |
| 25208 | + return &nfsIoMethods; | |
| 25209 | + } else { | |
| 25210 | + return &posixIoMethods; | |
| 25211 | + } | |
| 24905 | 25212 | }else{ |
| 24906 | 25213 | return &dotlockIoMethods; |
| 24907 | 25214 | } |
| 24908 | 25215 | } |
| 24909 | 25216 | static const sqlite3_io_methods |
| @@ -25010,11 +25317,15 @@ | ||
| 25010 | 25317 | ** zFilename remains valid until file is closed, to support */ |
| 25011 | 25318 | pNew->lockingContext = (void*)zFilename; |
| 25012 | 25319 | #endif |
| 25013 | 25320 | } |
| 25014 | 25321 | |
| 25015 | - if( pLockingStyle == &posixIoMethods ){ | |
| 25322 | + if( pLockingStyle == &posixIoMethods | |
| 25323 | +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE | |
| 25324 | + || pLockingStyle == &nfsIoMethods | |
| 25325 | +#endif | |
| 25326 | + ){ | |
| 25016 | 25327 | unixEnterMutex(); |
| 25017 | 25328 | rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); |
| 25018 | 25329 | if( rc!=SQLITE_OK ){ |
| 25019 | 25330 | /* If an error occured in findLockInfo(), close the file descriptor |
| 25020 | 25331 | ** immediately, before releasing the mutex. findLockInfo() may fail |
| @@ -25052,13 +25363,19 @@ | ||
| 25052 | 25363 | }else{ |
| 25053 | 25364 | /* NB: zFilename exists and remains valid until the file is closed |
| 25054 | 25365 | ** according to requirement F11141. So we do not need to make a |
| 25055 | 25366 | ** copy of the filename. */ |
| 25056 | 25367 | pCtx->dbPath = zFilename; |
| 25368 | + pCtx->reserved = 0; | |
| 25057 | 25369 | srandomdev(); |
| 25058 | 25370 | unixEnterMutex(); |
| 25059 | - rc = findLockInfo(pNew, NULL, &pNew->pOpen); | |
| 25371 | + rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); | |
| 25372 | + if( rc!=SQLITE_OK ){ | |
| 25373 | + sqlite3_free(pNew->lockingContext); | |
| 25374 | + close(h); | |
| 25375 | + h = -1; | |
| 25376 | + } | |
| 25060 | 25377 | unixLeaveMutex(); |
| 25061 | 25378 | } |
| 25062 | 25379 | } |
| 25063 | 25380 | #endif |
| 25064 | 25381 | |
| @@ -25103,10 +25420,12 @@ | ||
| 25103 | 25420 | #endif |
| 25104 | 25421 | |
| 25105 | 25422 | pNew->lastErrno = 0; |
| 25106 | 25423 | #if OS_VXWORKS |
| 25107 | 25424 | if( rc!=SQLITE_OK ){ |
| 25425 | + if( h>=0 ) close(h); | |
| 25426 | + h = -1; | |
| 25108 | 25427 | unlink(zFilename); |
| 25109 | 25428 | isDelete = 0; |
| 25110 | 25429 | } |
| 25111 | 25430 | pNew->isDelete = isDelete; |
| 25112 | 25431 | #endif |
| @@ -25146,11 +25465,11 @@ | ||
| 25146 | 25465 | #endif |
| 25147 | 25466 | OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname); |
| 25148 | 25467 | } |
| 25149 | 25468 | } |
| 25150 | 25469 | *pFd = fd; |
| 25151 | - return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN); | |
| 25470 | + return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN_BKPT); | |
| 25152 | 25471 | } |
| 25153 | 25472 | |
| 25154 | 25473 | /* |
| 25155 | 25474 | ** Create a temporary file name in zBuf. zBuf must be allocated |
| 25156 | 25475 | ** by the calling process and must be big enough to hold at least |
| @@ -25255,20 +25574,21 @@ | ||
| 25255 | 25574 | ** descriptor on the same path, fail, and return an error to SQLite. |
| 25256 | 25575 | ** |
| 25257 | 25576 | ** Even if a subsequent open() call does succeed, the consequences of |
| 25258 | 25577 | ** not searching for a resusable file descriptor are not dire. */ |
| 25259 | 25578 | if( 0==stat(zPath, &sStat) ){ |
| 25260 | - struct unixOpenCnt *pO; | |
| 25261 | - struct unixFileId id; | |
| 25262 | - id.dev = sStat.st_dev; | |
| 25263 | - id.ino = sStat.st_ino; | |
| 25579 | + struct unixOpenCnt *pOpen; | |
| 25264 | 25580 | |
| 25265 | 25581 | unixEnterMutex(); |
| 25266 | - for(pO=openList; pO && memcmp(&id, &pO->fileId, sizeof(id)); pO=pO->pNext); | |
| 25267 | - if( pO ){ | |
| 25582 | + pOpen = openList; | |
| 25583 | + while( pOpen && (pOpen->fileId.dev!=sStat.st_dev | |
| 25584 | + || pOpen->fileId.ino!=sStat.st_ino) ){ | |
| 25585 | + pOpen = pOpen->pNext; | |
| 25586 | + } | |
| 25587 | + if( pOpen ){ | |
| 25268 | 25588 | UnixUnusedFd **pp; |
| 25269 | - for(pp=&pO->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); | |
| 25589 | + for(pp=&pOpen->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); | |
| 25270 | 25590 | pUnused = *pp; |
| 25271 | 25591 | if( pUnused ){ |
| 25272 | 25592 | *pp = pUnused->pNext; |
| 25273 | 25593 | } |
| 25274 | 25594 | } |
| @@ -25318,10 +25638,13 @@ | ||
| 25318 | 25638 | int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); |
| 25319 | 25639 | int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); |
| 25320 | 25640 | int isCreate = (flags & SQLITE_OPEN_CREATE); |
| 25321 | 25641 | int isReadonly = (flags & SQLITE_OPEN_READONLY); |
| 25322 | 25642 | int isReadWrite = (flags & SQLITE_OPEN_READWRITE); |
| 25643 | +#if SQLITE_ENABLE_LOCKING_STYLE | |
| 25644 | + int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY); | |
| 25645 | +#endif | |
| 25323 | 25646 | |
| 25324 | 25647 | /* If creating a master or main-file journal, this function will open |
| 25325 | 25648 | ** a file-descriptor on the directory too. The first time unixSync() |
| 25326 | 25649 | ** is called the directory file descriptor will be fsync()ed and close()d. |
| 25327 | 25650 | */ |
| @@ -25405,11 +25728,11 @@ | ||
| 25405 | 25728 | flags |= SQLITE_OPEN_READONLY; |
| 25406 | 25729 | openFlags |= O_RDONLY; |
| 25407 | 25730 | fd = open(zName, openFlags, openMode); |
| 25408 | 25731 | } |
| 25409 | 25732 | if( fd<0 ){ |
| 25410 | - rc = SQLITE_CANTOPEN; | |
| 25733 | + rc = SQLITE_CANTOPEN_BKPT; | |
| 25411 | 25734 | goto open_finished; |
| 25412 | 25735 | } |
| 25413 | 25736 | } |
| 25414 | 25737 | assert( fd>=0 ); |
| 25415 | 25738 | if( pOutFlags ){ |
| @@ -25451,12 +25774,29 @@ | ||
| 25451 | 25774 | fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 25452 | 25775 | #endif |
| 25453 | 25776 | |
| 25454 | 25777 | noLock = eType!=SQLITE_OPEN_MAIN_DB; |
| 25455 | 25778 | |
| 25779 | + | |
| 25780 | +#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE | |
| 25781 | + struct statfs fsInfo; | |
| 25782 | + if( fstatfs(fd, &fsInfo) == -1 ){ | |
| 25783 | + ((unixFile*)pFile)->lastErrno = errno; | |
| 25784 | + if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */ | |
| 25785 | + close(fd); /* silently leak if fail, in error */ | |
| 25786 | + return SQLITE_IOERR_ACCESS; | |
| 25787 | + } | |
| 25788 | + if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { | |
| 25789 | + ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; | |
| 25790 | + } | |
| 25791 | +#endif | |
| 25792 | + | |
| 25793 | +#if SQLITE_ENABLE_LOCKING_STYLE | |
| 25456 | 25794 | #if SQLITE_PREFER_PROXY_LOCKING |
| 25457 | - if( zPath!=NULL && !noLock && pVfs->xOpen ){ | |
| 25795 | + isAutoProxy = 1; | |
| 25796 | +#endif | |
| 25797 | + if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){ | |
| 25458 | 25798 | char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); |
| 25459 | 25799 | int useProxy = 0; |
| 25460 | 25800 | |
| 25461 | 25801 | /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means |
| 25462 | 25802 | ** never use proxy, NULL means use proxy for non-local files only. */ |
| @@ -25484,10 +25824,18 @@ | ||
| 25484 | 25824 | } |
| 25485 | 25825 | if( useProxy ){ |
| 25486 | 25826 | rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); |
| 25487 | 25827 | if( rc==SQLITE_OK ){ |
| 25488 | 25828 | rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); |
| 25829 | + if( rc!=SQLITE_OK ){ | |
| 25830 | + /* Use unixClose to clean up the resources added in fillInUnixFile | |
| 25831 | + ** and clear all the structure's references. Specifically, | |
| 25832 | + ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op | |
| 25833 | + */ | |
| 25834 | + unixClose(pFile); | |
| 25835 | + return rc; | |
| 25836 | + } | |
| 25489 | 25837 | } |
| 25490 | 25838 | goto open_finished; |
| 25491 | 25839 | } |
| 25492 | 25840 | } |
| 25493 | 25841 | #endif |
| @@ -25604,11 +25952,11 @@ | ||
| 25604 | 25952 | if( zPath[0]=='/' ){ |
| 25605 | 25953 | sqlite3_snprintf(nOut, zOut, "%s", zPath); |
| 25606 | 25954 | }else{ |
| 25607 | 25955 | int nCwd; |
| 25608 | 25956 | if( getcwd(zOut, nOut-1)==0 ){ |
| 25609 | - return SQLITE_CANTOPEN; | |
| 25957 | + return SQLITE_CANTOPEN_BKPT; | |
| 25610 | 25958 | } |
| 25611 | 25959 | nCwd = (int)strlen(zOut); |
| 25612 | 25960 | sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath); |
| 25613 | 25961 | } |
| 25614 | 25962 | return SQLITE_OK; |
| @@ -25911,15 +26259,10 @@ | ||
| 25911 | 26259 | ** The proxy file - a single-byte file used for all advisory file locks |
| 25912 | 26260 | ** normally taken on the database file. This allows for safe sharing |
| 25913 | 26261 | ** of the database file for multiple readers and writers on the same |
| 25914 | 26262 | ** host (the conch ensures that they all use the same local lock file). |
| 25915 | 26263 | ** |
| 25916 | -** There is a third file - the host ID file - used as a persistent record | |
| 25917 | -** of a unique identifier for the host, a 128-byte unique host id file | |
| 25918 | -** in the path defined by the HOSTIDPATH macro (default value is | |
| 25919 | -** /Library/Caches/.com.apple.sqliteConchHostId). | |
| 25920 | -** | |
| 25921 | 26264 | ** Requesting the lock proxy does not immediately take the conch, it is |
| 25922 | 26265 | ** only taken when the first request to lock database file is made. |
| 25923 | 26266 | ** This matches the semantics of the traditional locking behavior, where |
| 25924 | 26267 | ** opening a connection to a database file does not take a lock on it. |
| 25925 | 26268 | ** The shared lock and an open file descriptor are maintained until |
| @@ -25941,14 +26284,10 @@ | ||
| 25941 | 26284 | ** SQLITE_PROXY_DEBUG |
| 25942 | 26285 | ** |
| 25943 | 26286 | ** Enables the logging of error messages during host id file |
| 25944 | 26287 | ** retrieval and creation |
| 25945 | 26288 | ** |
| 25946 | -** HOSTIDPATH | |
| 25947 | -** | |
| 25948 | -** Overrides the default host ID file path location | |
| 25949 | -** | |
| 25950 | 26289 | ** LOCKPROXYDIR |
| 25951 | 26290 | ** |
| 25952 | 26291 | ** Overrides the default directory used for lock proxy files that |
| 25953 | 26292 | ** are named automatically via the ":auto:" setting |
| 25954 | 26293 | ** |
| @@ -25969,15 +26308,10 @@ | ||
| 25969 | 26308 | /* |
| 25970 | 26309 | ** Proxy locking is only available on MacOSX |
| 25971 | 26310 | */ |
| 25972 | 26311 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 25973 | 26312 | |
| 25974 | -#ifdef SQLITE_TEST | |
| 25975 | -/* simulate multiple hosts by creating unique hostid file paths */ | |
| 25976 | -SQLITE_API int sqlite3_hostid_num = 0; | |
| 25977 | -#endif | |
| 25978 | - | |
| 25979 | 26313 | /* |
| 25980 | 26314 | ** The proxyLockingContext has the path and file structures for the remote |
| 25981 | 26315 | ** and local proxy files in it |
| 25982 | 26316 | */ |
| 25983 | 26317 | typedef struct proxyLockingContext proxyLockingContext; |
| @@ -25985,138 +26319,20 @@ | ||
| 25985 | 26319 | unixFile *conchFile; /* Open conch file */ |
| 25986 | 26320 | char *conchFilePath; /* Name of the conch file */ |
| 25987 | 26321 | unixFile *lockProxy; /* Open proxy lock file */ |
| 25988 | 26322 | char *lockProxyPath; /* Name of the proxy lock file */ |
| 25989 | 26323 | char *dbPath; /* Name of the open file */ |
| 25990 | - int conchHeld; /* True if the conch is currently held */ | |
| 26324 | + int conchHeld; /* 1 if the conch is held, -1 if lockless */ | |
| 25991 | 26325 | void *oldLockingContext; /* Original lockingcontext to restore on close */ |
| 25992 | 26326 | sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ |
| 25993 | 26327 | }; |
| 25994 | 26328 | |
| 25995 | -/* HOSTIDLEN and CONCHLEN both include space for the string | |
| 25996 | -** terminating nul | |
| 25997 | -*/ | |
| 25998 | -#define HOSTIDLEN 128 | |
| 25999 | -#define CONCHLEN (MAXPATHLEN+HOSTIDLEN+1) | |
| 26000 | -#ifndef HOSTIDPATH | |
| 26001 | -# define HOSTIDPATH "/Library/Caches/.com.apple.sqliteConchHostId" | |
| 26002 | -#endif | |
| 26003 | - | |
| 26004 | -/* basically a copy of unixRandomness with different | |
| 26005 | -** test behavior built in */ | |
| 26006 | -static int proxyGenerateHostID(char *pHostID){ | |
| 26007 | - int pid, fd, len; | |
| 26008 | - unsigned char *key = (unsigned char *)pHostID; | |
| 26009 | - | |
| 26010 | - memset(key, 0, HOSTIDLEN); | |
| 26011 | - len = 0; | |
| 26012 | - fd = open("/dev/urandom", O_RDONLY); | |
| 26013 | - if( fd>=0 ){ | |
| 26014 | - len = read(fd, key, HOSTIDLEN); | |
| 26015 | - close(fd); /* silently leak the fd if it fails */ | |
| 26016 | - } | |
| 26017 | - if( len < HOSTIDLEN ){ | |
| 26018 | - time_t t; | |
| 26019 | - time(&t); | |
| 26020 | - memcpy(key, &t, sizeof(t)); | |
| 26021 | - pid = getpid(); | |
| 26022 | - memcpy(&key[sizeof(t)], &pid, sizeof(pid)); | |
| 26023 | - } | |
| 26024 | - | |
| 26025 | -#ifdef MAKE_PRETTY_HOSTID | |
| 26026 | - { | |
| 26027 | - int i; | |
| 26028 | - /* filter the bytes into printable ascii characters and NUL terminate */ | |
| 26029 | - key[(HOSTIDLEN-1)] = 0x00; | |
| 26030 | - for( i=0; i<(HOSTIDLEN-1); i++ ){ | |
| 26031 | - unsigned char pa = key[i]&0x7F; | |
| 26032 | - if( pa<0x20 ){ | |
| 26033 | - key[i] = (key[i]&0x80 == 0x80) ? pa+0x40 : pa+0x20; | |
| 26034 | - }else if( pa==0x7F ){ | |
| 26035 | - key[i] = (key[i]&0x80 == 0x80) ? pa=0x20 : pa+0x7E; | |
| 26036 | - } | |
| 26037 | - } | |
| 26038 | - } | |
| 26039 | -#endif | |
| 26040 | - return SQLITE_OK; | |
| 26041 | -} | |
| 26042 | - | |
| 26043 | -/* writes the host id path to path, path should be an pre-allocated buffer | |
| 26044 | -** with enough space for a path | |
| 26045 | -*/ | |
| 26046 | -static void proxyGetHostIDPath(char *path, size_t len){ | |
| 26047 | - strlcpy(path, HOSTIDPATH, len); | |
| 26048 | -#ifdef SQLITE_TEST | |
| 26049 | - if( sqlite3_hostid_num>0 ){ | |
| 26050 | - char suffix[2] = "1"; | |
| 26051 | - suffix[0] = suffix[0] + sqlite3_hostid_num; | |
| 26052 | - strlcat(path, suffix, len); | |
| 26053 | - } | |
| 26054 | -#endif | |
| 26055 | - OSTRACE3("GETHOSTIDPATH %s pid=%d\n", path, getpid()); | |
| 26056 | -} | |
| 26057 | - | |
| 26058 | -/* get the host ID from a sqlite hostid file stored in the | |
| 26059 | -** user-specific tmp directory, create the ID if it's not there already | |
| 26060 | -*/ | |
| 26061 | -static int proxyGetHostID(char *pHostID, int *pError){ | |
| 26062 | - int fd; | |
| 26063 | - char path[MAXPATHLEN]; | |
| 26064 | - size_t len; | |
| 26065 | - int rc=SQLITE_OK; | |
| 26066 | - | |
| 26067 | - proxyGetHostIDPath(path, MAXPATHLEN); | |
| 26068 | - /* try to create the host ID file, if it already exists read the contents */ | |
| 26069 | - fd = open(path, O_CREAT|O_WRONLY|O_EXCL, 0644); | |
| 26070 | - if( fd<0 ){ | |
| 26071 | - int err=errno; | |
| 26072 | - | |
| 26073 | - if( err!=EEXIST ){ | |
| 26074 | -#ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */ | |
| 26075 | - fprintf(stderr, "sqlite error creating host ID file %s: %s\n", | |
| 26076 | - path, strerror(err)); | |
| 26077 | -#endif | |
| 26078 | - return SQLITE_PERM; | |
| 26079 | - } | |
| 26080 | - /* couldn't create the file, read it instead */ | |
| 26081 | - fd = open(path, O_RDONLY|O_EXCL); | |
| 26082 | - if( fd<0 ){ | |
| 26083 | -#ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */ | |
| 26084 | - int err = errno; | |
| 26085 | - fprintf(stderr, "sqlite error opening host ID file %s: %s\n", | |
| 26086 | - path, strerror(err)); | |
| 26087 | -#endif | |
| 26088 | - return SQLITE_PERM; | |
| 26089 | - } | |
| 26090 | - len = pread(fd, pHostID, HOSTIDLEN, 0); | |
| 26091 | - if( len<0 ){ | |
| 26092 | - *pError = errno; | |
| 26093 | - rc = SQLITE_IOERR_READ; | |
| 26094 | - }else if( len<HOSTIDLEN ){ | |
| 26095 | - *pError = 0; | |
| 26096 | - rc = SQLITE_IOERR_SHORT_READ; | |
| 26097 | - } | |
| 26098 | - close(fd); /* silently leak the fd if it fails */ | |
| 26099 | - OSTRACE3("GETHOSTID read %s pid=%d\n", pHostID, getpid()); | |
| 26100 | - return rc; | |
| 26101 | - }else{ | |
| 26102 | - /* we're creating the host ID file (use a random string of bytes) */ | |
| 26103 | - proxyGenerateHostID(pHostID); | |
| 26104 | - len = pwrite(fd, pHostID, HOSTIDLEN, 0); | |
| 26105 | - if( len<0 ){ | |
| 26106 | - *pError = errno; | |
| 26107 | - rc = SQLITE_IOERR_WRITE; | |
| 26108 | - }else if( len<HOSTIDLEN ){ | |
| 26109 | - *pError = 0; | |
| 26110 | - rc = SQLITE_IOERR_WRITE; | |
| 26111 | - } | |
| 26112 | - close(fd); /* silently leak the fd if it fails */ | |
| 26113 | - OSTRACE3("GETHOSTID wrote %s pid=%d\n", pHostID, getpid()); | |
| 26114 | - return rc; | |
| 26115 | - } | |
| 26116 | -} | |
| 26117 | - | |
| 26329 | +/* | |
| 26330 | +** The proxy lock file path for the database at dbPath is written into lPath, | |
| 26331 | +** which must point to valid, writable memory large enough for a maxLen length | |
| 26332 | +** file path. | |
| 26333 | +*/ | |
| 26118 | 26334 | static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ |
| 26119 | 26335 | int len; |
| 26120 | 26336 | int dbLen; |
| 26121 | 26337 | int i; |
| 26122 | 26338 | |
| @@ -26123,25 +26339,16 @@ | ||
| 26123 | 26339 | #ifdef LOCKPROXYDIR |
| 26124 | 26340 | len = strlcpy(lPath, LOCKPROXYDIR, maxLen); |
| 26125 | 26341 | #else |
| 26126 | 26342 | # ifdef _CS_DARWIN_USER_TEMP_DIR |
| 26127 | 26343 | { |
| 26128 | - confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen); | |
| 26129 | - len = strlcat(lPath, "sqliteplocks", maxLen); | |
| 26130 | - if( mkdir(lPath, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ | |
| 26131 | - /* if mkdir fails, handle as lock file creation failure */ | |
| 26132 | -# ifdef SQLITE_DEBUG | |
| 26133 | - int err = errno; | |
| 26134 | - if( err!=EEXIST ){ | |
| 26135 | - fprintf(stderr, "proxyGetLockPath: mkdir(%s,0%o) error %d %s\n", lPath, | |
| 26136 | - SQLITE_DEFAULT_PROXYDIR_PERMISSIONS, err, strerror(err)); | |
| 26137 | - } | |
| 26138 | -# endif | |
| 26139 | - }else{ | |
| 26140 | - OSTRACE3("GETLOCKPATH mkdir %s pid=%d\n", lPath, getpid()); | |
| 26141 | - } | |
| 26142 | - | |
| 26344 | + if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ | |
| 26345 | + OSTRACE4("GETLOCKPATH failed %s errno=%d pid=%d\n", | |
| 26346 | + lPath, errno, getpid()); | |
| 26347 | + return SQLITE_IOERR_LOCK; | |
| 26348 | + } | |
| 26349 | + len = strlcat(lPath, "sqliteplocks", maxLen); | |
| 26143 | 26350 | } |
| 26144 | 26351 | # else |
| 26145 | 26352 | len = strlcpy(lPath, "/tmp/", maxLen); |
| 26146 | 26353 | # endif |
| 26147 | 26354 | #endif |
| @@ -26156,213 +26363,535 @@ | ||
| 26156 | 26363 | char c = dbPath[i]; |
| 26157 | 26364 | lPath[i+len] = (c=='/')?'_':c; |
| 26158 | 26365 | } |
| 26159 | 26366 | lPath[i+len]='\0'; |
| 26160 | 26367 | strlcat(lPath, ":auto:", maxLen); |
| 26368 | + OSTRACE3("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()); | |
| 26161 | 26369 | return SQLITE_OK; |
| 26162 | 26370 | } |
| 26371 | + | |
| 26372 | +/* | |
| 26373 | + ** Creates the lock file and any missing directories in lockPath | |
| 26374 | + */ | |
| 26375 | +static int proxyCreateLockPath(const char *lockPath){ | |
| 26376 | + int i, len; | |
| 26377 | + char buf[MAXPATHLEN]; | |
| 26378 | + int start = 0; | |
| 26379 | + | |
| 26380 | + assert(lockPath!=NULL); | |
| 26381 | + /* try to create all the intermediate directories */ | |
| 26382 | + len = (int)strlen(lockPath); | |
| 26383 | + buf[0] = lockPath[0]; | |
| 26384 | + for( i=1; i<len; i++ ){ | |
| 26385 | + if( lockPath[i] == '/' && (i - start > 0) ){ | |
| 26386 | + /* only mkdir if leaf dir != "." or "/" or ".." */ | |
| 26387 | + if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') | |
| 26388 | + || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){ | |
| 26389 | + buf[i]='\0'; | |
| 26390 | + if( mkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ | |
| 26391 | + int err=errno; | |
| 26392 | + if( err!=EEXIST ) { | |
| 26393 | + OSTRACE5("CREATELOCKPATH FAILED creating %s, " | |
| 26394 | + "'%s' proxy lock path=%s pid=%d\n", | |
| 26395 | + buf, strerror(err), lockPath, getpid()); | |
| 26396 | + return err; | |
| 26397 | + } | |
| 26398 | + } | |
| 26399 | + } | |
| 26400 | + start=i+1; | |
| 26401 | + } | |
| 26402 | + buf[i] = lockPath[i]; | |
| 26403 | + } | |
| 26404 | + OSTRACE3("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()); | |
| 26405 | + return 0; | |
| 26406 | +} | |
| 26163 | 26407 | |
| 26164 | 26408 | /* |
| 26165 | 26409 | ** Create a new VFS file descriptor (stored in memory obtained from |
| 26166 | 26410 | ** sqlite3_malloc) and open the file named "path" in the file descriptor. |
| 26167 | 26411 | ** |
| 26168 | 26412 | ** The caller is responsible not only for closing the file descriptor |
| 26169 | 26413 | ** but also for freeing the memory associated with the file descriptor. |
| 26170 | 26414 | */ |
| 26171 | -static int proxyCreateUnixFile(const char *path, unixFile **ppFile) { | |
| 26415 | +static int proxyCreateUnixFile( | |
| 26416 | + const char *path, /* path for the new unixFile */ | |
| 26417 | + unixFile **ppFile, /* unixFile created and returned by ref */ | |
| 26418 | + int islockfile /* if non zero missing dirs will be created */ | |
| 26419 | +) { | |
| 26420 | + int fd = -1; | |
| 26421 | + int dirfd = -1; | |
| 26172 | 26422 | unixFile *pNew; |
| 26173 | - int flags = SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE; | |
| 26174 | 26423 | int rc = SQLITE_OK; |
| 26424 | + int openFlags = O_RDWR | O_CREAT; | |
| 26175 | 26425 | sqlite3_vfs dummyVfs; |
| 26426 | + int terrno = 0; | |
| 26427 | + UnixUnusedFd *pUnused = NULL; | |
| 26176 | 26428 | |
| 26177 | - pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile)); | |
| 26178 | - if( !pNew ){ | |
| 26179 | - return SQLITE_NOMEM; | |
| 26429 | + /* 1. first try to open/create the file | |
| 26430 | + ** 2. if that fails, and this is a lock file (not-conch), try creating | |
| 26431 | + ** the parent directories and then try again. | |
| 26432 | + ** 3. if that fails, try to open the file read-only | |
| 26433 | + ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file | |
| 26434 | + */ | |
| 26435 | + pUnused = findReusableFd(path, openFlags); | |
| 26436 | + if( pUnused ){ | |
| 26437 | + fd = pUnused->fd; | |
| 26438 | + }else{ | |
| 26439 | + pUnused = sqlite3_malloc(sizeof(*pUnused)); | |
| 26440 | + if( !pUnused ){ | |
| 26441 | + return SQLITE_NOMEM; | |
| 26442 | + } | |
| 26443 | + } | |
| 26444 | + if( fd<0 ){ | |
| 26445 | + fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); | |
| 26446 | + terrno = errno; | |
| 26447 | + if( fd<0 && errno==ENOENT && islockfile ){ | |
| 26448 | + if( proxyCreateLockPath(path) == SQLITE_OK ){ | |
| 26449 | + fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); | |
| 26450 | + } | |
| 26451 | + } | |
| 26452 | + } | |
| 26453 | + if( fd<0 ){ | |
| 26454 | + openFlags = O_RDONLY; | |
| 26455 | + fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); | |
| 26456 | + terrno = errno; | |
| 26457 | + } | |
| 26458 | + if( fd<0 ){ | |
| 26459 | + if( islockfile ){ | |
| 26460 | + return SQLITE_BUSY; | |
| 26461 | + } | |
| 26462 | + switch (terrno) { | |
| 26463 | + case EACCES: | |
| 26464 | + return SQLITE_PERM; | |
| 26465 | + case EIO: | |
| 26466 | + return SQLITE_IOERR_LOCK; /* even though it is the conch */ | |
| 26467 | + default: | |
| 26468 | + return SQLITE_CANTOPEN_BKPT; | |
| 26469 | + } | |
| 26470 | + } | |
| 26471 | + | |
| 26472 | + pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew)); | |
| 26473 | + if( pNew==NULL ){ | |
| 26474 | + rc = SQLITE_NOMEM; | |
| 26475 | + goto end_create_proxy; | |
| 26180 | 26476 | } |
| 26181 | 26477 | memset(pNew, 0, sizeof(unixFile)); |
| 26182 | - | |
| 26183 | - /* Call unixOpen() to open the proxy file. The flags passed to unixOpen() | |
| 26184 | - ** suggest that the file being opened is a "main database". This is | |
| 26185 | - ** necessary as other file types do not necessarily support locking. It | |
| 26186 | - ** is better to use unixOpen() instead of opening the file directly with | |
| 26187 | - ** open(), as unixOpen() sets up the various mechanisms required to | |
| 26188 | - ** make sure a call to close() does not cause the system to discard | |
| 26189 | - ** POSIX locks prematurely. | |
| 26190 | - ** | |
| 26191 | - ** It is important that the xOpen member of the VFS object passed to | |
| 26192 | - ** unixOpen() is NULL. This tells unixOpen() may try to open a proxy-file | |
| 26193 | - ** for the proxy-file (creating a potential infinite loop). | |
| 26194 | - */ | |
| 26478 | + pNew->openFlags = openFlags; | |
| 26195 | 26479 | dummyVfs.pAppData = (void*)&autolockIoFinder; |
| 26196 | - dummyVfs.xOpen = 0; | |
| 26197 | - rc = unixOpen(&dummyVfs, path, (sqlite3_file *)pNew, flags, &flags); | |
| 26198 | - if( rc==SQLITE_OK && (flags&SQLITE_OPEN_READONLY) ){ | |
| 26199 | - pNew->pMethod->xClose((sqlite3_file *)pNew); | |
| 26200 | - rc = SQLITE_CANTOPEN; | |
| 26201 | - } | |
| 26202 | - | |
| 26203 | - if( rc!=SQLITE_OK ){ | |
| 26204 | - sqlite3_free(pNew); | |
| 26205 | - pNew = 0; | |
| 26206 | - } | |
| 26207 | - | |
| 26208 | - *ppFile = pNew; | |
| 26209 | - return rc; | |
| 26210 | -} | |
| 26211 | - | |
| 26212 | -/* takes the conch by taking a shared lock and read the contents conch, if | |
| 26480 | + pUnused->fd = fd; | |
| 26481 | + pUnused->flags = openFlags; | |
| 26482 | + pNew->pUnused = pUnused; | |
| 26483 | + | |
| 26484 | + rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0); | |
| 26485 | + if( rc==SQLITE_OK ){ | |
| 26486 | + *ppFile = pNew; | |
| 26487 | + return SQLITE_OK; | |
| 26488 | + } | |
| 26489 | +end_create_proxy: | |
| 26490 | + close(fd); /* silently leak fd if error, we're already in error */ | |
| 26491 | + sqlite3_free(pNew); | |
| 26492 | + sqlite3_free(pUnused); | |
| 26493 | + return rc; | |
| 26494 | +} | |
| 26495 | + | |
| 26496 | +#ifdef SQLITE_TEST | |
| 26497 | +/* simulate multiple hosts by creating unique hostid file paths */ | |
| 26498 | +SQLITE_API int sqlite3_hostid_num = 0; | |
| 26499 | +#endif | |
| 26500 | + | |
| 26501 | +#define PROXY_HOSTIDLEN 16 /* conch file host id length */ | |
| 26502 | + | |
| 26503 | +/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN | |
| 26504 | +** bytes of writable memory. | |
| 26505 | +*/ | |
| 26506 | +static int proxyGetHostID(unsigned char *pHostID, int *pError){ | |
| 26507 | + struct timespec timeout = {1, 0}; /* 1 sec timeout */ | |
| 26508 | + | |
| 26509 | + assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); | |
| 26510 | + memset(pHostID, 0, PROXY_HOSTIDLEN); | |
| 26511 | + if( gethostuuid(pHostID, &timeout) ){ | |
| 26512 | + int err = errno; | |
| 26513 | + if( pError ){ | |
| 26514 | + *pError = err; | |
| 26515 | + } | |
| 26516 | + return SQLITE_IOERR; | |
| 26517 | + } | |
| 26518 | +#ifdef SQLITE_TEST | |
| 26519 | + /* simulate multiple hosts by creating unique hostid file paths */ | |
| 26520 | + if( sqlite3_hostid_num != 0){ | |
| 26521 | + pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF)); | |
| 26522 | + } | |
| 26523 | +#endif | |
| 26524 | + | |
| 26525 | + return SQLITE_OK; | |
| 26526 | +} | |
| 26527 | + | |
| 26528 | +/* The conch file contains the header, host id and lock file path | |
| 26529 | + */ | |
| 26530 | +#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */ | |
| 26531 | +#define PROXY_HEADERLEN 1 /* conch file header length */ | |
| 26532 | +#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN) | |
| 26533 | +#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN) | |
| 26534 | + | |
| 26535 | +/* | |
| 26536 | +** Takes an open conch file, copies the contents to a new path and then moves | |
| 26537 | +** it back. The newly created file's file descriptor is assigned to the | |
| 26538 | +** conch file structure and finally the original conch file descriptor is | |
| 26539 | +** closed. Returns zero if successful. | |
| 26540 | +*/ | |
| 26541 | +static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ | |
| 26542 | + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; | |
| 26543 | + unixFile *conchFile = pCtx->conchFile; | |
| 26544 | + char tPath[MAXPATHLEN]; | |
| 26545 | + char buf[PROXY_MAXCONCHLEN]; | |
| 26546 | + char *cPath = pCtx->conchFilePath; | |
| 26547 | + size_t readLen = 0; | |
| 26548 | + size_t pathLen = 0; | |
| 26549 | + char errmsg[64] = ""; | |
| 26550 | + int fd = -1; | |
| 26551 | + int rc = -1; | |
| 26552 | + | |
| 26553 | + /* create a new path by replace the trailing '-conch' with '-break' */ | |
| 26554 | + pathLen = strlcpy(tPath, cPath, MAXPATHLEN); | |
| 26555 | + if( pathLen>MAXPATHLEN || pathLen<6 || | |
| 26556 | + (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){ | |
| 26557 | + sprintf(errmsg, "path error (len %d)", (int)pathLen); | |
| 26558 | + goto end_breaklock; | |
| 26559 | + } | |
| 26560 | + /* read the conch content */ | |
| 26561 | + readLen = pread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0); | |
| 26562 | + if( readLen<PROXY_PATHINDEX ){ | |
| 26563 | + sprintf(errmsg, "read error (len %d)", (int)readLen); | |
| 26564 | + goto end_breaklock; | |
| 26565 | + } | |
| 26566 | + /* write it out to the temporary break file */ | |
| 26567 | + fd = open(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS); | |
| 26568 | + if( fd<0 ){ | |
| 26569 | + sprintf(errmsg, "create failed (%d)", errno); | |
| 26570 | + goto end_breaklock; | |
| 26571 | + } | |
| 26572 | + if( pwrite(fd, buf, readLen, 0) != readLen ){ | |
| 26573 | + sprintf(errmsg, "write failed (%d)", errno); | |
| 26574 | + goto end_breaklock; | |
| 26575 | + } | |
| 26576 | + if( rename(tPath, cPath) ){ | |
| 26577 | + sprintf(errmsg, "rename failed (%d)", errno); | |
| 26578 | + goto end_breaklock; | |
| 26579 | + } | |
| 26580 | + rc = 0; | |
| 26581 | + fprintf(stderr, "broke stale lock on %s\n", cPath); | |
| 26582 | + close(conchFile->h); | |
| 26583 | + conchFile->h = fd; | |
| 26584 | + conchFile->openFlags = O_RDWR | O_CREAT; | |
| 26585 | + | |
| 26586 | +end_breaklock: | |
| 26587 | + if( rc ){ | |
| 26588 | + if( fd>=0 ){ | |
| 26589 | + unlink(tPath); | |
| 26590 | + close(fd); | |
| 26591 | + } | |
| 26592 | + fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); | |
| 26593 | + } | |
| 26594 | + return rc; | |
| 26595 | +} | |
| 26596 | + | |
| 26597 | +/* Take the requested lock on the conch file and break a stale lock if the | |
| 26598 | +** host id matches. | |
| 26599 | +*/ | |
| 26600 | +static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ | |
| 26601 | + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; | |
| 26602 | + unixFile *conchFile = pCtx->conchFile; | |
| 26603 | + int rc = SQLITE_OK; | |
| 26604 | + int nTries = 0; | |
| 26605 | + struct timespec conchModTime; | |
| 26606 | + | |
| 26607 | + do { | |
| 26608 | + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); | |
| 26609 | + nTries ++; | |
| 26610 | + if( rc==SQLITE_BUSY ){ | |
| 26611 | + /* If the lock failed (busy): | |
| 26612 | + * 1st try: get the mod time of the conch, wait 0.5s and try again. | |
| 26613 | + * 2nd try: fail if the mod time changed or host id is different, wait | |
| 26614 | + * 10 sec and try again | |
| 26615 | + * 3rd try: break the lock unless the mod time has changed. | |
| 26616 | + */ | |
| 26617 | + struct stat buf; | |
| 26618 | + if( fstat(conchFile->h, &buf) ){ | |
| 26619 | + pFile->lastErrno = errno; | |
| 26620 | + return SQLITE_IOERR_LOCK; | |
| 26621 | + } | |
| 26622 | + | |
| 26623 | + if( nTries==1 ){ | |
| 26624 | + conchModTime = buf.st_mtimespec; | |
| 26625 | + usleep(500000); /* wait 0.5 sec and try the lock again*/ | |
| 26626 | + continue; | |
| 26627 | + } | |
| 26628 | + | |
| 26629 | + assert( nTries>1 ); | |
| 26630 | + if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || | |
| 26631 | + conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){ | |
| 26632 | + return SQLITE_BUSY; | |
| 26633 | + } | |
| 26634 | + | |
| 26635 | + if( nTries==2 ){ | |
| 26636 | + char tBuf[PROXY_MAXCONCHLEN]; | |
| 26637 | + int len = pread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); | |
| 26638 | + if( len<0 ){ | |
| 26639 | + pFile->lastErrno = errno; | |
| 26640 | + return SQLITE_IOERR_LOCK; | |
| 26641 | + } | |
| 26642 | + if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ | |
| 26643 | + /* don't break the lock if the host id doesn't match */ | |
| 26644 | + if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){ | |
| 26645 | + return SQLITE_BUSY; | |
| 26646 | + } | |
| 26647 | + }else{ | |
| 26648 | + /* don't break the lock on short read or a version mismatch */ | |
| 26649 | + return SQLITE_BUSY; | |
| 26650 | + } | |
| 26651 | + usleep(10000000); /* wait 10 sec and try the lock again */ | |
| 26652 | + continue; | |
| 26653 | + } | |
| 26654 | + | |
| 26655 | + assert( nTries==3 ); | |
| 26656 | + if( 0==proxyBreakConchLock(pFile, myHostID) ){ | |
| 26657 | + rc = SQLITE_OK; | |
| 26658 | + if( lockType==EXCLUSIVE_LOCK ){ | |
| 26659 | + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); | |
| 26660 | + } | |
| 26661 | + if( !rc ){ | |
| 26662 | + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); | |
| 26663 | + } | |
| 26664 | + } | |
| 26665 | + } | |
| 26666 | + } while( rc==SQLITE_BUSY && nTries<3 ); | |
| 26667 | + | |
| 26668 | + return rc; | |
| 26669 | +} | |
| 26670 | + | |
| 26671 | +/* Takes the conch by taking a shared lock and read the contents conch, if | |
| 26213 | 26672 | ** lockPath is non-NULL, the host ID and lock file path must match. A NULL |
| 26214 | 26673 | ** lockPath means that the lockPath in the conch file will be used if the |
| 26215 | 26674 | ** host IDs match, or a new lock path will be generated automatically |
| 26216 | 26675 | ** and written to the conch file. |
| 26217 | 26676 | */ |
| 26218 | 26677 | static int proxyTakeConch(unixFile *pFile){ |
| 26219 | 26678 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26220 | 26679 | |
| 26221 | - if( pCtx->conchHeld>0 ){ | |
| 26680 | + if( pCtx->conchHeld!=0 ){ | |
| 26222 | 26681 | return SQLITE_OK; |
| 26223 | 26682 | }else{ |
| 26224 | 26683 | unixFile *conchFile = pCtx->conchFile; |
| 26225 | - char testValue[CONCHLEN]; | |
| 26226 | - char conchValue[CONCHLEN]; | |
| 26684 | + uuid_t myHostID; | |
| 26685 | + int pError = 0; | |
| 26686 | + char readBuf[PROXY_MAXCONCHLEN]; | |
| 26227 | 26687 | char lockPath[MAXPATHLEN]; |
| 26228 | - char *tLockPath = NULL; | |
| 26688 | + char *tempLockPath = NULL; | |
| 26229 | 26689 | int rc = SQLITE_OK; |
| 26230 | - int readRc = SQLITE_OK; | |
| 26231 | - int syncPerms = 0; | |
| 26232 | - | |
| 26690 | + int createConch = 0; | |
| 26691 | + int hostIdMatch = 0; | |
| 26692 | + int readLen = 0; | |
| 26693 | + int tryOldLockPath = 0; | |
| 26694 | + int forceNewLockPath = 0; | |
| 26695 | + | |
| 26233 | 26696 | OSTRACE4("TAKECONCH %d for %s pid=%d\n", conchFile->h, |
| 26234 | 26697 | (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()); |
| 26235 | 26698 | |
| 26236 | - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); | |
| 26237 | - if( rc==SQLITE_OK ){ | |
| 26238 | - int pError = 0; | |
| 26239 | - memset(testValue, 0, CONCHLEN); /* conch is fixed size */ | |
| 26240 | - rc = proxyGetHostID(testValue, &pError); | |
| 26241 | - if( (rc&0xff)==SQLITE_IOERR ){ | |
| 26242 | - pFile->lastErrno = pError; | |
| 26243 | - } | |
| 26244 | - if( pCtx->lockProxyPath ){ | |
| 26245 | - strlcpy(&testValue[HOSTIDLEN], pCtx->lockProxyPath, MAXPATHLEN); | |
| 26246 | - } | |
| 26247 | - } | |
| 26248 | - if( rc!=SQLITE_OK ){ | |
| 26249 | - goto end_takeconch; | |
| 26250 | - } | |
| 26251 | - | |
| 26252 | - readRc = unixRead((sqlite3_file *)conchFile, conchValue, CONCHLEN, 0); | |
| 26253 | - if( readRc!=SQLITE_IOERR_SHORT_READ ){ | |
| 26254 | - if( readRc!=SQLITE_OK ){ | |
| 26255 | - if( (rc&0xff)==SQLITE_IOERR ){ | |
| 26256 | - pFile->lastErrno = conchFile->lastErrno; | |
| 26257 | - } | |
| 26258 | - rc = readRc; | |
| 26259 | - goto end_takeconch; | |
| 26260 | - } | |
| 26261 | - /* if the conch has data compare the contents */ | |
| 26262 | - if( !pCtx->lockProxyPath ){ | |
| 26263 | - /* for auto-named local lock file, just check the host ID and we'll | |
| 26264 | - ** use the local lock file path that's already in there */ | |
| 26265 | - if( !memcmp(testValue, conchValue, HOSTIDLEN) ){ | |
| 26266 | - tLockPath = (char *)&conchValue[HOSTIDLEN]; | |
| 26267 | - goto end_takeconch; | |
| 26268 | - } | |
| 26269 | - }else{ | |
| 26270 | - /* we've got the conch if conchValue matches our path and host ID */ | |
| 26271 | - if( !memcmp(testValue, conchValue, CONCHLEN) ){ | |
| 26272 | - goto end_takeconch; | |
| 26273 | - } | |
| 26274 | - } | |
| 26275 | - }else{ | |
| 26276 | - /* a short read means we're "creating" the conch (even though it could | |
| 26277 | - ** have been user-intervention), if we acquire the exclusive lock, | |
| 26278 | - ** we'll try to match the current on-disk permissions of the database | |
| 26279 | - */ | |
| 26280 | - syncPerms = 1; | |
| 26281 | - } | |
| 26282 | - | |
| 26283 | - /* either conch was emtpy or didn't match */ | |
| 26284 | - if( !pCtx->lockProxyPath ){ | |
| 26285 | - proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN); | |
| 26286 | - tLockPath = lockPath; | |
| 26287 | - strlcpy(&testValue[HOSTIDLEN], lockPath, MAXPATHLEN); | |
| 26288 | - } | |
| 26289 | - | |
| 26290 | - /* update conch with host and path (this will fail if other process | |
| 26291 | - ** has a shared lock already) */ | |
| 26292 | - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK); | |
| 26293 | - if( rc==SQLITE_OK ){ | |
| 26294 | - rc = unixWrite((sqlite3_file *)conchFile, testValue, CONCHLEN, 0); | |
| 26295 | - if( rc==SQLITE_OK && syncPerms ){ | |
| 26296 | - struct stat buf; | |
| 26297 | - int err = fstat(pFile->h, &buf); | |
| 26298 | - if( err==0 ){ | |
| 26299 | - /* try to match the database file permissions, ignore failure */ | |
| 26300 | -#ifndef SQLITE_PROXY_DEBUG | |
| 26301 | - fchmod(conchFile->h, buf.st_mode); | |
| 26302 | -#else | |
| 26303 | - if( fchmod(conchFile->h, buf.st_mode)!=0 ){ | |
| 26304 | - int code = errno; | |
| 26305 | - fprintf(stderr, "fchmod %o FAILED with %d %s\n", | |
| 26306 | - buf.st_mode, code, strerror(code)); | |
| 26307 | - } else { | |
| 26308 | - fprintf(stderr, "fchmod %o SUCCEDED\n",buf.st_mode); | |
| 26309 | - } | |
| 26310 | - }else{ | |
| 26311 | - int code = errno; | |
| 26312 | - fprintf(stderr, "STAT FAILED[%d] with %d %s\n", | |
| 26313 | - err, code, strerror(code)); | |
| 26314 | -#endif | |
| 26315 | - } | |
| 26316 | - } | |
| 26317 | - } | |
| 26318 | - conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); | |
| 26319 | - | |
| 26320 | -end_takeconch: | |
| 26321 | - OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h); | |
| 26322 | - if( rc==SQLITE_OK && pFile->openFlags ){ | |
| 26323 | - if( pFile->h>=0 ){ | |
| 26324 | -#ifdef STRICT_CLOSE_ERROR | |
| 26325 | - if( close(pFile->h) ){ | |
| 26326 | - pFile->lastErrno = errno; | |
| 26327 | - return SQLITE_IOERR_CLOSE; | |
| 26328 | - } | |
| 26329 | -#else | |
| 26330 | - close(pFile->h); /* silently leak fd if fail */ | |
| 26331 | -#endif | |
| 26332 | - } | |
| 26333 | - pFile->h = -1; | |
| 26334 | - int fd = open(pCtx->dbPath, pFile->openFlags, | |
| 26335 | - SQLITE_DEFAULT_FILE_PERMISSIONS); | |
| 26336 | - OSTRACE2("TRANSPROXY: OPEN %d\n", fd); | |
| 26337 | - if( fd>=0 ){ | |
| 26338 | - pFile->h = fd; | |
| 26339 | - }else{ | |
| 26340 | - rc=SQLITE_CANTOPEN; /* SQLITE_BUSY? proxyTakeConch called | |
| 26341 | - during locking */ | |
| 26342 | - } | |
| 26343 | - } | |
| 26344 | - if( rc==SQLITE_OK && !pCtx->lockProxy ){ | |
| 26345 | - char *path = tLockPath ? tLockPath : pCtx->lockProxyPath; | |
| 26346 | - /* ACS: Need to make a copy of path sometimes */ | |
| 26347 | - rc = proxyCreateUnixFile(path, &pCtx->lockProxy); | |
| 26348 | - } | |
| 26349 | - if( rc==SQLITE_OK ){ | |
| 26350 | - pCtx->conchHeld = 1; | |
| 26351 | - | |
| 26352 | - if( tLockPath ){ | |
| 26353 | - pCtx->lockProxyPath = sqlite3DbStrDup(0, tLockPath); | |
| 26354 | - if( pCtx->lockProxy->pMethod == &afpIoMethods ){ | |
| 26355 | - ((afpLockingContext *)pCtx->lockProxy->lockingContext)->dbPath = | |
| 26356 | - pCtx->lockProxyPath; | |
| 26357 | - } | |
| 26358 | - } | |
| 26359 | - } else { | |
| 26360 | - conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); | |
| 26361 | - } | |
| 26362 | - OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed"); | |
| 26363 | - return rc; | |
| 26699 | + rc = proxyGetHostID(myHostID, &pError); | |
| 26700 | + if( (rc&0xff)==SQLITE_IOERR ){ | |
| 26701 | + pFile->lastErrno = pError; | |
| 26702 | + goto end_takeconch; | |
| 26703 | + } | |
| 26704 | + rc = proxyConchLock(pFile, myHostID, SHARED_LOCK); | |
| 26705 | + if( rc!=SQLITE_OK ){ | |
| 26706 | + goto end_takeconch; | |
| 26707 | + } | |
| 26708 | + /* read the existing conch file */ | |
| 26709 | + readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN); | |
| 26710 | + if( readLen<0 ){ | |
| 26711 | + /* I/O error: lastErrno set by seekAndRead */ | |
| 26712 | + pFile->lastErrno = conchFile->lastErrno; | |
| 26713 | + rc = SQLITE_IOERR_READ; | |
| 26714 | + goto end_takeconch; | |
| 26715 | + }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || | |
| 26716 | + readBuf[0]!=(char)PROXY_CONCHVERSION ){ | |
| 26717 | + /* a short read or version format mismatch means we need to create a new | |
| 26718 | + ** conch file. | |
| 26719 | + */ | |
| 26720 | + createConch = 1; | |
| 26721 | + } | |
| 26722 | + /* if the host id matches and the lock path already exists in the conch | |
| 26723 | + ** we'll try to use the path there, if we can't open that path, we'll | |
| 26724 | + ** retry with a new auto-generated path | |
| 26725 | + */ | |
| 26726 | + do { /* in case we need to try again for an :auto: named lock file */ | |
| 26727 | + | |
| 26728 | + if( !createConch && !forceNewLockPath ){ | |
| 26729 | + hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, | |
| 26730 | + PROXY_HOSTIDLEN); | |
| 26731 | + /* if the conch has data compare the contents */ | |
| 26732 | + if( !pCtx->lockProxyPath ){ | |
| 26733 | + /* for auto-named local lock file, just check the host ID and we'll | |
| 26734 | + ** use the local lock file path that's already in there | |
| 26735 | + */ | |
| 26736 | + if( hostIdMatch ){ | |
| 26737 | + size_t pathLen = (readLen - PROXY_PATHINDEX); | |
| 26738 | + | |
| 26739 | + if( pathLen>=MAXPATHLEN ){ | |
| 26740 | + pathLen=MAXPATHLEN-1; | |
| 26741 | + } | |
| 26742 | + memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen); | |
| 26743 | + lockPath[pathLen] = 0; | |
| 26744 | + tempLockPath = lockPath; | |
| 26745 | + tryOldLockPath = 1; | |
| 26746 | + /* create a copy of the lock path if the conch is taken */ | |
| 26747 | + goto end_takeconch; | |
| 26748 | + } | |
| 26749 | + }else if( hostIdMatch | |
| 26750 | + && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX], | |
| 26751 | + readLen-PROXY_PATHINDEX) | |
| 26752 | + ){ | |
| 26753 | + /* conch host and lock path match */ | |
| 26754 | + goto end_takeconch; | |
| 26755 | + } | |
| 26756 | + } | |
| 26757 | + | |
| 26758 | + /* if the conch isn't writable and doesn't match, we can't take it */ | |
| 26759 | + if( (conchFile->openFlags&O_RDWR) == 0 ){ | |
| 26760 | + rc = SQLITE_BUSY; | |
| 26761 | + goto end_takeconch; | |
| 26762 | + } | |
| 26763 | + | |
| 26764 | + /* either the conch didn't match or we need to create a new one */ | |
| 26765 | + if( !pCtx->lockProxyPath ){ | |
| 26766 | + proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN); | |
| 26767 | + tempLockPath = lockPath; | |
| 26768 | + /* create a copy of the lock path _only_ if the conch is taken */ | |
| 26769 | + } | |
| 26770 | + | |
| 26771 | + /* update conch with host and path (this will fail if other process | |
| 26772 | + ** has a shared lock already), if the host id matches, use the big | |
| 26773 | + ** stick. | |
| 26774 | + */ | |
| 26775 | + futimes(conchFile->h, NULL); | |
| 26776 | + if( hostIdMatch && !createConch ){ | |
| 26777 | + if( conchFile->pLock && conchFile->pLock->cnt>1 ){ | |
| 26778 | + /* We are trying for an exclusive lock but another thread in this | |
| 26779 | + ** same process is still holding a shared lock. */ | |
| 26780 | + rc = SQLITE_BUSY; | |
| 26781 | + } else { | |
| 26782 | + rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); | |
| 26783 | + } | |
| 26784 | + }else{ | |
| 26785 | + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK); | |
| 26786 | + } | |
| 26787 | + if( rc==SQLITE_OK ){ | |
| 26788 | + char writeBuffer[PROXY_MAXCONCHLEN]; | |
| 26789 | + int writeSize = 0; | |
| 26790 | + | |
| 26791 | + writeBuffer[0] = (char)PROXY_CONCHVERSION; | |
| 26792 | + memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); | |
| 26793 | + if( pCtx->lockProxyPath!=NULL ){ | |
| 26794 | + strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN); | |
| 26795 | + }else{ | |
| 26796 | + strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); | |
| 26797 | + } | |
| 26798 | + writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); | |
| 26799 | + ftruncate(conchFile->h, writeSize); | |
| 26800 | + rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); | |
| 26801 | + fsync(conchFile->h); | |
| 26802 | + /* If we created a new conch file (not just updated the contents of a | |
| 26803 | + ** valid conch file), try to match the permissions of the database | |
| 26804 | + */ | |
| 26805 | + if( rc==SQLITE_OK && createConch ){ | |
| 26806 | + struct stat buf; | |
| 26807 | + int err = fstat(pFile->h, &buf); | |
| 26808 | + if( err==0 ){ | |
| 26809 | + mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | | |
| 26810 | + S_IROTH|S_IWOTH); | |
| 26811 | + /* try to match the database file R/W permissions, ignore failure */ | |
| 26812 | +#ifndef SQLITE_PROXY_DEBUG | |
| 26813 | + fchmod(conchFile->h, cmode); | |
| 26814 | +#else | |
| 26815 | + if( fchmod(conchFile->h, cmode)!=0 ){ | |
| 26816 | + int code = errno; | |
| 26817 | + fprintf(stderr, "fchmod %o FAILED with %d %s\n", | |
| 26818 | + cmode, code, strerror(code)); | |
| 26819 | + } else { | |
| 26820 | + fprintf(stderr, "fchmod %o SUCCEDED\n",cmode); | |
| 26821 | + } | |
| 26822 | + }else{ | |
| 26823 | + int code = errno; | |
| 26824 | + fprintf(stderr, "STAT FAILED[%d] with %d %s\n", | |
| 26825 | + err, code, strerror(code)); | |
| 26826 | +#endif | |
| 26827 | + } | |
| 26828 | + } | |
| 26829 | + } | |
| 26830 | + conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); | |
| 26831 | + | |
| 26832 | + end_takeconch: | |
| 26833 | + OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h); | |
| 26834 | + if( rc==SQLITE_OK && pFile->openFlags ){ | |
| 26835 | + if( pFile->h>=0 ){ | |
| 26836 | +#ifdef STRICT_CLOSE_ERROR | |
| 26837 | + if( close(pFile->h) ){ | |
| 26838 | + pFile->lastErrno = errno; | |
| 26839 | + return SQLITE_IOERR_CLOSE; | |
| 26840 | + } | |
| 26841 | +#else | |
| 26842 | + close(pFile->h); /* silently leak fd if fail */ | |
| 26843 | +#endif | |
| 26844 | + } | |
| 26845 | + pFile->h = -1; | |
| 26846 | + int fd = open(pCtx->dbPath, pFile->openFlags, | |
| 26847 | + SQLITE_DEFAULT_FILE_PERMISSIONS); | |
| 26848 | + OSTRACE2("TRANSPROXY: OPEN %d\n", fd); | |
| 26849 | + if( fd>=0 ){ | |
| 26850 | + pFile->h = fd; | |
| 26851 | + }else{ | |
| 26852 | + rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called | |
| 26853 | + during locking */ | |
| 26854 | + } | |
| 26855 | + } | |
| 26856 | + if( rc==SQLITE_OK && !pCtx->lockProxy ){ | |
| 26857 | + char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath; | |
| 26858 | + rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1); | |
| 26859 | + if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){ | |
| 26860 | + /* we couldn't create the proxy lock file with the old lock file path | |
| 26861 | + ** so try again via auto-naming | |
| 26862 | + */ | |
| 26863 | + forceNewLockPath = 1; | |
| 26864 | + tryOldLockPath = 0; | |
| 26865 | + continue; /* go back to the do {} while start point, try again */ | |
| 26866 | + } | |
| 26867 | + } | |
| 26868 | + if( rc==SQLITE_OK ){ | |
| 26869 | + /* Need to make a copy of path if we extracted the value | |
| 26870 | + ** from the conch file or the path was allocated on the stack | |
| 26871 | + */ | |
| 26872 | + if( tempLockPath ){ | |
| 26873 | + pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath); | |
| 26874 | + if( !pCtx->lockProxyPath ){ | |
| 26875 | + rc = SQLITE_NOMEM; | |
| 26876 | + } | |
| 26877 | + } | |
| 26878 | + } | |
| 26879 | + if( rc==SQLITE_OK ){ | |
| 26880 | + pCtx->conchHeld = 1; | |
| 26881 | + | |
| 26882 | + if( pCtx->lockProxy->pMethod == &afpIoMethods ){ | |
| 26883 | + afpLockingContext *afpCtx; | |
| 26884 | + afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext; | |
| 26885 | + afpCtx->dbPath = pCtx->lockProxyPath; | |
| 26886 | + } | |
| 26887 | + } else { | |
| 26888 | + conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); | |
| 26889 | + } | |
| 26890 | + OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed"); | |
| 26891 | + return rc; | |
| 26892 | + } while (1); /* in case we need to retry the :auto: lock file - we should never get here except via the 'continue' call. */ | |
| 26364 | 26893 | } |
| 26365 | 26894 | } |
| 26366 | 26895 | |
| 26367 | 26896 | /* |
| 26368 | 26897 | ** If pFile holds a lock on a conch file, then release that lock. |
| @@ -26375,12 +26904,14 @@ | ||
| 26375 | 26904 | pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26376 | 26905 | conchFile = pCtx->conchFile; |
| 26377 | 26906 | OSTRACE4("RELEASECONCH %d for %s pid=%d\n", conchFile->h, |
| 26378 | 26907 | (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), |
| 26379 | 26908 | getpid()); |
| 26909 | + if( pCtx->conchHeld>0 ){ | |
| 26910 | + rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); | |
| 26911 | + } | |
| 26380 | 26912 | pCtx->conchHeld = 0; |
| 26381 | - rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); | |
| 26382 | 26913 | OSTRACE3("RELEASECONCH %d %s\n", conchFile->h, |
| 26383 | 26914 | (rc==SQLITE_OK ? "ok" : "failed")); |
| 26384 | 26915 | return rc; |
| 26385 | 26916 | } |
| 26386 | 26917 | |
| @@ -26472,22 +27003,22 @@ | ||
| 26472 | 27003 | #if defined(__APPLE__) |
| 26473 | 27004 | if( pFile->pMethod == &afpIoMethods ){ |
| 26474 | 27005 | /* afp style keeps a reference to the db path in the filePath field |
| 26475 | 27006 | ** of the struct */ |
| 26476 | 27007 | assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); |
| 26477 | - strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath); | |
| 26478 | - }else | |
| 27008 | + strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN); | |
| 27009 | + } else | |
| 26479 | 27010 | #endif |
| 26480 | 27011 | if( pFile->pMethod == &dotlockIoMethods ){ |
| 26481 | 27012 | /* dot lock style uses the locking context to store the dot lock |
| 26482 | 27013 | ** file path */ |
| 26483 | 27014 | int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX); |
| 26484 | 27015 | memcpy(dbPath, (char *)pFile->lockingContext, len + 1); |
| 26485 | 27016 | }else{ |
| 26486 | 27017 | /* all other styles use the locking context to store the db file path */ |
| 26487 | 27018 | assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); |
| 26488 | - strcpy(dbPath, (char *)pFile->lockingContext); | |
| 27019 | + strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN); | |
| 26489 | 27020 | } |
| 26490 | 27021 | return SQLITE_OK; |
| 26491 | 27022 | } |
| 26492 | 27023 | |
| 26493 | 27024 | /* |
| @@ -26523,31 +27054,57 @@ | ||
| 26523 | 27054 | } |
| 26524 | 27055 | memset(pCtx, 0, sizeof(*pCtx)); |
| 26525 | 27056 | |
| 26526 | 27057 | rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath); |
| 26527 | 27058 | if( rc==SQLITE_OK ){ |
| 26528 | - rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile); | |
| 27059 | + rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0); | |
| 27060 | + if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){ | |
| 27061 | + /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and | |
| 27062 | + ** (c) the file system is read-only, then enable no-locking access. | |
| 27063 | + ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts | |
| 27064 | + ** that openFlags will have only one of O_RDONLY or O_RDWR. | |
| 27065 | + */ | |
| 27066 | + struct statfs fsInfo; | |
| 27067 | + struct stat conchInfo; | |
| 27068 | + int goLockless = 0; | |
| 27069 | + | |
| 27070 | + if( stat(pCtx->conchFilePath, &conchInfo) == -1 ) { | |
| 27071 | + int err = errno; | |
| 27072 | + if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){ | |
| 27073 | + goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY; | |
| 27074 | + } | |
| 27075 | + } | |
| 27076 | + if( goLockless ){ | |
| 27077 | + pCtx->conchHeld = -1; /* read only FS/ lockless */ | |
| 27078 | + rc = SQLITE_OK; | |
| 27079 | + } | |
| 27080 | + } | |
| 26529 | 27081 | } |
| 26530 | 27082 | if( rc==SQLITE_OK && lockPath ){ |
| 26531 | 27083 | pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); |
| 26532 | 27084 | } |
| 26533 | 27085 | |
| 27086 | + if( rc==SQLITE_OK ){ | |
| 27087 | + pCtx->dbPath = sqlite3DbStrDup(0, dbPath); | |
| 27088 | + if( pCtx->dbPath==NULL ){ | |
| 27089 | + rc = SQLITE_NOMEM; | |
| 27090 | + } | |
| 27091 | + } | |
| 26534 | 27092 | if( rc==SQLITE_OK ){ |
| 26535 | 27093 | /* all memory is allocated, proxys are created and assigned, |
| 26536 | 27094 | ** switch the locking context and pMethod then return. |
| 26537 | 27095 | */ |
| 26538 | - pCtx->dbPath = sqlite3DbStrDup(0, dbPath); | |
| 26539 | 27096 | pCtx->oldLockingContext = pFile->lockingContext; |
| 26540 | 27097 | pFile->lockingContext = pCtx; |
| 26541 | 27098 | pCtx->pOldMethod = pFile->pMethod; |
| 26542 | 27099 | pFile->pMethod = &proxyIoMethods; |
| 26543 | 27100 | }else{ |
| 26544 | 27101 | if( pCtx->conchFile ){ |
| 26545 | - rc = pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); | |
| 26546 | - if( rc ) return rc; | |
| 27102 | + pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); | |
| 26547 | 27103 | sqlite3_free(pCtx->conchFile); |
| 26548 | 27104 | } |
| 27105 | + sqlite3_free(pCtx->lockProxyPath); | |
| 26549 | 27106 | sqlite3_free(pCtx->conchFilePath); |
| 26550 | 27107 | sqlite3_free(pCtx); |
| 26551 | 27108 | } |
| 26552 | 27109 | OSTRACE3("TRANSPROXY %d %s\n", pFile->h, |
| 26553 | 27110 | (rc==SQLITE_OK ? "ok" : "failed")); |
| @@ -26632,12 +27189,16 @@ | ||
| 26632 | 27189 | static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) { |
| 26633 | 27190 | unixFile *pFile = (unixFile*)id; |
| 26634 | 27191 | int rc = proxyTakeConch(pFile); |
| 26635 | 27192 | if( rc==SQLITE_OK ){ |
| 26636 | 27193 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26637 | - unixFile *proxy = pCtx->lockProxy; | |
| 26638 | - return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut); | |
| 27194 | + if( pCtx->conchHeld>0 ){ | |
| 27195 | + unixFile *proxy = pCtx->lockProxy; | |
| 27196 | + return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut); | |
| 27197 | + }else{ /* conchHeld < 0 is lockless */ | |
| 27198 | + pResOut=0; | |
| 27199 | + } | |
| 26639 | 27200 | } |
| 26640 | 27201 | return rc; |
| 26641 | 27202 | } |
| 26642 | 27203 | |
| 26643 | 27204 | /* |
| @@ -26667,13 +27228,17 @@ | ||
| 26667 | 27228 | static int proxyLock(sqlite3_file *id, int locktype) { |
| 26668 | 27229 | unixFile *pFile = (unixFile*)id; |
| 26669 | 27230 | int rc = proxyTakeConch(pFile); |
| 26670 | 27231 | if( rc==SQLITE_OK ){ |
| 26671 | 27232 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26672 | - unixFile *proxy = pCtx->lockProxy; | |
| 26673 | - rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype); | |
| 26674 | - pFile->locktype = proxy->locktype; | |
| 27233 | + if( pCtx->conchHeld>0 ){ | |
| 27234 | + unixFile *proxy = pCtx->lockProxy; | |
| 27235 | + rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype); | |
| 27236 | + pFile->locktype = proxy->locktype; | |
| 27237 | + }else{ | |
| 27238 | + /* conchHeld < 0 is lockless */ | |
| 27239 | + } | |
| 26675 | 27240 | } |
| 26676 | 27241 | return rc; |
| 26677 | 27242 | } |
| 26678 | 27243 | |
| 26679 | 27244 | |
| @@ -26687,13 +27252,17 @@ | ||
| 26687 | 27252 | static int proxyUnlock(sqlite3_file *id, int locktype) { |
| 26688 | 27253 | unixFile *pFile = (unixFile*)id; |
| 26689 | 27254 | int rc = proxyTakeConch(pFile); |
| 26690 | 27255 | if( rc==SQLITE_OK ){ |
| 26691 | 27256 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26692 | - unixFile *proxy = pCtx->lockProxy; | |
| 26693 | - rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype); | |
| 26694 | - pFile->locktype = proxy->locktype; | |
| 27257 | + if( pCtx->conchHeld>0 ){ | |
| 27258 | + unixFile *proxy = pCtx->lockProxy; | |
| 27259 | + rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype); | |
| 27260 | + pFile->locktype = proxy->locktype; | |
| 27261 | + }else{ | |
| 27262 | + /* conchHeld < 0 is lockless */ | |
| 27263 | + } | |
| 26695 | 27264 | } |
| 26696 | 27265 | return rc; |
| 26697 | 27266 | } |
| 26698 | 27267 | |
| 26699 | 27268 | /* |
| @@ -26816,11 +27385,10 @@ | ||
| 26816 | 27385 | #else |
| 26817 | 27386 | UNIXVFS("unix", posixIoFinder ), |
| 26818 | 27387 | #endif |
| 26819 | 27388 | UNIXVFS("unix-none", nolockIoFinder ), |
| 26820 | 27389 | UNIXVFS("unix-dotfile", dotlockIoFinder ), |
| 26821 | - UNIXVFS("unix-wfl", posixWflIoFinder ), | |
| 26822 | 27390 | #if OS_VXWORKS |
| 26823 | 27391 | UNIXVFS("unix-namedsem", semIoFinder ), |
| 26824 | 27392 | #endif |
| 26825 | 27393 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 26826 | 27394 | UNIXVFS("unix-posix", posixIoFinder ), |
| @@ -26828,10 +27396,11 @@ | ||
| 26828 | 27396 | UNIXVFS("unix-flock", flockIoFinder ), |
| 26829 | 27397 | #endif |
| 26830 | 27398 | #endif |
| 26831 | 27399 | #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) |
| 26832 | 27400 | UNIXVFS("unix-afp", afpIoFinder ), |
| 27401 | + UNIXVFS("unix-nfs", nfsIoFinder ), | |
| 26833 | 27402 | UNIXVFS("unix-proxy", proxyIoFinder ), |
| 26834 | 27403 | #endif |
| 26835 | 27404 | }; |
| 26836 | 27405 | unsigned int i; /* Loop counter */ |
| 26837 | 27406 | |
| @@ -28491,11 +29060,11 @@ | ||
| 28491 | 29060 | free(zConverted); |
| 28492 | 29061 | if( flags & SQLITE_OPEN_READWRITE ){ |
| 28493 | 29062 | return winOpen(pVfs, zName, id, |
| 28494 | 29063 | ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); |
| 28495 | 29064 | }else{ |
| 28496 | - return SQLITE_CANTOPEN; | |
| 29065 | + return SQLITE_CANTOPEN_BKPT; | |
| 28497 | 29066 | } |
| 28498 | 29067 | } |
| 28499 | 29068 | if( pOutFlags ){ |
| 28500 | 29069 | if( flags & SQLITE_OPEN_READWRITE ){ |
| 28501 | 29070 | *pOutFlags = SQLITE_OPEN_READWRITE; |
| @@ -28513,11 +29082,11 @@ | ||
| 28513 | 29082 | (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) |
| 28514 | 29083 | && !winceCreateLock(zName, pFile) |
| 28515 | 29084 | ){ |
| 28516 | 29085 | CloseHandle(h); |
| 28517 | 29086 | free(zConverted); |
| 28518 | - return SQLITE_CANTOPEN; | |
| 29087 | + return SQLITE_CANTOPEN_BKPT; | |
| 28519 | 29088 | } |
| 28520 | 29089 | if( isTemp ){ |
| 28521 | 29090 | pFile->zDeleteOnClose = zConverted; |
| 28522 | 29091 | }else |
| 28523 | 29092 | #endif |
| @@ -29653,10 +30222,11 @@ | ||
| 29653 | 30222 | expensive_assert( pcacheCheckSynced(pCache) ); |
| 29654 | 30223 | for(pPg=pCache->pSynced; |
| 29655 | 30224 | pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); |
| 29656 | 30225 | pPg=pPg->pDirtyPrev |
| 29657 | 30226 | ); |
| 30227 | + pCache->pSynced = pPg; | |
| 29658 | 30228 | if( !pPg ){ |
| 29659 | 30229 | for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); |
| 29660 | 30230 | } |
| 29661 | 30231 | if( pPg ){ |
| 29662 | 30232 | int rc; |
| @@ -34067,13 +34637,11 @@ | ||
| 34067 | 34637 | ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to |
| 34068 | 34638 | ** make the file smaller (presumably by auto-vacuum code). Do not write |
| 34069 | 34639 | ** any such pages to the file. |
| 34070 | 34640 | ** |
| 34071 | 34641 | ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag |
| 34072 | - ** set (set by sqlite3PagerDontWrite()). Note that if compiled with | |
| 34073 | - ** SQLITE_SECURE_DELETE the PGHDR_DONT_WRITE bit is never set and so | |
| 34074 | - ** the second test is always true. | |
| 34642 | + ** set (set by sqlite3PagerDontWrite()). | |
| 34075 | 34643 | */ |
| 34076 | 34644 | if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ |
| 34077 | 34645 | i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ |
| 34078 | 34646 | char *pData; /* Data to write */ |
| 34079 | 34647 | |
| @@ -34356,11 +34924,11 @@ | ||
| 34356 | 34924 | ** the database being opened will be more than pVfs->mxPathname |
| 34357 | 34925 | ** bytes in length. This means the database cannot be opened, |
| 34358 | 34926 | ** as it will not be possible to open the journal file or even |
| 34359 | 34927 | ** check for a hot-journal before reading. |
| 34360 | 34928 | */ |
| 34361 | - rc = SQLITE_CANTOPEN; | |
| 34929 | + rc = SQLITE_CANTOPEN_BKPT; | |
| 34362 | 34930 | } |
| 34363 | 34931 | if( rc!=SQLITE_OK ){ |
| 34364 | 34932 | sqlite3_free(zPathname); |
| 34365 | 34933 | return rc; |
| 34366 | 34934 | } |
| @@ -34815,11 +35383,11 @@ | ||
| 34815 | 35383 | int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; |
| 34816 | 35384 | assert( !pPager->tempFile ); |
| 34817 | 35385 | rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); |
| 34818 | 35386 | assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); |
| 34819 | 35387 | if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ |
| 34820 | - rc = SQLITE_CANTOPEN; | |
| 35388 | + rc = SQLITE_CANTOPEN_BKPT; | |
| 34821 | 35389 | sqlite3OsClose(pPager->jfd); |
| 34822 | 35390 | } |
| 34823 | 35391 | }else{ |
| 34824 | 35392 | /* If the journal does not exist, it usually means that some |
| 34825 | 35393 | ** other connection managed to get in and roll it back before |
| @@ -35034,11 +35602,11 @@ | ||
| 35034 | 35602 | rc = sqlite3PagerPagecount(pPager, &nMax); |
| 35035 | 35603 | if( rc!=SQLITE_OK ){ |
| 35036 | 35604 | goto pager_acquire_err; |
| 35037 | 35605 | } |
| 35038 | 35606 | |
| 35039 | - if( MEMDB || nMax<(int)pgno || noContent ){ | |
| 35607 | + if( MEMDB || nMax<(int)pgno || noContent || !isOpen(pPager->fd) ){ | |
| 35040 | 35608 | if( pgno>pPager->mxPgno ){ |
| 35041 | 35609 | rc = SQLITE_FULL; |
| 35042 | 35610 | goto pager_acquire_err; |
| 35043 | 35611 | } |
| 35044 | 35612 | if( noContent ){ |
| @@ -35054,13 +35622,12 @@ | ||
| 35054 | 35622 | testcase( rc==SQLITE_NOMEM ); |
| 35055 | 35623 | } |
| 35056 | 35624 | TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); |
| 35057 | 35625 | testcase( rc==SQLITE_NOMEM ); |
| 35058 | 35626 | sqlite3EndBenignMalloc(); |
| 35059 | - }else{ | |
| 35060 | - memset(pPg->pData, 0, pPager->pageSize); | |
| 35061 | 35627 | } |
| 35628 | + memset(pPg->pData, 0, pPager->pageSize); | |
| 35062 | 35629 | IOTRACE(("ZERO %p %d\n", pPager, pgno)); |
| 35063 | 35630 | }else{ |
| 35064 | 35631 | assert( pPg->pPager==pPager ); |
| 35065 | 35632 | rc = readDbPage(pPg); |
| 35066 | 35633 | if( rc!=SQLITE_OK ){ |
| @@ -35578,11 +36145,10 @@ | ||
| 35578 | 36145 | SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ |
| 35579 | 36146 | return pPg->flags&PGHDR_DIRTY; |
| 35580 | 36147 | } |
| 35581 | 36148 | #endif |
| 35582 | 36149 | |
| 35583 | -#ifndef SQLITE_SECURE_DELETE | |
| 35584 | 36150 | /* |
| 35585 | 36151 | ** A call to this routine tells the pager that it is not necessary to |
| 35586 | 36152 | ** write the information on page pPg back to the disk, even though |
| 35587 | 36153 | ** that page might be marked as dirty. This happens, for example, when |
| 35588 | 36154 | ** the page has been added as a leaf of the freelist and so its |
| @@ -35604,11 +36170,10 @@ | ||
| 35604 | 36170 | #ifdef SQLITE_CHECK_PAGES |
| 35605 | 36171 | pPg->pageHash = pager_pagehash(pPg); |
| 35606 | 36172 | #endif |
| 35607 | 36173 | } |
| 35608 | 36174 | } |
| 35609 | -#endif /* !defined(SQLITE_SECURE_DELETE) */ | |
| 35610 | 36175 | |
| 35611 | 36176 | /* |
| 35612 | 36177 | ** This routine is called to increment the value of the database file |
| 35613 | 36178 | ** change-counter, stored as a 4-byte big-endian integer starting at |
| 35614 | 36179 | ** byte offset 24 of the pager file. |
| @@ -36174,34 +36739,38 @@ | ||
| 36174 | 36739 | |
| 36175 | 36740 | /* Figure out how many savepoints will still be active after this |
| 36176 | 36741 | ** operation. Store this value in nNew. Then free resources associated |
| 36177 | 36742 | ** with any savepoints that are destroyed by this operation. |
| 36178 | 36743 | */ |
| 36179 | - nNew = iSavepoint + (op==SAVEPOINT_ROLLBACK); | |
| 36744 | + nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1); | |
| 36180 | 36745 | for(ii=nNew; ii<pPager->nSavepoint; ii++){ |
| 36181 | 36746 | sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); |
| 36182 | 36747 | } |
| 36183 | 36748 | pPager->nSavepoint = nNew; |
| 36184 | 36749 | |
| 36185 | - /* If this is a rollback operation, playback the specified savepoint. | |
| 36750 | + /* If this is a release of the outermost savepoint, truncate | |
| 36751 | + ** the sub-journal to zero bytes in size. */ | |
| 36752 | + if( op==SAVEPOINT_RELEASE ){ | |
| 36753 | + if( nNew==0 && isOpen(pPager->sjfd) ){ | |
| 36754 | + /* Only truncate if it is an in-memory sub-journal. */ | |
| 36755 | + if( sqlite3IsMemJournal(pPager->sjfd) ){ | |
| 36756 | + rc = sqlite3OsTruncate(pPager->sjfd, 0); | |
| 36757 | + } | |
| 36758 | + pPager->nSubRec = 0; | |
| 36759 | + } | |
| 36760 | + } | |
| 36761 | + /* Else this is a rollback operation, playback the specified savepoint. | |
| 36186 | 36762 | ** If this is a temp-file, it is possible that the journal file has |
| 36187 | 36763 | ** not yet been opened. In this case there have been no changes to |
| 36188 | 36764 | ** the database file, so the playback operation can be skipped. |
| 36189 | 36765 | */ |
| 36190 | - if( op==SAVEPOINT_ROLLBACK && isOpen(pPager->jfd) ){ | |
| 36766 | + else if( isOpen(pPager->jfd) ){ | |
| 36191 | 36767 | PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; |
| 36192 | 36768 | rc = pagerPlaybackSavepoint(pPager, pSavepoint); |
| 36193 | 36769 | assert(rc!=SQLITE_DONE); |
| 36194 | 36770 | } |
| 36195 | 36771 | |
| 36196 | - /* If this is a release of the outermost savepoint, truncate | |
| 36197 | - ** the sub-journal to zero bytes in size. */ | |
| 36198 | - if( nNew==0 && op==SAVEPOINT_RELEASE && isOpen(pPager->sjfd) ){ | |
| 36199 | - assert( rc==SQLITE_OK ); | |
| 36200 | - rc = sqlite3OsTruncate(pPager->sjfd, 0); | |
| 36201 | - pPager->nSubRec = 0; | |
| 36202 | - } | |
| 36203 | 36772 | } |
| 36204 | 36773 | return rc; |
| 36205 | 36774 | } |
| 36206 | 36775 | |
| 36207 | 36776 | /* |
| @@ -36957,10 +37526,11 @@ | ||
| 36957 | 37526 | sqlite3 *db; /* Database connection currently using this Btree */ |
| 36958 | 37527 | BtCursor *pCursor; /* A list of all open cursors */ |
| 36959 | 37528 | MemPage *pPage1; /* First page of the database */ |
| 36960 | 37529 | u8 readOnly; /* True if the underlying file is readonly */ |
| 36961 | 37530 | u8 pageSizeFixed; /* True if the page size can no longer be changed */ |
| 37531 | + u8 secureDelete; /* True if secure_delete is enabled */ | |
| 36962 | 37532 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 36963 | 37533 | u8 autoVacuum; /* True if auto-vacuum is enabled */ |
| 36964 | 37534 | u8 incrVacuum; /* True if incr-vacuum is enabled */ |
| 36965 | 37535 | #endif |
| 36966 | 37536 | u16 pageSize; /* Total number of bytes on a page */ |
| @@ -38780,15 +39350,15 @@ | ||
| 38780 | 39350 | assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); |
| 38781 | 39351 | assert( (start + size)<=pPage->pBt->usableSize ); |
| 38782 | 39352 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 38783 | 39353 | assert( size>=0 ); /* Minimum cell size is 4 */ |
| 38784 | 39354 | |
| 38785 | -#ifdef SQLITE_SECURE_DELETE | |
| 38786 | - /* Overwrite deleted information with zeros when the SECURE_DELETE | |
| 38787 | - ** option is enabled at compile-time */ | |
| 38788 | - memset(&data[start], 0, size); | |
| 38789 | -#endif | |
| 39355 | + if( pPage->pBt->secureDelete ){ | |
| 39356 | + /* Overwrite deleted information with zeros when the secure_delete | |
| 39357 | + ** option is enabled */ | |
| 39358 | + memset(&data[start], 0, size); | |
| 39359 | + } | |
| 38790 | 39360 | |
| 38791 | 39361 | /* Add the space back into the linked list of freeblocks. Note that |
| 38792 | 39362 | ** even though the freeblock list was checked by btreeInitPage(), |
| 38793 | 39363 | ** btreeInitPage() did not detect overlapping cells or |
| 38794 | 39364 | ** freeblocks that overlapped cells. Nor does it detect when the |
| @@ -39016,13 +39586,13 @@ | ||
| 39016 | 39586 | assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); |
| 39017 | 39587 | assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); |
| 39018 | 39588 | assert( sqlite3PagerGetData(pPage->pDbPage) == data ); |
| 39019 | 39589 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 39020 | 39590 | assert( sqlite3_mutex_held(pBt->mutex) ); |
| 39021 | -#ifdef SQLITE_SECURE_DELETE | |
| 39022 | - memset(&data[hdr], 0, pBt->usableSize - hdr); | |
| 39023 | -#endif | |
| 39591 | + if( pBt->secureDelete ){ | |
| 39592 | + memset(&data[hdr], 0, pBt->usableSize - hdr); | |
| 39593 | + } | |
| 39024 | 39594 | data[hdr] = (char)flags; |
| 39025 | 39595 | first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); |
| 39026 | 39596 | memset(&data[hdr+1], 0, 4); |
| 39027 | 39597 | data[hdr+7] = 0; |
| 39028 | 39598 | put2byte(&data[hdr+5], pBt->usableSize); |
| @@ -39338,10 +39908,13 @@ | ||
| 39338 | 39908 | p->pBt = pBt; |
| 39339 | 39909 | |
| 39340 | 39910 | pBt->pCursor = 0; |
| 39341 | 39911 | pBt->pPage1 = 0; |
| 39342 | 39912 | pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); |
| 39913 | +#ifdef SQLITE_SECURE_DELETE | |
| 39914 | + pBt->secureDelete = 1; | |
| 39915 | +#endif | |
| 39343 | 39916 | pBt->pageSize = get2byte(&zDbHeader[16]); |
| 39344 | 39917 | if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE |
| 39345 | 39918 | || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ |
| 39346 | 39919 | pBt->pageSize = 0; |
| 39347 | 39920 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| @@ -39694,10 +40267,27 @@ | ||
| 39694 | 40267 | sqlite3BtreeEnter(p); |
| 39695 | 40268 | n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); |
| 39696 | 40269 | sqlite3BtreeLeave(p); |
| 39697 | 40270 | return n; |
| 39698 | 40271 | } |
| 40272 | + | |
| 40273 | +/* | |
| 40274 | +** Set the secureDelete flag if newFlag is 0 or 1. If newFlag is -1, | |
| 40275 | +** then make no changes. Always return the value of the secureDelete | |
| 40276 | +** setting after the change. | |
| 40277 | +*/ | |
| 40278 | +SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ | |
| 40279 | + int b; | |
| 40280 | + if( p==0 ) return 0; | |
| 40281 | + sqlite3BtreeEnter(p); | |
| 40282 | + if( newFlag>=0 ){ | |
| 40283 | + p->pBt->secureDelete = (newFlag!=0) ? 1 : 0; | |
| 40284 | + } | |
| 40285 | + b = p->pBt->secureDelete; | |
| 40286 | + sqlite3BtreeLeave(p); | |
| 40287 | + return b; | |
| 40288 | +} | |
| 39699 | 40289 | #endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ |
| 39700 | 40290 | |
| 39701 | 40291 | /* |
| 39702 | 40292 | ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' |
| 39703 | 40293 | ** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it |
| @@ -42437,21 +43027,21 @@ | ||
| 42437 | 43027 | rc = sqlite3PagerWrite(pPage1->pDbPage); |
| 42438 | 43028 | if( rc ) goto freepage_out; |
| 42439 | 43029 | nFree = get4byte(&pPage1->aData[36]); |
| 42440 | 43030 | put4byte(&pPage1->aData[36], nFree+1); |
| 42441 | 43031 | |
| 42442 | -#ifdef SQLITE_SECURE_DELETE | |
| 42443 | - /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then | |
| 42444 | - ** always fully overwrite deleted information with zeros. | |
| 42445 | - */ | |
| 42446 | - if( (!pPage && (rc = btreeGetPage(pBt, iPage, &pPage, 0))) | |
| 42447 | - || (rc = sqlite3PagerWrite(pPage->pDbPage)) | |
| 42448 | - ){ | |
| 42449 | - goto freepage_out; | |
| 42450 | - } | |
| 42451 | - memset(pPage->aData, 0, pPage->pBt->pageSize); | |
| 42452 | -#endif | |
| 43032 | + if( pBt->secureDelete ){ | |
| 43033 | + /* If the secure_delete option is enabled, then | |
| 43034 | + ** always fully overwrite deleted information with zeros. | |
| 43035 | + */ | |
| 43036 | + if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) ) | |
| 43037 | + || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0) | |
| 43038 | + ){ | |
| 43039 | + goto freepage_out; | |
| 43040 | + } | |
| 43041 | + memset(pPage->aData, 0, pPage->pBt->pageSize); | |
| 43042 | + } | |
| 42453 | 43043 | |
| 42454 | 43044 | /* If the database supports auto-vacuum, write an entry in the pointer-map |
| 42455 | 43045 | ** to indicate that the page is free. |
| 42456 | 43046 | */ |
| 42457 | 43047 | if( ISAUTOVACUUM ){ |
| @@ -42498,15 +43088,13 @@ | ||
| 42498 | 43088 | */ |
| 42499 | 43089 | rc = sqlite3PagerWrite(pTrunk->pDbPage); |
| 42500 | 43090 | if( rc==SQLITE_OK ){ |
| 42501 | 43091 | put4byte(&pTrunk->aData[4], nLeaf+1); |
| 42502 | 43092 | put4byte(&pTrunk->aData[8+nLeaf*4], iPage); |
| 42503 | -#ifndef SQLITE_SECURE_DELETE | |
| 42504 | - if( pPage ){ | |
| 43093 | + if( pPage && !pBt->secureDelete ){ | |
| 42505 | 43094 | sqlite3PagerDontWrite(pPage->pDbPage); |
| 42506 | 43095 | } |
| 42507 | -#endif | |
| 42508 | 43096 | rc = btreeSetHasContent(pBt, iPage); |
| 42509 | 43097 | } |
| 42510 | 43098 | TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); |
| 42511 | 43099 | goto freepage_out; |
| 42512 | 43100 | } |
| @@ -42576,11 +43164,29 @@ | ||
| 42576 | 43164 | } |
| 42577 | 43165 | if( nOvfl ){ |
| 42578 | 43166 | rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); |
| 42579 | 43167 | if( rc ) return rc; |
| 42580 | 43168 | } |
| 42581 | - rc = freePage2(pBt, pOvfl, ovflPgno); | |
| 43169 | + | |
| 43170 | + if( (pOvfl || (pOvfl = btreePageLookup(pBt, ovflPgno))) | |
| 43171 | + && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1 | |
| 43172 | + ){ | |
| 43173 | + /* There is no reason any cursor should have an outstanding reference | |
| 43174 | + ** to an overflow page belonging to a cell that is being deleted/updated. | |
| 43175 | + ** So if there exists more than one reference to this page, then it | |
| 43176 | + ** must not really be an overflow page and the database must be corrupt. | |
| 43177 | + ** It is helpful to detect this before calling freePage2(), as | |
| 43178 | + ** freePage2() may zero the page contents if secure-delete mode is | |
| 43179 | + ** enabled. If this 'overflow' page happens to be a page that the | |
| 43180 | + ** caller is iterating through or using in some other way, this | |
| 43181 | + ** can be problematic. | |
| 43182 | + */ | |
| 43183 | + rc = SQLITE_CORRUPT_BKPT; | |
| 43184 | + }else{ | |
| 43185 | + rc = freePage2(pBt, pOvfl, ovflPgno); | |
| 43186 | + } | |
| 43187 | + | |
| 42582 | 43188 | if( pOvfl ){ |
| 42583 | 43189 | sqlite3PagerUnref(pOvfl->pDbPage); |
| 42584 | 43190 | } |
| 42585 | 43191 | if( rc ) return rc; |
| 42586 | 43192 | ovflPgno = iNext; |
| @@ -42820,11 +43426,11 @@ | ||
| 42820 | 43426 | int sz, /* Bytes of content in pCell */ |
| 42821 | 43427 | u8 *pTemp, /* Temp storage space for pCell, if needed */ |
| 42822 | 43428 | Pgno iChild, /* If non-zero, replace first 4 bytes with this value */ |
| 42823 | 43429 | int *pRC /* Read and write return code from here */ |
| 42824 | 43430 | ){ |
| 42825 | - int idx; /* Where to write new cell content in data[] */ | |
| 43431 | + int idx = 0; /* Where to write new cell content in data[] */ | |
| 42826 | 43432 | int j; /* Loop counter */ |
| 42827 | 43433 | int end; /* First byte past the last cell pointer in data[] */ |
| 42828 | 43434 | int ins; /* Index in data[] where new cell pointer is inserted */ |
| 42829 | 43435 | int cellOffset; /* Address of first cell pointer in data[] */ |
| 42830 | 43436 | u8 *data; /* The content of the whole page */ |
| @@ -43311,14 +43917,14 @@ | ||
| 43311 | 43917 | ** Unless SQLite is compiled in secure-delete mode. In this case, |
| 43312 | 43918 | ** the dropCell() routine will overwrite the entire cell with zeroes. |
| 43313 | 43919 | ** In this case, temporarily copy the cell into the aOvflSpace[] |
| 43314 | 43920 | ** buffer. It will be copied out again as soon as the aSpace[] buffer |
| 43315 | 43921 | ** is allocated. */ |
| 43316 | -#ifdef SQLITE_SECURE_DELETE | |
| 43317 | - memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]); | |
| 43318 | - apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; | |
| 43319 | -#endif | |
| 43922 | + if( pBt->secureDelete ){ | |
| 43923 | + memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]); | |
| 43924 | + apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; | |
| 43925 | + } | |
| 43320 | 43926 | dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); |
| 43321 | 43927 | } |
| 43322 | 43928 | } |
| 43323 | 43929 | |
| 43324 | 43930 | /* Make nMaxCells a multiple of 4 in order to preserve 8-byte |
| @@ -43434,11 +44040,11 @@ | ||
| 43434 | 44040 | szNew[k] = subtotal - szCell[i]; |
| 43435 | 44041 | cntNew[k] = i; |
| 43436 | 44042 | if( leafData ){ i--; } |
| 43437 | 44043 | subtotal = 0; |
| 43438 | 44044 | k++; |
| 43439 | - if( k>NB+1 ){ rc = SQLITE_CORRUPT; goto balance_cleanup; } | |
| 44045 | + if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } | |
| 43440 | 44046 | } |
| 43441 | 44047 | } |
| 43442 | 44048 | szNew[k] = subtotal; |
| 43443 | 44049 | cntNew[k] = nCell; |
| 43444 | 44050 | k++; |
| @@ -43488,11 +44094,11 @@ | ||
| 43488 | 44094 | |
| 43489 | 44095 | /* |
| 43490 | 44096 | ** Allocate k new pages. Reuse old pages where possible. |
| 43491 | 44097 | */ |
| 43492 | 44098 | if( apOld[0]->pgno<=1 ){ |
| 43493 | - rc = SQLITE_CORRUPT; | |
| 44099 | + rc = SQLITE_CORRUPT_BKPT; | |
| 43494 | 44100 | goto balance_cleanup; |
| 43495 | 44101 | } |
| 43496 | 44102 | pageFlags = apOld[0]->aData[0]; |
| 43497 | 44103 | for(i=0; i<k; i++){ |
| 43498 | 44104 | MemPage *pNew; |
| @@ -44926,11 +45532,13 @@ | ||
| 44926 | 45532 | ** the root of the tree. |
| 44927 | 45533 | */ |
| 44928 | 45534 | static int checkTreePage( |
| 44929 | 45535 | IntegrityCk *pCheck, /* Context for the sanity check */ |
| 44930 | 45536 | int iPage, /* Page number of the page to check */ |
| 44931 | - char *zParentContext /* Parent context */ | |
| 45537 | + char *zParentContext, /* Parent context */ | |
| 45538 | + i64 *pnParentMinKey, | |
| 45539 | + i64 *pnParentMaxKey | |
| 44932 | 45540 | ){ |
| 44933 | 45541 | MemPage *pPage; |
| 44934 | 45542 | int i, rc, depth, d2, pgno, cnt; |
| 44935 | 45543 | int hdr, cellStart; |
| 44936 | 45544 | int nCell; |
| @@ -44937,10 +45545,12 @@ | ||
| 44937 | 45545 | u8 *data; |
| 44938 | 45546 | BtShared *pBt; |
| 44939 | 45547 | int usableSize; |
| 44940 | 45548 | char zContext[100]; |
| 44941 | 45549 | char *hit = 0; |
| 45550 | + i64 nMinKey = 0; | |
| 45551 | + i64 nMaxKey = 0; | |
| 44942 | 45552 | |
| 44943 | 45553 | sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); |
| 44944 | 45554 | |
| 44945 | 45555 | /* Check that the page exists |
| 44946 | 45556 | */ |
| @@ -44979,10 +45589,20 @@ | ||
| 44979 | 45589 | "On tree page %d cell %d: ", iPage, i); |
| 44980 | 45590 | pCell = findCell(pPage,i); |
| 44981 | 45591 | btreeParseCellPtr(pPage, pCell, &info); |
| 44982 | 45592 | sz = info.nData; |
| 44983 | 45593 | if( !pPage->intKey ) sz += (int)info.nKey; |
| 45594 | + /* For intKey pages, check that the keys are in order. | |
| 45595 | + */ | |
| 45596 | + else if( i==0 ) nMinKey = nMaxKey = info.nKey; | |
| 45597 | + else{ | |
| 45598 | + if( info.nKey <= nMaxKey ){ | |
| 45599 | + checkAppendMsg(pCheck, zContext, | |
| 45600 | + "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey); | |
| 45601 | + } | |
| 45602 | + nMaxKey = info.nKey; | |
| 45603 | + } | |
| 44984 | 45604 | assert( sz==info.nPayload ); |
| 44985 | 45605 | if( (sz>info.nLocal) |
| 44986 | 45606 | && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize]) |
| 44987 | 45607 | ){ |
| 44988 | 45608 | int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); |
| @@ -45002,29 +45622,66 @@ | ||
| 45002 | 45622 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45003 | 45623 | if( pBt->autoVacuum ){ |
| 45004 | 45624 | checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); |
| 45005 | 45625 | } |
| 45006 | 45626 | #endif |
| 45007 | - d2 = checkTreePage(pCheck, pgno, zContext); | |
| 45627 | + d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey); | |
| 45008 | 45628 | if( i>0 && d2!=depth ){ |
| 45009 | 45629 | checkAppendMsg(pCheck, zContext, "Child page depth differs"); |
| 45010 | 45630 | } |
| 45011 | 45631 | depth = d2; |
| 45012 | 45632 | } |
| 45013 | 45633 | } |
| 45634 | + | |
| 45014 | 45635 | if( !pPage->leaf ){ |
| 45015 | 45636 | pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); |
| 45016 | 45637 | sqlite3_snprintf(sizeof(zContext), zContext, |
| 45017 | 45638 | "On page %d at right child: ", iPage); |
| 45018 | 45639 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45019 | 45640 | if( pBt->autoVacuum ){ |
| 45020 | - checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0); | |
| 45641 | + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); | |
| 45021 | 45642 | } |
| 45022 | 45643 | #endif |
| 45023 | - checkTreePage(pCheck, pgno, zContext); | |
| 45644 | + checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey); | |
| 45024 | 45645 | } |
| 45025 | 45646 | |
| 45647 | + /* For intKey leaf pages, check that the min/max keys are in order | |
| 45648 | + ** with any left/parent/right pages. | |
| 45649 | + */ | |
| 45650 | + if( pPage->leaf && pPage->intKey ){ | |
| 45651 | + /* if we are a left child page */ | |
| 45652 | + if( pnParentMinKey ){ | |
| 45653 | + /* if we are the left most child page */ | |
| 45654 | + if( !pnParentMaxKey ){ | |
| 45655 | + if( nMaxKey > *pnParentMinKey ){ | |
| 45656 | + checkAppendMsg(pCheck, zContext, | |
| 45657 | + "Rowid %lld out of order (max larger than parent min of %lld)", | |
| 45658 | + nMaxKey, *pnParentMinKey); | |
| 45659 | + } | |
| 45660 | + }else{ | |
| 45661 | + if( nMinKey <= *pnParentMinKey ){ | |
| 45662 | + checkAppendMsg(pCheck, zContext, | |
| 45663 | + "Rowid %lld out of order (min less than parent min of %lld)", | |
| 45664 | + nMinKey, *pnParentMinKey); | |
| 45665 | + } | |
| 45666 | + if( nMaxKey > *pnParentMaxKey ){ | |
| 45667 | + checkAppendMsg(pCheck, zContext, | |
| 45668 | + "Rowid %lld out of order (max larger than parent max of %lld)", | |
| 45669 | + nMaxKey, *pnParentMaxKey); | |
| 45670 | + } | |
| 45671 | + *pnParentMinKey = nMaxKey; | |
| 45672 | + } | |
| 45673 | + /* else if we're a right child page */ | |
| 45674 | + } else if( pnParentMaxKey ){ | |
| 45675 | + if( nMinKey <= *pnParentMaxKey ){ | |
| 45676 | + checkAppendMsg(pCheck, zContext, | |
| 45677 | + "Rowid %lld out of order (min less than parent max of %lld)", | |
| 45678 | + nMinKey, *pnParentMaxKey); | |
| 45679 | + } | |
| 45680 | + } | |
| 45681 | + } | |
| 45682 | + | |
| 45026 | 45683 | /* Check for complete coverage of the page |
| 45027 | 45684 | */ |
| 45028 | 45685 | data = pPage->aData; |
| 45029 | 45686 | hdr = pPage->hdrOffset; |
| 45030 | 45687 | hit = sqlite3PageMalloc( pBt->pageSize ); |
| @@ -45044,11 +45701,11 @@ | ||
| 45044 | 45701 | if( pc<=usableSize-4 ){ |
| 45045 | 45702 | size = cellSizePtr(pPage, &data[pc]); |
| 45046 | 45703 | } |
| 45047 | 45704 | if( (pc+size-1)>=usableSize ){ |
| 45048 | 45705 | checkAppendMsg(pCheck, 0, |
| 45049 | - "Corruption detected in cell %d on page %d",i,iPage,0); | |
| 45706 | + "Corruption detected in cell %d on page %d",i,iPage); | |
| 45050 | 45707 | }else{ |
| 45051 | 45708 | for(j=pc+size-1; j>=pc; j--) hit[j]++; |
| 45052 | 45709 | } |
| 45053 | 45710 | } |
| 45054 | 45711 | i = get2byte(&data[hdr+1]); |
| @@ -45150,11 +45807,11 @@ | ||
| 45150 | 45807 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45151 | 45808 | if( pBt->autoVacuum && aRoot[i]>1 ){ |
| 45152 | 45809 | checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); |
| 45153 | 45810 | } |
| 45154 | 45811 | #endif |
| 45155 | - checkTreePage(&sCheck, aRoot[i], "List of tree roots: "); | |
| 45812 | + checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL); | |
| 45156 | 45813 | } |
| 45157 | 45814 | |
| 45158 | 45815 | /* Make sure every page in the file is referenced |
| 45159 | 45816 | */ |
| 45160 | 45817 | for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ |
| @@ -45483,14 +46140,14 @@ | ||
| 45483 | 46140 | sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory"); |
| 45484 | 46141 | rc = SQLITE_NOMEM; |
| 45485 | 46142 | }else{ |
| 45486 | 46143 | pParse->db = pDb; |
| 45487 | 46144 | if( sqlite3OpenTempDatabase(pParse) ){ |
| 45488 | - sqlite3ErrorClear(pParse); | |
| 45489 | 46145 | sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); |
| 45490 | 46146 | rc = SQLITE_ERROR; |
| 45491 | 46147 | } |
| 46148 | + sqlite3DbFree(pErrorDb, pParse->zErrMsg); | |
| 45492 | 46149 | sqlite3StackFree(pErrorDb, pParse); |
| 45493 | 46150 | } |
| 45494 | 46151 | if( rc ){ |
| 45495 | 46152 | return 0; |
| 45496 | 46153 | } |
| @@ -46329,10 +46986,14 @@ | ||
| 46329 | 46986 | ** Because we do not completely understand the problem, we will |
| 46330 | 46987 | ** take the conservative approach and always do range tests |
| 46331 | 46988 | ** before attempting the conversion. |
| 46332 | 46989 | */ |
| 46333 | 46990 | static i64 doubleToInt64(double r){ |
| 46991 | +#ifdef SQLITE_OMIT_FLOATING_POINT | |
| 46992 | + /* When floating-point is omitted, double and int64 are the same thing */ | |
| 46993 | + return r; | |
| 46994 | +#else | |
| 46334 | 46995 | /* |
| 46335 | 46996 | ** Many compilers we encounter do not define constants for the |
| 46336 | 46997 | ** minimum and maximum 64-bit integers, or they define them |
| 46337 | 46998 | ** inconsistently. And many do not understand the "LL" notation. |
| 46338 | 46999 | ** So we define our own static constants here using nothing |
| @@ -46350,10 +47011,11 @@ | ||
| 46350 | 47011 | ** does so for compatibility we will do the same in software. */ |
| 46351 | 47012 | return minInt; |
| 46352 | 47013 | }else{ |
| 46353 | 47014 | return (i64)r; |
| 46354 | 47015 | } |
| 47016 | +#endif | |
| 46355 | 47017 | } |
| 46356 | 47018 | |
| 46357 | 47019 | /* |
| 46358 | 47020 | ** Return some kind of integer value which is the best we can do |
| 46359 | 47021 | ** at representing the value that *pMem describes as an integer. |
| @@ -46477,25 +47139,30 @@ | ||
| 46477 | 47139 | } |
| 46478 | 47140 | |
| 46479 | 47141 | /* |
| 46480 | 47142 | ** Convert pMem so that it has types MEM_Real or MEM_Int or both. |
| 46481 | 47143 | ** Invalidate any prior representations. |
| 47144 | +** | |
| 47145 | +** Every effort is made to force the conversion, even if the input | |
| 47146 | +** is a string that does not look completely like a number. Convert | |
| 47147 | +** as much of the string as we can and ignore the rest. | |
| 46482 | 47148 | */ |
| 46483 | 47149 | SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ |
| 46484 | - double r1, r2; | |
| 46485 | - i64 i; | |
| 47150 | + int rc; | |
| 46486 | 47151 | assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ); |
| 46487 | 47152 | assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); |
| 46488 | 47153 | assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); |
| 46489 | - r1 = sqlite3VdbeRealValue(pMem); | |
| 46490 | - i = doubleToInt64(r1); | |
| 46491 | - r2 = (double)i; | |
| 46492 | - if( r1==r2 ){ | |
| 46493 | - sqlite3VdbeMemIntegerify(pMem); | |
| 47154 | + rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8); | |
| 47155 | + if( rc ) return rc; | |
| 47156 | + rc = sqlite3VdbeMemNulTerminate(pMem); | |
| 47157 | + if( rc ) return rc; | |
| 47158 | + if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){ | |
| 47159 | + MemSetTypeFlag(pMem, MEM_Int); | |
| 46494 | 47160 | }else{ |
| 46495 | - pMem->r = r1; | |
| 47161 | + pMem->r = sqlite3VdbeRealValue(pMem); | |
| 46496 | 47162 | MemSetTypeFlag(pMem, MEM_Real); |
| 47163 | + sqlite3VdbeIntegerAffinity(pMem); | |
| 46497 | 47164 | } |
| 46498 | 47165 | return SQLITE_OK; |
| 46499 | 47166 | } |
| 46500 | 47167 | |
| 46501 | 47168 | /* |
| @@ -46543,10 +47210,11 @@ | ||
| 46543 | 47210 | pMem->u.i = val; |
| 46544 | 47211 | pMem->flags = MEM_Int; |
| 46545 | 47212 | pMem->type = SQLITE_INTEGER; |
| 46546 | 47213 | } |
| 46547 | 47214 | |
| 47215 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 46548 | 47216 | /* |
| 46549 | 47217 | ** Delete any previous value and set the value stored in *pMem to val, |
| 46550 | 47218 | ** manifest type REAL. |
| 46551 | 47219 | */ |
| 46552 | 47220 | SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ |
| @@ -46557,10 +47225,11 @@ | ||
| 46557 | 47225 | pMem->r = val; |
| 46558 | 47226 | pMem->flags = MEM_Real; |
| 46559 | 47227 | pMem->type = SQLITE_FLOAT; |
| 46560 | 47228 | } |
| 46561 | 47229 | } |
| 47230 | +#endif | |
| 46562 | 47231 | |
| 46563 | 47232 | /* |
| 46564 | 47233 | ** Delete any previous value and set the value of pMem to be an |
| 46565 | 47234 | ** empty boolean index. |
| 46566 | 47235 | */ |
| @@ -47182,11 +47851,11 @@ | ||
| 47182 | 47851 | /* |
| 47183 | 47852 | ** Return the SQL associated with a prepared statement |
| 47184 | 47853 | */ |
| 47185 | 47854 | SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ |
| 47186 | 47855 | Vdbe *p = (Vdbe *)pStmt; |
| 47187 | - return (p->isPrepareV2 ? p->zSql : 0); | |
| 47856 | + return (p && p->isPrepareV2) ? p->zSql : 0; | |
| 47188 | 47857 | } |
| 47189 | 47858 | |
| 47190 | 47859 | /* |
| 47191 | 47860 | ** Swap all content between two VDBE structures. |
| 47192 | 47861 | */ |
| @@ -47370,10 +48039,17 @@ | ||
| 47370 | 48039 | assert( j>=0 && j<p->nLabel ); |
| 47371 | 48040 | if( p->aLabel ){ |
| 47372 | 48041 | p->aLabel[j] = p->nOp; |
| 47373 | 48042 | } |
| 47374 | 48043 | } |
| 48044 | + | |
| 48045 | +/* | |
| 48046 | +** Mark the VDBE as one that can only be run one time. | |
| 48047 | +*/ | |
| 48048 | +SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){ | |
| 48049 | + p->runOnlyOnce = 1; | |
| 48050 | +} | |
| 47375 | 48051 | |
| 47376 | 48052 | #ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ |
| 47377 | 48053 | |
| 47378 | 48054 | /* |
| 47379 | 48055 | ** The following type and function are used to iterate through all opcodes |
| @@ -48175,11 +48851,10 @@ | ||
| 48175 | 48851 | int rc = SQLITE_OK; /* Return code */ |
| 48176 | 48852 | Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */ |
| 48177 | 48853 | |
| 48178 | 48854 | assert( p->explain ); |
| 48179 | 48855 | assert( p->magic==VDBE_MAGIC_RUN ); |
| 48180 | - assert( db->magic==SQLITE_MAGIC_BUSY ); | |
| 48181 | 48856 | assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); |
| 48182 | 48857 | |
| 48183 | 48858 | /* Even though this opcode does not use dynamic strings for |
| 48184 | 48859 | ** the result, result columns may become dynamic if the user calls |
| 48185 | 48860 | ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. |
| @@ -48590,13 +49265,11 @@ | ||
| 48590 | 49265 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 48591 | 49266 | if( pCx->pVtabCursor ){ |
| 48592 | 49267 | sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; |
| 48593 | 49268 | const sqlite3_module *pModule = pCx->pModule; |
| 48594 | 49269 | p->inVtabMethod = 1; |
| 48595 | - (void)sqlite3SafetyOff(p->db); | |
| 48596 | 49270 | pModule->xClose(pVtabCursor); |
| 48597 | - (void)sqlite3SafetyOn(p->db); | |
| 48598 | 49271 | p->inVtabMethod = 0; |
| 48599 | 49272 | } |
| 48600 | 49273 | #endif |
| 48601 | 49274 | } |
| 48602 | 49275 | |
| @@ -48773,13 +49446,11 @@ | ||
| 48773 | 49446 | } |
| 48774 | 49447 | } |
| 48775 | 49448 | |
| 48776 | 49449 | /* If there are any write-transactions at all, invoke the commit hook */ |
| 48777 | 49450 | if( needXcommit && db->xCommitCallback ){ |
| 48778 | - (void)sqlite3SafetyOff(db); | |
| 48779 | 49451 | rc = db->xCommitCallback(db->pCommitArg); |
| 48780 | - (void)sqlite3SafetyOn(db); | |
| 48781 | 49452 | if( rc ){ |
| 48782 | 49453 | return SQLITE_CONSTRAINT; |
| 48783 | 49454 | } |
| 48784 | 49455 | } |
| 48785 | 49456 | |
| @@ -49329,13 +50000,11 @@ | ||
| 49329 | 50000 | |
| 49330 | 50001 | /* If the VM did not run to completion or if it encountered an |
| 49331 | 50002 | ** error, then it might not have been halted properly. So halt |
| 49332 | 50003 | ** it now. |
| 49333 | 50004 | */ |
| 49334 | - (void)sqlite3SafetyOn(db); | |
| 49335 | 50005 | sqlite3VdbeHalt(p); |
| 49336 | - (void)sqlite3SafetyOff(db); | |
| 49337 | 50006 | |
| 49338 | 50007 | /* If the VDBE has be run even partially, then transfer the error code |
| 49339 | 50008 | ** and error message from the VDBE into the main database structure. But |
| 49340 | 50009 | ** if the VDBE has just been set to run but has not actually executed any |
| 49341 | 50010 | ** instructions yet, leave the main database error information unchanged. |
| @@ -49351,10 +50020,11 @@ | ||
| 49351 | 50020 | }else if( p->rc ){ |
| 49352 | 50021 | sqlite3Error(db, p->rc, 0); |
| 49353 | 50022 | }else{ |
| 49354 | 50023 | sqlite3Error(db, SQLITE_OK, 0); |
| 49355 | 50024 | } |
| 50025 | + if( p->runOnlyOnce ) p->expired = 1; | |
| 49356 | 50026 | }else if( p->rc && p->expired ){ |
| 49357 | 50027 | /* The expired flag was set on the VDBE before the first call |
| 49358 | 50028 | ** to sqlite3_step(). For consistency (since sqlite3_step() was |
| 49359 | 50029 | ** called), set the database error in this case as well. |
| 49360 | 50030 | */ |
| @@ -49452,10 +50122,11 @@ | ||
| 49452 | 50122 | sqlite3DbFree(db, p->aLabel); |
| 49453 | 50123 | sqlite3DbFree(db, p->aColName); |
| 49454 | 50124 | sqlite3DbFree(db, p->zSql); |
| 49455 | 50125 | p->magic = VDBE_MAGIC_DEAD; |
| 49456 | 50126 | sqlite3DbFree(db, p->pFree); |
| 50127 | + p->db = 0; | |
| 49457 | 50128 | sqlite3DbFree(db, p); |
| 49458 | 50129 | } |
| 49459 | 50130 | |
| 49460 | 50131 | /* |
| 49461 | 50132 | ** Make sure the cursor p is ready to read or write the row to which it |
| @@ -50132,11 +50803,11 @@ | ||
| 50132 | 50803 | assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ |
| 50133 | 50804 | /* nCellKey will always be between 0 and 0xffffffff because of the say |
| 50134 | 50805 | ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ |
| 50135 | 50806 | if( nCellKey<=0 || nCellKey>0x7fffffff ){ |
| 50136 | 50807 | *res = 0; |
| 50137 | - return SQLITE_CORRUPT; | |
| 50808 | + return SQLITE_CORRUPT_BKPT; | |
| 50138 | 50809 | } |
| 50139 | 50810 | memset(&m, 0, sizeof(m)); |
| 50140 | 50811 | rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m); |
| 50141 | 50812 | if( rc ){ |
| 50142 | 50813 | return rc; |
| @@ -50258,10 +50929,32 @@ | ||
| 50258 | 50929 | SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ |
| 50259 | 50930 | Vdbe *p = (Vdbe*)pStmt; |
| 50260 | 50931 | return p==0 || p->expired; |
| 50261 | 50932 | } |
| 50262 | 50933 | #endif |
| 50934 | + | |
| 50935 | +/* | |
| 50936 | +** Check on a Vdbe to make sure it has not been finalized. Log | |
| 50937 | +** an error and return true if it has been finalized (or is otherwise | |
| 50938 | +** invalid). Return false if it is ok. | |
| 50939 | +*/ | |
| 50940 | +static int vdbeSafety(Vdbe *p){ | |
| 50941 | + if( p->db==0 ){ | |
| 50942 | + sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement"); | |
| 50943 | + return 1; | |
| 50944 | + }else{ | |
| 50945 | + return 0; | |
| 50946 | + } | |
| 50947 | +} | |
| 50948 | +static int vdbeSafetyNotNull(Vdbe *p){ | |
| 50949 | + if( p==0 ){ | |
| 50950 | + sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement"); | |
| 50951 | + return 1; | |
| 50952 | + }else{ | |
| 50953 | + return vdbeSafety(p); | |
| 50954 | + } | |
| 50955 | +} | |
| 50263 | 50956 | |
| 50264 | 50957 | /* |
| 50265 | 50958 | ** The following routine destroys a virtual machine that is created by |
| 50266 | 50959 | ** the sqlite3_compile() routine. The integer returned is an SQLITE_ |
| 50267 | 50960 | ** success/failure code that describes the result of executing the virtual |
| @@ -50276,11 +50969,15 @@ | ||
| 50276 | 50969 | rc = SQLITE_OK; |
| 50277 | 50970 | }else{ |
| 50278 | 50971 | Vdbe *v = (Vdbe*)pStmt; |
| 50279 | 50972 | sqlite3 *db = v->db; |
| 50280 | 50973 | #if SQLITE_THREADSAFE |
| 50281 | - sqlite3_mutex *mutex = v->db->mutex; | |
| 50974 | + sqlite3_mutex *mutex; | |
| 50975 | +#endif | |
| 50976 | + if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; | |
| 50977 | +#if SQLITE_THREADSAFE | |
| 50978 | + mutex = v->db->mutex; | |
| 50282 | 50979 | #endif |
| 50283 | 50980 | sqlite3_mutex_enter(mutex); |
| 50284 | 50981 | rc = sqlite3VdbeFinalize(v); |
| 50285 | 50982 | rc = sqlite3ApiExit(db, rc); |
| 50286 | 50983 | sqlite3_mutex_leave(mutex); |
| @@ -50523,30 +51220,27 @@ | ||
| 50523 | 51220 | sqlite3 *db; |
| 50524 | 51221 | int rc; |
| 50525 | 51222 | |
| 50526 | 51223 | assert(p); |
| 50527 | 51224 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| 50528 | - return SQLITE_MISUSE; | |
| 51225 | + sqlite3_log(SQLITE_MISUSE, | |
| 51226 | + "attempt to step a halted statement: [%s]", p->zSql); | |
| 51227 | + return SQLITE_MISUSE_BKPT; | |
| 50529 | 51228 | } |
| 50530 | 51229 | |
| 50531 | - /* Assert that malloc() has not failed */ | |
| 51230 | + /* Check that malloc() has not failed. If it has, return early. */ | |
| 50532 | 51231 | db = p->db; |
| 50533 | 51232 | if( db->mallocFailed ){ |
| 51233 | + p->rc = SQLITE_NOMEM; | |
| 50534 | 51234 | return SQLITE_NOMEM; |
| 50535 | 51235 | } |
| 50536 | 51236 | |
| 50537 | 51237 | if( p->pc<=0 && p->expired ){ |
| 50538 | - if( ALWAYS(p->rc==SQLITE_OK || p->rc==SQLITE_SCHEMA) ){ | |
| 50539 | - p->rc = SQLITE_SCHEMA; | |
| 50540 | - } | |
| 51238 | + p->rc = SQLITE_SCHEMA; | |
| 50541 | 51239 | rc = SQLITE_ERROR; |
| 50542 | 51240 | goto end_of_step; |
| 50543 | 51241 | } |
| 50544 | - if( sqlite3SafetyOn(db) ){ | |
| 50545 | - p->rc = SQLITE_MISUSE; | |
| 50546 | - return SQLITE_MISUSE; | |
| 50547 | - } | |
| 50548 | 51242 | if( p->pc<0 ){ |
| 50549 | 51243 | /* If there are no other statements currently running, then |
| 50550 | 51244 | ** reset the interrupt flag. This prevents a call to sqlite3_interrupt |
| 50551 | 51245 | ** from interrupting a statement that has not yet started. |
| 50552 | 51246 | */ |
| @@ -50575,14 +51269,10 @@ | ||
| 50575 | 51269 | #endif /* SQLITE_OMIT_EXPLAIN */ |
| 50576 | 51270 | { |
| 50577 | 51271 | rc = sqlite3VdbeExec(p); |
| 50578 | 51272 | } |
| 50579 | 51273 | |
| 50580 | - if( sqlite3SafetyOff(db) ){ | |
| 50581 | - rc = SQLITE_MISUSE; | |
| 50582 | - } | |
| 50583 | - | |
| 50584 | 51274 | #ifndef SQLITE_OMIT_TRACE |
| 50585 | 51275 | /* Invoke the profile callback if there is one |
| 50586 | 51276 | */ |
| 50587 | 51277 | if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){ |
| 50588 | 51278 | double rNow; |
| @@ -50625,43 +51315,48 @@ | ||
| 50625 | 51315 | ** This is the top-level implementation of sqlite3_step(). Call |
| 50626 | 51316 | ** sqlite3Step() to do most of the work. If a schema error occurs, |
| 50627 | 51317 | ** call sqlite3Reprepare() and try again. |
| 50628 | 51318 | */ |
| 50629 | 51319 | SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ |
| 50630 | - int rc = SQLITE_MISUSE; | |
| 50631 | - if( pStmt ){ | |
| 50632 | - int cnt = 0; | |
| 50633 | - Vdbe *v = (Vdbe*)pStmt; | |
| 50634 | - sqlite3 *db = v->db; | |
| 50635 | - sqlite3_mutex_enter(db->mutex); | |
| 50636 | - while( (rc = sqlite3Step(v))==SQLITE_SCHEMA | |
| 50637 | - && cnt++ < 5 | |
| 50638 | - && (rc = sqlite3Reprepare(v))==SQLITE_OK ){ | |
| 50639 | - sqlite3_reset(pStmt); | |
| 50640 | - v->expired = 0; | |
| 50641 | - } | |
| 50642 | - if( rc==SQLITE_SCHEMA && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ | |
| 50643 | - /* This case occurs after failing to recompile an sql statement. | |
| 50644 | - ** The error message from the SQL compiler has already been loaded | |
| 50645 | - ** into the database handle. This block copies the error message | |
| 50646 | - ** from the database handle into the statement and sets the statement | |
| 50647 | - ** program counter to 0 to ensure that when the statement is | |
| 50648 | - ** finalized or reset the parser error message is available via | |
| 50649 | - ** sqlite3_errmsg() and sqlite3_errcode(). | |
| 50650 | - */ | |
| 50651 | - const char *zErr = (const char *)sqlite3_value_text(db->pErr); | |
| 50652 | - sqlite3DbFree(db, v->zErrMsg); | |
| 50653 | - if( !db->mallocFailed ){ | |
| 50654 | - v->zErrMsg = sqlite3DbStrDup(db, zErr); | |
| 50655 | - } else { | |
| 50656 | - v->zErrMsg = 0; | |
| 50657 | - v->rc = SQLITE_NOMEM; | |
| 50658 | - } | |
| 50659 | - } | |
| 50660 | - rc = sqlite3ApiExit(db, rc); | |
| 50661 | - sqlite3_mutex_leave(db->mutex); | |
| 50662 | - } | |
| 51320 | + int rc = SQLITE_OK; /* Result from sqlite3Step() */ | |
| 51321 | + int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ | |
| 51322 | + Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ | |
| 51323 | + int cnt = 0; /* Counter to prevent infinite loop of reprepares */ | |
| 51324 | + sqlite3 *db; /* The database connection */ | |
| 51325 | + | |
| 51326 | + if( vdbeSafetyNotNull(v) ){ | |
| 51327 | + return SQLITE_MISUSE_BKPT; | |
| 51328 | + } | |
| 51329 | + db = v->db; | |
| 51330 | + sqlite3_mutex_enter(db->mutex); | |
| 51331 | + while( (rc = sqlite3Step(v))==SQLITE_SCHEMA | |
| 51332 | + && cnt++ < 5 | |
| 51333 | + && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ | |
| 51334 | + sqlite3_reset(pStmt); | |
| 51335 | + v->expired = 0; | |
| 51336 | + } | |
| 51337 | + if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ | |
| 51338 | + /* This case occurs after failing to recompile an sql statement. | |
| 51339 | + ** The error message from the SQL compiler has already been loaded | |
| 51340 | + ** into the database handle. This block copies the error message | |
| 51341 | + ** from the database handle into the statement and sets the statement | |
| 51342 | + ** program counter to 0 to ensure that when the statement is | |
| 51343 | + ** finalized or reset the parser error message is available via | |
| 51344 | + ** sqlite3_errmsg() and sqlite3_errcode(). | |
| 51345 | + */ | |
| 51346 | + const char *zErr = (const char *)sqlite3_value_text(db->pErr); | |
| 51347 | + sqlite3DbFree(db, v->zErrMsg); | |
| 51348 | + if( !db->mallocFailed ){ | |
| 51349 | + v->zErrMsg = sqlite3DbStrDup(db, zErr); | |
| 51350 | + v->rc = rc2; | |
| 51351 | + } else { | |
| 51352 | + v->zErrMsg = 0; | |
| 51353 | + v->rc = rc = SQLITE_NOMEM; | |
| 51354 | + } | |
| 51355 | + } | |
| 51356 | + rc = sqlite3ApiExit(db, rc); | |
| 51357 | + sqlite3_mutex_leave(db->mutex); | |
| 50663 | 51358 | return rc; |
| 50664 | 51359 | } |
| 50665 | 51360 | |
| 50666 | 51361 | /* |
| 50667 | 51362 | ** Extract the user data from a sqlite3_context structure and return a |
| @@ -51127,16 +51822,20 @@ | ||
| 51127 | 51822 | ** The error code stored in database p->db is overwritten with the return |
| 51128 | 51823 | ** value in any case. |
| 51129 | 51824 | */ |
| 51130 | 51825 | static int vdbeUnbind(Vdbe *p, int i){ |
| 51131 | 51826 | Mem *pVar; |
| 51132 | - if( p==0 ) return SQLITE_MISUSE; | |
| 51827 | + if( vdbeSafetyNotNull(p) ){ | |
| 51828 | + return SQLITE_MISUSE_BKPT; | |
| 51829 | + } | |
| 51133 | 51830 | sqlite3_mutex_enter(p->db->mutex); |
| 51134 | 51831 | if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ |
| 51135 | 51832 | sqlite3Error(p->db, SQLITE_MISUSE, 0); |
| 51136 | 51833 | sqlite3_mutex_leave(p->db->mutex); |
| 51137 | - return SQLITE_MISUSE; | |
| 51834 | + sqlite3_log(SQLITE_MISUSE, | |
| 51835 | + "bind on a busy prepared statement: [%s]", p->zSql); | |
| 51836 | + return SQLITE_MISUSE_BKPT; | |
| 51138 | 51837 | } |
| 51139 | 51838 | if( i<1 || i>p->nVar ){ |
| 51140 | 51839 | sqlite3Error(p->db, SQLITE_RANGE, 0); |
| 51141 | 51840 | sqlite3_mutex_leave(p->db->mutex); |
| 51142 | 51841 | return SQLITE_RANGE; |
| @@ -52225,11 +52924,11 @@ | ||
| 52225 | 52924 | ** used to clean up the mess that was left behind. |
| 52226 | 52925 | */ |
| 52227 | 52926 | SQLITE_PRIVATE int sqlite3VdbeExec( |
| 52228 | 52927 | Vdbe *p /* The VDBE */ |
| 52229 | 52928 | ){ |
| 52230 | - int pc; /* The program counter */ | |
| 52929 | + int pc=0; /* The program counter */ | |
| 52231 | 52930 | Op *aOp = p->aOp; /* Copy of p->aOp */ |
| 52232 | 52931 | Op *pOp; /* Current operation */ |
| 52233 | 52932 | int rc = SQLITE_OK; /* Value to return */ |
| 52234 | 52933 | sqlite3 *db = p->db; /* The database */ |
| 52235 | 52934 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */ |
| @@ -52336,11 +53035,11 @@ | ||
| 52336 | 53035 | Mem *pDest; /* Where to write the extracted value */ |
| 52337 | 53036 | Mem sMem; /* For storing the record being decoded */ |
| 52338 | 53037 | u8 *zIdx; /* Index into header */ |
| 52339 | 53038 | u8 *zEndHdr; /* Pointer to first byte after the header */ |
| 52340 | 53039 | u32 offset; /* Offset into the data */ |
| 52341 | - u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */ | |
| 53040 | + u32 szField; /* Number of bytes in the content of a field */ | |
| 52342 | 53041 | int szHdr; /* Size of the header size field at start of record */ |
| 52343 | 53042 | int avail; /* Number of bytes of available data */ |
| 52344 | 53043 | Mem *pReg; /* PseudoTable input register */ |
| 52345 | 53044 | } am; |
| 52346 | 53045 | struct OP_Affinity_stack_vars { |
| @@ -52648,11 +53347,10 @@ | ||
| 52648 | 53347 | } u; |
| 52649 | 53348 | /* End automatically generated code |
| 52650 | 53349 | ********************************************************************/ |
| 52651 | 53350 | |
| 52652 | 53351 | assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ |
| 52653 | - assert( db->magic==SQLITE_MAGIC_BUSY ); | |
| 52654 | 53352 | sqlite3VdbeMutexArrayEnter(p); |
| 52655 | 53353 | if( p->rc==SQLITE_NOMEM ){ |
| 52656 | 53354 | /* This happens if a malloc() inside a call to sqlite3_column_text() or |
| 52657 | 53355 | ** sqlite3_column_text16() failed. */ |
| 52658 | 53356 | goto no_mem; |
| @@ -52733,13 +53431,11 @@ | ||
| 52733 | 53431 | ** a return code SQLITE_ABORT. |
| 52734 | 53432 | */ |
| 52735 | 53433 | if( checkProgress ){ |
| 52736 | 53434 | if( db->nProgressOps==nProgressOps ){ |
| 52737 | 53435 | int prc; |
| 52738 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 52739 | - prc =db->xProgress(db->pProgressArg); | |
| 52740 | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; | |
| 53436 | + prc = db->xProgress(db->pProgressArg); | |
| 52741 | 53437 | if( prc!=0 ){ |
| 52742 | 53438 | rc = SQLITE_INTERRUPT; |
| 52743 | 53439 | goto vdbe_error_halt; |
| 52744 | 53440 | } |
| 52745 | 53441 | nProgressOps = 0; |
| @@ -52937,11 +53633,17 @@ | ||
| 52937 | 53633 | |
| 52938 | 53634 | p->rc = pOp->p1; |
| 52939 | 53635 | p->errorAction = (u8)pOp->p2; |
| 52940 | 53636 | p->pc = pc; |
| 52941 | 53637 | if( pOp->p4.z ){ |
| 53638 | + assert( p->rc!=SQLITE_OK ); | |
| 52942 | 53639 | sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); |
| 53640 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 53641 | + sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z); | |
| 53642 | + }else if( p->rc ){ | |
| 53643 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 53644 | + sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql); | |
| 52943 | 53645 | } |
| 52944 | 53646 | rc = sqlite3VdbeHalt(p); |
| 52945 | 53647 | assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); |
| 52946 | 53648 | if( rc==SQLITE_BUSY ){ |
| 52947 | 53649 | p->rc = rc = SQLITE_BUSY; |
| @@ -52971,10 +53673,11 @@ | ||
| 52971 | 53673 | assert( pOp->p4.pI64!=0 ); |
| 52972 | 53674 | pOut->u.i = *pOp->p4.pI64; |
| 52973 | 53675 | break; |
| 52974 | 53676 | } |
| 52975 | 53677 | |
| 53678 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 52976 | 53679 | /* Opcode: Real * P2 * P4 * |
| 52977 | 53680 | ** |
| 52978 | 53681 | ** P4 is a pointer to a 64-bit floating point value. |
| 52979 | 53682 | ** Write that value into register P2. |
| 52980 | 53683 | */ |
| @@ -52982,10 +53685,11 @@ | ||
| 52982 | 53685 | pOut->flags = MEM_Real; |
| 52983 | 53686 | assert( !sqlite3IsNaN(*pOp->p4.pReal) ); |
| 52984 | 53687 | pOut->r = *pOp->p4.pReal; |
| 52985 | 53688 | break; |
| 52986 | 53689 | } |
| 53690 | +#endif | |
| 52987 | 53691 | |
| 52988 | 53692 | /* Opcode: String8 * P2 * P4 * |
| 52989 | 53693 | ** |
| 52990 | 53694 | ** P4 points to a nul terminated UTF-8 string. This opcode is transformed |
| 52991 | 53695 | ** into an OP_String before it is executed for the first time. |
| @@ -53392,18 +54096,23 @@ | ||
| 53392 | 54096 | if( u.af.iA==-1 ) u.af.iA = 1; |
| 53393 | 54097 | u.af.rB = (double)(u.af.iB % u.af.iA); |
| 53394 | 54098 | break; |
| 53395 | 54099 | } |
| 53396 | 54100 | } |
| 54101 | +#ifdef SQLITE_OMIT_FLOATING_POINT | |
| 54102 | + pOut->u.i = u.af.rB; | |
| 54103 | + MemSetTypeFlag(pOut, MEM_Int); | |
| 54104 | +#else | |
| 53397 | 54105 | if( sqlite3IsNaN(u.af.rB) ){ |
| 53398 | 54106 | goto arithmetic_result_is_null; |
| 53399 | 54107 | } |
| 53400 | 54108 | pOut->r = u.af.rB; |
| 53401 | 54109 | MemSetTypeFlag(pOut, MEM_Real); |
| 53402 | 54110 | if( (u.af.flags & MEM_Real)==0 ){ |
| 53403 | 54111 | sqlite3VdbeIntegerAffinity(pOut); |
| 53404 | 54112 | } |
| 54113 | +#endif | |
| 53405 | 54114 | } |
| 53406 | 54115 | break; |
| 53407 | 54116 | |
| 53408 | 54117 | arithmetic_result_is_null: |
| 53409 | 54118 | sqlite3VdbeMemSetNull(pOut); |
| @@ -53492,25 +54201,16 @@ | ||
| 53492 | 54201 | assert( pOp>aOp ); |
| 53493 | 54202 | assert( pOp[-1].p4type==P4_COLLSEQ ); |
| 53494 | 54203 | assert( pOp[-1].opcode==OP_CollSeq ); |
| 53495 | 54204 | u.ag.ctx.pColl = pOp[-1].p4.pColl; |
| 53496 | 54205 | } |
| 53497 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 53498 | 54206 | (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); |
| 53499 | - if( sqlite3SafetyOn(db) ){ | |
| 53500 | - sqlite3VdbeMemRelease(&u.ag.ctx.s); | |
| 53501 | - goto abort_due_to_misuse; | |
| 53502 | - } | |
| 53503 | 54207 | if( db->mallocFailed ){ |
| 53504 | 54208 | /* Even though a malloc() has failed, the implementation of the |
| 53505 | 54209 | ** user function may have called an sqlite3_result_XXX() function |
| 53506 | 54210 | ** to return a value. The following call releases any resources |
| 53507 | 54211 | ** associated with such a value. |
| 53508 | - ** | |
| 53509 | - ** Note: Maybe MemRelease() should be called if sqlite3SafetyOn() | |
| 53510 | - ** fails also (the if(...) statement above). But if people are | |
| 53511 | - ** misusing sqlite, they have bigger problems than a leaked value. | |
| 53512 | 54212 | */ |
| 53513 | 54213 | sqlite3VdbeMemRelease(&u.ag.ctx.s); |
| 53514 | 54214 | goto no_mem; |
| 53515 | 54215 | } |
| 53516 | 54216 | |
| @@ -53631,10 +54331,11 @@ | ||
| 53631 | 54331 | MemSetTypeFlag(pIn1, MEM_Int); |
| 53632 | 54332 | } |
| 53633 | 54333 | break; |
| 53634 | 54334 | } |
| 53635 | 54335 | |
| 54336 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 53636 | 54337 | /* Opcode: RealAffinity P1 * * * * |
| 53637 | 54338 | ** |
| 53638 | 54339 | ** If register P1 holds an integer convert it to a real value. |
| 53639 | 54340 | ** |
| 53640 | 54341 | ** This opcode is used when extracting information from a column that |
| @@ -53647,10 +54348,11 @@ | ||
| 53647 | 54348 | if( pIn1->flags & MEM_Int ){ |
| 53648 | 54349 | sqlite3VdbeMemRealify(pIn1); |
| 53649 | 54350 | } |
| 53650 | 54351 | break; |
| 53651 | 54352 | } |
| 54353 | +#endif | |
| 53652 | 54354 | |
| 53653 | 54355 | #ifndef SQLITE_OMIT_CAST |
| 53654 | 54356 | /* Opcode: ToText P1 * * * * |
| 53655 | 54357 | ** |
| 53656 | 54358 | ** Force the value in register P1 to be text. |
| @@ -53730,11 +54432,11 @@ | ||
| 53730 | 54432 | sqlite3VdbeMemIntegerify(pIn1); |
| 53731 | 54433 | } |
| 53732 | 54434 | break; |
| 53733 | 54435 | } |
| 53734 | 54436 | |
| 53735 | -#ifndef SQLITE_OMIT_CAST | |
| 54437 | +#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) | |
| 53736 | 54438 | /* Opcode: ToReal P1 * * * * |
| 53737 | 54439 | ** |
| 53738 | 54440 | ** Force the value in register P1 to be a floating point number. |
| 53739 | 54441 | ** If The value is currently an integer, convert it. |
| 53740 | 54442 | ** If the value is text or blob, try to convert it to an integer using the |
| @@ -53747,11 +54449,11 @@ | ||
| 53747 | 54449 | if( (pIn1->flags & MEM_Null)==0 ){ |
| 53748 | 54450 | sqlite3VdbeMemRealify(pIn1); |
| 53749 | 54451 | } |
| 53750 | 54452 | break; |
| 53751 | 54453 | } |
| 53752 | -#endif /* SQLITE_OMIT_CAST */ | |
| 54454 | +#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */ | |
| 53753 | 54455 | |
| 53754 | 54456 | /* Opcode: Lt P1 P2 P3 P4 P5 |
| 53755 | 54457 | ** |
| 53756 | 54458 | ** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then |
| 53757 | 54459 | ** jump to address P2. |
| @@ -54169,11 +54871,11 @@ | ||
| 54169 | 54871 | Mem *pDest; /* Where to write the extracted value */ |
| 54170 | 54872 | Mem sMem; /* For storing the record being decoded */ |
| 54171 | 54873 | u8 *zIdx; /* Index into header */ |
| 54172 | 54874 | u8 *zEndHdr; /* Pointer to first byte after the header */ |
| 54173 | 54875 | u32 offset; /* Offset into the data */ |
| 54174 | - u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */ | |
| 54876 | + u32 szField; /* Number of bytes in the content of a field */ | |
| 54175 | 54877 | int szHdr; /* Size of the header size field at start of record */ |
| 54176 | 54878 | int avail; /* Number of bytes of available data */ |
| 54177 | 54879 | Mem *pReg; /* PseudoTable input register */ |
| 54178 | 54880 | #endif /* local variables moved into u.am */ |
| 54179 | 54881 | |
| @@ -54345,16 +55047,20 @@ | ||
| 54345 | 55047 | /* Scan the header and use it to fill in the u.am.aType[] and u.am.aOffset[] |
| 54346 | 55048 | ** arrays. u.am.aType[u.am.i] will contain the type integer for the u.am.i-th |
| 54347 | 55049 | ** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning |
| 54348 | 55050 | ** of the record to the start of the data for the u.am.i-th column |
| 54349 | 55051 | */ |
| 54350 | - u.am.offset64 = u.am.offset; | |
| 54351 | 55052 | for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){ |
| 54352 | 55053 | if( u.am.zIdx<u.am.zEndHdr ){ |
| 54353 | - u.am.aOffset[u.am.i] = (u32)u.am.offset64; | |
| 55054 | + u.am.aOffset[u.am.i] = u.am.offset; | |
| 54354 | 55055 | u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]); |
| 54355 | - u.am.offset64 += sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]); | |
| 55056 | + u.am.szField = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]); | |
| 55057 | + u.am.offset += u.am.szField; | |
| 55058 | + if( u.am.offset<u.am.szField ){ /* True if u.am.offset overflows */ | |
| 55059 | + u.am.zIdx = &u.am.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */ | |
| 55060 | + break; | |
| 55061 | + } | |
| 54356 | 55062 | }else{ |
| 54357 | 55063 | /* If u.am.i is less that u.am.nField, then there are less fields in this |
| 54358 | 55064 | ** record than SetNumColumns indicated there are columns in the |
| 54359 | 55065 | ** table. Set the u.am.offset for any extra columns not present in |
| 54360 | 55066 | ** the record to 0. This tells code below to store a NULL |
| @@ -54370,12 +55076,12 @@ | ||
| 54370 | 55076 | ** or if the end of the last field appears to be past the end of the |
| 54371 | 55077 | ** record, or if the end of the last field appears to be before the end |
| 54372 | 55078 | ** of the record (when all fields present), then we must be dealing |
| 54373 | 55079 | ** with a corrupt database. |
| 54374 | 55080 | */ |
| 54375 | - if( (u.am.zIdx > u.am.zEndHdr)|| (u.am.offset64 > u.am.payloadSize) | |
| 54376 | - || (u.am.zIdx==u.am.zEndHdr && u.am.offset64!=(u64)u.am.payloadSize) ){ | |
| 55081 | + if( (u.am.zIdx > u.am.zEndHdr) || (u.am.offset > u.am.payloadSize) | |
| 55082 | + || (u.am.zIdx==u.am.zEndHdr && u.am.offset!=u.am.payloadSize) ){ | |
| 54377 | 55083 | rc = SQLITE_CORRUPT_BKPT; |
| 54378 | 55084 | goto op_column_out; |
| 54379 | 55085 | } |
| 54380 | 55086 | } |
| 54381 | 55087 | |
| @@ -55239,11 +55945,11 @@ | ||
| 55239 | 55945 | ** Open a new cursor that points to a fake table that contains a single |
| 55240 | 55946 | ** row of data. The content of that one row in the content of memory |
| 55241 | 55947 | ** register P2. In other words, cursor P1 becomes an alias for the |
| 55242 | 55948 | ** MEM_Blob content contained in register P2. |
| 55243 | 55949 | ** |
| 55244 | -** A pseudo-table created by this opcode is used to hold the a single | |
| 55950 | +** A pseudo-table created by this opcode is used to hold a single | |
| 55245 | 55951 | ** row output from the sorter so that the row can be decomposed into |
| 55246 | 55952 | ** individual columns using the OP_Column opcode. The OP_Column opcode |
| 55247 | 55953 | ** is the only cursor opcode that works with a pseudo-table. |
| 55248 | 55954 | ** |
| 55249 | 55955 | ** P3 is the number of fields in the records that will be stored by |
| @@ -56191,16 +56897,14 @@ | ||
| 56191 | 56897 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 56192 | 56898 | }else if( u.bi.pC->pVtabCursor ){ |
| 56193 | 56899 | u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab; |
| 56194 | 56900 | u.bi.pModule = u.bi.pVtab->pModule; |
| 56195 | 56901 | assert( u.bi.pModule->xRowid ); |
| 56196 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 56197 | 56902 | rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v); |
| 56198 | 56903 | sqlite3DbFree(db, p->zErrMsg); |
| 56199 | 56904 | p->zErrMsg = u.bi.pVtab->zErrMsg; |
| 56200 | 56905 | u.bi.pVtab->zErrMsg = 0; |
| 56201 | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; | |
| 56202 | 56906 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 56203 | 56907 | }else{ |
| 56204 | 56908 | assert( u.bi.pC->pCursor!=0 ); |
| 56205 | 56909 | rc = sqlite3VdbeCursorMoveto(u.bi.pC); |
| 56206 | 56910 | if( rc ) goto abort_due_to_error; |
| @@ -56751,25 +57455,23 @@ | ||
| 56751 | 57455 | u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb); |
| 56752 | 57456 | u.bu.initData.db = db; |
| 56753 | 57457 | u.bu.initData.iDb = pOp->p1; |
| 56754 | 57458 | u.bu.initData.pzErrMsg = &p->zErrMsg; |
| 56755 | 57459 | u.bu.zSql = sqlite3MPrintf(db, |
| 56756 | - "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s", | |
| 57460 | + "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", | |
| 56757 | 57461 | db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z); |
| 56758 | 57462 | if( u.bu.zSql==0 ){ |
| 56759 | 57463 | rc = SQLITE_NOMEM; |
| 56760 | 57464 | }else{ |
| 56761 | - (void)sqlite3SafetyOff(db); | |
| 56762 | 57465 | assert( db->init.busy==0 ); |
| 56763 | 57466 | db->init.busy = 1; |
| 56764 | 57467 | u.bu.initData.rc = SQLITE_OK; |
| 56765 | 57468 | assert( !db->mallocFailed ); |
| 56766 | 57469 | rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0); |
| 56767 | 57470 | if( rc==SQLITE_OK ) rc = u.bu.initData.rc; |
| 56768 | 57471 | sqlite3DbFree(db, u.bu.zSql); |
| 56769 | 57472 | db->init.busy = 0; |
| 56770 | - (void)sqlite3SafetyOn(db); | |
| 56771 | 57473 | } |
| 56772 | 57474 | } |
| 56773 | 57475 | sqlite3BtreeLeaveAll(db); |
| 56774 | 57476 | if( rc==SQLITE_NOMEM ){ |
| 56775 | 57477 | goto no_mem; |
| @@ -57351,13 +58053,11 @@ | ||
| 57351 | 58053 | ** Vacuum the entire database. This opcode will cause other virtual |
| 57352 | 58054 | ** machines to be created and run. It may not be called from within |
| 57353 | 58055 | ** a transaction. |
| 57354 | 58056 | */ |
| 57355 | 58057 | case OP_Vacuum: { |
| 57356 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 57357 | 58058 | rc = sqlite3RunVacuum(&p->zErrMsg, db); |
| 57358 | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; | |
| 57359 | 58059 | break; |
| 57360 | 58060 | } |
| 57361 | 58061 | #endif |
| 57362 | 58062 | |
| 57363 | 58063 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| @@ -57503,16 +58203,14 @@ | ||
| 57503 | 58203 | u.cf.pCur = 0; |
| 57504 | 58204 | u.cf.pVtabCursor = 0; |
| 57505 | 58205 | u.cf.pVtab = pOp->p4.pVtab->pVtab; |
| 57506 | 58206 | u.cf.pModule = (sqlite3_module *)u.cf.pVtab->pModule; |
| 57507 | 58207 | assert(u.cf.pVtab && u.cf.pModule); |
| 57508 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 57509 | 58208 | rc = u.cf.pModule->xOpen(u.cf.pVtab, &u.cf.pVtabCursor); |
| 57510 | 58209 | sqlite3DbFree(db, p->zErrMsg); |
| 57511 | 58210 | p->zErrMsg = u.cf.pVtab->zErrMsg; |
| 57512 | 58211 | u.cf.pVtab->zErrMsg = 0; |
| 57513 | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; | |
| 57514 | 58212 | if( SQLITE_OK==rc ){ |
| 57515 | 58213 | /* Initialize sqlite3_vtab_cursor base class */ |
| 57516 | 58214 | u.cf.pVtabCursor->pVtab = u.cf.pVtab; |
| 57517 | 58215 | |
| 57518 | 58216 | /* Initialise vdbe cursor object */ |
| @@ -57584,21 +58282,19 @@ | ||
| 57584 | 58282 | for(u.cg.i = 0; u.cg.i<u.cg.nArg; u.cg.i++){ |
| 57585 | 58283 | u.cg.apArg[u.cg.i] = &u.cg.pArgc[u.cg.i+1]; |
| 57586 | 58284 | sqlite3VdbeMemStoreType(u.cg.apArg[u.cg.i]); |
| 57587 | 58285 | } |
| 57588 | 58286 | |
| 57589 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 57590 | 58287 | p->inVtabMethod = 1; |
| 57591 | 58288 | rc = u.cg.pModule->xFilter(u.cg.pVtabCursor, u.cg.iQuery, pOp->p4.z, u.cg.nArg, u.cg.apArg); |
| 57592 | 58289 | p->inVtabMethod = 0; |
| 57593 | 58290 | sqlite3DbFree(db, p->zErrMsg); |
| 57594 | 58291 | p->zErrMsg = u.cg.pVtab->zErrMsg; |
| 57595 | 58292 | u.cg.pVtab->zErrMsg = 0; |
| 57596 | 58293 | if( rc==SQLITE_OK ){ |
| 57597 | 58294 | u.cg.res = u.cg.pModule->xEof(u.cg.pVtabCursor); |
| 57598 | 58295 | } |
| 57599 | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; | |
| 57600 | 58296 | |
| 57601 | 58297 | if( u.cg.res ){ |
| 57602 | 58298 | pc = pOp->p2 - 1; |
| 57603 | 58299 | } |
| 57604 | 58300 | } |
| @@ -57642,11 +58338,10 @@ | ||
| 57642 | 58338 | ** new one. |
| 57643 | 58339 | */ |
| 57644 | 58340 | sqlite3VdbeMemMove(&u.ch.sContext.s, u.ch.pDest); |
| 57645 | 58341 | MemSetTypeFlag(&u.ch.sContext.s, MEM_Null); |
| 57646 | 58342 | |
| 57647 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 57648 | 58343 | rc = u.ch.pModule->xColumn(pCur->pVtabCursor, &u.ch.sContext, pOp->p2); |
| 57649 | 58344 | sqlite3DbFree(db, p->zErrMsg); |
| 57650 | 58345 | p->zErrMsg = u.ch.pVtab->zErrMsg; |
| 57651 | 58346 | u.ch.pVtab->zErrMsg = 0; |
| 57652 | 58347 | if( u.ch.sContext.isError ){ |
| @@ -57660,13 +58355,10 @@ | ||
| 57660 | 58355 | sqlite3VdbeChangeEncoding(&u.ch.sContext.s, encoding); |
| 57661 | 58356 | sqlite3VdbeMemMove(u.ch.pDest, &u.ch.sContext.s); |
| 57662 | 58357 | REGISTER_TRACE(pOp->p3, u.ch.pDest); |
| 57663 | 58358 | UPDATE_MAX_BLOBSIZE(u.ch.pDest); |
| 57664 | 58359 | |
| 57665 | - if( sqlite3SafetyOn(db) ){ | |
| 57666 | - goto abort_due_to_misuse; | |
| 57667 | - } | |
| 57668 | 58360 | if( sqlite3VdbeMemTooBig(u.ch.pDest) ){ |
| 57669 | 58361 | goto too_big; |
| 57670 | 58362 | } |
| 57671 | 58363 | break; |
| 57672 | 58364 | } |
| @@ -57701,21 +58393,19 @@ | ||
| 57701 | 58393 | ** underlying implementation to return an error if one occurs during |
| 57702 | 58394 | ** xNext(). Instead, if an error occurs, true is returned (indicating that |
| 57703 | 58395 | ** data is available) and the error code returned when xColumn or |
| 57704 | 58396 | ** some other method is next invoked on the save virtual table cursor. |
| 57705 | 58397 | */ |
| 57706 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 57707 | 58398 | p->inVtabMethod = 1; |
| 57708 | 58399 | rc = u.ci.pModule->xNext(u.ci.pCur->pVtabCursor); |
| 57709 | 58400 | p->inVtabMethod = 0; |
| 57710 | 58401 | sqlite3DbFree(db, p->zErrMsg); |
| 57711 | 58402 | p->zErrMsg = u.ci.pVtab->zErrMsg; |
| 57712 | 58403 | u.ci.pVtab->zErrMsg = 0; |
| 57713 | 58404 | if( rc==SQLITE_OK ){ |
| 57714 | 58405 | u.ci.res = u.ci.pModule->xEof(u.ci.pCur->pVtabCursor); |
| 57715 | 58406 | } |
| 57716 | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; | |
| 57717 | 58407 | |
| 57718 | 58408 | if( !u.ci.res ){ |
| 57719 | 58409 | /* If there is data, jump to P2 */ |
| 57720 | 58410 | pc = pOp->p2 - 1; |
| 57721 | 58411 | } |
| @@ -57739,16 +58429,14 @@ | ||
| 57739 | 58429 | u.cj.pVtab = pOp->p4.pVtab->pVtab; |
| 57740 | 58430 | u.cj.pName = &aMem[pOp->p1]; |
| 57741 | 58431 | assert( u.cj.pVtab->pModule->xRename ); |
| 57742 | 58432 | REGISTER_TRACE(pOp->p1, u.cj.pName); |
| 57743 | 58433 | assert( u.cj.pName->flags & MEM_Str ); |
| 57744 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 57745 | 58434 | rc = u.cj.pVtab->pModule->xRename(u.cj.pVtab, u.cj.pName->z); |
| 57746 | 58435 | sqlite3DbFree(db, p->zErrMsg); |
| 57747 | 58436 | p->zErrMsg = u.cj.pVtab->zErrMsg; |
| 57748 | 58437 | u.cj.pVtab->zErrMsg = 0; |
| 57749 | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; | |
| 57750 | 58438 | |
| 57751 | 58439 | break; |
| 57752 | 58440 | } |
| 57753 | 58441 | #endif |
| 57754 | 58442 | |
| @@ -57797,16 +58485,14 @@ | ||
| 57797 | 58485 | for(u.ck.i=0; u.ck.i<u.ck.nArg; u.ck.i++){ |
| 57798 | 58486 | sqlite3VdbeMemStoreType(u.ck.pX); |
| 57799 | 58487 | u.ck.apArg[u.ck.i] = u.ck.pX; |
| 57800 | 58488 | u.ck.pX++; |
| 57801 | 58489 | } |
| 57802 | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; | |
| 57803 | 58490 | rc = u.ck.pModule->xUpdate(u.ck.pVtab, u.ck.nArg, u.ck.apArg, &u.ck.rowid); |
| 57804 | 58491 | sqlite3DbFree(db, p->zErrMsg); |
| 57805 | 58492 | p->zErrMsg = u.ck.pVtab->zErrMsg; |
| 57806 | 58493 | u.ck.pVtab->zErrMsg = 0; |
| 57807 | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; | |
| 57808 | 58494 | if( rc==SQLITE_OK && pOp->p1 ){ |
| 57809 | 58495 | assert( u.ck.nArg>1 && u.ck.apArg[0] && (u.ck.apArg[0]->flags&MEM_Null) ); |
| 57810 | 58496 | db->lastRowid = u.ck.rowid; |
| 57811 | 58497 | } |
| 57812 | 58498 | p->nChange++; |
| @@ -57879,10 +58565,11 @@ | ||
| 57879 | 58565 | ** is to say when the EXPLAIN QUERY PLAN syntax is used.) |
| 57880 | 58566 | ** This opcode records information from the optimizer. It is the |
| 57881 | 58567 | ** the same as a no-op. This opcodesnever appears in a real VM program. |
| 57882 | 58568 | */ |
| 57883 | 58569 | default: { /* This is really OP_Noop and OP_Explain */ |
| 58570 | + assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); | |
| 57884 | 58571 | break; |
| 57885 | 58572 | } |
| 57886 | 58573 | |
| 57887 | 58574 | /***************************************************************************** |
| 57888 | 58575 | ** The cases of the switch statement above this line should all be indented |
| @@ -57930,10 +58617,11 @@ | ||
| 57930 | 58617 | ** an error of some kind. |
| 57931 | 58618 | */ |
| 57932 | 58619 | vdbe_error_halt: |
| 57933 | 58620 | assert( rc ); |
| 57934 | 58621 | p->rc = rc; |
| 58622 | + sqlite3_log(rc, "prepared statement aborts at %d: [%s]", pc, p->zSql); | |
| 57935 | 58623 | sqlite3VdbeHalt(p); |
| 57936 | 58624 | if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; |
| 57937 | 58625 | rc = SQLITE_ERROR; |
| 57938 | 58626 | if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0); |
| 57939 | 58627 | |
| @@ -57958,16 +58646,10 @@ | ||
| 57958 | 58646 | db->mallocFailed = 1; |
| 57959 | 58647 | sqlite3SetString(&p->zErrMsg, db, "out of memory"); |
| 57960 | 58648 | rc = SQLITE_NOMEM; |
| 57961 | 58649 | goto vdbe_error_halt; |
| 57962 | 58650 | |
| 57963 | - /* Jump to here for an SQLITE_MISUSE error. | |
| 57964 | - */ | |
| 57965 | -abort_due_to_misuse: | |
| 57966 | - rc = SQLITE_MISUSE; | |
| 57967 | - /* Fall thru into abort_due_to_error */ | |
| 57968 | - | |
| 57969 | 58651 | /* Jump to here for any other kind of fatal error. The "rc" variable |
| 57970 | 58652 | ** should hold the error number. |
| 57971 | 58653 | */ |
| 57972 | 58654 | abort_due_to_error: |
| 57973 | 58655 | assert( p->zErrMsg==0 ); |
| @@ -58083,17 +58765,10 @@ | ||
| 58083 | 58765 | } |
| 58084 | 58766 | do { |
| 58085 | 58767 | memset(pParse, 0, sizeof(Parse)); |
| 58086 | 58768 | pParse->db = db; |
| 58087 | 58769 | |
| 58088 | - if( sqlite3SafetyOn(db) ){ | |
| 58089 | - sqlite3DbFree(db, zErr); | |
| 58090 | - sqlite3StackFree(db, pParse); | |
| 58091 | - sqlite3_mutex_leave(db->mutex); | |
| 58092 | - return SQLITE_MISUSE; | |
| 58093 | - } | |
| 58094 | - | |
| 58095 | 58770 | sqlite3BtreeEnterAll(db); |
| 58096 | 58771 | pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); |
| 58097 | 58772 | if( pTab && IsVirtual(pTab) ){ |
| 58098 | 58773 | pTab = 0; |
| 58099 | 58774 | sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); |
| @@ -58109,11 +58784,10 @@ | ||
| 58109 | 58784 | sqlite3DbFree(db, zErr); |
| 58110 | 58785 | zErr = pParse->zErrMsg; |
| 58111 | 58786 | pParse->zErrMsg = 0; |
| 58112 | 58787 | } |
| 58113 | 58788 | rc = SQLITE_ERROR; |
| 58114 | - (void)sqlite3SafetyOff(db); | |
| 58115 | 58789 | sqlite3BtreeLeaveAll(db); |
| 58116 | 58790 | goto blob_open_out; |
| 58117 | 58791 | } |
| 58118 | 58792 | |
| 58119 | 58793 | /* Now search pTab for the exact column. */ |
| @@ -58124,11 +58798,10 @@ | ||
| 58124 | 58798 | } |
| 58125 | 58799 | if( iCol==pTab->nCol ){ |
| 58126 | 58800 | sqlite3DbFree(db, zErr); |
| 58127 | 58801 | zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); |
| 58128 | 58802 | rc = SQLITE_ERROR; |
| 58129 | - (void)sqlite3SafetyOff(db); | |
| 58130 | 58803 | sqlite3BtreeLeaveAll(db); |
| 58131 | 58804 | goto blob_open_out; |
| 58132 | 58805 | } |
| 58133 | 58806 | |
| 58134 | 58807 | /* If the value is being opened for writing, check that the |
| @@ -58165,11 +58838,10 @@ | ||
| 58165 | 58838 | } |
| 58166 | 58839 | if( zFault ){ |
| 58167 | 58840 | sqlite3DbFree(db, zErr); |
| 58168 | 58841 | zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault); |
| 58169 | 58842 | rc = SQLITE_ERROR; |
| 58170 | - (void)sqlite3SafetyOff(db); | |
| 58171 | 58843 | sqlite3BtreeLeaveAll(db); |
| 58172 | 58844 | goto blob_open_out; |
| 58173 | 58845 | } |
| 58174 | 58846 | } |
| 58175 | 58847 | |
| @@ -58215,12 +58887,11 @@ | ||
| 58215 | 58887 | sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0); |
| 58216 | 58888 | } |
| 58217 | 58889 | } |
| 58218 | 58890 | |
| 58219 | 58891 | sqlite3BtreeLeaveAll(db); |
| 58220 | - rc = sqlite3SafetyOff(db); | |
| 58221 | - if( NEVER(rc!=SQLITE_OK) || db->mallocFailed ){ | |
| 58892 | + if( db->mallocFailed ){ | |
| 58222 | 58893 | goto blob_open_out; |
| 58223 | 58894 | } |
| 58224 | 58895 | |
| 58225 | 58896 | sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow); |
| 58226 | 58897 | rc = sqlite3_step((sqlite3_stmt *)v); |
| @@ -58317,11 +58988,11 @@ | ||
| 58317 | 58988 | int rc; |
| 58318 | 58989 | Incrblob *p = (Incrblob *)pBlob; |
| 58319 | 58990 | Vdbe *v; |
| 58320 | 58991 | sqlite3 *db; |
| 58321 | 58992 | |
| 58322 | - if( p==0 ) return SQLITE_MISUSE; | |
| 58993 | + if( p==0 ) return SQLITE_MISUSE_BKPT; | |
| 58323 | 58994 | db = p->db; |
| 58324 | 58995 | sqlite3_mutex_enter(db->mutex); |
| 58325 | 58996 | v = (Vdbe*)p->pStmt; |
| 58326 | 58997 | |
| 58327 | 58998 | if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ |
| @@ -59675,10 +60346,13 @@ | ||
| 59675 | 60346 | Expr *pE /* The specific ORDER BY term */ |
| 59676 | 60347 | ){ |
| 59677 | 60348 | int i; /* Loop counter */ |
| 59678 | 60349 | ExprList *pEList; /* The columns of the result set */ |
| 59679 | 60350 | NameContext nc; /* Name context for resolving pE */ |
| 60351 | + sqlite3 *db; /* Database connection */ | |
| 60352 | + int rc; /* Return code from subprocedures */ | |
| 60353 | + u8 savedSuppErr; /* Saved value of db->suppressErr */ | |
| 59680 | 60354 | |
| 59681 | 60355 | assert( sqlite3ExprIsInteger(pE, &i)==0 ); |
| 59682 | 60356 | pEList = pSelect->pEList; |
| 59683 | 60357 | |
| 59684 | 60358 | /* Resolve all names in the ORDER BY term expression |
| @@ -59687,21 +60361,23 @@ | ||
| 59687 | 60361 | nc.pParse = pParse; |
| 59688 | 60362 | nc.pSrcList = pSelect->pSrc; |
| 59689 | 60363 | nc.pEList = pEList; |
| 59690 | 60364 | nc.allowAgg = 1; |
| 59691 | 60365 | nc.nErr = 0; |
| 59692 | - if( sqlite3ResolveExprNames(&nc, pE) ){ | |
| 59693 | - sqlite3ErrorClear(pParse); | |
| 59694 | - return 0; | |
| 59695 | - } | |
| 60366 | + db = pParse->db; | |
| 60367 | + savedSuppErr = db->suppressErr; | |
| 60368 | + db->suppressErr = 1; | |
| 60369 | + rc = sqlite3ResolveExprNames(&nc, pE); | |
| 60370 | + db->suppressErr = savedSuppErr; | |
| 60371 | + if( rc ) return 0; | |
| 59696 | 60372 | |
| 59697 | 60373 | /* Try to match the ORDER BY expression against an expression |
| 59698 | 60374 | ** in the result set. Return an 1-based index of the matching |
| 59699 | 60375 | ** result-set entry. |
| 59700 | 60376 | */ |
| 59701 | 60377 | for(i=0; i<pEList->nExpr; i++){ |
| 59702 | - if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){ | |
| 60378 | + if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){ | |
| 59703 | 60379 | return i+1; |
| 59704 | 60380 | } |
| 59705 | 60381 | } |
| 59706 | 60382 | |
| 59707 | 60383 | /* If no match, return 0. */ |
| @@ -62091,10 +62767,11 @@ | ||
| 62091 | 62767 | memcpy(out, in, 8); |
| 62092 | 62768 | } |
| 62093 | 62769 | return out; |
| 62094 | 62770 | } |
| 62095 | 62771 | |
| 62772 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 62096 | 62773 | /* |
| 62097 | 62774 | ** Generate an instruction that will put the floating point |
| 62098 | 62775 | ** value described by z[0..n-1] into register iMem. |
| 62099 | 62776 | ** |
| 62100 | 62777 | ** The z[] string will probably not be zero-terminated. But the |
| @@ -62110,10 +62787,11 @@ | ||
| 62110 | 62787 | if( negateFlag ) value = -value; |
| 62111 | 62788 | zV = dup8bytes(v, (char*)&value); |
| 62112 | 62789 | sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); |
| 62113 | 62790 | } |
| 62114 | 62791 | } |
| 62792 | +#endif | |
| 62115 | 62793 | |
| 62116 | 62794 | |
| 62117 | 62795 | /* |
| 62118 | 62796 | ** Generate an instruction that will put the integer describe by |
| 62119 | 62797 | ** text z[0..n-1] into register iMem. |
| @@ -62120,11 +62798,12 @@ | ||
| 62120 | 62798 | ** |
| 62121 | 62799 | ** The z[] string will probably not be zero-terminated. But the |
| 62122 | 62800 | ** z[n] character is guaranteed to be something that does not look |
| 62123 | 62801 | ** like the continuation of the number. |
| 62124 | 62802 | */ |
| 62125 | -static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ | |
| 62803 | +static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ | |
| 62804 | + Vdbe *v = pParse->pVdbe; | |
| 62126 | 62805 | if( pExpr->flags & EP_IntValue ){ |
| 62127 | 62806 | int i = pExpr->u.iValue; |
| 62128 | 62807 | if( negFlag ) i = -i; |
| 62129 | 62808 | sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); |
| 62130 | 62809 | }else{ |
| @@ -62136,11 +62815,15 @@ | ||
| 62136 | 62815 | sqlite3Atoi64(z, &value); |
| 62137 | 62816 | if( negFlag ) value = -value; |
| 62138 | 62817 | zV = dup8bytes(v, (char*)&value); |
| 62139 | 62818 | sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); |
| 62140 | 62819 | }else{ |
| 62820 | +#ifdef SQLITE_OMIT_FLOATING_POINT | |
| 62821 | + sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); | |
| 62822 | +#else | |
| 62141 | 62823 | codeReal(v, z, negFlag, iMem); |
| 62824 | +#endif | |
| 62142 | 62825 | } |
| 62143 | 62826 | } |
| 62144 | 62827 | } |
| 62145 | 62828 | |
| 62146 | 62829 | /* |
| @@ -62523,18 +63206,20 @@ | ||
| 62523 | 63206 | pExpr->iColumn, pExpr->iTable, target); |
| 62524 | 63207 | } |
| 62525 | 63208 | break; |
| 62526 | 63209 | } |
| 62527 | 63210 | case TK_INTEGER: { |
| 62528 | - codeInteger(v, pExpr, 0, target); | |
| 63211 | + codeInteger(pParse, pExpr, 0, target); | |
| 62529 | 63212 | break; |
| 62530 | 63213 | } |
| 63214 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 62531 | 63215 | case TK_FLOAT: { |
| 62532 | 63216 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 62533 | 63217 | codeReal(v, pExpr->u.zToken, 0, target); |
| 62534 | 63218 | break; |
| 62535 | 63219 | } |
| 63220 | +#endif | |
| 62536 | 63221 | case TK_STRING: { |
| 62537 | 63222 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 62538 | 63223 | sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); |
| 62539 | 63224 | break; |
| 62540 | 63225 | } |
| @@ -62700,15 +63385,17 @@ | ||
| 62700 | 63385 | break; |
| 62701 | 63386 | } |
| 62702 | 63387 | case TK_UMINUS: { |
| 62703 | 63388 | Expr *pLeft = pExpr->pLeft; |
| 62704 | 63389 | assert( pLeft ); |
| 62705 | - if( pLeft->op==TK_FLOAT ){ | |
| 63390 | + if( pLeft->op==TK_INTEGER ){ | |
| 63391 | + codeInteger(pParse, pLeft, 1, target); | |
| 63392 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 63393 | + }else if( pLeft->op==TK_FLOAT ){ | |
| 62706 | 63394 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 62707 | 63395 | codeReal(v, pLeft->u.zToken, 1, target); |
| 62708 | - }else if( pLeft->op==TK_INTEGER ){ | |
| 62709 | - codeInteger(v, pLeft, 1, target); | |
| 63396 | +#endif | |
| 62710 | 63397 | }else{ |
| 62711 | 63398 | regFree1 = r1 = sqlite3GetTempReg(pParse); |
| 62712 | 63399 | sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); |
| 62713 | 63400 | r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); |
| 62714 | 63401 | sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); |
| @@ -62952,17 +63639,19 @@ | ||
| 62952 | 63639 | (pExpr->iTable ? "new" : "old"), |
| 62953 | 63640 | (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), |
| 62954 | 63641 | target |
| 62955 | 63642 | )); |
| 62956 | 63643 | |
| 63644 | +#ifndef SQLITE_OMIT_FLOATING_POINT | |
| 62957 | 63645 | /* If the column has REAL affinity, it may currently be stored as an |
| 62958 | 63646 | ** integer. Use OP_RealAffinity to make sure it is really real. */ |
| 62959 | 63647 | if( pExpr->iColumn>=0 |
| 62960 | 63648 | && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL |
| 62961 | 63649 | ){ |
| 62962 | 63650 | sqlite3VdbeAddOp1(v, OP_RealAffinity, target); |
| 62963 | 63651 | } |
| 63652 | +#endif | |
| 62964 | 63653 | break; |
| 62965 | 63654 | } |
| 62966 | 63655 | |
| 62967 | 63656 | |
| 62968 | 63657 | /* |
| @@ -63624,61 +64313,65 @@ | ||
| 63624 | 64313 | sqlite3ReleaseTempReg(pParse, regFree1); |
| 63625 | 64314 | sqlite3ReleaseTempReg(pParse, regFree2); |
| 63626 | 64315 | } |
| 63627 | 64316 | |
| 63628 | 64317 | /* |
| 63629 | -** Do a deep comparison of two expression trees. Return TRUE (non-zero) | |
| 63630 | -** if they are identical and return FALSE if they differ in any way. | |
| 64318 | +** Do a deep comparison of two expression trees. Return 0 if the two | |
| 64319 | +** expressions are completely identical. Return 1 if they differ only | |
| 64320 | +** by a COLLATE operator at the top level. Return 2 if there are differences | |
| 64321 | +** other than the top-level COLLATE operator. | |
| 63631 | 64322 | ** |
| 63632 | -** Sometimes this routine will return FALSE even if the two expressions | |
| 64323 | +** Sometimes this routine will return 2 even if the two expressions | |
| 63633 | 64324 | ** really are equivalent. If we cannot prove that the expressions are |
| 63634 | -** identical, we return FALSE just to be safe. So if this routine | |
| 63635 | -** returns false, then you do not really know for certain if the two | |
| 63636 | -** expressions are the same. But if you get a TRUE return, then you | |
| 64325 | +** identical, we return 2 just to be safe. So if this routine | |
| 64326 | +** returns 2, then you do not really know for certain if the two | |
| 64327 | +** expressions are the same. But if you get a 0 or 1 return, then you | |
| 63637 | 64328 | ** can be sure the expressions are the same. In the places where |
| 63638 | -** this routine is used, it does not hurt to get an extra FALSE - that | |
| 64329 | +** this routine is used, it does not hurt to get an extra 2 - that | |
| 63639 | 64330 | ** just might result in some slightly slower code. But returning |
| 63640 | -** an incorrect TRUE could lead to a malfunction. | |
| 64331 | +** an incorrect 0 or 1 could lead to a malfunction. | |
| 63641 | 64332 | */ |
| 63642 | 64333 | SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){ |
| 63643 | 64334 | int i; |
| 63644 | 64335 | if( pA==0||pB==0 ){ |
| 63645 | - return pB==pA; | |
| 64336 | + return pB==pA ? 0 : 2; | |
| 63646 | 64337 | } |
| 63647 | 64338 | assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); |
| 63648 | 64339 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 63649 | 64340 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 63650 | - return 0; | |
| 64341 | + return 2; | |
| 63651 | 64342 | } |
| 63652 | - if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0; | |
| 63653 | - if( pA->op!=pB->op ) return 0; | |
| 63654 | - if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0; | |
| 63655 | - if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0; | |
| 64343 | + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; | |
| 64344 | + if( pA->op!=pB->op ) return 2; | |
| 64345 | + if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; | |
| 64346 | + if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; | |
| 63656 | 64347 | |
| 63657 | 64348 | if( pA->x.pList && pB->x.pList ){ |
| 63658 | - if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 0; | |
| 64349 | + if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 2; | |
| 63659 | 64350 | for(i=0; i<pA->x.pList->nExpr; i++){ |
| 63660 | 64351 | Expr *pExprA = pA->x.pList->a[i].pExpr; |
| 63661 | 64352 | Expr *pExprB = pB->x.pList->a[i].pExpr; |
| 63662 | - if( !sqlite3ExprCompare(pExprA, pExprB) ) return 0; | |
| 64353 | + if( sqlite3ExprCompare(pExprA, pExprB) ) return 2; | |
| 63663 | 64354 | } |
| 63664 | 64355 | }else if( pA->x.pList || pB->x.pList ){ |
| 63665 | - return 0; | |
| 64356 | + return 2; | |
| 63666 | 64357 | } |
| 63667 | 64358 | |
| 63668 | - if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; | |
| 64359 | + if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; | |
| 63669 | 64360 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| 63670 | 64361 | if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ |
| 63671 | - return 0; | |
| 64362 | + return 2; | |
| 63672 | 64363 | } |
| 63673 | 64364 | }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ |
| 63674 | - if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 0; | |
| 64365 | + if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; | |
| 63675 | 64366 | if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 63676 | - return 0; | |
| 64367 | + return 2; | |
| 63677 | 64368 | } |
| 63678 | 64369 | } |
| 63679 | - return 1; | |
| 64370 | + if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; | |
| 64371 | + if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; | |
| 64372 | + return 0; | |
| 63680 | 64373 | } |
| 63681 | 64374 | |
| 63682 | 64375 | |
| 63683 | 64376 | /* |
| 63684 | 64377 | ** Add a new element to the pAggInfo->aCol[] array. Return the index of |
| @@ -63805,11 +64498,11 @@ | ||
| 63805 | 64498 | /* Check to see if pExpr is a duplicate of another aggregate |
| 63806 | 64499 | ** function that is already in the pAggInfo structure |
| 63807 | 64500 | */ |
| 63808 | 64501 | struct AggInfo_func *pItem = pAggInfo->aFunc; |
| 63809 | 64502 | for(i=0; i<pAggInfo->nFunc; i++, pItem++){ |
| 63810 | - if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){ | |
| 64503 | + if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){ | |
| 63811 | 64504 | break; |
| 63812 | 64505 | } |
| 63813 | 64506 | } |
| 63814 | 64507 | if( i>=pAggInfo->nFunc ){ |
| 63815 | 64508 | /* pExpr is original. Make a new entry in pAggInfo->aFunc[] |
| @@ -64426,13 +65119,13 @@ | ||
| 64426 | 65119 | /* If foreign-key support is enabled, rewrite the CREATE TABLE |
| 64427 | 65120 | ** statements corresponding to all child tables of foreign key constraints |
| 64428 | 65121 | ** for which the renamed table is the parent table. */ |
| 64429 | 65122 | if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ |
| 64430 | 65123 | sqlite3NestedParse(pParse, |
| 64431 | - "UPDATE sqlite_master SET " | |
| 65124 | + "UPDATE \"%w\".%s SET " | |
| 64432 | 65125 | "sql = sqlite_rename_parent(sql, %Q, %Q) " |
| 64433 | - "WHERE %s;", zTabName, zName, zWhere); | |
| 65126 | + "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere); | |
| 64434 | 65127 | sqlite3DbFree(db, zWhere); |
| 64435 | 65128 | } |
| 64436 | 65129 | } |
| 64437 | 65130 | #endif |
| 64438 | 65131 | |
| @@ -65301,13 +65994,11 @@ | ||
| 65301 | 65994 | zSql = sqlite3MPrintf(db, |
| 65302 | 65995 | "SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase); |
| 65303 | 65996 | if( zSql==0 ){ |
| 65304 | 65997 | rc = SQLITE_NOMEM; |
| 65305 | 65998 | }else{ |
| 65306 | - (void)sqlite3SafetyOff(db); | |
| 65307 | 65999 | rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); |
| 65308 | - (void)sqlite3SafetyOn(db); | |
| 65309 | 66000 | sqlite3DbFree(db, zSql); |
| 65310 | 66001 | } |
| 65311 | 66002 | |
| 65312 | 66003 | |
| 65313 | 66004 | /* Load the statistics from the sqlite_stat2 table. */ |
| @@ -65321,18 +66012,15 @@ | ||
| 65321 | 66012 | zSql = sqlite3MPrintf(db, |
| 65322 | 66013 | "SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase); |
| 65323 | 66014 | if( !zSql ){ |
| 65324 | 66015 | rc = SQLITE_NOMEM; |
| 65325 | 66016 | }else{ |
| 65326 | - (void)sqlite3SafetyOff(db); | |
| 65327 | 66017 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 65328 | - (void)sqlite3SafetyOn(db); | |
| 65329 | 66018 | sqlite3DbFree(db, zSql); |
| 65330 | 66019 | } |
| 65331 | 66020 | |
| 65332 | 66021 | if( rc==SQLITE_OK ){ |
| 65333 | - (void)sqlite3SafetyOff(db); | |
| 65334 | 66022 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 65335 | 66023 | char *zIndex = (char *)sqlite3_column_text(pStmt, 0); |
| 65336 | 66024 | Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase); |
| 65337 | 66025 | if( pIdx ){ |
| 65338 | 66026 | int iSample = sqlite3_column_int(pStmt, 1); |
| @@ -65378,11 +66066,10 @@ | ||
| 65378 | 66066 | } |
| 65379 | 66067 | } |
| 65380 | 66068 | } |
| 65381 | 66069 | } |
| 65382 | 66070 | rc = sqlite3_finalize(pStmt); |
| 65383 | - (void)sqlite3SafetyOn(db); | |
| 65384 | 66071 | } |
| 65385 | 66072 | } |
| 65386 | 66073 | #endif |
| 65387 | 66074 | |
| 65388 | 66075 | if( rc==SQLITE_NOMEM ){ |
| @@ -65539,15 +66226,21 @@ | ||
| 65539 | 66226 | rc = SQLITE_ERROR; |
| 65540 | 66227 | } |
| 65541 | 66228 | pPager = sqlite3BtreePager(aNew->pBt); |
| 65542 | 66229 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 65543 | 66230 | sqlite3PagerJournalMode(pPager, db->dfltJournalMode); |
| 66231 | + sqlite3BtreeSecureDelete(aNew->pBt, | |
| 66232 | + sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); | |
| 65544 | 66233 | } |
| 65545 | - aNew->zName = sqlite3DbStrDup(db, zName); | |
| 65546 | 66234 | aNew->safety_level = 3; |
| 66235 | + aNew->zName = sqlite3DbStrDup(db, zName); | |
| 66236 | + if( rc==SQLITE_OK && aNew->zName==0 ){ | |
| 66237 | + rc = SQLITE_NOMEM; | |
| 66238 | + } | |
| 65547 | 66239 | |
| 65548 | -#if SQLITE_HAS_CODEC | |
| 66240 | + | |
| 66241 | +#ifdef SQLITE_HAS_CODEC | |
| 65549 | 66242 | if( rc==SQLITE_OK ){ |
| 65550 | 66243 | extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); |
| 65551 | 66244 | extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); |
| 65552 | 66245 | int nKey; |
| 65553 | 66246 | char *zKey; |
| @@ -65579,15 +66272,13 @@ | ||
| 65579 | 66272 | ** If this fails, or if opening the file failed, then close the file and |
| 65580 | 66273 | ** remove the entry from the db->aDb[] array. i.e. put everything back the way |
| 65581 | 66274 | ** we found it. |
| 65582 | 66275 | */ |
| 65583 | 66276 | if( rc==SQLITE_OK ){ |
| 65584 | - (void)sqlite3SafetyOn(db); | |
| 65585 | 66277 | sqlite3BtreeEnterAll(db); |
| 65586 | 66278 | rc = sqlite3Init(db, &zErrDyn); |
| 65587 | 66279 | sqlite3BtreeLeaveAll(db); |
| 65588 | - (void)sqlite3SafetyOff(db); | |
| 65589 | 66280 | } |
| 65590 | 66281 | if( rc ){ |
| 65591 | 66282 | int iDb = db->nDb - 1; |
| 65592 | 66283 | assert( iDb>=2 ); |
| 65593 | 66284 | if( db->aDb[iDb].pBt ){ |
| @@ -66385,11 +67076,11 @@ | ||
| 66385 | 67076 | sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem, |
| 66386 | 67077 | pParse->nTab, pParse->nMaxArg, pParse->explain, |
| 66387 | 67078 | pParse->isMultiWrite && pParse->mayAbort); |
| 66388 | 67079 | pParse->rc = SQLITE_DONE; |
| 66389 | 67080 | pParse->colNamesSet = 0; |
| 66390 | - }else if( pParse->rc==SQLITE_OK ){ | |
| 67081 | + }else{ | |
| 66391 | 67082 | pParse->rc = SQLITE_ERROR; |
| 66392 | 67083 | } |
| 66393 | 67084 | pParse->nTab = 0; |
| 66394 | 67085 | pParse->nMem = 0; |
| 66395 | 67086 | pParse->nSet = 0; |
| @@ -68157,17 +68848,16 @@ | ||
| 68157 | 68848 | if( db->mallocFailed ){ |
| 68158 | 68849 | goto exit_drop_table; |
| 68159 | 68850 | } |
| 68160 | 68851 | assert( pParse->nErr==0 ); |
| 68161 | 68852 | assert( pName->nSrc==1 ); |
| 68853 | + if( noErr ) db->suppressErr++; | |
| 68162 | 68854 | pTab = sqlite3LocateTable(pParse, isView, |
| 68163 | 68855 | pName->a[0].zName, pName->a[0].zDatabase); |
| 68856 | + if( noErr ) db->suppressErr--; | |
| 68164 | 68857 | |
| 68165 | 68858 | if( pTab==0 ){ |
| 68166 | - if( noErr ){ | |
| 68167 | - sqlite3ErrorClear(pParse); | |
| 68168 | - } | |
| 68169 | 68859 | goto exit_drop_table; |
| 68170 | 68860 | } |
| 68171 | 68861 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 68172 | 68862 | assert( iDb>=0 && iDb<db->nDb ); |
| 68173 | 68863 | |
| @@ -69585,28 +70275,32 @@ | ||
| 69585 | 70275 | */ |
| 69586 | 70276 | SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ |
| 69587 | 70277 | sqlite3 *db = pParse->db; |
| 69588 | 70278 | if( db->aDb[1].pBt==0 && !pParse->explain ){ |
| 69589 | 70279 | int rc; |
| 70280 | + Btree *pBt; | |
| 69590 | 70281 | static const int flags = |
| 69591 | 70282 | SQLITE_OPEN_READWRITE | |
| 69592 | 70283 | SQLITE_OPEN_CREATE | |
| 69593 | 70284 | SQLITE_OPEN_EXCLUSIVE | |
| 69594 | 70285 | SQLITE_OPEN_DELETEONCLOSE | |
| 69595 | 70286 | SQLITE_OPEN_TEMP_DB; |
| 69596 | 70287 | |
| 69597 | - rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, | |
| 69598 | - &db->aDb[1].pBt); | |
| 70288 | + rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, &pBt); | |
| 69599 | 70289 | if( rc!=SQLITE_OK ){ |
| 69600 | 70290 | sqlite3ErrorMsg(pParse, "unable to open a temporary database " |
| 69601 | 70291 | "file for storing temporary tables"); |
| 69602 | 70292 | pParse->rc = rc; |
| 69603 | 70293 | return 1; |
| 69604 | 70294 | } |
| 70295 | + db->aDb[1].pBt = pBt; | |
| 69605 | 70296 | assert( db->aDb[1].pSchema ); |
| 69606 | - sqlite3PagerJournalMode(sqlite3BtreePager(db->aDb[1].pBt), | |
| 69607 | - db->dfltJournalMode); | |
| 70297 | + if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ | |
| 70298 | + db->mallocFailed = 1; | |
| 70299 | + return 1; | |
| 70300 | + } | |
| 70301 | + sqlite3PagerJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode); | |
| 69608 | 70302 | } |
| 69609 | 70303 | return 0; |
| 69610 | 70304 | } |
| 69611 | 70305 | |
| 69612 | 70306 | /* |
| @@ -70339,10 +71033,397 @@ | ||
| 70339 | 71033 | } |
| 70340 | 71034 | return p; |
| 70341 | 71035 | } |
| 70342 | 71036 | |
| 70343 | 71037 | /************** End of callback.c ********************************************/ |
| 71038 | +/************** Begin file ctime.c *******************************************/ | |
| 71039 | +/* | |
| 71040 | +** 2010 February 23 | |
| 71041 | +** | |
| 71042 | +** The author disclaims copyright to this source code. In place of | |
| 71043 | +** a legal notice, here is a blessing: | |
| 71044 | +** | |
| 71045 | +** May you do good and not evil. | |
| 71046 | +** May you find forgiveness for yourself and forgive others. | |
| 71047 | +** May you share freely, never taking more than you give. | |
| 71048 | +** | |
| 71049 | +************************************************************************* | |
| 71050 | +** | |
| 71051 | +** This file implements routines used to report what compile-time options | |
| 71052 | +** SQLite was built with. | |
| 71053 | +*/ | |
| 71054 | + | |
| 71055 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS | |
| 71056 | + | |
| 71057 | + | |
| 71058 | +/* | |
| 71059 | +** An array of names of all compile-time options. This array should | |
| 71060 | +** be sorted A-Z. | |
| 71061 | +** | |
| 71062 | +** This array looks large, but in a typical installation actually uses | |
| 71063 | +** only a handful of compile-time options, so most times this array is usually | |
| 71064 | +** rather short and uses little memory space. | |
| 71065 | +*/ | |
| 71066 | +static const char * const azCompileOpt[] = { | |
| 71067 | + | |
| 71068 | +/* These macros are provided to "stringify" the value of the define | |
| 71069 | +** for those options in which the value is meaningful. */ | |
| 71070 | +#define CTIMEOPT_VAL_(opt) #opt | |
| 71071 | +#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) | |
| 71072 | + | |
| 71073 | +#ifdef SQLITE_32BIT_ROWID | |
| 71074 | + "32BIT_ROWID", | |
| 71075 | +#endif | |
| 71076 | +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC | |
| 71077 | + "4_BYTE_ALIGNED_MALLOC", | |
| 71078 | +#endif | |
| 71079 | +#ifdef SQLITE_CASE_SENSITIVE_LIKE | |
| 71080 | + "CASE_SENSITIVE_LIKE", | |
| 71081 | +#endif | |
| 71082 | +#ifdef SQLITE_CHECK_PAGES | |
| 71083 | + "CHECK_PAGES", | |
| 71084 | +#endif | |
| 71085 | +#ifdef SQLITE_COVERAGE_TEST | |
| 71086 | + "COVERAGE_TEST", | |
| 71087 | +#endif | |
| 71088 | +#ifdef SQLITE_DEBUG | |
| 71089 | + "DEBUG", | |
| 71090 | +#endif | |
| 71091 | +#ifdef SQLITE_DEFAULT_LOCKING_MODE | |
| 71092 | + "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), | |
| 71093 | +#endif | |
| 71094 | +#ifdef SQLITE_DISABLE_DIRSYNC | |
| 71095 | + "DISABLE_DIRSYNC", | |
| 71096 | +#endif | |
| 71097 | +#ifdef SQLITE_DISABLE_LFS | |
| 71098 | + "DISABLE_LFS", | |
| 71099 | +#endif | |
| 71100 | +#ifdef SQLITE_ENABLE_ATOMIC_WRITE | |
| 71101 | + "ENABLE_ATOMIC_WRITE", | |
| 71102 | +#endif | |
| 71103 | +#ifdef SQLITE_ENABLE_CEROD | |
| 71104 | + "ENABLE_CEROD", | |
| 71105 | +#endif | |
| 71106 | +#ifdef SQLITE_ENABLE_COLUMN_METADATA | |
| 71107 | + "ENABLE_COLUMN_METADATA", | |
| 71108 | +#endif | |
| 71109 | +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT | |
| 71110 | + "ENABLE_EXPENSIVE_ASSERT", | |
| 71111 | +#endif | |
| 71112 | +#ifdef SQLITE_ENABLE_FTS1 | |
| 71113 | + "ENABLE_FTS1", | |
| 71114 | +#endif | |
| 71115 | +#ifdef SQLITE_ENABLE_FTS2 | |
| 71116 | + "ENABLE_FTS2", | |
| 71117 | +#endif | |
| 71118 | +#ifdef SQLITE_ENABLE_FTS3 | |
| 71119 | + "ENABLE_FTS3", | |
| 71120 | +#endif | |
| 71121 | +#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS | |
| 71122 | + "ENABLE_FTS3_PARENTHESIS", | |
| 71123 | +#endif | |
| 71124 | +#ifdef SQLITE_ENABLE_FTS4 | |
| 71125 | + "ENABLE_FTS4", | |
| 71126 | +#endif | |
| 71127 | +#ifdef SQLITE_ENABLE_ICU | |
| 71128 | + "ENABLE_ICU", | |
| 71129 | +#endif | |
| 71130 | +#ifdef SQLITE_ENABLE_IOTRACE | |
| 71131 | + "ENABLE_IOTRACE", | |
| 71132 | +#endif | |
| 71133 | +#ifdef SQLITE_ENABLE_LOAD_EXTENSION | |
| 71134 | + "ENABLE_LOAD_EXTENSION", | |
| 71135 | +#endif | |
| 71136 | +#ifdef SQLITE_ENABLE_LOCKING_STYLE | |
| 71137 | + "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), | |
| 71138 | +#endif | |
| 71139 | +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT | |
| 71140 | + "ENABLE_MEMORY_MANAGEMENT", | |
| 71141 | +#endif | |
| 71142 | +#ifdef SQLITE_ENABLE_MEMSYS3 | |
| 71143 | + "ENABLE_MEMSYS3", | |
| 71144 | +#endif | |
| 71145 | +#ifdef SQLITE_ENABLE_MEMSYS5 | |
| 71146 | + "ENABLE_MEMSYS5", | |
| 71147 | +#endif | |
| 71148 | +#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK | |
| 71149 | + "ENABLE_OVERSIZE_CELL_CHECK", | |
| 71150 | +#endif | |
| 71151 | +#ifdef SQLITE_ENABLE_RTREE | |
| 71152 | + "ENABLE_RTREE", | |
| 71153 | +#endif | |
| 71154 | +#ifdef SQLITE_ENABLE_STAT2 | |
| 71155 | + "ENABLE_STAT2", | |
| 71156 | +#endif | |
| 71157 | +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY | |
| 71158 | + "ENABLE_UNLOCK_NOTIFY", | |
| 71159 | +#endif | |
| 71160 | +#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT | |
| 71161 | + "ENABLE_UPDATE_DELETE_LIMIT", | |
| 71162 | +#endif | |
| 71163 | +#ifdef SQLITE_HAS_CODEC | |
| 71164 | + "HAS_CODEC", | |
| 71165 | +#endif | |
| 71166 | +#ifdef SQLITE_HAVE_ISNAN | |
| 71167 | + "HAVE_ISNAN", | |
| 71168 | +#endif | |
| 71169 | +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX | |
| 71170 | + "HOMEGROWN_RECURSIVE_MUTEX", | |
| 71171 | +#endif | |
| 71172 | +#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS | |
| 71173 | + "IGNORE_AFP_LOCK_ERRORS", | |
| 71174 | +#endif | |
| 71175 | +#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS | |
| 71176 | + "IGNORE_FLOCK_LOCK_ERRORS", | |
| 71177 | +#endif | |
| 71178 | +#ifdef SQLITE_INT64_TYPE | |
| 71179 | + "INT64_TYPE", | |
| 71180 | +#endif | |
| 71181 | +#ifdef SQLITE_LOCK_TRACE | |
| 71182 | + "LOCK_TRACE", | |
| 71183 | +#endif | |
| 71184 | +#ifdef SQLITE_MEMDEBUG | |
| 71185 | + "MEMDEBUG", | |
| 71186 | +#endif | |
| 71187 | +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT | |
| 71188 | + "MIXED_ENDIAN_64BIT_FLOAT", | |
| 71189 | +#endif | |
| 71190 | +#ifdef SQLITE_NO_SYNC | |
| 71191 | + "NO_SYNC", | |
| 71192 | +#endif | |
| 71193 | +#ifdef SQLITE_OMIT_ALTERTABLE | |
| 71194 | + "OMIT_ALTERTABLE", | |
| 71195 | +#endif | |
| 71196 | +#ifdef SQLITE_OMIT_ANALYZE | |
| 71197 | + "OMIT_ANALYZE", | |
| 71198 | +#endif | |
| 71199 | +#ifdef SQLITE_OMIT_ATTACH | |
| 71200 | + "OMIT_ATTACH", | |
| 71201 | +#endif | |
| 71202 | +#ifdef SQLITE_OMIT_AUTHORIZATION | |
| 71203 | + "OMIT_AUTHORIZATION", | |
| 71204 | +#endif | |
| 71205 | +#ifdef SQLITE_OMIT_AUTOINCREMENT | |
| 71206 | + "OMIT_AUTOINCREMENT", | |
| 71207 | +#endif | |
| 71208 | +#ifdef SQLITE_OMIT_AUTOINIT | |
| 71209 | + "OMIT_AUTOINIT", | |
| 71210 | +#endif | |
| 71211 | +#ifdef SQLITE_OMIT_AUTOVACUUM | |
| 71212 | + "OMIT_AUTOVACUUM", | |
| 71213 | +#endif | |
| 71214 | +#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION | |
| 71215 | + "OMIT_BETWEEN_OPTIMIZATION", | |
| 71216 | +#endif | |
| 71217 | +#ifdef SQLITE_OMIT_BLOB_LITERAL | |
| 71218 | + "OMIT_BLOB_LITERAL", | |
| 71219 | +#endif | |
| 71220 | +#ifdef SQLITE_OMIT_BTREECOUNT | |
| 71221 | + "OMIT_BTREECOUNT", | |
| 71222 | +#endif | |
| 71223 | +#ifdef SQLITE_OMIT_BUILTIN_TEST | |
| 71224 | + "OMIT_BUILTIN_TEST", | |
| 71225 | +#endif | |
| 71226 | +#ifdef SQLITE_OMIT_CAST | |
| 71227 | + "OMIT_CAST", | |
| 71228 | +#endif | |
| 71229 | +#ifdef SQLITE_OMIT_CHECK | |
| 71230 | + "OMIT_CHECK", | |
| 71231 | +#endif | |
| 71232 | +#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS | |
| 71233 | + "OMIT_COMPILEOPTION_DIAGS", | |
| 71234 | +#endif | |
| 71235 | +#ifdef SQLITE_OMIT_COMPLETE | |
| 71236 | + "OMIT_COMPLETE", | |
| 71237 | +#endif | |
| 71238 | +#ifdef SQLITE_OMIT_COMPOUND_SELECT | |
| 71239 | + "OMIT_COMPOUND_SELECT", | |
| 71240 | +#endif | |
| 71241 | +#ifdef SQLITE_OMIT_DATETIME_FUNCS | |
| 71242 | + "OMIT_DATETIME_FUNCS", | |
| 71243 | +#endif | |
| 71244 | +#ifdef SQLITE_OMIT_DECLTYPE | |
| 71245 | + "OMIT_DECLTYPE", | |
| 71246 | +#endif | |
| 71247 | +#ifdef SQLITE_OMIT_DEPRECATED | |
| 71248 | + "OMIT_DEPRECATED", | |
| 71249 | +#endif | |
| 71250 | +#ifdef SQLITE_OMIT_DISKIO | |
| 71251 | + "OMIT_DISKIO", | |
| 71252 | +#endif | |
| 71253 | +#ifdef SQLITE_OMIT_EXPLAIN | |
| 71254 | + "OMIT_EXPLAIN", | |
| 71255 | +#endif | |
| 71256 | +#ifdef SQLITE_OMIT_FLAG_PRAGMAS | |
| 71257 | + "OMIT_FLAG_PRAGMAS", | |
| 71258 | +#endif | |
| 71259 | +#ifdef SQLITE_OMIT_FLOATING_POINT | |
| 71260 | + "OMIT_FLOATING_POINT", | |
| 71261 | +#endif | |
| 71262 | +#ifdef SQLITE_OMIT_FOREIGN_KEY | |
| 71263 | + "OMIT_FOREIGN_KEY", | |
| 71264 | +#endif | |
| 71265 | +#ifdef SQLITE_OMIT_GET_TABLE | |
| 71266 | + "OMIT_GET_TABLE", | |
| 71267 | +#endif | |
| 71268 | +#ifdef SQLITE_OMIT_GLOBALRECOVER | |
| 71269 | + "OMIT_GLOBALRECOVER", | |
| 71270 | +#endif | |
| 71271 | +#ifdef SQLITE_OMIT_INCRBLOB | |
| 71272 | + "OMIT_INCRBLOB", | |
| 71273 | +#endif | |
| 71274 | +#ifdef SQLITE_OMIT_INTEGRITY_CHECK | |
| 71275 | + "OMIT_INTEGRITY_CHECK", | |
| 71276 | +#endif | |
| 71277 | +#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION | |
| 71278 | + "OMIT_LIKE_OPTIMIZATION", | |
| 71279 | +#endif | |
| 71280 | +#ifdef SQLITE_OMIT_LOAD_EXTENSION | |
| 71281 | + "OMIT_LOAD_EXTENSION", | |
| 71282 | +#endif | |
| 71283 | +#ifdef SQLITE_OMIT_LOCALTIME | |
| 71284 | + "OMIT_LOCALTIME", | |
| 71285 | +#endif | |
| 71286 | +#ifdef SQLITE_OMIT_LOOKASIDE | |
| 71287 | + "OMIT_LOOKASIDE", | |
| 71288 | +#endif | |
| 71289 | +#ifdef SQLITE_OMIT_MEMORYDB | |
| 71290 | + "OMIT_MEMORYDB", | |
| 71291 | +#endif | |
| 71292 | +#ifdef SQLITE_OMIT_OR_OPTIMIZATION | |
| 71293 | + "OMIT_OR_OPTIMIZATION", | |
| 71294 | +#endif | |
| 71295 | +#ifdef SQLITE_OMIT_PAGER_PRAGMAS | |
| 71296 | + "OMIT_PAGER_PRAGMAS", | |
| 71297 | +#endif | |
| 71298 | +#ifdef SQLITE_OMIT_PRAGMA | |
| 71299 | + "OMIT_PRAGMA", | |
| 71300 | +#endif | |
| 71301 | +#ifdef SQLITE_OMIT_PROGRESS_CALLBACK | |
| 71302 | + "OMIT_PROGRESS_CALLBACK", | |
| 71303 | +#endif | |
| 71304 | +#ifdef SQLITE_OMIT_QUICKBALANCE | |
| 71305 | + "OMIT_QUICKBALANCE", | |
| 71306 | +#endif | |
| 71307 | +#ifdef SQLITE_OMIT_REINDEX | |
| 71308 | + "OMIT_REINDEX", | |
| 71309 | +#endif | |
| 71310 | +#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS | |
| 71311 | + "OMIT_SCHEMA_PRAGMAS", | |
| 71312 | +#endif | |
| 71313 | +#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS | |
| 71314 | + "OMIT_SCHEMA_VERSION_PRAGMAS", | |
| 71315 | +#endif | |
| 71316 | +#ifdef SQLITE_OMIT_SHARED_CACHE | |
| 71317 | + "OMIT_SHARED_CACHE", | |
| 71318 | +#endif | |
| 71319 | +#ifdef SQLITE_OMIT_SUBQUERY | |
| 71320 | + "OMIT_SUBQUERY", | |
| 71321 | +#endif | |
| 71322 | +#ifdef SQLITE_OMIT_TCL_VARIABLE | |
| 71323 | + "OMIT_TCL_VARIABLE", | |
| 71324 | +#endif | |
| 71325 | +#ifdef SQLITE_OMIT_TEMPDB | |
| 71326 | + "OMIT_TEMPDB", | |
| 71327 | +#endif | |
| 71328 | +#ifdef SQLITE_OMIT_TRACE | |
| 71329 | + "OMIT_TRACE", | |
| 71330 | +#endif | |
| 71331 | +#ifdef SQLITE_OMIT_TRIGGER | |
| 71332 | + "OMIT_TRIGGER", | |
| 71333 | +#endif | |
| 71334 | +#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION | |
| 71335 | + "OMIT_TRUNCATE_OPTIMIZATION", | |
| 71336 | +#endif | |
| 71337 | +#ifdef SQLITE_OMIT_UTF16 | |
| 71338 | + "OMIT_UTF16", | |
| 71339 | +#endif | |
| 71340 | +#ifdef SQLITE_OMIT_VACUUM | |
| 71341 | + "OMIT_VACUUM", | |
| 71342 | +#endif | |
| 71343 | +#ifdef SQLITE_OMIT_VIEW | |
| 71344 | + "OMIT_VIEW", | |
| 71345 | +#endif | |
| 71346 | +#ifdef SQLITE_OMIT_VIRTUALTABLE | |
| 71347 | + "OMIT_VIRTUALTABLE", | |
| 71348 | +#endif | |
| 71349 | +#ifdef SQLITE_OMIT_WSD | |
| 71350 | + "OMIT_WSD", | |
| 71351 | +#endif | |
| 71352 | +#ifdef SQLITE_OMIT_XFER_OPT | |
| 71353 | + "OMIT_XFER_OPT", | |
| 71354 | +#endif | |
| 71355 | +#ifdef SQLITE_PERFORMANCE_TRACE | |
| 71356 | + "PERFORMANCE_TRACE", | |
| 71357 | +#endif | |
| 71358 | +#ifdef SQLITE_PROXY_DEBUG | |
| 71359 | + "PROXY_DEBUG", | |
| 71360 | +#endif | |
| 71361 | +#ifdef SQLITE_SECURE_DELETE | |
| 71362 | + "SECURE_DELETE", | |
| 71363 | +#endif | |
| 71364 | +#ifdef SQLITE_SMALL_STACK | |
| 71365 | + "SMALL_STACK", | |
| 71366 | +#endif | |
| 71367 | +#ifdef SQLITE_SOUNDEX | |
| 71368 | + "SOUNDEX", | |
| 71369 | +#endif | |
| 71370 | +#ifdef SQLITE_TCL | |
| 71371 | + "TCL", | |
| 71372 | +#endif | |
| 71373 | +#ifdef SQLITE_TEMP_STORE | |
| 71374 | + "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), | |
| 71375 | +#endif | |
| 71376 | +#ifdef SQLITE_TEST | |
| 71377 | + "TEST", | |
| 71378 | +#endif | |
| 71379 | +#ifdef SQLITE_THREADSAFE | |
| 71380 | + "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), | |
| 71381 | +#endif | |
| 71382 | +#ifdef SQLITE_USE_ALLOCA | |
| 71383 | + "USE_ALLOCA", | |
| 71384 | +#endif | |
| 71385 | +#ifdef SQLITE_ZERO_MALLOC | |
| 71386 | + "ZERO_MALLOC" | |
| 71387 | +#endif | |
| 71388 | +}; | |
| 71389 | + | |
| 71390 | +/* | |
| 71391 | +** Given the name of a compile-time option, return true if that option | |
| 71392 | +** was used and false if not. | |
| 71393 | +** | |
| 71394 | +** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix | |
| 71395 | +** is not required for a match. | |
| 71396 | +*/ | |
| 71397 | +SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ | |
| 71398 | + int i, n; | |
| 71399 | + if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; | |
| 71400 | + n = sqlite3Strlen30(zOptName); | |
| 71401 | + | |
| 71402 | + /* Since ArraySize(azCompileOpt) is normally in single digits, a | |
| 71403 | + ** linear search is adequate. No need for a binary search. */ | |
| 71404 | + for(i=0; i<ArraySize(azCompileOpt); i++){ | |
| 71405 | + if( (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0) | |
| 71406 | + && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1; | |
| 71407 | + } | |
| 71408 | + return 0; | |
| 71409 | +} | |
| 71410 | + | |
| 71411 | +/* | |
| 71412 | +** Return the N-th compile-time option string. If N is out of range, | |
| 71413 | +** return a NULL pointer. | |
| 71414 | +*/ | |
| 71415 | +SQLITE_API const char *sqlite3_compileoption_get(int N){ | |
| 71416 | + if( N>=0 && N<ArraySize(azCompileOpt) ){ | |
| 71417 | + return azCompileOpt[N]; | |
| 71418 | + } | |
| 71419 | + return 0; | |
| 71420 | +} | |
| 71421 | + | |
| 71422 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ | |
| 71423 | + | |
| 71424 | +/************** End of ctime.c ***********************************************/ | |
| 70344 | 71425 | /************** Begin file delete.c ******************************************/ |
| 70345 | 71426 | /* |
| 70346 | 71427 | ** 2001 September 15 |
| 70347 | 71428 | ** |
| 70348 | 71429 | ** The author disclaims copyright to this source code. In place of |
| @@ -71247,18 +72328,28 @@ | ||
| 71247 | 72328 | if( n>30 ) n = 30; |
| 71248 | 72329 | if( n<0 ) n = 0; |
| 71249 | 72330 | } |
| 71250 | 72331 | if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
| 71251 | 72332 | r = sqlite3_value_double(argv[0]); |
| 71252 | - zBuf = sqlite3_mprintf("%.*f",n,r); | |
| 71253 | - if( zBuf==0 ){ | |
| 71254 | - sqlite3_result_error_nomem(context); | |
| 72333 | + /* If Y==0 and X will fit in a 64-bit int, | |
| 72334 | + ** handle the rounding directly, | |
| 72335 | + ** otherwise use printf. | |
| 72336 | + */ | |
| 72337 | + if( n==0 && r>=0 && r<LARGEST_INT64-1 ){ | |
| 72338 | + r = (double)((sqlite_int64)(r+0.5)); | |
| 72339 | + }else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){ | |
| 72340 | + r = -(double)((sqlite_int64)((-r)+0.5)); | |
| 71255 | 72341 | }else{ |
| 72342 | + zBuf = sqlite3_mprintf("%.*f",n,r); | |
| 72343 | + if( zBuf==0 ){ | |
| 72344 | + sqlite3_result_error_nomem(context); | |
| 72345 | + return; | |
| 72346 | + } | |
| 71256 | 72347 | sqlite3AtoF(zBuf, &r); |
| 71257 | 72348 | sqlite3_free(zBuf); |
| 71258 | - sqlite3_result_double(context, r); | |
| 71259 | 72349 | } |
| 72350 | + sqlite3_result_double(context, r); | |
| 71260 | 72351 | } |
| 71261 | 72352 | #endif |
| 71262 | 72353 | |
| 71263 | 72354 | /* |
| 71264 | 72355 | ** Allocate nByte bytes of space using sqlite3_malloc(). If the |
| @@ -71416,16 +72507,22 @@ | ||
| 71416 | 72507 | int NotUsed, |
| 71417 | 72508 | sqlite3_value **NotUsed2 |
| 71418 | 72509 | ){ |
| 71419 | 72510 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 71420 | 72511 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 72512 | + /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a | |
| 72513 | + ** wrapper around the sqlite3_last_insert_rowid() C/C++ interface | |
| 72514 | + ** function. */ | |
| 71421 | 72515 | sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); |
| 71422 | 72516 | } |
| 71423 | 72517 | |
| 71424 | 72518 | /* |
| 71425 | -** Implementation of the changes() SQL function. The return value is the | |
| 71426 | -** same as the sqlite3_changes() API function. | |
| 72519 | +** Implementation of the changes() SQL function. | |
| 72520 | +** | |
| 72521 | +** IMP: R-62073-11209 The changes() SQL function is a wrapper | |
| 72522 | +** around the sqlite3_changes() C/C++ function and hence follows the same | |
| 72523 | +** rules for counting changes. | |
| 71427 | 72524 | */ |
| 71428 | 72525 | static void changes( |
| 71429 | 72526 | sqlite3_context *context, |
| 71430 | 72527 | int NotUsed, |
| 71431 | 72528 | sqlite3_value **NotUsed2 |
| @@ -71444,10 +72541,12 @@ | ||
| 71444 | 72541 | int NotUsed, |
| 71445 | 72542 | sqlite3_value **NotUsed2 |
| 71446 | 72543 | ){ |
| 71447 | 72544 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 71448 | 72545 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 72546 | + /* IMP: R-52756-41993 This function is a wrapper around the | |
| 72547 | + ** sqlite3_total_changes() C/C++ interface. */ | |
| 71449 | 72548 | sqlite3_result_int(context, sqlite3_total_changes(db)); |
| 71450 | 72549 | } |
| 71451 | 72550 | |
| 71452 | 72551 | /* |
| 71453 | 72552 | ** A structure defining how to do GLOB-style comparisons. |
| @@ -71711,11 +72810,13 @@ | ||
| 71711 | 72810 | sqlite3_context *context, |
| 71712 | 72811 | int NotUsed, |
| 71713 | 72812 | sqlite3_value **NotUsed2 |
| 71714 | 72813 | ){ |
| 71715 | 72814 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 71716 | - sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC); | |
| 72815 | + /* IMP: R-48699-48617 This function is an SQL wrapper around the | |
| 72816 | + ** sqlite3_libversion() C-interface. */ | |
| 72817 | + sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC); | |
| 71717 | 72818 | } |
| 71718 | 72819 | |
| 71719 | 72820 | /* |
| 71720 | 72821 | ** Implementation of the sqlite_source_id() function. The result is a string |
| 71721 | 72822 | ** that identifies the particular version of the source code used to build |
| @@ -71725,13 +72826,58 @@ | ||
| 71725 | 72826 | sqlite3_context *context, |
| 71726 | 72827 | int NotUsed, |
| 71727 | 72828 | sqlite3_value **NotUsed2 |
| 71728 | 72829 | ){ |
| 71729 | 72830 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 71730 | - sqlite3_result_text(context, SQLITE_SOURCE_ID, -1, SQLITE_STATIC); | |
| 72831 | + /* IMP: R-24470-31136 This function is an SQL wrapper around the | |
| 72832 | + ** sqlite3_sourceid() C interface. */ | |
| 72833 | + sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC); | |
| 71731 | 72834 | } |
| 71732 | 72835 | |
| 72836 | +/* | |
| 72837 | +** Implementation of the sqlite_compileoption_used() function. | |
| 72838 | +** The result is an integer that identifies if the compiler option | |
| 72839 | +** was used to build SQLite. | |
| 72840 | +*/ | |
| 72841 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS | |
| 72842 | +static void compileoptionusedFunc( | |
| 72843 | + sqlite3_context *context, | |
| 72844 | + int argc, | |
| 72845 | + sqlite3_value **argv | |
| 72846 | +){ | |
| 72847 | + const char *zOptName; | |
| 72848 | + assert( argc==1 ); | |
| 72849 | + UNUSED_PARAMETER(argc); | |
| 72850 | + /* IMP: R-xxxx This function is an SQL wrapper around the | |
| 72851 | + ** sqlite3_compileoption_used() C interface. */ | |
| 72852 | + if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){ | |
| 72853 | + sqlite3_result_int(context, sqlite3_compileoption_used(zOptName)); | |
| 72854 | + } | |
| 72855 | +} | |
| 72856 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ | |
| 72857 | + | |
| 72858 | +/* | |
| 72859 | +** Implementation of the sqlite_compileoption_get() function. | |
| 72860 | +** The result is a string that identifies the compiler options | |
| 72861 | +** used to build SQLite. | |
| 72862 | +*/ | |
| 72863 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS | |
| 72864 | +static void compileoptiongetFunc( | |
| 72865 | + sqlite3_context *context, | |
| 72866 | + int argc, | |
| 72867 | + sqlite3_value **argv | |
| 72868 | +){ | |
| 72869 | + int n; | |
| 72870 | + assert( argc==1 ); | |
| 72871 | + UNUSED_PARAMETER(argc); | |
| 72872 | + /* IMP: R-xxxx This function is an SQL wrapper around the | |
| 72873 | + ** sqlite3_compileoption_get() C interface. */ | |
| 72874 | + n = sqlite3_value_int(argv[0]); | |
| 72875 | + sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC); | |
| 72876 | +} | |
| 72877 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ | |
| 72878 | + | |
| 71733 | 72879 | /* Array for converting from half-bytes (nybbles) into ASCII hex |
| 71734 | 72880 | ** digits. */ |
| 71735 | 72881 | static const char hexdigits[] = { |
| 71736 | 72882 | '0', '1', '2', '3', '4', '5', '6', '7', |
| 71737 | 72883 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' |
| @@ -71854,11 +73000,11 @@ | ||
| 71854 | 73000 | testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
| 71855 | 73001 | testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); |
| 71856 | 73002 | if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 71857 | 73003 | sqlite3_result_error_toobig(context); |
| 71858 | 73004 | }else{ |
| 71859 | - sqlite3_result_zeroblob(context, (int)n); | |
| 73005 | + sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */ | |
| 71860 | 73006 | } |
| 71861 | 73007 | } |
| 71862 | 73008 | |
| 71863 | 73009 | /* |
| 71864 | 73010 | ** The replace() function. Three arguments are all strings: call |
| @@ -72459,10 +73605,14 @@ | ||
| 72459 | 73605 | FUNCTION(random, 0, 0, 0, randomFunc ), |
| 72460 | 73606 | FUNCTION(randomblob, 1, 0, 0, randomBlob ), |
| 72461 | 73607 | FUNCTION(nullif, 2, 0, 1, nullifFunc ), |
| 72462 | 73608 | FUNCTION(sqlite_version, 0, 0, 0, versionFunc ), |
| 72463 | 73609 | FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), |
| 73610 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS | |
| 73611 | + FUNCTION(sqlite_compile_option_used,1, 0, 0, compileoptionusedFunc ), | |
| 73612 | + FUNCTION(sqlite_compile_option_get, 1, 0, 0, compileoptiongetFunc ), | |
| 73613 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ | |
| 72464 | 73614 | FUNCTION(quote, 1, 0, 0, quoteFunc ), |
| 72465 | 73615 | FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), |
| 72466 | 73616 | FUNCTION(changes, 0, 0, 0, changes ), |
| 72467 | 73617 | FUNCTION(total_changes, 0, 0, 0, total_changes ), |
| 72468 | 73618 | FUNCTION(replace, 3, 0, 0, replaceFunc ), |
| @@ -74958,23 +76108,37 @@ | ||
| 74958 | 76108 | ** recursive-triggers flag is set, call GenerateRowDelete() to |
| 74959 | 76109 | ** remove the conflicting row from the the table. This will fire |
| 74960 | 76110 | ** the triggers and remove both the table and index b-tree entries. |
| 74961 | 76111 | ** |
| 74962 | 76112 | ** Otherwise, if there are no triggers or the recursive-triggers |
| 74963 | - ** flag is not set, call GenerateRowIndexDelete(). This removes | |
| 74964 | - ** the index b-tree entries only. The table b-tree entry will be | |
| 74965 | - ** replaced by the new entry when it is inserted. */ | |
| 76113 | + ** flag is not set, but the table has one or more indexes, call | |
| 76114 | + ** GenerateRowIndexDelete(). This removes the index b-tree entries | |
| 76115 | + ** only. The table b-tree entry will be replaced by the new entry | |
| 76116 | + ** when it is inserted. | |
| 76117 | + ** | |
| 76118 | + ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called, | |
| 76119 | + ** also invoke MultiWrite() to indicate that this VDBE may require | |
| 76120 | + ** statement rollback (if the statement is aborted after the delete | |
| 76121 | + ** takes place). Earlier versions called sqlite3MultiWrite() regardless, | |
| 76122 | + ** but being more selective here allows statements like: | |
| 76123 | + ** | |
| 76124 | + ** REPLACE INTO t(rowid) VALUES($newrowid) | |
| 76125 | + ** | |
| 76126 | + ** to run without a statement journal if there are no indexes on the | |
| 76127 | + ** table. | |
| 76128 | + */ | |
| 74966 | 76129 | Trigger *pTrigger = 0; |
| 74967 | 76130 | if( pParse->db->flags&SQLITE_RecTriggers ){ |
| 74968 | 76131 | pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
| 74969 | 76132 | } |
| 74970 | - sqlite3MultiWrite(pParse); | |
| 74971 | 76133 | if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ |
| 76134 | + sqlite3MultiWrite(pParse); | |
| 74972 | 76135 | sqlite3GenerateRowDelete( |
| 74973 | 76136 | pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace |
| 74974 | 76137 | ); |
| 74975 | - }else{ | |
| 76138 | + }else if( pTab->pIndex ){ | |
| 76139 | + sqlite3MultiWrite(pParse); | |
| 74976 | 76140 | sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); |
| 74977 | 76141 | } |
| 74978 | 76142 | seenReplace = 1; |
| 74979 | 76143 | break; |
| 74980 | 76144 | } |
| @@ -75412,11 +76576,11 @@ | ||
| 75412 | 76576 | if( pSrcIdx==0 ){ |
| 75413 | 76577 | return 0; /* pDestIdx has no corresponding index in pSrc */ |
| 75414 | 76578 | } |
| 75415 | 76579 | } |
| 75416 | 76580 | #ifndef SQLITE_OMIT_CHECK |
| 75417 | - if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ | |
| 76581 | + if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ | |
| 75418 | 76582 | return 0; /* Tables have different CHECK constraints. Ticket #2252 */ |
| 75419 | 76583 | } |
| 75420 | 76584 | #endif |
| 75421 | 76585 | |
| 75422 | 76586 | /* If we get this far, it means either: |
| @@ -75555,10 +76719,11 @@ | ||
| 75555 | 76719 | sqlite3_stmt *pStmt = 0; /* The current SQL statement */ |
| 75556 | 76720 | char **azCols = 0; /* Names of result columns */ |
| 75557 | 76721 | int nRetry = 0; /* Number of retry attempts */ |
| 75558 | 76722 | int callbackIsInit; /* True if callback data is initialized */ |
| 75559 | 76723 | |
| 76724 | + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; | |
| 75560 | 76725 | if( zSql==0 ) zSql = ""; |
| 75561 | 76726 | |
| 75562 | 76727 | sqlite3_mutex_enter(db->mutex); |
| 75563 | 76728 | sqlite3Error(db, SQLITE_OK, 0); |
| 75564 | 76729 | while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){ |
| @@ -76936,10 +78101,11 @@ | ||
| 76936 | 78101 | int iDb; /* Database index for <database> */ |
| 76937 | 78102 | sqlite3 *db = pParse->db; |
| 76938 | 78103 | Db *pDb; |
| 76939 | 78104 | Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); |
| 76940 | 78105 | if( v==0 ) return; |
| 78106 | + sqlite3VdbeRunOnlyOnce(v); | |
| 76941 | 78107 | pParse->nMem = 2; |
| 76942 | 78108 | |
| 76943 | 78109 | /* Interpret the [database.] part of the pragma statement. iDb is the |
| 76944 | 78110 | ** index of the database this pragma is being applied to in db.aDb[]. */ |
| 76945 | 78111 | iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); |
| @@ -77067,10 +78233,35 @@ | ||
| 77067 | 78233 | newMax = sqlite3BtreeMaxPageCount(pBt, newMax); |
| 77068 | 78234 | } |
| 77069 | 78235 | returnSingleInt(pParse, "max_page_count", newMax); |
| 77070 | 78236 | }else |
| 77071 | 78237 | |
| 78238 | + /* | |
| 78239 | + ** PRAGMA [database.]secure_delete | |
| 78240 | + ** PRAGMA [database.]secure_delete=ON/OFF | |
| 78241 | + ** | |
| 78242 | + ** The first form reports the current setting for the | |
| 78243 | + ** secure_delete flag. The second form changes the secure_delete | |
| 78244 | + ** flag setting and reports thenew value. | |
| 78245 | + */ | |
| 78246 | + if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){ | |
| 78247 | + Btree *pBt = pDb->pBt; | |
| 78248 | + int b = -1; | |
| 78249 | + assert( pBt!=0 ); | |
| 78250 | + if( zRight ){ | |
| 78251 | + b = getBoolean(zRight); | |
| 78252 | + } | |
| 78253 | + if( pId2->n==0 && b>=0 ){ | |
| 78254 | + int ii; | |
| 78255 | + for(ii=0; ii<db->nDb; ii++){ | |
| 78256 | + sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b); | |
| 78257 | + } | |
| 78258 | + } | |
| 78259 | + b = sqlite3BtreeSecureDelete(pBt, b); | |
| 78260 | + returnSingleInt(pParse, "secure_delete", b); | |
| 78261 | + }else | |
| 78262 | + | |
| 77072 | 78263 | /* |
| 77073 | 78264 | ** PRAGMA [database.]page_count |
| 77074 | 78265 | ** |
| 77075 | 78266 | ** Return the number of pages in the specified database. |
| 77076 | 78267 | */ |
| @@ -77985,10 +79176,38 @@ | ||
| 77985 | 79176 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); |
| 77986 | 79177 | } |
| 77987 | 79178 | }else |
| 77988 | 79179 | #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ |
| 77989 | 79180 | |
| 79181 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS | |
| 79182 | + /* | |
| 79183 | + ** PRAGMA compile_options | |
| 79184 | + ** PRAGMA compile_option(<option>) | |
| 79185 | + ** | |
| 79186 | + ** The first form returns a single row for each option that was | |
| 79187 | + ** defined at compile time. The second form returns 0 or 1 | |
| 79188 | + ** indicating whether the specified option was defined at | |
| 79189 | + ** compile time. | |
| 79190 | + */ | |
| 79191 | + if( sqlite3StrICmp(zLeft, "compile_option")==0 && zRight ){ | |
| 79192 | + int used = sqlite3_compileoption_used(zRight); | |
| 79193 | + returnSingleInt(pParse, zRight, used); | |
| 79194 | + }else | |
| 79195 | + | |
| 79196 | + if( sqlite3StrICmp(zLeft, "compile_options")==0 ){ | |
| 79197 | + int i = 0; | |
| 79198 | + const char *zOpt; | |
| 79199 | + sqlite3VdbeSetNumCols(v, 1); | |
| 79200 | + pParse->nMem = 1; | |
| 79201 | + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC); | |
| 79202 | + while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ | |
| 79203 | + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0); | |
| 79204 | + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); | |
| 79205 | + } | |
| 79206 | + }else | |
| 79207 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ | |
| 79208 | + | |
| 77990 | 79209 | #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
| 77991 | 79210 | /* |
| 77992 | 79211 | ** Report the current state of file logs for all databases |
| 77993 | 79212 | */ |
| 77994 | 79213 | if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ |
| @@ -78019,11 +79238,11 @@ | ||
| 78019 | 79238 | } |
| 78020 | 79239 | |
| 78021 | 79240 | }else |
| 78022 | 79241 | #endif |
| 78023 | 79242 | |
| 78024 | -#if SQLITE_HAS_CODEC | |
| 79243 | +#ifdef SQLITE_HAS_CODEC | |
| 78025 | 79244 | if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){ |
| 78026 | 79245 | sqlite3_key(db, zRight, sqlite3Strlen30(zRight)); |
| 78027 | 79246 | }else |
| 78028 | 79247 | if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){ |
| 78029 | 79248 | sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight)); |
| @@ -78042,36 +79261,28 @@ | ||
| 78042 | 79261 | }else{ |
| 78043 | 79262 | sqlite3_rekey(db, zKey, i/2); |
| 78044 | 79263 | } |
| 78045 | 79264 | }else |
| 78046 | 79265 | #endif |
| 78047 | -#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD) | |
| 79266 | +#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) | |
| 78048 | 79267 | if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){ |
| 78049 | -#if SQLITE_HAS_CODEC | |
| 79268 | +#ifdef SQLITE_HAS_CODEC | |
| 78050 | 79269 | if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ |
| 78051 | - extern void sqlite3_activate_see(const char*); | |
| 78052 | 79270 | sqlite3_activate_see(&zRight[4]); |
| 78053 | 79271 | } |
| 78054 | 79272 | #endif |
| 78055 | 79273 | #ifdef SQLITE_ENABLE_CEROD |
| 78056 | 79274 | if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ |
| 78057 | - extern void sqlite3_activate_cerod(const char*); | |
| 78058 | 79275 | sqlite3_activate_cerod(&zRight[6]); |
| 78059 | 79276 | } |
| 78060 | 79277 | #endif |
| 78061 | 79278 | }else |
| 78062 | 79279 | #endif |
| 78063 | 79280 | |
| 78064 | 79281 | |
| 78065 | 79282 | {/* Empty ELSE clause */} |
| 78066 | 79283 | |
| 78067 | - /* Code an OP_Expire at the end of each PRAGMA program to cause | |
| 78068 | - ** the VDBE implementing the pragma to expire. Most (all?) pragmas | |
| 78069 | - ** are only valid for a single execution. | |
| 78070 | - */ | |
| 78071 | - sqlite3VdbeAddOp2(v, OP_Expire, 1, 0); | |
| 78072 | - | |
| 78073 | 79284 | /* |
| 78074 | 79285 | ** Reset the safety level, in case the fullfsync flag or synchronous |
| 78075 | 79286 | ** setting changed. |
| 78076 | 79287 | */ |
| 78077 | 79288 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| @@ -78280,13 +79491,11 @@ | ||
| 78280 | 79491 | azArg[3] = 0; |
| 78281 | 79492 | initData.db = db; |
| 78282 | 79493 | initData.iDb = iDb; |
| 78283 | 79494 | initData.rc = SQLITE_OK; |
| 78284 | 79495 | initData.pzErrMsg = pzErrMsg; |
| 78285 | - (void)sqlite3SafetyOff(db); | |
| 78286 | 79496 | sqlite3InitCallback(&initData, 3, (char **)azArg, 0); |
| 78287 | - (void)sqlite3SafetyOn(db); | |
| 78288 | 79497 | if( initData.rc ){ |
| 78289 | 79498 | rc = initData.rc; |
| 78290 | 79499 | goto error_out; |
| 78291 | 79500 | } |
| 78292 | 79501 | pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); |
| @@ -78403,13 +79612,12 @@ | ||
| 78403 | 79612 | */ |
| 78404 | 79613 | assert( db->init.busy ); |
| 78405 | 79614 | { |
| 78406 | 79615 | char *zSql; |
| 78407 | 79616 | zSql = sqlite3MPrintf(db, |
| 78408 | - "SELECT name, rootpage, sql FROM '%q'.%s", | |
| 79617 | + "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid", | |
| 78409 | 79618 | db->aDb[iDb].zName, zMasterName); |
| 78410 | - (void)sqlite3SafetyOff(db); | |
| 78411 | 79619 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 78412 | 79620 | { |
| 78413 | 79621 | int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); |
| 78414 | 79622 | xAuth = db->xAuth; |
| 78415 | 79623 | db->xAuth = 0; |
| @@ -78418,11 +79626,10 @@ | ||
| 78418 | 79626 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 78419 | 79627 | db->xAuth = xAuth; |
| 78420 | 79628 | } |
| 78421 | 79629 | #endif |
| 78422 | 79630 | if( rc==SQLITE_OK ) rc = initData.rc; |
| 78423 | - (void)sqlite3SafetyOn(db); | |
| 78424 | 79631 | sqlite3DbFree(db, zSql); |
| 78425 | 79632 | #ifndef SQLITE_OMIT_ANALYZE |
| 78426 | 79633 | if( rc==SQLITE_OK ){ |
| 78427 | 79634 | sqlite3AnalysisLoad(db, iDb); |
| 78428 | 79635 | } |
| @@ -78627,15 +79834,10 @@ | ||
| 78627 | 79834 | if( pParse==0 ){ |
| 78628 | 79835 | rc = SQLITE_NOMEM; |
| 78629 | 79836 | goto end_prepare; |
| 78630 | 79837 | } |
| 78631 | 79838 | pParse->pReprepare = pReprepare; |
| 78632 | - | |
| 78633 | - if( sqlite3SafetyOn(db) ){ | |
| 78634 | - rc = SQLITE_MISUSE; | |
| 78635 | - goto end_prepare; | |
| 78636 | - } | |
| 78637 | 79839 | assert( ppStmt && *ppStmt==0 ); |
| 78638 | 79840 | assert( !db->mallocFailed ); |
| 78639 | 79841 | assert( sqlite3_mutex_held(db->mutex) ); |
| 78640 | 79842 | |
| 78641 | 79843 | /* Check to verify that it is possible to get a read lock on all |
| @@ -78667,11 +79869,10 @@ | ||
| 78667 | 79869 | assert( sqlite3BtreeHoldsMutex(pBt) ); |
| 78668 | 79870 | rc = sqlite3BtreeSchemaLocked(pBt); |
| 78669 | 79871 | if( rc ){ |
| 78670 | 79872 | const char *zDb = db->aDb[i].zName; |
| 78671 | 79873 | sqlite3Error(db, rc, "database schema is locked: %s", zDb); |
| 78672 | - (void)sqlite3SafetyOff(db); | |
| 78673 | 79874 | testcase( db->flags & SQLITE_ReadUncommitted ); |
| 78674 | 79875 | goto end_prepare; |
| 78675 | 79876 | } |
| 78676 | 79877 | } |
| 78677 | 79878 | } |
| @@ -78684,11 +79885,10 @@ | ||
| 78684 | 79885 | int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 78685 | 79886 | testcase( nBytes==mxLen ); |
| 78686 | 79887 | testcase( nBytes==mxLen+1 ); |
| 78687 | 79888 | if( nBytes>mxLen ){ |
| 78688 | 79889 | sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); |
| 78689 | - (void)sqlite3SafetyOff(db); | |
| 78690 | 79890 | rc = sqlite3ApiExit(db, SQLITE_TOOBIG); |
| 78691 | 79891 | goto end_prepare; |
| 78692 | 79892 | } |
| 78693 | 79893 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 78694 | 79894 | if( zSqlCopy ){ |
| @@ -78741,14 +79941,10 @@ | ||
| 78741 | 79941 | azColName[i], SQLITE_STATIC); |
| 78742 | 79942 | } |
| 78743 | 79943 | } |
| 78744 | 79944 | #endif |
| 78745 | 79945 | |
| 78746 | - if( sqlite3SafetyOff(db) ){ | |
| 78747 | - rc = SQLITE_MISUSE; | |
| 78748 | - } | |
| 78749 | - | |
| 78750 | 79946 | assert( db->init.busy==0 || saveSqlFlag==0 ); |
| 78751 | 79947 | if( db->init.busy==0 ){ |
| 78752 | 79948 | Vdbe *pVdbe = pParse->pVdbe; |
| 78753 | 79949 | sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); |
| 78754 | 79950 | } |
| @@ -78792,11 +79988,11 @@ | ||
| 78792 | 79988 | ){ |
| 78793 | 79989 | int rc; |
| 78794 | 79990 | assert( ppStmt!=0 ); |
| 78795 | 79991 | *ppStmt = 0; |
| 78796 | 79992 | if( !sqlite3SafetyCheckOk(db) ){ |
| 78797 | - return SQLITE_MISUSE; | |
| 79993 | + return SQLITE_MISUSE_BKPT; | |
| 78798 | 79994 | } |
| 78799 | 79995 | sqlite3_mutex_enter(db->mutex); |
| 78800 | 79996 | sqlite3BtreeEnterAll(db); |
| 78801 | 79997 | rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); |
| 78802 | 79998 | if( rc==SQLITE_SCHEMA ){ |
| @@ -78831,11 +80027,11 @@ | ||
| 78831 | 80027 | if( rc ){ |
| 78832 | 80028 | if( rc==SQLITE_NOMEM ){ |
| 78833 | 80029 | db->mallocFailed = 1; |
| 78834 | 80030 | } |
| 78835 | 80031 | assert( pNew==0 ); |
| 78836 | - return (rc==SQLITE_LOCKED) ? SQLITE_LOCKED : SQLITE_SCHEMA; | |
| 80032 | + return rc; | |
| 78837 | 80033 | }else{ |
| 78838 | 80034 | assert( pNew!=0 ); |
| 78839 | 80035 | } |
| 78840 | 80036 | sqlite3VdbeSwap((Vdbe*)pNew, p); |
| 78841 | 80037 | sqlite3TransferBindings(pNew, (sqlite3_stmt*)p); |
| @@ -78900,11 +80096,11 @@ | ||
| 78900 | 80096 | int rc = SQLITE_OK; |
| 78901 | 80097 | |
| 78902 | 80098 | assert( ppStmt ); |
| 78903 | 80099 | *ppStmt = 0; |
| 78904 | 80100 | if( !sqlite3SafetyCheckOk(db) ){ |
| 78905 | - return SQLITE_MISUSE; | |
| 80101 | + return SQLITE_MISUSE_BKPT; | |
| 78906 | 80102 | } |
| 78907 | 80103 | sqlite3_mutex_enter(db->mutex); |
| 78908 | 80104 | zSql8 = sqlite3Utf16to8(db, zSql, nBytes); |
| 78909 | 80105 | if( zSql8 ){ |
| 78910 | 80106 | rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); |
| @@ -82288,22 +83484,23 @@ | ||
| 82288 | 83484 | int i; |
| 82289 | 83485 | SrcList *pTabList; |
| 82290 | 83486 | struct SrcList_item *pFrom; |
| 82291 | 83487 | |
| 82292 | 83488 | assert( p->selFlags & SF_Resolved ); |
| 82293 | - assert( (p->selFlags & SF_HasTypeInfo)==0 ); | |
| 82294 | - p->selFlags |= SF_HasTypeInfo; | |
| 82295 | - pParse = pWalker->pParse; | |
| 82296 | - pTabList = p->pSrc; | |
| 82297 | - for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ | |
| 82298 | - Table *pTab = pFrom->pTab; | |
| 82299 | - if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ | |
| 82300 | - /* A sub-query in the FROM clause of a SELECT */ | |
| 82301 | - Select *pSel = pFrom->pSelect; | |
| 82302 | - assert( pSel ); | |
| 82303 | - while( pSel->pPrior ) pSel = pSel->pPrior; | |
| 82304 | - selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel); | |
| 83489 | + if( (p->selFlags & SF_HasTypeInfo)==0 ){ | |
| 83490 | + p->selFlags |= SF_HasTypeInfo; | |
| 83491 | + pParse = pWalker->pParse; | |
| 83492 | + pTabList = p->pSrc; | |
| 83493 | + for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ | |
| 83494 | + Table *pTab = pFrom->pTab; | |
| 83495 | + if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ | |
| 83496 | + /* A sub-query in the FROM clause of a SELECT */ | |
| 83497 | + Select *pSel = pFrom->pSelect; | |
| 83498 | + assert( pSel ); | |
| 83499 | + while( pSel->pPrior ) pSel = pSel->pPrior; | |
| 83500 | + selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel); | |
| 83501 | + } | |
| 82305 | 83502 | } |
| 82306 | 83503 | } |
| 82307 | 83504 | return WRC_Continue; |
| 82308 | 83505 | } |
| 82309 | 83506 | #endif |
| @@ -83571,11 +84768,12 @@ | ||
| 83571 | 84768 | */ |
| 83572 | 84769 | if( !pTableName || db->mallocFailed ){ |
| 83573 | 84770 | goto trigger_cleanup; |
| 83574 | 84771 | } |
| 83575 | 84772 | pTab = sqlite3SrcListLookup(pParse, pTableName); |
| 83576 | - if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ | |
| 84773 | + if( db->init.busy==0 && pName2->n==0 && pTab | |
| 84774 | + && pTab->pSchema==db->aDb[1].pSchema ){ | |
| 83577 | 84775 | iDb = 1; |
| 83578 | 84776 | } |
| 83579 | 84777 | |
| 83580 | 84778 | /* Ensure the table name matches database name and that the table exists */ |
| 83581 | 84779 | if( db->mallocFailed ) goto trigger_cleanup; |
| @@ -83699,16 +84897,16 @@ | ||
| 83699 | 84897 | SQLITE_PRIVATE void sqlite3FinishTrigger( |
| 83700 | 84898 | Parse *pParse, /* Parser context */ |
| 83701 | 84899 | TriggerStep *pStepList, /* The triggered program */ |
| 83702 | 84900 | Token *pAll /* Token that describes the complete CREATE TRIGGER */ |
| 83703 | 84901 | ){ |
| 83704 | - Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ | |
| 83705 | - char *zName; /* Name of trigger */ | |
| 83706 | - sqlite3 *db = pParse->db; /* The database */ | |
| 83707 | - DbFixer sFix; | |
| 83708 | - int iDb; /* Database containing the trigger */ | |
| 83709 | - Token nameToken; /* Trigger name for error reporting */ | |
| 84902 | + Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ | |
| 84903 | + char *zName; /* Name of trigger */ | |
| 84904 | + sqlite3 *db = pParse->db; /* The database */ | |
| 84905 | + DbFixer sFix; /* Fixer object */ | |
| 84906 | + int iDb; /* Database containing the trigger */ | |
| 84907 | + Token nameToken; /* Trigger name for error reporting */ | |
| 83710 | 84908 | |
| 83711 | 84909 | pTrig = pParse->pNewTrigger; |
| 83712 | 84910 | pParse->pNewTrigger = 0; |
| 83713 | 84911 | if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; |
| 83714 | 84912 | zName = pTrig->zName; |
| @@ -83723,11 +84921,11 @@ | ||
| 83723 | 84921 | if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) |
| 83724 | 84922 | && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ |
| 83725 | 84923 | goto triggerfinish_cleanup; |
| 83726 | 84924 | } |
| 83727 | 84925 | |
| 83728 | - /* if we are not initializing, and this trigger is not on a TEMP table, | |
| 84926 | + /* if we are not initializing, | |
| 83729 | 84927 | ** build the sqlite_master entry |
| 83730 | 84928 | */ |
| 83731 | 84929 | if( !db->init.busy ){ |
| 83732 | 84930 | Vdbe *v; |
| 83733 | 84931 | char *z; |
| @@ -85222,47 +86420,61 @@ | ||
| 85222 | 86420 | ** Most of the code in this file may be omitted by defining the |
| 85223 | 86421 | ** SQLITE_OMIT_VACUUM macro. |
| 85224 | 86422 | */ |
| 85225 | 86423 | |
| 85226 | 86424 | #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) |
| 86425 | +/* | |
| 86426 | +** Finalize a prepared statement. If there was an error, store the | |
| 86427 | +** text of the error message in *pzErrMsg. Return the result code. | |
| 86428 | +*/ | |
| 86429 | +static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){ | |
| 86430 | + int rc; | |
| 86431 | + rc = sqlite3VdbeFinalize((Vdbe*)pStmt); | |
| 86432 | + if( rc ){ | |
| 86433 | + sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); | |
| 86434 | + } | |
| 86435 | + return rc; | |
| 86436 | +} | |
| 86437 | + | |
| 85227 | 86438 | /* |
| 85228 | 86439 | ** Execute zSql on database db. Return an error code. |
| 85229 | 86440 | */ |
| 85230 | -static int execSql(sqlite3 *db, const char *zSql){ | |
| 86441 | +static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ | |
| 85231 | 86442 | sqlite3_stmt *pStmt; |
| 85232 | 86443 | VVA_ONLY( int rc; ) |
| 85233 | 86444 | if( !zSql ){ |
| 85234 | 86445 | return SQLITE_NOMEM; |
| 85235 | 86446 | } |
| 85236 | 86447 | if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ |
| 86448 | + sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); | |
| 85237 | 86449 | return sqlite3_errcode(db); |
| 85238 | 86450 | } |
| 85239 | 86451 | VVA_ONLY( rc = ) sqlite3_step(pStmt); |
| 85240 | 86452 | assert( rc!=SQLITE_ROW ); |
| 85241 | - return sqlite3_finalize(pStmt); | |
| 86453 | + return vacuumFinalize(db, pStmt, pzErrMsg); | |
| 85242 | 86454 | } |
| 85243 | 86455 | |
| 85244 | 86456 | /* |
| 85245 | 86457 | ** Execute zSql on database db. The statement returns exactly |
| 85246 | 86458 | ** one column. Execute this as SQL on the same database. |
| 85247 | 86459 | */ |
| 85248 | -static int execExecSql(sqlite3 *db, const char *zSql){ | |
| 86460 | +static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ | |
| 85249 | 86461 | sqlite3_stmt *pStmt; |
| 85250 | 86462 | int rc; |
| 85251 | 86463 | |
| 85252 | 86464 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 85253 | 86465 | if( rc!=SQLITE_OK ) return rc; |
| 85254 | 86466 | |
| 85255 | 86467 | while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 85256 | - rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0)); | |
| 86468 | + rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0)); | |
| 85257 | 86469 | if( rc!=SQLITE_OK ){ |
| 85258 | - sqlite3_finalize(pStmt); | |
| 86470 | + vacuumFinalize(db, pStmt, pzErrMsg); | |
| 85259 | 86471 | return rc; |
| 85260 | 86472 | } |
| 85261 | 86473 | } |
| 85262 | 86474 | |
| 85263 | - return sqlite3_finalize(pStmt); | |
| 86475 | + return vacuumFinalize(db, pStmt, pzErrMsg); | |
| 85264 | 86476 | } |
| 85265 | 86477 | |
| 85266 | 86478 | /* |
| 85267 | 86479 | ** The non-standard VACUUM command is used to clean up the database, |
| 85268 | 86480 | ** collapse free space, etc. It is modelled after the VACUUM command |
| @@ -85308,11 +86520,11 @@ | ||
| 85308 | 86520 | saved_flags = db->flags; |
| 85309 | 86521 | saved_nChange = db->nChange; |
| 85310 | 86522 | saved_nTotalChange = db->nTotalChange; |
| 85311 | 86523 | saved_xTrace = db->xTrace; |
| 85312 | 86524 | db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; |
| 85313 | - db->flags &= ~SQLITE_ForeignKeys; | |
| 86525 | + db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder); | |
| 85314 | 86526 | db->xTrace = 0; |
| 85315 | 86527 | |
| 85316 | 86528 | pMain = db->aDb[0].pBt; |
| 85317 | 86529 | isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); |
| 85318 | 86530 | |
| @@ -85329,11 +86541,11 @@ | ||
| 85329 | 86541 | ** empty. Only the journal header is written. Apparently it takes more |
| 85330 | 86542 | ** time to parse and run the PRAGMA to turn journalling off than it does |
| 85331 | 86543 | ** to write the journal header file. |
| 85332 | 86544 | */ |
| 85333 | 86545 | zSql = "ATTACH '' AS vacuum_db;"; |
| 85334 | - rc = execSql(db, zSql); | |
| 86546 | + rc = execSql(db, pzErrMsg, zSql); | |
| 85335 | 86547 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85336 | 86548 | pDb = &db->aDb[db->nDb-1]; |
| 85337 | 86549 | assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); |
| 85338 | 86550 | pTemp = db->aDb[db->nDb-1].pBt; |
| 85339 | 86551 | |
| @@ -85361,11 +86573,11 @@ | ||
| 85361 | 86573 | || NEVER(db->mallocFailed) |
| 85362 | 86574 | ){ |
| 85363 | 86575 | rc = SQLITE_NOMEM; |
| 85364 | 86576 | goto end_of_vacuum; |
| 85365 | 86577 | } |
| 85366 | - rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); | |
| 86578 | + rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); | |
| 85367 | 86579 | if( rc!=SQLITE_OK ){ |
| 85368 | 86580 | goto end_of_vacuum; |
| 85369 | 86581 | } |
| 85370 | 86582 | |
| 85371 | 86583 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| @@ -85372,53 +86584,52 @@ | ||
| 85372 | 86584 | sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : |
| 85373 | 86585 | sqlite3BtreeGetAutoVacuum(pMain)); |
| 85374 | 86586 | #endif |
| 85375 | 86587 | |
| 85376 | 86588 | /* Begin a transaction */ |
| 85377 | - rc = execSql(db, "BEGIN EXCLUSIVE;"); | |
| 86589 | + rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;"); | |
| 85378 | 86590 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85379 | 86591 | |
| 85380 | 86592 | /* Query the schema of the main database. Create a mirror schema |
| 85381 | 86593 | ** in the temporary database. |
| 85382 | 86594 | */ |
| 85383 | - rc = execExecSql(db, | |
| 86595 | + rc = execExecSql(db, pzErrMsg, | |
| 85384 | 86596 | "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " |
| 85385 | 86597 | " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" |
| 85386 | 86598 | " AND rootpage>0" |
| 85387 | 86599 | ); |
| 85388 | 86600 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85389 | - rc = execExecSql(db, | |
| 86601 | + rc = execExecSql(db, pzErrMsg, | |
| 85390 | 86602 | "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)" |
| 85391 | 86603 | " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "); |
| 85392 | 86604 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85393 | - rc = execExecSql(db, | |
| 86605 | + rc = execExecSql(db, pzErrMsg, | |
| 85394 | 86606 | "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " |
| 85395 | 86607 | " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); |
| 85396 | 86608 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85397 | 86609 | |
| 85398 | 86610 | /* Loop through the tables in the main database. For each, do |
| 85399 | 86611 | ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy |
| 85400 | 86612 | ** the contents to the temporary database. |
| 85401 | 86613 | */ |
| 85402 | - rc = execExecSql(db, | |
| 86614 | + rc = execExecSql(db, pzErrMsg, | |
| 85403 | 86615 | "SELECT 'INSERT INTO vacuum_db.' || quote(name) " |
| 85404 | 86616 | "|| ' SELECT * FROM main.' || quote(name) || ';'" |
| 85405 | 86617 | "FROM main.sqlite_master " |
| 85406 | 86618 | "WHERE type = 'table' AND name!='sqlite_sequence' " |
| 85407 | 86619 | " AND rootpage>0" |
| 85408 | - | |
| 85409 | 86620 | ); |
| 85410 | 86621 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85411 | 86622 | |
| 85412 | 86623 | /* Copy over the sequence table |
| 85413 | 86624 | */ |
| 85414 | - rc = execExecSql(db, | |
| 86625 | + rc = execExecSql(db, pzErrMsg, | |
| 85415 | 86626 | "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " |
| 85416 | 86627 | "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " |
| 85417 | 86628 | ); |
| 85418 | 86629 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85419 | - rc = execExecSql(db, | |
| 86630 | + rc = execExecSql(db, pzErrMsg, | |
| 85420 | 86631 | "SELECT 'INSERT INTO vacuum_db.' || quote(name) " |
| 85421 | 86632 | "|| ' SELECT * FROM main.' || quote(name) || ';' " |
| 85422 | 86633 | "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';" |
| 85423 | 86634 | ); |
| 85424 | 86635 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| @@ -85427,11 +86638,11 @@ | ||
| 85427 | 86638 | /* Copy the triggers, views, and virtual tables from the main database |
| 85428 | 86639 | ** over to the temporary database. None of these objects has any |
| 85429 | 86640 | ** associated storage, so all we have to do is copy their entries |
| 85430 | 86641 | ** from the SQLITE_MASTER table. |
| 85431 | 86642 | */ |
| 85432 | - rc = execSql(db, | |
| 86643 | + rc = execSql(db, pzErrMsg, | |
| 85433 | 86644 | "INSERT INTO vacuum_db.sqlite_master " |
| 85434 | 86645 | " SELECT type, name, tbl_name, rootpage, sql" |
| 85435 | 86646 | " FROM main.sqlite_master" |
| 85436 | 86647 | " WHERE type='view' OR type='trigger'" |
| 85437 | 86648 | " OR (type='table' AND rootpage=0)" |
| @@ -85639,20 +86850,11 @@ | ||
| 85639 | 86850 | |
| 85640 | 86851 | pVTab->nRef--; |
| 85641 | 86852 | if( pVTab->nRef==0 ){ |
| 85642 | 86853 | sqlite3_vtab *p = pVTab->pVtab; |
| 85643 | 86854 | if( p ){ |
| 85644 | -#ifdef SQLITE_DEBUG | |
| 85645 | - if( pVTab->db->magic==SQLITE_MAGIC_BUSY ){ | |
| 85646 | - (void)sqlite3SafetyOff(db); | |
| 85647 | - p->pModule->xDisconnect(p); | |
| 85648 | - (void)sqlite3SafetyOn(db); | |
| 85649 | - } else | |
| 85650 | -#endif | |
| 85651 | - { | |
| 85652 | - p->pModule->xDisconnect(p); | |
| 85653 | - } | |
| 86855 | + p->pModule->xDisconnect(p); | |
| 85654 | 86856 | } |
| 85655 | 86857 | sqlite3DbFree(db, pVTab); |
| 85656 | 86858 | } |
| 85657 | 86859 | } |
| 85658 | 86860 | |
| @@ -85984,13 +87186,11 @@ | ||
| 85984 | 87186 | assert( !db->pVTab ); |
| 85985 | 87187 | assert( xConstruct ); |
| 85986 | 87188 | db->pVTab = pTab; |
| 85987 | 87189 | |
| 85988 | 87190 | /* Invoke the virtual table constructor */ |
| 85989 | - (void)sqlite3SafetyOff(db); | |
| 85990 | 87191 | rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
| 85991 | - (void)sqlite3SafetyOn(db); | |
| 85992 | 87192 | if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 85993 | 87193 | |
| 85994 | 87194 | if( SQLITE_OK!=rc ){ |
| 85995 | 87195 | if( zErr==0 ){ |
| 85996 | 87196 | *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
| @@ -86174,11 +87374,11 @@ | ||
| 86174 | 87374 | sqlite3_mutex_enter(db->mutex); |
| 86175 | 87375 | pTab = db->pVTab; |
| 86176 | 87376 | if( !pTab ){ |
| 86177 | 87377 | sqlite3Error(db, SQLITE_MISUSE, 0); |
| 86178 | 87378 | sqlite3_mutex_leave(db->mutex); |
| 86179 | - return SQLITE_MISUSE; | |
| 87379 | + return SQLITE_MISUSE_BKPT; | |
| 86180 | 87380 | } |
| 86181 | 87381 | assert( (pTab->tabFlags & TF_Virtual)!=0 ); |
| 86182 | 87382 | |
| 86183 | 87383 | pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
| 86184 | 87384 | if( pParse==0 ){ |
| @@ -86233,14 +87433,12 @@ | ||
| 86233 | 87433 | |
| 86234 | 87434 | pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); |
| 86235 | 87435 | if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ |
| 86236 | 87436 | VTable *p = vtabDisconnectAll(db, pTab); |
| 86237 | 87437 | |
| 86238 | - rc = sqlite3SafetyOff(db); | |
| 86239 | 87438 | assert( rc==SQLITE_OK ); |
| 86240 | 87439 | rc = p->pMod->pModule->xDestroy(p->pVtab); |
| 86241 | - (void)sqlite3SafetyOn(db); | |
| 86242 | 87440 | |
| 86243 | 87441 | /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ |
| 86244 | 87442 | if( rc==SQLITE_OK ){ |
| 86245 | 87443 | assert( pTab->pVTable==p && p->pNext==0 ); |
| 86246 | 87444 | p->pVtab = 0; |
| @@ -86288,14 +87486,12 @@ | ||
| 86288 | 87486 | ** sqlite3DbFree() containing an error message, if one is available. |
| 86289 | 87487 | */ |
| 86290 | 87488 | SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){ |
| 86291 | 87489 | int i; |
| 86292 | 87490 | int rc = SQLITE_OK; |
| 86293 | - int rcsafety; | |
| 86294 | 87491 | VTable **aVTrans = db->aVTrans; |
| 86295 | 87492 | |
| 86296 | - rc = sqlite3SafetyOff(db); | |
| 86297 | 87493 | db->aVTrans = 0; |
| 86298 | 87494 | for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){ |
| 86299 | 87495 | int (*x)(sqlite3_vtab *); |
| 86300 | 87496 | sqlite3_vtab *pVtab = aVTrans[i]->pVtab; |
| 86301 | 87497 | if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ |
| @@ -86304,15 +87500,10 @@ | ||
| 86304 | 87500 | *pzErrmsg = pVtab->zErrMsg; |
| 86305 | 87501 | pVtab->zErrMsg = 0; |
| 86306 | 87502 | } |
| 86307 | 87503 | } |
| 86308 | 87504 | db->aVTrans = aVTrans; |
| 86309 | - rcsafety = sqlite3SafetyOn(db); | |
| 86310 | - | |
| 86311 | - if( rc==SQLITE_OK ){ | |
| 86312 | - rc = rcsafety; | |
| 86313 | - } | |
| 86314 | 87505 | return rc; |
| 86315 | 87506 | } |
| 86316 | 87507 | |
| 86317 | 87508 | /* |
| 86318 | 87509 | ** Invoke the xRollback method of all virtual tables in the |
| @@ -87131,11 +88322,11 @@ | ||
| 87131 | 88322 | ** be the name of an indexed column with TEXT affinity. */ |
| 87132 | 88323 | return 0; |
| 87133 | 88324 | } |
| 87134 | 88325 | assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ |
| 87135 | 88326 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 87136 | - assert( pColl!=0 ); /* Every non-IPK column has a collating sequence */ | |
| 88327 | + if( pColl==0 ) return 0; /* Happens when LHS has an undefined collation */ | |
| 87137 | 88328 | if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) && |
| 87138 | 88329 | (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){ |
| 87139 | 88330 | /* IMP: R-09003-32046 For the GLOB operator, the column must use the |
| 87140 | 88331 | ** default BINARY collating sequence. |
| 87141 | 88332 | ** IMP: R-41408-28306 For the LIKE operator, if case_sensitive_like mode |
| @@ -87574,11 +88765,11 @@ | ||
| 87574 | 88765 | WhereTerm *pTerm; /* The term to be analyzed */ |
| 87575 | 88766 | WhereMaskSet *pMaskSet; /* Set of table index masks */ |
| 87576 | 88767 | Expr *pExpr; /* The expression to be analyzed */ |
| 87577 | 88768 | Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ |
| 87578 | 88769 | Bitmask prereqAll; /* Prerequesites of pExpr */ |
| 87579 | - Bitmask extraRight = 0; /* */ | |
| 88770 | + Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ | |
| 87580 | 88771 | Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ |
| 87581 | 88772 | int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ |
| 87582 | 88773 | int noCase = 0; /* LIKE/GLOB distinguishes case */ |
| 87583 | 88774 | int op; /* Top-level operator. pExpr->op */ |
| 87584 | 88775 | Parse *pParse = pWC->pParse; /* Parsing context */ |
| @@ -87646,11 +88837,12 @@ | ||
| 87646 | 88837 | } |
| 87647 | 88838 | exprCommute(pParse, pDup); |
| 87648 | 88839 | pLeft = pDup->pLeft; |
| 87649 | 88840 | pNew->leftCursor = pLeft->iTable; |
| 87650 | 88841 | pNew->u.leftColumn = pLeft->iColumn; |
| 87651 | - pNew->prereqRight = prereqLeft; | |
| 88842 | + testcase( (prereqLeft | extraRight) != prereqLeft ); | |
| 88843 | + pNew->prereqRight = prereqLeft | extraRight; | |
| 87652 | 88844 | pNew->prereqAll = prereqAll; |
| 87653 | 88845 | pNew->eOperator = operatorMask(pDup->op); |
| 87654 | 88846 | } |
| 87655 | 88847 | } |
| 87656 | 88848 | |
| @@ -88236,16 +89428,14 @@ | ||
| 88236 | 89428 | static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ |
| 88237 | 89429 | sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; |
| 88238 | 89430 | int i; |
| 88239 | 89431 | int rc; |
| 88240 | 89432 | |
| 88241 | - (void)sqlite3SafetyOff(pParse->db); | |
| 88242 | 89433 | WHERETRACE(("xBestIndex for %s\n", pTab->zName)); |
| 88243 | 89434 | TRACE_IDX_INPUTS(p); |
| 88244 | 89435 | rc = pVtab->pModule->xBestIndex(pVtab, p); |
| 88245 | 89436 | TRACE_IDX_OUTPUTS(p); |
| 88246 | - (void)sqlite3SafetyOn(pParse->db); | |
| 88247 | 89437 | |
| 88248 | 89438 | if( rc!=SQLITE_OK ){ |
| 88249 | 89439 | if( rc==SQLITE_NOMEM ){ |
| 88250 | 89440 | pParse->db->mallocFailed = 1; |
| 88251 | 89441 | }else if( !pVtab->zErrMsg ){ |
| @@ -90871,11 +92061,11 @@ | ||
| 90871 | 92061 | ** shifting terminals. |
| 90872 | 92062 | ** yy_reduce_ofst[] For each state, the offset into yy_action for |
| 90873 | 92063 | ** shifting non-terminals after a reduce. |
| 90874 | 92064 | ** yy_default[] Default action for each state. |
| 90875 | 92065 | */ |
| 90876 | -#define YY_ACTTAB_COUNT (1543) | |
| 92066 | +#define YY_ACTTAB_COUNT (1550) | |
| 90877 | 92067 | static const YYACTIONTYPE yy_action[] = { |
| 90878 | 92068 | /* 0 */ 313, 49, 556, 46, 147, 172, 628, 598, 55, 55, |
| 90879 | 92069 | /* 10 */ 55, 55, 302, 53, 53, 53, 53, 52, 52, 51, |
| 90880 | 92070 | /* 20 */ 51, 51, 50, 238, 603, 66, 624, 623, 604, 598, |
| 90881 | 92071 | /* 30 */ 591, 585, 48, 53, 53, 53, 53, 52, 52, 51, |
| @@ -91021,17 +92211,17 @@ | ||
| 91021 | 92211 | /* 1430 */ 602, 81, 411, 514, 414, 512, 131, 602, 70, 229, |
| 91022 | 92212 | /* 1440 */ 228, 227, 494, 602, 17, 411, 488, 414, 259, 346, |
| 91023 | 92213 | /* 1450 */ 249, 389, 487, 486, 314, 164, 602, 79, 310, 240, |
| 91024 | 92214 | /* 1460 */ 414, 373, 480, 163, 262, 371, 414, 162, 369, 602, |
| 91025 | 92215 | /* 1470 */ 78, 212, 478, 26, 477, 602, 9, 161, 467, 363, |
| 91026 | - /* 1480 */ 141, 122, 339, 187, 119, 457, 348, 117, 347, 116, | |
| 91027 | - /* 1490 */ 115, 114, 448, 112, 182, 320, 22, 433, 19, 432, | |
| 91028 | - /* 1500 */ 431, 63, 428, 610, 193, 298, 597, 574, 572, 404, | |
| 91029 | - /* 1510 */ 555, 552, 290, 281, 510, 499, 498, 497, 495, 380, | |
| 91030 | - /* 1520 */ 356, 460, 256, 250, 345, 447, 306, 5, 570, 550, | |
| 91031 | - /* 1530 */ 299, 211, 370, 401, 550, 508, 502, 501, 490, 527, | |
| 91032 | - /* 1540 */ 525, 483, 238, | |
| 92216 | + /* 1480 */ 141, 122, 339, 187, 119, 457, 348, 347, 117, 116, | |
| 92217 | + /* 1490 */ 115, 112, 114, 448, 182, 22, 320, 433, 432, 431, | |
| 92218 | + /* 1500 */ 19, 428, 610, 597, 574, 193, 572, 63, 298, 404, | |
| 92219 | + /* 1510 */ 555, 552, 290, 281, 510, 460, 498, 499, 495, 447, | |
| 92220 | + /* 1520 */ 356, 497, 256, 380, 306, 570, 5, 250, 345, 238, | |
| 92221 | + /* 1530 */ 299, 550, 527, 490, 508, 525, 502, 401, 501, 963, | |
| 92222 | + /* 1540 */ 211, 963, 483, 963, 963, 963, 963, 963, 963, 370, | |
| 91033 | 92223 | }; |
| 91034 | 92224 | static const YYCODETYPE yy_lookahead[] = { |
| 91035 | 92225 | /* 0 */ 19, 222, 223, 224, 225, 24, 1, 26, 77, 78, |
| 91036 | 92226 | /* 10 */ 79, 80, 15, 82, 83, 84, 85, 86, 87, 88, |
| 91037 | 92227 | /* 20 */ 89, 90, 91, 92, 113, 22, 26, 27, 117, 26, |
| @@ -91178,22 +92368,22 @@ | ||
| 91178 | 92368 | /* 1430 */ 174, 175, 150, 178, 165, 176, 22, 174, 175, 230, |
| 91179 | 92369 | /* 1440 */ 92, 230, 184, 174, 175, 150, 176, 165, 105, 106, |
| 91180 | 92370 | /* 1450 */ 107, 150, 176, 176, 111, 156, 174, 175, 179, 116, |
| 91181 | 92371 | /* 1460 */ 165, 18, 157, 156, 238, 157, 165, 156, 45, 174, |
| 91182 | 92372 | /* 1470 */ 175, 157, 157, 135, 239, 174, 175, 156, 189, 157, |
| 91183 | - /* 1480 */ 68, 189, 139, 219, 22, 199, 157, 192, 18, 192, | |
| 91184 | - /* 1490 */ 192, 192, 199, 189, 219, 157, 243, 40, 243, 157, | |
| 91185 | - /* 1500 */ 157, 246, 38, 153, 196, 198, 166, 233, 233, 228, | |
| 91186 | - /* 1510 */ 177, 177, 209, 177, 182, 177, 166, 177, 166, 178, | |
| 91187 | - /* 1520 */ 242, 199, 242, 209, 209, 199, 148, 196, 166, 208, | |
| 91188 | - /* 1530 */ 195, 236, 237, 191, 208, 183, 183, 183, 186, 174, | |
| 91189 | - /* 1540 */ 174, 186, 92, | |
| 92373 | + /* 1480 */ 68, 189, 139, 219, 22, 199, 157, 18, 192, 192, | |
| 92374 | + /* 1490 */ 192, 189, 192, 199, 219, 243, 157, 40, 157, 157, | |
| 92375 | + /* 1500 */ 243, 38, 153, 166, 233, 196, 233, 246, 198, 228, | |
| 92376 | + /* 1510 */ 177, 177, 209, 177, 182, 199, 166, 177, 166, 199, | |
| 92377 | + /* 1520 */ 242, 177, 242, 178, 148, 166, 196, 209, 209, 92, | |
| 92378 | + /* 1530 */ 195, 208, 174, 186, 183, 174, 183, 191, 183, 253, | |
| 92379 | + /* 1540 */ 236, 253, 186, 253, 253, 253, 253, 253, 253, 237, | |
| 91190 | 92380 | }; |
| 91191 | 92381 | #define YY_SHIFT_USE_DFLT (-90) |
| 91192 | 92382 | #define YY_SHIFT_COUNT (418) |
| 91193 | 92383 | #define YY_SHIFT_MIN (-89) |
| 91194 | -#define YY_SHIFT_MAX (1470) | |
| 92384 | +#define YY_SHIFT_MAX (1469) | |
| 91195 | 92385 | static const short yy_shift_ofst[] = { |
| 91196 | 92386 | /* 0 */ 993, 1114, 1343, 1114, 1213, 1213, 90, 90, 0, -19, |
| 91197 | 92387 | /* 10 */ 1213, 1213, 1213, 1213, 1213, 352, 517, 721, 1091, 1213, |
| 91198 | 92388 | /* 20 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, |
| 91199 | 92389 | /* 30 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, |
| @@ -91204,11 +92394,11 @@ | ||
| 91204 | 92394 | /* 80 */ 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, |
| 91205 | 92395 | /* 90 */ 795, 795, 795, 795, 795, 795, 869, 795, 943, 1017, |
| 91206 | 92396 | /* 100 */ 1017, -69, -69, -69, -69, -1, -1, 58, 138, -44, |
| 91207 | 92397 | /* 110 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91208 | 92398 | /* 120 */ 517, 517, 517, 517, 517, 517, 202, 579, 517, 517, |
| 91209 | - /* 130 */ 517, 517, 517, 382, 885, 1450, -90, -90, -90, 1293, | |
| 92399 | + /* 130 */ 517, 517, 517, 382, 885, 1437, -90, -90, -90, 1293, | |
| 91210 | 92400 | /* 140 */ 73, 272, 272, 309, 311, 297, 282, 216, 602, 538, |
| 91211 | 92401 | /* 150 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91212 | 92402 | /* 160 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91213 | 92403 | /* 170 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91214 | 92404 | /* 180 */ 517, 517, 505, 231, 231, 231, 706, 64, 1177, 1177, |
| @@ -91215,12 +92405,12 @@ | ||
| 91215 | 92405 | /* 190 */ 1177, -90, -90, -90, 136, 168, 168, 12, 496, 496, |
| 91216 | 92406 | /* 200 */ 496, 506, 423, 512, 370, 349, 335, 149, 149, 149, |
| 91217 | 92407 | /* 210 */ 149, 604, 516, 149, 149, 508, 3, 299, 677, 871, |
| 91218 | 92408 | /* 220 */ 613, 613, 879, 871, 879, 144, 382, 226, 382, 226, |
| 91219 | 92409 | /* 230 */ 564, 226, 613, 226, 226, 404, 625, 625, 382, 426, |
| 91220 | - /* 240 */ -89, 801, 1464, 1244, 1244, 1457, 1457, 1244, 1462, 1412, | |
| 91221 | - /* 250 */ 1188, 1470, 1470, 1470, 1470, 1244, 1188, 1462, 1412, 1412, | |
| 92410 | + /* 240 */ -89, 801, 1463, 1244, 1244, 1457, 1457, 1244, 1462, 1412, | |
| 92411 | + /* 250 */ 1188, 1469, 1469, 1469, 1469, 1244, 1188, 1462, 1412, 1412, | |
| 91222 | 92412 | /* 260 */ 1244, 1443, 1338, 1423, 1244, 1244, 1443, 1244, 1443, 1244, |
| 91223 | 92413 | /* 270 */ 1443, 1414, 1306, 1306, 1306, 1365, 1348, 1348, 1414, 1306, |
| 91224 | 92414 | /* 280 */ 1317, 1306, 1365, 1306, 1306, 1267, 1268, 1267, 1268, 1267, |
| 91225 | 92415 | /* 290 */ 1268, 1244, 1244, 1216, 1214, 1215, 1192, 1173, 1188, 1177, |
| 91226 | 92416 | /* 300 */ 1260, 1253, 1253, 1248, 1248, 1248, 1248, -90, -90, -90, |
| @@ -91237,11 +92427,11 @@ | ||
| 91237 | 92427 | /* 410 */ 152, 123, 68, -20, -42, 57, 39, -3, 5, |
| 91238 | 92428 | }; |
| 91239 | 92429 | #define YY_REDUCE_USE_DFLT (-222) |
| 91240 | 92430 | #define YY_REDUCE_COUNT (312) |
| 91241 | 92431 | #define YY_REDUCE_MIN (-221) |
| 91242 | -#define YY_REDUCE_MAX (1378) | |
| 92432 | +#define YY_REDUCE_MAX (1376) | |
| 91243 | 92433 | static const short yy_reduce_ofst[] = { |
| 91244 | 92434 | /* 0 */ 310, 994, 1134, 221, 169, 157, 89, 18, 83, 301, |
| 91245 | 92435 | /* 10 */ 377, 316, 312, 16, 295, 238, 249, 391, 1301, 1295, |
| 91246 | 92436 | /* 20 */ 1282, 1269, 1263, 1256, 1251, 1240, 1234, 1228, 1221, 1208, |
| 91247 | 92437 | /* 30 */ 1109, 1103, 1077, 1054, 1022, 1016, 911, 908, 890, 888, |
| @@ -91258,17 +92448,17 @@ | ||
| 91258 | 92448 | /* 140 */ 823, 738, 712, 892, 1199, 1185, 1176, 1171, 673, 673, |
| 91259 | 92449 | /* 150 */ 1168, 1167, 1162, 1159, 1148, 1145, 1139, 1117, 1111, 1107, |
| 91260 | 92450 | /* 160 */ 1084, 1066, 1049, 1011, 1010, 1006, 1002, 999, 998, 973, |
| 91261 | 92451 | /* 170 */ 972, 970, 966, 964, 895, 894, 892, 833, 822, 762, |
| 91262 | 92452 | /* 180 */ 761, 229, 811, 804, 803, 389, 688, 808, 807, 737, |
| 91263 | - /* 190 */ 460, 464, 572, 584, 1355, 1366, 1365, 1352, 1354, 1353, | |
| 91264 | - /* 200 */ 1352, 1326, 1335, 1342, 1335, 1335, 1335, 1335, 1335, 1335, | |
| 91265 | - /* 210 */ 1335, 1295, 1295, 1335, 1335, 1321, 1362, 1331, 1378, 1326, | |
| 91266 | - /* 220 */ 1315, 1314, 1280, 1322, 1278, 1341, 1352, 1340, 1350, 1338, | |
| 91267 | - /* 230 */ 1332, 1336, 1303, 1334, 1333, 1281, 1275, 1274, 1340, 1307, | |
| 91268 | - /* 240 */ 1308, 1350, 1255, 1343, 1342, 1255, 1253, 1338, 1275, 1304, | |
| 91269 | - /* 250 */ 1293, 1299, 1298, 1297, 1295, 1329, 1286, 1264, 1292, 1289, | |
| 92453 | + /* 190 */ 460, 464, 572, 584, 1356, 1361, 1358, 1347, 1355, 1353, | |
| 92454 | + /* 200 */ 1351, 1323, 1335, 1346, 1335, 1335, 1335, 1335, 1335, 1335, | |
| 92455 | + /* 210 */ 1335, 1312, 1304, 1335, 1335, 1323, 1359, 1330, 1376, 1320, | |
| 92456 | + /* 220 */ 1319, 1318, 1280, 1316, 1278, 1345, 1352, 1344, 1350, 1340, | |
| 92457 | + /* 230 */ 1332, 1336, 1303, 1334, 1333, 1281, 1273, 1271, 1337, 1310, | |
| 92458 | + /* 240 */ 1309, 1349, 1261, 1342, 1341, 1257, 1252, 1339, 1275, 1302, | |
| 92459 | + /* 250 */ 1294, 1300, 1298, 1297, 1296, 1329, 1286, 1264, 1292, 1289, | |
| 91270 | 92460 | /* 260 */ 1322, 1321, 1235, 1226, 1315, 1314, 1311, 1308, 1307, 1305, |
| 91271 | 92461 | /* 270 */ 1299, 1279, 1277, 1276, 1270, 1258, 1211, 1209, 1250, 1259, |
| 91272 | 92462 | /* 280 */ 1255, 1242, 1243, 1241, 1201, 1200, 1184, 1186, 1182, 1178, |
| 91273 | 92463 | /* 290 */ 1165, 1206, 1204, 1113, 1135, 1095, 1124, 1105, 1102, 1096, |
| 91274 | 92464 | /* 300 */ 1112, 1140, 1136, 1121, 1116, 1115, 1089, 985, 961, 987, |
| @@ -94758,10 +95948,11 @@ | ||
| 94758 | 95948 | sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc)); |
| 94759 | 95949 | } |
| 94760 | 95950 | assert( pzErrMsg!=0 ); |
| 94761 | 95951 | if( pParse->zErrMsg ){ |
| 94762 | 95952 | *pzErrMsg = pParse->zErrMsg; |
| 95953 | + sqlite3_log(pParse->rc, "%s", *pzErrMsg); | |
| 94763 | 95954 | pParse->zErrMsg = 0; |
| 94764 | 95955 | nErr++; |
| 94765 | 95956 | } |
| 94766 | 95957 | if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ |
| 94767 | 95958 | sqlite3VdbeDelete(pParse->pVdbe); |
| @@ -95436,11 +96627,11 @@ | ||
| 95436 | 96627 | va_list ap; |
| 95437 | 96628 | int rc = SQLITE_OK; |
| 95438 | 96629 | |
| 95439 | 96630 | /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while |
| 95440 | 96631 | ** the SQLite library is in use. */ |
| 95441 | - if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE; | |
| 96632 | + if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT; | |
| 95442 | 96633 | |
| 95443 | 96634 | va_start(ap, op); |
| 95444 | 96635 | switch( op ){ |
| 95445 | 96636 | |
| 95446 | 96637 | /* Mutex configuration options are only available in a threadsafe |
| @@ -95557,10 +96748,25 @@ | ||
| 95557 | 96748 | case SQLITE_CONFIG_LOOKASIDE: { |
| 95558 | 96749 | sqlite3GlobalConfig.szLookaside = va_arg(ap, int); |
| 95559 | 96750 | sqlite3GlobalConfig.nLookaside = va_arg(ap, int); |
| 95560 | 96751 | break; |
| 95561 | 96752 | } |
| 96753 | + | |
| 96754 | + /* Record a pointer to the logger funcction and its first argument. | |
| 96755 | + ** The default is NULL. Logging is disabled if the function pointer is | |
| 96756 | + ** NULL. | |
| 96757 | + */ | |
| 96758 | + case SQLITE_CONFIG_LOG: { | |
| 96759 | + /* MSVC is picky about pulling func ptrs from va lists. | |
| 96760 | + ** http://support.microsoft.com/kb/47961 | |
| 96761 | + ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*)); | |
| 96762 | + */ | |
| 96763 | + typedef void(*LOGFUNC_t)(void*,int,const char*); | |
| 96764 | + sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t); | |
| 96765 | + sqlite3GlobalConfig.pLogArg = va_arg(ap, void*); | |
| 96766 | + break; | |
| 96767 | + } | |
| 95562 | 96768 | |
| 95563 | 96769 | default: { |
| 95564 | 96770 | rc = SQLITE_ERROR; |
| 95565 | 96771 | break; |
| 95566 | 96772 | } |
| @@ -95770,11 +96976,11 @@ | ||
| 95770 | 96976 | |
| 95771 | 96977 | if( !db ){ |
| 95772 | 96978 | return SQLITE_OK; |
| 95773 | 96979 | } |
| 95774 | 96980 | if( !sqlite3SafetyCheckSickOrOk(db) ){ |
| 95775 | - return SQLITE_MISUSE; | |
| 96981 | + return SQLITE_MISUSE_BKPT; | |
| 95776 | 96982 | } |
| 95777 | 96983 | sqlite3_mutex_enter(db->mutex); |
| 95778 | 96984 | |
| 95779 | 96985 | sqlite3ResetInternalSchema(db, 0); |
| 95780 | 96986 | |
| @@ -96117,11 +97323,11 @@ | ||
| 96117 | 97323 | (xFunc && (xFinal || xStep)) || |
| 96118 | 97324 | (!xFunc && (xFinal && !xStep)) || |
| 96119 | 97325 | (!xFunc && (!xFinal && xStep)) || |
| 96120 | 97326 | (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || |
| 96121 | 97327 | (255<(nName = sqlite3Strlen30( zFunctionName))) ){ |
| 96122 | - return SQLITE_MISUSE; | |
| 97328 | + return SQLITE_MISUSE_BKPT; | |
| 96123 | 97329 | } |
| 96124 | 97330 | |
| 96125 | 97331 | #ifndef SQLITE_OMIT_UTF16 |
| 96126 | 97332 | /* If SQLITE_UTF16 is specified as the encoding type, transform this |
| 96127 | 97333 | ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the |
| @@ -96448,11 +97654,11 @@ | ||
| 96448 | 97654 | const char *z; |
| 96449 | 97655 | if( !db ){ |
| 96450 | 97656 | return sqlite3ErrStr(SQLITE_NOMEM); |
| 96451 | 97657 | } |
| 96452 | 97658 | if( !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96453 | - return sqlite3ErrStr(SQLITE_MISUSE); | |
| 97659 | + return sqlite3ErrStr(SQLITE_MISUSE_BKPT); | |
| 96454 | 97660 | } |
| 96455 | 97661 | sqlite3_mutex_enter(db->mutex); |
| 96456 | 97662 | if( db->mallocFailed ){ |
| 96457 | 97663 | z = sqlite3ErrStr(SQLITE_NOMEM); |
| 96458 | 97664 | }else{ |
| @@ -96517,20 +97723,20 @@ | ||
| 96517 | 97723 | ** Return the most recent error code generated by an SQLite routine. If NULL is |
| 96518 | 97724 | ** passed to this function, we assume a malloc() failed during sqlite3_open(). |
| 96519 | 97725 | */ |
| 96520 | 97726 | SQLITE_API int sqlite3_errcode(sqlite3 *db){ |
| 96521 | 97727 | if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96522 | - return SQLITE_MISUSE; | |
| 97728 | + return SQLITE_MISUSE_BKPT; | |
| 96523 | 97729 | } |
| 96524 | 97730 | if( !db || db->mallocFailed ){ |
| 96525 | 97731 | return SQLITE_NOMEM; |
| 96526 | 97732 | } |
| 96527 | 97733 | return db->errCode & db->errMask; |
| 96528 | 97734 | } |
| 96529 | 97735 | SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ |
| 96530 | 97736 | if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96531 | - return SQLITE_MISUSE; | |
| 97737 | + return SQLITE_MISUSE_BKPT; | |
| 96532 | 97738 | } |
| 96533 | 97739 | if( !db || db->mallocFailed ){ |
| 96534 | 97740 | return SQLITE_NOMEM; |
| 96535 | 97741 | } |
| 96536 | 97742 | return db->errCode; |
| @@ -96564,11 +97770,11 @@ | ||
| 96564 | 97770 | testcase( enc2==SQLITE_UTF16_ALIGNED ); |
| 96565 | 97771 | if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){ |
| 96566 | 97772 | enc2 = SQLITE_UTF16NATIVE; |
| 96567 | 97773 | } |
| 96568 | 97774 | if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){ |
| 96569 | - return SQLITE_MISUSE; | |
| 97775 | + return SQLITE_MISUSE_BKPT; | |
| 96570 | 97776 | } |
| 96571 | 97777 | |
| 96572 | 97778 | /* Check if this call is removing or replacing an existing collation |
| 96573 | 97779 | ** sequence. If so, and there are active VMs, return busy. If there |
| 96574 | 97780 | ** are no active VMs, invalidate any pre-compiled statements. |
| @@ -97108,20 +98314,38 @@ | ||
| 97108 | 98314 | */ |
| 97109 | 98315 | SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ |
| 97110 | 98316 | return db->autoCommit; |
| 97111 | 98317 | } |
| 97112 | 98318 | |
| 97113 | -#ifdef SQLITE_DEBUG | |
| 97114 | 98319 | /* |
| 97115 | -** The following routine is subtituted for constant SQLITE_CORRUPT in | |
| 97116 | -** debugging builds. This provides a way to set a breakpoint for when | |
| 97117 | -** corruption is first detected. | |
| 98320 | +** The following routines are subtitutes for constants SQLITE_CORRUPT, | |
| 98321 | +** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error | |
| 98322 | +** constants. They server two purposes: | |
| 98323 | +** | |
| 98324 | +** 1. Serve as a convenient place to set a breakpoint in a debugger | |
| 98325 | +** to detect when version error conditions occurs. | |
| 98326 | +** | |
| 98327 | +** 2. Invoke sqlite3_log() to provide the source code location where | |
| 98328 | +** a low-level error is first detected. | |
| 97118 | 98329 | */ |
| 97119 | -SQLITE_PRIVATE int sqlite3Corrupt(void){ | |
| 98330 | +SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ | |
| 98331 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 98332 | + sqlite3_log(SQLITE_CORRUPT, | |
| 98333 | + "database corruption found by source line %d", lineno); | |
| 97120 | 98334 | return SQLITE_CORRUPT; |
| 97121 | 98335 | } |
| 97122 | -#endif | |
| 98336 | +SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ | |
| 98337 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 98338 | + sqlite3_log(SQLITE_MISUSE, "misuse detected by source line %d", lineno); | |
| 98339 | + return SQLITE_MISUSE; | |
| 98340 | +} | |
| 98341 | +SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ | |
| 98342 | + testcase( sqlite3GlobalConfig.xLog!=0 ); | |
| 98343 | + sqlite3_log(SQLITE_CANTOPEN, "cannot open file at source line %d", lineno); | |
| 98344 | + return SQLITE_CANTOPEN; | |
| 98345 | +} | |
| 98346 | + | |
| 97123 | 98347 | |
| 97124 | 98348 | #ifndef SQLITE_OMIT_DEPRECATED |
| 97125 | 98349 | /* |
| 97126 | 98350 | ** This is a convenience routine that makes sure that all thread-specific |
| 97127 | 98351 | ** data for this thread has been deallocated. |
| @@ -97161,11 +98385,10 @@ | ||
| 97161 | 98385 | int primarykey = 0; |
| 97162 | 98386 | int autoinc = 0; |
| 97163 | 98387 | |
| 97164 | 98388 | /* Ensure the database schema has been loaded */ |
| 97165 | 98389 | sqlite3_mutex_enter(db->mutex); |
| 97166 | - (void)sqlite3SafetyOn(db); | |
| 97167 | 98390 | sqlite3BtreeEnterAll(db); |
| 97168 | 98391 | rc = sqlite3Init(db, &zErrMsg); |
| 97169 | 98392 | if( SQLITE_OK!=rc ){ |
| 97170 | 98393 | goto error_out; |
| 97171 | 98394 | } |
| @@ -97220,11 +98443,10 @@ | ||
| 97220 | 98443 | zCollSeq = "BINARY"; |
| 97221 | 98444 | } |
| 97222 | 98445 | |
| 97223 | 98446 | error_out: |
| 97224 | 98447 | sqlite3BtreeLeaveAll(db); |
| 97225 | - (void)sqlite3SafetyOff(db); | |
| 97226 | 98448 | |
| 97227 | 98449 | /* Whether the function call succeeded or failed, set the output parameters |
| 97228 | 98450 | ** to whatever their local counterparts contain. If an error did occur, |
| 97229 | 98451 | ** this has the effect of zeroing all output parameters. |
| 97230 | 98452 | */ |
| @@ -97859,13 +99081,10 @@ | ||
| 97859 | 99081 | ** |
| 97860 | 99082 | ** * The FTS3 module is being built into the core of |
| 97861 | 99083 | ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). |
| 97862 | 99084 | */ |
| 97863 | 99085 | |
| 97864 | -/* TODO(shess) Consider exporting this comment to an HTML file or the | |
| 97865 | -** wiki. | |
| 97866 | -*/ | |
| 97867 | 99086 | /* The full-text index is stored in a series of b+tree (-like) |
| 97868 | 99087 | ** structures called segments which map terms to doclists. The |
| 97869 | 99088 | ** structures are like b+trees in layout, but are constructed from the |
| 97870 | 99089 | ** bottom up in optimal fashion and are not updatable. Since trees |
| 97871 | 99090 | ** are built from the bottom up, things will be described from the |
| @@ -97884,45 +99103,68 @@ | ||
| 97884 | 99103 | ** 7 bits - A |
| 97885 | 99104 | ** 14 bits - BA |
| 97886 | 99105 | ** 21 bits - BBA |
| 97887 | 99106 | ** and so on. |
| 97888 | 99107 | ** |
| 97889 | -** This is identical to how sqlite encodes varints (see util.c). | |
| 99108 | +** This is similar in concept to how sqlite encodes "varints" but | |
| 99109 | +** the encoding is not the same. SQLite varints are big-endian | |
| 99110 | +** are are limited to 9 bytes in length whereas FTS3 varints are | |
| 99111 | +** little-endian and can be upt to 10 bytes in length (in theory). | |
| 99112 | +** | |
| 99113 | +** Example encodings: | |
| 99114 | +** | |
| 99115 | +** 1: 0x01 | |
| 99116 | +** 127: 0x7f | |
| 99117 | +** 128: 0x81 0x00 | |
| 97890 | 99118 | ** |
| 97891 | 99119 | ** |
| 97892 | 99120 | **** Document lists **** |
| 97893 | 99121 | ** A doclist (document list) holds a docid-sorted list of hits for a |
| 97894 | 99122 | ** given term. Doclists hold docids, and can optionally associate |
| 97895 | -** token positions and offsets with docids. | |
| 99123 | +** token positions and offsets with docids. A position is the index | |
| 99124 | +** of a word within the document. The first word of the document has | |
| 99125 | +** a position of 0. | |
| 99126 | +** | |
| 99127 | +** FTS3 used to optionally store character offsets using a compile-time | |
| 99128 | +** option. But that functionality is no longer supported. | |
| 97896 | 99129 | ** |
| 97897 | 99130 | ** A DL_POSITIONS_OFFSETS doclist is stored like this: |
| 97898 | 99131 | ** |
| 97899 | 99132 | ** array { |
| 97900 | 99133 | ** varint docid; |
| 97901 | 99134 | ** array { (position list for column 0) |
| 97902 | 99135 | ** varint position; (delta from previous position plus POS_BASE) |
| 97903 | -** varint startOffset; (delta from previous startOffset) | |
| 97904 | -** varint endOffset; (delta from startOffset) | |
| 97905 | 99136 | ** } |
| 97906 | 99137 | ** array { |
| 97907 | 99138 | ** varint POS_COLUMN; (marks start of position list for new column) |
| 97908 | 99139 | ** varint column; (index of new column) |
| 97909 | 99140 | ** array { |
| 97910 | 99141 | ** varint position; (delta from previous position plus POS_BASE) |
| 97911 | -** varint startOffset;(delta from previous startOffset) | |
| 97912 | -** varint endOffset; (delta from startOffset) | |
| 97913 | 99142 | ** } |
| 97914 | 99143 | ** } |
| 97915 | 99144 | ** varint POS_END; (marks end of positions for this document. |
| 97916 | 99145 | ** } |
| 97917 | 99146 | ** |
| 97918 | 99147 | ** Here, array { X } means zero or more occurrences of X, adjacent in |
| 97919 | 99148 | ** memory. A "position" is an index of a token in the token stream |
| 97920 | -** generated by the tokenizer, while an "offset" is a byte offset, | |
| 97921 | -** both based at 0. Note that POS_END and POS_COLUMN occur in the | |
| 97922 | -** same logical place as the position element, and act as sentinals | |
| 97923 | -** ending a position list array. | |
| 99149 | +** generated by the tokenizer. Note that POS_END and POS_COLUMN occur | |
| 99150 | +** in the same logical place as the position element, and act as sentinals | |
| 99151 | +** ending a position list array. POS_END is 0. POS_COLUMN is 1. | |
| 99152 | +** The positions numbers are not stored literally but rather as two more | |
| 99153 | +** the difference from the prior position, or the just the position plus | |
| 99154 | +** 2 for the first position. Example: | |
| 99155 | +** | |
| 99156 | +** label: A B C D E F G H I J K | |
| 99157 | +** value: 123 5 9 1 1 14 35 0 234 72 0 | |
| 99158 | +** | |
| 99159 | +** The 123 value is the first docid. For column zero in this document | |
| 99160 | +** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1 | |
| 99161 | +** at D signals the start of a new column; the 1 at E indicates that the | |
| 99162 | +** new column is column number 1. There are two positions at 12 and 45 | |
| 99163 | +** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The | |
| 99164 | +** 234 at I is the next docid. It has one position 72 (72-2) and then | |
| 99165 | +** terminates with the 0 at K. | |
| 97924 | 99166 | ** |
| 97925 | 99167 | ** A DL_POSITIONS doclist omits the startOffset and endOffset |
| 97926 | 99168 | ** information. A DL_DOCIDS doclist omits both the position and |
| 97927 | 99169 | ** offset information, becoming an array of varint-encoded docids. |
| 97928 | 99170 | ** |
| @@ -98492,11 +99734,11 @@ | ||
| 98492 | 99734 | sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ |
| 98493 | 99735 | |
| 98494 | 99736 | /* Precompiled statements used by the implementation. Each of these |
| 98495 | 99737 | ** statements is run and reset within a single virtual table API call. |
| 98496 | 99738 | */ |
| 98497 | - sqlite3_stmt *aStmt[18]; | |
| 99739 | + sqlite3_stmt *aStmt[25]; | |
| 98498 | 99740 | |
| 98499 | 99741 | /* Pointer to string containing the SQL: |
| 98500 | 99742 | ** |
| 98501 | 99743 | ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ? |
| 98502 | 99744 | ** ORDER BY blockid" |
| @@ -98506,10 +99748,12 @@ | ||
| 98506 | 99748 | int nLeavesTotal; /* Total number of prepared leaves stmts */ |
| 98507 | 99749 | int nLeavesAlloc; /* Allocated size of aLeavesStmt */ |
| 98508 | 99750 | sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */ |
| 98509 | 99751 | |
| 98510 | 99752 | int nNodeSize; /* Soft limit for node size */ |
| 99753 | + u8 bHasContent; /* True if %_content table exists */ | |
| 99754 | + u8 bHasDocsize; /* True if %_docsize table exists */ | |
| 98511 | 99755 | |
| 98512 | 99756 | /* The following hash table is used to buffer pending index updates during |
| 98513 | 99757 | ** transactions. Variable nPendingData estimates the memory size of the |
| 98514 | 99758 | ** pending data, including hash table overhead, but not malloc overhead. |
| 98515 | 99759 | ** When nPendingData exceeds nMaxPendingData, the buffer is flushed |
| @@ -98536,12 +99780,12 @@ | ||
| 98536 | 99780 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 98537 | 99781 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 98538 | 99782 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 98539 | 99783 | char *aDoclist; /* List of docids for full-text queries */ |
| 98540 | 99784 | int nDoclist; /* Size of buffer at aDoclist */ |
| 98541 | - int isMatchinfoOk; /* True when aMatchinfo[] matches iPrevId */ | |
| 98542 | - u32 *aMatchinfo; | |
| 99785 | + int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ | |
| 99786 | + u32 *aMatchinfo; /* Information about most recent match */ | |
| 98543 | 99787 | }; |
| 98544 | 99788 | |
| 98545 | 99789 | /* |
| 98546 | 99790 | ** The Fts3Cursor.eSearch member is always set to one of the following. |
| 98547 | 99791 | ** Actualy, Fts3Cursor.eSearch can be greater than or equal to |
| @@ -98643,10 +99887,12 @@ | ||
| 98643 | 99887 | Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, |
| 98644 | 99888 | int (*)(Fts3Table *, void *, char *, int, char *, int), void * |
| 98645 | 99889 | ); |
| 98646 | 99890 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); |
| 98647 | 99891 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
| 99892 | +SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*); | |
| 99893 | +SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*); | |
| 98648 | 99894 | |
| 98649 | 99895 | /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ |
| 98650 | 99896 | #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 |
| 98651 | 99897 | #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 |
| 98652 | 99898 | #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 |
| @@ -98667,10 +99913,11 @@ | ||
| 98667 | 99913 | SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); |
| 98668 | 99914 | SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); |
| 98669 | 99915 | |
| 98670 | 99916 | SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int); |
| 98671 | 99917 | SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *, Fts3Expr *); |
| 99918 | +SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int); | |
| 98672 | 99919 | |
| 98673 | 99920 | /* fts3_tokenizer.c */ |
| 98674 | 99921 | SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); |
| 98675 | 99922 | SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); |
| 98676 | 99923 | SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, |
| @@ -98677,14 +99924,11 @@ | ||
| 98677 | 99924 | const char *, sqlite3_tokenizer **, const char **, char ** |
| 98678 | 99925 | ); |
| 98679 | 99926 | |
| 98680 | 99927 | /* fts3_snippet.c */ |
| 98681 | 99928 | SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); |
| 98682 | -SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context*, Fts3Cursor*, | |
| 98683 | - const char *, const char *, const char * | |
| 98684 | -); | |
| 98685 | -SQLITE_PRIVATE void sqlite3Fts3Snippet2(sqlite3_context *, Fts3Cursor *, const char *, | |
| 99929 | +SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, | |
| 98686 | 99930 | const char *, const char *, int, int |
| 98687 | 99931 | ); |
| 98688 | 99932 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *); |
| 98689 | 99933 | |
| 98690 | 99934 | /* fts3_expr.c */ |
| @@ -98800,16 +100044,27 @@ | ||
| 98800 | 100044 | } |
| 98801 | 100045 | z[iOut] = '\0'; |
| 98802 | 100046 | } |
| 98803 | 100047 | } |
| 98804 | 100048 | |
| 100049 | +/* | |
| 100050 | +** Read a single varint from the doclist at *pp and advance *pp to point | |
| 100051 | +** to the next element of the varlist. Add the value of the varint | |
| 100052 | +** to *pVal. | |
| 100053 | +*/ | |
| 98805 | 100054 | static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){ |
| 98806 | 100055 | sqlite3_int64 iVal; |
| 98807 | 100056 | *pp += sqlite3Fts3GetVarint(*pp, &iVal); |
| 98808 | 100057 | *pVal += iVal; |
| 98809 | 100058 | } |
| 98810 | 100059 | |
| 100060 | +/* | |
| 100061 | +** As long as *pp has not reached its end (pEnd), then do the same | |
| 100062 | +** as fts3GetDeltaVarint(): read a single varint and add it to *pVal. | |
| 100063 | +** But if we have reached the end of the varint, just set *pp=0 and | |
| 100064 | +** leave *pVal unchanged. | |
| 100065 | +*/ | |
| 98811 | 100066 | static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){ |
| 98812 | 100067 | if( *pp>=pEnd ){ |
| 98813 | 100068 | *pp = 0; |
| 98814 | 100069 | }else{ |
| 98815 | 100070 | fts3GetDeltaVarint(pp, pVal); |
| @@ -98839,35 +100094,52 @@ | ||
| 98839 | 100094 | p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
| 98840 | 100095 | |
| 98841 | 100096 | sqlite3_free(p); |
| 98842 | 100097 | return SQLITE_OK; |
| 98843 | 100098 | } |
| 100099 | + | |
| 100100 | +/* | |
| 100101 | +** Construct one or more SQL statements from the format string given | |
| 100102 | +** and then evaluate those statements. The success code is writting | |
| 100103 | +** into *pRc. | |
| 100104 | +** | |
| 100105 | +** If *pRc is initially non-zero then this routine is a no-op. | |
| 100106 | +*/ | |
| 100107 | +void fts3DbExec( | |
| 100108 | + int *pRc, /* Success code */ | |
| 100109 | + sqlite3 *db, /* Database in which to run SQL */ | |
| 100110 | + const char *zFormat, /* Format string for SQL */ | |
| 100111 | + ... /* Arguments to the format string */ | |
| 100112 | +){ | |
| 100113 | + va_list ap; | |
| 100114 | + char *zSql; | |
| 100115 | + if( *pRc ) return; | |
| 100116 | + va_start(ap, zFormat); | |
| 100117 | + zSql = sqlite3_vmprintf(zFormat, ap); | |
| 100118 | + va_end(ap); | |
| 100119 | + if( zSql==0 ){ | |
| 100120 | + *pRc = SQLITE_NOMEM; | |
| 100121 | + }else{ | |
| 100122 | + *pRc = sqlite3_exec(db, zSql, 0, 0, 0); | |
| 100123 | + sqlite3_free(zSql); | |
| 100124 | + } | |
| 100125 | +} | |
| 98844 | 100126 | |
| 98845 | 100127 | /* |
| 98846 | 100128 | ** The xDestroy() virtual table method. |
| 98847 | 100129 | */ |
| 98848 | 100130 | static int fts3DestroyMethod(sqlite3_vtab *pVtab){ |
| 98849 | - int rc; /* Return code */ | |
| 100131 | + int rc = SQLITE_OK; /* Return code */ | |
| 98850 | 100132 | Fts3Table *p = (Fts3Table *)pVtab; |
| 98851 | - | |
| 98852 | - /* Create a script to drop the underlying three storage tables. */ | |
| 98853 | - char *zSql = sqlite3_mprintf( | |
| 98854 | - "DROP TABLE IF EXISTS %Q.'%q_content';" | |
| 98855 | - "DROP TABLE IF EXISTS %Q.'%q_segments';" | |
| 98856 | - "DROP TABLE IF EXISTS %Q.'%q_segdir';", | |
| 98857 | - p->zDb, p->zName, p->zDb, p->zName, p->zDb, p->zName | |
| 98858 | - ); | |
| 98859 | - | |
| 98860 | - /* If malloc has failed, set rc to SQLITE_NOMEM. Otherwise, try to | |
| 98861 | - ** execute the SQL script created above. | |
| 98862 | - */ | |
| 98863 | - if( zSql ){ | |
| 98864 | - rc = sqlite3_exec(p->db, zSql, 0, 0, 0); | |
| 98865 | - sqlite3_free(zSql); | |
| 98866 | - }else{ | |
| 98867 | - rc = SQLITE_NOMEM; | |
| 98868 | - } | |
| 100133 | + sqlite3 *db = p->db; | |
| 100134 | + | |
| 100135 | + /* Drop the shadow tables */ | |
| 100136 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", p->zDb, p->zName); | |
| 100137 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", p->zDb,p->zName); | |
| 100138 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", p->zDb, p->zName); | |
| 100139 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", p->zDb, p->zName); | |
| 100140 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", p->zDb, p->zName); | |
| 98869 | 100141 | |
| 98870 | 100142 | /* If everything has worked, invoke fts3DisconnectMethod() to free the |
| 98871 | 100143 | ** memory associated with the Fts3Table structure and return SQLITE_OK. |
| 98872 | 100144 | ** Otherwise, return an SQLite error code. |
| 98873 | 100145 | */ |
| @@ -98912,50 +100184,77 @@ | ||
| 98912 | 100184 | ** Create the backing store tables (%_content, %_segments and %_segdir) |
| 98913 | 100185 | ** required by the FTS3 table passed as the only argument. This is done |
| 98914 | 100186 | ** as part of the vtab xCreate() method. |
| 98915 | 100187 | */ |
| 98916 | 100188 | static int fts3CreateTables(Fts3Table *p){ |
| 98917 | - int rc; /* Return code */ | |
| 100189 | + int rc = SQLITE_OK; /* Return code */ | |
| 98918 | 100190 | int i; /* Iterator variable */ |
| 98919 | 100191 | char *zContentCols; /* Columns of %_content table */ |
| 98920 | - char *zSql; /* SQL script to create required tables */ | |
| 100192 | + sqlite3 *db = p->db; /* The database connection */ | |
| 98921 | 100193 | |
| 98922 | 100194 | /* Create a list of user columns for the content table */ |
| 98923 | - zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); | |
| 98924 | - for(i=0; zContentCols && i<p->nColumn; i++){ | |
| 98925 | - char *z = p->azColumn[i]; | |
| 98926 | - zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); | |
| 98927 | - } | |
| 98928 | - | |
| 98929 | - /* Create the whole SQL script */ | |
| 98930 | - zSql = sqlite3_mprintf( | |
| 98931 | - "CREATE TABLE %Q.'%q_content'(%s);" | |
| 98932 | - "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);" | |
| 100195 | + if( p->bHasContent ){ | |
| 100196 | + zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); | |
| 100197 | + for(i=0; zContentCols && i<p->nColumn; i++){ | |
| 100198 | + char *z = p->azColumn[i]; | |
| 100199 | + zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); | |
| 100200 | + } | |
| 100201 | + if( zContentCols==0 ) rc = SQLITE_NOMEM; | |
| 100202 | + | |
| 100203 | + /* Create the content table */ | |
| 100204 | + fts3DbExec(&rc, db, | |
| 100205 | + "CREATE TABLE %Q.'%q_content'(%s)", | |
| 100206 | + p->zDb, p->zName, zContentCols | |
| 100207 | + ); | |
| 100208 | + sqlite3_free(zContentCols); | |
| 100209 | + } | |
| 100210 | + /* Create other tables */ | |
| 100211 | + fts3DbExec(&rc, db, | |
| 100212 | + "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);", | |
| 100213 | + p->zDb, p->zName | |
| 100214 | + ); | |
| 100215 | + fts3DbExec(&rc, db, | |
| 98933 | 100216 | "CREATE TABLE %Q.'%q_segdir'(" |
| 98934 | 100217 | "level INTEGER," |
| 98935 | 100218 | "idx INTEGER," |
| 98936 | 100219 | "start_block INTEGER," |
| 98937 | 100220 | "leaves_end_block INTEGER," |
| 98938 | 100221 | "end_block INTEGER," |
| 98939 | 100222 | "root BLOB," |
| 98940 | 100223 | "PRIMARY KEY(level, idx)" |
| 98941 | 100224 | ");", |
| 98942 | - p->zDb, p->zName, zContentCols, p->zDb, p->zName, p->zDb, p->zName | |
| 100225 | + p->zDb, p->zName | |
| 98943 | 100226 | ); |
| 98944 | - | |
| 98945 | - /* Unless a malloc() failure has occurred, execute the SQL script to | |
| 98946 | - ** create the tables used to store data for this FTS3 virtual table. | |
| 98947 | - */ | |
| 98948 | - if( zContentCols==0 || zSql==0 ){ | |
| 98949 | - rc = SQLITE_NOMEM; | |
| 98950 | - }else{ | |
| 98951 | - rc = sqlite3_exec(p->db, zSql, 0, 0, 0); | |
| 98952 | - } | |
| 98953 | - | |
| 98954 | - sqlite3_free(zSql); | |
| 98955 | - sqlite3_free(zContentCols); | |
| 98956 | - return rc; | |
| 100227 | + if( p->bHasDocsize ){ | |
| 100228 | + fts3DbExec(&rc, db, | |
| 100229 | + "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", | |
| 100230 | + p->zDb, p->zName | |
| 100231 | + ); | |
| 100232 | + fts3DbExec(&rc, db, | |
| 100233 | + "CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);", | |
| 100234 | + p->zDb, p->zName | |
| 100235 | + ); | |
| 100236 | + } | |
| 100237 | + return rc; | |
| 100238 | +} | |
| 100239 | + | |
| 100240 | +/* | |
| 100241 | +** Determine if a table currently exists in the database. | |
| 100242 | +*/ | |
| 100243 | +static void fts3TableExists( | |
| 100244 | + int *pRc, /* Success code */ | |
| 100245 | + sqlite3 *db, /* The database connection to test */ | |
| 100246 | + const char *zDb, /* ATTACHed database within the connection */ | |
| 100247 | + const char *zName, /* Name of the FTS3 table */ | |
| 100248 | + const char *zSuffix, /* Shadow table extension */ | |
| 100249 | + u8 *pResult /* Write results here */ | |
| 100250 | +){ | |
| 100251 | + int rc = SQLITE_OK; | |
| 100252 | + if( *pRc ) return; | |
| 100253 | + fts3DbExec(&rc, db, "SELECT 1 FROM %Q.'%q%s'", zDb, zName, zSuffix); | |
| 100254 | + *pResult = (rc==SQLITE_OK) ? 1 : 0; | |
| 100255 | + if( rc!=SQLITE_ERROR ) *pRc = rc; | |
| 98957 | 100256 | } |
| 98958 | 100257 | |
| 98959 | 100258 | /* |
| 98960 | 100259 | ** This function is the implementation of both the xConnect and xCreate |
| 98961 | 100260 | ** methods of the FTS3 virtual table. |
| @@ -99070,13 +100369,19 @@ | ||
| 99070 | 100369 | |
| 99071 | 100370 | /* If this is an xCreate call, create the underlying tables in the |
| 99072 | 100371 | ** database. TODO: For xConnect(), it could verify that said tables exist. |
| 99073 | 100372 | */ |
| 99074 | 100373 | if( isCreate ){ |
| 100374 | + p->bHasContent = 1; | |
| 100375 | + p->bHasDocsize = argv[0][3]=='4'; | |
| 99075 | 100376 | rc = fts3CreateTables(p); |
| 99076 | - if( rc!=SQLITE_OK ) goto fts3_init_out; | |
| 100377 | + }else{ | |
| 100378 | + rc = SQLITE_OK; | |
| 100379 | + fts3TableExists(&rc, db, argv[1], argv[2], "_content", &p->bHasContent); | |
| 100380 | + fts3TableExists(&rc, db, argv[1], argv[2], "_docsize", &p->bHasDocsize); | |
| 99077 | 100381 | } |
| 100382 | + if( rc!=SQLITE_OK ) goto fts3_init_out; | |
| 99078 | 100383 | |
| 99079 | 100384 | rc = fts3DeclareVtab(p); |
| 99080 | 100385 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 99081 | 100386 | |
| 99082 | 100387 | *ppVTab = &p->base; |
| @@ -99193,16 +100498,10 @@ | ||
| 99193 | 100498 | return SQLITE_NOMEM; |
| 99194 | 100499 | } |
| 99195 | 100500 | memset(pCsr, 0, sizeof(Fts3Cursor)); |
| 99196 | 100501 | return SQLITE_OK; |
| 99197 | 100502 | } |
| 99198 | - | |
| 99199 | -/****************************************************************/ | |
| 99200 | -/****************************************************************/ | |
| 99201 | -/****************************************************************/ | |
| 99202 | -/****************************************************************/ | |
| 99203 | - | |
| 99204 | 100503 | |
| 99205 | 100504 | /* |
| 99206 | 100505 | ** Close the cursor. For additional information see the documentation |
| 99207 | 100506 | ** on the xClose method of the virtual table interface. |
| 99208 | 100507 | */ |
| @@ -99255,11 +100554,11 @@ | ||
| 99255 | 100554 | pCsr->isEof = 1; |
| 99256 | 100555 | }else{ |
| 99257 | 100556 | sqlite3_reset(pCsr->pStmt); |
| 99258 | 100557 | fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId); |
| 99259 | 100558 | pCsr->isRequireSeek = 1; |
| 99260 | - pCsr->isMatchinfoOk = 1; | |
| 100559 | + pCsr->isMatchinfoNeeded = 1; | |
| 99261 | 100560 | } |
| 99262 | 100561 | return rc; |
| 99263 | 100562 | } |
| 99264 | 100563 | |
| 99265 | 100564 | |
| @@ -100120,10 +101419,78 @@ | ||
| 100120 | 101419 | }else{ |
| 100121 | 101420 | sqlite3_free(pOut); |
| 100122 | 101421 | } |
| 100123 | 101422 | return rc; |
| 100124 | 101423 | } |
| 101424 | + | |
| 101425 | +static int fts3NearMerge( | |
| 101426 | + int mergetype, /* MERGE_POS_NEAR or MERGE_NEAR */ | |
| 101427 | + int nNear, /* Parameter to NEAR operator */ | |
| 101428 | + int nTokenLeft, /* Number of tokens in LHS phrase arg */ | |
| 101429 | + char *aLeft, /* Doclist for LHS (incl. positions) */ | |
| 101430 | + int nLeft, /* Size of LHS doclist in bytes */ | |
| 101431 | + int nTokenRight, /* As nTokenLeft */ | |
| 101432 | + char *aRight, /* As aLeft */ | |
| 101433 | + int nRight, /* As nRight */ | |
| 101434 | + char **paOut, /* OUT: Results of merge (malloced) */ | |
| 101435 | + int *pnOut /* OUT: Sized of output buffer */ | |
| 101436 | +){ | |
| 101437 | + char *aOut; | |
| 101438 | + int rc; | |
| 101439 | + | |
| 101440 | + assert( mergetype==MERGE_POS_NEAR || MERGE_NEAR ); | |
| 101441 | + | |
| 101442 | + aOut = sqlite3_malloc(nLeft+nRight+1); | |
| 101443 | + if( aOut==0 ){ | |
| 101444 | + rc = SQLITE_NOMEM; | |
| 101445 | + }else{ | |
| 101446 | + rc = fts3DoclistMerge(mergetype, nNear+nTokenRight, nNear+nTokenLeft, | |
| 101447 | + aOut, pnOut, aLeft, nLeft, aRight, nRight | |
| 101448 | + ); | |
| 101449 | + if( rc!=SQLITE_OK ){ | |
| 101450 | + sqlite3_free(aOut); | |
| 101451 | + aOut = 0; | |
| 101452 | + } | |
| 101453 | + } | |
| 101454 | + | |
| 101455 | + *paOut = aOut; | |
| 101456 | + return rc; | |
| 101457 | +} | |
| 101458 | + | |
| 101459 | +SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *pLeft, Fts3Expr *pRight, int nNear){ | |
| 101460 | + int rc; | |
| 101461 | + if( pLeft->aDoclist==0 || pRight->aDoclist==0 ){ | |
| 101462 | + sqlite3_free(pLeft->aDoclist); | |
| 101463 | + sqlite3_free(pRight->aDoclist); | |
| 101464 | + pRight->aDoclist = 0; | |
| 101465 | + pLeft->aDoclist = 0; | |
| 101466 | + rc = SQLITE_OK; | |
| 101467 | + }else{ | |
| 101468 | + char *aOut; | |
| 101469 | + int nOut; | |
| 101470 | + | |
| 101471 | + rc = fts3NearMerge(MERGE_POS_NEAR, nNear, | |
| 101472 | + pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist, | |
| 101473 | + pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist, | |
| 101474 | + &aOut, &nOut | |
| 101475 | + ); | |
| 101476 | + if( rc!=SQLITE_OK ) return rc; | |
| 101477 | + sqlite3_free(pRight->aDoclist); | |
| 101478 | + pRight->aDoclist = aOut; | |
| 101479 | + pRight->nDoclist = nOut; | |
| 101480 | + | |
| 101481 | + rc = fts3NearMerge(MERGE_POS_NEAR, nNear, | |
| 101482 | + pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist, | |
| 101483 | + pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist, | |
| 101484 | + &aOut, &nOut | |
| 101485 | + ); | |
| 101486 | + sqlite3_free(pLeft->aDoclist); | |
| 101487 | + pLeft->aDoclist = aOut; | |
| 101488 | + pLeft->nDoclist = nOut; | |
| 101489 | + } | |
| 101490 | + return rc; | |
| 101491 | +} | |
| 100125 | 101492 | |
| 100126 | 101493 | /* |
| 100127 | 101494 | ** Evaluate the full-text expression pExpr against fts3 table pTab. Store |
| 100128 | 101495 | ** the resulting doclist in *paOut and *pnOut. |
| 100129 | 101496 | */ |
| @@ -100165,13 +101532,10 @@ | ||
| 100165 | 101532 | switch( pExpr->eType ){ |
| 100166 | 101533 | case FTSQUERY_NEAR: { |
| 100167 | 101534 | Fts3Expr *pLeft; |
| 100168 | 101535 | Fts3Expr *pRight; |
| 100169 | 101536 | int mergetype = isReqPos ? MERGE_POS_NEAR : MERGE_NEAR; |
| 100170 | - int nParam1; | |
| 100171 | - int nParam2; | |
| 100172 | - char *aBuffer; | |
| 100173 | 101537 | |
| 100174 | 101538 | if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){ |
| 100175 | 101539 | mergetype = MERGE_POS_NEAR; |
| 100176 | 101540 | } |
| 100177 | 101541 | pLeft = pExpr->pLeft; |
| @@ -100180,21 +101544,15 @@ | ||
| 100180 | 101544 | } |
| 100181 | 101545 | pRight = pExpr->pRight; |
| 100182 | 101546 | assert( pRight->eType==FTSQUERY_PHRASE ); |
| 100183 | 101547 | assert( pLeft->eType==FTSQUERY_PHRASE ); |
| 100184 | 101548 | |
| 100185 | - nParam1 = pExpr->nNear+1; | |
| 100186 | - nParam2 = nParam1+pLeft->pPhrase->nToken+pRight->pPhrase->nToken-2; | |
| 100187 | - aBuffer = sqlite3_malloc(nLeft+nRight+1); | |
| 100188 | - rc = fts3DoclistMerge(mergetype, nParam1, nParam2, aBuffer, | |
| 100189 | - pnOut, aLeft, nLeft, aRight, nRight | |
| 101549 | + rc = fts3NearMerge(mergetype, pExpr->nNear, | |
| 101550 | + pLeft->pPhrase->nToken, aLeft, nLeft, | |
| 101551 | + pRight->pPhrase->nToken, aRight, nRight, | |
| 101552 | + paOut, pnOut | |
| 100190 | 101553 | ); |
| 100191 | - if( rc!=SQLITE_OK ){ | |
| 100192 | - sqlite3_free(aBuffer); | |
| 100193 | - }else{ | |
| 100194 | - *paOut = aBuffer; | |
| 100195 | - } | |
| 100196 | 101554 | sqlite3_free(aLeft); |
| 100197 | 101555 | break; |
| 100198 | 101556 | } |
| 100199 | 101557 | |
| 100200 | 101558 | case FTSQUERY_OR: { |
| @@ -100441,11 +101799,11 @@ | ||
| 100441 | 101799 | return evalFts3Expr(pTab, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1); |
| 100442 | 101800 | } |
| 100443 | 101801 | |
| 100444 | 101802 | /* |
| 100445 | 101803 | ** After ExprLoadDoclist() (see above) has been called, this function is |
| 100446 | -** used to iterate through the position lists that make up the doclist | |
| 101804 | +** used to iterate/search through the position lists that make up the doclist | |
| 100447 | 101805 | ** stored in pExpr->aDoclist. |
| 100448 | 101806 | */ |
| 100449 | 101807 | SQLITE_PRIVATE char *sqlite3Fts3FindPositions( |
| 100450 | 101808 | Fts3Expr *pExpr, /* Access this expressions doclist */ |
| 100451 | 101809 | sqlite3_int64 iDocid, /* Docid associated with requested pos-list */ |
| @@ -100476,11 +101834,11 @@ | ||
| 100476 | 101834 | fts3ColumnlistCopy(0, &pCsr); |
| 100477 | 101835 | if( *pCsr==0x00 ) return 0; |
| 100478 | 101836 | pCsr++; |
| 100479 | 101837 | pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis); |
| 100480 | 101838 | } |
| 100481 | - if( iCol==iThis ) return pCsr; | |
| 101839 | + if( iCol==iThis && (*pCsr&0xFE) ) return pCsr; | |
| 100482 | 101840 | } |
| 100483 | 101841 | return 0; |
| 100484 | 101842 | } |
| 100485 | 101843 | } |
| 100486 | 101844 | } |
| @@ -100528,49 +101886,12 @@ | ||
| 100528 | 101886 | ){ |
| 100529 | 101887 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 100530 | 101888 | const char *zStart = "<b>"; |
| 100531 | 101889 | const char *zEnd = "</b>"; |
| 100532 | 101890 | const char *zEllipsis = "<b>...</b>"; |
| 100533 | - | |
| 100534 | - /* There must be at least one argument passed to this function (otherwise | |
| 100535 | - ** the non-overloaded version would have been called instead of this one). | |
| 100536 | - */ | |
| 100537 | - assert( nVal>=1 ); | |
| 100538 | - | |
| 100539 | - if( nVal>4 ){ | |
| 100540 | - sqlite3_result_error(pContext, | |
| 100541 | - "wrong number of arguments to function snippet()", -1); | |
| 100542 | - return; | |
| 100543 | - } | |
| 100544 | - if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; | |
| 100545 | - | |
| 100546 | - switch( nVal ){ | |
| 100547 | - case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); | |
| 100548 | - case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); | |
| 100549 | - case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); | |
| 100550 | - } | |
| 100551 | - if( !zEllipsis || !zEnd || !zStart ){ | |
| 100552 | - sqlite3_result_error_nomem(pContext); | |
| 100553 | - }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ | |
| 100554 | - sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis); | |
| 100555 | - } | |
| 100556 | -} | |
| 100557 | - | |
| 100558 | -/* | |
| 100559 | -** Implementation of the snippet2() function for FTS3 | |
| 100560 | -*/ | |
| 100561 | -static void fts3Snippet2Func( | |
| 100562 | - sqlite3_context *pContext, /* SQLite function call context */ | |
| 100563 | - int nVal, /* Size of apVal[] array */ | |
| 100564 | - sqlite3_value **apVal /* Array of arguments */ | |
| 100565 | -){ | |
| 100566 | - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ | |
| 100567 | - const char *zStart = "<b>"; | |
| 100568 | - const char *zEnd = "</b>"; | |
| 100569 | - const char *zEllipsis = "<b>...</b>"; | |
| 100570 | 101891 | int iCol = -1; |
| 100571 | - int nToken = 10; | |
| 101892 | + int nToken = 15; /* Default number of tokens in snippet */ | |
| 100572 | 101893 | |
| 100573 | 101894 | /* There must be at least one argument passed to this function (otherwise |
| 100574 | 101895 | ** the non-overloaded version would have been called instead of this one). |
| 100575 | 101896 | */ |
| 100576 | 101897 | assert( nVal>=1 ); |
| @@ -100590,11 +101911,11 @@ | ||
| 100590 | 101911 | case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); |
| 100591 | 101912 | } |
| 100592 | 101913 | if( !zEllipsis || !zEnd || !zStart ){ |
| 100593 | 101914 | sqlite3_result_error_nomem(pContext); |
| 100594 | 101915 | }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ |
| 100595 | - sqlite3Fts3Snippet2(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); | |
| 101916 | + sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); | |
| 100596 | 101917 | } |
| 100597 | 101918 | } |
| 100598 | 101919 | |
| 100599 | 101920 | /* |
| 100600 | 101921 | ** Implementation of the offsets() function for FTS3 |
| @@ -100691,11 +102012,10 @@ | ||
| 100691 | 102012 | struct Overloaded { |
| 100692 | 102013 | const char *zName; |
| 100693 | 102014 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**); |
| 100694 | 102015 | } aOverload[] = { |
| 100695 | 102016 | { "snippet", fts3SnippetFunc }, |
| 100696 | - { "snippet2", fts3Snippet2Func }, | |
| 100697 | 102017 | { "offsets", fts3OffsetsFunc }, |
| 100698 | 102018 | { "optimize", fts3OptimizeFunc }, |
| 100699 | 102019 | { "matchinfo", fts3MatchinfoFunc }, |
| 100700 | 102020 | }; |
| 100701 | 102021 | int i; /* Iterator variable */ |
| @@ -100720,26 +102040,39 @@ | ||
| 100720 | 102040 | */ |
| 100721 | 102041 | static int fts3RenameMethod( |
| 100722 | 102042 | sqlite3_vtab *pVtab, /* Virtual table handle */ |
| 100723 | 102043 | const char *zName /* New name of table */ |
| 100724 | 102044 | ){ |
| 100725 | - Fts3Table *p = (Fts3Table *)pVtab; | |
| 100726 | - int rc = SQLITE_NOMEM; /* Return Code */ | |
| 100727 | - char *zSql; /* SQL script to run to rename tables */ | |
| 100728 | - | |
| 100729 | - zSql = sqlite3_mprintf( | |
| 100730 | - "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';" | |
| 100731 | - "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';" | |
| 100732 | - "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';" | |
| 100733 | - , p->zDb, p->zName, zName | |
| 100734 | - , p->zDb, p->zName, zName | |
| 100735 | - , p->zDb, p->zName, zName | |
| 100736 | - ); | |
| 100737 | - if( zSql ){ | |
| 100738 | - rc = sqlite3_exec(p->db, zSql, 0, 0, 0); | |
| 100739 | - sqlite3_free(zSql); | |
| 100740 | - } | |
| 102045 | + Fts3Table *p = (Fts3Table *)pVtab; | |
| 102046 | + sqlite3 *db; /* Database connection */ | |
| 102047 | + int rc; /* Return Code */ | |
| 102048 | + | |
| 102049 | + db = p->db; | |
| 102050 | + rc = SQLITE_OK; | |
| 102051 | + fts3DbExec(&rc, db, | |
| 102052 | + "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", | |
| 102053 | + p->zDb, p->zName, zName | |
| 102054 | + ); | |
| 102055 | + if( rc==SQLITE_ERROR ) rc = SQLITE_OK; | |
| 102056 | + if( p->bHasDocsize ){ | |
| 102057 | + fts3DbExec(&rc, db, | |
| 102058 | + "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';", | |
| 102059 | + p->zDb, p->zName, zName | |
| 102060 | + ); | |
| 102061 | + fts3DbExec(&rc, db, | |
| 102062 | + "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';", | |
| 102063 | + p->zDb, p->zName, zName | |
| 102064 | + ); | |
| 102065 | + } | |
| 102066 | + fts3DbExec(&rc, db, | |
| 102067 | + "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';", | |
| 102068 | + p->zDb, p->zName, zName | |
| 102069 | + ); | |
| 102070 | + fts3DbExec(&rc, db, | |
| 102071 | + "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';", | |
| 102072 | + p->zDb, p->zName, zName | |
| 102073 | + ); | |
| 100741 | 102074 | return rc; |
| 100742 | 102075 | } |
| 100743 | 102076 | |
| 100744 | 102077 | static const sqlite3_module fts3Module = { |
| 100745 | 102078 | /* iVersion */ 0, |
| @@ -100841,18 +102174,23 @@ | ||
| 100841 | 102174 | ** module with sqlite. |
| 100842 | 102175 | */ |
| 100843 | 102176 | if( SQLITE_OK==rc |
| 100844 | 102177 | && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) |
| 100845 | 102178 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) |
| 100846 | - && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet2", -1)) | |
| 100847 | 102179 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) |
| 100848 | 102180 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", -1)) |
| 100849 | 102181 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) |
| 100850 | 102182 | ){ |
| 100851 | - return sqlite3_create_module_v2( | |
| 102183 | + rc = sqlite3_create_module_v2( | |
| 100852 | 102184 | db, "fts3", &fts3Module, (void *)pHash, hashDestroy |
| 100853 | 102185 | ); |
| 102186 | + if( rc==SQLITE_OK ){ | |
| 102187 | + rc = sqlite3_create_module_v2( | |
| 102188 | + db, "fts4", &fts3Module, (void *)pHash, 0 | |
| 102189 | + ); | |
| 102190 | + } | |
| 102191 | + return rc; | |
| 100854 | 102192 | } |
| 100855 | 102193 | |
| 100856 | 102194 | /* An error has occurred. Delete the hash table and return the error code. */ |
| 100857 | 102195 | assert( rc!=SQLITE_OK ); |
| 100858 | 102196 | if( pHash ){ |
| @@ -102778,13 +104116,15 @@ | ||
| 102778 | 104116 | } |
| 102779 | 104117 | |
| 102780 | 104118 | if( c->iOffset>iStartOffset ){ |
| 102781 | 104119 | int n = c->iOffset-iStartOffset; |
| 102782 | 104120 | if( n>c->nAllocated ){ |
| 104121 | + char *pNew; | |
| 102783 | 104122 | c->nAllocated = n+20; |
| 102784 | - c->zToken = sqlite3_realloc(c->zToken, c->nAllocated); | |
| 102785 | - if( c->zToken==NULL ) return SQLITE_NOMEM; | |
| 104123 | + pNew = sqlite3_realloc(c->zToken, c->nAllocated); | |
| 104124 | + if( !pNew ) return SQLITE_NOMEM; | |
| 104125 | + c->zToken = pNew; | |
| 102786 | 104126 | } |
| 102787 | 104127 | porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); |
| 102788 | 104128 | *pzToken = c->zToken; |
| 102789 | 104129 | *piStartOffset = iStartOffset; |
| 102790 | 104130 | *piEndOffset = c->iOffset; |
| @@ -103491,13 +104831,15 @@ | ||
| 103491 | 104831 | } |
| 103492 | 104832 | |
| 103493 | 104833 | if( c->iOffset>iStartOffset ){ |
| 103494 | 104834 | int i, n = c->iOffset-iStartOffset; |
| 103495 | 104835 | if( n>c->nTokenAllocated ){ |
| 104836 | + char *pNew; | |
| 103496 | 104837 | c->nTokenAllocated = n+20; |
| 103497 | - c->pToken = sqlite3_realloc(c->pToken, c->nTokenAllocated); | |
| 103498 | - if( c->pToken==NULL ) return SQLITE_NOMEM; | |
| 104838 | + pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated); | |
| 104839 | + if( !pNew ) return SQLITE_NOMEM; | |
| 104840 | + c->pToken = pNew; | |
| 103499 | 104841 | } |
| 103500 | 104842 | for(i=0; i<n; i++){ |
| 103501 | 104843 | /* TODO(shess) This needs expansion to handle UTF-8 |
| 103502 | 104844 | ** case-insensitivity. |
| 103503 | 104845 | */ |
| @@ -103677,23 +105019,30 @@ | ||
| 103677 | 105019 | #define SQL_DELETE_CONTENT 0 |
| 103678 | 105020 | #define SQL_IS_EMPTY 1 |
| 103679 | 105021 | #define SQL_DELETE_ALL_CONTENT 2 |
| 103680 | 105022 | #define SQL_DELETE_ALL_SEGMENTS 3 |
| 103681 | 105023 | #define SQL_DELETE_ALL_SEGDIR 4 |
| 103682 | -#define SQL_SELECT_CONTENT_BY_ROWID 5 | |
| 103683 | -#define SQL_NEXT_SEGMENT_INDEX 6 | |
| 103684 | -#define SQL_INSERT_SEGMENTS 7 | |
| 103685 | -#define SQL_NEXT_SEGMENTS_ID 8 | |
| 103686 | -#define SQL_INSERT_SEGDIR 9 | |
| 103687 | -#define SQL_SELECT_LEVEL 10 | |
| 103688 | -#define SQL_SELECT_ALL_LEVEL 11 | |
| 103689 | -#define SQL_SELECT_LEVEL_COUNT 12 | |
| 103690 | -#define SQL_SELECT_SEGDIR_COUNT_MAX 13 | |
| 103691 | -#define SQL_DELETE_SEGDIR_BY_LEVEL 14 | |
| 103692 | -#define SQL_DELETE_SEGMENTS_RANGE 15 | |
| 103693 | -#define SQL_CONTENT_INSERT 16 | |
| 103694 | -#define SQL_GET_BLOCK 17 | |
| 105024 | +#define SQL_DELETE_ALL_DOCSIZE 5 | |
| 105025 | +#define SQL_DELETE_ALL_STAT 6 | |
| 105026 | +#define SQL_SELECT_CONTENT_BY_ROWID 7 | |
| 105027 | +#define SQL_NEXT_SEGMENT_INDEX 8 | |
| 105028 | +#define SQL_INSERT_SEGMENTS 9 | |
| 105029 | +#define SQL_NEXT_SEGMENTS_ID 10 | |
| 105030 | +#define SQL_INSERT_SEGDIR 11 | |
| 105031 | +#define SQL_SELECT_LEVEL 12 | |
| 105032 | +#define SQL_SELECT_ALL_LEVEL 13 | |
| 105033 | +#define SQL_SELECT_LEVEL_COUNT 14 | |
| 105034 | +#define SQL_SELECT_SEGDIR_COUNT_MAX 15 | |
| 105035 | +#define SQL_DELETE_SEGDIR_BY_LEVEL 16 | |
| 105036 | +#define SQL_DELETE_SEGMENTS_RANGE 17 | |
| 105037 | +#define SQL_CONTENT_INSERT 18 | |
| 105038 | +#define SQL_GET_BLOCK 19 | |
| 105039 | +#define SQL_DELETE_DOCSIZE 20 | |
| 105040 | +#define SQL_REPLACE_DOCSIZE 21 | |
| 105041 | +#define SQL_SELECT_DOCSIZE 22 | |
| 105042 | +#define SQL_SELECT_DOCTOTAL 23 | |
| 105043 | +#define SQL_REPLACE_DOCTOTAL 24 | |
| 103695 | 105044 | |
| 103696 | 105045 | /* |
| 103697 | 105046 | ** This function is used to obtain an SQLite prepared statement handle |
| 103698 | 105047 | ** for the statement identified by the second argument. If successful, |
| 103699 | 105048 | ** *pp is set to the requested statement handle and SQLITE_OK returned. |
| @@ -103714,29 +105063,36 @@ | ||
| 103714 | 105063 | /* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?", |
| 103715 | 105064 | /* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)", |
| 103716 | 105065 | /* 2 */ "DELETE FROM %Q.'%q_content'", |
| 103717 | 105066 | /* 3 */ "DELETE FROM %Q.'%q_segments'", |
| 103718 | 105067 | /* 4 */ "DELETE FROM %Q.'%q_segdir'", |
| 103719 | -/* 5 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?", | |
| 103720 | -/* 6 */ "SELECT coalesce(max(idx)+1, 0) FROM %Q.'%q_segdir' WHERE level=?", | |
| 103721 | -/* 7 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", | |
| 103722 | -/* 8 */ "SELECT coalesce(max(blockid)+1, 1) FROM %Q.'%q_segments'", | |
| 103723 | -/* 9 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", | |
| 105068 | +/* 5 */ "DELETE FROM %Q.'%q_docsize'", | |
| 105069 | +/* 6 */ "DELETE FROM %Q.'%q_stat'", | |
| 105070 | +/* 7 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?", | |
| 105071 | +/* 8 */ "SELECT coalesce(max(idx)+1, 0) FROM %Q.'%q_segdir' WHERE level=?", | |
| 105072 | +/* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", | |
| 105073 | +/* 10 */ "SELECT coalesce(max(blockid)+1, 1) FROM %Q.'%q_segments'", | |
| 105074 | +/* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", | |
| 103724 | 105075 | |
| 103725 | 105076 | /* Return segments in order from oldest to newest.*/ |
| 103726 | -/* 10 */ "SELECT idx, start_block, leaves_end_block, end_block, root " | |
| 105077 | +/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root " | |
| 103727 | 105078 | "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC", |
| 103728 | -/* 11 */ "SELECT idx, start_block, leaves_end_block, end_block, root " | |
| 105079 | +/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root " | |
| 103729 | 105080 | "FROM %Q.'%q_segdir' ORDER BY level DESC, idx ASC", |
| 103730 | 105081 | |
| 103731 | -/* 12 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", | |
| 103732 | -/* 13 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'", | |
| 105082 | +/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", | |
| 105083 | +/* 15 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'", | |
| 103733 | 105084 | |
| 103734 | -/* 14 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?", | |
| 103735 | -/* 15 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?", | |
| 103736 | -/* 16 */ "INSERT INTO %Q.'%q_content' VALUES(%z)", | |
| 103737 | -/* 17 */ "SELECT block FROM %Q.'%q_segments' WHERE blockid = ?", | |
| 105085 | +/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?", | |
| 105086 | +/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?", | |
| 105087 | +/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%z)", | |
| 105088 | +/* 19 */ "SELECT block FROM %Q.'%q_segments' WHERE blockid = ?", | |
| 105089 | +/* 20 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", | |
| 105090 | +/* 21 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", | |
| 105091 | +/* 22 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", | |
| 105092 | +/* 23 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0", | |
| 105093 | +/* 24 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)", | |
| 103738 | 105094 | }; |
| 103739 | 105095 | int rc = SQLITE_OK; |
| 103740 | 105096 | sqlite3_stmt *pStmt; |
| 103741 | 105097 | |
| 103742 | 105098 | assert( SizeofArray(azSql)==SizeofArray(p->aStmt) ); |
| @@ -103789,18 +105145,25 @@ | ||
| 103789 | 105145 | ** is executed. |
| 103790 | 105146 | ** |
| 103791 | 105147 | ** Returns SQLITE_OK if the statement is successfully executed, or an |
| 103792 | 105148 | ** SQLite error code otherwise. |
| 103793 | 105149 | */ |
| 103794 | -static int fts3SqlExec(Fts3Table *p, int eStmt, sqlite3_value **apVal){ | |
| 105150 | +static void fts3SqlExec( | |
| 105151 | + int *pRC, /* Result code */ | |
| 105152 | + Fts3Table *p, /* The FTS3 table */ | |
| 105153 | + int eStmt, /* Index of statement to evaluate */ | |
| 105154 | + sqlite3_value **apVal /* Parameters to bind */ | |
| 105155 | +){ | |
| 103795 | 105156 | sqlite3_stmt *pStmt; |
| 103796 | - int rc = fts3SqlStmt(p, eStmt, &pStmt, apVal); | |
| 105157 | + int rc; | |
| 105158 | + if( *pRC ) return; | |
| 105159 | + rc = fts3SqlStmt(p, eStmt, &pStmt, apVal); | |
| 103797 | 105160 | if( rc==SQLITE_OK ){ |
| 103798 | 105161 | sqlite3_step(pStmt); |
| 103799 | 105162 | rc = sqlite3_reset(pStmt); |
| 103800 | 105163 | } |
| 103801 | - return rc; | |
| 105164 | + *pRC = rc; | |
| 103802 | 105165 | } |
| 103803 | 105166 | |
| 103804 | 105167 | |
| 103805 | 105168 | /* |
| 103806 | 105169 | ** Read a single block from the %_segments table. If the specified block |
| @@ -103976,15 +105339,21 @@ | ||
| 103976 | 105339 | ** pending-terms hash-table. The docid used is that currently stored in |
| 103977 | 105340 | ** p->iPrevDocid, and the column is specified by argument iCol. |
| 103978 | 105341 | ** |
| 103979 | 105342 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. |
| 103980 | 105343 | */ |
| 103981 | -static int fts3PendingTermsAdd(Fts3Table *p, const char *zText, int iCol){ | |
| 105344 | +static int fts3PendingTermsAdd( | |
| 105345 | + Fts3Table *p, /* FTS table into which text will be inserted */ | |
| 105346 | + const char *zText, /* Text of document to be inseted */ | |
| 105347 | + int iCol, /* Column number into which text is inserted */ | |
| 105348 | + u32 *pnWord /* OUT: Number of tokens inserted */ | |
| 105349 | +){ | |
| 103982 | 105350 | int rc; |
| 103983 | 105351 | int iStart; |
| 103984 | 105352 | int iEnd; |
| 103985 | 105353 | int iPos; |
| 105354 | + int nWord = 0; | |
| 103986 | 105355 | |
| 103987 | 105356 | char const *zToken; |
| 103988 | 105357 | int nToken; |
| 103989 | 105358 | |
| 103990 | 105359 | sqlite3_tokenizer *pTokenizer = p->pTokenizer; |
| @@ -104004,10 +105373,12 @@ | ||
| 104004 | 105373 | xNext = pModule->xNext; |
| 104005 | 105374 | while( SQLITE_OK==rc |
| 104006 | 105375 | && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) |
| 104007 | 105376 | ){ |
| 104008 | 105377 | PendingList *pList; |
| 105378 | + | |
| 105379 | + if( iPos>=nWord ) nWord = iPos+1; | |
| 104009 | 105380 | |
| 104010 | 105381 | /* Positions cannot be negative; we use -1 as a terminator internally. |
| 104011 | 105382 | ** Tokens must have a non-zero length. |
| 104012 | 105383 | */ |
| 104013 | 105384 | if( iPos<0 || !zToken || nToken<=0 ){ |
| @@ -104033,10 +105404,11 @@ | ||
| 104033 | 105404 | p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem)); |
| 104034 | 105405 | } |
| 104035 | 105406 | } |
| 104036 | 105407 | |
| 104037 | 105408 | pModule->xClose(pCsr); |
| 105409 | + *pnWord = nWord; | |
| 104038 | 105410 | return (rc==SQLITE_DONE ? SQLITE_OK : rc); |
| 104039 | 105411 | } |
| 104040 | 105412 | |
| 104041 | 105413 | /* |
| 104042 | 105414 | ** Calling this function indicates that subsequent calls to |
| @@ -104073,16 +105445,16 @@ | ||
| 104073 | 105445 | ** pendingTerms hash table. |
| 104074 | 105446 | ** |
| 104075 | 105447 | ** Argument apVal is the same as the similarly named argument passed to |
| 104076 | 105448 | ** fts3InsertData(). Parameter iDocid is the docid of the new row. |
| 104077 | 105449 | */ |
| 104078 | -static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal){ | |
| 105450 | +static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){ | |
| 104079 | 105451 | int i; /* Iterator variable */ |
| 104080 | 105452 | for(i=2; i<p->nColumn+2; i++){ |
| 104081 | 105453 | const char *zText = (const char *)sqlite3_value_text(apVal[i]); |
| 104082 | 105454 | if( zText ){ |
| 104083 | - int rc = fts3PendingTermsAdd(p, zText, i-2); | |
| 105455 | + int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]); | |
| 104084 | 105456 | if( rc!=SQLITE_OK ){ |
| 104085 | 105457 | return rc; |
| 104086 | 105458 | } |
| 104087 | 105459 | } |
| 104088 | 105460 | } |
| @@ -104159,53 +105531,60 @@ | ||
| 104159 | 105531 | /* |
| 104160 | 105532 | ** Remove all data from the FTS3 table. Clear the hash table containing |
| 104161 | 105533 | ** pending terms. |
| 104162 | 105534 | */ |
| 104163 | 105535 | static int fts3DeleteAll(Fts3Table *p){ |
| 104164 | - int rc; /* Return code */ | |
| 105536 | + int rc = SQLITE_OK; /* Return code */ | |
| 104165 | 105537 | |
| 104166 | 105538 | /* Discard the contents of the pending-terms hash table. */ |
| 104167 | 105539 | sqlite3Fts3PendingTermsClear(p); |
| 104168 | 105540 | |
| 104169 | 105541 | /* Delete everything from the %_content, %_segments and %_segdir tables. */ |
| 104170 | - rc = fts3SqlExec(p, SQL_DELETE_ALL_CONTENT, 0); | |
| 104171 | - if( rc==SQLITE_OK ){ | |
| 104172 | - rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGMENTS, 0); | |
| 104173 | - } | |
| 104174 | - if( rc==SQLITE_OK ){ | |
| 104175 | - rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGDIR, 0); | |
| 105542 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0); | |
| 105543 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0); | |
| 105544 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); | |
| 105545 | + if( p->bHasDocsize ){ | |
| 105546 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0); | |
| 105547 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); | |
| 104176 | 105548 | } |
| 104177 | 105549 | return rc; |
| 104178 | 105550 | } |
| 104179 | 105551 | |
| 104180 | 105552 | /* |
| 104181 | 105553 | ** The first element in the apVal[] array is assumed to contain the docid |
| 104182 | 105554 | ** (an integer) of a row about to be deleted. Remove all terms from the |
| 104183 | 105555 | ** full-text index. |
| 104184 | 105556 | */ |
| 104185 | -static int fts3DeleteTerms(Fts3Table *p, sqlite3_value **apVal){ | |
| 105557 | +static void fts3DeleteTerms( | |
| 105558 | + int *pRC, /* Result code */ | |
| 105559 | + Fts3Table *p, /* The FTS table to delete from */ | |
| 105560 | + sqlite3_value **apVal, /* apVal[] contains the docid to be deleted */ | |
| 105561 | + u32 *aSz /* Sizes of deleted document written here */ | |
| 105562 | +){ | |
| 104186 | 105563 | int rc; |
| 104187 | 105564 | sqlite3_stmt *pSelect; |
| 104188 | 105565 | |
| 105566 | + if( *pRC ) return; | |
| 104189 | 105567 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, apVal); |
| 104190 | 105568 | if( rc==SQLITE_OK ){ |
| 104191 | 105569 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 104192 | 105570 | int i; |
| 104193 | 105571 | for(i=1; i<=p->nColumn; i++){ |
| 104194 | 105572 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 104195 | - rc = fts3PendingTermsAdd(p, zText, -1); | |
| 105573 | + rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]); | |
| 104196 | 105574 | if( rc!=SQLITE_OK ){ |
| 104197 | 105575 | sqlite3_reset(pSelect); |
| 104198 | - return rc; | |
| 105576 | + *pRC = rc; | |
| 105577 | + return; | |
| 104199 | 105578 | } |
| 104200 | 105579 | } |
| 104201 | 105580 | } |
| 104202 | 105581 | rc = sqlite3_reset(pSelect); |
| 104203 | 105582 | }else{ |
| 104204 | 105583 | sqlite3_reset(pSelect); |
| 104205 | 105584 | } |
| 104206 | - return rc; | |
| 105585 | + *pRC = rc; | |
| 104207 | 105586 | } |
| 104208 | 105587 | |
| 104209 | 105588 | /* |
| 104210 | 105589 | ** Forward declaration to account for the circular dependency between |
| 104211 | 105590 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| @@ -105321,11 +106700,11 @@ | ||
| 105321 | 106700 | sqlite3_bind_int(pDelete, 1, iLevel); |
| 105322 | 106701 | sqlite3_step(pDelete); |
| 105323 | 106702 | rc = sqlite3_reset(pDelete); |
| 105324 | 106703 | } |
| 105325 | 106704 | }else{ |
| 105326 | - rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGDIR, 0); | |
| 106705 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); | |
| 105327 | 106706 | } |
| 105328 | 106707 | |
| 105329 | 106708 | return rc; |
| 105330 | 106709 | } |
| 105331 | 106710 | |
| @@ -105748,10 +107127,215 @@ | ||
| 105748 | 107127 | if( rc==SQLITE_OK ){ |
| 105749 | 107128 | sqlite3Fts3PendingTermsClear(p); |
| 105750 | 107129 | } |
| 105751 | 107130 | return rc; |
| 105752 | 107131 | } |
| 107132 | + | |
| 107133 | +/* | |
| 107134 | +** Encode N integers as varints into a blob. | |
| 107135 | +*/ | |
| 107136 | +static void fts3EncodeIntArray( | |
| 107137 | + int N, /* The number of integers to encode */ | |
| 107138 | + u32 *a, /* The integer values */ | |
| 107139 | + char *zBuf, /* Write the BLOB here */ | |
| 107140 | + int *pNBuf /* Write number of bytes if zBuf[] used here */ | |
| 107141 | +){ | |
| 107142 | + int i, j; | |
| 107143 | + for(i=j=0; i<N; i++){ | |
| 107144 | + j += sqlite3Fts3PutVarint(&zBuf[j], (sqlite3_int64)a[i]); | |
| 107145 | + } | |
| 107146 | + *pNBuf = j; | |
| 107147 | +} | |
| 107148 | + | |
| 107149 | +/* | |
| 107150 | +** Decode a blob of varints into N integers | |
| 107151 | +*/ | |
| 107152 | +static void fts3DecodeIntArray( | |
| 107153 | + int N, /* The number of integers to decode */ | |
| 107154 | + u32 *a, /* Write the integer values */ | |
| 107155 | + const char *zBuf, /* The BLOB containing the varints */ | |
| 107156 | + int nBuf /* size of the BLOB */ | |
| 107157 | +){ | |
| 107158 | + int i, j; | |
| 107159 | + UNUSED_PARAMETER(nBuf); | |
| 107160 | + for(i=j=0; i<N; i++){ | |
| 107161 | + sqlite3_int64 x; | |
| 107162 | + j += sqlite3Fts3GetVarint(&zBuf[j], &x); | |
| 107163 | + assert(j<=nBuf); | |
| 107164 | + a[i] = (u32)(x & 0xffffffff); | |
| 107165 | + } | |
| 107166 | +} | |
| 107167 | + | |
| 107168 | +/* | |
| 107169 | +** Fill in the document size auxiliary information for the matchinfo | |
| 107170 | +** structure. The auxiliary information is: | |
| 107171 | +** | |
| 107172 | +** N Total number of documents in the full-text index | |
| 107173 | +** a0 Average length of column 0 over the whole index | |
| 107174 | +** n0 Length of column 0 on the matching row | |
| 107175 | +** ... | |
| 107176 | +** aM Average length of column M over the whole index | |
| 107177 | +** nM Length of column M on the matching row | |
| 107178 | +** | |
| 107179 | +** The fts3MatchinfoDocsizeLocal() routine fills in the nX values. | |
| 107180 | +** The fts3MatchinfoDocsizeGlobal() routine fills in N and the aX values. | |
| 107181 | +*/ | |
| 107182 | +SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor *pCur, u32 *a){ | |
| 107183 | + const char *pBlob; /* The BLOB holding %_docsize info */ | |
| 107184 | + int nBlob; /* Size of the BLOB */ | |
| 107185 | + sqlite3_stmt *pStmt; /* Statement for reading and writing */ | |
| 107186 | + int i, j; /* Loop counters */ | |
| 107187 | + sqlite3_int64 x; /* Varint value */ | |
| 107188 | + int rc; /* Result code from subfunctions */ | |
| 107189 | + Fts3Table *p; /* The FTS table */ | |
| 107190 | + | |
| 107191 | + p = (Fts3Table*)pCur->base.pVtab; | |
| 107192 | + rc = fts3SqlStmt(p, SQL_SELECT_DOCSIZE, &pStmt, 0); | |
| 107193 | + if( rc ){ | |
| 107194 | + return rc; | |
| 107195 | + } | |
| 107196 | + sqlite3_bind_int64(pStmt, 1, pCur->iPrevId); | |
| 107197 | + if( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 107198 | + nBlob = sqlite3_column_bytes(pStmt, 0); | |
| 107199 | + pBlob = (const char*)sqlite3_column_blob(pStmt, 0); | |
| 107200 | + for(i=j=0; i<p->nColumn && j<nBlob; i++){ | |
| 107201 | + j = sqlite3Fts3GetVarint(&pBlob[j], &x); | |
| 107202 | + a[2+i*2] = (u32)(x & 0xffffffff); | |
| 107203 | + } | |
| 107204 | + } | |
| 107205 | + sqlite3_reset(pStmt); | |
| 107206 | + return SQLITE_OK; | |
| 107207 | +} | |
| 107208 | +SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor *pCur, u32 *a){ | |
| 107209 | + const char *pBlob; /* The BLOB holding %_stat info */ | |
| 107210 | + int nBlob; /* Size of the BLOB */ | |
| 107211 | + sqlite3_stmt *pStmt; /* Statement for reading and writing */ | |
| 107212 | + int i, j; /* Loop counters */ | |
| 107213 | + sqlite3_int64 x; /* Varint value */ | |
| 107214 | + int nDoc; /* Number of documents */ | |
| 107215 | + int rc; /* Result code from subfunctions */ | |
| 107216 | + Fts3Table *p; /* The FTS table */ | |
| 107217 | + | |
| 107218 | + p = (Fts3Table*)pCur->base.pVtab; | |
| 107219 | + rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0); | |
| 107220 | + if( rc ){ | |
| 107221 | + return rc; | |
| 107222 | + } | |
| 107223 | + if( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 107224 | + nBlob = sqlite3_column_bytes(pStmt, 0); | |
| 107225 | + pBlob = (const char*)sqlite3_column_blob(pStmt, 0); | |
| 107226 | + j = sqlite3Fts3GetVarint(pBlob, &x); | |
| 107227 | + a[0] = nDoc = (u32)(x & 0xffffffff); | |
| 107228 | + for(i=0; i<p->nColumn && j<nBlob; i++){ | |
| 107229 | + j = sqlite3Fts3GetVarint(&pBlob[j], &x); | |
| 107230 | + a[1+i*2] = ((u32)(x & 0xffffffff) + nDoc/2)/nDoc; | |
| 107231 | + } | |
| 107232 | + } | |
| 107233 | + sqlite3_reset(pStmt); | |
| 107234 | + return SQLITE_OK; | |
| 107235 | +} | |
| 107236 | + | |
| 107237 | +/* | |
| 107238 | +** Insert the sizes (in tokens) for each column of the document | |
| 107239 | +** with docid equal to p->iPrevDocid. The sizes are encoded as | |
| 107240 | +** a blob of varints. | |
| 107241 | +*/ | |
| 107242 | +static void fts3InsertDocsize( | |
| 107243 | + int *pRC, /* Result code */ | |
| 107244 | + Fts3Table *p, /* Table into which to insert */ | |
| 107245 | + u32 *aSz /* Sizes of each column */ | |
| 107246 | +){ | |
| 107247 | + char *pBlob; /* The BLOB encoding of the document size */ | |
| 107248 | + int nBlob; /* Number of bytes in the BLOB */ | |
| 107249 | + sqlite3_stmt *pStmt; /* Statement used to insert the encoding */ | |
| 107250 | + int rc; /* Result code from subfunctions */ | |
| 107251 | + | |
| 107252 | + if( *pRC ) return; | |
| 107253 | + pBlob = sqlite3_malloc( 10*p->nColumn ); | |
| 107254 | + if( pBlob==0 ){ | |
| 107255 | + *pRC = SQLITE_NOMEM; | |
| 107256 | + return; | |
| 107257 | + } | |
| 107258 | + fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob); | |
| 107259 | + rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0); | |
| 107260 | + if( rc ){ | |
| 107261 | + sqlite3_free(pBlob); | |
| 107262 | + *pRC = rc; | |
| 107263 | + return; | |
| 107264 | + } | |
| 107265 | + sqlite3_bind_int64(pStmt, 1, p->iPrevDocid); | |
| 107266 | + sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free); | |
| 107267 | + sqlite3_step(pStmt); | |
| 107268 | + *pRC = sqlite3_reset(pStmt); | |
| 107269 | +} | |
| 107270 | + | |
| 107271 | +/* | |
| 107272 | +** Update the 0 record of the %_stat table so that it holds a blob | |
| 107273 | +** which contains the document count followed by the cumulative | |
| 107274 | +** document sizes for all columns. | |
| 107275 | +*/ | |
| 107276 | +static void fts3UpdateDocTotals( | |
| 107277 | + int *pRC, /* The result code */ | |
| 107278 | + Fts3Table *p, /* Table being updated */ | |
| 107279 | + u32 *aSzIns, /* Size increases */ | |
| 107280 | + u32 *aSzDel, /* Size decreases */ | |
| 107281 | + int nChng /* Change in the number of documents */ | |
| 107282 | +){ | |
| 107283 | + char *pBlob; /* Storage for BLOB written into %_stat */ | |
| 107284 | + int nBlob; /* Size of BLOB written into %_stat */ | |
| 107285 | + u32 *a; /* Array of integers that becomes the BLOB */ | |
| 107286 | + sqlite3_stmt *pStmt; /* Statement for reading and writing */ | |
| 107287 | + int i; /* Loop counter */ | |
| 107288 | + int rc; /* Result code from subfunctions */ | |
| 107289 | + | |
| 107290 | + if( *pRC ) return; | |
| 107291 | + a = sqlite3_malloc( (sizeof(u32)+10)*(p->nColumn+1) ); | |
| 107292 | + if( a==0 ){ | |
| 107293 | + *pRC = SQLITE_NOMEM; | |
| 107294 | + return; | |
| 107295 | + } | |
| 107296 | + pBlob = (char*)&a[p->nColumn+1]; | |
| 107297 | + rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0); | |
| 107298 | + if( rc ){ | |
| 107299 | + sqlite3_free(a); | |
| 107300 | + *pRC = rc; | |
| 107301 | + return; | |
| 107302 | + } | |
| 107303 | + if( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 107304 | + fts3DecodeIntArray(p->nColumn+1, a, | |
| 107305 | + sqlite3_column_blob(pStmt, 0), | |
| 107306 | + sqlite3_column_bytes(pStmt, 0)); | |
| 107307 | + }else{ | |
| 107308 | + memset(a, 0, sizeof(u32)*(p->nColumn+1) ); | |
| 107309 | + } | |
| 107310 | + sqlite3_reset(pStmt); | |
| 107311 | + if( nChng<0 && a[0]<(u32)(-nChng) ){ | |
| 107312 | + a[0] = 0; | |
| 107313 | + }else{ | |
| 107314 | + a[0] += nChng; | |
| 107315 | + } | |
| 107316 | + for(i=0; i<p->nColumn; i++){ | |
| 107317 | + u32 x = a[i+1]; | |
| 107318 | + if( x+aSzIns[i] < aSzDel[i] ){ | |
| 107319 | + x = 0; | |
| 107320 | + }else{ | |
| 107321 | + x = x + aSzIns[i] - aSzDel[i]; | |
| 107322 | + } | |
| 107323 | + a[i+1] = x; | |
| 107324 | + } | |
| 107325 | + fts3EncodeIntArray(p->nColumn+1, a, pBlob, &nBlob); | |
| 107326 | + rc = fts3SqlStmt(p, SQL_REPLACE_DOCTOTAL, &pStmt, 0); | |
| 107327 | + if( rc ){ | |
| 107328 | + sqlite3_free(a); | |
| 107329 | + *pRC = rc; | |
| 107330 | + return; | |
| 107331 | + } | |
| 107332 | + sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC); | |
| 107333 | + sqlite3_step(pStmt); | |
| 107334 | + *pRC = sqlite3_reset(pStmt); | |
| 107335 | + sqlite3_free(a); | |
| 107336 | +} | |
| 105753 | 107337 | |
| 105754 | 107338 | /* |
| 105755 | 107339 | ** Handle a 'special' INSERT of the form: |
| 105756 | 107340 | ** |
| 105757 | 107341 | ** "INSERT INTO tbl(tbl) VALUES(<expr>)" |
| @@ -105800,11 +107384,20 @@ | ||
| 105800 | 107384 | ){ |
| 105801 | 107385 | Fts3Table *p = (Fts3Table *)pVtab; |
| 105802 | 107386 | int rc = SQLITE_OK; /* Return Code */ |
| 105803 | 107387 | int isRemove = 0; /* True for an UPDATE or DELETE */ |
| 105804 | 107388 | sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */ |
| 107389 | + u32 *aSzIns; /* Sizes of inserted documents */ | |
| 107390 | + u32 *aSzDel; /* Sizes of deleted documents */ | |
| 107391 | + int nChng = 0; /* Net change in number of documents */ | |
| 105805 | 107392 | |
| 107393 | + | |
| 107394 | + /* Allocate space to hold the change in document sizes */ | |
| 107395 | + aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*p->nColumn*2 ); | |
| 107396 | + if( aSzIns==0 ) return SQLITE_NOMEM; | |
| 107397 | + aSzDel = &aSzIns[p->nColumn]; | |
| 107398 | + memset(aSzIns, 0, sizeof(aSzIns[0])*p->nColumn*2); | |
| 105806 | 107399 | |
| 105807 | 107400 | /* If this is a DELETE or UPDATE operation, remove the old record. */ |
| 105808 | 107401 | if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 105809 | 107402 | int isEmpty; |
| 105810 | 107403 | rc = fts3IsEmpty(p, apVal, &isEmpty); |
| @@ -105817,19 +107410,20 @@ | ||
| 105817 | 107410 | rc = fts3DeleteAll(p); |
| 105818 | 107411 | }else{ |
| 105819 | 107412 | isRemove = 1; |
| 105820 | 107413 | iRemove = sqlite3_value_int64(apVal[0]); |
| 105821 | 107414 | rc = fts3PendingTermsDocid(p, iRemove); |
| 105822 | - if( rc==SQLITE_OK ){ | |
| 105823 | - rc = fts3DeleteTerms(p, apVal); | |
| 105824 | - if( rc==SQLITE_OK ){ | |
| 105825 | - rc = fts3SqlExec(p, SQL_DELETE_CONTENT, apVal); | |
| 105826 | - } | |
| 107415 | + fts3DeleteTerms(&rc, p, apVal, aSzDel); | |
| 107416 | + fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, apVal); | |
| 107417 | + if( p->bHasDocsize ){ | |
| 107418 | + fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, apVal); | |
| 107419 | + nChng--; | |
| 105827 | 107420 | } |
| 105828 | 107421 | } |
| 105829 | 107422 | } |
| 105830 | 107423 | }else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){ |
| 107424 | + sqlite3_free(aSzIns); | |
| 105831 | 107425 | return fts3SpecialInsert(p, apVal[p->nColumn+2]); |
| 105832 | 107426 | } |
| 105833 | 107427 | |
| 105834 | 107428 | /* If this is an INSERT or UPDATE operation, insert the new record. */ |
| 105835 | 107429 | if( nArg>1 && rc==SQLITE_OK ){ |
| @@ -105836,14 +107430,23 @@ | ||
| 105836 | 107430 | rc = fts3InsertData(p, apVal, pRowid); |
| 105837 | 107431 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){ |
| 105838 | 107432 | rc = fts3PendingTermsDocid(p, *pRowid); |
| 105839 | 107433 | } |
| 105840 | 107434 | if( rc==SQLITE_OK ){ |
| 105841 | - rc = fts3InsertTerms(p, apVal); | |
| 107435 | + rc = fts3InsertTerms(p, apVal, aSzIns); | |
| 107436 | + } | |
| 107437 | + if( p->bHasDocsize ){ | |
| 107438 | + nChng++; | |
| 107439 | + fts3InsertDocsize(&rc, p, aSzIns); | |
| 105842 | 107440 | } |
| 105843 | 107441 | } |
| 105844 | 107442 | |
| 107443 | + if( p->bHasDocsize ){ | |
| 107444 | + fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); | |
| 107445 | + } | |
| 107446 | + | |
| 107447 | + sqlite3_free(aSzIns); | |
| 105845 | 107448 | return rc; |
| 105846 | 107449 | } |
| 105847 | 107450 | |
| 105848 | 107451 | /* |
| 105849 | 107452 | ** Flush any data in the pending-terms hash table to disk. If successful, |
| @@ -105886,736 +107489,131 @@ | ||
| 105886 | 107489 | */ |
| 105887 | 107490 | |
| 105888 | 107491 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 105889 | 107492 | |
| 105890 | 107493 | |
| 105891 | -typedef struct Snippet Snippet; | |
| 105892 | 107494 | |
| 105893 | 107495 | /* |
| 105894 | -** An instance of the following structure keeps track of generated | |
| 105895 | -** matching-word offset information and snippets. | |
| 107496 | +** Used as an fts3ExprIterate() context when loading phrase doclists to | |
| 107497 | +** Fts3Expr.aDoclist[]/nDoclist. | |
| 105896 | 107498 | */ |
| 105897 | -struct Snippet { | |
| 105898 | - int nMatch; /* Total number of matches */ | |
| 105899 | - int nAlloc; /* Space allocated for aMatch[] */ | |
| 105900 | - struct snippetMatch { /* One entry for each matching term */ | |
| 105901 | - char snStatus; /* Status flag for use while constructing snippets */ | |
| 105902 | - short int nByte; /* Number of bytes in the term */ | |
| 105903 | - short int iCol; /* The column that contains the match */ | |
| 105904 | - short int iTerm; /* The index in Query.pTerms[] of the matching term */ | |
| 105905 | - int iToken; /* The index of the matching document token */ | |
| 105906 | - int iStart; /* The offset to the first character of the term */ | |
| 105907 | - } *aMatch; /* Points to space obtained from malloc */ | |
| 105908 | - char *zOffset; /* Text rendering of aMatch[] */ | |
| 105909 | - int nOffset; /* strlen(zOffset) */ | |
| 105910 | - char *zSnippet; /* Snippet text */ | |
| 105911 | - int nSnippet; /* strlen(zSnippet) */ | |
| 107499 | +typedef struct LoadDoclistCtx LoadDoclistCtx; | |
| 107500 | +struct LoadDoclistCtx { | |
| 107501 | + Fts3Table *pTab; /* FTS3 Table */ | |
| 107502 | + int nPhrase; /* Number of phrases seen so far */ | |
| 107503 | + int nToken; /* Number of tokens seen so far */ | |
| 107504 | +}; | |
| 107505 | + | |
| 107506 | +/* | |
| 107507 | +** The following types are used as part of the implementation of the | |
| 107508 | +** fts3BestSnippet() routine. | |
| 107509 | +*/ | |
| 107510 | +typedef struct SnippetIter SnippetIter; | |
| 107511 | +typedef struct SnippetPhrase SnippetPhrase; | |
| 107512 | +typedef struct SnippetFragment SnippetFragment; | |
| 107513 | + | |
| 107514 | +struct SnippetIter { | |
| 107515 | + Fts3Cursor *pCsr; /* Cursor snippet is being generated from */ | |
| 107516 | + int iCol; /* Extract snippet from this column */ | |
| 107517 | + int nSnippet; /* Requested snippet length (in tokens) */ | |
| 107518 | + int nPhrase; /* Number of phrases in query */ | |
| 107519 | + SnippetPhrase *aPhrase; /* Array of size nPhrase */ | |
| 107520 | + int iCurrent; /* First token of current snippet */ | |
| 107521 | +}; | |
| 107522 | + | |
| 107523 | +struct SnippetPhrase { | |
| 107524 | + int nToken; /* Number of tokens in phrase */ | |
| 107525 | + char *pList; /* Pointer to start of phrase position list */ | |
| 107526 | + int iHead; /* Next value in position list */ | |
| 107527 | + char *pHead; /* Position list data following iHead */ | |
| 107528 | + int iTail; /* Next value in trailing position list */ | |
| 107529 | + char *pTail; /* Position list data following iTail */ | |
| 107530 | +}; | |
| 107531 | + | |
| 107532 | +struct SnippetFragment { | |
| 107533 | + int iCol; /* Column snippet is extracted from */ | |
| 107534 | + int iPos; /* Index of first token in snippet */ | |
| 107535 | + u64 covered; /* Mask of query phrases covered */ | |
| 107536 | + u64 hlmask; /* Mask of snippet terms to highlight */ | |
| 107537 | +}; | |
| 107538 | + | |
| 107539 | +/* | |
| 107540 | +** This type is used as an fts3ExprIterate() context object while | |
| 107541 | +** accumulating the data returned by the matchinfo() function. | |
| 107542 | +*/ | |
| 107543 | +typedef struct MatchInfo MatchInfo; | |
| 107544 | +struct MatchInfo { | |
| 107545 | + Fts3Cursor *pCursor; /* FTS3 Cursor */ | |
| 107546 | + int nCol; /* Number of columns in table */ | |
| 107547 | + u32 *aMatchinfo; /* Pre-allocated buffer */ | |
| 107548 | +}; | |
| 107549 | + | |
| 107550 | + | |
| 107551 | + | |
| 107552 | +/* | |
| 107553 | +** The snippet() and offsets() functions both return text values. An instance | |
| 107554 | +** of the following structure is used to accumulate those values while the | |
| 107555 | +** functions are running. See fts3StringAppend() for details. | |
| 107556 | +*/ | |
| 107557 | +typedef struct StrBuffer StrBuffer; | |
| 107558 | +struct StrBuffer { | |
| 107559 | + char *z; /* Pointer to buffer containing string */ | |
| 107560 | + int n; /* Length of z in bytes (excl. nul-term) */ | |
| 107561 | + int nAlloc; /* Allocated size of buffer z in bytes */ | |
| 105912 | 107562 | }; |
| 105913 | 107563 | |
| 105914 | 107564 | |
| 105915 | -/* It is not safe to call isspace(), tolower(), or isalnum() on | |
| 105916 | -** hi-bit-set characters. This is the same solution used in the | |
| 105917 | -** tokenizer. | |
| 105918 | -*/ | |
| 105919 | -static int fts3snippetIsspace(char c){ | |
| 105920 | - return (c&0x80)==0 ? isspace(c) : 0; | |
| 105921 | -} | |
| 105922 | - | |
| 105923 | - | |
| 105924 | -/* | |
| 105925 | -** A StringBuffer object holds a zero-terminated string that grows | |
| 105926 | -** arbitrarily by appending. Space to hold the string is obtained | |
| 105927 | -** from sqlite3_malloc(). After any memory allocation failure, | |
| 105928 | -** StringBuffer.z is set to NULL and no further allocation is attempted. | |
| 105929 | -*/ | |
| 105930 | -typedef struct StringBuffer { | |
| 105931 | - char *z; /* Text of the string. Space from malloc. */ | |
| 105932 | - int nUsed; /* Number bytes of z[] used, not counting \000 terminator */ | |
| 105933 | - int nAlloc; /* Bytes allocated for z[] */ | |
| 105934 | -} StringBuffer; | |
| 105935 | - | |
| 105936 | - | |
| 105937 | -/* | |
| 105938 | -** Initialize a new StringBuffer. | |
| 105939 | -*/ | |
| 105940 | -static void fts3SnippetSbInit(StringBuffer *p){ | |
| 105941 | - p->nAlloc = 100; | |
| 105942 | - p->nUsed = 0; | |
| 105943 | - p->z = sqlite3_malloc( p->nAlloc ); | |
| 105944 | -} | |
| 105945 | - | |
| 105946 | -/* | |
| 105947 | -** Append text to the string buffer. | |
| 105948 | -*/ | |
| 105949 | -static void fts3SnippetAppend(StringBuffer *p, const char *zNew, int nNew){ | |
| 105950 | - if( p->z==0 ) return; | |
| 105951 | - if( nNew<0 ) nNew = (int)strlen(zNew); | |
| 105952 | - if( p->nUsed + nNew >= p->nAlloc ){ | |
| 105953 | - int nAlloc; | |
| 105954 | - char *zNew; | |
| 105955 | - | |
| 105956 | - nAlloc = p->nUsed + nNew + p->nAlloc; | |
| 105957 | - zNew = sqlite3_realloc(p->z, nAlloc); | |
| 105958 | - if( zNew==0 ){ | |
| 105959 | - sqlite3_free(p->z); | |
| 105960 | - p->z = 0; | |
| 105961 | - return; | |
| 105962 | - } | |
| 105963 | - p->z = zNew; | |
| 105964 | - p->nAlloc = nAlloc; | |
| 105965 | - } | |
| 105966 | - memcpy(&p->z[p->nUsed], zNew, nNew); | |
| 105967 | - p->nUsed += nNew; | |
| 105968 | - p->z[p->nUsed] = 0; | |
| 105969 | -} | |
| 105970 | - | |
| 105971 | -/* If the StringBuffer ends in something other than white space, add a | |
| 105972 | -** single space character to the end. | |
| 105973 | -*/ | |
| 105974 | -static void fts3SnippetAppendWhiteSpace(StringBuffer *p){ | |
| 105975 | - if( p->z && p->nUsed && !fts3snippetIsspace(p->z[p->nUsed-1]) ){ | |
| 105976 | - fts3SnippetAppend(p, " ", 1); | |
| 105977 | - } | |
| 105978 | -} | |
| 105979 | - | |
| 105980 | -/* Remove white space from the end of the StringBuffer */ | |
| 105981 | -static void fts3SnippetTrimWhiteSpace(StringBuffer *p){ | |
| 105982 | - if( p->z ){ | |
| 105983 | - while( p->nUsed && fts3snippetIsspace(p->z[p->nUsed-1]) ){ | |
| 105984 | - p->nUsed--; | |
| 105985 | - } | |
| 105986 | - p->z[p->nUsed] = 0; | |
| 105987 | - } | |
| 105988 | -} | |
| 105989 | - | |
| 105990 | -/* | |
| 105991 | -** Release all memory associated with the Snippet structure passed as | |
| 105992 | -** an argument. | |
| 105993 | -*/ | |
| 105994 | -static void fts3SnippetFree(Snippet *p){ | |
| 105995 | - if( p ){ | |
| 105996 | - sqlite3_free(p->aMatch); | |
| 105997 | - sqlite3_free(p->zOffset); | |
| 105998 | - sqlite3_free(p->zSnippet); | |
| 105999 | - sqlite3_free(p); | |
| 106000 | - } | |
| 106001 | -} | |
| 106002 | - | |
| 106003 | -/* | |
| 106004 | -** Append a single entry to the p->aMatch[] log. | |
| 106005 | -*/ | |
| 106006 | -static int snippetAppendMatch( | |
| 106007 | - Snippet *p, /* Append the entry to this snippet */ | |
| 106008 | - int iCol, int iTerm, /* The column and query term */ | |
| 106009 | - int iToken, /* Matching token in document */ | |
| 106010 | - int iStart, int nByte /* Offset and size of the match */ | |
| 106011 | -){ | |
| 106012 | - int i; | |
| 106013 | - struct snippetMatch *pMatch; | |
| 106014 | - if( p->nMatch+1>=p->nAlloc ){ | |
| 106015 | - struct snippetMatch *pNew; | |
| 106016 | - p->nAlloc = p->nAlloc*2 + 10; | |
| 106017 | - pNew = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); | |
| 106018 | - if( pNew==0 ){ | |
| 106019 | - p->aMatch = 0; | |
| 106020 | - p->nMatch = 0; | |
| 106021 | - p->nAlloc = 0; | |
| 106022 | - return SQLITE_NOMEM; | |
| 106023 | - } | |
| 106024 | - p->aMatch = pNew; | |
| 106025 | - } | |
| 106026 | - i = p->nMatch++; | |
| 106027 | - pMatch = &p->aMatch[i]; | |
| 106028 | - pMatch->iCol = (short)iCol; | |
| 106029 | - pMatch->iTerm = (short)iTerm; | |
| 106030 | - pMatch->iToken = iToken; | |
| 106031 | - pMatch->iStart = iStart; | |
| 106032 | - pMatch->nByte = (short)nByte; | |
| 106033 | - return SQLITE_OK; | |
| 106034 | -} | |
| 106035 | - | |
| 106036 | -/* | |
| 106037 | -** Sizing information for the circular buffer used in snippetOffsetsOfColumn() | |
| 106038 | -*/ | |
| 106039 | -#define FTS3_ROTOR_SZ (32) | |
| 106040 | -#define FTS3_ROTOR_MASK (FTS3_ROTOR_SZ-1) | |
| 106041 | - | |
| 106042 | -/* | |
| 106043 | -** Function to iterate through the tokens of a compiled expression. | |
| 106044 | -** | |
| 106045 | -** Except, skip all tokens on the right-hand side of a NOT operator. | |
| 106046 | -** This function is used to find tokens as part of snippet and offset | |
| 106047 | -** generation and we do nt want snippets and offsets to report matches | |
| 106048 | -** for tokens on the RHS of a NOT. | |
| 106049 | -*/ | |
| 106050 | -static int fts3NextExprToken(Fts3Expr **ppExpr, int *piToken){ | |
| 106051 | - Fts3Expr *p = *ppExpr; | |
| 106052 | - int iToken = *piToken; | |
| 106053 | - if( iToken<0 ){ | |
| 106054 | - /* In this case the expression p is the root of an expression tree. | |
| 106055 | - ** Move to the first token in the expression tree. | |
| 106056 | - */ | |
| 106057 | - while( p->pLeft ){ | |
| 106058 | - p = p->pLeft; | |
| 106059 | - } | |
| 106060 | - iToken = 0; | |
| 106061 | - }else{ | |
| 106062 | - assert(p && p->eType==FTSQUERY_PHRASE ); | |
| 106063 | - if( iToken<(p->pPhrase->nToken-1) ){ | |
| 106064 | - iToken++; | |
| 106065 | - }else{ | |
| 106066 | - iToken = 0; | |
| 106067 | - while( p->pParent && p->pParent->pLeft!=p ){ | |
| 106068 | - assert( p->pParent->pRight==p ); | |
| 106069 | - p = p->pParent; | |
| 106070 | - } | |
| 106071 | - p = p->pParent; | |
| 106072 | - if( p ){ | |
| 106073 | - assert( p->pRight!=0 ); | |
| 106074 | - p = p->pRight; | |
| 106075 | - while( p->pLeft ){ | |
| 106076 | - p = p->pLeft; | |
| 106077 | - } | |
| 106078 | - } | |
| 106079 | - } | |
| 106080 | - } | |
| 106081 | - | |
| 106082 | - *ppExpr = p; | |
| 106083 | - *piToken = iToken; | |
| 106084 | - return p?1:0; | |
| 106085 | -} | |
| 106086 | - | |
| 106087 | -/* | |
| 106088 | -** Return TRUE if the expression node pExpr is located beneath the | |
| 106089 | -** RHS of a NOT operator. | |
| 106090 | -*/ | |
| 106091 | -static int fts3ExprBeneathNot(Fts3Expr *p){ | |
| 106092 | - Fts3Expr *pParent; | |
| 106093 | - while( p ){ | |
| 106094 | - pParent = p->pParent; | |
| 106095 | - if( pParent && pParent->eType==FTSQUERY_NOT && pParent->pRight==p ){ | |
| 106096 | - return 1; | |
| 106097 | - } | |
| 106098 | - p = pParent; | |
| 106099 | - } | |
| 106100 | - return 0; | |
| 106101 | -} | |
| 106102 | - | |
| 106103 | -/* | |
| 106104 | -** Add entries to pSnippet->aMatch[] for every match that occurs against | |
| 106105 | -** document zDoc[0..nDoc-1] which is stored in column iColumn. | |
| 106106 | -*/ | |
| 106107 | -static int snippetOffsetsOfColumn( | |
| 106108 | - Fts3Cursor *pCur, /* The fulltest search cursor */ | |
| 106109 | - Snippet *pSnippet, /* The Snippet object to be filled in */ | |
| 106110 | - int iColumn, /* Index of fulltext table column */ | |
| 106111 | - const char *zDoc, /* Text of the fulltext table column */ | |
| 106112 | - int nDoc /* Length of zDoc in bytes */ | |
| 106113 | -){ | |
| 106114 | - const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */ | |
| 106115 | - sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */ | |
| 106116 | - sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */ | |
| 106117 | - Fts3Table *pVtab; /* The full text index */ | |
| 106118 | - int nColumn; /* Number of columns in the index */ | |
| 106119 | - int i, j; /* Loop counters */ | |
| 106120 | - int rc; /* Return code */ | |
| 106121 | - unsigned int match, prevMatch; /* Phrase search bitmasks */ | |
| 106122 | - const char *zToken; /* Next token from the tokenizer */ | |
| 106123 | - int nToken; /* Size of zToken */ | |
| 106124 | - int iBegin, iEnd, iPos; /* Offsets of beginning and end */ | |
| 106125 | - | |
| 106126 | - /* The following variables keep a circular buffer of the last | |
| 106127 | - ** few tokens */ | |
| 106128 | - unsigned int iRotor = 0; /* Index of current token */ | |
| 106129 | - int iRotorBegin[FTS3_ROTOR_SZ]; /* Beginning offset of token */ | |
| 106130 | - int iRotorLen[FTS3_ROTOR_SZ]; /* Length of token */ | |
| 106131 | - | |
| 106132 | - pVtab = (Fts3Table *)pCur->base.pVtab; | |
| 106133 | - nColumn = pVtab->nColumn; | |
| 106134 | - pTokenizer = pVtab->pTokenizer; | |
| 106135 | - pTModule = pTokenizer->pModule; | |
| 106136 | - rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor); | |
| 106137 | - if( rc ) return rc; | |
| 106138 | - pTCursor->pTokenizer = pTokenizer; | |
| 106139 | - | |
| 106140 | - prevMatch = 0; | |
| 106141 | - while( (rc = pTModule->xNext(pTCursor, &zToken, &nToken, | |
| 106142 | - &iBegin, &iEnd, &iPos))==SQLITE_OK ){ | |
| 106143 | - Fts3Expr *pIter = pCur->pExpr; | |
| 106144 | - int iIter = -1; | |
| 106145 | - iRotorBegin[iRotor&FTS3_ROTOR_MASK] = iBegin; | |
| 106146 | - iRotorLen[iRotor&FTS3_ROTOR_MASK] = iEnd-iBegin; | |
| 106147 | - match = 0; | |
| 106148 | - for(i=0; i<(FTS3_ROTOR_SZ-1) && fts3NextExprToken(&pIter, &iIter); i++){ | |
| 106149 | - int nPhrase; /* Number of tokens in current phrase */ | |
| 106150 | - struct PhraseToken *pToken; /* Current token */ | |
| 106151 | - int iCol; /* Column index */ | |
| 106152 | - | |
| 106153 | - if( fts3ExprBeneathNot(pIter) ) continue; | |
| 106154 | - nPhrase = pIter->pPhrase->nToken; | |
| 106155 | - pToken = &pIter->pPhrase->aToken[iIter]; | |
| 106156 | - iCol = pIter->pPhrase->iColumn; | |
| 106157 | - if( iCol>=0 && iCol<nColumn && iCol!=iColumn ) continue; | |
| 106158 | - if( pToken->n>nToken ) continue; | |
| 106159 | - if( !pToken->isPrefix && pToken->n<nToken ) continue; | |
| 106160 | - assert( pToken->n<=nToken ); | |
| 106161 | - if( memcmp(pToken->z, zToken, pToken->n) ) continue; | |
| 106162 | - if( iIter>0 && (prevMatch & (1<<i))==0 ) continue; | |
| 106163 | - match |= 1<<i; | |
| 106164 | - if( i==(FTS3_ROTOR_SZ-2) || nPhrase==iIter+1 ){ | |
| 106165 | - for(j=nPhrase-1; j>=0; j--){ | |
| 106166 | - int k = (iRotor-j) & FTS3_ROTOR_MASK; | |
| 106167 | - rc = snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j, | |
| 106168 | - iRotorBegin[k], iRotorLen[k]); | |
| 106169 | - if( rc ) goto end_offsets_of_column; | |
| 106170 | - } | |
| 106171 | - } | |
| 106172 | - } | |
| 106173 | - prevMatch = match<<1; | |
| 106174 | - iRotor++; | |
| 106175 | - } | |
| 106176 | -end_offsets_of_column: | |
| 106177 | - pTModule->xClose(pTCursor); | |
| 106178 | - return rc==SQLITE_DONE ? SQLITE_OK : rc; | |
| 106179 | -} | |
| 106180 | - | |
| 106181 | -/* | |
| 106182 | -** Remove entries from the pSnippet structure to account for the NEAR | |
| 106183 | -** operator. When this is called, pSnippet contains the list of token | |
| 106184 | -** offsets produced by treating all NEAR operators as AND operators. | |
| 106185 | -** This function removes any entries that should not be present after | |
| 106186 | -** accounting for the NEAR restriction. For example, if the queried | |
| 106187 | -** document is: | |
| 106188 | -** | |
| 106189 | -** "A B C D E A" | |
| 106190 | -** | |
| 106191 | -** and the query is: | |
| 106192 | -** | |
| 106193 | -** A NEAR/0 E | |
| 106194 | -** | |
| 106195 | -** then when this function is called the Snippet contains token offsets | |
| 106196 | -** 0, 4 and 5. This function removes the "0" entry (because the first A | |
| 106197 | -** is not near enough to an E). | |
| 106198 | -** | |
| 106199 | -** When this function is called, the value pointed to by parameter piLeft is | |
| 106200 | -** the integer id of the left-most token in the expression tree headed by | |
| 106201 | -** pExpr. This function increments *piLeft by the total number of tokens | |
| 106202 | -** in the expression tree headed by pExpr. | |
| 106203 | -** | |
| 106204 | -** Return 1 if any trimming occurs. Return 0 if no trimming is required. | |
| 106205 | -*/ | |
| 106206 | -static int trimSnippetOffsets( | |
| 106207 | - Fts3Expr *pExpr, /* The search expression */ | |
| 106208 | - Snippet *pSnippet, /* The set of snippet offsets to be trimmed */ | |
| 106209 | - int *piLeft /* Index of left-most token in pExpr */ | |
| 106210 | -){ | |
| 106211 | - if( pExpr ){ | |
| 106212 | - if( trimSnippetOffsets(pExpr->pLeft, pSnippet, piLeft) ){ | |
| 106213 | - return 1; | |
| 106214 | - } | |
| 106215 | - | |
| 106216 | - switch( pExpr->eType ){ | |
| 106217 | - case FTSQUERY_PHRASE: | |
| 106218 | - *piLeft += pExpr->pPhrase->nToken; | |
| 106219 | - break; | |
| 106220 | - case FTSQUERY_NEAR: { | |
| 106221 | - /* The right-hand-side of a NEAR operator is always a phrase. The | |
| 106222 | - ** left-hand-side is either a phrase or an expression tree that is | |
| 106223 | - ** itself headed by a NEAR operator. The following initializations | |
| 106224 | - ** set local variable iLeft to the token number of the left-most | |
| 106225 | - ** token in the right-hand phrase, and iRight to the right most | |
| 106226 | - ** token in the same phrase. For example, if we had: | |
| 106227 | - ** | |
| 106228 | - ** <col> MATCH '"abc def" NEAR/2 "ghi jkl"' | |
| 106229 | - ** | |
| 106230 | - ** then iLeft will be set to 2 (token number of ghi) and nToken will | |
| 106231 | - ** be set to 4. | |
| 106232 | - */ | |
| 106233 | - Fts3Expr *pLeft = pExpr->pLeft; | |
| 106234 | - Fts3Expr *pRight = pExpr->pRight; | |
| 106235 | - int iLeft = *piLeft; | |
| 106236 | - int nNear = pExpr->nNear; | |
| 106237 | - int nToken = pRight->pPhrase->nToken; | |
| 106238 | - int jj, ii; | |
| 106239 | - if( pLeft->eType==FTSQUERY_NEAR ){ | |
| 106240 | - pLeft = pLeft->pRight; | |
| 106241 | - } | |
| 106242 | - assert( pRight->eType==FTSQUERY_PHRASE ); | |
| 106243 | - assert( pLeft->eType==FTSQUERY_PHRASE ); | |
| 106244 | - nToken += pLeft->pPhrase->nToken; | |
| 106245 | - | |
| 106246 | - for(ii=0; ii<pSnippet->nMatch; ii++){ | |
| 106247 | - struct snippetMatch *p = &pSnippet->aMatch[ii]; | |
| 106248 | - if( p->iTerm==iLeft ){ | |
| 106249 | - int isOk = 0; | |
| 106250 | - /* Snippet ii is an occurence of query term iLeft in the document. | |
| 106251 | - ** It occurs at position (p->iToken) of the document. We now | |
| 106252 | - ** search for an instance of token (iLeft-1) somewhere in the | |
| 106253 | - ** range (p->iToken - nNear)...(p->iToken + nNear + nToken) within | |
| 106254 | - ** the set of snippetMatch structures. If one is found, proceed. | |
| 106255 | - ** If one cannot be found, then remove snippets ii..(ii+N-1) | |
| 106256 | - ** from the matching snippets, where N is the number of tokens | |
| 106257 | - ** in phrase pRight->pPhrase. | |
| 106258 | - */ | |
| 106259 | - for(jj=0; isOk==0 && jj<pSnippet->nMatch; jj++){ | |
| 106260 | - struct snippetMatch *p2 = &pSnippet->aMatch[jj]; | |
| 106261 | - if( p2->iTerm==(iLeft-1) ){ | |
| 106262 | - if( p2->iToken>=(p->iToken-nNear-1) | |
| 106263 | - && p2->iToken<(p->iToken+nNear+nToken) | |
| 106264 | - ){ | |
| 106265 | - isOk = 1; | |
| 106266 | - } | |
| 106267 | - } | |
| 106268 | - } | |
| 106269 | - if( !isOk ){ | |
| 106270 | - int kk; | |
| 106271 | - for(kk=0; kk<pRight->pPhrase->nToken; kk++){ | |
| 106272 | - pSnippet->aMatch[kk+ii].iTerm = -2; | |
| 106273 | - } | |
| 106274 | - return 1; | |
| 106275 | - } | |
| 106276 | - } | |
| 106277 | - if( p->iTerm==(iLeft-1) ){ | |
| 106278 | - int isOk = 0; | |
| 106279 | - for(jj=0; isOk==0 && jj<pSnippet->nMatch; jj++){ | |
| 106280 | - struct snippetMatch *p2 = &pSnippet->aMatch[jj]; | |
| 106281 | - if( p2->iTerm==iLeft ){ | |
| 106282 | - if( p2->iToken<=(p->iToken+nNear+1) | |
| 106283 | - && p2->iToken>(p->iToken-nNear-nToken) | |
| 106284 | - ){ | |
| 106285 | - isOk = 1; | |
| 106286 | - } | |
| 106287 | - } | |
| 106288 | - } | |
| 106289 | - if( !isOk ){ | |
| 106290 | - int kk; | |
| 106291 | - for(kk=0; kk<pLeft->pPhrase->nToken; kk++){ | |
| 106292 | - pSnippet->aMatch[ii-kk].iTerm = -2; | |
| 106293 | - } | |
| 106294 | - return 1; | |
| 106295 | - } | |
| 106296 | - } | |
| 106297 | - } | |
| 106298 | - break; | |
| 106299 | - } | |
| 106300 | - } | |
| 106301 | - | |
| 106302 | - if( trimSnippetOffsets(pExpr->pRight, pSnippet, piLeft) ){ | |
| 106303 | - return 1; | |
| 106304 | - } | |
| 106305 | - } | |
| 106306 | - return 0; | |
| 106307 | -} | |
| 106308 | - | |
| 106309 | -/* | |
| 106310 | -** Compute all offsets for the current row of the query. | |
| 106311 | -** If the offsets have already been computed, this routine is a no-op. | |
| 106312 | -*/ | |
| 106313 | -static int snippetAllOffsets(Fts3Cursor *pCsr, Snippet **ppSnippet){ | |
| 106314 | - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; /* The FTS3 virtual table */ | |
| 106315 | - int nColumn; /* Number of columns. Docid does count */ | |
| 106316 | - int iColumn; /* Index of of a column */ | |
| 106317 | - int i; /* Loop index */ | |
| 106318 | - int iFirst; /* First column to search */ | |
| 106319 | - int iLast; /* Last coumn to search */ | |
| 106320 | - int iTerm = 0; | |
| 106321 | - Snippet *pSnippet; | |
| 106322 | - int rc = SQLITE_OK; | |
| 106323 | - | |
| 106324 | - if( pCsr->pExpr==0 ){ | |
| 106325 | - return SQLITE_OK; | |
| 106326 | - } | |
| 106327 | - | |
| 106328 | - pSnippet = (Snippet *)sqlite3_malloc(sizeof(Snippet)); | |
| 106329 | - *ppSnippet = pSnippet; | |
| 106330 | - if( !pSnippet ){ | |
| 106331 | - return SQLITE_NOMEM; | |
| 106332 | - } | |
| 106333 | - memset(pSnippet, 0, sizeof(Snippet)); | |
| 106334 | - | |
| 106335 | - nColumn = p->nColumn; | |
| 106336 | - iColumn = (pCsr->eSearch - 2); | |
| 106337 | - if( iColumn<0 || iColumn>=nColumn ){ | |
| 106338 | - /* Look for matches over all columns of the full-text index */ | |
| 106339 | - iFirst = 0; | |
| 106340 | - iLast = nColumn-1; | |
| 106341 | - }else{ | |
| 106342 | - /* Look for matches in the iColumn-th column of the index only */ | |
| 106343 | - iFirst = iColumn; | |
| 106344 | - iLast = iColumn; | |
| 106345 | - } | |
| 106346 | - for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){ | |
| 106347 | - const char *zDoc; | |
| 106348 | - int nDoc; | |
| 106349 | - zDoc = (const char*)sqlite3_column_text(pCsr->pStmt, i+1); | |
| 106350 | - nDoc = sqlite3_column_bytes(pCsr->pStmt, i+1); | |
| 106351 | - if( zDoc==0 && sqlite3_column_type(pCsr->pStmt, i+1)!=SQLITE_NULL ){ | |
| 106352 | - rc = SQLITE_NOMEM; | |
| 106353 | - }else{ | |
| 106354 | - rc = snippetOffsetsOfColumn(pCsr, pSnippet, i, zDoc, nDoc); | |
| 106355 | - } | |
| 106356 | - } | |
| 106357 | - | |
| 106358 | - while( trimSnippetOffsets(pCsr->pExpr, pSnippet, &iTerm) ){ | |
| 106359 | - iTerm = 0; | |
| 106360 | - } | |
| 106361 | - | |
| 106362 | - return rc; | |
| 106363 | -} | |
| 106364 | - | |
| 106365 | -/* | |
| 106366 | -** Convert the information in the aMatch[] array of the snippet | |
| 106367 | -** into the string zOffset[0..nOffset-1]. This string is used as | |
| 106368 | -** the return of the SQL offsets() function. | |
| 106369 | -*/ | |
| 106370 | -static void snippetOffsetText(Snippet *p){ | |
| 106371 | - int i; | |
| 106372 | - int cnt = 0; | |
| 106373 | - StringBuffer sb; | |
| 106374 | - char zBuf[200]; | |
| 106375 | - if( p->zOffset ) return; | |
| 106376 | - fts3SnippetSbInit(&sb); | |
| 106377 | - for(i=0; i<p->nMatch; i++){ | |
| 106378 | - struct snippetMatch *pMatch = &p->aMatch[i]; | |
| 106379 | - if( pMatch->iTerm>=0 ){ | |
| 106380 | - /* If snippetMatch.iTerm is less than 0, then the match was | |
| 106381 | - ** discarded as part of processing the NEAR operator (see the | |
| 106382 | - ** trimSnippetOffsetsForNear() function for details). Ignore | |
| 106383 | - ** it in this case | |
| 106384 | - */ | |
| 106385 | - zBuf[0] = ' '; | |
| 106386 | - sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d", | |
| 106387 | - pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte); | |
| 106388 | - fts3SnippetAppend(&sb, zBuf, -1); | |
| 106389 | - cnt++; | |
| 106390 | - } | |
| 106391 | - } | |
| 106392 | - p->zOffset = sb.z; | |
| 106393 | - p->nOffset = sb.z ? sb.nUsed : 0; | |
| 106394 | -} | |
| 106395 | - | |
| 106396 | -/* | |
| 106397 | -** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set | |
| 106398 | -** of matching words some of which might be in zDoc. zDoc is column | |
| 106399 | -** number iCol. | |
| 106400 | -** | |
| 106401 | -** iBreak is suggested spot in zDoc where we could begin or end an | |
| 106402 | -** excerpt. Return a value similar to iBreak but possibly adjusted | |
| 106403 | -** to be a little left or right so that the break point is better. | |
| 106404 | -*/ | |
| 106405 | -static int wordBoundary( | |
| 106406 | - int iBreak, /* The suggested break point */ | |
| 106407 | - const char *zDoc, /* Document text */ | |
| 106408 | - int nDoc, /* Number of bytes in zDoc[] */ | |
| 106409 | - struct snippetMatch *aMatch, /* Matching words */ | |
| 106410 | - int nMatch, /* Number of entries in aMatch[] */ | |
| 106411 | - int iCol /* The column number for zDoc[] */ | |
| 106412 | -){ | |
| 106413 | - int i; | |
| 106414 | - if( iBreak<=10 ){ | |
| 106415 | - return 0; | |
| 106416 | - } | |
| 106417 | - if( iBreak>=nDoc-10 ){ | |
| 106418 | - return nDoc; | |
| 106419 | - } | |
| 106420 | - for(i=0; ALWAYS(i<nMatch) && aMatch[i].iCol<iCol; i++){} | |
| 106421 | - while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; } | |
| 106422 | - if( i<nMatch ){ | |
| 106423 | - if( aMatch[i].iStart<iBreak+10 ){ | |
| 106424 | - return aMatch[i].iStart; | |
| 106425 | - } | |
| 106426 | - if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){ | |
| 106427 | - return aMatch[i-1].iStart; | |
| 106428 | - } | |
| 106429 | - } | |
| 106430 | - for(i=1; i<=10; i++){ | |
| 106431 | - if( fts3snippetIsspace(zDoc[iBreak-i]) ){ | |
| 106432 | - return iBreak - i + 1; | |
| 106433 | - } | |
| 106434 | - if( fts3snippetIsspace(zDoc[iBreak+i]) ){ | |
| 106435 | - return iBreak + i + 1; | |
| 106436 | - } | |
| 106437 | - } | |
| 106438 | - return iBreak; | |
| 106439 | -} | |
| 106440 | - | |
| 106441 | - | |
| 106442 | - | |
| 106443 | -/* | |
| 106444 | -** Allowed values for Snippet.aMatch[].snStatus | |
| 106445 | -*/ | |
| 106446 | -#define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */ | |
| 106447 | -#define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */ | |
| 106448 | - | |
| 106449 | -/* | |
| 106450 | -** Generate the text of a snippet. | |
| 106451 | -*/ | |
| 106452 | -static void snippetText( | |
| 106453 | - Fts3Cursor *pCursor, /* The cursor we need the snippet for */ | |
| 106454 | - Snippet *pSnippet, | |
| 106455 | - const char *zStartMark, /* Markup to appear before each match */ | |
| 106456 | - const char *zEndMark, /* Markup to appear after each match */ | |
| 106457 | - const char *zEllipsis /* Ellipsis mark */ | |
| 106458 | -){ | |
| 106459 | - int i, j; | |
| 106460 | - struct snippetMatch *aMatch; | |
| 106461 | - int nMatch; | |
| 106462 | - int nDesired; | |
| 106463 | - StringBuffer sb; | |
| 106464 | - int tailCol; | |
| 106465 | - int tailOffset; | |
| 106466 | - int iCol; | |
| 106467 | - int nDoc; | |
| 106468 | - const char *zDoc; | |
| 106469 | - int iStart, iEnd; | |
| 106470 | - int tailEllipsis = 0; | |
| 106471 | - int iMatch; | |
| 106472 | - | |
| 106473 | - | |
| 106474 | - sqlite3_free(pSnippet->zSnippet); | |
| 106475 | - pSnippet->zSnippet = 0; | |
| 106476 | - aMatch = pSnippet->aMatch; | |
| 106477 | - nMatch = pSnippet->nMatch; | |
| 106478 | - fts3SnippetSbInit(&sb); | |
| 106479 | - | |
| 106480 | - for(i=0; i<nMatch; i++){ | |
| 106481 | - aMatch[i].snStatus = SNIPPET_IGNORE; | |
| 106482 | - } | |
| 106483 | - nDesired = 0; | |
| 106484 | - for(i=0; i<FTS3_ROTOR_SZ; i++){ | |
| 106485 | - for(j=0; j<nMatch; j++){ | |
| 106486 | - if( aMatch[j].iTerm==i ){ | |
| 106487 | - aMatch[j].snStatus = SNIPPET_DESIRED; | |
| 106488 | - nDesired++; | |
| 106489 | - break; | |
| 106490 | - } | |
| 106491 | - } | |
| 106492 | - } | |
| 106493 | - | |
| 106494 | - iMatch = 0; | |
| 106495 | - tailCol = -1; | |
| 106496 | - tailOffset = 0; | |
| 106497 | - for(i=0; i<nMatch && nDesired>0; i++){ | |
| 106498 | - if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue; | |
| 106499 | - nDesired--; | |
| 106500 | - iCol = aMatch[i].iCol; | |
| 106501 | - zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1); | |
| 106502 | - nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1); | |
| 106503 | - iStart = aMatch[i].iStart - 40; | |
| 106504 | - iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol); | |
| 106505 | - if( iStart<=10 ){ | |
| 106506 | - iStart = 0; | |
| 106507 | - } | |
| 106508 | - if( iCol==tailCol && iStart<=tailOffset+20 ){ | |
| 106509 | - iStart = tailOffset; | |
| 106510 | - } | |
| 106511 | - if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){ | |
| 106512 | - fts3SnippetTrimWhiteSpace(&sb); | |
| 106513 | - fts3SnippetAppendWhiteSpace(&sb); | |
| 106514 | - fts3SnippetAppend(&sb, zEllipsis, -1); | |
| 106515 | - fts3SnippetAppendWhiteSpace(&sb); | |
| 106516 | - } | |
| 106517 | - iEnd = aMatch[i].iStart + aMatch[i].nByte + 40; | |
| 106518 | - iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol); | |
| 106519 | - if( iEnd>=nDoc-10 ){ | |
| 106520 | - iEnd = nDoc; | |
| 106521 | - tailEllipsis = 0; | |
| 106522 | - }else{ | |
| 106523 | - tailEllipsis = 1; | |
| 106524 | - } | |
| 106525 | - while( iMatch<nMatch && aMatch[iMatch].iCol<iCol ){ iMatch++; } | |
| 106526 | - while( iStart<iEnd ){ | |
| 106527 | - while( iMatch<nMatch && aMatch[iMatch].iStart<iStart | |
| 106528 | - && aMatch[iMatch].iCol<=iCol ){ | |
| 106529 | - iMatch++; | |
| 106530 | - } | |
| 106531 | - if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd | |
| 106532 | - && aMatch[iMatch].iCol==iCol ){ | |
| 106533 | - fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart); | |
| 106534 | - iStart = aMatch[iMatch].iStart; | |
| 106535 | - fts3SnippetAppend(&sb, zStartMark, -1); | |
| 106536 | - fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].nByte); | |
| 106537 | - fts3SnippetAppend(&sb, zEndMark, -1); | |
| 106538 | - iStart += aMatch[iMatch].nByte; | |
| 106539 | - for(j=iMatch+1; j<nMatch; j++){ | |
| 106540 | - if( aMatch[j].iTerm==aMatch[iMatch].iTerm | |
| 106541 | - && aMatch[j].snStatus==SNIPPET_DESIRED ){ | |
| 106542 | - nDesired--; | |
| 106543 | - aMatch[j].snStatus = SNIPPET_IGNORE; | |
| 106544 | - } | |
| 106545 | - } | |
| 106546 | - }else{ | |
| 106547 | - fts3SnippetAppend(&sb, &zDoc[iStart], iEnd - iStart); | |
| 106548 | - iStart = iEnd; | |
| 106549 | - } | |
| 106550 | - } | |
| 106551 | - tailCol = iCol; | |
| 106552 | - tailOffset = iEnd; | |
| 106553 | - } | |
| 106554 | - fts3SnippetTrimWhiteSpace(&sb); | |
| 106555 | - if( tailEllipsis ){ | |
| 106556 | - fts3SnippetAppendWhiteSpace(&sb); | |
| 106557 | - fts3SnippetAppend(&sb, zEllipsis, -1); | |
| 106558 | - } | |
| 106559 | - pSnippet->zSnippet = sb.z; | |
| 106560 | - pSnippet->nSnippet = sb.z ? sb.nUsed : 0; | |
| 106561 | -} | |
| 106562 | - | |
| 106563 | -SQLITE_PRIVATE void sqlite3Fts3Offsets( | |
| 106564 | - sqlite3_context *pCtx, /* SQLite function call context */ | |
| 106565 | - Fts3Cursor *pCsr /* Cursor object */ | |
| 106566 | -){ | |
| 106567 | - Snippet *p; /* Snippet structure */ | |
| 106568 | - int rc = snippetAllOffsets(pCsr, &p); | |
| 106569 | - if( rc==SQLITE_OK ){ | |
| 106570 | - snippetOffsetText(p); | |
| 106571 | - if( p->zOffset ){ | |
| 106572 | - sqlite3_result_text(pCtx, p->zOffset, p->nOffset, SQLITE_TRANSIENT); | |
| 106573 | - }else{ | |
| 106574 | - sqlite3_result_error_nomem(pCtx); | |
| 106575 | - } | |
| 106576 | - }else{ | |
| 106577 | - sqlite3_result_error_nomem(pCtx); | |
| 106578 | - } | |
| 106579 | - fts3SnippetFree(p); | |
| 106580 | -} | |
| 106581 | - | |
| 106582 | -SQLITE_PRIVATE void sqlite3Fts3Snippet( | |
| 106583 | - sqlite3_context *pCtx, /* SQLite function call context */ | |
| 106584 | - Fts3Cursor *pCsr, /* Cursor object */ | |
| 106585 | - const char *zStart, /* Snippet start text - "<b>" */ | |
| 106586 | - const char *zEnd, /* Snippet end text - "</b>" */ | |
| 106587 | - const char *zEllipsis /* Snippet ellipsis text - "<b>...</b>" */ | |
| 106588 | -){ | |
| 106589 | - Snippet *p; /* Snippet structure */ | |
| 106590 | - int rc = snippetAllOffsets(pCsr, &p); | |
| 106591 | - if( rc==SQLITE_OK ){ | |
| 106592 | - snippetText(pCsr, p, zStart, zEnd, zEllipsis); | |
| 106593 | - if( p->zSnippet ){ | |
| 106594 | - sqlite3_result_text(pCtx, p->zSnippet, p->nSnippet, SQLITE_TRANSIENT); | |
| 106595 | - }else{ | |
| 106596 | - sqlite3_result_error_nomem(pCtx); | |
| 106597 | - } | |
| 106598 | - }else{ | |
| 106599 | - sqlite3_result_error_nomem(pCtx); | |
| 106600 | - } | |
| 106601 | - fts3SnippetFree(p); | |
| 106602 | -} | |
| 106603 | - | |
| 106604 | -/************************************************************************* | |
| 106605 | -** Below this point is the alternative, experimental snippet() implementation. | |
| 106606 | -*/ | |
| 106607 | - | |
| 106608 | -#define SNIPPET_BUFFER_CHUNK 64 | |
| 106609 | -#define SNIPPET_BUFFER_SIZE SNIPPET_BUFFER_CHUNK*4 | |
| 106610 | -#define SNIPPET_BUFFER_MASK (SNIPPET_BUFFER_SIZE-1) | |
| 106611 | - | |
| 107565 | +/* | |
| 107566 | +** This function is used to help iterate through a position-list. A position | |
| 107567 | +** list is a list of unique integers, sorted from smallest to largest. Each | |
| 107568 | +** element of the list is represented by an FTS3 varint that takes the value | |
| 107569 | +** of the difference between the current element and the previous one plus | |
| 107570 | +** two. For example, to store the position-list: | |
| 107571 | +** | |
| 107572 | +** 4 9 113 | |
| 107573 | +** | |
| 107574 | +** the three varints: | |
| 107575 | +** | |
| 107576 | +** 6 7 106 | |
| 107577 | +** | |
| 107578 | +** are encoded. | |
| 107579 | +** | |
| 107580 | +** When this function is called, *pp points to the start of an element of | |
| 107581 | +** the list. *piPos contains the value of the previous entry in the list. | |
| 107582 | +** After it returns, *piPos contains the value of the next element of the | |
| 107583 | +** list and *pp is advanced to the following varint. | |
| 107584 | +*/ | |
| 106612 | 107585 | static void fts3GetDeltaPosition(char **pp, int *piPos){ |
| 106613 | 107586 | int iVal; |
| 106614 | 107587 | *pp += sqlite3Fts3GetVarint32(*pp, &iVal); |
| 106615 | 107588 | *piPos += (iVal-2); |
| 106616 | 107589 | } |
| 107590 | + | |
| 107591 | +/* | |
| 107592 | +** Helper function for fts3ExprIterate() (see below). | |
| 107593 | +*/ | |
| 107594 | +static int fts3ExprIterate2( | |
| 107595 | + Fts3Expr *pExpr, /* Expression to iterate phrases of */ | |
| 107596 | + int *piPhrase, /* Pointer to phrase counter */ | |
| 107597 | + int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ | |
| 107598 | + void *pCtx /* Second argument to pass to callback */ | |
| 107599 | +){ | |
| 107600 | + int rc; /* Return code */ | |
| 107601 | + int eType = pExpr->eType; /* Type of expression node pExpr */ | |
| 107602 | + | |
| 107603 | + if( eType!=FTSQUERY_PHRASE ){ | |
| 107604 | + assert( pExpr->pLeft && pExpr->pRight ); | |
| 107605 | + rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx); | |
| 107606 | + if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){ | |
| 107607 | + rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx); | |
| 107608 | + } | |
| 107609 | + }else{ | |
| 107610 | + rc = x(pExpr, *piPhrase, pCtx); | |
| 107611 | + (*piPhrase)++; | |
| 107612 | + } | |
| 107613 | + return rc; | |
| 107614 | +} | |
| 106617 | 107615 | |
| 106618 | 107616 | /* |
| 106619 | 107617 | ** Iterate through all phrase nodes in an FTS3 query, except those that |
| 106620 | 107618 | ** are part of a sub-tree that is the right-hand-side of a NOT operator. |
| 106621 | 107619 | ** For each phrase node found, the supplied callback function is invoked. |
| @@ -106625,289 +107623,391 @@ | ||
| 106625 | 107623 | ** Otherwise, SQLITE_OK is returned after a callback has been made for |
| 106626 | 107624 | ** all eligible phrase nodes. |
| 106627 | 107625 | */ |
| 106628 | 107626 | static int fts3ExprIterate( |
| 106629 | 107627 | Fts3Expr *pExpr, /* Expression to iterate phrases of */ |
| 106630 | - int (*x)(Fts3Expr *, void *), /* Callback function to invoke for phrases */ | |
| 107628 | + int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ | |
| 106631 | 107629 | void *pCtx /* Second argument to pass to callback */ |
| 106632 | 107630 | ){ |
| 106633 | - int rc; | |
| 106634 | - int eType = pExpr->eType; | |
| 106635 | - if( eType==FTSQUERY_NOT ){ | |
| 106636 | - rc = SQLITE_OK; | |
| 106637 | - }else if( eType!=FTSQUERY_PHRASE ){ | |
| 106638 | - assert( pExpr->pLeft && pExpr->pRight ); | |
| 106639 | - rc = fts3ExprIterate(pExpr->pLeft, x, pCtx); | |
| 106640 | - if( rc==SQLITE_OK ){ | |
| 106641 | - rc = fts3ExprIterate(pExpr->pRight, x, pCtx); | |
| 106642 | - } | |
| 106643 | - }else{ | |
| 106644 | - rc = x(pExpr, pCtx); | |
| 106645 | - } | |
| 107631 | + int iPhrase = 0; /* Variable used as the phrase counter */ | |
| 107632 | + return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); | |
| 107633 | +} | |
| 107634 | + | |
| 107635 | +/* | |
| 107636 | +** The argument to this function is always a phrase node. Its doclist | |
| 107637 | +** (Fts3Expr.aDoclist[]) and the doclists associated with all phrase nodes | |
| 107638 | +** to the left of this one in the query tree have already been loaded. | |
| 107639 | +** | |
| 107640 | +** If this phrase node is part of a series of phrase nodes joined by | |
| 107641 | +** NEAR operators (and is not the left-most of said series), then elements are | |
| 107642 | +** removed from the phrases doclist consistent with the NEAR restriction. If | |
| 107643 | +** required, elements may be removed from the doclists of phrases to the | |
| 107644 | +** left of this one that are part of the same series of NEAR operator | |
| 107645 | +** connected phrases. | |
| 107646 | +** | |
| 107647 | +** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK. | |
| 107648 | +*/ | |
| 107649 | +static int fts3ExprNearTrim(Fts3Expr *pExpr){ | |
| 107650 | + int rc = SQLITE_OK; | |
| 107651 | + Fts3Expr *pParent = pExpr->pParent; | |
| 107652 | + | |
| 107653 | + assert( pExpr->eType==FTSQUERY_PHRASE ); | |
| 107654 | + while( rc==SQLITE_OK | |
| 107655 | + && pParent | |
| 107656 | + && pParent->eType==FTSQUERY_NEAR | |
| 107657 | + && pParent->pRight==pExpr | |
| 107658 | + ){ | |
| 107659 | + /* This expression (pExpr) is the right-hand-side of a NEAR operator. | |
| 107660 | + ** Find the expression to the left of the same operator. | |
| 107661 | + */ | |
| 107662 | + int nNear = pParent->nNear; | |
| 107663 | + Fts3Expr *pLeft = pParent->pLeft; | |
| 107664 | + | |
| 107665 | + if( pLeft->eType!=FTSQUERY_PHRASE ){ | |
| 107666 | + assert( pLeft->eType==FTSQUERY_NEAR ); | |
| 107667 | + assert( pLeft->pRight->eType==FTSQUERY_PHRASE ); | |
| 107668 | + pLeft = pLeft->pRight; | |
| 107669 | + } | |
| 107670 | + | |
| 107671 | + rc = sqlite3Fts3ExprNearTrim(pLeft, pExpr, nNear); | |
| 107672 | + | |
| 107673 | + pExpr = pLeft; | |
| 107674 | + pParent = pExpr->pParent; | |
| 107675 | + } | |
| 107676 | + | |
| 106646 | 107677 | return rc; |
| 106647 | 107678 | } |
| 106648 | 107679 | |
| 106649 | -typedef struct LoadDoclistCtx LoadDoclistCtx; | |
| 106650 | -struct LoadDoclistCtx { | |
| 106651 | - Fts3Table *pTab; /* FTS3 Table */ | |
| 106652 | - int nPhrase; /* Number of phrases so far */ | |
| 106653 | -}; | |
| 106654 | - | |
| 106655 | -static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, void *ctx){ | |
| 107680 | +/* | |
| 107681 | +** This is an fts3ExprIterate() callback used while loading the doclists | |
| 107682 | +** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also | |
| 107683 | +** fts3ExprLoadDoclists(). | |
| 107684 | +*/ | |
| 107685 | +static int fts3ExprLoadDoclistsCb1(Fts3Expr *pExpr, int iPhrase, void *ctx){ | |
| 106656 | 107686 | int rc = SQLITE_OK; |
| 106657 | 107687 | LoadDoclistCtx *p = (LoadDoclistCtx *)ctx; |
| 107688 | + | |
| 107689 | + UNUSED_PARAMETER(iPhrase); | |
| 107690 | + | |
| 106658 | 107691 | p->nPhrase++; |
| 107692 | + p->nToken += pExpr->pPhrase->nToken; | |
| 107693 | + | |
| 106659 | 107694 | if( pExpr->isLoaded==0 ){ |
| 106660 | 107695 | rc = sqlite3Fts3ExprLoadDoclist(p->pTab, pExpr); |
| 106661 | 107696 | pExpr->isLoaded = 1; |
| 106662 | - if( rc==SQLITE_OK && pExpr->aDoclist ){ | |
| 106663 | - pExpr->pCurrent = pExpr->aDoclist; | |
| 106664 | - pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent,&pExpr->iCurrent); | |
| 107697 | + if( rc==SQLITE_OK ){ | |
| 107698 | + rc = fts3ExprNearTrim(pExpr); | |
| 106665 | 107699 | } |
| 106666 | 107700 | } |
| 107701 | + | |
| 106667 | 107702 | return rc; |
| 106668 | 107703 | } |
| 106669 | 107704 | |
| 106670 | -static int fts3ExprLoadDoclists(Fts3Cursor *pCsr, int *pnPhrase){ | |
| 106671 | - int rc; | |
| 106672 | - LoadDoclistCtx sCtx = {0, 0}; | |
| 107705 | +/* | |
| 107706 | +** This is an fts3ExprIterate() callback used while loading the doclists | |
| 107707 | +** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also | |
| 107708 | +** fts3ExprLoadDoclists(). | |
| 107709 | +*/ | |
| 107710 | +static int fts3ExprLoadDoclistsCb2(Fts3Expr *pExpr, int iPhrase, void *ctx){ | |
| 107711 | + UNUSED_PARAMETER(iPhrase); | |
| 107712 | + UNUSED_PARAMETER(ctx); | |
| 107713 | + if( pExpr->aDoclist ){ | |
| 107714 | + pExpr->pCurrent = pExpr->aDoclist; | |
| 107715 | + pExpr->iCurrent = 0; | |
| 107716 | + pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent, &pExpr->iCurrent); | |
| 107717 | + } | |
| 107718 | + return SQLITE_OK; | |
| 107719 | +} | |
| 107720 | + | |
| 107721 | +/* | |
| 107722 | +** Load the doclists for each phrase in the query associated with FTS3 cursor | |
| 107723 | +** pCsr. | |
| 107724 | +** | |
| 107725 | +** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable | |
| 107726 | +** phrases in the expression (all phrases except those directly or | |
| 107727 | +** indirectly descended from the right-hand-side of a NOT operator). If | |
| 107728 | +** pnToken is not NULL, then it is set to the number of tokens in all | |
| 107729 | +** matchable phrases of the expression. | |
| 107730 | +*/ | |
| 107731 | +static int fts3ExprLoadDoclists( | |
| 107732 | + Fts3Cursor *pCsr, /* Fts3 cursor for current query */ | |
| 107733 | + int *pnPhrase, /* OUT: Number of phrases in query */ | |
| 107734 | + int *pnToken /* OUT: Number of tokens in query */ | |
| 107735 | +){ | |
| 107736 | + int rc; /* Return Code */ | |
| 107737 | + LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */ | |
| 106673 | 107738 | sCtx.pTab = (Fts3Table *)pCsr->base.pVtab; |
| 106674 | - rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx); | |
| 106675 | - *pnPhrase = sCtx.nPhrase; | |
| 107739 | + rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb1, (void *)&sCtx); | |
| 107740 | + if( rc==SQLITE_OK ){ | |
| 107741 | + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb2, 0); | |
| 107742 | + } | |
| 107743 | + if( pnPhrase ) *pnPhrase = sCtx.nPhrase; | |
| 107744 | + if( pnToken ) *pnToken = sCtx.nToken; | |
| 106676 | 107745 | return rc; |
| 106677 | 107746 | } |
| 106678 | 107747 | |
| 106679 | 107748 | /* |
| 106680 | -** Each call to this function populates a chunk of a snippet-buffer | |
| 106681 | -** SNIPPET_BUFFER_CHUNK bytes in size. | |
| 106682 | -** | |
| 106683 | -** Return true if the end of the data has been reached (and all subsequent | |
| 106684 | -** calls to fts3LoadSnippetBuffer() with the same arguments will be no-ops), | |
| 106685 | -** or false otherwise. | |
| 107749 | +** Advance the position list iterator specified by the first two | |
| 107750 | +** arguments so that it points to the first element with a value greater | |
| 107751 | +** than or equal to parameter iNext. | |
| 106686 | 107752 | */ |
| 106687 | -static int fts3LoadSnippetBuffer( | |
| 106688 | - int iPos, /* Document token offset to load data for */ | |
| 106689 | - u8 *aBuffer, /* Circular snippet buffer to populate */ | |
| 106690 | - int nList, /* Number of position lists in appList */ | |
| 106691 | - char **apList, /* IN/OUT: nList position list pointers */ | |
| 106692 | - int *aiPrev /* IN/OUT: Previous positions read */ | |
| 106693 | -){ | |
| 106694 | - int i; | |
| 106695 | - int nFin = 0; | |
| 106696 | - | |
| 106697 | - assert( (iPos&(SNIPPET_BUFFER_CHUNK-1))==0 ); | |
| 106698 | - | |
| 106699 | - memset(&aBuffer[iPos&SNIPPET_BUFFER_MASK], 0, SNIPPET_BUFFER_CHUNK); | |
| 106700 | - | |
| 106701 | - for(i=0; i<nList; i++){ | |
| 106702 | - int iPrev = aiPrev[i]; | |
| 106703 | - char *pList = apList[i]; | |
| 106704 | - | |
| 106705 | - if( !pList ){ | |
| 106706 | - nFin++; | |
| 106707 | - continue; | |
| 106708 | - } | |
| 106709 | - | |
| 106710 | - while( iPrev<(iPos+SNIPPET_BUFFER_CHUNK) ){ | |
| 106711 | - if( iPrev>=iPos ){ | |
| 106712 | - aBuffer[iPrev&SNIPPET_BUFFER_MASK] = i+1; | |
| 106713 | - } | |
| 106714 | - if( 0==((*pList)&0xFE) ){ | |
| 106715 | - nFin++; | |
| 107753 | +static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){ | |
| 107754 | + char *pIter = *ppIter; | |
| 107755 | + if( pIter ){ | |
| 107756 | + int iIter = *piIter; | |
| 107757 | + | |
| 107758 | + while( iIter<iNext ){ | |
| 107759 | + if( 0==(*pIter & 0xFE) ){ | |
| 107760 | + iIter = -1; | |
| 107761 | + pIter = 0; | |
| 106716 | 107762 | break; |
| 106717 | 107763 | } |
| 106718 | - fts3GetDeltaPosition(&pList, &iPrev); | |
| 106719 | - } | |
| 106720 | - | |
| 106721 | - aiPrev[i] = iPrev; | |
| 106722 | - apList[i] = pList; | |
| 106723 | - } | |
| 106724 | - | |
| 106725 | - return (nFin==nList); | |
| 106726 | -} | |
| 106727 | - | |
| 106728 | -typedef struct SnippetCtx SnippetCtx; | |
| 106729 | -struct SnippetCtx { | |
| 106730 | - Fts3Cursor *pCsr; | |
| 106731 | - int iCol; | |
| 106732 | - int iPhrase; | |
| 106733 | - int *aiPrev; | |
| 106734 | - int *anToken; | |
| 106735 | - char **apList; | |
| 106736 | -}; | |
| 106737 | - | |
| 106738 | -static int fts3SnippetFindPositions(Fts3Expr *pExpr, void *ctx){ | |
| 106739 | - SnippetCtx *p = (SnippetCtx *)ctx; | |
| 106740 | - int iPhrase = p->iPhrase++; | |
| 107764 | + fts3GetDeltaPosition(&pIter, &iIter); | |
| 107765 | + } | |
| 107766 | + | |
| 107767 | + *piIter = iIter; | |
| 107768 | + *ppIter = pIter; | |
| 107769 | + } | |
| 107770 | +} | |
| 107771 | + | |
| 107772 | +/* | |
| 107773 | +** Advance the snippet iterator to the next candidate snippet. | |
| 107774 | +*/ | |
| 107775 | +static int fts3SnippetNextCandidate(SnippetIter *pIter){ | |
| 107776 | + int i; /* Loop counter */ | |
| 107777 | + | |
| 107778 | + if( pIter->iCurrent<0 ){ | |
| 107779 | + /* The SnippetIter object has just been initialized. The first snippet | |
| 107780 | + ** candidate always starts at offset 0 (even if this candidate has a | |
| 107781 | + ** score of 0.0). | |
| 107782 | + */ | |
| 107783 | + pIter->iCurrent = 0; | |
| 107784 | + | |
| 107785 | + /* Advance the 'head' iterator of each phrase to the first offset that | |
| 107786 | + ** is greater than or equal to (iNext+nSnippet). | |
| 107787 | + */ | |
| 107788 | + for(i=0; i<pIter->nPhrase; i++){ | |
| 107789 | + SnippetPhrase *pPhrase = &pIter->aPhrase[i]; | |
| 107790 | + fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet); | |
| 107791 | + } | |
| 107792 | + }else{ | |
| 107793 | + int iStart; | |
| 107794 | + int iEnd = 0x7FFFFFFF; | |
| 107795 | + | |
| 107796 | + for(i=0; i<pIter->nPhrase; i++){ | |
| 107797 | + SnippetPhrase *pPhrase = &pIter->aPhrase[i]; | |
| 107798 | + if( pPhrase->pHead && pPhrase->iHead<iEnd ){ | |
| 107799 | + iEnd = pPhrase->iHead; | |
| 107800 | + } | |
| 107801 | + } | |
| 107802 | + if( iEnd==0x7FFFFFFF ){ | |
| 107803 | + return 1; | |
| 107804 | + } | |
| 107805 | + | |
| 107806 | + pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1; | |
| 107807 | + for(i=0; i<pIter->nPhrase; i++){ | |
| 107808 | + SnippetPhrase *pPhrase = &pIter->aPhrase[i]; | |
| 107809 | + fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1); | |
| 107810 | + fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart); | |
| 107811 | + } | |
| 107812 | + } | |
| 107813 | + | |
| 107814 | + return 0; | |
| 107815 | +} | |
| 107816 | + | |
| 107817 | +/* | |
| 107818 | +** Retrieve information about the current candidate snippet of snippet | |
| 107819 | +** iterator pIter. | |
| 107820 | +*/ | |
| 107821 | +static void fts3SnippetDetails( | |
| 107822 | + SnippetIter *pIter, /* Snippet iterator */ | |
| 107823 | + u64 mCovered, /* Bitmask of phrases already covered */ | |
| 107824 | + int *piToken, /* OUT: First token of proposed snippet */ | |
| 107825 | + int *piScore, /* OUT: "Score" for this snippet */ | |
| 107826 | + u64 *pmCover, /* OUT: Bitmask of phrases covered */ | |
| 107827 | + u64 *pmHighlight /* OUT: Bitmask of terms to highlight */ | |
| 107828 | +){ | |
| 107829 | + int iStart = pIter->iCurrent; /* First token of snippet */ | |
| 107830 | + int iScore = 0; /* Score of this snippet */ | |
| 107831 | + int i; /* Loop counter */ | |
| 107832 | + u64 mCover = 0; /* Mask of phrases covered by this snippet */ | |
| 107833 | + u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */ | |
| 107834 | + | |
| 107835 | + for(i=0; i<pIter->nPhrase; i++){ | |
| 107836 | + SnippetPhrase *pPhrase = &pIter->aPhrase[i]; | |
| 107837 | + if( pPhrase->pTail ){ | |
| 107838 | + char *pCsr = pPhrase->pTail; | |
| 107839 | + int iCsr = pPhrase->iTail; | |
| 107840 | + | |
| 107841 | + while( iCsr<(iStart+pIter->nSnippet) ){ | |
| 107842 | + int j; | |
| 107843 | + u64 mPhrase = (u64)1 << i; | |
| 107844 | + u64 mPos = (u64)1 << (iCsr - iStart); | |
| 107845 | + assert( iCsr>=iStart ); | |
| 107846 | + if( (mCover|mCovered)&mPhrase ){ | |
| 107847 | + iScore++; | |
| 107848 | + }else{ | |
| 107849 | + iScore += 1000; | |
| 107850 | + } | |
| 107851 | + mCover |= mPhrase; | |
| 107852 | + | |
| 107853 | + for(j=0; j<pPhrase->nToken; j++){ | |
| 107854 | + mHighlight |= (mPos>>j); | |
| 107855 | + } | |
| 107856 | + | |
| 107857 | + if( 0==(*pCsr & 0x0FE) ) break; | |
| 107858 | + fts3GetDeltaPosition(&pCsr, &iCsr); | |
| 107859 | + } | |
| 107860 | + } | |
| 107861 | + } | |
| 107862 | + | |
| 107863 | + /* Set the output variables before returning. */ | |
| 107864 | + *piToken = iStart; | |
| 107865 | + *piScore = iScore; | |
| 107866 | + *pmCover = mCover; | |
| 107867 | + *pmHighlight = mHighlight; | |
| 107868 | +} | |
| 107869 | + | |
| 107870 | +/* | |
| 107871 | +** This function is an fts3ExprIterate() callback used by fts3BestSnippet(). | |
| 107872 | +** Each invocation populates an element of the SnippetIter.aPhrase[] array. | |
| 107873 | +*/ | |
| 107874 | +static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ | |
| 107875 | + SnippetIter *p = (SnippetIter *)ctx; | |
| 107876 | + SnippetPhrase *pPhrase = &p->aPhrase[iPhrase]; | |
| 106741 | 107877 | char *pCsr; |
| 106742 | 107878 | |
| 106743 | - p->anToken[iPhrase] = pExpr->pPhrase->nToken; | |
| 107879 | + pPhrase->nToken = pExpr->pPhrase->nToken; | |
| 107880 | + | |
| 106744 | 107881 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCsr->iPrevId, p->iCol); |
| 106745 | - | |
| 106746 | 107882 | if( pCsr ){ |
| 106747 | - int iVal; | |
| 106748 | - pCsr += sqlite3Fts3GetVarint32(pCsr, &iVal); | |
| 106749 | - p->apList[iPhrase] = pCsr; | |
| 106750 | - p->aiPrev[iPhrase] = iVal-2; | |
| 107883 | + int iFirst = 0; | |
| 107884 | + pPhrase->pList = pCsr; | |
| 107885 | + fts3GetDeltaPosition(&pCsr, &iFirst); | |
| 107886 | + pPhrase->pHead = pCsr; | |
| 107887 | + pPhrase->pTail = pCsr; | |
| 107888 | + pPhrase->iHead = iFirst; | |
| 107889 | + pPhrase->iTail = iFirst; | |
| 107890 | + }else{ | |
| 107891 | + assert( pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 ); | |
| 106751 | 107892 | } |
| 107893 | + | |
| 106752 | 107894 | return SQLITE_OK; |
| 106753 | 107895 | } |
| 106754 | 107896 | |
| 106755 | -static void fts3SnippetCnt( | |
| 106756 | - int iIdx, | |
| 106757 | - int nSnippet, | |
| 106758 | - int *anCnt, | |
| 106759 | - u8 *aBuffer, | |
| 106760 | - int *anToken, | |
| 106761 | - u64 *pHlmask | |
| 106762 | -){ | |
| 106763 | - int iSub = (iIdx-1)&SNIPPET_BUFFER_MASK; | |
| 106764 | - int iAdd = (iIdx+nSnippet-1)&SNIPPET_BUFFER_MASK; | |
| 106765 | - int iSub2 = (iIdx+(nSnippet/3)-1)&SNIPPET_BUFFER_MASK; | |
| 106766 | - int iAdd2 = (iIdx+(nSnippet*2/3)-1)&SNIPPET_BUFFER_MASK; | |
| 106767 | - | |
| 106768 | - u64 h = *pHlmask; | |
| 106769 | - | |
| 106770 | - anCnt[ aBuffer[iSub] ]--; | |
| 106771 | - anCnt[ aBuffer[iSub2] ]--; | |
| 106772 | - anCnt[ aBuffer[iAdd] ]++; | |
| 106773 | - anCnt[ aBuffer[iAdd2] ]++; | |
| 106774 | - | |
| 106775 | - h = h >> 1; | |
| 106776 | - if( aBuffer[iAdd] ){ | |
| 106777 | - int j; | |
| 106778 | - for(j=anToken[aBuffer[iAdd]-1]; j>=1; j--){ | |
| 106779 | - h |= (u64)1 << (nSnippet-j); | |
| 106780 | - } | |
| 106781 | - } | |
| 106782 | - *pHlmask = h; | |
| 106783 | -} | |
| 106784 | - | |
| 106785 | -static int fts3SnippetScore(int n, int *anCnt){ | |
| 106786 | - int j; | |
| 106787 | - int iScore = 0; | |
| 106788 | - for(j=1; j<=n; j++){ | |
| 106789 | - int nCnt = anCnt[j]; | |
| 106790 | - iScore += nCnt + (nCnt ? 1000 : 0); | |
| 106791 | - } | |
| 106792 | - return iScore; | |
| 106793 | -} | |
| 106794 | - | |
| 107897 | +/* | |
| 107898 | +** Select the fragment of text consisting of nFragment contiguous tokens | |
| 107899 | +** from column iCol that represent the "best" snippet. The best snippet | |
| 107900 | +** is the snippet with the highest score, where scores are calculated | |
| 107901 | +** by adding: | |
| 107902 | +** | |
| 107903 | +** (a) +1 point for each occurence of a matchable phrase in the snippet. | |
| 107904 | +** | |
| 107905 | +** (b) +1000 points for the first occurence of each matchable phrase in | |
| 107906 | +** the snippet for which the corresponding mCovered bit is not set. | |
| 107907 | +** | |
| 107908 | +** The selected snippet parameters are stored in structure *pFragment before | |
| 107909 | +** returning. The score of the selected snippet is stored in *piScore | |
| 107910 | +** before returning. | |
| 107911 | +*/ | |
| 106795 | 107912 | static int fts3BestSnippet( |
| 106796 | 107913 | int nSnippet, /* Desired snippet length */ |
| 106797 | 107914 | Fts3Cursor *pCsr, /* Cursor to create snippet for */ |
| 106798 | 107915 | int iCol, /* Index of column to create snippet from */ |
| 106799 | - int *piPos, /* OUT: Starting token for best snippet */ | |
| 106800 | - u64 *pHlmask /* OUT: Highlight mask for best snippet */ | |
| 107916 | + u64 mCovered, /* Mask of phrases already covered */ | |
| 107917 | + u64 *pmSeen, /* IN/OUT: Mask of phrases seen */ | |
| 107918 | + SnippetFragment *pFragment, /* OUT: Best snippet found */ | |
| 107919 | + int *piScore /* OUT: Score of snippet pFragment */ | |
| 106801 | 107920 | ){ |
| 106802 | 107921 | int rc; /* Return Code */ |
| 106803 | - u8 aBuffer[SNIPPET_BUFFER_SIZE];/* Circular snippet buffer */ | |
| 106804 | - int *aiPrev; /* Used by fts3LoadSnippetBuffer() */ | |
| 106805 | - int *anToken; /* Number of tokens in each phrase */ | |
| 106806 | - char **apList; /* Array of position lists */ | |
| 106807 | - int *anCnt; /* Running totals of phrase occurences */ | |
| 106808 | - int nList; | |
| 106809 | - | |
| 106810 | - int i; | |
| 106811 | - | |
| 106812 | - u64 hlmask = 0; /* Current mask of highlighted terms */ | |
| 106813 | - u64 besthlmask = 0; /* Mask of highlighted terms for iBestPos */ | |
| 106814 | - int iBestPos = 0; /* Starting position of 'best' snippet */ | |
| 106815 | - int iBestScore = 0; /* Score of best snippet higher->better */ | |
| 106816 | - SnippetCtx sCtx; | |
| 107922 | + int nList; /* Number of phrases in expression */ | |
| 107923 | + SnippetIter sIter; /* Iterates through snippet candidates */ | |
| 107924 | + int nByte; /* Number of bytes of space to allocate */ | |
| 107925 | + int iBestScore = -1; /* Best snippet score found so far */ | |
| 107926 | + int i; /* Loop counter */ | |
| 107927 | + | |
| 107928 | + memset(&sIter, 0, sizeof(sIter)); | |
| 106817 | 107929 | |
| 106818 | 107930 | /* Iterate through the phrases in the expression to count them. The same |
| 106819 | 107931 | ** callback makes sure the doclists are loaded for each phrase. |
| 106820 | 107932 | */ |
| 106821 | - rc = fts3ExprLoadDoclists(pCsr, &nList); | |
| 107933 | + rc = fts3ExprLoadDoclists(pCsr, &nList, 0); | |
| 106822 | 107934 | if( rc!=SQLITE_OK ){ |
| 106823 | 107935 | return rc; |
| 106824 | 107936 | } |
| 106825 | 107937 | |
| 106826 | 107938 | /* Now that it is known how many phrases there are, allocate and zero |
| 106827 | - ** the required arrays using malloc(). | |
| 107939 | + ** the required space using malloc(). | |
| 106828 | 107940 | */ |
| 106829 | - apList = sqlite3_malloc( | |
| 106830 | - sizeof(u8*)*nList + /* apList */ | |
| 106831 | - sizeof(int)*(nList) + /* anToken */ | |
| 106832 | - sizeof(int)*nList + /* aiPrev */ | |
| 106833 | - sizeof(int)*(nList+1) /* anCnt */ | |
| 106834 | - ); | |
| 106835 | - if( !apList ){ | |
| 107941 | + nByte = sizeof(SnippetPhrase) * nList; | |
| 107942 | + sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte); | |
| 107943 | + if( !sIter.aPhrase ){ | |
| 106836 | 107944 | return SQLITE_NOMEM; |
| 106837 | 107945 | } |
| 106838 | - memset(apList, 0, sizeof(u8*)*nList+sizeof(int)*nList+sizeof(int)*nList); | |
| 106839 | - anToken = (int *)&apList[nList]; | |
| 106840 | - aiPrev = &anToken[nList]; | |
| 106841 | - anCnt = &aiPrev[nList]; | |
| 106842 | - | |
| 106843 | - /* Initialize the contents of the aiPrev and aiList arrays. */ | |
| 106844 | - sCtx.pCsr = pCsr; | |
| 106845 | - sCtx.iCol = iCol; | |
| 106846 | - sCtx.apList = apList; | |
| 106847 | - sCtx.aiPrev = aiPrev; | |
| 106848 | - sCtx.anToken = anToken; | |
| 106849 | - sCtx.iPhrase = 0; | |
| 106850 | - (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sCtx); | |
| 106851 | - | |
| 106852 | - /* Load the first two chunks of data into the buffer. */ | |
| 106853 | - memset(aBuffer, 0, SNIPPET_BUFFER_SIZE); | |
| 106854 | - fts3LoadSnippetBuffer(0, aBuffer, nList, apList, aiPrev); | |
| 106855 | - fts3LoadSnippetBuffer(SNIPPET_BUFFER_CHUNK, aBuffer, nList, apList, aiPrev); | |
| 106856 | - | |
| 106857 | - /* Set the initial contents of the highlight-mask and anCnt[] array. */ | |
| 106858 | - for(i=1-nSnippet; i<=0; i++){ | |
| 106859 | - fts3SnippetCnt(i, nSnippet, anCnt, aBuffer, anToken, &hlmask); | |
| 106860 | - } | |
| 106861 | - iBestScore = fts3SnippetScore(nList, anCnt); | |
| 106862 | - besthlmask = hlmask; | |
| 106863 | - iBestPos = 0; | |
| 106864 | - | |
| 106865 | - for(i=1; 1; i++){ | |
| 107946 | + memset(sIter.aPhrase, 0, nByte); | |
| 107947 | + | |
| 107948 | + /* Initialize the contents of the SnippetIter object. Then iterate through | |
| 107949 | + ** the set of phrases in the expression to populate the aPhrase[] array. | |
| 107950 | + */ | |
| 107951 | + sIter.pCsr = pCsr; | |
| 107952 | + sIter.iCol = iCol; | |
| 107953 | + sIter.nSnippet = nSnippet; | |
| 107954 | + sIter.nPhrase = nList; | |
| 107955 | + sIter.iCurrent = -1; | |
| 107956 | + (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter); | |
| 107957 | + | |
| 107958 | + /* Set the *pmSeen output variable. */ | |
| 107959 | + for(i=0; i<nList; i++){ | |
| 107960 | + if( sIter.aPhrase[i].pHead ){ | |
| 107961 | + *pmSeen |= (u64)1 << i; | |
| 107962 | + } | |
| 107963 | + } | |
| 107964 | + | |
| 107965 | + /* Loop through all candidate snippets. Store the best snippet in | |
| 107966 | + ** *pFragment. Store its associated 'score' in iBestScore. | |
| 107967 | + */ | |
| 107968 | + pFragment->iCol = iCol; | |
| 107969 | + while( !fts3SnippetNextCandidate(&sIter) ){ | |
| 107970 | + int iPos; | |
| 106866 | 107971 | int iScore; |
| 106867 | - | |
| 106868 | - if( 0==(i&(SNIPPET_BUFFER_CHUNK-1)) ){ | |
| 106869 | - int iLoad = i + SNIPPET_BUFFER_CHUNK; | |
| 106870 | - if( fts3LoadSnippetBuffer(iLoad, aBuffer, nList, apList, aiPrev) ) break; | |
| 106871 | - } | |
| 106872 | - | |
| 106873 | - /* Figure out how highly a snippet starting at token offset i scores | |
| 106874 | - ** according to fts3SnippetScore(). If it is higher than any previously | |
| 106875 | - ** considered position, save the current position, score and hlmask as | |
| 106876 | - ** the best snippet candidate found so far. | |
| 106877 | - */ | |
| 106878 | - fts3SnippetCnt(i, nSnippet, anCnt, aBuffer, anToken, &hlmask); | |
| 106879 | - iScore = fts3SnippetScore(nList, anCnt); | |
| 107972 | + u64 mCover; | |
| 107973 | + u64 mHighlight; | |
| 107974 | + fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight); | |
| 107975 | + assert( iScore>=0 ); | |
| 106880 | 107976 | if( iScore>iBestScore ){ |
| 106881 | - iBestPos = i; | |
| 107977 | + pFragment->iPos = iPos; | |
| 107978 | + pFragment->hlmask = mHighlight; | |
| 107979 | + pFragment->covered = mCover; | |
| 106882 | 107980 | iBestScore = iScore; |
| 106883 | - besthlmask = hlmask; | |
| 106884 | 107981 | } |
| 106885 | 107982 | } |
| 106886 | 107983 | |
| 106887 | - sqlite3_free(apList); | |
| 106888 | - *piPos = iBestPos; | |
| 106889 | - *pHlmask = besthlmask; | |
| 107984 | + sqlite3_free(sIter.aPhrase); | |
| 107985 | + *piScore = iBestScore; | |
| 106890 | 107986 | return SQLITE_OK; |
| 106891 | 107987 | } |
| 106892 | 107988 | |
| 106893 | -typedef struct StrBuffer StrBuffer; | |
| 106894 | -struct StrBuffer { | |
| 106895 | - char *z; | |
| 106896 | - int n; | |
| 106897 | - int nAlloc; | |
| 106898 | -}; | |
| 106899 | 107989 | |
| 107990 | +/* | |
| 107991 | +** Append a string to the string-buffer passed as the first argument. | |
| 107992 | +** | |
| 107993 | +** If nAppend is negative, then the length of the string zAppend is | |
| 107994 | +** determined using strlen(). | |
| 107995 | +*/ | |
| 106900 | 107996 | static int fts3StringAppend( |
| 106901 | - StrBuffer *pStr, | |
| 106902 | - const char *zAppend, | |
| 106903 | - int nAppend | |
| 107997 | + StrBuffer *pStr, /* Buffer to append to */ | |
| 107998 | + const char *zAppend, /* Pointer to data to append to buffer */ | |
| 107999 | + int nAppend /* Size of zAppend in bytes (or -1) */ | |
| 106904 | 108000 | ){ |
| 106905 | 108001 | if( nAppend<0 ){ |
| 106906 | - nAppend = strlen(zAppend); | |
| 108002 | + nAppend = (int)strlen(zAppend); | |
| 106907 | 108003 | } |
| 106908 | 108004 | |
| 108005 | + /* If there is insufficient space allocated at StrBuffer.z, use realloc() | |
| 108006 | + ** to grow the buffer until so that it is big enough to accomadate the | |
| 108007 | + ** appended data. | |
| 108008 | + */ | |
| 106909 | 108009 | if( pStr->n+nAppend+1>=pStr->nAlloc ){ |
| 106910 | 108010 | int nAlloc = pStr->nAlloc+nAppend+100; |
| 106911 | 108011 | char *zNew = sqlite3_realloc(pStr->z, nAlloc); |
| 106912 | 108012 | if( !zNew ){ |
| 106913 | 108013 | return SQLITE_NOMEM; |
| @@ -106914,137 +108014,213 @@ | ||
| 106914 | 108014 | } |
| 106915 | 108015 | pStr->z = zNew; |
| 106916 | 108016 | pStr->nAlloc = nAlloc; |
| 106917 | 108017 | } |
| 106918 | 108018 | |
| 108019 | + /* Append the data to the string buffer. */ | |
| 106919 | 108020 | memcpy(&pStr->z[pStr->n], zAppend, nAppend); |
| 106920 | 108021 | pStr->n += nAppend; |
| 106921 | 108022 | pStr->z[pStr->n] = '\0'; |
| 106922 | 108023 | |
| 106923 | 108024 | return SQLITE_OK; |
| 106924 | 108025 | } |
| 106925 | 108026 | |
| 108027 | +/* | |
| 108028 | +** The fts3BestSnippet() function often selects snippets that end with a | |
| 108029 | +** query term. That is, the final term of the snippet is always a term | |
| 108030 | +** that requires highlighting. For example, if 'X' is a highlighted term | |
| 108031 | +** and '.' is a non-highlighted term, BestSnippet() may select: | |
| 108032 | +** | |
| 108033 | +** ........X.....X | |
| 108034 | +** | |
| 108035 | +** This function "shifts" the beginning of the snippet forward in the | |
| 108036 | +** document so that there are approximately the same number of | |
| 108037 | +** non-highlighted terms to the right of the final highlighted term as there | |
| 108038 | +** are to the left of the first highlighted term. For example, to this: | |
| 108039 | +** | |
| 108040 | +** ....X.....X.... | |
| 108041 | +** | |
| 108042 | +** This is done as part of extracting the snippet text, not when selecting | |
| 108043 | +** the snippet. Snippet selection is done based on doclists only, so there | |
| 108044 | +** is no way for fts3BestSnippet() to know whether or not the document | |
| 108045 | +** actually contains terms that follow the final highlighted term. | |
| 108046 | +*/ | |
| 108047 | +int fts3SnippetShift( | |
| 108048 | + Fts3Table *pTab, /* FTS3 table snippet comes from */ | |
| 108049 | + int nSnippet, /* Number of tokens desired for snippet */ | |
| 108050 | + const char *zDoc, /* Document text to extract snippet from */ | |
| 108051 | + int nDoc, /* Size of buffer zDoc in bytes */ | |
| 108052 | + int *piPos, /* IN/OUT: First token of snippet */ | |
| 108053 | + u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */ | |
| 108054 | +){ | |
| 108055 | + u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */ | |
| 108056 | + | |
| 108057 | + if( hlmask ){ | |
| 108058 | + int nLeft; /* Tokens to the left of first highlight */ | |
| 108059 | + int nRight; /* Tokens to the right of last highlight */ | |
| 108060 | + int nDesired; /* Ideal number of tokens to shift forward */ | |
| 108061 | + | |
| 108062 | + for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++); | |
| 108063 | + for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++); | |
| 108064 | + nDesired = (nLeft-nRight)/2; | |
| 108065 | + | |
| 108066 | + /* Ideally, the start of the snippet should be pushed forward in the | |
| 108067 | + ** document nDesired tokens. This block checks if there are actually | |
| 108068 | + ** nDesired tokens to the right of the snippet. If so, *piPos and | |
| 108069 | + ** *pHlMask are updated to shift the snippet nDesired tokens to the | |
| 108070 | + ** right. Otherwise, the snippet is shifted by the number of tokens | |
| 108071 | + ** available. | |
| 108072 | + */ | |
| 108073 | + if( nDesired>0 ){ | |
| 108074 | + int nShift; /* Number of tokens to shift snippet by */ | |
| 108075 | + int iCurrent = 0; /* Token counter */ | |
| 108076 | + int rc; /* Return Code */ | |
| 108077 | + sqlite3_tokenizer_module *pMod; | |
| 108078 | + sqlite3_tokenizer_cursor *pC; | |
| 108079 | + pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; | |
| 108080 | + | |
| 108081 | + /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) | |
| 108082 | + ** or more tokens in zDoc/nDoc. | |
| 108083 | + */ | |
| 108084 | + rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); | |
| 108085 | + if( rc!=SQLITE_OK ){ | |
| 108086 | + return rc; | |
| 108087 | + } | |
| 108088 | + pC->pTokenizer = pTab->pTokenizer; | |
| 108089 | + while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ | |
| 108090 | + const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3; | |
| 108091 | + rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); | |
| 108092 | + } | |
| 108093 | + pMod->xClose(pC); | |
| 108094 | + if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; } | |
| 108095 | + | |
| 108096 | + nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet; | |
| 108097 | + assert( nShift<=nDesired ); | |
| 108098 | + if( nShift>0 ){ | |
| 108099 | + *piPos += nShift; | |
| 108100 | + *pHlmask = hlmask >> nShift; | |
| 108101 | + } | |
| 108102 | + } | |
| 108103 | + } | |
| 108104 | + return SQLITE_OK; | |
| 108105 | +} | |
| 108106 | + | |
| 108107 | +/* | |
| 108108 | +** Extract the snippet text for fragment pFragment from cursor pCsr and | |
| 108109 | +** append it to string buffer pOut. | |
| 108110 | +*/ | |
| 106926 | 108111 | static int fts3SnippetText( |
| 106927 | 108112 | Fts3Cursor *pCsr, /* FTS3 Cursor */ |
| 106928 | - const char *zDoc, /* Document to extract snippet from */ | |
| 106929 | - int nDoc, /* Size of zDoc in bytes */ | |
| 108113 | + SnippetFragment *pFragment, /* Snippet to extract */ | |
| 108114 | + int iFragment, /* Fragment number */ | |
| 108115 | + int isLast, /* True for final fragment in snippet */ | |
| 106930 | 108116 | int nSnippet, /* Number of tokens in extracted snippet */ |
| 106931 | - int iPos, /* Index of first document token in snippet */ | |
| 106932 | - u64 hlmask, /* Bitmask of terms to highlight in snippet */ | |
| 106933 | 108117 | const char *zOpen, /* String inserted before highlighted term */ |
| 106934 | 108118 | const char *zClose, /* String inserted after highlighted term */ |
| 106935 | - const char *zEllipsis, | |
| 106936 | - char **pzSnippet /* OUT: Snippet text */ | |
| 108119 | + const char *zEllipsis, /* String inserted between snippets */ | |
| 108120 | + StrBuffer *pOut /* Write output here */ | |
| 106937 | 108121 | ){ |
| 106938 | 108122 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 106939 | 108123 | int rc; /* Return code */ |
| 106940 | - int iCurrent = 0; | |
| 106941 | - int iStart = 0; | |
| 106942 | - int iEnd; | |
| 106943 | - | |
| 108124 | + const char *zDoc; /* Document text to extract snippet from */ | |
| 108125 | + int nDoc; /* Size of zDoc in bytes */ | |
| 108126 | + int iCurrent = 0; /* Current token number of document */ | |
| 108127 | + int iEnd = 0; /* Byte offset of end of current token */ | |
| 108128 | + int isShiftDone = 0; /* True after snippet is shifted */ | |
| 108129 | + int iPos = pFragment->iPos; /* First token of snippet */ | |
| 108130 | + u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ | |
| 108131 | + int iCol = pFragment->iCol+1; /* Query column to extract text from */ | |
| 106944 | 108132 | sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ |
| 106945 | 108133 | sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ |
| 106946 | - const char *ZDUMMY; /* Dummy arguments used with tokenizer */ | |
| 106947 | - int DUMMY1, DUMMY2, DUMMY3; /* Dummy arguments used with tokenizer */ | |
| 106948 | - | |
| 106949 | - StrBuffer res = {0, 0, 0}; /* Result string */ | |
| 106950 | - | |
| 106951 | - /* Open a token cursor on the document. Read all tokens up to and | |
| 106952 | - ** including token iPos (the first token of the snippet). Set variable | |
| 106953 | - ** iStart to the byte offset in zDoc of the start of token iPos. | |
| 106954 | - */ | |
| 108134 | + const char *ZDUMMY; /* Dummy argument used with tokenizer */ | |
| 108135 | + int DUMMY1; /* Dummy argument used with tokenizer */ | |
| 108136 | + | |
| 108137 | + zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); | |
| 108138 | + if( zDoc==0 ){ | |
| 108139 | + if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ | |
| 108140 | + return SQLITE_NOMEM; | |
| 108141 | + } | |
| 108142 | + return SQLITE_OK; | |
| 108143 | + } | |
| 108144 | + nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); | |
| 108145 | + | |
| 108146 | + /* Open a token cursor on the document. */ | |
| 106955 | 108147 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 106956 | 108148 | rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 106957 | - while( rc==SQLITE_OK && iCurrent<iPos ){ | |
| 106958 | - rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iStart, &DUMMY2, &iCurrent); | |
| 106959 | - } | |
| 106960 | - iEnd = iStart; | |
| 106961 | - | |
| 106962 | - if( rc==SQLITE_OK && iStart>0 ){ | |
| 106963 | - rc = fts3StringAppend(&res, zEllipsis, -1); | |
| 106964 | - } | |
| 108149 | + if( rc!=SQLITE_OK ){ | |
| 108150 | + return rc; | |
| 108151 | + } | |
| 108152 | + pC->pTokenizer = pTab->pTokenizer; | |
| 106965 | 108153 | |
| 106966 | 108154 | while( rc==SQLITE_OK ){ |
| 106967 | - int iBegin; | |
| 106968 | - int iFin; | |
| 108155 | + int iBegin; /* Offset in zDoc of start of token */ | |
| 108156 | + int iFin; /* Offset in zDoc of end of token */ | |
| 108157 | + int isHighlight; /* True for highlighted terms */ | |
| 108158 | + | |
| 106969 | 108159 | rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent); |
| 106970 | - | |
| 106971 | - if( rc==SQLITE_OK ){ | |
| 106972 | - if( iCurrent>=(iPos+nSnippet) ){ | |
| 106973 | - rc = SQLITE_DONE; | |
| 106974 | - }else{ | |
| 106975 | - iEnd = iFin; | |
| 106976 | - if( hlmask & ((u64)1 << (iCurrent-iPos)) ){ | |
| 106977 | - if( fts3StringAppend(&res, &zDoc[iStart], iBegin-iStart) | |
| 106978 | - || fts3StringAppend(&res, zOpen, -1) | |
| 106979 | - || fts3StringAppend(&res, &zDoc[iBegin], iEnd-iBegin) | |
| 106980 | - || fts3StringAppend(&res, zClose, -1) | |
| 106981 | - ){ | |
| 106982 | - rc = SQLITE_NOMEM; | |
| 106983 | - } | |
| 106984 | - iStart = iEnd; | |
| 106985 | - } | |
| 106986 | - } | |
| 106987 | - } | |
| 106988 | - } | |
| 106989 | - assert( rc!=SQLITE_OK ); | |
| 106990 | - if( rc==SQLITE_DONE ){ | |
| 106991 | - rc = fts3StringAppend(&res, &zDoc[iStart], iEnd-iStart); | |
| 106992 | - if( rc==SQLITE_OK ){ | |
| 106993 | - rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); | |
| 106994 | - if( rc==SQLITE_OK ){ | |
| 106995 | - rc = fts3StringAppend(&res, zEllipsis, -1); | |
| 106996 | - }else if( rc==SQLITE_DONE ){ | |
| 106997 | - rc = fts3StringAppend(&res, &zDoc[iEnd], -1); | |
| 106998 | - } | |
| 106999 | - } | |
| 108160 | + if( rc!=SQLITE_OK ){ | |
| 108161 | + if( rc==SQLITE_DONE ){ | |
| 108162 | + /* Special case - the last token of the snippet is also the last token | |
| 108163 | + ** of the column. Append any punctuation that occurred between the end | |
| 108164 | + ** of the previous token and the end of the document to the output. | |
| 108165 | + ** Then break out of the loop. */ | |
| 108166 | + rc = fts3StringAppend(pOut, &zDoc[iEnd], -1); | |
| 108167 | + } | |
| 108168 | + break; | |
| 108169 | + } | |
| 108170 | + if( iCurrent<iPos ){ continue; } | |
| 108171 | + | |
| 108172 | + if( !isShiftDone ){ | |
| 108173 | + int n = nDoc - iBegin; | |
| 108174 | + rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask); | |
| 108175 | + isShiftDone = 1; | |
| 108176 | + | |
| 108177 | + /* Now that the shift has been done, check if the initial "..." are | |
| 108178 | + ** required. They are required if (a) this is not the first fragment, | |
| 108179 | + ** or (b) this fragment does not begin at position 0 of its column. | |
| 108180 | + */ | |
| 108181 | + if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){ | |
| 108182 | + rc = fts3StringAppend(pOut, zEllipsis, -1); | |
| 108183 | + } | |
| 108184 | + if( rc!=SQLITE_OK || iCurrent<iPos ) continue; | |
| 108185 | + } | |
| 108186 | + | |
| 108187 | + if( iCurrent>=(iPos+nSnippet) ){ | |
| 108188 | + if( isLast ){ | |
| 108189 | + rc = fts3StringAppend(pOut, zEllipsis, -1); | |
| 108190 | + } | |
| 108191 | + break; | |
| 108192 | + } | |
| 108193 | + | |
| 108194 | + /* Set isHighlight to true if this term should be highlighted. */ | |
| 108195 | + isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0; | |
| 108196 | + | |
| 108197 | + if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd); | |
| 108198 | + if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1); | |
| 108199 | + if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin); | |
| 108200 | + if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1); | |
| 108201 | + | |
| 108202 | + iEnd = iFin; | |
| 107000 | 108203 | } |
| 107001 | 108204 | |
| 107002 | 108205 | pMod->xClose(pC); |
| 107003 | - if( rc!=SQLITE_OK ){ | |
| 107004 | - sqlite3_free(res.z); | |
| 107005 | - }else{ | |
| 107006 | - *pzSnippet = res.z; | |
| 107007 | - } | |
| 107008 | 108206 | return rc; |
| 107009 | 108207 | } |
| 107010 | 108208 | |
| 107011 | 108209 | |
| 107012 | 108210 | /* |
| 107013 | -** An instance of this structure is used to collect the 'global' part of | |
| 107014 | -** the matchinfo statistics. The 'global' part consists of the following: | |
| 107015 | -** | |
| 107016 | -** 1. The number of phrases in the query (nPhrase). | |
| 107017 | -** | |
| 107018 | -** 2. The number of columns in the FTS3 table (nCol). | |
| 107019 | -** | |
| 107020 | -** 3. A matrix of (nPhrase*nCol) integers containing the sum of the | |
| 107021 | -** number of hits for each phrase in each column across all rows | |
| 107022 | -** of the table. | |
| 107023 | -** | |
| 107024 | -** The total size of the global matchinfo array, assuming the number of | |
| 107025 | -** columns is N and the number of phrases is P is: | |
| 107026 | -** | |
| 107027 | -** 2 + P*(N+1) | |
| 107028 | -** | |
| 107029 | -** The number of hits for the 3rd phrase in the second column is found | |
| 107030 | -** using the expression: | |
| 107031 | -** | |
| 107032 | -** aGlobal[2 + P*(1+2) + 1] | |
| 107033 | -*/ | |
| 107034 | -typedef struct MatchInfo MatchInfo; | |
| 107035 | -struct MatchInfo { | |
| 107036 | - Fts3Table *pTab; /* FTS3 Table */ | |
| 107037 | - Fts3Cursor *pCursor; /* FTS3 Cursor */ | |
| 107038 | - int iPhrase; /* Number of phrases so far */ | |
| 107039 | - int nCol; /* Number of columns in table */ | |
| 107040 | - u32 *aGlobal; /* Pre-allocated buffer */ | |
| 107041 | -}; | |
| 107042 | - | |
| 107043 | -/* | |
| 107044 | -** This function is used to count the entries in a column-list (delta-encoded | |
| 107045 | -** list of term offsets within a single column of a single row). | |
| 108211 | +** This function is used to count the entries in a column-list (a | |
| 108212 | +** delta-encoded list of term offsets within a single column of a single | |
| 108213 | +** row). When this function is called, *ppCollist should point to the | |
| 108214 | +** beginning of the first varint in the column-list (the varint that | |
| 108215 | +** contains the position of the first matching term in the column data). | |
| 108216 | +** Before returning, *ppCollist is set to point to the first byte after | |
| 108217 | +** the last varint in the column-list (either the 0x00 signifying the end | |
| 108218 | +** of the position-list, or the 0x01 that precedes the column number of | |
| 108219 | +** the next column in the position-list). | |
| 108220 | +** | |
| 108221 | +** The number of elements in the column-list is returned. | |
| 107046 | 108222 | */ |
| 107047 | 108223 | static int fts3ColumnlistCount(char **ppCollist){ |
| 107048 | 108224 | char *pEnd = *ppCollist; |
| 107049 | 108225 | char c = 0; |
| 107050 | 108226 | int nEntry = 0; |
| @@ -107057,158 +108233,445 @@ | ||
| 107057 | 108233 | |
| 107058 | 108234 | *ppCollist = pEnd; |
| 107059 | 108235 | return nEntry; |
| 107060 | 108236 | } |
| 107061 | 108237 | |
| 107062 | -static void fts3LoadColumnlistCounts(char **pp, u32 *aOut){ | |
| 108238 | +static void fts3LoadColumnlistCounts(char **pp, u32 *aOut, int isGlobal){ | |
| 107063 | 108239 | char *pCsr = *pp; |
| 107064 | 108240 | while( *pCsr ){ |
| 108241 | + int nHit; | |
| 107065 | 108242 | sqlite3_int64 iCol = 0; |
| 107066 | 108243 | if( *pCsr==0x01 ){ |
| 107067 | 108244 | pCsr++; |
| 107068 | 108245 | pCsr += sqlite3Fts3GetVarint(pCsr, &iCol); |
| 107069 | 108246 | } |
| 107070 | - aOut[iCol] += fts3ColumnlistCount(&pCsr); | |
| 108247 | + nHit = fts3ColumnlistCount(&pCsr); | |
| 108248 | + assert( nHit>0 ); | |
| 108249 | + if( isGlobal ){ | |
| 108250 | + aOut[iCol*3+1]++; | |
| 108251 | + } | |
| 108252 | + aOut[iCol*3] += nHit; | |
| 107071 | 108253 | } |
| 107072 | 108254 | pCsr++; |
| 107073 | 108255 | *pp = pCsr; |
| 107074 | 108256 | } |
| 107075 | 108257 | |
| 107076 | 108258 | /* |
| 107077 | 108259 | ** fts3ExprIterate() callback used to collect the "global" matchinfo stats |
| 107078 | -** for a single query. | |
| 108260 | +** for a single query. The "global" stats are those elements of the matchinfo | |
| 108261 | +** array that are constant for all rows returned by the current query. | |
| 107079 | 108262 | */ |
| 107080 | 108263 | static int fts3ExprGlobalMatchinfoCb( |
| 107081 | 108264 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 108265 | + int iPhrase, /* Phrase number (numbered from zero) */ | |
| 107082 | 108266 | void *pCtx /* Pointer to MatchInfo structure */ |
| 107083 | 108267 | ){ |
| 107084 | 108268 | MatchInfo *p = (MatchInfo *)pCtx; |
| 107085 | 108269 | char *pCsr; |
| 107086 | 108270 | char *pEnd; |
| 107087 | - const int iStart = 2 + p->nCol*p->iPhrase; | |
| 108271 | + const int iStart = 2 + (iPhrase * p->nCol * 3) + 1; | |
| 107088 | 108272 | |
| 107089 | 108273 | assert( pExpr->isLoaded ); |
| 107090 | 108274 | |
| 107091 | 108275 | /* Fill in the global hit count matrix row for this phrase. */ |
| 107092 | 108276 | pCsr = pExpr->aDoclist; |
| 107093 | 108277 | pEnd = &pExpr->aDoclist[pExpr->nDoclist]; |
| 107094 | 108278 | while( pCsr<pEnd ){ |
| 107095 | - while( *pCsr++ & 0x80 ); | |
| 107096 | - fts3LoadColumnlistCounts(&pCsr, &p->aGlobal[iStart]); | |
| 108279 | + while( *pCsr++ & 0x80 ); /* Skip past docid. */ | |
| 108280 | + fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 1); | |
| 107097 | 108281 | } |
| 107098 | 108282 | |
| 107099 | - p->iPhrase++; | |
| 107100 | 108283 | return SQLITE_OK; |
| 107101 | 108284 | } |
| 107102 | 108285 | |
| 108286 | +/* | |
| 108287 | +** fts3ExprIterate() callback used to collect the "local" matchinfo stats | |
| 108288 | +** for a single query. The "local" stats are those elements of the matchinfo | |
| 108289 | +** array that are different for each row returned by the query. | |
| 108290 | +*/ | |
| 107103 | 108291 | static int fts3ExprLocalMatchinfoCb( |
| 107104 | 108292 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 108293 | + int iPhrase, /* Phrase number */ | |
| 107105 | 108294 | void *pCtx /* Pointer to MatchInfo structure */ |
| 107106 | 108295 | ){ |
| 107107 | 108296 | MatchInfo *p = (MatchInfo *)pCtx; |
| 107108 | - int iPhrase = p->iPhrase++; | |
| 107109 | 108297 | |
| 107110 | 108298 | if( pExpr->aDoclist ){ |
| 107111 | 108299 | char *pCsr; |
| 107112 | - int iOffset = 2 + p->nCol*(p->aGlobal[0]+iPhrase); | |
| 108300 | + int iStart = 2 + (iPhrase * p->nCol * 3); | |
| 108301 | + int i; | |
| 107113 | 108302 | |
| 107114 | - memset(&p->aGlobal[iOffset], 0, p->nCol*sizeof(u32)); | |
| 108303 | + for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0; | |
| 108304 | + | |
| 107115 | 108305 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1); |
| 107116 | - if( pCsr ) fts3LoadColumnlistCounts(&pCsr, &p->aGlobal[iOffset]); | |
| 108306 | + if( pCsr ){ | |
| 108307 | + fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0); | |
| 108308 | + } | |
| 107117 | 108309 | } |
| 107118 | 108310 | |
| 107119 | 108311 | return SQLITE_OK; |
| 107120 | 108312 | } |
| 107121 | 108313 | |
| 107122 | 108314 | /* |
| 107123 | -** Populate pCsr->aMatchinfo[] with data for the current row. The 'matchinfo' | |
| 107124 | -** data is an array of 32-bit unsigned integers (C type u32). | |
| 108315 | +** Populate pCsr->aMatchinfo[] with data for the current row. The | |
| 108316 | +** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). | |
| 107125 | 108317 | */ |
| 107126 | 108318 | static int fts3GetMatchinfo(Fts3Cursor *pCsr){ |
| 107127 | - MatchInfo g; | |
| 108319 | + MatchInfo sInfo; | |
| 107128 | 108320 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 108321 | + int rc = SQLITE_OK; | |
| 108322 | + | |
| 108323 | + sInfo.pCursor = pCsr; | |
| 108324 | + sInfo.nCol = pTab->nColumn; | |
| 108325 | + | |
| 107129 | 108326 | if( pCsr->aMatchinfo==0 ){ |
| 107130 | - int rc; | |
| 107131 | - int nPhrase; | |
| 107132 | - int nMatchinfo; | |
| 107133 | - | |
| 107134 | - g.pTab = pTab; | |
| 107135 | - g.nCol = pTab->nColumn; | |
| 107136 | - g.iPhrase = 0; | |
| 107137 | - rc = fts3ExprLoadDoclists(pCsr, &nPhrase); | |
| 108327 | + /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the | |
| 108328 | + ** matchinfo function has been called for this query. In this case | |
| 108329 | + ** allocate the array used to accumulate the matchinfo data and | |
| 108330 | + ** initialize those elements that are constant for every row. | |
| 108331 | + */ | |
| 108332 | + int nPhrase; /* Number of phrases */ | |
| 108333 | + int nMatchinfo; /* Number of u32 elements in match-info */ | |
| 108334 | + | |
| 108335 | + /* Load doclists for each phrase in the query. */ | |
| 108336 | + rc = fts3ExprLoadDoclists(pCsr, &nPhrase, 0); | |
| 107138 | 108337 | if( rc!=SQLITE_OK ){ |
| 107139 | 108338 | return rc; |
| 107140 | 108339 | } |
| 108340 | + nMatchinfo = 2 + 3*sInfo.nCol*nPhrase; | |
| 108341 | + if( pTab->bHasDocsize ){ | |
| 108342 | + nMatchinfo += 1 + 2*pTab->nColumn; | |
| 108343 | + } | |
| 107141 | 108344 | |
| 107142 | - nMatchinfo = 2 + 2*g.nCol*nPhrase; | |
| 107143 | - | |
| 107144 | - g.iPhrase = 0; | |
| 107145 | - g.aGlobal = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo); | |
| 107146 | - if( !g.aGlobal ){ | |
| 108345 | + sInfo.aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo); | |
| 108346 | + if( !sInfo.aMatchinfo ){ | |
| 107147 | 108347 | return SQLITE_NOMEM; |
| 107148 | 108348 | } |
| 107149 | - memset(g.aGlobal, 0, sizeof(u32)*nMatchinfo); | |
| 107150 | - | |
| 107151 | - g.aGlobal[0] = nPhrase; | |
| 107152 | - g.aGlobal[1] = g.nCol; | |
| 107153 | - (void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb, (void *)&g); | |
| 107154 | - | |
| 107155 | - pCsr->aMatchinfo = g.aGlobal; | |
| 107156 | - } | |
| 107157 | - | |
| 107158 | - g.pTab = pTab; | |
| 107159 | - g.pCursor = pCsr; | |
| 107160 | - g.nCol = pTab->nColumn; | |
| 107161 | - g.iPhrase = 0; | |
| 107162 | - g.aGlobal = pCsr->aMatchinfo; | |
| 107163 | - | |
| 107164 | - if( pCsr->isMatchinfoOk ){ | |
| 107165 | - (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void *)&g); | |
| 107166 | - pCsr->isMatchinfoOk = 0; | |
| 108349 | + memset(sInfo.aMatchinfo, 0, sizeof(u32)*nMatchinfo); | |
| 108350 | + | |
| 108351 | + | |
| 108352 | + /* First element of match-info is the number of phrases in the query */ | |
| 108353 | + sInfo.aMatchinfo[0] = nPhrase; | |
| 108354 | + sInfo.aMatchinfo[1] = sInfo.nCol; | |
| 108355 | + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo); | |
| 108356 | + if( pTab->bHasDocsize ){ | |
| 108357 | + int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; | |
| 108358 | + rc = sqlite3Fts3MatchinfoDocsizeGlobal(pCsr, &sInfo.aMatchinfo[ofst]); | |
| 108359 | + } | |
| 108360 | + pCsr->aMatchinfo = sInfo.aMatchinfo; | |
| 108361 | + pCsr->isMatchinfoNeeded = 1; | |
| 108362 | + } | |
| 108363 | + | |
| 108364 | + sInfo.aMatchinfo = pCsr->aMatchinfo; | |
| 108365 | + if( rc==SQLITE_OK && pCsr->isMatchinfoNeeded ){ | |
| 108366 | + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void*)&sInfo); | |
| 108367 | + if( pTab->bHasDocsize ){ | |
| 108368 | + int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; | |
| 108369 | + rc = sqlite3Fts3MatchinfoDocsizeLocal(pCsr, &sInfo.aMatchinfo[ofst]); | |
| 108370 | + } | |
| 108371 | + pCsr->isMatchinfoNeeded = 0; | |
| 107167 | 108372 | } |
| 107168 | 108373 | |
| 107169 | 108374 | return SQLITE_OK; |
| 107170 | 108375 | } |
| 107171 | 108376 | |
| 107172 | -SQLITE_PRIVATE void sqlite3Fts3Snippet2( | |
| 108377 | +/* | |
| 108378 | +** Implementation of snippet() function. | |
| 108379 | +*/ | |
| 108380 | +SQLITE_PRIVATE void sqlite3Fts3Snippet( | |
| 107173 | 108381 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 107174 | 108382 | Fts3Cursor *pCsr, /* Cursor object */ |
| 107175 | 108383 | const char *zStart, /* Snippet start text - "<b>" */ |
| 107176 | 108384 | const char *zEnd, /* Snippet end text - "</b>" */ |
| 107177 | 108385 | const char *zEllipsis, /* Snippet ellipsis text - "<b>...</b>" */ |
| 107178 | 108386 | int iCol, /* Extract snippet from this column */ |
| 107179 | 108387 | int nToken /* Approximate number of tokens in snippet */ |
| 107180 | 108388 | ){ |
| 107181 | - int rc; | |
| 107182 | - int iPos = 0; | |
| 107183 | - u64 hlmask = 0; | |
| 107184 | - char *z = 0; | |
| 107185 | - int nDoc; | |
| 107186 | - const char *zDoc; | |
| 107187 | - | |
| 107188 | - rc = fts3BestSnippet(nToken, pCsr, iCol, &iPos, &hlmask); | |
| 107189 | - | |
| 107190 | - nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1); | |
| 107191 | - zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1); | |
| 107192 | - | |
| 107193 | - if( rc==SQLITE_OK ){ | |
| 107194 | - rc = fts3SnippetText( | |
| 107195 | - pCsr, zDoc, nDoc, nToken, iPos, hlmask, zStart, zEnd, zEllipsis, &z); | |
| 107196 | - } | |
| 108389 | + Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; | |
| 108390 | + int rc = SQLITE_OK; | |
| 108391 | + int i; | |
| 108392 | + StrBuffer res = {0, 0, 0}; | |
| 108393 | + | |
| 108394 | + /* The returned text includes up to four fragments of text extracted from | |
| 108395 | + ** the data in the current row. The first iteration of the for(...) loop | |
| 108396 | + ** below attempts to locate a single fragment of text nToken tokens in | |
| 108397 | + ** size that contains at least one instance of all phrases in the query | |
| 108398 | + ** expression that appear in the current row. If such a fragment of text | |
| 108399 | + ** cannot be found, the second iteration of the loop attempts to locate | |
| 108400 | + ** a pair of fragments, and so on. | |
| 108401 | + */ | |
| 108402 | + int nSnippet = 0; /* Number of fragments in this snippet */ | |
| 108403 | + SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */ | |
| 108404 | + int nFToken = -1; /* Number of tokens in each fragment */ | |
| 108405 | + | |
| 108406 | + if( !pCsr->pExpr ){ | |
| 108407 | + sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); | |
| 108408 | + return; | |
| 108409 | + } | |
| 108410 | + | |
| 108411 | + for(nSnippet=1; 1; nSnippet++){ | |
| 108412 | + | |
| 108413 | + int iSnip; /* Loop counter 0..nSnippet-1 */ | |
| 108414 | + u64 mCovered = 0; /* Bitmask of phrases covered by snippet */ | |
| 108415 | + u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */ | |
| 108416 | + | |
| 108417 | + if( nToken>=0 ){ | |
| 108418 | + nFToken = (nToken+nSnippet-1) / nSnippet; | |
| 108419 | + }else{ | |
| 108420 | + nFToken = -1 * nToken; | |
| 108421 | + } | |
| 108422 | + | |
| 108423 | + for(iSnip=0; iSnip<nSnippet; iSnip++){ | |
| 108424 | + int iBestScore = -1; /* Best score of columns checked so far */ | |
| 108425 | + int iRead; /* Used to iterate through columns */ | |
| 108426 | + SnippetFragment *pFragment = &aSnippet[iSnip]; | |
| 108427 | + | |
| 108428 | + memset(pFragment, 0, sizeof(*pFragment)); | |
| 108429 | + | |
| 108430 | + /* Loop through all columns of the table being considered for snippets. | |
| 108431 | + ** If the iCol argument to this function was negative, this means all | |
| 108432 | + ** columns of the FTS3 table. Otherwise, only column iCol is considered. | |
| 108433 | + */ | |
| 108434 | + for(iRead=0; iRead<pTab->nColumn; iRead++){ | |
| 108435 | + SnippetFragment sF; | |
| 108436 | + int iS; | |
| 108437 | + if( iCol>=0 && iRead!=iCol ) continue; | |
| 108438 | + | |
| 108439 | + /* Find the best snippet of nFToken tokens in column iRead. */ | |
| 108440 | + rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS); | |
| 108441 | + if( rc!=SQLITE_OK ){ | |
| 108442 | + goto snippet_out; | |
| 108443 | + } | |
| 108444 | + if( iS>iBestScore ){ | |
| 108445 | + *pFragment = sF; | |
| 108446 | + iBestScore = iS; | |
| 108447 | + } | |
| 108448 | + } | |
| 108449 | + | |
| 108450 | + mCovered |= pFragment->covered; | |
| 108451 | + } | |
| 108452 | + | |
| 108453 | + /* If all query phrases seen by fts3BestSnippet() are present in at least | |
| 108454 | + ** one of the nSnippet snippet fragments, break out of the loop. | |
| 108455 | + */ | |
| 108456 | + assert( (mCovered&mSeen)==mCovered ); | |
| 108457 | + if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break; | |
| 108458 | + } | |
| 108459 | + | |
| 108460 | + assert( nFToken>0 ); | |
| 108461 | + | |
| 108462 | + for(i=0; i<nSnippet && rc==SQLITE_OK; i++){ | |
| 108463 | + rc = fts3SnippetText(pCsr, &aSnippet[i], | |
| 108464 | + i, (i==nSnippet-1), nFToken, zStart, zEnd, zEllipsis, &res | |
| 108465 | + ); | |
| 108466 | + } | |
| 108467 | + | |
| 108468 | + snippet_out: | |
| 107197 | 108469 | if( rc!=SQLITE_OK ){ |
| 107198 | 108470 | sqlite3_result_error_code(pCtx, rc); |
| 108471 | + sqlite3_free(res.z); | |
| 108472 | + }else{ | |
| 108473 | + sqlite3_result_text(pCtx, res.z, -1, sqlite3_free); | |
| 108474 | + } | |
| 108475 | +} | |
| 108476 | + | |
| 108477 | + | |
| 108478 | +typedef struct TermOffset TermOffset; | |
| 108479 | +typedef struct TermOffsetCtx TermOffsetCtx; | |
| 108480 | + | |
| 108481 | +struct TermOffset { | |
| 108482 | + char *pList; /* Position-list */ | |
| 108483 | + int iPos; /* Position just read from pList */ | |
| 108484 | + int iOff; /* Offset of this term from read positions */ | |
| 108485 | +}; | |
| 108486 | + | |
| 108487 | +struct TermOffsetCtx { | |
| 108488 | + int iCol; /* Column of table to populate aTerm for */ | |
| 108489 | + int iTerm; | |
| 108490 | + sqlite3_int64 iDocid; | |
| 108491 | + TermOffset *aTerm; | |
| 108492 | +}; | |
| 108493 | + | |
| 108494 | +/* | |
| 108495 | +** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets(). | |
| 108496 | +*/ | |
| 108497 | +static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ | |
| 108498 | + TermOffsetCtx *p = (TermOffsetCtx *)ctx; | |
| 108499 | + int nTerm; /* Number of tokens in phrase */ | |
| 108500 | + int iTerm; /* For looping through nTerm phrase terms */ | |
| 108501 | + char *pList; /* Pointer to position list for phrase */ | |
| 108502 | + int iPos = 0; /* First position in position-list */ | |
| 108503 | + | |
| 108504 | + UNUSED_PARAMETER(iPhrase); | |
| 108505 | + pList = sqlite3Fts3FindPositions(pExpr, p->iDocid, p->iCol); | |
| 108506 | + nTerm = pExpr->pPhrase->nToken; | |
| 108507 | + if( pList ){ | |
| 108508 | + fts3GetDeltaPosition(&pList, &iPos); | |
| 108509 | + assert( iPos>=0 ); | |
| 108510 | + } | |
| 108511 | + | |
| 108512 | + for(iTerm=0; iTerm<nTerm; iTerm++){ | |
| 108513 | + TermOffset *pT = &p->aTerm[p->iTerm++]; | |
| 108514 | + pT->iOff = nTerm-iTerm-1; | |
| 108515 | + pT->pList = pList; | |
| 108516 | + pT->iPos = iPos; | |
| 108517 | + } | |
| 108518 | + | |
| 108519 | + return SQLITE_OK; | |
| 108520 | +} | |
| 108521 | + | |
| 108522 | +/* | |
| 108523 | +** Implementation of offsets() function. | |
| 108524 | +*/ | |
| 108525 | +SQLITE_PRIVATE void sqlite3Fts3Offsets( | |
| 108526 | + sqlite3_context *pCtx, /* SQLite function call context */ | |
| 108527 | + Fts3Cursor *pCsr /* Cursor object */ | |
| 108528 | +){ | |
| 108529 | + Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; | |
| 108530 | + sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; | |
| 108531 | + const char *ZDUMMY; /* Dummy argument used with xNext() */ | |
| 108532 | + int NDUMMY; /* Dummy argument used with xNext() */ | |
| 108533 | + int rc; /* Return Code */ | |
| 108534 | + int nToken; /* Number of tokens in query */ | |
| 108535 | + int iCol; /* Column currently being processed */ | |
| 108536 | + StrBuffer res = {0, 0, 0}; /* Result string */ | |
| 108537 | + TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */ | |
| 108538 | + | |
| 108539 | + if( !pCsr->pExpr ){ | |
| 108540 | + sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); | |
| 108541 | + return; | |
| 108542 | + } | |
| 108543 | + | |
| 108544 | + memset(&sCtx, 0, sizeof(sCtx)); | |
| 108545 | + assert( pCsr->isRequireSeek==0 ); | |
| 108546 | + | |
| 108547 | + /* Count the number of terms in the query */ | |
| 108548 | + rc = fts3ExprLoadDoclists(pCsr, 0, &nToken); | |
| 108549 | + if( rc!=SQLITE_OK ) goto offsets_out; | |
| 108550 | + | |
| 108551 | + /* Allocate the array of TermOffset iterators. */ | |
| 108552 | + sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken); | |
| 108553 | + if( 0==sCtx.aTerm ){ | |
| 108554 | + rc = SQLITE_NOMEM; | |
| 108555 | + goto offsets_out; | |
| 108556 | + } | |
| 108557 | + sCtx.iDocid = pCsr->iPrevId; | |
| 108558 | + | |
| 108559 | + /* Loop through the table columns, appending offset information to | |
| 108560 | + ** string-buffer res for each column. | |
| 108561 | + */ | |
| 108562 | + for(iCol=0; iCol<pTab->nColumn; iCol++){ | |
| 108563 | + sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ | |
| 108564 | + int iStart; | |
| 108565 | + int iEnd; | |
| 108566 | + int iCurrent; | |
| 108567 | + const char *zDoc; | |
| 108568 | + int nDoc; | |
| 108569 | + | |
| 108570 | + /* Initialize the contents of sCtx.aTerm[] for column iCol. There is | |
| 108571 | + ** no way that this operation can fail, so the return code from | |
| 108572 | + ** fts3ExprIterate() can be discarded. | |
| 108573 | + */ | |
| 108574 | + sCtx.iCol = iCol; | |
| 108575 | + sCtx.iTerm = 0; | |
| 108576 | + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx); | |
| 108577 | + | |
| 108578 | + /* Retreive the text stored in column iCol. If an SQL NULL is stored | |
| 108579 | + ** in column iCol, jump immediately to the next iteration of the loop. | |
| 108580 | + ** If an OOM occurs while retrieving the data (this can happen if SQLite | |
| 108581 | + ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM | |
| 108582 | + ** to the caller. | |
| 108583 | + */ | |
| 108584 | + zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1); | |
| 108585 | + nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1); | |
| 108586 | + if( zDoc==0 ){ | |
| 108587 | + if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){ | |
| 108588 | + continue; | |
| 108589 | + } | |
| 108590 | + rc = SQLITE_NOMEM; | |
| 108591 | + goto offsets_out; | |
| 108592 | + } | |
| 108593 | + | |
| 108594 | + /* Initialize a tokenizer iterator to iterate through column iCol. */ | |
| 108595 | + rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); | |
| 108596 | + if( rc!=SQLITE_OK ) goto offsets_out; | |
| 108597 | + pC->pTokenizer = pTab->pTokenizer; | |
| 108598 | + | |
| 108599 | + rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); | |
| 108600 | + while( rc==SQLITE_OK ){ | |
| 108601 | + int i; /* Used to loop through terms */ | |
| 108602 | + int iMinPos = 0x7FFFFFFF; /* Position of next token */ | |
| 108603 | + TermOffset *pTerm = 0; /* TermOffset associated with next token */ | |
| 108604 | + | |
| 108605 | + for(i=0; i<nToken; i++){ | |
| 108606 | + TermOffset *pT = &sCtx.aTerm[i]; | |
| 108607 | + if( pT->pList && (pT->iPos-pT->iOff)<iMinPos ){ | |
| 108608 | + iMinPos = pT->iPos-pT->iOff; | |
| 108609 | + pTerm = pT; | |
| 108610 | + } | |
| 108611 | + } | |
| 108612 | + | |
| 108613 | + if( !pTerm ){ | |
| 108614 | + /* All offsets for this column have been gathered. */ | |
| 108615 | + break; | |
| 108616 | + }else{ | |
| 108617 | + assert( iCurrent<=iMinPos ); | |
| 108618 | + if( 0==(0xFE&*pTerm->pList) ){ | |
| 108619 | + pTerm->pList = 0; | |
| 108620 | + }else{ | |
| 108621 | + fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos); | |
| 108622 | + } | |
| 108623 | + while( rc==SQLITE_OK && iCurrent<iMinPos ){ | |
| 108624 | + rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); | |
| 108625 | + } | |
| 108626 | + if( rc==SQLITE_OK ){ | |
| 108627 | + char aBuffer[64]; | |
| 108628 | + sqlite3_snprintf(sizeof(aBuffer), aBuffer, | |
| 108629 | + "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart | |
| 108630 | + ); | |
| 108631 | + rc = fts3StringAppend(&res, aBuffer, -1); | |
| 108632 | + } | |
| 108633 | + } | |
| 108634 | + } | |
| 108635 | + if( rc==SQLITE_DONE ){ | |
| 108636 | + rc = SQLITE_CORRUPT; | |
| 108637 | + } | |
| 108638 | + | |
| 108639 | + pMod->xClose(pC); | |
| 108640 | + if( rc!=SQLITE_OK ) goto offsets_out; | |
| 108641 | + } | |
| 108642 | + | |
| 108643 | + offsets_out: | |
| 108644 | + sqlite3_free(sCtx.aTerm); | |
| 108645 | + assert( rc!=SQLITE_DONE ); | |
| 108646 | + if( rc!=SQLITE_OK ){ | |
| 108647 | + sqlite3_result_error_code(pCtx, rc); | |
| 108648 | + sqlite3_free(res.z); | |
| 107199 | 108649 | }else{ |
| 107200 | - sqlite3_result_text(pCtx, z, -1, sqlite3_free); | |
| 108650 | + sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free); | |
| 107201 | 108651 | } |
| 108652 | + return; | |
| 107202 | 108653 | } |
| 107203 | 108654 | |
| 108655 | +/* | |
| 108656 | +** Implementation of matchinfo() function. | |
| 108657 | +*/ | |
| 107204 | 108658 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *pCsr){ |
| 107205 | - int rc = fts3GetMatchinfo(pCsr); | |
| 108659 | + int rc; | |
| 108660 | + if( !pCsr->pExpr ){ | |
| 108661 | + sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); | |
| 108662 | + return; | |
| 108663 | + } | |
| 108664 | + rc = fts3GetMatchinfo(pCsr); | |
| 107206 | 108665 | if( rc!=SQLITE_OK ){ |
| 107207 | 108666 | sqlite3_result_error_code(pContext, rc); |
| 107208 | 108667 | }else{ |
| 107209 | - int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*2); | |
| 108668 | + Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab; | |
| 108669 | + int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*3); | |
| 108670 | + if( pTab->bHasDocsize ){ | |
| 108671 | + n += sizeof(u32)*(1 + 2*pTab->nColumn); | |
| 108672 | + } | |
| 107210 | 108673 | sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); |
| 107211 | 108674 | } |
| 107212 | 108675 | } |
| 107213 | 108676 | |
| 107214 | 108677 | #endif |
| @@ -107634,10 +109097,11 @@ | ||
| 107634 | 109097 | |
| 107635 | 109098 | sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); |
| 107636 | 109099 | rc = sqlite3_step(pRtree->pReadNode); |
| 107637 | 109100 | if( rc==SQLITE_ROW ){ |
| 107638 | 109101 | const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); |
| 109102 | + assert( sqlite3_column_bytes(pRtree->pReadNode, 0)==pRtree->iNodeSize ); | |
| 107639 | 109103 | memcpy(pNode->zData, zBlob, pRtree->iNodeSize); |
| 107640 | 109104 | nodeReference(pParent); |
| 107641 | 109105 | }else{ |
| 107642 | 109106 | sqlite3_free(pNode); |
| 107643 | 109107 | pNode = 0; |
| @@ -109830,35 +111294,73 @@ | ||
| 109830 | 111294 | |
| 109831 | 111295 | return rc; |
| 109832 | 111296 | } |
| 109833 | 111297 | |
| 109834 | 111298 | /* |
| 109835 | -** This routine queries database handle db for the page-size used by | |
| 109836 | -** database zDb. If successful, the page-size in bytes is written to | |
| 109837 | -** *piPageSize and SQLITE_OK returned. Otherwise, and an SQLite error | |
| 109838 | -** code is returned. | |
| 111299 | +** The second argument to this function contains the text of an SQL statement | |
| 111300 | +** that returns a single integer value. The statement is compiled and executed | |
| 111301 | +** using database connection db. If successful, the integer value returned | |
| 111302 | +** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error | |
| 111303 | +** code is returned and the value of *piVal after returning is not defined. | |
| 109839 | 111304 | */ |
| 109840 | -static int getPageSize(sqlite3 *db, const char *zDb, int *piPageSize){ | |
| 111305 | +static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){ | |
| 109841 | 111306 | int rc = SQLITE_NOMEM; |
| 111307 | + if( zSql ){ | |
| 111308 | + sqlite3_stmt *pStmt = 0; | |
| 111309 | + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); | |
| 111310 | + if( rc==SQLITE_OK ){ | |
| 111311 | + if( SQLITE_ROW==sqlite3_step(pStmt) ){ | |
| 111312 | + *piVal = sqlite3_column_int(pStmt, 0); | |
| 111313 | + } | |
| 111314 | + rc = sqlite3_finalize(pStmt); | |
| 111315 | + } | |
| 111316 | + } | |
| 111317 | + return rc; | |
| 111318 | +} | |
| 111319 | + | |
| 111320 | +/* | |
| 111321 | +** This function is called from within the xConnect() or xCreate() method to | |
| 111322 | +** determine the node-size used by the rtree table being created or connected | |
| 111323 | +** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned. | |
| 111324 | +** Otherwise, an SQLite error code is returned. | |
| 111325 | +** | |
| 111326 | +** If this function is being called as part of an xConnect(), then the rtree | |
| 111327 | +** table already exists. In this case the node-size is determined by inspecting | |
| 111328 | +** the root node of the tree. | |
| 111329 | +** | |
| 111330 | +** Otherwise, for an xCreate(), use 64 bytes less than the database page-size. | |
| 111331 | +** This ensures that each node is stored on a single database page. If the | |
| 111332 | +** database page-size is so large that more than RTREE_MAXCELLS entries | |
| 111333 | +** would fit in a single node, use a smaller node-size. | |
| 111334 | +*/ | |
| 111335 | +static int getNodeSize( | |
| 111336 | + sqlite3 *db, /* Database handle */ | |
| 111337 | + Rtree *pRtree, /* Rtree handle */ | |
| 111338 | + int isCreate /* True for xCreate, false for xConnect */ | |
| 111339 | +){ | |
| 111340 | + int rc; | |
| 109842 | 111341 | char *zSql; |
| 109843 | - sqlite3_stmt *pStmt = 0; | |
| 109844 | - | |
| 109845 | - zSql = sqlite3_mprintf("PRAGMA %Q.page_size", zDb); | |
| 109846 | - if( !zSql ){ | |
| 109847 | - return SQLITE_NOMEM; | |
| 111342 | + if( isCreate ){ | |
| 111343 | + int iPageSize; | |
| 111344 | + zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb); | |
| 111345 | + rc = getIntFromStmt(db, zSql, &iPageSize); | |
| 111346 | + if( rc==SQLITE_OK ){ | |
| 111347 | + pRtree->iNodeSize = iPageSize-64; | |
| 111348 | + if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ | |
| 111349 | + pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; | |
| 111350 | + } | |
| 111351 | + } | |
| 111352 | + }else{ | |
| 111353 | + zSql = sqlite3_mprintf( | |
| 111354 | + "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1", | |
| 111355 | + pRtree->zDb, pRtree->zName | |
| 111356 | + ); | |
| 111357 | + rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); | |
| 109848 | 111358 | } |
| 109849 | 111359 | |
| 109850 | - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); | |
| 109851 | 111360 | sqlite3_free(zSql); |
| 109852 | - if( rc!=SQLITE_OK ){ | |
| 109853 | - return rc; | |
| 109854 | - } | |
| 109855 | - | |
| 109856 | - if( SQLITE_ROW==sqlite3_step(pStmt) ){ | |
| 109857 | - *piPageSize = sqlite3_column_int(pStmt, 0); | |
| 109858 | - } | |
| 109859 | - return sqlite3_finalize(pStmt); | |
| 111361 | + return rc; | |
| 109860 | 111362 | } |
| 109861 | 111363 | |
| 109862 | 111364 | /* |
| 109863 | 111365 | ** This function is the implementation of both the xConnect and xCreate |
| 109864 | 111366 | ** methods of the r-tree virtual table. |
| @@ -109875,11 +111377,10 @@ | ||
| 109875 | 111377 | sqlite3_vtab **ppVtab, /* OUT: New virtual table */ |
| 109876 | 111378 | char **pzErr, /* OUT: Error message, if any */ |
| 109877 | 111379 | int isCreate /* True for xCreate, false for xConnect */ |
| 109878 | 111380 | ){ |
| 109879 | 111381 | int rc = SQLITE_OK; |
| 109880 | - int iPageSize = 0; | |
| 109881 | 111382 | Rtree *pRtree; |
| 109882 | 111383 | int nDb; /* Length of string argv[1] */ |
| 109883 | 111384 | int nName; /* Length of string argv[2] */ |
| 109884 | 111385 | int eCoordType = (int)pAux; |
| 109885 | 111386 | |
| @@ -109894,15 +111395,10 @@ | ||
| 109894 | 111395 | if( aErrMsg[iErr] ){ |
| 109895 | 111396 | *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); |
| 109896 | 111397 | return SQLITE_ERROR; |
| 109897 | 111398 | } |
| 109898 | 111399 | |
| 109899 | - rc = getPageSize(db, argv[1], &iPageSize); | |
| 109900 | - if( rc!=SQLITE_OK ){ | |
| 109901 | - return rc; | |
| 109902 | - } | |
| 109903 | - | |
| 109904 | 111400 | /* Allocate the sqlite3_vtab structure */ |
| 109905 | 111401 | nDb = strlen(argv[1]); |
| 109906 | 111402 | nName = strlen(argv[2]); |
| 109907 | 111403 | pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); |
| 109908 | 111404 | if( !pRtree ){ |
| @@ -109917,48 +111413,41 @@ | ||
| 109917 | 111413 | pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; |
| 109918 | 111414 | pRtree->eCoordType = eCoordType; |
| 109919 | 111415 | memcpy(pRtree->zDb, argv[1], nDb); |
| 109920 | 111416 | memcpy(pRtree->zName, argv[2], nName); |
| 109921 | 111417 | |
| 109922 | - /* Figure out the node size to use. By default, use 64 bytes less than | |
| 109923 | - ** the database page-size. This ensures that each node is stored on | |
| 109924 | - ** a single database page. | |
| 109925 | - ** | |
| 109926 | - ** If the databasd page-size is so large that more than RTREE_MAXCELLS | |
| 109927 | - ** entries would fit in a single node, use a smaller node-size. | |
| 109928 | - */ | |
| 109929 | - pRtree->iNodeSize = iPageSize-64; | |
| 109930 | - if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ | |
| 109931 | - pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; | |
| 109932 | - } | |
| 111418 | + /* Figure out the node size to use. */ | |
| 111419 | + rc = getNodeSize(db, pRtree, isCreate); | |
| 109933 | 111420 | |
| 109934 | 111421 | /* Create/Connect to the underlying relational database schema. If |
| 109935 | 111422 | ** that is successful, call sqlite3_declare_vtab() to configure |
| 109936 | 111423 | ** the r-tree table schema. |
| 109937 | 111424 | */ |
| 109938 | - if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ | |
| 109939 | - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); | |
| 109940 | - }else{ | |
| 109941 | - char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); | |
| 109942 | - char *zTmp; | |
| 109943 | - int ii; | |
| 109944 | - for(ii=4; zSql && ii<argc; ii++){ | |
| 109945 | - zTmp = zSql; | |
| 109946 | - zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); | |
| 109947 | - sqlite3_free(zTmp); | |
| 109948 | - } | |
| 109949 | - if( zSql ){ | |
| 109950 | - zTmp = zSql; | |
| 109951 | - zSql = sqlite3_mprintf("%s);", zTmp); | |
| 109952 | - sqlite3_free(zTmp); | |
| 109953 | - } | |
| 109954 | - if( !zSql ){ | |
| 109955 | - rc = SQLITE_NOMEM; | |
| 109956 | - }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ | |
| 109957 | - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); | |
| 109958 | - } | |
| 109959 | - sqlite3_free(zSql); | |
| 111425 | + if( rc==SQLITE_OK ){ | |
| 111426 | + if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ | |
| 111427 | + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); | |
| 111428 | + }else{ | |
| 111429 | + char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); | |
| 111430 | + char *zTmp; | |
| 111431 | + int ii; | |
| 111432 | + for(ii=4; zSql && ii<argc; ii++){ | |
| 111433 | + zTmp = zSql; | |
| 111434 | + zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); | |
| 111435 | + sqlite3_free(zTmp); | |
| 111436 | + } | |
| 111437 | + if( zSql ){ | |
| 111438 | + zTmp = zSql; | |
| 111439 | + zSql = sqlite3_mprintf("%s);", zTmp); | |
| 111440 | + sqlite3_free(zTmp); | |
| 111441 | + } | |
| 111442 | + if( !zSql ){ | |
| 111443 | + rc = SQLITE_NOMEM; | |
| 111444 | + }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ | |
| 111445 | + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); | |
| 111446 | + } | |
| 111447 | + sqlite3_free(zSql); | |
| 111448 | + } | |
| 109960 | 111449 | } |
| 109961 | 111450 | |
| 109962 | 111451 | if( rc==SQLITE_OK ){ |
| 109963 | 111452 | *ppVtab = (sqlite3_vtab *)pRtree; |
| 109964 | 111453 | }else{ |
| 109965 | 111454 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.6.22. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a one translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% are more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -305,10 +305,15 @@ | |
| 305 | #endif |
| 306 | #ifdef HAVE_INTTYPES_H |
| 307 | #include <inttypes.h> |
| 308 | #endif |
| 309 | |
| 310 | #define SQLITE_INDEX_SAMPLES 10 |
| 311 | |
| 312 | /* |
| 313 | ** This macro is used to "hide" some ugliness in casting an int |
| 314 | ** value to a ptr value under the MSVC 64-bit compiler. Casting |
| @@ -369,27 +374,22 @@ | |
| 369 | ** Exactly one of the following macros must be defined in order to |
| 370 | ** specify which memory allocation subsystem to use. |
| 371 | ** |
| 372 | ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() |
| 373 | ** SQLITE_MEMDEBUG // Debugging version of system malloc() |
| 374 | ** SQLITE_MEMORY_SIZE // internal allocator #1 |
| 375 | ** SQLITE_MMAP_HEAP_SIZE // internal mmap() allocator |
| 376 | ** SQLITE_POW2_MEMORY_SIZE // internal power-of-two allocator |
| 377 | ** |
| 378 | ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as |
| 379 | ** the default. |
| 380 | */ |
| 381 | #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\ |
| 382 | defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\ |
| 383 | defined(SQLITE_POW2_MEMORY_SIZE)>1 |
| 384 | # error "At most one of the following compile-time configuration options\ |
| 385 | is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\ |
| 386 | SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE" |
| 387 | #endif |
| 388 | #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\ |
| 389 | defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\ |
| 390 | defined(SQLITE_POW2_MEMORY_SIZE)==0 |
| 391 | # define SQLITE_SYSTEM_MALLOC 1 |
| 392 | #endif |
| 393 | |
| 394 | /* |
| 395 | ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the |
| @@ -629,17 +629,17 @@ | |
| 629 | ** |
| 630 | ** See also: [sqlite3_libversion()], |
| 631 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 632 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 633 | */ |
| 634 | #define SQLITE_VERSION "3.6.22" |
| 635 | #define SQLITE_VERSION_NUMBER 3006022 |
| 636 | #define SQLITE_SOURCE_ID "2010-01-02 19:02:02 51f7ee844057086789dcfcdcba7daf45343cae62" |
| 637 | |
| 638 | /* |
| 639 | ** CAPI3REF: Run-Time Library Version Numbers |
| 640 | ** KEYWORDS: sqlite3_version |
| 641 | ** |
| 642 | ** These interfaces provide the same information as the [SQLITE_VERSION], |
| 643 | ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| 644 | ** but are associated with the library instead of the header file. ^(Cautious |
| 645 | ** programmers might include assert() statements in their application to |
| @@ -657,21 +657,48 @@ | |
| 657 | ** macro. ^The sqlite3_libversion() function returns a pointer to the |
| 658 | ** to the sqlite3_version[] string constant. The sqlite3_libversion() |
| 659 | ** function is provided for use in DLLs since DLL users usually do not have |
| 660 | ** direct access to string constants within the DLL. ^The |
| 661 | ** sqlite3_libversion_number() function returns an integer equal to |
| 662 | ** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function a pointer |
| 663 | ** to a string constant whose value is the same as the [SQLITE_SOURCE_ID] |
| 664 | ** C preprocessor macro. |
| 665 | ** |
| 666 | ** See also: [sqlite_version()] and [sqlite_source_id()]. |
| 667 | */ |
| 668 | SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; |
| 669 | SQLITE_API const char *sqlite3_libversion(void); |
| 670 | SQLITE_API const char *sqlite3_sourceid(void); |
| 671 | SQLITE_API int sqlite3_libversion_number(void); |
| 672 | |
| 673 | /* |
| 674 | ** CAPI3REF: Test To See If The Library Is Threadsafe |
| 675 | ** |
| 676 | ** ^The sqlite3_threadsafe() function returns zero if and only if |
| 677 | ** SQLite was compiled mutexing code omitted due to the |
| @@ -959,10 +986,11 @@ | |
| 959 | #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ |
| 960 | #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ |
| 961 | #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ |
| 962 | #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ |
| 963 | #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ |
| 964 | #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ |
| 965 | #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ |
| 966 | #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ |
| 967 | #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ |
| 968 | #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ |
| @@ -1440,11 +1468,10 @@ | |
| 1440 | SQLITE_API int sqlite3_os_init(void); |
| 1441 | SQLITE_API int sqlite3_os_end(void); |
| 1442 | |
| 1443 | /* |
| 1444 | ** CAPI3REF: Configuring The SQLite Library |
| 1445 | ** EXPERIMENTAL |
| 1446 | ** |
| 1447 | ** The sqlite3_config() interface is used to make global configuration |
| 1448 | ** changes to SQLite in order to tune SQLite to the specific needs of |
| 1449 | ** the application. The default configuration is recommended for most |
| 1450 | ** applications and so this routine is usually not necessary. It is |
| @@ -1781,10 +1808,11 @@ | |
| 1781 | #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ |
| 1782 | /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ |
| 1783 | #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ |
| 1784 | #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ |
| 1785 | #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ |
| 1786 | |
| 1787 | /* |
| 1788 | ** CAPI3REF: Configuration Options |
| 1789 | ** EXPERIMENTAL |
| 1790 | ** |
| @@ -4183,10 +4211,11 @@ | |
| 4183 | sqlite3*, |
| 4184 | void*, |
| 4185 | void(*)(void*,sqlite3*,int eTextRep,const void*) |
| 4186 | ); |
| 4187 | |
| 4188 | /* |
| 4189 | ** Specify the key for an encrypted database. This routine should be |
| 4190 | ** called right after sqlite3_open(). |
| 4191 | ** |
| 4192 | ** The code to implement this API is not available in the public release |
| @@ -4208,10 +4237,29 @@ | |
| 4208 | SQLITE_API int sqlite3_rekey( |
| 4209 | sqlite3 *db, /* Database to be rekeyed */ |
| 4210 | const void *pKey, int nKey /* The new key */ |
| 4211 | ); |
| 4212 | |
| 4213 | /* |
| 4214 | ** CAPI3REF: Suspend Execution For A Short Time |
| 4215 | ** |
| 4216 | ** ^The sqlite3_sleep() function causes the current thread to suspend execution |
| 4217 | ** for at least a number of milliseconds specified in its parameter. |
| @@ -6169,10 +6217,28 @@ | |
| 6169 | ** case-indendent fashion, using the same definition of case independence |
| 6170 | ** that SQLite uses internally when comparing identifiers. |
| 6171 | */ |
| 6172 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 6173 | |
| 6174 | /* |
| 6175 | ** Undo the hack that converts floating point types to integer for |
| 6176 | ** builds on processors without floating point support. |
| 6177 | */ |
| 6178 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| @@ -6484,24 +6550,10 @@ | |
| 6484 | #define OMIT_TEMPDB 1 |
| 6485 | #else |
| 6486 | #define OMIT_TEMPDB 0 |
| 6487 | #endif |
| 6488 | |
| 6489 | /* |
| 6490 | ** If the following macro is set to 1, then NULL values are considered |
| 6491 | ** distinct when determining whether or not two entries are the same |
| 6492 | ** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL, |
| 6493 | ** OCELOT, and Firebird all work. The SQL92 spec explicitly says this |
| 6494 | ** is the way things are suppose to work. |
| 6495 | ** |
| 6496 | ** If the following macro is set to 0, the NULLs are indistinct for |
| 6497 | ** a UNIQUE index. In this mode, you can only have a single NULL entry |
| 6498 | ** for a column declared UNIQUE. This is the way Informix and SQL Server |
| 6499 | ** work. |
| 6500 | */ |
| 6501 | #define NULL_DISTINCT_FOR_UNIQUE 1 |
| 6502 | |
| 6503 | /* |
| 6504 | ** The "file format" number is an integer that is incremented whenever |
| 6505 | ** the VDBE-level file format changes. The following macros define the |
| 6506 | ** the default file format for new databases and the maximum file format |
| 6507 | ** that the library can read. |
| @@ -6509,10 +6561,14 @@ | |
| 6509 | #define SQLITE_MAX_FILE_FORMAT 4 |
| 6510 | #ifndef SQLITE_DEFAULT_FILE_FORMAT |
| 6511 | # define SQLITE_DEFAULT_FILE_FORMAT 1 |
| 6512 | #endif |
| 6513 | |
| 6514 | #ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS |
| 6515 | # define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 |
| 6516 | #endif |
| 6517 | |
| 6518 | /* |
| @@ -6753,11 +6809,10 @@ | |
| 6753 | */ |
| 6754 | typedef struct AggInfo AggInfo; |
| 6755 | typedef struct AuthContext AuthContext; |
| 6756 | typedef struct AutoincInfo AutoincInfo; |
| 6757 | typedef struct Bitvec Bitvec; |
| 6758 | typedef struct RowSet RowSet; |
| 6759 | typedef struct CollSeq CollSeq; |
| 6760 | typedef struct Column Column; |
| 6761 | typedef struct Db Db; |
| 6762 | typedef struct Schema Schema; |
| 6763 | typedef struct Expr Expr; |
| @@ -6774,20 +6829,21 @@ | |
| 6774 | typedef struct Lookaside Lookaside; |
| 6775 | typedef struct LookasideSlot LookasideSlot; |
| 6776 | typedef struct Module Module; |
| 6777 | typedef struct NameContext NameContext; |
| 6778 | typedef struct Parse Parse; |
| 6779 | typedef struct Savepoint Savepoint; |
| 6780 | typedef struct Select Select; |
| 6781 | typedef struct SrcList SrcList; |
| 6782 | typedef struct StrAccum StrAccum; |
| 6783 | typedef struct Table Table; |
| 6784 | typedef struct TableLock TableLock; |
| 6785 | typedef struct Token Token; |
| 6786 | typedef struct TriggerPrg TriggerPrg; |
| 6787 | typedef struct TriggerStep TriggerStep; |
| 6788 | typedef struct Trigger Trigger; |
| 6789 | typedef struct UnpackedRecord UnpackedRecord; |
| 6790 | typedef struct VTable VTable; |
| 6791 | typedef struct Walker Walker; |
| 6792 | typedef struct WherePlan WherePlan; |
| 6793 | typedef struct WhereInfo WhereInfo; |
| @@ -6881,10 +6937,11 @@ | |
| 6881 | SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); |
| 6882 | SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); |
| 6883 | SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); |
| 6884 | SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); |
| 6885 | SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); |
| 6886 | SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); |
| 6887 | SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); |
| 6888 | SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); |
| 6889 | SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); |
| 6890 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); |
| @@ -7413,10 +7470,11 @@ | |
| 7413 | SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); |
| 7414 | SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); |
| 7415 | SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); |
| 7416 | SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); |
| 7417 | SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); |
| 7418 | SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); |
| 7419 | SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int); |
| 7420 | SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); |
| 7421 | SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); |
| 7422 | SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); |
| @@ -8186,19 +8244,19 @@ | |
| 8186 | #endif |
| 8187 | }; |
| 8188 | |
| 8189 | /* |
| 8190 | ** These macros can be used to test, set, or clear bits in the |
| 8191 | ** Db.flags field. |
| 8192 | */ |
| 8193 | #define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) |
| 8194 | #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) |
| 8195 | #define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) |
| 8196 | #define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) |
| 8197 | |
| 8198 | /* |
| 8199 | ** Allowed values for the DB.flags field. |
| 8200 | ** |
| 8201 | ** The DB_SchemaLoaded flag is set after the database schema has been |
| 8202 | ** read into internal hash tables. |
| 8203 | ** |
| 8204 | ** DB_UnresetViews means that one or more views have column names that |
| @@ -8258,11 +8316,11 @@ | |
| 8258 | struct FuncDefHash { |
| 8259 | FuncDef *a[23]; /* Hash table for functions */ |
| 8260 | }; |
| 8261 | |
| 8262 | /* |
| 8263 | ** Each database is an instance of the following structure. |
| 8264 | ** |
| 8265 | ** The sqlite.lastRowid records the last insert rowid generated by an |
| 8266 | ** insert statement. Inserts on views do not affect its value. Each |
| 8267 | ** trigger has its own context, so that lastRowid can be updated inside |
| 8268 | ** triggers as usual. The previous value will be restored once the trigger |
| @@ -8297,10 +8355,11 @@ | |
| 8297 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 8298 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 8299 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 8300 | u8 dfltJournalMode; /* Default journal mode for attached dbs */ |
| 8301 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| 8302 | int nextPagesize; /* Pagesize after VACUUM if >0 */ |
| 8303 | int nTable; /* Number of tables in the database */ |
| 8304 | CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ |
| 8305 | i64 lastRowid; /* ROWID of most recent insert (see above) */ |
| 8306 | u32 magic; /* Magic number for detect library misuse */ |
| @@ -9873,10 +9932,12 @@ | |
| 9873 | int isMutexInit; /* True after mutexes are initialized */ |
| 9874 | int isMallocInit; /* True after malloc is initialized */ |
| 9875 | int isPCacheInit; /* True after malloc is initialized */ |
| 9876 | sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ |
| 9877 | int nRefInitMutex; /* Number of users of pInitMutex */ |
| 9878 | }; |
| 9879 | |
| 9880 | /* |
| 9881 | ** Context pointer passed down through the tree-walk. |
| 9882 | */ |
| @@ -9914,20 +9975,31 @@ | |
| 9914 | while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ |
| 9915 | } \ |
| 9916 | } |
| 9917 | |
| 9918 | /* |
| 9919 | ** The SQLITE_CORRUPT_BKPT macro can be either a constant (for production |
| 9920 | ** builds) or a function call (for debugging). If it is a function call, |
| 9921 | ** it allows the operator to set a breakpoint at the spot where database |
| 9922 | ** corruption is first detected. |
| 9923 | */ |
| 9924 | #ifdef SQLITE_DEBUG |
| 9925 | SQLITE_PRIVATE int sqlite3Corrupt(void); |
| 9926 | # define SQLITE_CORRUPT_BKPT sqlite3Corrupt() |
| 9927 | #else |
| 9928 | # define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT |
| 9929 | #endif |
| 9930 | |
| 9931 | /* |
| 9932 | ** The ctype.h header is needed for non-ASCII systems. It is also |
| 9933 | ** needed by FTS3 when FTS3 is included in the amalgamation. |
| @@ -10025,11 +10097,15 @@ | |
| 10025 | |
| 10026 | SQLITE_PRIVATE int sqlite3StatusValue(int); |
| 10027 | SQLITE_PRIVATE void sqlite3StatusAdd(int, int); |
| 10028 | SQLITE_PRIVATE void sqlite3StatusSet(int, int); |
| 10029 | |
| 10030 | SQLITE_PRIVATE int sqlite3IsNaN(double); |
| 10031 | |
| 10032 | SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); |
| 10033 | #ifndef SQLITE_OMIT_TRACE |
| 10034 | SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); |
| 10035 | #endif |
| @@ -10042,11 +10118,10 @@ | |
| 10042 | #if defined(SQLITE_TEST) |
| 10043 | SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); |
| 10044 | #endif |
| 10045 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...); |
| 10046 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); |
| 10047 | SQLITE_PRIVATE void sqlite3ErrorClear(Parse*); |
| 10048 | SQLITE_PRIVATE int sqlite3Dequote(char*); |
| 10049 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); |
| 10050 | SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); |
| 10051 | SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); |
| 10052 | SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); |
| @@ -10212,17 +10287,10 @@ | |
| 10212 | SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); |
| 10213 | SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); |
| 10214 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); |
| 10215 | SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); |
| 10216 | SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); |
| 10217 | #ifdef SQLITE_DEBUG |
| 10218 | SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3*); |
| 10219 | SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3*); |
| 10220 | #else |
| 10221 | # define sqlite3SafetyOn(A) 0 |
| 10222 | # define sqlite3SafetyOff(A) 0 |
| 10223 | #endif |
| 10224 | SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); |
| 10225 | SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); |
| 10226 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); |
| 10227 | |
| 10228 | #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) |
| @@ -10754,10 +10822,12 @@ | |
| 10754 | 0, /* isMutexInit */ |
| 10755 | 0, /* isMallocInit */ |
| 10756 | 0, /* isPCacheInit */ |
| 10757 | 0, /* pInitMutex */ |
| 10758 | 0, /* nRefInitMutex */ |
| 10759 | }; |
| 10760 | |
| 10761 | |
| 10762 | /* |
| 10763 | ** Hash table for global functions - functions common to all |
| @@ -10878,11 +10948,11 @@ | |
| 10878 | ** then this routine is not threadsafe. |
| 10879 | */ |
| 10880 | SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ |
| 10881 | wsdStatInit; |
| 10882 | if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ |
| 10883 | return SQLITE_MISUSE; |
| 10884 | } |
| 10885 | *pCurrent = wsdStat.nowValue[op]; |
| 10886 | *pHighwater = wsdStat.mxValue[op]; |
| 10887 | if( resetFlag ){ |
| 10888 | wsdStat.mxValue[op] = wsdStat.nowValue[op]; |
| @@ -12007,12 +12077,12 @@ | |
| 12007 | FUNCTION(current_time, 0, 0, 0, ctimeFunc ), |
| 12008 | FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), |
| 12009 | FUNCTION(current_date, 0, 0, 0, cdateFunc ), |
| 12010 | #else |
| 12011 | STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc), |
| 12012 | STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d", 0, currentTimeFunc), |
| 12013 | STR_FUNCTION(current_date, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), |
| 12014 | #endif |
| 12015 | }; |
| 12016 | int i; |
| 12017 | FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); |
| 12018 | FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs); |
| @@ -12135,15 +12205,15 @@ | |
| 12135 | int flags, |
| 12136 | int *pFlagsOut |
| 12137 | ){ |
| 12138 | int rc; |
| 12139 | DO_OS_MALLOC_TEST(0); |
| 12140 | /* 0x7f1f is a mask of SQLITE_OPEN_ flags that are valid to be passed |
| 12141 | ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, |
| 12142 | ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before |
| 12143 | ** reaching the VFS. */ |
| 12144 | rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f1f, pFlagsOut); |
| 12145 | assert( rc==SQLITE_OK || pFile->pMethods==0 ); |
| 12146 | return rc; |
| 12147 | } |
| 12148 | SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
| 12149 | return pVfs->xDelete(pVfs, zPath, dirSync); |
| @@ -12514,10 +12584,13 @@ | |
| 12514 | nByte = ROUND8(nByte); |
| 12515 | p = malloc( nByte+8 ); |
| 12516 | if( p ){ |
| 12517 | p[0] = nByte; |
| 12518 | p++; |
| 12519 | } |
| 12520 | return (void *)p; |
| 12521 | } |
| 12522 | |
| 12523 | /* |
| @@ -12532,10 +12605,22 @@ | |
| 12532 | sqlite3_int64 *p = (sqlite3_int64*)pPrior; |
| 12533 | assert( pPrior!=0 ); |
| 12534 | p--; |
| 12535 | free(p); |
| 12536 | } |
| 12537 | |
| 12538 | /* |
| 12539 | ** Like realloc(). Resize an allocation previously obtained from |
| 12540 | ** sqlite3MemMalloc(). |
| 12541 | ** |
| @@ -12547,32 +12632,24 @@ | |
| 12547 | */ |
| 12548 | static void *sqlite3MemRealloc(void *pPrior, int nByte){ |
| 12549 | sqlite3_int64 *p = (sqlite3_int64*)pPrior; |
| 12550 | assert( pPrior!=0 && nByte>0 ); |
| 12551 | nByte = ROUND8(nByte); |
| 12552 | p = (sqlite3_int64*)pPrior; |
| 12553 | p--; |
| 12554 | p = realloc(p, nByte+8 ); |
| 12555 | if( p ){ |
| 12556 | p[0] = nByte; |
| 12557 | p++; |
| 12558 | } |
| 12559 | return (void*)p; |
| 12560 | } |
| 12561 | |
| 12562 | /* |
| 12563 | ** Report the allocated size of a prior return from xMalloc() |
| 12564 | ** or xRealloc(). |
| 12565 | */ |
| 12566 | static int sqlite3MemSize(void *pPrior){ |
| 12567 | sqlite3_int64 *p; |
| 12568 | if( pPrior==0 ) return 0; |
| 12569 | p = (sqlite3_int64*)pPrior; |
| 12570 | p--; |
| 12571 | return (int)p[0]; |
| 12572 | } |
| 12573 | |
| 12574 | /* |
| 12575 | ** Round up a request size to the next valid allocation size. |
| 12576 | */ |
| 12577 | static int sqlite3MemRoundup(int n){ |
| 12578 | return ROUND8(n); |
| @@ -12825,10 +12902,35 @@ | |
| 12825 | ** Round up a request size to the next valid allocation size. |
| 12826 | */ |
| 12827 | static int sqlite3MemRoundup(int n){ |
| 12828 | return ROUND8(n); |
| 12829 | } |
| 12830 | |
| 12831 | /* |
| 12832 | ** Allocate nByte bytes of memory. |
| 12833 | */ |
| 12834 | static void *sqlite3MemMalloc(int nByte){ |
| @@ -12876,11 +12978,12 @@ | |
| 12876 | } |
| 12877 | pHdr->iSize = nByte; |
| 12878 | adjustStats(nByte, +1); |
| 12879 | pInt = (int*)&pHdr[1]; |
| 12880 | pInt[nReserve/sizeof(int)] = REARGUARD; |
| 12881 | memset(pInt, 0x65, nReserve); |
| 12882 | p = (void*)pInt; |
| 12883 | } |
| 12884 | sqlite3_mutex_leave(mem.mutex); |
| 12885 | return p; |
| 12886 | } |
| @@ -12912,12 +13015,12 @@ | |
| 12912 | mem.pLast = pHdr->pPrev; |
| 12913 | } |
| 12914 | z = (char*)pBt; |
| 12915 | z -= pHdr->nTitle; |
| 12916 | adjustStats(pHdr->iSize, -1); |
| 12917 | memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + |
| 12918 | pHdr->iSize + sizeof(int) + pHdr->nTitle); |
| 12919 | free(z); |
| 12920 | sqlite3_mutex_leave(mem.mutex); |
| 12921 | } |
| 12922 | |
| 12923 | /* |
| @@ -12936,11 +13039,11 @@ | |
| 12936 | pOldHdr = sqlite3MemsysGetHeader(pPrior); |
| 12937 | pNew = sqlite3MemMalloc(nByte); |
| 12938 | if( pNew ){ |
| 12939 | memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize); |
| 12940 | if( nByte>pOldHdr->iSize ){ |
| 12941 | memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize); |
| 12942 | } |
| 12943 | sqlite3MemFree(pPrior); |
| 12944 | } |
| 12945 | return pNew; |
| 12946 | } |
| @@ -14017,11 +14120,15 @@ | |
| 14017 | /* Make sure mem5.aiFreelist[iLogsize] contains at least one free |
| 14018 | ** block. If not, then split a block of the next larger power of |
| 14019 | ** two in order to create a new free block of size iLogsize. |
| 14020 | */ |
| 14021 | for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){} |
| 14022 | if( iBin>LOGMAX ) return 0; |
| 14023 | i = memsys5UnlinkFirst(iBin); |
| 14024 | while( iBin>iLogsize ){ |
| 14025 | int newSize; |
| 14026 | |
| 14027 | iBin--; |
| @@ -15294,11 +15401,20 @@ | |
| 15294 | struct sqlite3_mutex { |
| 15295 | CRITICAL_SECTION mutex; /* Mutex controlling the lock */ |
| 15296 | int id; /* Mutex type */ |
| 15297 | int nRef; /* Number of enterances */ |
| 15298 | DWORD owner; /* Thread holding this mutex */ |
| 15299 | }; |
| 15300 | |
| 15301 | /* |
| 15302 | ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, |
| 15303 | ** or WinCE. Return false (zero) for Win95, Win98, or WinME. |
| 15304 | ** |
| @@ -15337,21 +15453,32 @@ | |
| 15337 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are |
| 15338 | ** intended for use only inside assert() statements. |
| 15339 | */ |
| 15340 | static int winMutexHeld(sqlite3_mutex *p){ |
| 15341 | return p->nRef!=0 && p->owner==GetCurrentThreadId(); |
| 15342 | } |
| 15343 | static int winMutexNotheld(sqlite3_mutex *p){ |
| 15344 | return p->nRef==0 || p->owner!=GetCurrentThreadId(); |
| 15345 | } |
| 15346 | #endif |
| 15347 | |
| 15348 | |
| 15349 | /* |
| 15350 | ** Initialize and deinitialize the mutex subsystem. |
| 15351 | */ |
| 15352 | static sqlite3_mutex winMutex_staticMutexes[6]; |
| 15353 | static int winMutex_isInit = 0; |
| 15354 | /* As winMutexInit() and winMutexEnd() are called as part |
| 15355 | ** of the sqlite3_initialize and sqlite3_shutdown() |
| 15356 | ** processing, the "interlocked" magic is probably not |
| 15357 | ** strictly necessary. |
| @@ -15481,18 +15608,25 @@ | |
| 15481 | ** mutex must be exited an equal number of times before another thread |
| 15482 | ** can enter. If the same thread tries to enter any other kind of mutex |
| 15483 | ** more than once, the behavior is undefined. |
| 15484 | */ |
| 15485 | static void winMutexEnter(sqlite3_mutex *p){ |
| 15486 | assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); |
| 15487 | EnterCriticalSection(&p->mutex); |
| 15488 | p->owner = GetCurrentThreadId(); |
| 15489 | p->nRef++; |
| 15490 | } |
| 15491 | static int winMutexTry(sqlite3_mutex *p){ |
| 15492 | int rc = SQLITE_BUSY; |
| 15493 | assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); |
| 15494 | /* |
| 15495 | ** The sqlite3_mutex_try() routine is very rarely used, and when it |
| 15496 | ** is used it is merely an optimization. So it is OK for it to always |
| 15497 | ** fail. |
| 15498 | ** |
| @@ -15502,16 +15636,21 @@ | |
| 15502 | ** For that reason, we will omit this optimization for now. See |
| 15503 | ** ticket #2685. |
| 15504 | */ |
| 15505 | #if 0 |
| 15506 | if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){ |
| 15507 | p->owner = GetCurrentThreadId(); |
| 15508 | p->nRef++; |
| 15509 | rc = SQLITE_OK; |
| 15510 | } |
| 15511 | #else |
| 15512 | UNUSED_PARAMETER(p); |
| 15513 | #endif |
| 15514 | return rc; |
| 15515 | } |
| 15516 | |
| 15517 | /* |
| @@ -15519,15 +15658,21 @@ | |
| 15519 | ** previously entered by the same thread. The behavior |
| 15520 | ** is undefined if the mutex is not currently entered or |
| 15521 | ** is not currently allocated. SQLite will never do either. |
| 15522 | */ |
| 15523 | static void winMutexLeave(sqlite3_mutex *p){ |
| 15524 | assert( p->nRef>0 ); |
| 15525 | assert( p->owner==GetCurrentThreadId() ); |
| 15526 | p->nRef--; |
| 15527 | assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 15528 | LeaveCriticalSection(&p->mutex); |
| 15529 | } |
| 15530 | |
| 15531 | SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ |
| 15532 | static sqlite3_mutex_methods sMutex = { |
| 15533 | winMutexInit, |
| @@ -16868,11 +17013,13 @@ | |
| 16868 | } |
| 16869 | i = prefix!=0; |
| 16870 | while( nPad-- ) bufpt[i++] = '0'; |
| 16871 | length = width; |
| 16872 | } |
| 16873 | #endif |
| 16874 | break; |
| 16875 | case etSIZE: |
| 16876 | *(va_arg(ap,int*)) = pAccum->nChar; |
| 16877 | length = width = 0; |
| 16878 | break; |
| @@ -17198,10 +17345,32 @@ | |
| 17198 | sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 17199 | va_end(ap); |
| 17200 | z = sqlite3StrAccumFinish(&acc); |
| 17201 | return z; |
| 17202 | } |
| 17203 | |
| 17204 | #if defined(SQLITE_DEBUG) |
| 17205 | /* |
| 17206 | ** A version of printf() that understands %lld. Used for debugging. |
| 17207 | ** The printf() built into some versions of windows does not understand %lld |
| @@ -17721,10 +17890,11 @@ | |
| 17721 | int rc; /* Value to return */ |
| 17722 | char *zErrMsg; /* Error message written here */ |
| 17723 | u8 explain; /* True if EXPLAIN present on SQL command */ |
| 17724 | u8 changeCntOn; /* True to update the change-counter */ |
| 17725 | u8 expired; /* True if the VM needs to be recompiled */ |
| 17726 | u8 minWriteFileFormat; /* Minimum file format for writable database files */ |
| 17727 | u8 inVtabMethod; /* See comments above */ |
| 17728 | u8 usesStmtJournal; /* True if uses a statement journal */ |
| 17729 | u8 readOnly; /* True for read-only statements */ |
| 17730 | u8 isPrepareV2; /* True if prepared with prepare_v2() */ |
| @@ -17782,11 +17952,15 @@ | |
| 17782 | SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); |
| 17783 | SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); |
| 17784 | SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); |
| 17785 | SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); |
| 17786 | SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); |
| 17787 | SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); |
| 17788 | SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); |
| 17789 | SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); |
| 17790 | SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); |
| 17791 | SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); |
| 17792 | SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int); |
| @@ -18388,10 +18562,11 @@ | |
| 18388 | static int dummy = 0; |
| 18389 | dummy += x; |
| 18390 | } |
| 18391 | #endif |
| 18392 | |
| 18393 | /* |
| 18394 | ** Return true if the floating point value is Not a Number (NaN). |
| 18395 | ** |
| 18396 | ** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN. |
| 18397 | ** Otherwise, we have our own implementation that works on most systems. |
| @@ -18432,10 +18607,11 @@ | |
| 18432 | rc = isnan(x); |
| 18433 | #endif /* SQLITE_HAVE_ISNAN */ |
| 18434 | testcase( rc ); |
| 18435 | return rc; |
| 18436 | } |
| 18437 | |
| 18438 | /* |
| 18439 | ** Compute a string length that is limited to what can be stored in |
| 18440 | ** lower 30 bits of a 32-bit signed integer. |
| 18441 | ** |
| @@ -18503,27 +18679,24 @@ | |
| 18503 | ** stored by this function into the database handle using sqlite3Error(). |
| 18504 | ** Function sqlite3Error() should be used during statement execution |
| 18505 | ** (sqlite3_step() etc.). |
| 18506 | */ |
| 18507 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ |
| 18508 | va_list ap; |
| 18509 | sqlite3 *db = pParse->db; |
| 18510 | pParse->nErr++; |
| 18511 | sqlite3DbFree(db, pParse->zErrMsg); |
| 18512 | va_start(ap, zFormat); |
| 18513 | pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap); |
| 18514 | va_end(ap); |
| 18515 | pParse->rc = SQLITE_ERROR; |
| 18516 | } |
| 18517 | |
| 18518 | /* |
| 18519 | ** Clear the error message in pParse, if any |
| 18520 | */ |
| 18521 | SQLITE_PRIVATE void sqlite3ErrorClear(Parse *pParse){ |
| 18522 | sqlite3DbFree(pParse->db, pParse->zErrMsg); |
| 18523 | pParse->zErrMsg = 0; |
| 18524 | pParse->nErr = 0; |
| 18525 | } |
| 18526 | |
| 18527 | /* |
| 18528 | ** Convert an SQL-style quoted string into a normal string by removing |
| 18529 | ** the quote characters. The conversion is done in-place. If the |
| @@ -18612,10 +18785,11 @@ | |
| 18612 | return 0; |
| 18613 | } |
| 18614 | z += incr; |
| 18615 | *realnum = 0; |
| 18616 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18617 | if( *z=='.' ){ |
| 18618 | z += incr; |
| 18619 | if( !sqlite3Isdigit(*z) ) return 0; |
| 18620 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18621 | *realnum = 1; |
| @@ -18625,10 +18799,11 @@ | |
| 18625 | if( *z=='+' || *z=='-' ) z += incr; |
| 18626 | if( !sqlite3Isdigit(*z) ) return 0; |
| 18627 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18628 | *realnum = 1; |
| 18629 | } |
| 18630 | return *z==0; |
| 18631 | } |
| 18632 | |
| 18633 | /* |
| 18634 | ** The string z[] is an ASCII representation of a real number. |
| @@ -18786,10 +18961,13 @@ | |
| 18786 | static int compare2pow63(const char *zNum){ |
| 18787 | int c; |
| 18788 | c = memcmp(zNum,"922337203685477580",18)*10; |
| 18789 | if( c==0 ){ |
| 18790 | c = zNum[18] - '8'; |
| 18791 | } |
| 18792 | return c; |
| 18793 | } |
| 18794 | |
| 18795 | |
| @@ -18822,10 +19000,13 @@ | |
| 18822 | while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */ |
| 18823 | for(i=0; (c=zNum[i])>='0' && c<='9'; i++){ |
| 18824 | v = v*10 + c - '0'; |
| 18825 | } |
| 18826 | *pNum = neg ? -v : v; |
| 18827 | if( c!=0 || (i==0 && zStart==zNum) || i>19 ){ |
| 18828 | /* zNum is empty or contains non-numeric text or is longer |
| 18829 | ** than 19 digits (thus guaranting that it is too large) */ |
| 18830 | return 0; |
| 18831 | }else if( i<19 ){ |
| @@ -18865,10 +19046,13 @@ | |
| 18865 | if( negFlag ) neg = 1-neg; |
| 18866 | while( *zNum=='0' ){ |
| 18867 | zNum++; /* Skip leading zeros. Ticket #2454 */ |
| 18868 | } |
| 18869 | for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); } |
| 18870 | if( i<19 ){ |
| 18871 | /* Guaranteed to fit if less than 19 digits */ |
| 18872 | return 1; |
| 18873 | }else if( i>19 ){ |
| 18874 | /* Guaranteed to be too big if greater than 19 digits */ |
| @@ -18905,13 +19089,15 @@ | |
| 18905 | /* The longest decimal representation of a 32 bit integer is 10 digits: |
| 18906 | ** |
| 18907 | ** 1234567890 |
| 18908 | ** 2^31 -> 2147483648 |
| 18909 | */ |
| 18910 | if( i>10 ){ |
| 18911 | return 0; |
| 18912 | } |
| 18913 | if( v-neg>2147483647 ){ |
| 18914 | return 0; |
| 18915 | } |
| 18916 | if( neg ){ |
| 18917 | v = -v; |
| @@ -19354,68 +19540,21 @@ | |
| 19354 | } |
| 19355 | return zBlob; |
| 19356 | } |
| 19357 | #endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */ |
| 19358 | |
| 19359 | |
| 19360 | /* |
| 19361 | ** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY. |
| 19362 | ** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN |
| 19363 | ** when this routine is called. |
| 19364 | ** |
| 19365 | ** This routine is called when entering an SQLite API. The SQLITE_MAGIC_OPEN |
| 19366 | ** value indicates that the database connection passed into the API is |
| 19367 | ** open and is not being used by another thread. By changing the value |
| 19368 | ** to SQLITE_MAGIC_BUSY we indicate that the connection is in use. |
| 19369 | ** sqlite3SafetyOff() below will change the value back to SQLITE_MAGIC_OPEN |
| 19370 | ** when the API exits. |
| 19371 | ** |
| 19372 | ** This routine is a attempt to detect if two threads use the |
| 19373 | ** same sqlite* pointer at the same time. There is a race |
| 19374 | ** condition so it is possible that the error is not detected. |
| 19375 | ** But usually the problem will be seen. The result will be an |
| 19376 | ** error which can be used to debug the application that is |
| 19377 | ** using SQLite incorrectly. |
| 19378 | ** |
| 19379 | ** Ticket #202: If db->magic is not a valid open value, take care not |
| 19380 | ** to modify the db structure at all. It could be that db is a stale |
| 19381 | ** pointer. In other words, it could be that there has been a prior |
| 19382 | ** call to sqlite3_close(db) and db has been deallocated. And we do |
| 19383 | ** not want to write into deallocated memory. |
| 19384 | */ |
| 19385 | #ifdef SQLITE_DEBUG |
| 19386 | SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3 *db){ |
| 19387 | if( db->magic==SQLITE_MAGIC_OPEN ){ |
| 19388 | db->magic = SQLITE_MAGIC_BUSY; |
| 19389 | assert( sqlite3_mutex_held(db->mutex) ); |
| 19390 | return 0; |
| 19391 | }else if( db->magic==SQLITE_MAGIC_BUSY ){ |
| 19392 | db->magic = SQLITE_MAGIC_ERROR; |
| 19393 | db->u1.isInterrupted = 1; |
| 19394 | } |
| 19395 | return 1; |
| 19396 | } |
| 19397 | #endif |
| 19398 | |
| 19399 | /* |
| 19400 | ** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN. |
| 19401 | ** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY |
| 19402 | ** when this routine is called. |
| 19403 | */ |
| 19404 | #ifdef SQLITE_DEBUG |
| 19405 | SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3 *db){ |
| 19406 | if( db->magic==SQLITE_MAGIC_BUSY ){ |
| 19407 | db->magic = SQLITE_MAGIC_OPEN; |
| 19408 | assert( sqlite3_mutex_held(db->mutex) ); |
| 19409 | return 0; |
| 19410 | }else{ |
| 19411 | db->magic = SQLITE_MAGIC_ERROR; |
| 19412 | db->u1.isInterrupted = 1; |
| 19413 | return 1; |
| 19414 | } |
| 19415 | } |
| 19416 | #endif |
| 19417 | |
| 19418 | /* |
| 19419 | ** Check to make sure we have a valid db pointer. This test is not |
| 19420 | ** foolproof but it does provide some measure of protection against |
| 19421 | ** misuse of the interface such as passing in db pointers that are |
| @@ -19429,17 +19568,20 @@ | |
| 19429 | ** open properly and is not fit for general use but which can be |
| 19430 | ** used as an argument to sqlite3_errmsg() or sqlite3_close(). |
| 19431 | */ |
| 19432 | SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){ |
| 19433 | u32 magic; |
| 19434 | if( db==0 ) return 0; |
| 19435 | magic = db->magic; |
| 19436 | if( magic!=SQLITE_MAGIC_OPEN |
| 19437 | #ifdef SQLITE_DEBUG |
| 19438 | && magic!=SQLITE_MAGIC_BUSY |
| 19439 | #endif |
| 19440 | ){ |
| 19441 | return 0; |
| 19442 | }else{ |
| 19443 | return 1; |
| 19444 | } |
| 19445 | } |
| @@ -19446,12 +19588,17 @@ | |
| 19446 | SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ |
| 19447 | u32 magic; |
| 19448 | magic = db->magic; |
| 19449 | if( magic!=SQLITE_MAGIC_SICK && |
| 19450 | magic!=SQLITE_MAGIC_OPEN && |
| 19451 | magic!=SQLITE_MAGIC_BUSY ) return 0; |
| 19452 | return 1; |
| 19453 | } |
| 19454 | |
| 19455 | /************** End of util.c ************************************************/ |
| 19456 | /************** Begin file hash.c ********************************************/ |
| 19457 | /* |
| @@ -21365,10 +21512,15 @@ | |
| 21365 | # include <sys/param.h> |
| 21366 | # include <sys/mount.h> |
| 21367 | # endif |
| 21368 | #endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
| 21369 | |
| 21370 | /* |
| 21371 | ** If we are to be thread-safe, include the pthreads header and define |
| 21372 | ** the SQLITE_UNIX_THREADS macro. |
| 21373 | */ |
| 21374 | #if SQLITE_THREADSAFE |
| @@ -21431,10 +21583,13 @@ | |
| 21431 | UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ |
| 21432 | int fileFlags; /* Miscellanous flags */ |
| 21433 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 21434 | int openFlags; /* The flags specified at open() */ |
| 21435 | #endif |
| 21436 | #if SQLITE_THREADSAFE && defined(__linux__) |
| 21437 | pthread_t tid; /* The thread that "owns" this unixFile */ |
| 21438 | #endif |
| 21439 | #if OS_VXWORKS |
| 21440 | int isDelete; /* Delete on close if true */ |
| @@ -22198,10 +22353,13 @@ | |
| 22198 | struct unixLockInfo { |
| 22199 | struct unixLockKey lockKey; /* The lookup key */ |
| 22200 | int cnt; /* Number of SHARED locks held */ |
| 22201 | int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ |
| 22202 | int nRef; /* Number of pointers to this structure */ |
| 22203 | struct unixLockInfo *pNext; /* List of all unixLockInfo objects */ |
| 22204 | struct unixLockInfo *pPrev; /* .... doubly linked */ |
| 22205 | }; |
| 22206 | |
| 22207 | /* |
| @@ -22441,13 +22599,14 @@ | |
| 22441 | ** an ASCII 'S' character which also happens to be the first byte |
| 22442 | ** in the header of every SQLite database. In this way, if there |
| 22443 | ** is a race condition such that another thread has already populated |
| 22444 | ** the first page of the database, no damage is done. |
| 22445 | */ |
| 22446 | if( statbuf.st_size==0 ){ |
| 22447 | rc = write(fd, "S", 1); |
| 22448 | if( rc!=1 ){ |
| 22449 | return SQLITE_IOERR; |
| 22450 | } |
| 22451 | rc = fstat(fd, &statbuf); |
| 22452 | if( rc!=0 ){ |
| 22453 | pFile->lastErrno = errno; |
| @@ -22483,10 +22642,13 @@ | |
| 22483 | } |
| 22484 | memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey)); |
| 22485 | pLock->nRef = 1; |
| 22486 | pLock->cnt = 0; |
| 22487 | pLock->locktype = 0; |
| 22488 | pLock->pNext = lockList; |
| 22489 | pLock->pPrev = 0; |
| 22490 | if( lockList ) lockList->pPrev = pLock; |
| 22491 | lockList = pLock; |
| 22492 | }else{ |
| @@ -22547,11 +22709,11 @@ | |
| 22547 | OSTRACE1("No-transfer, same thread\n"); |
| 22548 | return SQLITE_OK; |
| 22549 | } |
| 22550 | if( pFile->locktype!=NO_LOCK ){ |
| 22551 | /* We cannot change ownership while we are holding a lock! */ |
| 22552 | return SQLITE_MISUSE; |
| 22553 | } |
| 22554 | OSTRACE4("Transfer ownership of %d from %d to %d\n", |
| 22555 | pFile->h, pFile->tid, hSelf); |
| 22556 | pFile->tid = hSelf; |
| 22557 | if (pFile->pLock != NULL) { |
| @@ -22613,66 +22775,10 @@ | |
| 22613 | |
| 22614 | unixLeaveMutex(); |
| 22615 | OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved); |
| 22616 | |
| 22617 | *pResOut = reserved; |
| 22618 | return rc; |
| 22619 | } |
| 22620 | |
| 22621 | /* |
| 22622 | ** Perform a file locking operation on a range of bytes in a file. |
| 22623 | ** The "op" parameter should be one of F_RDLCK, F_WRLCK, or F_UNLCK. |
| 22624 | ** Return 0 on success or -1 for failure. On failure, write the error |
| 22625 | ** code into *pErrcode. |
| 22626 | ** |
| 22627 | ** If the SQLITE_WHOLE_FILE_LOCKING bit is clear, then only lock |
| 22628 | ** the range of bytes on the locking page between SHARED_FIRST and |
| 22629 | ** SHARED_SIZE. If SQLITE_WHOLE_FILE_LOCKING is set, then lock all |
| 22630 | ** bytes from 0 up to but not including PENDING_BYTE, and all bytes |
| 22631 | ** that follow SHARED_FIRST. |
| 22632 | ** |
| 22633 | ** In other words, of SQLITE_WHOLE_FILE_LOCKING if false (the historical |
| 22634 | ** default case) then only lock a small range of bytes from SHARED_FIRST |
| 22635 | ** through SHARED_FIRST+SHARED_SIZE-1. But if SQLITE_WHOLE_FILE_LOCKING is |
| 22636 | ** true then lock every byte in the file except for PENDING_BYTE and |
| 22637 | ** RESERVED_BYTE. |
| 22638 | ** |
| 22639 | ** SQLITE_WHOLE_FILE_LOCKING=true overlaps SQLITE_WHOLE_FILE_LOCKING=false |
| 22640 | ** and so the locking schemes are compatible. One type of lock will |
| 22641 | ** effectively exclude the other type. The reason for using the |
| 22642 | ** SQLITE_WHOLE_FILE_LOCKING=true is that by indicating the full range |
| 22643 | ** of bytes to be read or written, we give hints to NFS to help it |
| 22644 | ** maintain cache coherency. On the other hand, whole file locking |
| 22645 | ** is slower, so we don't want to use it except for NFS. |
| 22646 | */ |
| 22647 | static int rangeLock(unixFile *pFile, int op, int *pErrcode){ |
| 22648 | struct flock lock; |
| 22649 | int rc; |
| 22650 | lock.l_type = op; |
| 22651 | lock.l_start = SHARED_FIRST; |
| 22652 | lock.l_whence = SEEK_SET; |
| 22653 | if( (pFile->fileFlags & SQLITE_WHOLE_FILE_LOCKING)==0 ){ |
| 22654 | lock.l_len = SHARED_SIZE; |
| 22655 | rc = fcntl(pFile->h, F_SETLK, &lock); |
| 22656 | *pErrcode = errno; |
| 22657 | }else{ |
| 22658 | lock.l_len = 0; |
| 22659 | rc = fcntl(pFile->h, F_SETLK, &lock); |
| 22660 | *pErrcode = errno; |
| 22661 | if( NEVER(op==F_UNLCK) || rc!=(-1) ){ |
| 22662 | lock.l_start = 0; |
| 22663 | lock.l_len = PENDING_BYTE; |
| 22664 | rc = fcntl(pFile->h, F_SETLK, &lock); |
| 22665 | if( ALWAYS(op!=F_UNLCK) && rc==(-1) ){ |
| 22666 | *pErrcode = errno; |
| 22667 | lock.l_type = F_UNLCK; |
| 22668 | lock.l_start = SHARED_FIRST; |
| 22669 | lock.l_len = 0; |
| 22670 | fcntl(pFile->h, F_SETLK, &lock); |
| 22671 | } |
| 22672 | } |
| 22673 | } |
| 22674 | return rc; |
| 22675 | } |
| 22676 | |
| 22677 | /* |
| 22678 | ** Lock the file with the lock specified by parameter locktype - one |
| @@ -22740,11 +22846,11 @@ | |
| 22740 | int rc = SQLITE_OK; |
| 22741 | unixFile *pFile = (unixFile*)id; |
| 22742 | struct unixLockInfo *pLock = pFile->pLock; |
| 22743 | struct flock lock; |
| 22744 | int s = 0; |
| 22745 | int tErrno; |
| 22746 | |
| 22747 | assert( pFile ); |
| 22748 | OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, |
| 22749 | locktypeName(locktype), locktypeName(pFile->locktype), |
| 22750 | locktypeName(pLock->locktype), pLock->cnt , getpid()); |
| @@ -22836,12 +22942,15 @@ | |
| 22836 | if( locktype==SHARED_LOCK ){ |
| 22837 | assert( pLock->cnt==0 ); |
| 22838 | assert( pLock->locktype==0 ); |
| 22839 | |
| 22840 | /* Now get the read-lock */ |
| 22841 | s = rangeLock(pFile, F_RDLCK, &tErrno); |
| 22842 | |
| 22843 | /* Drop the temporary PENDING lock */ |
| 22844 | lock.l_start = PENDING_BYTE; |
| 22845 | lock.l_len = 1L; |
| 22846 | lock.l_type = F_UNLCK; |
| 22847 | if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ |
| @@ -22877,20 +22986,21 @@ | |
| 22877 | assert( 0!=pFile->locktype ); |
| 22878 | lock.l_type = F_WRLCK; |
| 22879 | switch( locktype ){ |
| 22880 | case RESERVED_LOCK: |
| 22881 | lock.l_start = RESERVED_BYTE; |
| 22882 | s = fcntl(pFile->h, F_SETLK, &lock); |
| 22883 | tErrno = errno; |
| 22884 | break; |
| 22885 | case EXCLUSIVE_LOCK: |
| 22886 | s = rangeLock(pFile, F_WRLCK, &tErrno); |
| 22887 | break; |
| 22888 | default: |
| 22889 | assert(0); |
| 22890 | } |
| 22891 | if( s==(-1) ){ |
| 22892 | rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); |
| 22893 | if( IS_LOCK_ERROR(rc) ){ |
| 22894 | pFile->lastErrno = tErrno; |
| 22895 | } |
| 22896 | } |
| @@ -22976,17 +23086,23 @@ | |
| 22976 | ** Lower the locking level on file descriptor pFile to locktype. locktype |
| 22977 | ** must be either NO_LOCK or SHARED_LOCK. |
| 22978 | ** |
| 22979 | ** If the locking level of the file descriptor is already at or below |
| 22980 | ** the requested locking level, this routine is a no-op. |
| 22981 | */ |
| 22982 | static int unixUnlock(sqlite3_file *id, int locktype){ |
| 22983 | unixFile *pFile = (unixFile*)id; /* The open file */ |
| 22984 | struct unixLockInfo *pLock; /* Structure describing current lock state */ |
| 22985 | struct flock lock; /* Information passed into fcntl() */ |
| 22986 | int rc = SQLITE_OK; /* Return code from this interface */ |
| 22987 | int h; /* The underlying file descriptor */ |
| 22988 | int tErrno; /* Error code from system call errors */ |
| 22989 | |
| 22990 | assert( pFile ); |
| 22991 | OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype, |
| 22992 | pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
| @@ -22994,11 +23110,11 @@ | |
| 22994 | assert( locktype<=SHARED_LOCK ); |
| 22995 | if( pFile->locktype<=locktype ){ |
| 22996 | return SQLITE_OK; |
| 22997 | } |
| 22998 | if( CHECK_THREADID(pFile) ){ |
| 22999 | return SQLITE_MISUSE; |
| 23000 | } |
| 23001 | unixEnterMutex(); |
| 23002 | h = pFile->h; |
| 23003 | pLock = pFile->pLock; |
| 23004 | assert( pLock->cnt!=0 ); |
| @@ -23021,18 +23137,72 @@ | |
| 23021 | || pFile->dbUpdate==0 |
| 23022 | || pFile->transCntrChng==1 ); |
| 23023 | pFile->inNormalWrite = 0; |
| 23024 | #endif |
| 23025 | |
| 23026 | |
| 23027 | if( locktype==SHARED_LOCK ){ |
| 23028 | if( rangeLock(pFile, F_RDLCK, &tErrno)==(-1) ){ |
| 23029 | rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); |
| 23030 | if( IS_LOCK_ERROR(rc) ){ |
| 23031 | pFile->lastErrno = tErrno; |
| 23032 | } |
| 23033 | goto end_unlock; |
| 23034 | } |
| 23035 | } |
| 23036 | lock.l_type = F_UNLCK; |
| 23037 | lock.l_whence = SEEK_SET; |
| 23038 | lock.l_start = PENDING_BYTE; |
| @@ -23094,10 +23264,21 @@ | |
| 23094 | end_unlock: |
| 23095 | unixLeaveMutex(); |
| 23096 | if( rc==SQLITE_OK ) pFile->locktype = locktype; |
| 23097 | return rc; |
| 23098 | } |
| 23099 | |
| 23100 | /* |
| 23101 | ** This function performs the parts of the "close file" operation |
| 23102 | ** common to all locking schemes. It closes the directory and file |
| 23103 | ** handles, if they are valid, and sets all fields of the unixFile |
| @@ -23806,11 +23987,11 @@ | |
| 23806 | /* |
| 23807 | ** The afpLockingContext structure contains all afp lock specific state |
| 23808 | */ |
| 23809 | typedef struct afpLockingContext afpLockingContext; |
| 23810 | struct afpLockingContext { |
| 23811 | unsigned long long sharedByte; |
| 23812 | const char *dbPath; /* Name of the open file */ |
| 23813 | }; |
| 23814 | |
| 23815 | struct ByteRangeLockPB2 |
| 23816 | { |
| @@ -23883,13 +24064,18 @@ | |
| 23883 | |
| 23884 | SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); |
| 23885 | |
| 23886 | assert( pFile ); |
| 23887 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 23888 | |
| 23889 | /* Check if a thread in this process holds such a lock */ |
| 23890 | if( pFile->locktype>SHARED_LOCK ){ |
| 23891 | reserved = 1; |
| 23892 | } |
| 23893 | |
| 23894 | /* Otherwise see if some other process holds it. |
| 23895 | */ |
| @@ -23907,10 +24093,11 @@ | |
| 23907 | if( IS_LOCK_ERROR(lrc) ){ |
| 23908 | rc=lrc; |
| 23909 | } |
| 23910 | } |
| 23911 | |
| 23912 | OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved); |
| 23913 | |
| 23914 | *pResOut = reserved; |
| 23915 | return rc; |
| 23916 | } |
| @@ -23940,15 +24127,17 @@ | |
| 23940 | ** routine to lower a locking level. |
| 23941 | */ |
| 23942 | static int afpLock(sqlite3_file *id, int locktype){ |
| 23943 | int rc = SQLITE_OK; |
| 23944 | unixFile *pFile = (unixFile*)id; |
| 23945 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 23946 | |
| 23947 | assert( pFile ); |
| 23948 | OSTRACE5("LOCK %d %s was %s pid=%d (afp)\n", pFile->h, |
| 23949 | locktypeName(locktype), locktypeName(pFile->locktype), getpid()); |
| 23950 | |
| 23951 | /* If there is already a lock of this type or more restrictive on the |
| 23952 | ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as |
| 23953 | ** unixEnterMutex() hasn't been called yet. |
| 23954 | */ |
| @@ -23957,10 +24146,13 @@ | |
| 23957 | locktypeName(locktype)); |
| 23958 | return SQLITE_OK; |
| 23959 | } |
| 23960 | |
| 23961 | /* Make sure the locking sequence is correct |
| 23962 | */ |
| 23963 | assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); |
| 23964 | assert( locktype!=PENDING_LOCK ); |
| 23965 | assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); |
| 23966 | |
| @@ -23972,10 +24164,36 @@ | |
| 23972 | */ |
| 23973 | rc = transferOwnership(pFile); |
| 23974 | if( rc!=SQLITE_OK ){ |
| 23975 | unixLeaveMutex(); |
| 23976 | return rc; |
| 23977 | } |
| 23978 | |
| 23979 | /* A PENDING lock is needed before acquiring a SHARED lock and before |
| 23980 | ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will |
| 23981 | ** be released. |
| @@ -23993,19 +24211,23 @@ | |
| 23993 | |
| 23994 | /* If control gets to this point, then actually go ahead and make |
| 23995 | ** operating system calls for the specified lock. |
| 23996 | */ |
| 23997 | if( locktype==SHARED_LOCK ){ |
| 23998 | int lk, lrc1, lrc2; |
| 23999 | int lrc1Errno = 0; |
| 24000 | |
| 24001 | /* Now get the read-lock SHARED_LOCK */ |
| 24002 | /* note that the quality of the randomness doesn't matter that much */ |
| 24003 | lk = random(); |
| 24004 | context->sharedByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); |
| 24005 | lrc1 = afpSetLock(context->dbPath, pFile, |
| 24006 | SHARED_FIRST+context->sharedByte, 1, 1); |
| 24007 | if( IS_LOCK_ERROR(lrc1) ){ |
| 24008 | lrc1Errno = pFile->lastErrno; |
| 24009 | } |
| 24010 | /* Drop the temporary PENDING lock */ |
| 24011 | lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); |
| @@ -24020,11 +24242,16 @@ | |
| 24020 | } else if( lrc1 != SQLITE_OK ) { |
| 24021 | rc = lrc1; |
| 24022 | } else { |
| 24023 | pFile->locktype = SHARED_LOCK; |
| 24024 | pFile->pOpen->nLock++; |
| 24025 | } |
| 24026 | }else{ |
| 24027 | /* The request was for a RESERVED or EXCLUSIVE lock. It is |
| 24028 | ** assumed that there is a SHARED or greater lock on the file |
| 24029 | ** already. |
| 24030 | */ |
| @@ -24031,25 +24258,28 @@ | |
| 24031 | int failed = 0; |
| 24032 | assert( 0!=pFile->locktype ); |
| 24033 | if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) { |
| 24034 | /* Acquire a RESERVED lock */ |
| 24035 | failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); |
| 24036 | } |
| 24037 | if (!failed && locktype == EXCLUSIVE_LOCK) { |
| 24038 | /* Acquire an EXCLUSIVE lock */ |
| 24039 | |
| 24040 | /* Remove the shared lock before trying the range. we'll need to |
| 24041 | ** reestablish the shared lock if we can't get the afpUnlock |
| 24042 | */ |
| 24043 | if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + |
| 24044 | context->sharedByte, 1, 0)) ){ |
| 24045 | int failed2 = SQLITE_OK; |
| 24046 | /* now attemmpt to get the exclusive lock range */ |
| 24047 | failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, |
| 24048 | SHARED_SIZE, 1); |
| 24049 | if( failed && (failed2 = afpSetLock(context->dbPath, pFile, |
| 24050 | SHARED_FIRST + context->sharedByte, 1, 1)) ){ |
| 24051 | /* Can't reestablish the shared lock. Sqlite can't deal, this is |
| 24052 | ** a critical I/O error |
| 24053 | */ |
| 24054 | rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : |
| 24055 | SQLITE_IOERR_LOCK; |
| @@ -24064,12 +24294,14 @@ | |
| 24064 | } |
| 24065 | } |
| 24066 | |
| 24067 | if( rc==SQLITE_OK ){ |
| 24068 | pFile->locktype = locktype; |
| 24069 | }else if( locktype==EXCLUSIVE_LOCK ){ |
| 24070 | pFile->locktype = PENDING_LOCK; |
| 24071 | } |
| 24072 | |
| 24073 | afp_end_lock: |
| 24074 | unixLeaveMutex(); |
| 24075 | OSTRACE4("LOCK %d %s %s (afp)\n", pFile->h, locktypeName(locktype), |
| @@ -24085,67 +24317,116 @@ | |
| 24085 | ** the requested locking level, this routine is a no-op. |
| 24086 | */ |
| 24087 | static int afpUnlock(sqlite3_file *id, int locktype) { |
| 24088 | int rc = SQLITE_OK; |
| 24089 | unixFile *pFile = (unixFile*)id; |
| 24090 | afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext; |
| 24091 | |
| 24092 | assert( pFile ); |
| 24093 | OSTRACE5("UNLOCK %d %d was %d pid=%d (afp)\n", pFile->h, locktype, |
| 24094 | pFile->locktype, getpid()); |
| 24095 | |
| 24096 | assert( locktype<=SHARED_LOCK ); |
| 24097 | if( pFile->locktype<=locktype ){ |
| 24098 | return SQLITE_OK; |
| 24099 | } |
| 24100 | if( CHECK_THREADID(pFile) ){ |
| 24101 | return SQLITE_MISUSE; |
| 24102 | } |
| 24103 | unixEnterMutex(); |
| 24104 | if( pFile->locktype>SHARED_LOCK ){ |
| 24105 | |
| 24106 | if( pFile->locktype==EXCLUSIVE_LOCK ){ |
| 24107 | rc = afpSetLock(pCtx->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); |
| 24108 | if( rc==SQLITE_OK && locktype==SHARED_LOCK ){ |
| 24109 | /* only re-establish the shared lock if necessary */ |
| 24110 | int sharedLockByte = SHARED_FIRST+pCtx->sharedByte; |
| 24111 | rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 1); |
| 24112 | } |
| 24113 | } |
| 24114 | if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){ |
| 24115 | rc = afpSetLock(pCtx->dbPath, pFile, PENDING_BYTE, 1, 0); |
| 24116 | } |
| 24117 | if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK ){ |
| 24118 | rc = afpSetLock(pCtx->dbPath, pFile, RESERVED_BYTE, 1, 0); |
| 24119 | } |
| 24120 | }else if( locktype==NO_LOCK ){ |
| 24121 | /* clear the shared lock */ |
| 24122 | int sharedLockByte = SHARED_FIRST+pCtx->sharedByte; |
| 24123 | rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 0); |
| 24124 | } |
| 24125 | |
| 24126 | if( rc==SQLITE_OK ){ |
| 24127 | if( locktype==NO_LOCK ){ |
| 24128 | struct unixOpenCnt *pOpen = pFile->pOpen; |
| 24129 | pOpen->nLock--; |
| 24130 | assert( pOpen->nLock>=0 ); |
| 24131 | if( pOpen->nLock==0 ){ |
| 24132 | rc = closePendingFds(pFile); |
| 24133 | } |
| 24134 | } |
| 24135 | } |
| 24136 | unixLeaveMutex(); |
| 24137 | if( rc==SQLITE_OK ){ |
| 24138 | pFile->locktype = locktype; |
| 24139 | } |
| 24140 | return rc; |
| 24141 | } |
| 24142 | |
| 24143 | /* |
| 24144 | ** Close a file & cleanup AFP specific locking context |
| 24145 | */ |
| 24146 | static int afpClose(sqlite3_file *id) { |
| 24147 | if( id ){ |
| 24148 | unixFile *pFile = (unixFile*)id; |
| 24149 | afpUnlock(id, NO_LOCK); |
| 24150 | unixEnterMutex(); |
| 24151 | if( pFile->pOpen && pFile->pOpen->nLock ){ |
| @@ -24154,16 +24435,17 @@ | |
| 24154 | ** descriptor to pOpen->aPending. It will be automatically closed when |
| 24155 | ** the last lock is cleared. |
| 24156 | */ |
| 24157 | setPendingFd(pFile); |
| 24158 | } |
| 24159 | releaseOpenCnt(pFile->pOpen); |
| 24160 | sqlite3_free(pFile->lockingContext); |
| 24161 | closeUnixFile(id); |
| 24162 | unixLeaveMutex(); |
| 24163 | } |
| 24164 | return SQLITE_OK; |
| 24165 | } |
| 24166 | |
| 24167 | #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ |
| 24168 | /* |
| 24169 | ** The code above is the AFP lock implementation. The code is specific |
| @@ -24172,10 +24454,33 @@ | |
| 24172 | ** VFS is not available. |
| 24173 | ** |
| 24174 | ********************* End of the AFP lock implementation ********************** |
| 24175 | ******************************************************************************/ |
| 24176 | |
| 24177 | |
| 24178 | /****************************************************************************** |
| 24179 | **************** Non-locking sqlite3_file methods ***************************** |
| 24180 | ** |
| 24181 | ** The next division contains implementations for all methods of the |
| @@ -24198,11 +24503,13 @@ | |
| 24198 | ** To avoid stomping the errno value on a failed read the lastErrno value |
| 24199 | ** is set before returning. |
| 24200 | */ |
| 24201 | static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ |
| 24202 | int got; |
| 24203 | i64 newOffset; |
| 24204 | TIMER_START; |
| 24205 | #if defined(USE_PREAD) |
| 24206 | got = pread(id->h, pBuf, cnt, offset); |
| 24207 | SimulateIOError( got = -1 ); |
| 24208 | #elif defined(USE_PREAD64) |
| @@ -24272,11 +24579,13 @@ | |
| 24272 | ** To avoid stomping the errno value on a failed write the lastErrno value |
| 24273 | ** is set before returning. |
| 24274 | */ |
| 24275 | static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ |
| 24276 | int got; |
| 24277 | i64 newOffset; |
| 24278 | TIMER_START; |
| 24279 | #if defined(USE_PREAD) |
| 24280 | got = pwrite(id->h, pBuf, cnt, offset); |
| 24281 | #elif defined(USE_PREAD64) |
| 24282 | got = pwrite64(id->h, pBuf, cnt, offset); |
| @@ -24466,10 +24775,15 @@ | |
| 24466 | ** It'd be better to detect fullfsync support once and avoid |
| 24467 | ** the fcntl call every time sync is called. |
| 24468 | */ |
| 24469 | if( rc ) rc = fsync(fd); |
| 24470 | |
| 24471 | #else |
| 24472 | rc = fdatasync(fd); |
| 24473 | #if OS_VXWORKS |
| 24474 | if( rc==-1 && errno==ENOTSUP ){ |
| 24475 | rc = fsync(fd); |
| @@ -24800,27 +25114,10 @@ | |
| 24800 | afpUnlock, /* xUnlock method */ |
| 24801 | afpCheckReservedLock /* xCheckReservedLock method */ |
| 24802 | ) |
| 24803 | #endif |
| 24804 | |
| 24805 | /* |
| 24806 | ** The "Whole File Locking" finder returns the same set of methods as |
| 24807 | ** the posix locking finder. But it also sets the SQLITE_WHOLE_FILE_LOCKING |
| 24808 | ** flag to force the posix advisory locks to cover the whole file instead |
| 24809 | ** of just a small span of bytes near the 1GiB boundary. Whole File Locking |
| 24810 | ** is useful on NFS-mounted files since it helps NFS to maintain cache |
| 24811 | ** coherency. But it is a detriment to other filesystems since it runs |
| 24812 | ** slower. |
| 24813 | */ |
| 24814 | static const sqlite3_io_methods *posixWflIoFinderImpl(const char*z, unixFile*p){ |
| 24815 | UNUSED_PARAMETER(z); |
| 24816 | p->fileFlags = SQLITE_WHOLE_FILE_LOCKING; |
| 24817 | return &posixIoMethods; |
| 24818 | } |
| 24819 | static const sqlite3_io_methods |
| 24820 | *(*const posixWflIoFinder)(const char*,unixFile *p) = posixWflIoFinderImpl; |
| 24821 | |
| 24822 | /* |
| 24823 | ** The proxy locking method is a "super-method" in the sense that it |
| 24824 | ** opens secondary file descriptors for the conch and lock files and |
| 24825 | ** it uses proxy, dot-file, AFP, and flock() locking methods on those |
| 24826 | ** secondary files. For this reason, the division that implements |
| @@ -24841,10 +25138,21 @@ | |
| 24841 | proxyUnlock, /* xUnlock method */ |
| 24842 | proxyCheckReservedLock /* xCheckReservedLock method */ |
| 24843 | ) |
| 24844 | #endif |
| 24845 | |
| 24846 | |
| 24847 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 24848 | /* |
| 24849 | ** This "finder" function attempts to determine the best locking strategy |
| 24850 | ** for the database file "filePath". It then returns the sqlite3_io_methods |
| @@ -24861,15 +25169,11 @@ | |
| 24861 | const sqlite3_io_methods *pMethods; /* Appropriate locking method */ |
| 24862 | } aMap[] = { |
| 24863 | { "hfs", &posixIoMethods }, |
| 24864 | { "ufs", &posixIoMethods }, |
| 24865 | { "afpfs", &afpIoMethods }, |
| 24866 | #ifdef SQLITE_ENABLE_AFP_LOCKING_SMB |
| 24867 | { "smbfs", &afpIoMethods }, |
| 24868 | #else |
| 24869 | { "smbfs", &flockIoMethods }, |
| 24870 | #endif |
| 24871 | { "webdav", &nolockIoMethods }, |
| 24872 | { 0, 0 } |
| 24873 | }; |
| 24874 | int i; |
| 24875 | struct statfs fsInfo; |
| @@ -24898,12 +25202,15 @@ | |
| 24898 | lockInfo.l_len = 1; |
| 24899 | lockInfo.l_start = 0; |
| 24900 | lockInfo.l_whence = SEEK_SET; |
| 24901 | lockInfo.l_type = F_RDLCK; |
| 24902 | if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { |
| 24903 | pNew->fileFlags = SQLITE_WHOLE_FILE_LOCKING; |
| 24904 | return &posixIoMethods; |
| 24905 | }else{ |
| 24906 | return &dotlockIoMethods; |
| 24907 | } |
| 24908 | } |
| 24909 | static const sqlite3_io_methods |
| @@ -25010,11 +25317,15 @@ | |
| 25010 | ** zFilename remains valid until file is closed, to support */ |
| 25011 | pNew->lockingContext = (void*)zFilename; |
| 25012 | #endif |
| 25013 | } |
| 25014 | |
| 25015 | if( pLockingStyle == &posixIoMethods ){ |
| 25016 | unixEnterMutex(); |
| 25017 | rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); |
| 25018 | if( rc!=SQLITE_OK ){ |
| 25019 | /* If an error occured in findLockInfo(), close the file descriptor |
| 25020 | ** immediately, before releasing the mutex. findLockInfo() may fail |
| @@ -25052,13 +25363,19 @@ | |
| 25052 | }else{ |
| 25053 | /* NB: zFilename exists and remains valid until the file is closed |
| 25054 | ** according to requirement F11141. So we do not need to make a |
| 25055 | ** copy of the filename. */ |
| 25056 | pCtx->dbPath = zFilename; |
| 25057 | srandomdev(); |
| 25058 | unixEnterMutex(); |
| 25059 | rc = findLockInfo(pNew, NULL, &pNew->pOpen); |
| 25060 | unixLeaveMutex(); |
| 25061 | } |
| 25062 | } |
| 25063 | #endif |
| 25064 | |
| @@ -25103,10 +25420,12 @@ | |
| 25103 | #endif |
| 25104 | |
| 25105 | pNew->lastErrno = 0; |
| 25106 | #if OS_VXWORKS |
| 25107 | if( rc!=SQLITE_OK ){ |
| 25108 | unlink(zFilename); |
| 25109 | isDelete = 0; |
| 25110 | } |
| 25111 | pNew->isDelete = isDelete; |
| 25112 | #endif |
| @@ -25146,11 +25465,11 @@ | |
| 25146 | #endif |
| 25147 | OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname); |
| 25148 | } |
| 25149 | } |
| 25150 | *pFd = fd; |
| 25151 | return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN); |
| 25152 | } |
| 25153 | |
| 25154 | /* |
| 25155 | ** Create a temporary file name in zBuf. zBuf must be allocated |
| 25156 | ** by the calling process and must be big enough to hold at least |
| @@ -25255,20 +25574,21 @@ | |
| 25255 | ** descriptor on the same path, fail, and return an error to SQLite. |
| 25256 | ** |
| 25257 | ** Even if a subsequent open() call does succeed, the consequences of |
| 25258 | ** not searching for a resusable file descriptor are not dire. */ |
| 25259 | if( 0==stat(zPath, &sStat) ){ |
| 25260 | struct unixOpenCnt *pO; |
| 25261 | struct unixFileId id; |
| 25262 | id.dev = sStat.st_dev; |
| 25263 | id.ino = sStat.st_ino; |
| 25264 | |
| 25265 | unixEnterMutex(); |
| 25266 | for(pO=openList; pO && memcmp(&id, &pO->fileId, sizeof(id)); pO=pO->pNext); |
| 25267 | if( pO ){ |
| 25268 | UnixUnusedFd **pp; |
| 25269 | for(pp=&pO->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); |
| 25270 | pUnused = *pp; |
| 25271 | if( pUnused ){ |
| 25272 | *pp = pUnused->pNext; |
| 25273 | } |
| 25274 | } |
| @@ -25318,10 +25638,13 @@ | |
| 25318 | int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); |
| 25319 | int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); |
| 25320 | int isCreate = (flags & SQLITE_OPEN_CREATE); |
| 25321 | int isReadonly = (flags & SQLITE_OPEN_READONLY); |
| 25322 | int isReadWrite = (flags & SQLITE_OPEN_READWRITE); |
| 25323 | |
| 25324 | /* If creating a master or main-file journal, this function will open |
| 25325 | ** a file-descriptor on the directory too. The first time unixSync() |
| 25326 | ** is called the directory file descriptor will be fsync()ed and close()d. |
| 25327 | */ |
| @@ -25405,11 +25728,11 @@ | |
| 25405 | flags |= SQLITE_OPEN_READONLY; |
| 25406 | openFlags |= O_RDONLY; |
| 25407 | fd = open(zName, openFlags, openMode); |
| 25408 | } |
| 25409 | if( fd<0 ){ |
| 25410 | rc = SQLITE_CANTOPEN; |
| 25411 | goto open_finished; |
| 25412 | } |
| 25413 | } |
| 25414 | assert( fd>=0 ); |
| 25415 | if( pOutFlags ){ |
| @@ -25451,12 +25774,29 @@ | |
| 25451 | fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 25452 | #endif |
| 25453 | |
| 25454 | noLock = eType!=SQLITE_OPEN_MAIN_DB; |
| 25455 | |
| 25456 | #if SQLITE_PREFER_PROXY_LOCKING |
| 25457 | if( zPath!=NULL && !noLock && pVfs->xOpen ){ |
| 25458 | char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); |
| 25459 | int useProxy = 0; |
| 25460 | |
| 25461 | /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means |
| 25462 | ** never use proxy, NULL means use proxy for non-local files only. */ |
| @@ -25484,10 +25824,18 @@ | |
| 25484 | } |
| 25485 | if( useProxy ){ |
| 25486 | rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); |
| 25487 | if( rc==SQLITE_OK ){ |
| 25488 | rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); |
| 25489 | } |
| 25490 | goto open_finished; |
| 25491 | } |
| 25492 | } |
| 25493 | #endif |
| @@ -25604,11 +25952,11 @@ | |
| 25604 | if( zPath[0]=='/' ){ |
| 25605 | sqlite3_snprintf(nOut, zOut, "%s", zPath); |
| 25606 | }else{ |
| 25607 | int nCwd; |
| 25608 | if( getcwd(zOut, nOut-1)==0 ){ |
| 25609 | return SQLITE_CANTOPEN; |
| 25610 | } |
| 25611 | nCwd = (int)strlen(zOut); |
| 25612 | sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath); |
| 25613 | } |
| 25614 | return SQLITE_OK; |
| @@ -25911,15 +26259,10 @@ | |
| 25911 | ** The proxy file - a single-byte file used for all advisory file locks |
| 25912 | ** normally taken on the database file. This allows for safe sharing |
| 25913 | ** of the database file for multiple readers and writers on the same |
| 25914 | ** host (the conch ensures that they all use the same local lock file). |
| 25915 | ** |
| 25916 | ** There is a third file - the host ID file - used as a persistent record |
| 25917 | ** of a unique identifier for the host, a 128-byte unique host id file |
| 25918 | ** in the path defined by the HOSTIDPATH macro (default value is |
| 25919 | ** /Library/Caches/.com.apple.sqliteConchHostId). |
| 25920 | ** |
| 25921 | ** Requesting the lock proxy does not immediately take the conch, it is |
| 25922 | ** only taken when the first request to lock database file is made. |
| 25923 | ** This matches the semantics of the traditional locking behavior, where |
| 25924 | ** opening a connection to a database file does not take a lock on it. |
| 25925 | ** The shared lock and an open file descriptor are maintained until |
| @@ -25941,14 +26284,10 @@ | |
| 25941 | ** SQLITE_PROXY_DEBUG |
| 25942 | ** |
| 25943 | ** Enables the logging of error messages during host id file |
| 25944 | ** retrieval and creation |
| 25945 | ** |
| 25946 | ** HOSTIDPATH |
| 25947 | ** |
| 25948 | ** Overrides the default host ID file path location |
| 25949 | ** |
| 25950 | ** LOCKPROXYDIR |
| 25951 | ** |
| 25952 | ** Overrides the default directory used for lock proxy files that |
| 25953 | ** are named automatically via the ":auto:" setting |
| 25954 | ** |
| @@ -25969,15 +26308,10 @@ | |
| 25969 | /* |
| 25970 | ** Proxy locking is only available on MacOSX |
| 25971 | */ |
| 25972 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 25973 | |
| 25974 | #ifdef SQLITE_TEST |
| 25975 | /* simulate multiple hosts by creating unique hostid file paths */ |
| 25976 | SQLITE_API int sqlite3_hostid_num = 0; |
| 25977 | #endif |
| 25978 | |
| 25979 | /* |
| 25980 | ** The proxyLockingContext has the path and file structures for the remote |
| 25981 | ** and local proxy files in it |
| 25982 | */ |
| 25983 | typedef struct proxyLockingContext proxyLockingContext; |
| @@ -25985,138 +26319,20 @@ | |
| 25985 | unixFile *conchFile; /* Open conch file */ |
| 25986 | char *conchFilePath; /* Name of the conch file */ |
| 25987 | unixFile *lockProxy; /* Open proxy lock file */ |
| 25988 | char *lockProxyPath; /* Name of the proxy lock file */ |
| 25989 | char *dbPath; /* Name of the open file */ |
| 25990 | int conchHeld; /* True if the conch is currently held */ |
| 25991 | void *oldLockingContext; /* Original lockingcontext to restore on close */ |
| 25992 | sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ |
| 25993 | }; |
| 25994 | |
| 25995 | /* HOSTIDLEN and CONCHLEN both include space for the string |
| 25996 | ** terminating nul |
| 25997 | */ |
| 25998 | #define HOSTIDLEN 128 |
| 25999 | #define CONCHLEN (MAXPATHLEN+HOSTIDLEN+1) |
| 26000 | #ifndef HOSTIDPATH |
| 26001 | # define HOSTIDPATH "/Library/Caches/.com.apple.sqliteConchHostId" |
| 26002 | #endif |
| 26003 | |
| 26004 | /* basically a copy of unixRandomness with different |
| 26005 | ** test behavior built in */ |
| 26006 | static int proxyGenerateHostID(char *pHostID){ |
| 26007 | int pid, fd, len; |
| 26008 | unsigned char *key = (unsigned char *)pHostID; |
| 26009 | |
| 26010 | memset(key, 0, HOSTIDLEN); |
| 26011 | len = 0; |
| 26012 | fd = open("/dev/urandom", O_RDONLY); |
| 26013 | if( fd>=0 ){ |
| 26014 | len = read(fd, key, HOSTIDLEN); |
| 26015 | close(fd); /* silently leak the fd if it fails */ |
| 26016 | } |
| 26017 | if( len < HOSTIDLEN ){ |
| 26018 | time_t t; |
| 26019 | time(&t); |
| 26020 | memcpy(key, &t, sizeof(t)); |
| 26021 | pid = getpid(); |
| 26022 | memcpy(&key[sizeof(t)], &pid, sizeof(pid)); |
| 26023 | } |
| 26024 | |
| 26025 | #ifdef MAKE_PRETTY_HOSTID |
| 26026 | { |
| 26027 | int i; |
| 26028 | /* filter the bytes into printable ascii characters and NUL terminate */ |
| 26029 | key[(HOSTIDLEN-1)] = 0x00; |
| 26030 | for( i=0; i<(HOSTIDLEN-1); i++ ){ |
| 26031 | unsigned char pa = key[i]&0x7F; |
| 26032 | if( pa<0x20 ){ |
| 26033 | key[i] = (key[i]&0x80 == 0x80) ? pa+0x40 : pa+0x20; |
| 26034 | }else if( pa==0x7F ){ |
| 26035 | key[i] = (key[i]&0x80 == 0x80) ? pa=0x20 : pa+0x7E; |
| 26036 | } |
| 26037 | } |
| 26038 | } |
| 26039 | #endif |
| 26040 | return SQLITE_OK; |
| 26041 | } |
| 26042 | |
| 26043 | /* writes the host id path to path, path should be an pre-allocated buffer |
| 26044 | ** with enough space for a path |
| 26045 | */ |
| 26046 | static void proxyGetHostIDPath(char *path, size_t len){ |
| 26047 | strlcpy(path, HOSTIDPATH, len); |
| 26048 | #ifdef SQLITE_TEST |
| 26049 | if( sqlite3_hostid_num>0 ){ |
| 26050 | char suffix[2] = "1"; |
| 26051 | suffix[0] = suffix[0] + sqlite3_hostid_num; |
| 26052 | strlcat(path, suffix, len); |
| 26053 | } |
| 26054 | #endif |
| 26055 | OSTRACE3("GETHOSTIDPATH %s pid=%d\n", path, getpid()); |
| 26056 | } |
| 26057 | |
| 26058 | /* get the host ID from a sqlite hostid file stored in the |
| 26059 | ** user-specific tmp directory, create the ID if it's not there already |
| 26060 | */ |
| 26061 | static int proxyGetHostID(char *pHostID, int *pError){ |
| 26062 | int fd; |
| 26063 | char path[MAXPATHLEN]; |
| 26064 | size_t len; |
| 26065 | int rc=SQLITE_OK; |
| 26066 | |
| 26067 | proxyGetHostIDPath(path, MAXPATHLEN); |
| 26068 | /* try to create the host ID file, if it already exists read the contents */ |
| 26069 | fd = open(path, O_CREAT|O_WRONLY|O_EXCL, 0644); |
| 26070 | if( fd<0 ){ |
| 26071 | int err=errno; |
| 26072 | |
| 26073 | if( err!=EEXIST ){ |
| 26074 | #ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */ |
| 26075 | fprintf(stderr, "sqlite error creating host ID file %s: %s\n", |
| 26076 | path, strerror(err)); |
| 26077 | #endif |
| 26078 | return SQLITE_PERM; |
| 26079 | } |
| 26080 | /* couldn't create the file, read it instead */ |
| 26081 | fd = open(path, O_RDONLY|O_EXCL); |
| 26082 | if( fd<0 ){ |
| 26083 | #ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */ |
| 26084 | int err = errno; |
| 26085 | fprintf(stderr, "sqlite error opening host ID file %s: %s\n", |
| 26086 | path, strerror(err)); |
| 26087 | #endif |
| 26088 | return SQLITE_PERM; |
| 26089 | } |
| 26090 | len = pread(fd, pHostID, HOSTIDLEN, 0); |
| 26091 | if( len<0 ){ |
| 26092 | *pError = errno; |
| 26093 | rc = SQLITE_IOERR_READ; |
| 26094 | }else if( len<HOSTIDLEN ){ |
| 26095 | *pError = 0; |
| 26096 | rc = SQLITE_IOERR_SHORT_READ; |
| 26097 | } |
| 26098 | close(fd); /* silently leak the fd if it fails */ |
| 26099 | OSTRACE3("GETHOSTID read %s pid=%d\n", pHostID, getpid()); |
| 26100 | return rc; |
| 26101 | }else{ |
| 26102 | /* we're creating the host ID file (use a random string of bytes) */ |
| 26103 | proxyGenerateHostID(pHostID); |
| 26104 | len = pwrite(fd, pHostID, HOSTIDLEN, 0); |
| 26105 | if( len<0 ){ |
| 26106 | *pError = errno; |
| 26107 | rc = SQLITE_IOERR_WRITE; |
| 26108 | }else if( len<HOSTIDLEN ){ |
| 26109 | *pError = 0; |
| 26110 | rc = SQLITE_IOERR_WRITE; |
| 26111 | } |
| 26112 | close(fd); /* silently leak the fd if it fails */ |
| 26113 | OSTRACE3("GETHOSTID wrote %s pid=%d\n", pHostID, getpid()); |
| 26114 | return rc; |
| 26115 | } |
| 26116 | } |
| 26117 | |
| 26118 | static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ |
| 26119 | int len; |
| 26120 | int dbLen; |
| 26121 | int i; |
| 26122 | |
| @@ -26123,25 +26339,16 @@ | |
| 26123 | #ifdef LOCKPROXYDIR |
| 26124 | len = strlcpy(lPath, LOCKPROXYDIR, maxLen); |
| 26125 | #else |
| 26126 | # ifdef _CS_DARWIN_USER_TEMP_DIR |
| 26127 | { |
| 26128 | confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen); |
| 26129 | len = strlcat(lPath, "sqliteplocks", maxLen); |
| 26130 | if( mkdir(lPath, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ |
| 26131 | /* if mkdir fails, handle as lock file creation failure */ |
| 26132 | # ifdef SQLITE_DEBUG |
| 26133 | int err = errno; |
| 26134 | if( err!=EEXIST ){ |
| 26135 | fprintf(stderr, "proxyGetLockPath: mkdir(%s,0%o) error %d %s\n", lPath, |
| 26136 | SQLITE_DEFAULT_PROXYDIR_PERMISSIONS, err, strerror(err)); |
| 26137 | } |
| 26138 | # endif |
| 26139 | }else{ |
| 26140 | OSTRACE3("GETLOCKPATH mkdir %s pid=%d\n", lPath, getpid()); |
| 26141 | } |
| 26142 | |
| 26143 | } |
| 26144 | # else |
| 26145 | len = strlcpy(lPath, "/tmp/", maxLen); |
| 26146 | # endif |
| 26147 | #endif |
| @@ -26156,213 +26363,535 @@ | |
| 26156 | char c = dbPath[i]; |
| 26157 | lPath[i+len] = (c=='/')?'_':c; |
| 26158 | } |
| 26159 | lPath[i+len]='\0'; |
| 26160 | strlcat(lPath, ":auto:", maxLen); |
| 26161 | return SQLITE_OK; |
| 26162 | } |
| 26163 | |
| 26164 | /* |
| 26165 | ** Create a new VFS file descriptor (stored in memory obtained from |
| 26166 | ** sqlite3_malloc) and open the file named "path" in the file descriptor. |
| 26167 | ** |
| 26168 | ** The caller is responsible not only for closing the file descriptor |
| 26169 | ** but also for freeing the memory associated with the file descriptor. |
| 26170 | */ |
| 26171 | static int proxyCreateUnixFile(const char *path, unixFile **ppFile) { |
| 26172 | unixFile *pNew; |
| 26173 | int flags = SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE; |
| 26174 | int rc = SQLITE_OK; |
| 26175 | sqlite3_vfs dummyVfs; |
| 26176 | |
| 26177 | pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile)); |
| 26178 | if( !pNew ){ |
| 26179 | return SQLITE_NOMEM; |
| 26180 | } |
| 26181 | memset(pNew, 0, sizeof(unixFile)); |
| 26182 | |
| 26183 | /* Call unixOpen() to open the proxy file. The flags passed to unixOpen() |
| 26184 | ** suggest that the file being opened is a "main database". This is |
| 26185 | ** necessary as other file types do not necessarily support locking. It |
| 26186 | ** is better to use unixOpen() instead of opening the file directly with |
| 26187 | ** open(), as unixOpen() sets up the various mechanisms required to |
| 26188 | ** make sure a call to close() does not cause the system to discard |
| 26189 | ** POSIX locks prematurely. |
| 26190 | ** |
| 26191 | ** It is important that the xOpen member of the VFS object passed to |
| 26192 | ** unixOpen() is NULL. This tells unixOpen() may try to open a proxy-file |
| 26193 | ** for the proxy-file (creating a potential infinite loop). |
| 26194 | */ |
| 26195 | dummyVfs.pAppData = (void*)&autolockIoFinder; |
| 26196 | dummyVfs.xOpen = 0; |
| 26197 | rc = unixOpen(&dummyVfs, path, (sqlite3_file *)pNew, flags, &flags); |
| 26198 | if( rc==SQLITE_OK && (flags&SQLITE_OPEN_READONLY) ){ |
| 26199 | pNew->pMethod->xClose((sqlite3_file *)pNew); |
| 26200 | rc = SQLITE_CANTOPEN; |
| 26201 | } |
| 26202 | |
| 26203 | if( rc!=SQLITE_OK ){ |
| 26204 | sqlite3_free(pNew); |
| 26205 | pNew = 0; |
| 26206 | } |
| 26207 | |
| 26208 | *ppFile = pNew; |
| 26209 | return rc; |
| 26210 | } |
| 26211 | |
| 26212 | /* takes the conch by taking a shared lock and read the contents conch, if |
| 26213 | ** lockPath is non-NULL, the host ID and lock file path must match. A NULL |
| 26214 | ** lockPath means that the lockPath in the conch file will be used if the |
| 26215 | ** host IDs match, or a new lock path will be generated automatically |
| 26216 | ** and written to the conch file. |
| 26217 | */ |
| 26218 | static int proxyTakeConch(unixFile *pFile){ |
| 26219 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26220 | |
| 26221 | if( pCtx->conchHeld>0 ){ |
| 26222 | return SQLITE_OK; |
| 26223 | }else{ |
| 26224 | unixFile *conchFile = pCtx->conchFile; |
| 26225 | char testValue[CONCHLEN]; |
| 26226 | char conchValue[CONCHLEN]; |
| 26227 | char lockPath[MAXPATHLEN]; |
| 26228 | char *tLockPath = NULL; |
| 26229 | int rc = SQLITE_OK; |
| 26230 | int readRc = SQLITE_OK; |
| 26231 | int syncPerms = 0; |
| 26232 | |
| 26233 | OSTRACE4("TAKECONCH %d for %s pid=%d\n", conchFile->h, |
| 26234 | (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()); |
| 26235 | |
| 26236 | rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); |
| 26237 | if( rc==SQLITE_OK ){ |
| 26238 | int pError = 0; |
| 26239 | memset(testValue, 0, CONCHLEN); /* conch is fixed size */ |
| 26240 | rc = proxyGetHostID(testValue, &pError); |
| 26241 | if( (rc&0xff)==SQLITE_IOERR ){ |
| 26242 | pFile->lastErrno = pError; |
| 26243 | } |
| 26244 | if( pCtx->lockProxyPath ){ |
| 26245 | strlcpy(&testValue[HOSTIDLEN], pCtx->lockProxyPath, MAXPATHLEN); |
| 26246 | } |
| 26247 | } |
| 26248 | if( rc!=SQLITE_OK ){ |
| 26249 | goto end_takeconch; |
| 26250 | } |
| 26251 | |
| 26252 | readRc = unixRead((sqlite3_file *)conchFile, conchValue, CONCHLEN, 0); |
| 26253 | if( readRc!=SQLITE_IOERR_SHORT_READ ){ |
| 26254 | if( readRc!=SQLITE_OK ){ |
| 26255 | if( (rc&0xff)==SQLITE_IOERR ){ |
| 26256 | pFile->lastErrno = conchFile->lastErrno; |
| 26257 | } |
| 26258 | rc = readRc; |
| 26259 | goto end_takeconch; |
| 26260 | } |
| 26261 | /* if the conch has data compare the contents */ |
| 26262 | if( !pCtx->lockProxyPath ){ |
| 26263 | /* for auto-named local lock file, just check the host ID and we'll |
| 26264 | ** use the local lock file path that's already in there */ |
| 26265 | if( !memcmp(testValue, conchValue, HOSTIDLEN) ){ |
| 26266 | tLockPath = (char *)&conchValue[HOSTIDLEN]; |
| 26267 | goto end_takeconch; |
| 26268 | } |
| 26269 | }else{ |
| 26270 | /* we've got the conch if conchValue matches our path and host ID */ |
| 26271 | if( !memcmp(testValue, conchValue, CONCHLEN) ){ |
| 26272 | goto end_takeconch; |
| 26273 | } |
| 26274 | } |
| 26275 | }else{ |
| 26276 | /* a short read means we're "creating" the conch (even though it could |
| 26277 | ** have been user-intervention), if we acquire the exclusive lock, |
| 26278 | ** we'll try to match the current on-disk permissions of the database |
| 26279 | */ |
| 26280 | syncPerms = 1; |
| 26281 | } |
| 26282 | |
| 26283 | /* either conch was emtpy or didn't match */ |
| 26284 | if( !pCtx->lockProxyPath ){ |
| 26285 | proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN); |
| 26286 | tLockPath = lockPath; |
| 26287 | strlcpy(&testValue[HOSTIDLEN], lockPath, MAXPATHLEN); |
| 26288 | } |
| 26289 | |
| 26290 | /* update conch with host and path (this will fail if other process |
| 26291 | ** has a shared lock already) */ |
| 26292 | rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK); |
| 26293 | if( rc==SQLITE_OK ){ |
| 26294 | rc = unixWrite((sqlite3_file *)conchFile, testValue, CONCHLEN, 0); |
| 26295 | if( rc==SQLITE_OK && syncPerms ){ |
| 26296 | struct stat buf; |
| 26297 | int err = fstat(pFile->h, &buf); |
| 26298 | if( err==0 ){ |
| 26299 | /* try to match the database file permissions, ignore failure */ |
| 26300 | #ifndef SQLITE_PROXY_DEBUG |
| 26301 | fchmod(conchFile->h, buf.st_mode); |
| 26302 | #else |
| 26303 | if( fchmod(conchFile->h, buf.st_mode)!=0 ){ |
| 26304 | int code = errno; |
| 26305 | fprintf(stderr, "fchmod %o FAILED with %d %s\n", |
| 26306 | buf.st_mode, code, strerror(code)); |
| 26307 | } else { |
| 26308 | fprintf(stderr, "fchmod %o SUCCEDED\n",buf.st_mode); |
| 26309 | } |
| 26310 | }else{ |
| 26311 | int code = errno; |
| 26312 | fprintf(stderr, "STAT FAILED[%d] with %d %s\n", |
| 26313 | err, code, strerror(code)); |
| 26314 | #endif |
| 26315 | } |
| 26316 | } |
| 26317 | } |
| 26318 | conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); |
| 26319 | |
| 26320 | end_takeconch: |
| 26321 | OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h); |
| 26322 | if( rc==SQLITE_OK && pFile->openFlags ){ |
| 26323 | if( pFile->h>=0 ){ |
| 26324 | #ifdef STRICT_CLOSE_ERROR |
| 26325 | if( close(pFile->h) ){ |
| 26326 | pFile->lastErrno = errno; |
| 26327 | return SQLITE_IOERR_CLOSE; |
| 26328 | } |
| 26329 | #else |
| 26330 | close(pFile->h); /* silently leak fd if fail */ |
| 26331 | #endif |
| 26332 | } |
| 26333 | pFile->h = -1; |
| 26334 | int fd = open(pCtx->dbPath, pFile->openFlags, |
| 26335 | SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26336 | OSTRACE2("TRANSPROXY: OPEN %d\n", fd); |
| 26337 | if( fd>=0 ){ |
| 26338 | pFile->h = fd; |
| 26339 | }else{ |
| 26340 | rc=SQLITE_CANTOPEN; /* SQLITE_BUSY? proxyTakeConch called |
| 26341 | during locking */ |
| 26342 | } |
| 26343 | } |
| 26344 | if( rc==SQLITE_OK && !pCtx->lockProxy ){ |
| 26345 | char *path = tLockPath ? tLockPath : pCtx->lockProxyPath; |
| 26346 | /* ACS: Need to make a copy of path sometimes */ |
| 26347 | rc = proxyCreateUnixFile(path, &pCtx->lockProxy); |
| 26348 | } |
| 26349 | if( rc==SQLITE_OK ){ |
| 26350 | pCtx->conchHeld = 1; |
| 26351 | |
| 26352 | if( tLockPath ){ |
| 26353 | pCtx->lockProxyPath = sqlite3DbStrDup(0, tLockPath); |
| 26354 | if( pCtx->lockProxy->pMethod == &afpIoMethods ){ |
| 26355 | ((afpLockingContext *)pCtx->lockProxy->lockingContext)->dbPath = |
| 26356 | pCtx->lockProxyPath; |
| 26357 | } |
| 26358 | } |
| 26359 | } else { |
| 26360 | conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); |
| 26361 | } |
| 26362 | OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed"); |
| 26363 | return rc; |
| 26364 | } |
| 26365 | } |
| 26366 | |
| 26367 | /* |
| 26368 | ** If pFile holds a lock on a conch file, then release that lock. |
| @@ -26375,12 +26904,14 @@ | |
| 26375 | pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26376 | conchFile = pCtx->conchFile; |
| 26377 | OSTRACE4("RELEASECONCH %d for %s pid=%d\n", conchFile->h, |
| 26378 | (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), |
| 26379 | getpid()); |
| 26380 | pCtx->conchHeld = 0; |
| 26381 | rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); |
| 26382 | OSTRACE3("RELEASECONCH %d %s\n", conchFile->h, |
| 26383 | (rc==SQLITE_OK ? "ok" : "failed")); |
| 26384 | return rc; |
| 26385 | } |
| 26386 | |
| @@ -26472,22 +27003,22 @@ | |
| 26472 | #if defined(__APPLE__) |
| 26473 | if( pFile->pMethod == &afpIoMethods ){ |
| 26474 | /* afp style keeps a reference to the db path in the filePath field |
| 26475 | ** of the struct */ |
| 26476 | assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); |
| 26477 | strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath); |
| 26478 | }else |
| 26479 | #endif |
| 26480 | if( pFile->pMethod == &dotlockIoMethods ){ |
| 26481 | /* dot lock style uses the locking context to store the dot lock |
| 26482 | ** file path */ |
| 26483 | int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX); |
| 26484 | memcpy(dbPath, (char *)pFile->lockingContext, len + 1); |
| 26485 | }else{ |
| 26486 | /* all other styles use the locking context to store the db file path */ |
| 26487 | assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); |
| 26488 | strcpy(dbPath, (char *)pFile->lockingContext); |
| 26489 | } |
| 26490 | return SQLITE_OK; |
| 26491 | } |
| 26492 | |
| 26493 | /* |
| @@ -26523,31 +27054,57 @@ | |
| 26523 | } |
| 26524 | memset(pCtx, 0, sizeof(*pCtx)); |
| 26525 | |
| 26526 | rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath); |
| 26527 | if( rc==SQLITE_OK ){ |
| 26528 | rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile); |
| 26529 | } |
| 26530 | if( rc==SQLITE_OK && lockPath ){ |
| 26531 | pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); |
| 26532 | } |
| 26533 | |
| 26534 | if( rc==SQLITE_OK ){ |
| 26535 | /* all memory is allocated, proxys are created and assigned, |
| 26536 | ** switch the locking context and pMethod then return. |
| 26537 | */ |
| 26538 | pCtx->dbPath = sqlite3DbStrDup(0, dbPath); |
| 26539 | pCtx->oldLockingContext = pFile->lockingContext; |
| 26540 | pFile->lockingContext = pCtx; |
| 26541 | pCtx->pOldMethod = pFile->pMethod; |
| 26542 | pFile->pMethod = &proxyIoMethods; |
| 26543 | }else{ |
| 26544 | if( pCtx->conchFile ){ |
| 26545 | rc = pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); |
| 26546 | if( rc ) return rc; |
| 26547 | sqlite3_free(pCtx->conchFile); |
| 26548 | } |
| 26549 | sqlite3_free(pCtx->conchFilePath); |
| 26550 | sqlite3_free(pCtx); |
| 26551 | } |
| 26552 | OSTRACE3("TRANSPROXY %d %s\n", pFile->h, |
| 26553 | (rc==SQLITE_OK ? "ok" : "failed")); |
| @@ -26632,12 +27189,16 @@ | |
| 26632 | static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) { |
| 26633 | unixFile *pFile = (unixFile*)id; |
| 26634 | int rc = proxyTakeConch(pFile); |
| 26635 | if( rc==SQLITE_OK ){ |
| 26636 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26637 | unixFile *proxy = pCtx->lockProxy; |
| 26638 | return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut); |
| 26639 | } |
| 26640 | return rc; |
| 26641 | } |
| 26642 | |
| 26643 | /* |
| @@ -26667,13 +27228,17 @@ | |
| 26667 | static int proxyLock(sqlite3_file *id, int locktype) { |
| 26668 | unixFile *pFile = (unixFile*)id; |
| 26669 | int rc = proxyTakeConch(pFile); |
| 26670 | if( rc==SQLITE_OK ){ |
| 26671 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26672 | unixFile *proxy = pCtx->lockProxy; |
| 26673 | rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype); |
| 26674 | pFile->locktype = proxy->locktype; |
| 26675 | } |
| 26676 | return rc; |
| 26677 | } |
| 26678 | |
| 26679 | |
| @@ -26687,13 +27252,17 @@ | |
| 26687 | static int proxyUnlock(sqlite3_file *id, int locktype) { |
| 26688 | unixFile *pFile = (unixFile*)id; |
| 26689 | int rc = proxyTakeConch(pFile); |
| 26690 | if( rc==SQLITE_OK ){ |
| 26691 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26692 | unixFile *proxy = pCtx->lockProxy; |
| 26693 | rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype); |
| 26694 | pFile->locktype = proxy->locktype; |
| 26695 | } |
| 26696 | return rc; |
| 26697 | } |
| 26698 | |
| 26699 | /* |
| @@ -26816,11 +27385,10 @@ | |
| 26816 | #else |
| 26817 | UNIXVFS("unix", posixIoFinder ), |
| 26818 | #endif |
| 26819 | UNIXVFS("unix-none", nolockIoFinder ), |
| 26820 | UNIXVFS("unix-dotfile", dotlockIoFinder ), |
| 26821 | UNIXVFS("unix-wfl", posixWflIoFinder ), |
| 26822 | #if OS_VXWORKS |
| 26823 | UNIXVFS("unix-namedsem", semIoFinder ), |
| 26824 | #endif |
| 26825 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 26826 | UNIXVFS("unix-posix", posixIoFinder ), |
| @@ -26828,10 +27396,11 @@ | |
| 26828 | UNIXVFS("unix-flock", flockIoFinder ), |
| 26829 | #endif |
| 26830 | #endif |
| 26831 | #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) |
| 26832 | UNIXVFS("unix-afp", afpIoFinder ), |
| 26833 | UNIXVFS("unix-proxy", proxyIoFinder ), |
| 26834 | #endif |
| 26835 | }; |
| 26836 | unsigned int i; /* Loop counter */ |
| 26837 | |
| @@ -28491,11 +29060,11 @@ | |
| 28491 | free(zConverted); |
| 28492 | if( flags & SQLITE_OPEN_READWRITE ){ |
| 28493 | return winOpen(pVfs, zName, id, |
| 28494 | ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); |
| 28495 | }else{ |
| 28496 | return SQLITE_CANTOPEN; |
| 28497 | } |
| 28498 | } |
| 28499 | if( pOutFlags ){ |
| 28500 | if( flags & SQLITE_OPEN_READWRITE ){ |
| 28501 | *pOutFlags = SQLITE_OPEN_READWRITE; |
| @@ -28513,11 +29082,11 @@ | |
| 28513 | (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) |
| 28514 | && !winceCreateLock(zName, pFile) |
| 28515 | ){ |
| 28516 | CloseHandle(h); |
| 28517 | free(zConverted); |
| 28518 | return SQLITE_CANTOPEN; |
| 28519 | } |
| 28520 | if( isTemp ){ |
| 28521 | pFile->zDeleteOnClose = zConverted; |
| 28522 | }else |
| 28523 | #endif |
| @@ -29653,10 +30222,11 @@ | |
| 29653 | expensive_assert( pcacheCheckSynced(pCache) ); |
| 29654 | for(pPg=pCache->pSynced; |
| 29655 | pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); |
| 29656 | pPg=pPg->pDirtyPrev |
| 29657 | ); |
| 29658 | if( !pPg ){ |
| 29659 | for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); |
| 29660 | } |
| 29661 | if( pPg ){ |
| 29662 | int rc; |
| @@ -34067,13 +34637,11 @@ | |
| 34067 | ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to |
| 34068 | ** make the file smaller (presumably by auto-vacuum code). Do not write |
| 34069 | ** any such pages to the file. |
| 34070 | ** |
| 34071 | ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag |
| 34072 | ** set (set by sqlite3PagerDontWrite()). Note that if compiled with |
| 34073 | ** SQLITE_SECURE_DELETE the PGHDR_DONT_WRITE bit is never set and so |
| 34074 | ** the second test is always true. |
| 34075 | */ |
| 34076 | if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ |
| 34077 | i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ |
| 34078 | char *pData; /* Data to write */ |
| 34079 | |
| @@ -34356,11 +34924,11 @@ | |
| 34356 | ** the database being opened will be more than pVfs->mxPathname |
| 34357 | ** bytes in length. This means the database cannot be opened, |
| 34358 | ** as it will not be possible to open the journal file or even |
| 34359 | ** check for a hot-journal before reading. |
| 34360 | */ |
| 34361 | rc = SQLITE_CANTOPEN; |
| 34362 | } |
| 34363 | if( rc!=SQLITE_OK ){ |
| 34364 | sqlite3_free(zPathname); |
| 34365 | return rc; |
| 34366 | } |
| @@ -34815,11 +35383,11 @@ | |
| 34815 | int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; |
| 34816 | assert( !pPager->tempFile ); |
| 34817 | rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); |
| 34818 | assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); |
| 34819 | if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ |
| 34820 | rc = SQLITE_CANTOPEN; |
| 34821 | sqlite3OsClose(pPager->jfd); |
| 34822 | } |
| 34823 | }else{ |
| 34824 | /* If the journal does not exist, it usually means that some |
| 34825 | ** other connection managed to get in and roll it back before |
| @@ -35034,11 +35602,11 @@ | |
| 35034 | rc = sqlite3PagerPagecount(pPager, &nMax); |
| 35035 | if( rc!=SQLITE_OK ){ |
| 35036 | goto pager_acquire_err; |
| 35037 | } |
| 35038 | |
| 35039 | if( MEMDB || nMax<(int)pgno || noContent ){ |
| 35040 | if( pgno>pPager->mxPgno ){ |
| 35041 | rc = SQLITE_FULL; |
| 35042 | goto pager_acquire_err; |
| 35043 | } |
| 35044 | if( noContent ){ |
| @@ -35054,13 +35622,12 @@ | |
| 35054 | testcase( rc==SQLITE_NOMEM ); |
| 35055 | } |
| 35056 | TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); |
| 35057 | testcase( rc==SQLITE_NOMEM ); |
| 35058 | sqlite3EndBenignMalloc(); |
| 35059 | }else{ |
| 35060 | memset(pPg->pData, 0, pPager->pageSize); |
| 35061 | } |
| 35062 | IOTRACE(("ZERO %p %d\n", pPager, pgno)); |
| 35063 | }else{ |
| 35064 | assert( pPg->pPager==pPager ); |
| 35065 | rc = readDbPage(pPg); |
| 35066 | if( rc!=SQLITE_OK ){ |
| @@ -35578,11 +36145,10 @@ | |
| 35578 | SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ |
| 35579 | return pPg->flags&PGHDR_DIRTY; |
| 35580 | } |
| 35581 | #endif |
| 35582 | |
| 35583 | #ifndef SQLITE_SECURE_DELETE |
| 35584 | /* |
| 35585 | ** A call to this routine tells the pager that it is not necessary to |
| 35586 | ** write the information on page pPg back to the disk, even though |
| 35587 | ** that page might be marked as dirty. This happens, for example, when |
| 35588 | ** the page has been added as a leaf of the freelist and so its |
| @@ -35604,11 +36170,10 @@ | |
| 35604 | #ifdef SQLITE_CHECK_PAGES |
| 35605 | pPg->pageHash = pager_pagehash(pPg); |
| 35606 | #endif |
| 35607 | } |
| 35608 | } |
| 35609 | #endif /* !defined(SQLITE_SECURE_DELETE) */ |
| 35610 | |
| 35611 | /* |
| 35612 | ** This routine is called to increment the value of the database file |
| 35613 | ** change-counter, stored as a 4-byte big-endian integer starting at |
| 35614 | ** byte offset 24 of the pager file. |
| @@ -36174,34 +36739,38 @@ | |
| 36174 | |
| 36175 | /* Figure out how many savepoints will still be active after this |
| 36176 | ** operation. Store this value in nNew. Then free resources associated |
| 36177 | ** with any savepoints that are destroyed by this operation. |
| 36178 | */ |
| 36179 | nNew = iSavepoint + (op==SAVEPOINT_ROLLBACK); |
| 36180 | for(ii=nNew; ii<pPager->nSavepoint; ii++){ |
| 36181 | sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); |
| 36182 | } |
| 36183 | pPager->nSavepoint = nNew; |
| 36184 | |
| 36185 | /* If this is a rollback operation, playback the specified savepoint. |
| 36186 | ** If this is a temp-file, it is possible that the journal file has |
| 36187 | ** not yet been opened. In this case there have been no changes to |
| 36188 | ** the database file, so the playback operation can be skipped. |
| 36189 | */ |
| 36190 | if( op==SAVEPOINT_ROLLBACK && isOpen(pPager->jfd) ){ |
| 36191 | PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; |
| 36192 | rc = pagerPlaybackSavepoint(pPager, pSavepoint); |
| 36193 | assert(rc!=SQLITE_DONE); |
| 36194 | } |
| 36195 | |
| 36196 | /* If this is a release of the outermost savepoint, truncate |
| 36197 | ** the sub-journal to zero bytes in size. */ |
| 36198 | if( nNew==0 && op==SAVEPOINT_RELEASE && isOpen(pPager->sjfd) ){ |
| 36199 | assert( rc==SQLITE_OK ); |
| 36200 | rc = sqlite3OsTruncate(pPager->sjfd, 0); |
| 36201 | pPager->nSubRec = 0; |
| 36202 | } |
| 36203 | } |
| 36204 | return rc; |
| 36205 | } |
| 36206 | |
| 36207 | /* |
| @@ -36957,10 +37526,11 @@ | |
| 36957 | sqlite3 *db; /* Database connection currently using this Btree */ |
| 36958 | BtCursor *pCursor; /* A list of all open cursors */ |
| 36959 | MemPage *pPage1; /* First page of the database */ |
| 36960 | u8 readOnly; /* True if the underlying file is readonly */ |
| 36961 | u8 pageSizeFixed; /* True if the page size can no longer be changed */ |
| 36962 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 36963 | u8 autoVacuum; /* True if auto-vacuum is enabled */ |
| 36964 | u8 incrVacuum; /* True if incr-vacuum is enabled */ |
| 36965 | #endif |
| 36966 | u16 pageSize; /* Total number of bytes on a page */ |
| @@ -38780,15 +39350,15 @@ | |
| 38780 | assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); |
| 38781 | assert( (start + size)<=pPage->pBt->usableSize ); |
| 38782 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 38783 | assert( size>=0 ); /* Minimum cell size is 4 */ |
| 38784 | |
| 38785 | #ifdef SQLITE_SECURE_DELETE |
| 38786 | /* Overwrite deleted information with zeros when the SECURE_DELETE |
| 38787 | ** option is enabled at compile-time */ |
| 38788 | memset(&data[start], 0, size); |
| 38789 | #endif |
| 38790 | |
| 38791 | /* Add the space back into the linked list of freeblocks. Note that |
| 38792 | ** even though the freeblock list was checked by btreeInitPage(), |
| 38793 | ** btreeInitPage() did not detect overlapping cells or |
| 38794 | ** freeblocks that overlapped cells. Nor does it detect when the |
| @@ -39016,13 +39586,13 @@ | |
| 39016 | assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); |
| 39017 | assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); |
| 39018 | assert( sqlite3PagerGetData(pPage->pDbPage) == data ); |
| 39019 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 39020 | assert( sqlite3_mutex_held(pBt->mutex) ); |
| 39021 | #ifdef SQLITE_SECURE_DELETE |
| 39022 | memset(&data[hdr], 0, pBt->usableSize - hdr); |
| 39023 | #endif |
| 39024 | data[hdr] = (char)flags; |
| 39025 | first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); |
| 39026 | memset(&data[hdr+1], 0, 4); |
| 39027 | data[hdr+7] = 0; |
| 39028 | put2byte(&data[hdr+5], pBt->usableSize); |
| @@ -39338,10 +39908,13 @@ | |
| 39338 | p->pBt = pBt; |
| 39339 | |
| 39340 | pBt->pCursor = 0; |
| 39341 | pBt->pPage1 = 0; |
| 39342 | pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); |
| 39343 | pBt->pageSize = get2byte(&zDbHeader[16]); |
| 39344 | if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE |
| 39345 | || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ |
| 39346 | pBt->pageSize = 0; |
| 39347 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| @@ -39694,10 +40267,27 @@ | |
| 39694 | sqlite3BtreeEnter(p); |
| 39695 | n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); |
| 39696 | sqlite3BtreeLeave(p); |
| 39697 | return n; |
| 39698 | } |
| 39699 | #endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ |
| 39700 | |
| 39701 | /* |
| 39702 | ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' |
| 39703 | ** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it |
| @@ -42437,21 +43027,21 @@ | |
| 42437 | rc = sqlite3PagerWrite(pPage1->pDbPage); |
| 42438 | if( rc ) goto freepage_out; |
| 42439 | nFree = get4byte(&pPage1->aData[36]); |
| 42440 | put4byte(&pPage1->aData[36], nFree+1); |
| 42441 | |
| 42442 | #ifdef SQLITE_SECURE_DELETE |
| 42443 | /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then |
| 42444 | ** always fully overwrite deleted information with zeros. |
| 42445 | */ |
| 42446 | if( (!pPage && (rc = btreeGetPage(pBt, iPage, &pPage, 0))) |
| 42447 | || (rc = sqlite3PagerWrite(pPage->pDbPage)) |
| 42448 | ){ |
| 42449 | goto freepage_out; |
| 42450 | } |
| 42451 | memset(pPage->aData, 0, pPage->pBt->pageSize); |
| 42452 | #endif |
| 42453 | |
| 42454 | /* If the database supports auto-vacuum, write an entry in the pointer-map |
| 42455 | ** to indicate that the page is free. |
| 42456 | */ |
| 42457 | if( ISAUTOVACUUM ){ |
| @@ -42498,15 +43088,13 @@ | |
| 42498 | */ |
| 42499 | rc = sqlite3PagerWrite(pTrunk->pDbPage); |
| 42500 | if( rc==SQLITE_OK ){ |
| 42501 | put4byte(&pTrunk->aData[4], nLeaf+1); |
| 42502 | put4byte(&pTrunk->aData[8+nLeaf*4], iPage); |
| 42503 | #ifndef SQLITE_SECURE_DELETE |
| 42504 | if( pPage ){ |
| 42505 | sqlite3PagerDontWrite(pPage->pDbPage); |
| 42506 | } |
| 42507 | #endif |
| 42508 | rc = btreeSetHasContent(pBt, iPage); |
| 42509 | } |
| 42510 | TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); |
| 42511 | goto freepage_out; |
| 42512 | } |
| @@ -42576,11 +43164,29 @@ | |
| 42576 | } |
| 42577 | if( nOvfl ){ |
| 42578 | rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); |
| 42579 | if( rc ) return rc; |
| 42580 | } |
| 42581 | rc = freePage2(pBt, pOvfl, ovflPgno); |
| 42582 | if( pOvfl ){ |
| 42583 | sqlite3PagerUnref(pOvfl->pDbPage); |
| 42584 | } |
| 42585 | if( rc ) return rc; |
| 42586 | ovflPgno = iNext; |
| @@ -42820,11 +43426,11 @@ | |
| 42820 | int sz, /* Bytes of content in pCell */ |
| 42821 | u8 *pTemp, /* Temp storage space for pCell, if needed */ |
| 42822 | Pgno iChild, /* If non-zero, replace first 4 bytes with this value */ |
| 42823 | int *pRC /* Read and write return code from here */ |
| 42824 | ){ |
| 42825 | int idx; /* Where to write new cell content in data[] */ |
| 42826 | int j; /* Loop counter */ |
| 42827 | int end; /* First byte past the last cell pointer in data[] */ |
| 42828 | int ins; /* Index in data[] where new cell pointer is inserted */ |
| 42829 | int cellOffset; /* Address of first cell pointer in data[] */ |
| 42830 | u8 *data; /* The content of the whole page */ |
| @@ -43311,14 +43917,14 @@ | |
| 43311 | ** Unless SQLite is compiled in secure-delete mode. In this case, |
| 43312 | ** the dropCell() routine will overwrite the entire cell with zeroes. |
| 43313 | ** In this case, temporarily copy the cell into the aOvflSpace[] |
| 43314 | ** buffer. It will be copied out again as soon as the aSpace[] buffer |
| 43315 | ** is allocated. */ |
| 43316 | #ifdef SQLITE_SECURE_DELETE |
| 43317 | memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]); |
| 43318 | apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; |
| 43319 | #endif |
| 43320 | dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); |
| 43321 | } |
| 43322 | } |
| 43323 | |
| 43324 | /* Make nMaxCells a multiple of 4 in order to preserve 8-byte |
| @@ -43434,11 +44040,11 @@ | |
| 43434 | szNew[k] = subtotal - szCell[i]; |
| 43435 | cntNew[k] = i; |
| 43436 | if( leafData ){ i--; } |
| 43437 | subtotal = 0; |
| 43438 | k++; |
| 43439 | if( k>NB+1 ){ rc = SQLITE_CORRUPT; goto balance_cleanup; } |
| 43440 | } |
| 43441 | } |
| 43442 | szNew[k] = subtotal; |
| 43443 | cntNew[k] = nCell; |
| 43444 | k++; |
| @@ -43488,11 +44094,11 @@ | |
| 43488 | |
| 43489 | /* |
| 43490 | ** Allocate k new pages. Reuse old pages where possible. |
| 43491 | */ |
| 43492 | if( apOld[0]->pgno<=1 ){ |
| 43493 | rc = SQLITE_CORRUPT; |
| 43494 | goto balance_cleanup; |
| 43495 | } |
| 43496 | pageFlags = apOld[0]->aData[0]; |
| 43497 | for(i=0; i<k; i++){ |
| 43498 | MemPage *pNew; |
| @@ -44926,11 +45532,13 @@ | |
| 44926 | ** the root of the tree. |
| 44927 | */ |
| 44928 | static int checkTreePage( |
| 44929 | IntegrityCk *pCheck, /* Context for the sanity check */ |
| 44930 | int iPage, /* Page number of the page to check */ |
| 44931 | char *zParentContext /* Parent context */ |
| 44932 | ){ |
| 44933 | MemPage *pPage; |
| 44934 | int i, rc, depth, d2, pgno, cnt; |
| 44935 | int hdr, cellStart; |
| 44936 | int nCell; |
| @@ -44937,10 +45545,12 @@ | |
| 44937 | u8 *data; |
| 44938 | BtShared *pBt; |
| 44939 | int usableSize; |
| 44940 | char zContext[100]; |
| 44941 | char *hit = 0; |
| 44942 | |
| 44943 | sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); |
| 44944 | |
| 44945 | /* Check that the page exists |
| 44946 | */ |
| @@ -44979,10 +45589,20 @@ | |
| 44979 | "On tree page %d cell %d: ", iPage, i); |
| 44980 | pCell = findCell(pPage,i); |
| 44981 | btreeParseCellPtr(pPage, pCell, &info); |
| 44982 | sz = info.nData; |
| 44983 | if( !pPage->intKey ) sz += (int)info.nKey; |
| 44984 | assert( sz==info.nPayload ); |
| 44985 | if( (sz>info.nLocal) |
| 44986 | && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize]) |
| 44987 | ){ |
| 44988 | int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); |
| @@ -45002,29 +45622,66 @@ | |
| 45002 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45003 | if( pBt->autoVacuum ){ |
| 45004 | checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); |
| 45005 | } |
| 45006 | #endif |
| 45007 | d2 = checkTreePage(pCheck, pgno, zContext); |
| 45008 | if( i>0 && d2!=depth ){ |
| 45009 | checkAppendMsg(pCheck, zContext, "Child page depth differs"); |
| 45010 | } |
| 45011 | depth = d2; |
| 45012 | } |
| 45013 | } |
| 45014 | if( !pPage->leaf ){ |
| 45015 | pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); |
| 45016 | sqlite3_snprintf(sizeof(zContext), zContext, |
| 45017 | "On page %d at right child: ", iPage); |
| 45018 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45019 | if( pBt->autoVacuum ){ |
| 45020 | checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0); |
| 45021 | } |
| 45022 | #endif |
| 45023 | checkTreePage(pCheck, pgno, zContext); |
| 45024 | } |
| 45025 | |
| 45026 | /* Check for complete coverage of the page |
| 45027 | */ |
| 45028 | data = pPage->aData; |
| 45029 | hdr = pPage->hdrOffset; |
| 45030 | hit = sqlite3PageMalloc( pBt->pageSize ); |
| @@ -45044,11 +45701,11 @@ | |
| 45044 | if( pc<=usableSize-4 ){ |
| 45045 | size = cellSizePtr(pPage, &data[pc]); |
| 45046 | } |
| 45047 | if( (pc+size-1)>=usableSize ){ |
| 45048 | checkAppendMsg(pCheck, 0, |
| 45049 | "Corruption detected in cell %d on page %d",i,iPage,0); |
| 45050 | }else{ |
| 45051 | for(j=pc+size-1; j>=pc; j--) hit[j]++; |
| 45052 | } |
| 45053 | } |
| 45054 | i = get2byte(&data[hdr+1]); |
| @@ -45150,11 +45807,11 @@ | |
| 45150 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45151 | if( pBt->autoVacuum && aRoot[i]>1 ){ |
| 45152 | checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); |
| 45153 | } |
| 45154 | #endif |
| 45155 | checkTreePage(&sCheck, aRoot[i], "List of tree roots: "); |
| 45156 | } |
| 45157 | |
| 45158 | /* Make sure every page in the file is referenced |
| 45159 | */ |
| 45160 | for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ |
| @@ -45483,14 +46140,14 @@ | |
| 45483 | sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory"); |
| 45484 | rc = SQLITE_NOMEM; |
| 45485 | }else{ |
| 45486 | pParse->db = pDb; |
| 45487 | if( sqlite3OpenTempDatabase(pParse) ){ |
| 45488 | sqlite3ErrorClear(pParse); |
| 45489 | sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); |
| 45490 | rc = SQLITE_ERROR; |
| 45491 | } |
| 45492 | sqlite3StackFree(pErrorDb, pParse); |
| 45493 | } |
| 45494 | if( rc ){ |
| 45495 | return 0; |
| 45496 | } |
| @@ -46329,10 +46986,14 @@ | |
| 46329 | ** Because we do not completely understand the problem, we will |
| 46330 | ** take the conservative approach and always do range tests |
| 46331 | ** before attempting the conversion. |
| 46332 | */ |
| 46333 | static i64 doubleToInt64(double r){ |
| 46334 | /* |
| 46335 | ** Many compilers we encounter do not define constants for the |
| 46336 | ** minimum and maximum 64-bit integers, or they define them |
| 46337 | ** inconsistently. And many do not understand the "LL" notation. |
| 46338 | ** So we define our own static constants here using nothing |
| @@ -46350,10 +47011,11 @@ | |
| 46350 | ** does so for compatibility we will do the same in software. */ |
| 46351 | return minInt; |
| 46352 | }else{ |
| 46353 | return (i64)r; |
| 46354 | } |
| 46355 | } |
| 46356 | |
| 46357 | /* |
| 46358 | ** Return some kind of integer value which is the best we can do |
| 46359 | ** at representing the value that *pMem describes as an integer. |
| @@ -46477,25 +47139,30 @@ | |
| 46477 | } |
| 46478 | |
| 46479 | /* |
| 46480 | ** Convert pMem so that it has types MEM_Real or MEM_Int or both. |
| 46481 | ** Invalidate any prior representations. |
| 46482 | */ |
| 46483 | SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ |
| 46484 | double r1, r2; |
| 46485 | i64 i; |
| 46486 | assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ); |
| 46487 | assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); |
| 46488 | assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); |
| 46489 | r1 = sqlite3VdbeRealValue(pMem); |
| 46490 | i = doubleToInt64(r1); |
| 46491 | r2 = (double)i; |
| 46492 | if( r1==r2 ){ |
| 46493 | sqlite3VdbeMemIntegerify(pMem); |
| 46494 | }else{ |
| 46495 | pMem->r = r1; |
| 46496 | MemSetTypeFlag(pMem, MEM_Real); |
| 46497 | } |
| 46498 | return SQLITE_OK; |
| 46499 | } |
| 46500 | |
| 46501 | /* |
| @@ -46543,10 +47210,11 @@ | |
| 46543 | pMem->u.i = val; |
| 46544 | pMem->flags = MEM_Int; |
| 46545 | pMem->type = SQLITE_INTEGER; |
| 46546 | } |
| 46547 | |
| 46548 | /* |
| 46549 | ** Delete any previous value and set the value stored in *pMem to val, |
| 46550 | ** manifest type REAL. |
| 46551 | */ |
| 46552 | SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ |
| @@ -46557,10 +47225,11 @@ | |
| 46557 | pMem->r = val; |
| 46558 | pMem->flags = MEM_Real; |
| 46559 | pMem->type = SQLITE_FLOAT; |
| 46560 | } |
| 46561 | } |
| 46562 | |
| 46563 | /* |
| 46564 | ** Delete any previous value and set the value of pMem to be an |
| 46565 | ** empty boolean index. |
| 46566 | */ |
| @@ -47182,11 +47851,11 @@ | |
| 47182 | /* |
| 47183 | ** Return the SQL associated with a prepared statement |
| 47184 | */ |
| 47185 | SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ |
| 47186 | Vdbe *p = (Vdbe *)pStmt; |
| 47187 | return (p->isPrepareV2 ? p->zSql : 0); |
| 47188 | } |
| 47189 | |
| 47190 | /* |
| 47191 | ** Swap all content between two VDBE structures. |
| 47192 | */ |
| @@ -47370,10 +48039,17 @@ | |
| 47370 | assert( j>=0 && j<p->nLabel ); |
| 47371 | if( p->aLabel ){ |
| 47372 | p->aLabel[j] = p->nOp; |
| 47373 | } |
| 47374 | } |
| 47375 | |
| 47376 | #ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ |
| 47377 | |
| 47378 | /* |
| 47379 | ** The following type and function are used to iterate through all opcodes |
| @@ -48175,11 +48851,10 @@ | |
| 48175 | int rc = SQLITE_OK; /* Return code */ |
| 48176 | Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */ |
| 48177 | |
| 48178 | assert( p->explain ); |
| 48179 | assert( p->magic==VDBE_MAGIC_RUN ); |
| 48180 | assert( db->magic==SQLITE_MAGIC_BUSY ); |
| 48181 | assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); |
| 48182 | |
| 48183 | /* Even though this opcode does not use dynamic strings for |
| 48184 | ** the result, result columns may become dynamic if the user calls |
| 48185 | ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. |
| @@ -48590,13 +49265,11 @@ | |
| 48590 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 48591 | if( pCx->pVtabCursor ){ |
| 48592 | sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; |
| 48593 | const sqlite3_module *pModule = pCx->pModule; |
| 48594 | p->inVtabMethod = 1; |
| 48595 | (void)sqlite3SafetyOff(p->db); |
| 48596 | pModule->xClose(pVtabCursor); |
| 48597 | (void)sqlite3SafetyOn(p->db); |
| 48598 | p->inVtabMethod = 0; |
| 48599 | } |
| 48600 | #endif |
| 48601 | } |
| 48602 | |
| @@ -48773,13 +49446,11 @@ | |
| 48773 | } |
| 48774 | } |
| 48775 | |
| 48776 | /* If there are any write-transactions at all, invoke the commit hook */ |
| 48777 | if( needXcommit && db->xCommitCallback ){ |
| 48778 | (void)sqlite3SafetyOff(db); |
| 48779 | rc = db->xCommitCallback(db->pCommitArg); |
| 48780 | (void)sqlite3SafetyOn(db); |
| 48781 | if( rc ){ |
| 48782 | return SQLITE_CONSTRAINT; |
| 48783 | } |
| 48784 | } |
| 48785 | |
| @@ -49329,13 +50000,11 @@ | |
| 49329 | |
| 49330 | /* If the VM did not run to completion or if it encountered an |
| 49331 | ** error, then it might not have been halted properly. So halt |
| 49332 | ** it now. |
| 49333 | */ |
| 49334 | (void)sqlite3SafetyOn(db); |
| 49335 | sqlite3VdbeHalt(p); |
| 49336 | (void)sqlite3SafetyOff(db); |
| 49337 | |
| 49338 | /* If the VDBE has be run even partially, then transfer the error code |
| 49339 | ** and error message from the VDBE into the main database structure. But |
| 49340 | ** if the VDBE has just been set to run but has not actually executed any |
| 49341 | ** instructions yet, leave the main database error information unchanged. |
| @@ -49351,10 +50020,11 @@ | |
| 49351 | }else if( p->rc ){ |
| 49352 | sqlite3Error(db, p->rc, 0); |
| 49353 | }else{ |
| 49354 | sqlite3Error(db, SQLITE_OK, 0); |
| 49355 | } |
| 49356 | }else if( p->rc && p->expired ){ |
| 49357 | /* The expired flag was set on the VDBE before the first call |
| 49358 | ** to sqlite3_step(). For consistency (since sqlite3_step() was |
| 49359 | ** called), set the database error in this case as well. |
| 49360 | */ |
| @@ -49452,10 +50122,11 @@ | |
| 49452 | sqlite3DbFree(db, p->aLabel); |
| 49453 | sqlite3DbFree(db, p->aColName); |
| 49454 | sqlite3DbFree(db, p->zSql); |
| 49455 | p->magic = VDBE_MAGIC_DEAD; |
| 49456 | sqlite3DbFree(db, p->pFree); |
| 49457 | sqlite3DbFree(db, p); |
| 49458 | } |
| 49459 | |
| 49460 | /* |
| 49461 | ** Make sure the cursor p is ready to read or write the row to which it |
| @@ -50132,11 +50803,11 @@ | |
| 50132 | assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ |
| 50133 | /* nCellKey will always be between 0 and 0xffffffff because of the say |
| 50134 | ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ |
| 50135 | if( nCellKey<=0 || nCellKey>0x7fffffff ){ |
| 50136 | *res = 0; |
| 50137 | return SQLITE_CORRUPT; |
| 50138 | } |
| 50139 | memset(&m, 0, sizeof(m)); |
| 50140 | rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m); |
| 50141 | if( rc ){ |
| 50142 | return rc; |
| @@ -50258,10 +50929,32 @@ | |
| 50258 | SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ |
| 50259 | Vdbe *p = (Vdbe*)pStmt; |
| 50260 | return p==0 || p->expired; |
| 50261 | } |
| 50262 | #endif |
| 50263 | |
| 50264 | /* |
| 50265 | ** The following routine destroys a virtual machine that is created by |
| 50266 | ** the sqlite3_compile() routine. The integer returned is an SQLITE_ |
| 50267 | ** success/failure code that describes the result of executing the virtual |
| @@ -50276,11 +50969,15 @@ | |
| 50276 | rc = SQLITE_OK; |
| 50277 | }else{ |
| 50278 | Vdbe *v = (Vdbe*)pStmt; |
| 50279 | sqlite3 *db = v->db; |
| 50280 | #if SQLITE_THREADSAFE |
| 50281 | sqlite3_mutex *mutex = v->db->mutex; |
| 50282 | #endif |
| 50283 | sqlite3_mutex_enter(mutex); |
| 50284 | rc = sqlite3VdbeFinalize(v); |
| 50285 | rc = sqlite3ApiExit(db, rc); |
| 50286 | sqlite3_mutex_leave(mutex); |
| @@ -50523,30 +51220,27 @@ | |
| 50523 | sqlite3 *db; |
| 50524 | int rc; |
| 50525 | |
| 50526 | assert(p); |
| 50527 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| 50528 | return SQLITE_MISUSE; |
| 50529 | } |
| 50530 | |
| 50531 | /* Assert that malloc() has not failed */ |
| 50532 | db = p->db; |
| 50533 | if( db->mallocFailed ){ |
| 50534 | return SQLITE_NOMEM; |
| 50535 | } |
| 50536 | |
| 50537 | if( p->pc<=0 && p->expired ){ |
| 50538 | if( ALWAYS(p->rc==SQLITE_OK || p->rc==SQLITE_SCHEMA) ){ |
| 50539 | p->rc = SQLITE_SCHEMA; |
| 50540 | } |
| 50541 | rc = SQLITE_ERROR; |
| 50542 | goto end_of_step; |
| 50543 | } |
| 50544 | if( sqlite3SafetyOn(db) ){ |
| 50545 | p->rc = SQLITE_MISUSE; |
| 50546 | return SQLITE_MISUSE; |
| 50547 | } |
| 50548 | if( p->pc<0 ){ |
| 50549 | /* If there are no other statements currently running, then |
| 50550 | ** reset the interrupt flag. This prevents a call to sqlite3_interrupt |
| 50551 | ** from interrupting a statement that has not yet started. |
| 50552 | */ |
| @@ -50575,14 +51269,10 @@ | |
| 50575 | #endif /* SQLITE_OMIT_EXPLAIN */ |
| 50576 | { |
| 50577 | rc = sqlite3VdbeExec(p); |
| 50578 | } |
| 50579 | |
| 50580 | if( sqlite3SafetyOff(db) ){ |
| 50581 | rc = SQLITE_MISUSE; |
| 50582 | } |
| 50583 | |
| 50584 | #ifndef SQLITE_OMIT_TRACE |
| 50585 | /* Invoke the profile callback if there is one |
| 50586 | */ |
| 50587 | if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){ |
| 50588 | double rNow; |
| @@ -50625,43 +51315,48 @@ | |
| 50625 | ** This is the top-level implementation of sqlite3_step(). Call |
| 50626 | ** sqlite3Step() to do most of the work. If a schema error occurs, |
| 50627 | ** call sqlite3Reprepare() and try again. |
| 50628 | */ |
| 50629 | SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ |
| 50630 | int rc = SQLITE_MISUSE; |
| 50631 | if( pStmt ){ |
| 50632 | int cnt = 0; |
| 50633 | Vdbe *v = (Vdbe*)pStmt; |
| 50634 | sqlite3 *db = v->db; |
| 50635 | sqlite3_mutex_enter(db->mutex); |
| 50636 | while( (rc = sqlite3Step(v))==SQLITE_SCHEMA |
| 50637 | && cnt++ < 5 |
| 50638 | && (rc = sqlite3Reprepare(v))==SQLITE_OK ){ |
| 50639 | sqlite3_reset(pStmt); |
| 50640 | v->expired = 0; |
| 50641 | } |
| 50642 | if( rc==SQLITE_SCHEMA && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ |
| 50643 | /* This case occurs after failing to recompile an sql statement. |
| 50644 | ** The error message from the SQL compiler has already been loaded |
| 50645 | ** into the database handle. This block copies the error message |
| 50646 | ** from the database handle into the statement and sets the statement |
| 50647 | ** program counter to 0 to ensure that when the statement is |
| 50648 | ** finalized or reset the parser error message is available via |
| 50649 | ** sqlite3_errmsg() and sqlite3_errcode(). |
| 50650 | */ |
| 50651 | const char *zErr = (const char *)sqlite3_value_text(db->pErr); |
| 50652 | sqlite3DbFree(db, v->zErrMsg); |
| 50653 | if( !db->mallocFailed ){ |
| 50654 | v->zErrMsg = sqlite3DbStrDup(db, zErr); |
| 50655 | } else { |
| 50656 | v->zErrMsg = 0; |
| 50657 | v->rc = SQLITE_NOMEM; |
| 50658 | } |
| 50659 | } |
| 50660 | rc = sqlite3ApiExit(db, rc); |
| 50661 | sqlite3_mutex_leave(db->mutex); |
| 50662 | } |
| 50663 | return rc; |
| 50664 | } |
| 50665 | |
| 50666 | /* |
| 50667 | ** Extract the user data from a sqlite3_context structure and return a |
| @@ -51127,16 +51822,20 @@ | |
| 51127 | ** The error code stored in database p->db is overwritten with the return |
| 51128 | ** value in any case. |
| 51129 | */ |
| 51130 | static int vdbeUnbind(Vdbe *p, int i){ |
| 51131 | Mem *pVar; |
| 51132 | if( p==0 ) return SQLITE_MISUSE; |
| 51133 | sqlite3_mutex_enter(p->db->mutex); |
| 51134 | if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ |
| 51135 | sqlite3Error(p->db, SQLITE_MISUSE, 0); |
| 51136 | sqlite3_mutex_leave(p->db->mutex); |
| 51137 | return SQLITE_MISUSE; |
| 51138 | } |
| 51139 | if( i<1 || i>p->nVar ){ |
| 51140 | sqlite3Error(p->db, SQLITE_RANGE, 0); |
| 51141 | sqlite3_mutex_leave(p->db->mutex); |
| 51142 | return SQLITE_RANGE; |
| @@ -52225,11 +52924,11 @@ | |
| 52225 | ** used to clean up the mess that was left behind. |
| 52226 | */ |
| 52227 | SQLITE_PRIVATE int sqlite3VdbeExec( |
| 52228 | Vdbe *p /* The VDBE */ |
| 52229 | ){ |
| 52230 | int pc; /* The program counter */ |
| 52231 | Op *aOp = p->aOp; /* Copy of p->aOp */ |
| 52232 | Op *pOp; /* Current operation */ |
| 52233 | int rc = SQLITE_OK; /* Value to return */ |
| 52234 | sqlite3 *db = p->db; /* The database */ |
| 52235 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */ |
| @@ -52336,11 +53035,11 @@ | |
| 52336 | Mem *pDest; /* Where to write the extracted value */ |
| 52337 | Mem sMem; /* For storing the record being decoded */ |
| 52338 | u8 *zIdx; /* Index into header */ |
| 52339 | u8 *zEndHdr; /* Pointer to first byte after the header */ |
| 52340 | u32 offset; /* Offset into the data */ |
| 52341 | u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */ |
| 52342 | int szHdr; /* Size of the header size field at start of record */ |
| 52343 | int avail; /* Number of bytes of available data */ |
| 52344 | Mem *pReg; /* PseudoTable input register */ |
| 52345 | } am; |
| 52346 | struct OP_Affinity_stack_vars { |
| @@ -52648,11 +53347,10 @@ | |
| 52648 | } u; |
| 52649 | /* End automatically generated code |
| 52650 | ********************************************************************/ |
| 52651 | |
| 52652 | assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ |
| 52653 | assert( db->magic==SQLITE_MAGIC_BUSY ); |
| 52654 | sqlite3VdbeMutexArrayEnter(p); |
| 52655 | if( p->rc==SQLITE_NOMEM ){ |
| 52656 | /* This happens if a malloc() inside a call to sqlite3_column_text() or |
| 52657 | ** sqlite3_column_text16() failed. */ |
| 52658 | goto no_mem; |
| @@ -52733,13 +53431,11 @@ | |
| 52733 | ** a return code SQLITE_ABORT. |
| 52734 | */ |
| 52735 | if( checkProgress ){ |
| 52736 | if( db->nProgressOps==nProgressOps ){ |
| 52737 | int prc; |
| 52738 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 52739 | prc =db->xProgress(db->pProgressArg); |
| 52740 | if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 52741 | if( prc!=0 ){ |
| 52742 | rc = SQLITE_INTERRUPT; |
| 52743 | goto vdbe_error_halt; |
| 52744 | } |
| 52745 | nProgressOps = 0; |
| @@ -52937,11 +53633,17 @@ | |
| 52937 | |
| 52938 | p->rc = pOp->p1; |
| 52939 | p->errorAction = (u8)pOp->p2; |
| 52940 | p->pc = pc; |
| 52941 | if( pOp->p4.z ){ |
| 52942 | sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); |
| 52943 | } |
| 52944 | rc = sqlite3VdbeHalt(p); |
| 52945 | assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); |
| 52946 | if( rc==SQLITE_BUSY ){ |
| 52947 | p->rc = rc = SQLITE_BUSY; |
| @@ -52971,10 +53673,11 @@ | |
| 52971 | assert( pOp->p4.pI64!=0 ); |
| 52972 | pOut->u.i = *pOp->p4.pI64; |
| 52973 | break; |
| 52974 | } |
| 52975 | |
| 52976 | /* Opcode: Real * P2 * P4 * |
| 52977 | ** |
| 52978 | ** P4 is a pointer to a 64-bit floating point value. |
| 52979 | ** Write that value into register P2. |
| 52980 | */ |
| @@ -52982,10 +53685,11 @@ | |
| 52982 | pOut->flags = MEM_Real; |
| 52983 | assert( !sqlite3IsNaN(*pOp->p4.pReal) ); |
| 52984 | pOut->r = *pOp->p4.pReal; |
| 52985 | break; |
| 52986 | } |
| 52987 | |
| 52988 | /* Opcode: String8 * P2 * P4 * |
| 52989 | ** |
| 52990 | ** P4 points to a nul terminated UTF-8 string. This opcode is transformed |
| 52991 | ** into an OP_String before it is executed for the first time. |
| @@ -53392,18 +54096,23 @@ | |
| 53392 | if( u.af.iA==-1 ) u.af.iA = 1; |
| 53393 | u.af.rB = (double)(u.af.iB % u.af.iA); |
| 53394 | break; |
| 53395 | } |
| 53396 | } |
| 53397 | if( sqlite3IsNaN(u.af.rB) ){ |
| 53398 | goto arithmetic_result_is_null; |
| 53399 | } |
| 53400 | pOut->r = u.af.rB; |
| 53401 | MemSetTypeFlag(pOut, MEM_Real); |
| 53402 | if( (u.af.flags & MEM_Real)==0 ){ |
| 53403 | sqlite3VdbeIntegerAffinity(pOut); |
| 53404 | } |
| 53405 | } |
| 53406 | break; |
| 53407 | |
| 53408 | arithmetic_result_is_null: |
| 53409 | sqlite3VdbeMemSetNull(pOut); |
| @@ -53492,25 +54201,16 @@ | |
| 53492 | assert( pOp>aOp ); |
| 53493 | assert( pOp[-1].p4type==P4_COLLSEQ ); |
| 53494 | assert( pOp[-1].opcode==OP_CollSeq ); |
| 53495 | u.ag.ctx.pColl = pOp[-1].p4.pColl; |
| 53496 | } |
| 53497 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 53498 | (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); |
| 53499 | if( sqlite3SafetyOn(db) ){ |
| 53500 | sqlite3VdbeMemRelease(&u.ag.ctx.s); |
| 53501 | goto abort_due_to_misuse; |
| 53502 | } |
| 53503 | if( db->mallocFailed ){ |
| 53504 | /* Even though a malloc() has failed, the implementation of the |
| 53505 | ** user function may have called an sqlite3_result_XXX() function |
| 53506 | ** to return a value. The following call releases any resources |
| 53507 | ** associated with such a value. |
| 53508 | ** |
| 53509 | ** Note: Maybe MemRelease() should be called if sqlite3SafetyOn() |
| 53510 | ** fails also (the if(...) statement above). But if people are |
| 53511 | ** misusing sqlite, they have bigger problems than a leaked value. |
| 53512 | */ |
| 53513 | sqlite3VdbeMemRelease(&u.ag.ctx.s); |
| 53514 | goto no_mem; |
| 53515 | } |
| 53516 | |
| @@ -53631,10 +54331,11 @@ | |
| 53631 | MemSetTypeFlag(pIn1, MEM_Int); |
| 53632 | } |
| 53633 | break; |
| 53634 | } |
| 53635 | |
| 53636 | /* Opcode: RealAffinity P1 * * * * |
| 53637 | ** |
| 53638 | ** If register P1 holds an integer convert it to a real value. |
| 53639 | ** |
| 53640 | ** This opcode is used when extracting information from a column that |
| @@ -53647,10 +54348,11 @@ | |
| 53647 | if( pIn1->flags & MEM_Int ){ |
| 53648 | sqlite3VdbeMemRealify(pIn1); |
| 53649 | } |
| 53650 | break; |
| 53651 | } |
| 53652 | |
| 53653 | #ifndef SQLITE_OMIT_CAST |
| 53654 | /* Opcode: ToText P1 * * * * |
| 53655 | ** |
| 53656 | ** Force the value in register P1 to be text. |
| @@ -53730,11 +54432,11 @@ | |
| 53730 | sqlite3VdbeMemIntegerify(pIn1); |
| 53731 | } |
| 53732 | break; |
| 53733 | } |
| 53734 | |
| 53735 | #ifndef SQLITE_OMIT_CAST |
| 53736 | /* Opcode: ToReal P1 * * * * |
| 53737 | ** |
| 53738 | ** Force the value in register P1 to be a floating point number. |
| 53739 | ** If The value is currently an integer, convert it. |
| 53740 | ** If the value is text or blob, try to convert it to an integer using the |
| @@ -53747,11 +54449,11 @@ | |
| 53747 | if( (pIn1->flags & MEM_Null)==0 ){ |
| 53748 | sqlite3VdbeMemRealify(pIn1); |
| 53749 | } |
| 53750 | break; |
| 53751 | } |
| 53752 | #endif /* SQLITE_OMIT_CAST */ |
| 53753 | |
| 53754 | /* Opcode: Lt P1 P2 P3 P4 P5 |
| 53755 | ** |
| 53756 | ** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then |
| 53757 | ** jump to address P2. |
| @@ -54169,11 +54871,11 @@ | |
| 54169 | Mem *pDest; /* Where to write the extracted value */ |
| 54170 | Mem sMem; /* For storing the record being decoded */ |
| 54171 | u8 *zIdx; /* Index into header */ |
| 54172 | u8 *zEndHdr; /* Pointer to first byte after the header */ |
| 54173 | u32 offset; /* Offset into the data */ |
| 54174 | u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */ |
| 54175 | int szHdr; /* Size of the header size field at start of record */ |
| 54176 | int avail; /* Number of bytes of available data */ |
| 54177 | Mem *pReg; /* PseudoTable input register */ |
| 54178 | #endif /* local variables moved into u.am */ |
| 54179 | |
| @@ -54345,16 +55047,20 @@ | |
| 54345 | /* Scan the header and use it to fill in the u.am.aType[] and u.am.aOffset[] |
| 54346 | ** arrays. u.am.aType[u.am.i] will contain the type integer for the u.am.i-th |
| 54347 | ** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning |
| 54348 | ** of the record to the start of the data for the u.am.i-th column |
| 54349 | */ |
| 54350 | u.am.offset64 = u.am.offset; |
| 54351 | for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){ |
| 54352 | if( u.am.zIdx<u.am.zEndHdr ){ |
| 54353 | u.am.aOffset[u.am.i] = (u32)u.am.offset64; |
| 54354 | u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]); |
| 54355 | u.am.offset64 += sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]); |
| 54356 | }else{ |
| 54357 | /* If u.am.i is less that u.am.nField, then there are less fields in this |
| 54358 | ** record than SetNumColumns indicated there are columns in the |
| 54359 | ** table. Set the u.am.offset for any extra columns not present in |
| 54360 | ** the record to 0. This tells code below to store a NULL |
| @@ -54370,12 +55076,12 @@ | |
| 54370 | ** or if the end of the last field appears to be past the end of the |
| 54371 | ** record, or if the end of the last field appears to be before the end |
| 54372 | ** of the record (when all fields present), then we must be dealing |
| 54373 | ** with a corrupt database. |
| 54374 | */ |
| 54375 | if( (u.am.zIdx > u.am.zEndHdr)|| (u.am.offset64 > u.am.payloadSize) |
| 54376 | || (u.am.zIdx==u.am.zEndHdr && u.am.offset64!=(u64)u.am.payloadSize) ){ |
| 54377 | rc = SQLITE_CORRUPT_BKPT; |
| 54378 | goto op_column_out; |
| 54379 | } |
| 54380 | } |
| 54381 | |
| @@ -55239,11 +55945,11 @@ | |
| 55239 | ** Open a new cursor that points to a fake table that contains a single |
| 55240 | ** row of data. The content of that one row in the content of memory |
| 55241 | ** register P2. In other words, cursor P1 becomes an alias for the |
| 55242 | ** MEM_Blob content contained in register P2. |
| 55243 | ** |
| 55244 | ** A pseudo-table created by this opcode is used to hold the a single |
| 55245 | ** row output from the sorter so that the row can be decomposed into |
| 55246 | ** individual columns using the OP_Column opcode. The OP_Column opcode |
| 55247 | ** is the only cursor opcode that works with a pseudo-table. |
| 55248 | ** |
| 55249 | ** P3 is the number of fields in the records that will be stored by |
| @@ -56191,16 +56897,14 @@ | |
| 56191 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 56192 | }else if( u.bi.pC->pVtabCursor ){ |
| 56193 | u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab; |
| 56194 | u.bi.pModule = u.bi.pVtab->pModule; |
| 56195 | assert( u.bi.pModule->xRowid ); |
| 56196 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 56197 | rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v); |
| 56198 | sqlite3DbFree(db, p->zErrMsg); |
| 56199 | p->zErrMsg = u.bi.pVtab->zErrMsg; |
| 56200 | u.bi.pVtab->zErrMsg = 0; |
| 56201 | if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 56202 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 56203 | }else{ |
| 56204 | assert( u.bi.pC->pCursor!=0 ); |
| 56205 | rc = sqlite3VdbeCursorMoveto(u.bi.pC); |
| 56206 | if( rc ) goto abort_due_to_error; |
| @@ -56751,25 +57455,23 @@ | |
| 56751 | u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb); |
| 56752 | u.bu.initData.db = db; |
| 56753 | u.bu.initData.iDb = pOp->p1; |
| 56754 | u.bu.initData.pzErrMsg = &p->zErrMsg; |
| 56755 | u.bu.zSql = sqlite3MPrintf(db, |
| 56756 | "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s", |
| 56757 | db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z); |
| 56758 | if( u.bu.zSql==0 ){ |
| 56759 | rc = SQLITE_NOMEM; |
| 56760 | }else{ |
| 56761 | (void)sqlite3SafetyOff(db); |
| 56762 | assert( db->init.busy==0 ); |
| 56763 | db->init.busy = 1; |
| 56764 | u.bu.initData.rc = SQLITE_OK; |
| 56765 | assert( !db->mallocFailed ); |
| 56766 | rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0); |
| 56767 | if( rc==SQLITE_OK ) rc = u.bu.initData.rc; |
| 56768 | sqlite3DbFree(db, u.bu.zSql); |
| 56769 | db->init.busy = 0; |
| 56770 | (void)sqlite3SafetyOn(db); |
| 56771 | } |
| 56772 | } |
| 56773 | sqlite3BtreeLeaveAll(db); |
| 56774 | if( rc==SQLITE_NOMEM ){ |
| 56775 | goto no_mem; |
| @@ -57351,13 +58053,11 @@ | |
| 57351 | ** Vacuum the entire database. This opcode will cause other virtual |
| 57352 | ** machines to be created and run. It may not be called from within |
| 57353 | ** a transaction. |
| 57354 | */ |
| 57355 | case OP_Vacuum: { |
| 57356 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57357 | rc = sqlite3RunVacuum(&p->zErrMsg, db); |
| 57358 | if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57359 | break; |
| 57360 | } |
| 57361 | #endif |
| 57362 | |
| 57363 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| @@ -57503,16 +58203,14 @@ | |
| 57503 | u.cf.pCur = 0; |
| 57504 | u.cf.pVtabCursor = 0; |
| 57505 | u.cf.pVtab = pOp->p4.pVtab->pVtab; |
| 57506 | u.cf.pModule = (sqlite3_module *)u.cf.pVtab->pModule; |
| 57507 | assert(u.cf.pVtab && u.cf.pModule); |
| 57508 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57509 | rc = u.cf.pModule->xOpen(u.cf.pVtab, &u.cf.pVtabCursor); |
| 57510 | sqlite3DbFree(db, p->zErrMsg); |
| 57511 | p->zErrMsg = u.cf.pVtab->zErrMsg; |
| 57512 | u.cf.pVtab->zErrMsg = 0; |
| 57513 | if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57514 | if( SQLITE_OK==rc ){ |
| 57515 | /* Initialize sqlite3_vtab_cursor base class */ |
| 57516 | u.cf.pVtabCursor->pVtab = u.cf.pVtab; |
| 57517 | |
| 57518 | /* Initialise vdbe cursor object */ |
| @@ -57584,21 +58282,19 @@ | |
| 57584 | for(u.cg.i = 0; u.cg.i<u.cg.nArg; u.cg.i++){ |
| 57585 | u.cg.apArg[u.cg.i] = &u.cg.pArgc[u.cg.i+1]; |
| 57586 | sqlite3VdbeMemStoreType(u.cg.apArg[u.cg.i]); |
| 57587 | } |
| 57588 | |
| 57589 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57590 | p->inVtabMethod = 1; |
| 57591 | rc = u.cg.pModule->xFilter(u.cg.pVtabCursor, u.cg.iQuery, pOp->p4.z, u.cg.nArg, u.cg.apArg); |
| 57592 | p->inVtabMethod = 0; |
| 57593 | sqlite3DbFree(db, p->zErrMsg); |
| 57594 | p->zErrMsg = u.cg.pVtab->zErrMsg; |
| 57595 | u.cg.pVtab->zErrMsg = 0; |
| 57596 | if( rc==SQLITE_OK ){ |
| 57597 | u.cg.res = u.cg.pModule->xEof(u.cg.pVtabCursor); |
| 57598 | } |
| 57599 | if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57600 | |
| 57601 | if( u.cg.res ){ |
| 57602 | pc = pOp->p2 - 1; |
| 57603 | } |
| 57604 | } |
| @@ -57642,11 +58338,10 @@ | |
| 57642 | ** new one. |
| 57643 | */ |
| 57644 | sqlite3VdbeMemMove(&u.ch.sContext.s, u.ch.pDest); |
| 57645 | MemSetTypeFlag(&u.ch.sContext.s, MEM_Null); |
| 57646 | |
| 57647 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57648 | rc = u.ch.pModule->xColumn(pCur->pVtabCursor, &u.ch.sContext, pOp->p2); |
| 57649 | sqlite3DbFree(db, p->zErrMsg); |
| 57650 | p->zErrMsg = u.ch.pVtab->zErrMsg; |
| 57651 | u.ch.pVtab->zErrMsg = 0; |
| 57652 | if( u.ch.sContext.isError ){ |
| @@ -57660,13 +58355,10 @@ | |
| 57660 | sqlite3VdbeChangeEncoding(&u.ch.sContext.s, encoding); |
| 57661 | sqlite3VdbeMemMove(u.ch.pDest, &u.ch.sContext.s); |
| 57662 | REGISTER_TRACE(pOp->p3, u.ch.pDest); |
| 57663 | UPDATE_MAX_BLOBSIZE(u.ch.pDest); |
| 57664 | |
| 57665 | if( sqlite3SafetyOn(db) ){ |
| 57666 | goto abort_due_to_misuse; |
| 57667 | } |
| 57668 | if( sqlite3VdbeMemTooBig(u.ch.pDest) ){ |
| 57669 | goto too_big; |
| 57670 | } |
| 57671 | break; |
| 57672 | } |
| @@ -57701,21 +58393,19 @@ | |
| 57701 | ** underlying implementation to return an error if one occurs during |
| 57702 | ** xNext(). Instead, if an error occurs, true is returned (indicating that |
| 57703 | ** data is available) and the error code returned when xColumn or |
| 57704 | ** some other method is next invoked on the save virtual table cursor. |
| 57705 | */ |
| 57706 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57707 | p->inVtabMethod = 1; |
| 57708 | rc = u.ci.pModule->xNext(u.ci.pCur->pVtabCursor); |
| 57709 | p->inVtabMethod = 0; |
| 57710 | sqlite3DbFree(db, p->zErrMsg); |
| 57711 | p->zErrMsg = u.ci.pVtab->zErrMsg; |
| 57712 | u.ci.pVtab->zErrMsg = 0; |
| 57713 | if( rc==SQLITE_OK ){ |
| 57714 | u.ci.res = u.ci.pModule->xEof(u.ci.pCur->pVtabCursor); |
| 57715 | } |
| 57716 | if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57717 | |
| 57718 | if( !u.ci.res ){ |
| 57719 | /* If there is data, jump to P2 */ |
| 57720 | pc = pOp->p2 - 1; |
| 57721 | } |
| @@ -57739,16 +58429,14 @@ | |
| 57739 | u.cj.pVtab = pOp->p4.pVtab->pVtab; |
| 57740 | u.cj.pName = &aMem[pOp->p1]; |
| 57741 | assert( u.cj.pVtab->pModule->xRename ); |
| 57742 | REGISTER_TRACE(pOp->p1, u.cj.pName); |
| 57743 | assert( u.cj.pName->flags & MEM_Str ); |
| 57744 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57745 | rc = u.cj.pVtab->pModule->xRename(u.cj.pVtab, u.cj.pName->z); |
| 57746 | sqlite3DbFree(db, p->zErrMsg); |
| 57747 | p->zErrMsg = u.cj.pVtab->zErrMsg; |
| 57748 | u.cj.pVtab->zErrMsg = 0; |
| 57749 | if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57750 | |
| 57751 | break; |
| 57752 | } |
| 57753 | #endif |
| 57754 | |
| @@ -57797,16 +58485,14 @@ | |
| 57797 | for(u.ck.i=0; u.ck.i<u.ck.nArg; u.ck.i++){ |
| 57798 | sqlite3VdbeMemStoreType(u.ck.pX); |
| 57799 | u.ck.apArg[u.ck.i] = u.ck.pX; |
| 57800 | u.ck.pX++; |
| 57801 | } |
| 57802 | if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57803 | rc = u.ck.pModule->xUpdate(u.ck.pVtab, u.ck.nArg, u.ck.apArg, &u.ck.rowid); |
| 57804 | sqlite3DbFree(db, p->zErrMsg); |
| 57805 | p->zErrMsg = u.ck.pVtab->zErrMsg; |
| 57806 | u.ck.pVtab->zErrMsg = 0; |
| 57807 | if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57808 | if( rc==SQLITE_OK && pOp->p1 ){ |
| 57809 | assert( u.ck.nArg>1 && u.ck.apArg[0] && (u.ck.apArg[0]->flags&MEM_Null) ); |
| 57810 | db->lastRowid = u.ck.rowid; |
| 57811 | } |
| 57812 | p->nChange++; |
| @@ -57879,10 +58565,11 @@ | |
| 57879 | ** is to say when the EXPLAIN QUERY PLAN syntax is used.) |
| 57880 | ** This opcode records information from the optimizer. It is the |
| 57881 | ** the same as a no-op. This opcodesnever appears in a real VM program. |
| 57882 | */ |
| 57883 | default: { /* This is really OP_Noop and OP_Explain */ |
| 57884 | break; |
| 57885 | } |
| 57886 | |
| 57887 | /***************************************************************************** |
| 57888 | ** The cases of the switch statement above this line should all be indented |
| @@ -57930,10 +58617,11 @@ | |
| 57930 | ** an error of some kind. |
| 57931 | */ |
| 57932 | vdbe_error_halt: |
| 57933 | assert( rc ); |
| 57934 | p->rc = rc; |
| 57935 | sqlite3VdbeHalt(p); |
| 57936 | if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; |
| 57937 | rc = SQLITE_ERROR; |
| 57938 | if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0); |
| 57939 | |
| @@ -57958,16 +58646,10 @@ | |
| 57958 | db->mallocFailed = 1; |
| 57959 | sqlite3SetString(&p->zErrMsg, db, "out of memory"); |
| 57960 | rc = SQLITE_NOMEM; |
| 57961 | goto vdbe_error_halt; |
| 57962 | |
| 57963 | /* Jump to here for an SQLITE_MISUSE error. |
| 57964 | */ |
| 57965 | abort_due_to_misuse: |
| 57966 | rc = SQLITE_MISUSE; |
| 57967 | /* Fall thru into abort_due_to_error */ |
| 57968 | |
| 57969 | /* Jump to here for any other kind of fatal error. The "rc" variable |
| 57970 | ** should hold the error number. |
| 57971 | */ |
| 57972 | abort_due_to_error: |
| 57973 | assert( p->zErrMsg==0 ); |
| @@ -58083,17 +58765,10 @@ | |
| 58083 | } |
| 58084 | do { |
| 58085 | memset(pParse, 0, sizeof(Parse)); |
| 58086 | pParse->db = db; |
| 58087 | |
| 58088 | if( sqlite3SafetyOn(db) ){ |
| 58089 | sqlite3DbFree(db, zErr); |
| 58090 | sqlite3StackFree(db, pParse); |
| 58091 | sqlite3_mutex_leave(db->mutex); |
| 58092 | return SQLITE_MISUSE; |
| 58093 | } |
| 58094 | |
| 58095 | sqlite3BtreeEnterAll(db); |
| 58096 | pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); |
| 58097 | if( pTab && IsVirtual(pTab) ){ |
| 58098 | pTab = 0; |
| 58099 | sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); |
| @@ -58109,11 +58784,10 @@ | |
| 58109 | sqlite3DbFree(db, zErr); |
| 58110 | zErr = pParse->zErrMsg; |
| 58111 | pParse->zErrMsg = 0; |
| 58112 | } |
| 58113 | rc = SQLITE_ERROR; |
| 58114 | (void)sqlite3SafetyOff(db); |
| 58115 | sqlite3BtreeLeaveAll(db); |
| 58116 | goto blob_open_out; |
| 58117 | } |
| 58118 | |
| 58119 | /* Now search pTab for the exact column. */ |
| @@ -58124,11 +58798,10 @@ | |
| 58124 | } |
| 58125 | if( iCol==pTab->nCol ){ |
| 58126 | sqlite3DbFree(db, zErr); |
| 58127 | zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); |
| 58128 | rc = SQLITE_ERROR; |
| 58129 | (void)sqlite3SafetyOff(db); |
| 58130 | sqlite3BtreeLeaveAll(db); |
| 58131 | goto blob_open_out; |
| 58132 | } |
| 58133 | |
| 58134 | /* If the value is being opened for writing, check that the |
| @@ -58165,11 +58838,10 @@ | |
| 58165 | } |
| 58166 | if( zFault ){ |
| 58167 | sqlite3DbFree(db, zErr); |
| 58168 | zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault); |
| 58169 | rc = SQLITE_ERROR; |
| 58170 | (void)sqlite3SafetyOff(db); |
| 58171 | sqlite3BtreeLeaveAll(db); |
| 58172 | goto blob_open_out; |
| 58173 | } |
| 58174 | } |
| 58175 | |
| @@ -58215,12 +58887,11 @@ | |
| 58215 | sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0); |
| 58216 | } |
| 58217 | } |
| 58218 | |
| 58219 | sqlite3BtreeLeaveAll(db); |
| 58220 | rc = sqlite3SafetyOff(db); |
| 58221 | if( NEVER(rc!=SQLITE_OK) || db->mallocFailed ){ |
| 58222 | goto blob_open_out; |
| 58223 | } |
| 58224 | |
| 58225 | sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow); |
| 58226 | rc = sqlite3_step((sqlite3_stmt *)v); |
| @@ -58317,11 +58988,11 @@ | |
| 58317 | int rc; |
| 58318 | Incrblob *p = (Incrblob *)pBlob; |
| 58319 | Vdbe *v; |
| 58320 | sqlite3 *db; |
| 58321 | |
| 58322 | if( p==0 ) return SQLITE_MISUSE; |
| 58323 | db = p->db; |
| 58324 | sqlite3_mutex_enter(db->mutex); |
| 58325 | v = (Vdbe*)p->pStmt; |
| 58326 | |
| 58327 | if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ |
| @@ -59675,10 +60346,13 @@ | |
| 59675 | Expr *pE /* The specific ORDER BY term */ |
| 59676 | ){ |
| 59677 | int i; /* Loop counter */ |
| 59678 | ExprList *pEList; /* The columns of the result set */ |
| 59679 | NameContext nc; /* Name context for resolving pE */ |
| 59680 | |
| 59681 | assert( sqlite3ExprIsInteger(pE, &i)==0 ); |
| 59682 | pEList = pSelect->pEList; |
| 59683 | |
| 59684 | /* Resolve all names in the ORDER BY term expression |
| @@ -59687,21 +60361,23 @@ | |
| 59687 | nc.pParse = pParse; |
| 59688 | nc.pSrcList = pSelect->pSrc; |
| 59689 | nc.pEList = pEList; |
| 59690 | nc.allowAgg = 1; |
| 59691 | nc.nErr = 0; |
| 59692 | if( sqlite3ResolveExprNames(&nc, pE) ){ |
| 59693 | sqlite3ErrorClear(pParse); |
| 59694 | return 0; |
| 59695 | } |
| 59696 | |
| 59697 | /* Try to match the ORDER BY expression against an expression |
| 59698 | ** in the result set. Return an 1-based index of the matching |
| 59699 | ** result-set entry. |
| 59700 | */ |
| 59701 | for(i=0; i<pEList->nExpr; i++){ |
| 59702 | if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){ |
| 59703 | return i+1; |
| 59704 | } |
| 59705 | } |
| 59706 | |
| 59707 | /* If no match, return 0. */ |
| @@ -62091,10 +62767,11 @@ | |
| 62091 | memcpy(out, in, 8); |
| 62092 | } |
| 62093 | return out; |
| 62094 | } |
| 62095 | |
| 62096 | /* |
| 62097 | ** Generate an instruction that will put the floating point |
| 62098 | ** value described by z[0..n-1] into register iMem. |
| 62099 | ** |
| 62100 | ** The z[] string will probably not be zero-terminated. But the |
| @@ -62110,10 +62787,11 @@ | |
| 62110 | if( negateFlag ) value = -value; |
| 62111 | zV = dup8bytes(v, (char*)&value); |
| 62112 | sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); |
| 62113 | } |
| 62114 | } |
| 62115 | |
| 62116 | |
| 62117 | /* |
| 62118 | ** Generate an instruction that will put the integer describe by |
| 62119 | ** text z[0..n-1] into register iMem. |
| @@ -62120,11 +62798,12 @@ | |
| 62120 | ** |
| 62121 | ** The z[] string will probably not be zero-terminated. But the |
| 62122 | ** z[n] character is guaranteed to be something that does not look |
| 62123 | ** like the continuation of the number. |
| 62124 | */ |
| 62125 | static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ |
| 62126 | if( pExpr->flags & EP_IntValue ){ |
| 62127 | int i = pExpr->u.iValue; |
| 62128 | if( negFlag ) i = -i; |
| 62129 | sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); |
| 62130 | }else{ |
| @@ -62136,11 +62815,15 @@ | |
| 62136 | sqlite3Atoi64(z, &value); |
| 62137 | if( negFlag ) value = -value; |
| 62138 | zV = dup8bytes(v, (char*)&value); |
| 62139 | sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); |
| 62140 | }else{ |
| 62141 | codeReal(v, z, negFlag, iMem); |
| 62142 | } |
| 62143 | } |
| 62144 | } |
| 62145 | |
| 62146 | /* |
| @@ -62523,18 +63206,20 @@ | |
| 62523 | pExpr->iColumn, pExpr->iTable, target); |
| 62524 | } |
| 62525 | break; |
| 62526 | } |
| 62527 | case TK_INTEGER: { |
| 62528 | codeInteger(v, pExpr, 0, target); |
| 62529 | break; |
| 62530 | } |
| 62531 | case TK_FLOAT: { |
| 62532 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 62533 | codeReal(v, pExpr->u.zToken, 0, target); |
| 62534 | break; |
| 62535 | } |
| 62536 | case TK_STRING: { |
| 62537 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 62538 | sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); |
| 62539 | break; |
| 62540 | } |
| @@ -62700,15 +63385,17 @@ | |
| 62700 | break; |
| 62701 | } |
| 62702 | case TK_UMINUS: { |
| 62703 | Expr *pLeft = pExpr->pLeft; |
| 62704 | assert( pLeft ); |
| 62705 | if( pLeft->op==TK_FLOAT ){ |
| 62706 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 62707 | codeReal(v, pLeft->u.zToken, 1, target); |
| 62708 | }else if( pLeft->op==TK_INTEGER ){ |
| 62709 | codeInteger(v, pLeft, 1, target); |
| 62710 | }else{ |
| 62711 | regFree1 = r1 = sqlite3GetTempReg(pParse); |
| 62712 | sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); |
| 62713 | r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); |
| 62714 | sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); |
| @@ -62952,17 +63639,19 @@ | |
| 62952 | (pExpr->iTable ? "new" : "old"), |
| 62953 | (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), |
| 62954 | target |
| 62955 | )); |
| 62956 | |
| 62957 | /* If the column has REAL affinity, it may currently be stored as an |
| 62958 | ** integer. Use OP_RealAffinity to make sure it is really real. */ |
| 62959 | if( pExpr->iColumn>=0 |
| 62960 | && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL |
| 62961 | ){ |
| 62962 | sqlite3VdbeAddOp1(v, OP_RealAffinity, target); |
| 62963 | } |
| 62964 | break; |
| 62965 | } |
| 62966 | |
| 62967 | |
| 62968 | /* |
| @@ -63624,61 +64313,65 @@ | |
| 63624 | sqlite3ReleaseTempReg(pParse, regFree1); |
| 63625 | sqlite3ReleaseTempReg(pParse, regFree2); |
| 63626 | } |
| 63627 | |
| 63628 | /* |
| 63629 | ** Do a deep comparison of two expression trees. Return TRUE (non-zero) |
| 63630 | ** if they are identical and return FALSE if they differ in any way. |
| 63631 | ** |
| 63632 | ** Sometimes this routine will return FALSE even if the two expressions |
| 63633 | ** really are equivalent. If we cannot prove that the expressions are |
| 63634 | ** identical, we return FALSE just to be safe. So if this routine |
| 63635 | ** returns false, then you do not really know for certain if the two |
| 63636 | ** expressions are the same. But if you get a TRUE return, then you |
| 63637 | ** can be sure the expressions are the same. In the places where |
| 63638 | ** this routine is used, it does not hurt to get an extra FALSE - that |
| 63639 | ** just might result in some slightly slower code. But returning |
| 63640 | ** an incorrect TRUE could lead to a malfunction. |
| 63641 | */ |
| 63642 | SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){ |
| 63643 | int i; |
| 63644 | if( pA==0||pB==0 ){ |
| 63645 | return pB==pA; |
| 63646 | } |
| 63647 | assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); |
| 63648 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 63649 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 63650 | return 0; |
| 63651 | } |
| 63652 | if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0; |
| 63653 | if( pA->op!=pB->op ) return 0; |
| 63654 | if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0; |
| 63655 | if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0; |
| 63656 | |
| 63657 | if( pA->x.pList && pB->x.pList ){ |
| 63658 | if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 0; |
| 63659 | for(i=0; i<pA->x.pList->nExpr; i++){ |
| 63660 | Expr *pExprA = pA->x.pList->a[i].pExpr; |
| 63661 | Expr *pExprB = pB->x.pList->a[i].pExpr; |
| 63662 | if( !sqlite3ExprCompare(pExprA, pExprB) ) return 0; |
| 63663 | } |
| 63664 | }else if( pA->x.pList || pB->x.pList ){ |
| 63665 | return 0; |
| 63666 | } |
| 63667 | |
| 63668 | if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; |
| 63669 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| 63670 | if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ |
| 63671 | return 0; |
| 63672 | } |
| 63673 | }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ |
| 63674 | if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 0; |
| 63675 | if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 63676 | return 0; |
| 63677 | } |
| 63678 | } |
| 63679 | return 1; |
| 63680 | } |
| 63681 | |
| 63682 | |
| 63683 | /* |
| 63684 | ** Add a new element to the pAggInfo->aCol[] array. Return the index of |
| @@ -63805,11 +64498,11 @@ | |
| 63805 | /* Check to see if pExpr is a duplicate of another aggregate |
| 63806 | ** function that is already in the pAggInfo structure |
| 63807 | */ |
| 63808 | struct AggInfo_func *pItem = pAggInfo->aFunc; |
| 63809 | for(i=0; i<pAggInfo->nFunc; i++, pItem++){ |
| 63810 | if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){ |
| 63811 | break; |
| 63812 | } |
| 63813 | } |
| 63814 | if( i>=pAggInfo->nFunc ){ |
| 63815 | /* pExpr is original. Make a new entry in pAggInfo->aFunc[] |
| @@ -64426,13 +65119,13 @@ | |
| 64426 | /* If foreign-key support is enabled, rewrite the CREATE TABLE |
| 64427 | ** statements corresponding to all child tables of foreign key constraints |
| 64428 | ** for which the renamed table is the parent table. */ |
| 64429 | if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ |
| 64430 | sqlite3NestedParse(pParse, |
| 64431 | "UPDATE sqlite_master SET " |
| 64432 | "sql = sqlite_rename_parent(sql, %Q, %Q) " |
| 64433 | "WHERE %s;", zTabName, zName, zWhere); |
| 64434 | sqlite3DbFree(db, zWhere); |
| 64435 | } |
| 64436 | } |
| 64437 | #endif |
| 64438 | |
| @@ -65301,13 +65994,11 @@ | |
| 65301 | zSql = sqlite3MPrintf(db, |
| 65302 | "SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase); |
| 65303 | if( zSql==0 ){ |
| 65304 | rc = SQLITE_NOMEM; |
| 65305 | }else{ |
| 65306 | (void)sqlite3SafetyOff(db); |
| 65307 | rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); |
| 65308 | (void)sqlite3SafetyOn(db); |
| 65309 | sqlite3DbFree(db, zSql); |
| 65310 | } |
| 65311 | |
| 65312 | |
| 65313 | /* Load the statistics from the sqlite_stat2 table. */ |
| @@ -65321,18 +66012,15 @@ | |
| 65321 | zSql = sqlite3MPrintf(db, |
| 65322 | "SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase); |
| 65323 | if( !zSql ){ |
| 65324 | rc = SQLITE_NOMEM; |
| 65325 | }else{ |
| 65326 | (void)sqlite3SafetyOff(db); |
| 65327 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 65328 | (void)sqlite3SafetyOn(db); |
| 65329 | sqlite3DbFree(db, zSql); |
| 65330 | } |
| 65331 | |
| 65332 | if( rc==SQLITE_OK ){ |
| 65333 | (void)sqlite3SafetyOff(db); |
| 65334 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 65335 | char *zIndex = (char *)sqlite3_column_text(pStmt, 0); |
| 65336 | Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase); |
| 65337 | if( pIdx ){ |
| 65338 | int iSample = sqlite3_column_int(pStmt, 1); |
| @@ -65378,11 +66066,10 @@ | |
| 65378 | } |
| 65379 | } |
| 65380 | } |
| 65381 | } |
| 65382 | rc = sqlite3_finalize(pStmt); |
| 65383 | (void)sqlite3SafetyOn(db); |
| 65384 | } |
| 65385 | } |
| 65386 | #endif |
| 65387 | |
| 65388 | if( rc==SQLITE_NOMEM ){ |
| @@ -65539,15 +66226,21 @@ | |
| 65539 | rc = SQLITE_ERROR; |
| 65540 | } |
| 65541 | pPager = sqlite3BtreePager(aNew->pBt); |
| 65542 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 65543 | sqlite3PagerJournalMode(pPager, db->dfltJournalMode); |
| 65544 | } |
| 65545 | aNew->zName = sqlite3DbStrDup(db, zName); |
| 65546 | aNew->safety_level = 3; |
| 65547 | |
| 65548 | #if SQLITE_HAS_CODEC |
| 65549 | if( rc==SQLITE_OK ){ |
| 65550 | extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); |
| 65551 | extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); |
| 65552 | int nKey; |
| 65553 | char *zKey; |
| @@ -65579,15 +66272,13 @@ | |
| 65579 | ** If this fails, or if opening the file failed, then close the file and |
| 65580 | ** remove the entry from the db->aDb[] array. i.e. put everything back the way |
| 65581 | ** we found it. |
| 65582 | */ |
| 65583 | if( rc==SQLITE_OK ){ |
| 65584 | (void)sqlite3SafetyOn(db); |
| 65585 | sqlite3BtreeEnterAll(db); |
| 65586 | rc = sqlite3Init(db, &zErrDyn); |
| 65587 | sqlite3BtreeLeaveAll(db); |
| 65588 | (void)sqlite3SafetyOff(db); |
| 65589 | } |
| 65590 | if( rc ){ |
| 65591 | int iDb = db->nDb - 1; |
| 65592 | assert( iDb>=2 ); |
| 65593 | if( db->aDb[iDb].pBt ){ |
| @@ -66385,11 +67076,11 @@ | |
| 66385 | sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem, |
| 66386 | pParse->nTab, pParse->nMaxArg, pParse->explain, |
| 66387 | pParse->isMultiWrite && pParse->mayAbort); |
| 66388 | pParse->rc = SQLITE_DONE; |
| 66389 | pParse->colNamesSet = 0; |
| 66390 | }else if( pParse->rc==SQLITE_OK ){ |
| 66391 | pParse->rc = SQLITE_ERROR; |
| 66392 | } |
| 66393 | pParse->nTab = 0; |
| 66394 | pParse->nMem = 0; |
| 66395 | pParse->nSet = 0; |
| @@ -68157,17 +68848,16 @@ | |
| 68157 | if( db->mallocFailed ){ |
| 68158 | goto exit_drop_table; |
| 68159 | } |
| 68160 | assert( pParse->nErr==0 ); |
| 68161 | assert( pName->nSrc==1 ); |
| 68162 | pTab = sqlite3LocateTable(pParse, isView, |
| 68163 | pName->a[0].zName, pName->a[0].zDatabase); |
| 68164 | |
| 68165 | if( pTab==0 ){ |
| 68166 | if( noErr ){ |
| 68167 | sqlite3ErrorClear(pParse); |
| 68168 | } |
| 68169 | goto exit_drop_table; |
| 68170 | } |
| 68171 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 68172 | assert( iDb>=0 && iDb<db->nDb ); |
| 68173 | |
| @@ -69585,28 +70275,32 @@ | |
| 69585 | */ |
| 69586 | SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ |
| 69587 | sqlite3 *db = pParse->db; |
| 69588 | if( db->aDb[1].pBt==0 && !pParse->explain ){ |
| 69589 | int rc; |
| 69590 | static const int flags = |
| 69591 | SQLITE_OPEN_READWRITE | |
| 69592 | SQLITE_OPEN_CREATE | |
| 69593 | SQLITE_OPEN_EXCLUSIVE | |
| 69594 | SQLITE_OPEN_DELETEONCLOSE | |
| 69595 | SQLITE_OPEN_TEMP_DB; |
| 69596 | |
| 69597 | rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, |
| 69598 | &db->aDb[1].pBt); |
| 69599 | if( rc!=SQLITE_OK ){ |
| 69600 | sqlite3ErrorMsg(pParse, "unable to open a temporary database " |
| 69601 | "file for storing temporary tables"); |
| 69602 | pParse->rc = rc; |
| 69603 | return 1; |
| 69604 | } |
| 69605 | assert( db->aDb[1].pSchema ); |
| 69606 | sqlite3PagerJournalMode(sqlite3BtreePager(db->aDb[1].pBt), |
| 69607 | db->dfltJournalMode); |
| 69608 | } |
| 69609 | return 0; |
| 69610 | } |
| 69611 | |
| 69612 | /* |
| @@ -70339,10 +71033,397 @@ | |
| 70339 | } |
| 70340 | return p; |
| 70341 | } |
| 70342 | |
| 70343 | /************** End of callback.c ********************************************/ |
| 70344 | /************** Begin file delete.c ******************************************/ |
| 70345 | /* |
| 70346 | ** 2001 September 15 |
| 70347 | ** |
| 70348 | ** The author disclaims copyright to this source code. In place of |
| @@ -71247,18 +72328,28 @@ | |
| 71247 | if( n>30 ) n = 30; |
| 71248 | if( n<0 ) n = 0; |
| 71249 | } |
| 71250 | if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
| 71251 | r = sqlite3_value_double(argv[0]); |
| 71252 | zBuf = sqlite3_mprintf("%.*f",n,r); |
| 71253 | if( zBuf==0 ){ |
| 71254 | sqlite3_result_error_nomem(context); |
| 71255 | }else{ |
| 71256 | sqlite3AtoF(zBuf, &r); |
| 71257 | sqlite3_free(zBuf); |
| 71258 | sqlite3_result_double(context, r); |
| 71259 | } |
| 71260 | } |
| 71261 | #endif |
| 71262 | |
| 71263 | /* |
| 71264 | ** Allocate nByte bytes of space using sqlite3_malloc(). If the |
| @@ -71416,16 +72507,22 @@ | |
| 71416 | int NotUsed, |
| 71417 | sqlite3_value **NotUsed2 |
| 71418 | ){ |
| 71419 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 71420 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 71421 | sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); |
| 71422 | } |
| 71423 | |
| 71424 | /* |
| 71425 | ** Implementation of the changes() SQL function. The return value is the |
| 71426 | ** same as the sqlite3_changes() API function. |
| 71427 | */ |
| 71428 | static void changes( |
| 71429 | sqlite3_context *context, |
| 71430 | int NotUsed, |
| 71431 | sqlite3_value **NotUsed2 |
| @@ -71444,10 +72541,12 @@ | |
| 71444 | int NotUsed, |
| 71445 | sqlite3_value **NotUsed2 |
| 71446 | ){ |
| 71447 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 71448 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 71449 | sqlite3_result_int(context, sqlite3_total_changes(db)); |
| 71450 | } |
| 71451 | |
| 71452 | /* |
| 71453 | ** A structure defining how to do GLOB-style comparisons. |
| @@ -71711,11 +72810,13 @@ | |
| 71711 | sqlite3_context *context, |
| 71712 | int NotUsed, |
| 71713 | sqlite3_value **NotUsed2 |
| 71714 | ){ |
| 71715 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 71716 | sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC); |
| 71717 | } |
| 71718 | |
| 71719 | /* |
| 71720 | ** Implementation of the sqlite_source_id() function. The result is a string |
| 71721 | ** that identifies the particular version of the source code used to build |
| @@ -71725,13 +72826,58 @@ | |
| 71725 | sqlite3_context *context, |
| 71726 | int NotUsed, |
| 71727 | sqlite3_value **NotUsed2 |
| 71728 | ){ |
| 71729 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 71730 | sqlite3_result_text(context, SQLITE_SOURCE_ID, -1, SQLITE_STATIC); |
| 71731 | } |
| 71732 | |
| 71733 | /* Array for converting from half-bytes (nybbles) into ASCII hex |
| 71734 | ** digits. */ |
| 71735 | static const char hexdigits[] = { |
| 71736 | '0', '1', '2', '3', '4', '5', '6', '7', |
| 71737 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' |
| @@ -71854,11 +73000,11 @@ | |
| 71854 | testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
| 71855 | testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); |
| 71856 | if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 71857 | sqlite3_result_error_toobig(context); |
| 71858 | }else{ |
| 71859 | sqlite3_result_zeroblob(context, (int)n); |
| 71860 | } |
| 71861 | } |
| 71862 | |
| 71863 | /* |
| 71864 | ** The replace() function. Three arguments are all strings: call |
| @@ -72459,10 +73605,14 @@ | |
| 72459 | FUNCTION(random, 0, 0, 0, randomFunc ), |
| 72460 | FUNCTION(randomblob, 1, 0, 0, randomBlob ), |
| 72461 | FUNCTION(nullif, 2, 0, 1, nullifFunc ), |
| 72462 | FUNCTION(sqlite_version, 0, 0, 0, versionFunc ), |
| 72463 | FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), |
| 72464 | FUNCTION(quote, 1, 0, 0, quoteFunc ), |
| 72465 | FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), |
| 72466 | FUNCTION(changes, 0, 0, 0, changes ), |
| 72467 | FUNCTION(total_changes, 0, 0, 0, total_changes ), |
| 72468 | FUNCTION(replace, 3, 0, 0, replaceFunc ), |
| @@ -74958,23 +76108,37 @@ | |
| 74958 | ** recursive-triggers flag is set, call GenerateRowDelete() to |
| 74959 | ** remove the conflicting row from the the table. This will fire |
| 74960 | ** the triggers and remove both the table and index b-tree entries. |
| 74961 | ** |
| 74962 | ** Otherwise, if there are no triggers or the recursive-triggers |
| 74963 | ** flag is not set, call GenerateRowIndexDelete(). This removes |
| 74964 | ** the index b-tree entries only. The table b-tree entry will be |
| 74965 | ** replaced by the new entry when it is inserted. */ |
| 74966 | Trigger *pTrigger = 0; |
| 74967 | if( pParse->db->flags&SQLITE_RecTriggers ){ |
| 74968 | pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
| 74969 | } |
| 74970 | sqlite3MultiWrite(pParse); |
| 74971 | if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ |
| 74972 | sqlite3GenerateRowDelete( |
| 74973 | pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace |
| 74974 | ); |
| 74975 | }else{ |
| 74976 | sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); |
| 74977 | } |
| 74978 | seenReplace = 1; |
| 74979 | break; |
| 74980 | } |
| @@ -75412,11 +76576,11 @@ | |
| 75412 | if( pSrcIdx==0 ){ |
| 75413 | return 0; /* pDestIdx has no corresponding index in pSrc */ |
| 75414 | } |
| 75415 | } |
| 75416 | #ifndef SQLITE_OMIT_CHECK |
| 75417 | if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ |
| 75418 | return 0; /* Tables have different CHECK constraints. Ticket #2252 */ |
| 75419 | } |
| 75420 | #endif |
| 75421 | |
| 75422 | /* If we get this far, it means either: |
| @@ -75555,10 +76719,11 @@ | |
| 75555 | sqlite3_stmt *pStmt = 0; /* The current SQL statement */ |
| 75556 | char **azCols = 0; /* Names of result columns */ |
| 75557 | int nRetry = 0; /* Number of retry attempts */ |
| 75558 | int callbackIsInit; /* True if callback data is initialized */ |
| 75559 | |
| 75560 | if( zSql==0 ) zSql = ""; |
| 75561 | |
| 75562 | sqlite3_mutex_enter(db->mutex); |
| 75563 | sqlite3Error(db, SQLITE_OK, 0); |
| 75564 | while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){ |
| @@ -76936,10 +78101,11 @@ | |
| 76936 | int iDb; /* Database index for <database> */ |
| 76937 | sqlite3 *db = pParse->db; |
| 76938 | Db *pDb; |
| 76939 | Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); |
| 76940 | if( v==0 ) return; |
| 76941 | pParse->nMem = 2; |
| 76942 | |
| 76943 | /* Interpret the [database.] part of the pragma statement. iDb is the |
| 76944 | ** index of the database this pragma is being applied to in db.aDb[]. */ |
| 76945 | iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); |
| @@ -77067,10 +78233,35 @@ | |
| 77067 | newMax = sqlite3BtreeMaxPageCount(pBt, newMax); |
| 77068 | } |
| 77069 | returnSingleInt(pParse, "max_page_count", newMax); |
| 77070 | }else |
| 77071 | |
| 77072 | /* |
| 77073 | ** PRAGMA [database.]page_count |
| 77074 | ** |
| 77075 | ** Return the number of pages in the specified database. |
| 77076 | */ |
| @@ -77985,10 +79176,38 @@ | |
| 77985 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); |
| 77986 | } |
| 77987 | }else |
| 77988 | #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ |
| 77989 | |
| 77990 | #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
| 77991 | /* |
| 77992 | ** Report the current state of file logs for all databases |
| 77993 | */ |
| 77994 | if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ |
| @@ -78019,11 +79238,11 @@ | |
| 78019 | } |
| 78020 | |
| 78021 | }else |
| 78022 | #endif |
| 78023 | |
| 78024 | #if SQLITE_HAS_CODEC |
| 78025 | if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){ |
| 78026 | sqlite3_key(db, zRight, sqlite3Strlen30(zRight)); |
| 78027 | }else |
| 78028 | if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){ |
| 78029 | sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight)); |
| @@ -78042,36 +79261,28 @@ | |
| 78042 | }else{ |
| 78043 | sqlite3_rekey(db, zKey, i/2); |
| 78044 | } |
| 78045 | }else |
| 78046 | #endif |
| 78047 | #if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD) |
| 78048 | if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){ |
| 78049 | #if SQLITE_HAS_CODEC |
| 78050 | if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ |
| 78051 | extern void sqlite3_activate_see(const char*); |
| 78052 | sqlite3_activate_see(&zRight[4]); |
| 78053 | } |
| 78054 | #endif |
| 78055 | #ifdef SQLITE_ENABLE_CEROD |
| 78056 | if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ |
| 78057 | extern void sqlite3_activate_cerod(const char*); |
| 78058 | sqlite3_activate_cerod(&zRight[6]); |
| 78059 | } |
| 78060 | #endif |
| 78061 | }else |
| 78062 | #endif |
| 78063 | |
| 78064 | |
| 78065 | {/* Empty ELSE clause */} |
| 78066 | |
| 78067 | /* Code an OP_Expire at the end of each PRAGMA program to cause |
| 78068 | ** the VDBE implementing the pragma to expire. Most (all?) pragmas |
| 78069 | ** are only valid for a single execution. |
| 78070 | */ |
| 78071 | sqlite3VdbeAddOp2(v, OP_Expire, 1, 0); |
| 78072 | |
| 78073 | /* |
| 78074 | ** Reset the safety level, in case the fullfsync flag or synchronous |
| 78075 | ** setting changed. |
| 78076 | */ |
| 78077 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| @@ -78280,13 +79491,11 @@ | |
| 78280 | azArg[3] = 0; |
| 78281 | initData.db = db; |
| 78282 | initData.iDb = iDb; |
| 78283 | initData.rc = SQLITE_OK; |
| 78284 | initData.pzErrMsg = pzErrMsg; |
| 78285 | (void)sqlite3SafetyOff(db); |
| 78286 | sqlite3InitCallback(&initData, 3, (char **)azArg, 0); |
| 78287 | (void)sqlite3SafetyOn(db); |
| 78288 | if( initData.rc ){ |
| 78289 | rc = initData.rc; |
| 78290 | goto error_out; |
| 78291 | } |
| 78292 | pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); |
| @@ -78403,13 +79612,12 @@ | |
| 78403 | */ |
| 78404 | assert( db->init.busy ); |
| 78405 | { |
| 78406 | char *zSql; |
| 78407 | zSql = sqlite3MPrintf(db, |
| 78408 | "SELECT name, rootpage, sql FROM '%q'.%s", |
| 78409 | db->aDb[iDb].zName, zMasterName); |
| 78410 | (void)sqlite3SafetyOff(db); |
| 78411 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 78412 | { |
| 78413 | int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); |
| 78414 | xAuth = db->xAuth; |
| 78415 | db->xAuth = 0; |
| @@ -78418,11 +79626,10 @@ | |
| 78418 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 78419 | db->xAuth = xAuth; |
| 78420 | } |
| 78421 | #endif |
| 78422 | if( rc==SQLITE_OK ) rc = initData.rc; |
| 78423 | (void)sqlite3SafetyOn(db); |
| 78424 | sqlite3DbFree(db, zSql); |
| 78425 | #ifndef SQLITE_OMIT_ANALYZE |
| 78426 | if( rc==SQLITE_OK ){ |
| 78427 | sqlite3AnalysisLoad(db, iDb); |
| 78428 | } |
| @@ -78627,15 +79834,10 @@ | |
| 78627 | if( pParse==0 ){ |
| 78628 | rc = SQLITE_NOMEM; |
| 78629 | goto end_prepare; |
| 78630 | } |
| 78631 | pParse->pReprepare = pReprepare; |
| 78632 | |
| 78633 | if( sqlite3SafetyOn(db) ){ |
| 78634 | rc = SQLITE_MISUSE; |
| 78635 | goto end_prepare; |
| 78636 | } |
| 78637 | assert( ppStmt && *ppStmt==0 ); |
| 78638 | assert( !db->mallocFailed ); |
| 78639 | assert( sqlite3_mutex_held(db->mutex) ); |
| 78640 | |
| 78641 | /* Check to verify that it is possible to get a read lock on all |
| @@ -78667,11 +79869,10 @@ | |
| 78667 | assert( sqlite3BtreeHoldsMutex(pBt) ); |
| 78668 | rc = sqlite3BtreeSchemaLocked(pBt); |
| 78669 | if( rc ){ |
| 78670 | const char *zDb = db->aDb[i].zName; |
| 78671 | sqlite3Error(db, rc, "database schema is locked: %s", zDb); |
| 78672 | (void)sqlite3SafetyOff(db); |
| 78673 | testcase( db->flags & SQLITE_ReadUncommitted ); |
| 78674 | goto end_prepare; |
| 78675 | } |
| 78676 | } |
| 78677 | } |
| @@ -78684,11 +79885,10 @@ | |
| 78684 | int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 78685 | testcase( nBytes==mxLen ); |
| 78686 | testcase( nBytes==mxLen+1 ); |
| 78687 | if( nBytes>mxLen ){ |
| 78688 | sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); |
| 78689 | (void)sqlite3SafetyOff(db); |
| 78690 | rc = sqlite3ApiExit(db, SQLITE_TOOBIG); |
| 78691 | goto end_prepare; |
| 78692 | } |
| 78693 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 78694 | if( zSqlCopy ){ |
| @@ -78741,14 +79941,10 @@ | |
| 78741 | azColName[i], SQLITE_STATIC); |
| 78742 | } |
| 78743 | } |
| 78744 | #endif |
| 78745 | |
| 78746 | if( sqlite3SafetyOff(db) ){ |
| 78747 | rc = SQLITE_MISUSE; |
| 78748 | } |
| 78749 | |
| 78750 | assert( db->init.busy==0 || saveSqlFlag==0 ); |
| 78751 | if( db->init.busy==0 ){ |
| 78752 | Vdbe *pVdbe = pParse->pVdbe; |
| 78753 | sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); |
| 78754 | } |
| @@ -78792,11 +79988,11 @@ | |
| 78792 | ){ |
| 78793 | int rc; |
| 78794 | assert( ppStmt!=0 ); |
| 78795 | *ppStmt = 0; |
| 78796 | if( !sqlite3SafetyCheckOk(db) ){ |
| 78797 | return SQLITE_MISUSE; |
| 78798 | } |
| 78799 | sqlite3_mutex_enter(db->mutex); |
| 78800 | sqlite3BtreeEnterAll(db); |
| 78801 | rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); |
| 78802 | if( rc==SQLITE_SCHEMA ){ |
| @@ -78831,11 +80027,11 @@ | |
| 78831 | if( rc ){ |
| 78832 | if( rc==SQLITE_NOMEM ){ |
| 78833 | db->mallocFailed = 1; |
| 78834 | } |
| 78835 | assert( pNew==0 ); |
| 78836 | return (rc==SQLITE_LOCKED) ? SQLITE_LOCKED : SQLITE_SCHEMA; |
| 78837 | }else{ |
| 78838 | assert( pNew!=0 ); |
| 78839 | } |
| 78840 | sqlite3VdbeSwap((Vdbe*)pNew, p); |
| 78841 | sqlite3TransferBindings(pNew, (sqlite3_stmt*)p); |
| @@ -78900,11 +80096,11 @@ | |
| 78900 | int rc = SQLITE_OK; |
| 78901 | |
| 78902 | assert( ppStmt ); |
| 78903 | *ppStmt = 0; |
| 78904 | if( !sqlite3SafetyCheckOk(db) ){ |
| 78905 | return SQLITE_MISUSE; |
| 78906 | } |
| 78907 | sqlite3_mutex_enter(db->mutex); |
| 78908 | zSql8 = sqlite3Utf16to8(db, zSql, nBytes); |
| 78909 | if( zSql8 ){ |
| 78910 | rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); |
| @@ -82288,22 +83484,23 @@ | |
| 82288 | int i; |
| 82289 | SrcList *pTabList; |
| 82290 | struct SrcList_item *pFrom; |
| 82291 | |
| 82292 | assert( p->selFlags & SF_Resolved ); |
| 82293 | assert( (p->selFlags & SF_HasTypeInfo)==0 ); |
| 82294 | p->selFlags |= SF_HasTypeInfo; |
| 82295 | pParse = pWalker->pParse; |
| 82296 | pTabList = p->pSrc; |
| 82297 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 82298 | Table *pTab = pFrom->pTab; |
| 82299 | if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
| 82300 | /* A sub-query in the FROM clause of a SELECT */ |
| 82301 | Select *pSel = pFrom->pSelect; |
| 82302 | assert( pSel ); |
| 82303 | while( pSel->pPrior ) pSel = pSel->pPrior; |
| 82304 | selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel); |
| 82305 | } |
| 82306 | } |
| 82307 | return WRC_Continue; |
| 82308 | } |
| 82309 | #endif |
| @@ -83571,11 +84768,12 @@ | |
| 83571 | */ |
| 83572 | if( !pTableName || db->mallocFailed ){ |
| 83573 | goto trigger_cleanup; |
| 83574 | } |
| 83575 | pTab = sqlite3SrcListLookup(pParse, pTableName); |
| 83576 | if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ |
| 83577 | iDb = 1; |
| 83578 | } |
| 83579 | |
| 83580 | /* Ensure the table name matches database name and that the table exists */ |
| 83581 | if( db->mallocFailed ) goto trigger_cleanup; |
| @@ -83699,16 +84897,16 @@ | |
| 83699 | SQLITE_PRIVATE void sqlite3FinishTrigger( |
| 83700 | Parse *pParse, /* Parser context */ |
| 83701 | TriggerStep *pStepList, /* The triggered program */ |
| 83702 | Token *pAll /* Token that describes the complete CREATE TRIGGER */ |
| 83703 | ){ |
| 83704 | Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ |
| 83705 | char *zName; /* Name of trigger */ |
| 83706 | sqlite3 *db = pParse->db; /* The database */ |
| 83707 | DbFixer sFix; |
| 83708 | int iDb; /* Database containing the trigger */ |
| 83709 | Token nameToken; /* Trigger name for error reporting */ |
| 83710 | |
| 83711 | pTrig = pParse->pNewTrigger; |
| 83712 | pParse->pNewTrigger = 0; |
| 83713 | if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; |
| 83714 | zName = pTrig->zName; |
| @@ -83723,11 +84921,11 @@ | |
| 83723 | if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) |
| 83724 | && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ |
| 83725 | goto triggerfinish_cleanup; |
| 83726 | } |
| 83727 | |
| 83728 | /* if we are not initializing, and this trigger is not on a TEMP table, |
| 83729 | ** build the sqlite_master entry |
| 83730 | */ |
| 83731 | if( !db->init.busy ){ |
| 83732 | Vdbe *v; |
| 83733 | char *z; |
| @@ -85222,47 +86420,61 @@ | |
| 85222 | ** Most of the code in this file may be omitted by defining the |
| 85223 | ** SQLITE_OMIT_VACUUM macro. |
| 85224 | */ |
| 85225 | |
| 85226 | #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) |
| 85227 | /* |
| 85228 | ** Execute zSql on database db. Return an error code. |
| 85229 | */ |
| 85230 | static int execSql(sqlite3 *db, const char *zSql){ |
| 85231 | sqlite3_stmt *pStmt; |
| 85232 | VVA_ONLY( int rc; ) |
| 85233 | if( !zSql ){ |
| 85234 | return SQLITE_NOMEM; |
| 85235 | } |
| 85236 | if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ |
| 85237 | return sqlite3_errcode(db); |
| 85238 | } |
| 85239 | VVA_ONLY( rc = ) sqlite3_step(pStmt); |
| 85240 | assert( rc!=SQLITE_ROW ); |
| 85241 | return sqlite3_finalize(pStmt); |
| 85242 | } |
| 85243 | |
| 85244 | /* |
| 85245 | ** Execute zSql on database db. The statement returns exactly |
| 85246 | ** one column. Execute this as SQL on the same database. |
| 85247 | */ |
| 85248 | static int execExecSql(sqlite3 *db, const char *zSql){ |
| 85249 | sqlite3_stmt *pStmt; |
| 85250 | int rc; |
| 85251 | |
| 85252 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 85253 | if( rc!=SQLITE_OK ) return rc; |
| 85254 | |
| 85255 | while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 85256 | rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0)); |
| 85257 | if( rc!=SQLITE_OK ){ |
| 85258 | sqlite3_finalize(pStmt); |
| 85259 | return rc; |
| 85260 | } |
| 85261 | } |
| 85262 | |
| 85263 | return sqlite3_finalize(pStmt); |
| 85264 | } |
| 85265 | |
| 85266 | /* |
| 85267 | ** The non-standard VACUUM command is used to clean up the database, |
| 85268 | ** collapse free space, etc. It is modelled after the VACUUM command |
| @@ -85308,11 +86520,11 @@ | |
| 85308 | saved_flags = db->flags; |
| 85309 | saved_nChange = db->nChange; |
| 85310 | saved_nTotalChange = db->nTotalChange; |
| 85311 | saved_xTrace = db->xTrace; |
| 85312 | db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; |
| 85313 | db->flags &= ~SQLITE_ForeignKeys; |
| 85314 | db->xTrace = 0; |
| 85315 | |
| 85316 | pMain = db->aDb[0].pBt; |
| 85317 | isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); |
| 85318 | |
| @@ -85329,11 +86541,11 @@ | |
| 85329 | ** empty. Only the journal header is written. Apparently it takes more |
| 85330 | ** time to parse and run the PRAGMA to turn journalling off than it does |
| 85331 | ** to write the journal header file. |
| 85332 | */ |
| 85333 | zSql = "ATTACH '' AS vacuum_db;"; |
| 85334 | rc = execSql(db, zSql); |
| 85335 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85336 | pDb = &db->aDb[db->nDb-1]; |
| 85337 | assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); |
| 85338 | pTemp = db->aDb[db->nDb-1].pBt; |
| 85339 | |
| @@ -85361,11 +86573,11 @@ | |
| 85361 | || NEVER(db->mallocFailed) |
| 85362 | ){ |
| 85363 | rc = SQLITE_NOMEM; |
| 85364 | goto end_of_vacuum; |
| 85365 | } |
| 85366 | rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); |
| 85367 | if( rc!=SQLITE_OK ){ |
| 85368 | goto end_of_vacuum; |
| 85369 | } |
| 85370 | |
| 85371 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| @@ -85372,53 +86584,52 @@ | |
| 85372 | sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : |
| 85373 | sqlite3BtreeGetAutoVacuum(pMain)); |
| 85374 | #endif |
| 85375 | |
| 85376 | /* Begin a transaction */ |
| 85377 | rc = execSql(db, "BEGIN EXCLUSIVE;"); |
| 85378 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85379 | |
| 85380 | /* Query the schema of the main database. Create a mirror schema |
| 85381 | ** in the temporary database. |
| 85382 | */ |
| 85383 | rc = execExecSql(db, |
| 85384 | "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " |
| 85385 | " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" |
| 85386 | " AND rootpage>0" |
| 85387 | ); |
| 85388 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85389 | rc = execExecSql(db, |
| 85390 | "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)" |
| 85391 | " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "); |
| 85392 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85393 | rc = execExecSql(db, |
| 85394 | "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " |
| 85395 | " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); |
| 85396 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85397 | |
| 85398 | /* Loop through the tables in the main database. For each, do |
| 85399 | ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy |
| 85400 | ** the contents to the temporary database. |
| 85401 | */ |
| 85402 | rc = execExecSql(db, |
| 85403 | "SELECT 'INSERT INTO vacuum_db.' || quote(name) " |
| 85404 | "|| ' SELECT * FROM main.' || quote(name) || ';'" |
| 85405 | "FROM main.sqlite_master " |
| 85406 | "WHERE type = 'table' AND name!='sqlite_sequence' " |
| 85407 | " AND rootpage>0" |
| 85408 | |
| 85409 | ); |
| 85410 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85411 | |
| 85412 | /* Copy over the sequence table |
| 85413 | */ |
| 85414 | rc = execExecSql(db, |
| 85415 | "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " |
| 85416 | "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " |
| 85417 | ); |
| 85418 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85419 | rc = execExecSql(db, |
| 85420 | "SELECT 'INSERT INTO vacuum_db.' || quote(name) " |
| 85421 | "|| ' SELECT * FROM main.' || quote(name) || ';' " |
| 85422 | "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';" |
| 85423 | ); |
| 85424 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| @@ -85427,11 +86638,11 @@ | |
| 85427 | /* Copy the triggers, views, and virtual tables from the main database |
| 85428 | ** over to the temporary database. None of these objects has any |
| 85429 | ** associated storage, so all we have to do is copy their entries |
| 85430 | ** from the SQLITE_MASTER table. |
| 85431 | */ |
| 85432 | rc = execSql(db, |
| 85433 | "INSERT INTO vacuum_db.sqlite_master " |
| 85434 | " SELECT type, name, tbl_name, rootpage, sql" |
| 85435 | " FROM main.sqlite_master" |
| 85436 | " WHERE type='view' OR type='trigger'" |
| 85437 | " OR (type='table' AND rootpage=0)" |
| @@ -85639,20 +86850,11 @@ | |
| 85639 | |
| 85640 | pVTab->nRef--; |
| 85641 | if( pVTab->nRef==0 ){ |
| 85642 | sqlite3_vtab *p = pVTab->pVtab; |
| 85643 | if( p ){ |
| 85644 | #ifdef SQLITE_DEBUG |
| 85645 | if( pVTab->db->magic==SQLITE_MAGIC_BUSY ){ |
| 85646 | (void)sqlite3SafetyOff(db); |
| 85647 | p->pModule->xDisconnect(p); |
| 85648 | (void)sqlite3SafetyOn(db); |
| 85649 | } else |
| 85650 | #endif |
| 85651 | { |
| 85652 | p->pModule->xDisconnect(p); |
| 85653 | } |
| 85654 | } |
| 85655 | sqlite3DbFree(db, pVTab); |
| 85656 | } |
| 85657 | } |
| 85658 | |
| @@ -85984,13 +87186,11 @@ | |
| 85984 | assert( !db->pVTab ); |
| 85985 | assert( xConstruct ); |
| 85986 | db->pVTab = pTab; |
| 85987 | |
| 85988 | /* Invoke the virtual table constructor */ |
| 85989 | (void)sqlite3SafetyOff(db); |
| 85990 | rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
| 85991 | (void)sqlite3SafetyOn(db); |
| 85992 | if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 85993 | |
| 85994 | if( SQLITE_OK!=rc ){ |
| 85995 | if( zErr==0 ){ |
| 85996 | *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
| @@ -86174,11 +87374,11 @@ | |
| 86174 | sqlite3_mutex_enter(db->mutex); |
| 86175 | pTab = db->pVTab; |
| 86176 | if( !pTab ){ |
| 86177 | sqlite3Error(db, SQLITE_MISUSE, 0); |
| 86178 | sqlite3_mutex_leave(db->mutex); |
| 86179 | return SQLITE_MISUSE; |
| 86180 | } |
| 86181 | assert( (pTab->tabFlags & TF_Virtual)!=0 ); |
| 86182 | |
| 86183 | pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
| 86184 | if( pParse==0 ){ |
| @@ -86233,14 +87433,12 @@ | |
| 86233 | |
| 86234 | pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); |
| 86235 | if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ |
| 86236 | VTable *p = vtabDisconnectAll(db, pTab); |
| 86237 | |
| 86238 | rc = sqlite3SafetyOff(db); |
| 86239 | assert( rc==SQLITE_OK ); |
| 86240 | rc = p->pMod->pModule->xDestroy(p->pVtab); |
| 86241 | (void)sqlite3SafetyOn(db); |
| 86242 | |
| 86243 | /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ |
| 86244 | if( rc==SQLITE_OK ){ |
| 86245 | assert( pTab->pVTable==p && p->pNext==0 ); |
| 86246 | p->pVtab = 0; |
| @@ -86288,14 +87486,12 @@ | |
| 86288 | ** sqlite3DbFree() containing an error message, if one is available. |
| 86289 | */ |
| 86290 | SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){ |
| 86291 | int i; |
| 86292 | int rc = SQLITE_OK; |
| 86293 | int rcsafety; |
| 86294 | VTable **aVTrans = db->aVTrans; |
| 86295 | |
| 86296 | rc = sqlite3SafetyOff(db); |
| 86297 | db->aVTrans = 0; |
| 86298 | for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){ |
| 86299 | int (*x)(sqlite3_vtab *); |
| 86300 | sqlite3_vtab *pVtab = aVTrans[i]->pVtab; |
| 86301 | if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ |
| @@ -86304,15 +87500,10 @@ | |
| 86304 | *pzErrmsg = pVtab->zErrMsg; |
| 86305 | pVtab->zErrMsg = 0; |
| 86306 | } |
| 86307 | } |
| 86308 | db->aVTrans = aVTrans; |
| 86309 | rcsafety = sqlite3SafetyOn(db); |
| 86310 | |
| 86311 | if( rc==SQLITE_OK ){ |
| 86312 | rc = rcsafety; |
| 86313 | } |
| 86314 | return rc; |
| 86315 | } |
| 86316 | |
| 86317 | /* |
| 86318 | ** Invoke the xRollback method of all virtual tables in the |
| @@ -87131,11 +88322,11 @@ | |
| 87131 | ** be the name of an indexed column with TEXT affinity. */ |
| 87132 | return 0; |
| 87133 | } |
| 87134 | assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ |
| 87135 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 87136 | assert( pColl!=0 ); /* Every non-IPK column has a collating sequence */ |
| 87137 | if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) && |
| 87138 | (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){ |
| 87139 | /* IMP: R-09003-32046 For the GLOB operator, the column must use the |
| 87140 | ** default BINARY collating sequence. |
| 87141 | ** IMP: R-41408-28306 For the LIKE operator, if case_sensitive_like mode |
| @@ -87574,11 +88765,11 @@ | |
| 87574 | WhereTerm *pTerm; /* The term to be analyzed */ |
| 87575 | WhereMaskSet *pMaskSet; /* Set of table index masks */ |
| 87576 | Expr *pExpr; /* The expression to be analyzed */ |
| 87577 | Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ |
| 87578 | Bitmask prereqAll; /* Prerequesites of pExpr */ |
| 87579 | Bitmask extraRight = 0; /* */ |
| 87580 | Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ |
| 87581 | int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ |
| 87582 | int noCase = 0; /* LIKE/GLOB distinguishes case */ |
| 87583 | int op; /* Top-level operator. pExpr->op */ |
| 87584 | Parse *pParse = pWC->pParse; /* Parsing context */ |
| @@ -87646,11 +88837,12 @@ | |
| 87646 | } |
| 87647 | exprCommute(pParse, pDup); |
| 87648 | pLeft = pDup->pLeft; |
| 87649 | pNew->leftCursor = pLeft->iTable; |
| 87650 | pNew->u.leftColumn = pLeft->iColumn; |
| 87651 | pNew->prereqRight = prereqLeft; |
| 87652 | pNew->prereqAll = prereqAll; |
| 87653 | pNew->eOperator = operatorMask(pDup->op); |
| 87654 | } |
| 87655 | } |
| 87656 | |
| @@ -88236,16 +89428,14 @@ | |
| 88236 | static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ |
| 88237 | sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; |
| 88238 | int i; |
| 88239 | int rc; |
| 88240 | |
| 88241 | (void)sqlite3SafetyOff(pParse->db); |
| 88242 | WHERETRACE(("xBestIndex for %s\n", pTab->zName)); |
| 88243 | TRACE_IDX_INPUTS(p); |
| 88244 | rc = pVtab->pModule->xBestIndex(pVtab, p); |
| 88245 | TRACE_IDX_OUTPUTS(p); |
| 88246 | (void)sqlite3SafetyOn(pParse->db); |
| 88247 | |
| 88248 | if( rc!=SQLITE_OK ){ |
| 88249 | if( rc==SQLITE_NOMEM ){ |
| 88250 | pParse->db->mallocFailed = 1; |
| 88251 | }else if( !pVtab->zErrMsg ){ |
| @@ -90871,11 +92061,11 @@ | |
| 90871 | ** shifting terminals. |
| 90872 | ** yy_reduce_ofst[] For each state, the offset into yy_action for |
| 90873 | ** shifting non-terminals after a reduce. |
| 90874 | ** yy_default[] Default action for each state. |
| 90875 | */ |
| 90876 | #define YY_ACTTAB_COUNT (1543) |
| 90877 | static const YYACTIONTYPE yy_action[] = { |
| 90878 | /* 0 */ 313, 49, 556, 46, 147, 172, 628, 598, 55, 55, |
| 90879 | /* 10 */ 55, 55, 302, 53, 53, 53, 53, 52, 52, 51, |
| 90880 | /* 20 */ 51, 51, 50, 238, 603, 66, 624, 623, 604, 598, |
| 90881 | /* 30 */ 591, 585, 48, 53, 53, 53, 53, 52, 52, 51, |
| @@ -91021,17 +92211,17 @@ | |
| 91021 | /* 1430 */ 602, 81, 411, 514, 414, 512, 131, 602, 70, 229, |
| 91022 | /* 1440 */ 228, 227, 494, 602, 17, 411, 488, 414, 259, 346, |
| 91023 | /* 1450 */ 249, 389, 487, 486, 314, 164, 602, 79, 310, 240, |
| 91024 | /* 1460 */ 414, 373, 480, 163, 262, 371, 414, 162, 369, 602, |
| 91025 | /* 1470 */ 78, 212, 478, 26, 477, 602, 9, 161, 467, 363, |
| 91026 | /* 1480 */ 141, 122, 339, 187, 119, 457, 348, 117, 347, 116, |
| 91027 | /* 1490 */ 115, 114, 448, 112, 182, 320, 22, 433, 19, 432, |
| 91028 | /* 1500 */ 431, 63, 428, 610, 193, 298, 597, 574, 572, 404, |
| 91029 | /* 1510 */ 555, 552, 290, 281, 510, 499, 498, 497, 495, 380, |
| 91030 | /* 1520 */ 356, 460, 256, 250, 345, 447, 306, 5, 570, 550, |
| 91031 | /* 1530 */ 299, 211, 370, 401, 550, 508, 502, 501, 490, 527, |
| 91032 | /* 1540 */ 525, 483, 238, |
| 91033 | }; |
| 91034 | static const YYCODETYPE yy_lookahead[] = { |
| 91035 | /* 0 */ 19, 222, 223, 224, 225, 24, 1, 26, 77, 78, |
| 91036 | /* 10 */ 79, 80, 15, 82, 83, 84, 85, 86, 87, 88, |
| 91037 | /* 20 */ 89, 90, 91, 92, 113, 22, 26, 27, 117, 26, |
| @@ -91178,22 +92368,22 @@ | |
| 91178 | /* 1430 */ 174, 175, 150, 178, 165, 176, 22, 174, 175, 230, |
| 91179 | /* 1440 */ 92, 230, 184, 174, 175, 150, 176, 165, 105, 106, |
| 91180 | /* 1450 */ 107, 150, 176, 176, 111, 156, 174, 175, 179, 116, |
| 91181 | /* 1460 */ 165, 18, 157, 156, 238, 157, 165, 156, 45, 174, |
| 91182 | /* 1470 */ 175, 157, 157, 135, 239, 174, 175, 156, 189, 157, |
| 91183 | /* 1480 */ 68, 189, 139, 219, 22, 199, 157, 192, 18, 192, |
| 91184 | /* 1490 */ 192, 192, 199, 189, 219, 157, 243, 40, 243, 157, |
| 91185 | /* 1500 */ 157, 246, 38, 153, 196, 198, 166, 233, 233, 228, |
| 91186 | /* 1510 */ 177, 177, 209, 177, 182, 177, 166, 177, 166, 178, |
| 91187 | /* 1520 */ 242, 199, 242, 209, 209, 199, 148, 196, 166, 208, |
| 91188 | /* 1530 */ 195, 236, 237, 191, 208, 183, 183, 183, 186, 174, |
| 91189 | /* 1540 */ 174, 186, 92, |
| 91190 | }; |
| 91191 | #define YY_SHIFT_USE_DFLT (-90) |
| 91192 | #define YY_SHIFT_COUNT (418) |
| 91193 | #define YY_SHIFT_MIN (-89) |
| 91194 | #define YY_SHIFT_MAX (1470) |
| 91195 | static const short yy_shift_ofst[] = { |
| 91196 | /* 0 */ 993, 1114, 1343, 1114, 1213, 1213, 90, 90, 0, -19, |
| 91197 | /* 10 */ 1213, 1213, 1213, 1213, 1213, 352, 517, 721, 1091, 1213, |
| 91198 | /* 20 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, |
| 91199 | /* 30 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, |
| @@ -91204,11 +92394,11 @@ | |
| 91204 | /* 80 */ 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, |
| 91205 | /* 90 */ 795, 795, 795, 795, 795, 795, 869, 795, 943, 1017, |
| 91206 | /* 100 */ 1017, -69, -69, -69, -69, -1, -1, 58, 138, -44, |
| 91207 | /* 110 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91208 | /* 120 */ 517, 517, 517, 517, 517, 517, 202, 579, 517, 517, |
| 91209 | /* 130 */ 517, 517, 517, 382, 885, 1450, -90, -90, -90, 1293, |
| 91210 | /* 140 */ 73, 272, 272, 309, 311, 297, 282, 216, 602, 538, |
| 91211 | /* 150 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91212 | /* 160 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91213 | /* 170 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91214 | /* 180 */ 517, 517, 505, 231, 231, 231, 706, 64, 1177, 1177, |
| @@ -91215,12 +92405,12 @@ | |
| 91215 | /* 190 */ 1177, -90, -90, -90, 136, 168, 168, 12, 496, 496, |
| 91216 | /* 200 */ 496, 506, 423, 512, 370, 349, 335, 149, 149, 149, |
| 91217 | /* 210 */ 149, 604, 516, 149, 149, 508, 3, 299, 677, 871, |
| 91218 | /* 220 */ 613, 613, 879, 871, 879, 144, 382, 226, 382, 226, |
| 91219 | /* 230 */ 564, 226, 613, 226, 226, 404, 625, 625, 382, 426, |
| 91220 | /* 240 */ -89, 801, 1464, 1244, 1244, 1457, 1457, 1244, 1462, 1412, |
| 91221 | /* 250 */ 1188, 1470, 1470, 1470, 1470, 1244, 1188, 1462, 1412, 1412, |
| 91222 | /* 260 */ 1244, 1443, 1338, 1423, 1244, 1244, 1443, 1244, 1443, 1244, |
| 91223 | /* 270 */ 1443, 1414, 1306, 1306, 1306, 1365, 1348, 1348, 1414, 1306, |
| 91224 | /* 280 */ 1317, 1306, 1365, 1306, 1306, 1267, 1268, 1267, 1268, 1267, |
| 91225 | /* 290 */ 1268, 1244, 1244, 1216, 1214, 1215, 1192, 1173, 1188, 1177, |
| 91226 | /* 300 */ 1260, 1253, 1253, 1248, 1248, 1248, 1248, -90, -90, -90, |
| @@ -91237,11 +92427,11 @@ | |
| 91237 | /* 410 */ 152, 123, 68, -20, -42, 57, 39, -3, 5, |
| 91238 | }; |
| 91239 | #define YY_REDUCE_USE_DFLT (-222) |
| 91240 | #define YY_REDUCE_COUNT (312) |
| 91241 | #define YY_REDUCE_MIN (-221) |
| 91242 | #define YY_REDUCE_MAX (1378) |
| 91243 | static const short yy_reduce_ofst[] = { |
| 91244 | /* 0 */ 310, 994, 1134, 221, 169, 157, 89, 18, 83, 301, |
| 91245 | /* 10 */ 377, 316, 312, 16, 295, 238, 249, 391, 1301, 1295, |
| 91246 | /* 20 */ 1282, 1269, 1263, 1256, 1251, 1240, 1234, 1228, 1221, 1208, |
| 91247 | /* 30 */ 1109, 1103, 1077, 1054, 1022, 1016, 911, 908, 890, 888, |
| @@ -91258,17 +92448,17 @@ | |
| 91258 | /* 140 */ 823, 738, 712, 892, 1199, 1185, 1176, 1171, 673, 673, |
| 91259 | /* 150 */ 1168, 1167, 1162, 1159, 1148, 1145, 1139, 1117, 1111, 1107, |
| 91260 | /* 160 */ 1084, 1066, 1049, 1011, 1010, 1006, 1002, 999, 998, 973, |
| 91261 | /* 170 */ 972, 970, 966, 964, 895, 894, 892, 833, 822, 762, |
| 91262 | /* 180 */ 761, 229, 811, 804, 803, 389, 688, 808, 807, 737, |
| 91263 | /* 190 */ 460, 464, 572, 584, 1355, 1366, 1365, 1352, 1354, 1353, |
| 91264 | /* 200 */ 1352, 1326, 1335, 1342, 1335, 1335, 1335, 1335, 1335, 1335, |
| 91265 | /* 210 */ 1335, 1295, 1295, 1335, 1335, 1321, 1362, 1331, 1378, 1326, |
| 91266 | /* 220 */ 1315, 1314, 1280, 1322, 1278, 1341, 1352, 1340, 1350, 1338, |
| 91267 | /* 230 */ 1332, 1336, 1303, 1334, 1333, 1281, 1275, 1274, 1340, 1307, |
| 91268 | /* 240 */ 1308, 1350, 1255, 1343, 1342, 1255, 1253, 1338, 1275, 1304, |
| 91269 | /* 250 */ 1293, 1299, 1298, 1297, 1295, 1329, 1286, 1264, 1292, 1289, |
| 91270 | /* 260 */ 1322, 1321, 1235, 1226, 1315, 1314, 1311, 1308, 1307, 1305, |
| 91271 | /* 270 */ 1299, 1279, 1277, 1276, 1270, 1258, 1211, 1209, 1250, 1259, |
| 91272 | /* 280 */ 1255, 1242, 1243, 1241, 1201, 1200, 1184, 1186, 1182, 1178, |
| 91273 | /* 290 */ 1165, 1206, 1204, 1113, 1135, 1095, 1124, 1105, 1102, 1096, |
| 91274 | /* 300 */ 1112, 1140, 1136, 1121, 1116, 1115, 1089, 985, 961, 987, |
| @@ -94758,10 +95948,11 @@ | |
| 94758 | sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc)); |
| 94759 | } |
| 94760 | assert( pzErrMsg!=0 ); |
| 94761 | if( pParse->zErrMsg ){ |
| 94762 | *pzErrMsg = pParse->zErrMsg; |
| 94763 | pParse->zErrMsg = 0; |
| 94764 | nErr++; |
| 94765 | } |
| 94766 | if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ |
| 94767 | sqlite3VdbeDelete(pParse->pVdbe); |
| @@ -95436,11 +96627,11 @@ | |
| 95436 | va_list ap; |
| 95437 | int rc = SQLITE_OK; |
| 95438 | |
| 95439 | /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while |
| 95440 | ** the SQLite library is in use. */ |
| 95441 | if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE; |
| 95442 | |
| 95443 | va_start(ap, op); |
| 95444 | switch( op ){ |
| 95445 | |
| 95446 | /* Mutex configuration options are only available in a threadsafe |
| @@ -95557,10 +96748,25 @@ | |
| 95557 | case SQLITE_CONFIG_LOOKASIDE: { |
| 95558 | sqlite3GlobalConfig.szLookaside = va_arg(ap, int); |
| 95559 | sqlite3GlobalConfig.nLookaside = va_arg(ap, int); |
| 95560 | break; |
| 95561 | } |
| 95562 | |
| 95563 | default: { |
| 95564 | rc = SQLITE_ERROR; |
| 95565 | break; |
| 95566 | } |
| @@ -95770,11 +96976,11 @@ | |
| 95770 | |
| 95771 | if( !db ){ |
| 95772 | return SQLITE_OK; |
| 95773 | } |
| 95774 | if( !sqlite3SafetyCheckSickOrOk(db) ){ |
| 95775 | return SQLITE_MISUSE; |
| 95776 | } |
| 95777 | sqlite3_mutex_enter(db->mutex); |
| 95778 | |
| 95779 | sqlite3ResetInternalSchema(db, 0); |
| 95780 | |
| @@ -96117,11 +97323,11 @@ | |
| 96117 | (xFunc && (xFinal || xStep)) || |
| 96118 | (!xFunc && (xFinal && !xStep)) || |
| 96119 | (!xFunc && (!xFinal && xStep)) || |
| 96120 | (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || |
| 96121 | (255<(nName = sqlite3Strlen30( zFunctionName))) ){ |
| 96122 | return SQLITE_MISUSE; |
| 96123 | } |
| 96124 | |
| 96125 | #ifndef SQLITE_OMIT_UTF16 |
| 96126 | /* If SQLITE_UTF16 is specified as the encoding type, transform this |
| 96127 | ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the |
| @@ -96448,11 +97654,11 @@ | |
| 96448 | const char *z; |
| 96449 | if( !db ){ |
| 96450 | return sqlite3ErrStr(SQLITE_NOMEM); |
| 96451 | } |
| 96452 | if( !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96453 | return sqlite3ErrStr(SQLITE_MISUSE); |
| 96454 | } |
| 96455 | sqlite3_mutex_enter(db->mutex); |
| 96456 | if( db->mallocFailed ){ |
| 96457 | z = sqlite3ErrStr(SQLITE_NOMEM); |
| 96458 | }else{ |
| @@ -96517,20 +97723,20 @@ | |
| 96517 | ** Return the most recent error code generated by an SQLite routine. If NULL is |
| 96518 | ** passed to this function, we assume a malloc() failed during sqlite3_open(). |
| 96519 | */ |
| 96520 | SQLITE_API int sqlite3_errcode(sqlite3 *db){ |
| 96521 | if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96522 | return SQLITE_MISUSE; |
| 96523 | } |
| 96524 | if( !db || db->mallocFailed ){ |
| 96525 | return SQLITE_NOMEM; |
| 96526 | } |
| 96527 | return db->errCode & db->errMask; |
| 96528 | } |
| 96529 | SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ |
| 96530 | if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96531 | return SQLITE_MISUSE; |
| 96532 | } |
| 96533 | if( !db || db->mallocFailed ){ |
| 96534 | return SQLITE_NOMEM; |
| 96535 | } |
| 96536 | return db->errCode; |
| @@ -96564,11 +97770,11 @@ | |
| 96564 | testcase( enc2==SQLITE_UTF16_ALIGNED ); |
| 96565 | if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){ |
| 96566 | enc2 = SQLITE_UTF16NATIVE; |
| 96567 | } |
| 96568 | if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){ |
| 96569 | return SQLITE_MISUSE; |
| 96570 | } |
| 96571 | |
| 96572 | /* Check if this call is removing or replacing an existing collation |
| 96573 | ** sequence. If so, and there are active VMs, return busy. If there |
| 96574 | ** are no active VMs, invalidate any pre-compiled statements. |
| @@ -97108,20 +98314,38 @@ | |
| 97108 | */ |
| 97109 | SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ |
| 97110 | return db->autoCommit; |
| 97111 | } |
| 97112 | |
| 97113 | #ifdef SQLITE_DEBUG |
| 97114 | /* |
| 97115 | ** The following routine is subtituted for constant SQLITE_CORRUPT in |
| 97116 | ** debugging builds. This provides a way to set a breakpoint for when |
| 97117 | ** corruption is first detected. |
| 97118 | */ |
| 97119 | SQLITE_PRIVATE int sqlite3Corrupt(void){ |
| 97120 | return SQLITE_CORRUPT; |
| 97121 | } |
| 97122 | #endif |
| 97123 | |
| 97124 | #ifndef SQLITE_OMIT_DEPRECATED |
| 97125 | /* |
| 97126 | ** This is a convenience routine that makes sure that all thread-specific |
| 97127 | ** data for this thread has been deallocated. |
| @@ -97161,11 +98385,10 @@ | |
| 97161 | int primarykey = 0; |
| 97162 | int autoinc = 0; |
| 97163 | |
| 97164 | /* Ensure the database schema has been loaded */ |
| 97165 | sqlite3_mutex_enter(db->mutex); |
| 97166 | (void)sqlite3SafetyOn(db); |
| 97167 | sqlite3BtreeEnterAll(db); |
| 97168 | rc = sqlite3Init(db, &zErrMsg); |
| 97169 | if( SQLITE_OK!=rc ){ |
| 97170 | goto error_out; |
| 97171 | } |
| @@ -97220,11 +98443,10 @@ | |
| 97220 | zCollSeq = "BINARY"; |
| 97221 | } |
| 97222 | |
| 97223 | error_out: |
| 97224 | sqlite3BtreeLeaveAll(db); |
| 97225 | (void)sqlite3SafetyOff(db); |
| 97226 | |
| 97227 | /* Whether the function call succeeded or failed, set the output parameters |
| 97228 | ** to whatever their local counterparts contain. If an error did occur, |
| 97229 | ** this has the effect of zeroing all output parameters. |
| 97230 | */ |
| @@ -97859,13 +99081,10 @@ | |
| 97859 | ** |
| 97860 | ** * The FTS3 module is being built into the core of |
| 97861 | ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). |
| 97862 | */ |
| 97863 | |
| 97864 | /* TODO(shess) Consider exporting this comment to an HTML file or the |
| 97865 | ** wiki. |
| 97866 | */ |
| 97867 | /* The full-text index is stored in a series of b+tree (-like) |
| 97868 | ** structures called segments which map terms to doclists. The |
| 97869 | ** structures are like b+trees in layout, but are constructed from the |
| 97870 | ** bottom up in optimal fashion and are not updatable. Since trees |
| 97871 | ** are built from the bottom up, things will be described from the |
| @@ -97884,45 +99103,68 @@ | |
| 97884 | ** 7 bits - A |
| 97885 | ** 14 bits - BA |
| 97886 | ** 21 bits - BBA |
| 97887 | ** and so on. |
| 97888 | ** |
| 97889 | ** This is identical to how sqlite encodes varints (see util.c). |
| 97890 | ** |
| 97891 | ** |
| 97892 | **** Document lists **** |
| 97893 | ** A doclist (document list) holds a docid-sorted list of hits for a |
| 97894 | ** given term. Doclists hold docids, and can optionally associate |
| 97895 | ** token positions and offsets with docids. |
| 97896 | ** |
| 97897 | ** A DL_POSITIONS_OFFSETS doclist is stored like this: |
| 97898 | ** |
| 97899 | ** array { |
| 97900 | ** varint docid; |
| 97901 | ** array { (position list for column 0) |
| 97902 | ** varint position; (delta from previous position plus POS_BASE) |
| 97903 | ** varint startOffset; (delta from previous startOffset) |
| 97904 | ** varint endOffset; (delta from startOffset) |
| 97905 | ** } |
| 97906 | ** array { |
| 97907 | ** varint POS_COLUMN; (marks start of position list for new column) |
| 97908 | ** varint column; (index of new column) |
| 97909 | ** array { |
| 97910 | ** varint position; (delta from previous position plus POS_BASE) |
| 97911 | ** varint startOffset;(delta from previous startOffset) |
| 97912 | ** varint endOffset; (delta from startOffset) |
| 97913 | ** } |
| 97914 | ** } |
| 97915 | ** varint POS_END; (marks end of positions for this document. |
| 97916 | ** } |
| 97917 | ** |
| 97918 | ** Here, array { X } means zero or more occurrences of X, adjacent in |
| 97919 | ** memory. A "position" is an index of a token in the token stream |
| 97920 | ** generated by the tokenizer, while an "offset" is a byte offset, |
| 97921 | ** both based at 0. Note that POS_END and POS_COLUMN occur in the |
| 97922 | ** same logical place as the position element, and act as sentinals |
| 97923 | ** ending a position list array. |
| 97924 | ** |
| 97925 | ** A DL_POSITIONS doclist omits the startOffset and endOffset |
| 97926 | ** information. A DL_DOCIDS doclist omits both the position and |
| 97927 | ** offset information, becoming an array of varint-encoded docids. |
| 97928 | ** |
| @@ -98492,11 +99734,11 @@ | |
| 98492 | sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ |
| 98493 | |
| 98494 | /* Precompiled statements used by the implementation. Each of these |
| 98495 | ** statements is run and reset within a single virtual table API call. |
| 98496 | */ |
| 98497 | sqlite3_stmt *aStmt[18]; |
| 98498 | |
| 98499 | /* Pointer to string containing the SQL: |
| 98500 | ** |
| 98501 | ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ? |
| 98502 | ** ORDER BY blockid" |
| @@ -98506,10 +99748,12 @@ | |
| 98506 | int nLeavesTotal; /* Total number of prepared leaves stmts */ |
| 98507 | int nLeavesAlloc; /* Allocated size of aLeavesStmt */ |
| 98508 | sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */ |
| 98509 | |
| 98510 | int nNodeSize; /* Soft limit for node size */ |
| 98511 | |
| 98512 | /* The following hash table is used to buffer pending index updates during |
| 98513 | ** transactions. Variable nPendingData estimates the memory size of the |
| 98514 | ** pending data, including hash table overhead, but not malloc overhead. |
| 98515 | ** When nPendingData exceeds nMaxPendingData, the buffer is flushed |
| @@ -98536,12 +99780,12 @@ | |
| 98536 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 98537 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 98538 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 98539 | char *aDoclist; /* List of docids for full-text queries */ |
| 98540 | int nDoclist; /* Size of buffer at aDoclist */ |
| 98541 | int isMatchinfoOk; /* True when aMatchinfo[] matches iPrevId */ |
| 98542 | u32 *aMatchinfo; |
| 98543 | }; |
| 98544 | |
| 98545 | /* |
| 98546 | ** The Fts3Cursor.eSearch member is always set to one of the following. |
| 98547 | ** Actualy, Fts3Cursor.eSearch can be greater than or equal to |
| @@ -98643,10 +99887,12 @@ | |
| 98643 | Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, |
| 98644 | int (*)(Fts3Table *, void *, char *, int, char *, int), void * |
| 98645 | ); |
| 98646 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); |
| 98647 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
| 98648 | |
| 98649 | /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ |
| 98650 | #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 |
| 98651 | #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 |
| 98652 | #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 |
| @@ -98667,10 +99913,11 @@ | |
| 98667 | SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); |
| 98668 | SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); |
| 98669 | |
| 98670 | SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int); |
| 98671 | SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *, Fts3Expr *); |
| 98672 | |
| 98673 | /* fts3_tokenizer.c */ |
| 98674 | SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); |
| 98675 | SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); |
| 98676 | SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, |
| @@ -98677,14 +99924,11 @@ | |
| 98677 | const char *, sqlite3_tokenizer **, const char **, char ** |
| 98678 | ); |
| 98679 | |
| 98680 | /* fts3_snippet.c */ |
| 98681 | SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); |
| 98682 | SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context*, Fts3Cursor*, |
| 98683 | const char *, const char *, const char * |
| 98684 | ); |
| 98685 | SQLITE_PRIVATE void sqlite3Fts3Snippet2(sqlite3_context *, Fts3Cursor *, const char *, |
| 98686 | const char *, const char *, int, int |
| 98687 | ); |
| 98688 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *); |
| 98689 | |
| 98690 | /* fts3_expr.c */ |
| @@ -98800,16 +100044,27 @@ | |
| 98800 | } |
| 98801 | z[iOut] = '\0'; |
| 98802 | } |
| 98803 | } |
| 98804 | |
| 98805 | static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){ |
| 98806 | sqlite3_int64 iVal; |
| 98807 | *pp += sqlite3Fts3GetVarint(*pp, &iVal); |
| 98808 | *pVal += iVal; |
| 98809 | } |
| 98810 | |
| 98811 | static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){ |
| 98812 | if( *pp>=pEnd ){ |
| 98813 | *pp = 0; |
| 98814 | }else{ |
| 98815 | fts3GetDeltaVarint(pp, pVal); |
| @@ -98839,35 +100094,52 @@ | |
| 98839 | p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
| 98840 | |
| 98841 | sqlite3_free(p); |
| 98842 | return SQLITE_OK; |
| 98843 | } |
| 98844 | |
| 98845 | /* |
| 98846 | ** The xDestroy() virtual table method. |
| 98847 | */ |
| 98848 | static int fts3DestroyMethod(sqlite3_vtab *pVtab){ |
| 98849 | int rc; /* Return code */ |
| 98850 | Fts3Table *p = (Fts3Table *)pVtab; |
| 98851 | |
| 98852 | /* Create a script to drop the underlying three storage tables. */ |
| 98853 | char *zSql = sqlite3_mprintf( |
| 98854 | "DROP TABLE IF EXISTS %Q.'%q_content';" |
| 98855 | "DROP TABLE IF EXISTS %Q.'%q_segments';" |
| 98856 | "DROP TABLE IF EXISTS %Q.'%q_segdir';", |
| 98857 | p->zDb, p->zName, p->zDb, p->zName, p->zDb, p->zName |
| 98858 | ); |
| 98859 | |
| 98860 | /* If malloc has failed, set rc to SQLITE_NOMEM. Otherwise, try to |
| 98861 | ** execute the SQL script created above. |
| 98862 | */ |
| 98863 | if( zSql ){ |
| 98864 | rc = sqlite3_exec(p->db, zSql, 0, 0, 0); |
| 98865 | sqlite3_free(zSql); |
| 98866 | }else{ |
| 98867 | rc = SQLITE_NOMEM; |
| 98868 | } |
| 98869 | |
| 98870 | /* If everything has worked, invoke fts3DisconnectMethod() to free the |
| 98871 | ** memory associated with the Fts3Table structure and return SQLITE_OK. |
| 98872 | ** Otherwise, return an SQLite error code. |
| 98873 | */ |
| @@ -98912,50 +100184,77 @@ | |
| 98912 | ** Create the backing store tables (%_content, %_segments and %_segdir) |
| 98913 | ** required by the FTS3 table passed as the only argument. This is done |
| 98914 | ** as part of the vtab xCreate() method. |
| 98915 | */ |
| 98916 | static int fts3CreateTables(Fts3Table *p){ |
| 98917 | int rc; /* Return code */ |
| 98918 | int i; /* Iterator variable */ |
| 98919 | char *zContentCols; /* Columns of %_content table */ |
| 98920 | char *zSql; /* SQL script to create required tables */ |
| 98921 | |
| 98922 | /* Create a list of user columns for the content table */ |
| 98923 | zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); |
| 98924 | for(i=0; zContentCols && i<p->nColumn; i++){ |
| 98925 | char *z = p->azColumn[i]; |
| 98926 | zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); |
| 98927 | } |
| 98928 | |
| 98929 | /* Create the whole SQL script */ |
| 98930 | zSql = sqlite3_mprintf( |
| 98931 | "CREATE TABLE %Q.'%q_content'(%s);" |
| 98932 | "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);" |
| 98933 | "CREATE TABLE %Q.'%q_segdir'(" |
| 98934 | "level INTEGER," |
| 98935 | "idx INTEGER," |
| 98936 | "start_block INTEGER," |
| 98937 | "leaves_end_block INTEGER," |
| 98938 | "end_block INTEGER," |
| 98939 | "root BLOB," |
| 98940 | "PRIMARY KEY(level, idx)" |
| 98941 | ");", |
| 98942 | p->zDb, p->zName, zContentCols, p->zDb, p->zName, p->zDb, p->zName |
| 98943 | ); |
| 98944 | |
| 98945 | /* Unless a malloc() failure has occurred, execute the SQL script to |
| 98946 | ** create the tables used to store data for this FTS3 virtual table. |
| 98947 | */ |
| 98948 | if( zContentCols==0 || zSql==0 ){ |
| 98949 | rc = SQLITE_NOMEM; |
| 98950 | }else{ |
| 98951 | rc = sqlite3_exec(p->db, zSql, 0, 0, 0); |
| 98952 | } |
| 98953 | |
| 98954 | sqlite3_free(zSql); |
| 98955 | sqlite3_free(zContentCols); |
| 98956 | return rc; |
| 98957 | } |
| 98958 | |
| 98959 | /* |
| 98960 | ** This function is the implementation of both the xConnect and xCreate |
| 98961 | ** methods of the FTS3 virtual table. |
| @@ -99070,13 +100369,19 @@ | |
| 99070 | |
| 99071 | /* If this is an xCreate call, create the underlying tables in the |
| 99072 | ** database. TODO: For xConnect(), it could verify that said tables exist. |
| 99073 | */ |
| 99074 | if( isCreate ){ |
| 99075 | rc = fts3CreateTables(p); |
| 99076 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 99077 | } |
| 99078 | |
| 99079 | rc = fts3DeclareVtab(p); |
| 99080 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 99081 | |
| 99082 | *ppVTab = &p->base; |
| @@ -99193,16 +100498,10 @@ | |
| 99193 | return SQLITE_NOMEM; |
| 99194 | } |
| 99195 | memset(pCsr, 0, sizeof(Fts3Cursor)); |
| 99196 | return SQLITE_OK; |
| 99197 | } |
| 99198 | |
| 99199 | /****************************************************************/ |
| 99200 | /****************************************************************/ |
| 99201 | /****************************************************************/ |
| 99202 | /****************************************************************/ |
| 99203 | |
| 99204 | |
| 99205 | /* |
| 99206 | ** Close the cursor. For additional information see the documentation |
| 99207 | ** on the xClose method of the virtual table interface. |
| 99208 | */ |
| @@ -99255,11 +100554,11 @@ | |
| 99255 | pCsr->isEof = 1; |
| 99256 | }else{ |
| 99257 | sqlite3_reset(pCsr->pStmt); |
| 99258 | fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId); |
| 99259 | pCsr->isRequireSeek = 1; |
| 99260 | pCsr->isMatchinfoOk = 1; |
| 99261 | } |
| 99262 | return rc; |
| 99263 | } |
| 99264 | |
| 99265 | |
| @@ -100120,10 +101419,78 @@ | |
| 100120 | }else{ |
| 100121 | sqlite3_free(pOut); |
| 100122 | } |
| 100123 | return rc; |
| 100124 | } |
| 100125 | |
| 100126 | /* |
| 100127 | ** Evaluate the full-text expression pExpr against fts3 table pTab. Store |
| 100128 | ** the resulting doclist in *paOut and *pnOut. |
| 100129 | */ |
| @@ -100165,13 +101532,10 @@ | |
| 100165 | switch( pExpr->eType ){ |
| 100166 | case FTSQUERY_NEAR: { |
| 100167 | Fts3Expr *pLeft; |
| 100168 | Fts3Expr *pRight; |
| 100169 | int mergetype = isReqPos ? MERGE_POS_NEAR : MERGE_NEAR; |
| 100170 | int nParam1; |
| 100171 | int nParam2; |
| 100172 | char *aBuffer; |
| 100173 | |
| 100174 | if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){ |
| 100175 | mergetype = MERGE_POS_NEAR; |
| 100176 | } |
| 100177 | pLeft = pExpr->pLeft; |
| @@ -100180,21 +101544,15 @@ | |
| 100180 | } |
| 100181 | pRight = pExpr->pRight; |
| 100182 | assert( pRight->eType==FTSQUERY_PHRASE ); |
| 100183 | assert( pLeft->eType==FTSQUERY_PHRASE ); |
| 100184 | |
| 100185 | nParam1 = pExpr->nNear+1; |
| 100186 | nParam2 = nParam1+pLeft->pPhrase->nToken+pRight->pPhrase->nToken-2; |
| 100187 | aBuffer = sqlite3_malloc(nLeft+nRight+1); |
| 100188 | rc = fts3DoclistMerge(mergetype, nParam1, nParam2, aBuffer, |
| 100189 | pnOut, aLeft, nLeft, aRight, nRight |
| 100190 | ); |
| 100191 | if( rc!=SQLITE_OK ){ |
| 100192 | sqlite3_free(aBuffer); |
| 100193 | }else{ |
| 100194 | *paOut = aBuffer; |
| 100195 | } |
| 100196 | sqlite3_free(aLeft); |
| 100197 | break; |
| 100198 | } |
| 100199 | |
| 100200 | case FTSQUERY_OR: { |
| @@ -100441,11 +101799,11 @@ | |
| 100441 | return evalFts3Expr(pTab, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1); |
| 100442 | } |
| 100443 | |
| 100444 | /* |
| 100445 | ** After ExprLoadDoclist() (see above) has been called, this function is |
| 100446 | ** used to iterate through the position lists that make up the doclist |
| 100447 | ** stored in pExpr->aDoclist. |
| 100448 | */ |
| 100449 | SQLITE_PRIVATE char *sqlite3Fts3FindPositions( |
| 100450 | Fts3Expr *pExpr, /* Access this expressions doclist */ |
| 100451 | sqlite3_int64 iDocid, /* Docid associated with requested pos-list */ |
| @@ -100476,11 +101834,11 @@ | |
| 100476 | fts3ColumnlistCopy(0, &pCsr); |
| 100477 | if( *pCsr==0x00 ) return 0; |
| 100478 | pCsr++; |
| 100479 | pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis); |
| 100480 | } |
| 100481 | if( iCol==iThis ) return pCsr; |
| 100482 | } |
| 100483 | return 0; |
| 100484 | } |
| 100485 | } |
| 100486 | } |
| @@ -100528,49 +101886,12 @@ | |
| 100528 | ){ |
| 100529 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 100530 | const char *zStart = "<b>"; |
| 100531 | const char *zEnd = "</b>"; |
| 100532 | const char *zEllipsis = "<b>...</b>"; |
| 100533 | |
| 100534 | /* There must be at least one argument passed to this function (otherwise |
| 100535 | ** the non-overloaded version would have been called instead of this one). |
| 100536 | */ |
| 100537 | assert( nVal>=1 ); |
| 100538 | |
| 100539 | if( nVal>4 ){ |
| 100540 | sqlite3_result_error(pContext, |
| 100541 | "wrong number of arguments to function snippet()", -1); |
| 100542 | return; |
| 100543 | } |
| 100544 | if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; |
| 100545 | |
| 100546 | switch( nVal ){ |
| 100547 | case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); |
| 100548 | case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); |
| 100549 | case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); |
| 100550 | } |
| 100551 | if( !zEllipsis || !zEnd || !zStart ){ |
| 100552 | sqlite3_result_error_nomem(pContext); |
| 100553 | }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ |
| 100554 | sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis); |
| 100555 | } |
| 100556 | } |
| 100557 | |
| 100558 | /* |
| 100559 | ** Implementation of the snippet2() function for FTS3 |
| 100560 | */ |
| 100561 | static void fts3Snippet2Func( |
| 100562 | sqlite3_context *pContext, /* SQLite function call context */ |
| 100563 | int nVal, /* Size of apVal[] array */ |
| 100564 | sqlite3_value **apVal /* Array of arguments */ |
| 100565 | ){ |
| 100566 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 100567 | const char *zStart = "<b>"; |
| 100568 | const char *zEnd = "</b>"; |
| 100569 | const char *zEllipsis = "<b>...</b>"; |
| 100570 | int iCol = -1; |
| 100571 | int nToken = 10; |
| 100572 | |
| 100573 | /* There must be at least one argument passed to this function (otherwise |
| 100574 | ** the non-overloaded version would have been called instead of this one). |
| 100575 | */ |
| 100576 | assert( nVal>=1 ); |
| @@ -100590,11 +101911,11 @@ | |
| 100590 | case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); |
| 100591 | } |
| 100592 | if( !zEllipsis || !zEnd || !zStart ){ |
| 100593 | sqlite3_result_error_nomem(pContext); |
| 100594 | }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ |
| 100595 | sqlite3Fts3Snippet2(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); |
| 100596 | } |
| 100597 | } |
| 100598 | |
| 100599 | /* |
| 100600 | ** Implementation of the offsets() function for FTS3 |
| @@ -100691,11 +102012,10 @@ | |
| 100691 | struct Overloaded { |
| 100692 | const char *zName; |
| 100693 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**); |
| 100694 | } aOverload[] = { |
| 100695 | { "snippet", fts3SnippetFunc }, |
| 100696 | { "snippet2", fts3Snippet2Func }, |
| 100697 | { "offsets", fts3OffsetsFunc }, |
| 100698 | { "optimize", fts3OptimizeFunc }, |
| 100699 | { "matchinfo", fts3MatchinfoFunc }, |
| 100700 | }; |
| 100701 | int i; /* Iterator variable */ |
| @@ -100720,26 +102040,39 @@ | |
| 100720 | */ |
| 100721 | static int fts3RenameMethod( |
| 100722 | sqlite3_vtab *pVtab, /* Virtual table handle */ |
| 100723 | const char *zName /* New name of table */ |
| 100724 | ){ |
| 100725 | Fts3Table *p = (Fts3Table *)pVtab; |
| 100726 | int rc = SQLITE_NOMEM; /* Return Code */ |
| 100727 | char *zSql; /* SQL script to run to rename tables */ |
| 100728 | |
| 100729 | zSql = sqlite3_mprintf( |
| 100730 | "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';" |
| 100731 | "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';" |
| 100732 | "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';" |
| 100733 | , p->zDb, p->zName, zName |
| 100734 | , p->zDb, p->zName, zName |
| 100735 | , p->zDb, p->zName, zName |
| 100736 | ); |
| 100737 | if( zSql ){ |
| 100738 | rc = sqlite3_exec(p->db, zSql, 0, 0, 0); |
| 100739 | sqlite3_free(zSql); |
| 100740 | } |
| 100741 | return rc; |
| 100742 | } |
| 100743 | |
| 100744 | static const sqlite3_module fts3Module = { |
| 100745 | /* iVersion */ 0, |
| @@ -100841,18 +102174,23 @@ | |
| 100841 | ** module with sqlite. |
| 100842 | */ |
| 100843 | if( SQLITE_OK==rc |
| 100844 | && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) |
| 100845 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) |
| 100846 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet2", -1)) |
| 100847 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) |
| 100848 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", -1)) |
| 100849 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) |
| 100850 | ){ |
| 100851 | return sqlite3_create_module_v2( |
| 100852 | db, "fts3", &fts3Module, (void *)pHash, hashDestroy |
| 100853 | ); |
| 100854 | } |
| 100855 | |
| 100856 | /* An error has occurred. Delete the hash table and return the error code. */ |
| 100857 | assert( rc!=SQLITE_OK ); |
| 100858 | if( pHash ){ |
| @@ -102778,13 +104116,15 @@ | |
| 102778 | } |
| 102779 | |
| 102780 | if( c->iOffset>iStartOffset ){ |
| 102781 | int n = c->iOffset-iStartOffset; |
| 102782 | if( n>c->nAllocated ){ |
| 102783 | c->nAllocated = n+20; |
| 102784 | c->zToken = sqlite3_realloc(c->zToken, c->nAllocated); |
| 102785 | if( c->zToken==NULL ) return SQLITE_NOMEM; |
| 102786 | } |
| 102787 | porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); |
| 102788 | *pzToken = c->zToken; |
| 102789 | *piStartOffset = iStartOffset; |
| 102790 | *piEndOffset = c->iOffset; |
| @@ -103491,13 +104831,15 @@ | |
| 103491 | } |
| 103492 | |
| 103493 | if( c->iOffset>iStartOffset ){ |
| 103494 | int i, n = c->iOffset-iStartOffset; |
| 103495 | if( n>c->nTokenAllocated ){ |
| 103496 | c->nTokenAllocated = n+20; |
| 103497 | c->pToken = sqlite3_realloc(c->pToken, c->nTokenAllocated); |
| 103498 | if( c->pToken==NULL ) return SQLITE_NOMEM; |
| 103499 | } |
| 103500 | for(i=0; i<n; i++){ |
| 103501 | /* TODO(shess) This needs expansion to handle UTF-8 |
| 103502 | ** case-insensitivity. |
| 103503 | */ |
| @@ -103677,23 +105019,30 @@ | |
| 103677 | #define SQL_DELETE_CONTENT 0 |
| 103678 | #define SQL_IS_EMPTY 1 |
| 103679 | #define SQL_DELETE_ALL_CONTENT 2 |
| 103680 | #define SQL_DELETE_ALL_SEGMENTS 3 |
| 103681 | #define SQL_DELETE_ALL_SEGDIR 4 |
| 103682 | #define SQL_SELECT_CONTENT_BY_ROWID 5 |
| 103683 | #define SQL_NEXT_SEGMENT_INDEX 6 |
| 103684 | #define SQL_INSERT_SEGMENTS 7 |
| 103685 | #define SQL_NEXT_SEGMENTS_ID 8 |
| 103686 | #define SQL_INSERT_SEGDIR 9 |
| 103687 | #define SQL_SELECT_LEVEL 10 |
| 103688 | #define SQL_SELECT_ALL_LEVEL 11 |
| 103689 | #define SQL_SELECT_LEVEL_COUNT 12 |
| 103690 | #define SQL_SELECT_SEGDIR_COUNT_MAX 13 |
| 103691 | #define SQL_DELETE_SEGDIR_BY_LEVEL 14 |
| 103692 | #define SQL_DELETE_SEGMENTS_RANGE 15 |
| 103693 | #define SQL_CONTENT_INSERT 16 |
| 103694 | #define SQL_GET_BLOCK 17 |
| 103695 | |
| 103696 | /* |
| 103697 | ** This function is used to obtain an SQLite prepared statement handle |
| 103698 | ** for the statement identified by the second argument. If successful, |
| 103699 | ** *pp is set to the requested statement handle and SQLITE_OK returned. |
| @@ -103714,29 +105063,36 @@ | |
| 103714 | /* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?", |
| 103715 | /* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)", |
| 103716 | /* 2 */ "DELETE FROM %Q.'%q_content'", |
| 103717 | /* 3 */ "DELETE FROM %Q.'%q_segments'", |
| 103718 | /* 4 */ "DELETE FROM %Q.'%q_segdir'", |
| 103719 | /* 5 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?", |
| 103720 | /* 6 */ "SELECT coalesce(max(idx)+1, 0) FROM %Q.'%q_segdir' WHERE level=?", |
| 103721 | /* 7 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", |
| 103722 | /* 8 */ "SELECT coalesce(max(blockid)+1, 1) FROM %Q.'%q_segments'", |
| 103723 | /* 9 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", |
| 103724 | |
| 103725 | /* Return segments in order from oldest to newest.*/ |
| 103726 | /* 10 */ "SELECT idx, start_block, leaves_end_block, end_block, root " |
| 103727 | "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC", |
| 103728 | /* 11 */ "SELECT idx, start_block, leaves_end_block, end_block, root " |
| 103729 | "FROM %Q.'%q_segdir' ORDER BY level DESC, idx ASC", |
| 103730 | |
| 103731 | /* 12 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", |
| 103732 | /* 13 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'", |
| 103733 | |
| 103734 | /* 14 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?", |
| 103735 | /* 15 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?", |
| 103736 | /* 16 */ "INSERT INTO %Q.'%q_content' VALUES(%z)", |
| 103737 | /* 17 */ "SELECT block FROM %Q.'%q_segments' WHERE blockid = ?", |
| 103738 | }; |
| 103739 | int rc = SQLITE_OK; |
| 103740 | sqlite3_stmt *pStmt; |
| 103741 | |
| 103742 | assert( SizeofArray(azSql)==SizeofArray(p->aStmt) ); |
| @@ -103789,18 +105145,25 @@ | |
| 103789 | ** is executed. |
| 103790 | ** |
| 103791 | ** Returns SQLITE_OK if the statement is successfully executed, or an |
| 103792 | ** SQLite error code otherwise. |
| 103793 | */ |
| 103794 | static int fts3SqlExec(Fts3Table *p, int eStmt, sqlite3_value **apVal){ |
| 103795 | sqlite3_stmt *pStmt; |
| 103796 | int rc = fts3SqlStmt(p, eStmt, &pStmt, apVal); |
| 103797 | if( rc==SQLITE_OK ){ |
| 103798 | sqlite3_step(pStmt); |
| 103799 | rc = sqlite3_reset(pStmt); |
| 103800 | } |
| 103801 | return rc; |
| 103802 | } |
| 103803 | |
| 103804 | |
| 103805 | /* |
| 103806 | ** Read a single block from the %_segments table. If the specified block |
| @@ -103976,15 +105339,21 @@ | |
| 103976 | ** pending-terms hash-table. The docid used is that currently stored in |
| 103977 | ** p->iPrevDocid, and the column is specified by argument iCol. |
| 103978 | ** |
| 103979 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. |
| 103980 | */ |
| 103981 | static int fts3PendingTermsAdd(Fts3Table *p, const char *zText, int iCol){ |
| 103982 | int rc; |
| 103983 | int iStart; |
| 103984 | int iEnd; |
| 103985 | int iPos; |
| 103986 | |
| 103987 | char const *zToken; |
| 103988 | int nToken; |
| 103989 | |
| 103990 | sqlite3_tokenizer *pTokenizer = p->pTokenizer; |
| @@ -104004,10 +105373,12 @@ | |
| 104004 | xNext = pModule->xNext; |
| 104005 | while( SQLITE_OK==rc |
| 104006 | && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) |
| 104007 | ){ |
| 104008 | PendingList *pList; |
| 104009 | |
| 104010 | /* Positions cannot be negative; we use -1 as a terminator internally. |
| 104011 | ** Tokens must have a non-zero length. |
| 104012 | */ |
| 104013 | if( iPos<0 || !zToken || nToken<=0 ){ |
| @@ -104033,10 +105404,11 @@ | |
| 104033 | p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem)); |
| 104034 | } |
| 104035 | } |
| 104036 | |
| 104037 | pModule->xClose(pCsr); |
| 104038 | return (rc==SQLITE_DONE ? SQLITE_OK : rc); |
| 104039 | } |
| 104040 | |
| 104041 | /* |
| 104042 | ** Calling this function indicates that subsequent calls to |
| @@ -104073,16 +105445,16 @@ | |
| 104073 | ** pendingTerms hash table. |
| 104074 | ** |
| 104075 | ** Argument apVal is the same as the similarly named argument passed to |
| 104076 | ** fts3InsertData(). Parameter iDocid is the docid of the new row. |
| 104077 | */ |
| 104078 | static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal){ |
| 104079 | int i; /* Iterator variable */ |
| 104080 | for(i=2; i<p->nColumn+2; i++){ |
| 104081 | const char *zText = (const char *)sqlite3_value_text(apVal[i]); |
| 104082 | if( zText ){ |
| 104083 | int rc = fts3PendingTermsAdd(p, zText, i-2); |
| 104084 | if( rc!=SQLITE_OK ){ |
| 104085 | return rc; |
| 104086 | } |
| 104087 | } |
| 104088 | } |
| @@ -104159,53 +105531,60 @@ | |
| 104159 | /* |
| 104160 | ** Remove all data from the FTS3 table. Clear the hash table containing |
| 104161 | ** pending terms. |
| 104162 | */ |
| 104163 | static int fts3DeleteAll(Fts3Table *p){ |
| 104164 | int rc; /* Return code */ |
| 104165 | |
| 104166 | /* Discard the contents of the pending-terms hash table. */ |
| 104167 | sqlite3Fts3PendingTermsClear(p); |
| 104168 | |
| 104169 | /* Delete everything from the %_content, %_segments and %_segdir tables. */ |
| 104170 | rc = fts3SqlExec(p, SQL_DELETE_ALL_CONTENT, 0); |
| 104171 | if( rc==SQLITE_OK ){ |
| 104172 | rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGMENTS, 0); |
| 104173 | } |
| 104174 | if( rc==SQLITE_OK ){ |
| 104175 | rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGDIR, 0); |
| 104176 | } |
| 104177 | return rc; |
| 104178 | } |
| 104179 | |
| 104180 | /* |
| 104181 | ** The first element in the apVal[] array is assumed to contain the docid |
| 104182 | ** (an integer) of a row about to be deleted. Remove all terms from the |
| 104183 | ** full-text index. |
| 104184 | */ |
| 104185 | static int fts3DeleteTerms(Fts3Table *p, sqlite3_value **apVal){ |
| 104186 | int rc; |
| 104187 | sqlite3_stmt *pSelect; |
| 104188 | |
| 104189 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, apVal); |
| 104190 | if( rc==SQLITE_OK ){ |
| 104191 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 104192 | int i; |
| 104193 | for(i=1; i<=p->nColumn; i++){ |
| 104194 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 104195 | rc = fts3PendingTermsAdd(p, zText, -1); |
| 104196 | if( rc!=SQLITE_OK ){ |
| 104197 | sqlite3_reset(pSelect); |
| 104198 | return rc; |
| 104199 | } |
| 104200 | } |
| 104201 | } |
| 104202 | rc = sqlite3_reset(pSelect); |
| 104203 | }else{ |
| 104204 | sqlite3_reset(pSelect); |
| 104205 | } |
| 104206 | return rc; |
| 104207 | } |
| 104208 | |
| 104209 | /* |
| 104210 | ** Forward declaration to account for the circular dependency between |
| 104211 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| @@ -105321,11 +106700,11 @@ | |
| 105321 | sqlite3_bind_int(pDelete, 1, iLevel); |
| 105322 | sqlite3_step(pDelete); |
| 105323 | rc = sqlite3_reset(pDelete); |
| 105324 | } |
| 105325 | }else{ |
| 105326 | rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGDIR, 0); |
| 105327 | } |
| 105328 | |
| 105329 | return rc; |
| 105330 | } |
| 105331 | |
| @@ -105748,10 +107127,215 @@ | |
| 105748 | if( rc==SQLITE_OK ){ |
| 105749 | sqlite3Fts3PendingTermsClear(p); |
| 105750 | } |
| 105751 | return rc; |
| 105752 | } |
| 105753 | |
| 105754 | /* |
| 105755 | ** Handle a 'special' INSERT of the form: |
| 105756 | ** |
| 105757 | ** "INSERT INTO tbl(tbl) VALUES(<expr>)" |
| @@ -105800,11 +107384,20 @@ | |
| 105800 | ){ |
| 105801 | Fts3Table *p = (Fts3Table *)pVtab; |
| 105802 | int rc = SQLITE_OK; /* Return Code */ |
| 105803 | int isRemove = 0; /* True for an UPDATE or DELETE */ |
| 105804 | sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */ |
| 105805 | |
| 105806 | |
| 105807 | /* If this is a DELETE or UPDATE operation, remove the old record. */ |
| 105808 | if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 105809 | int isEmpty; |
| 105810 | rc = fts3IsEmpty(p, apVal, &isEmpty); |
| @@ -105817,19 +107410,20 @@ | |
| 105817 | rc = fts3DeleteAll(p); |
| 105818 | }else{ |
| 105819 | isRemove = 1; |
| 105820 | iRemove = sqlite3_value_int64(apVal[0]); |
| 105821 | rc = fts3PendingTermsDocid(p, iRemove); |
| 105822 | if( rc==SQLITE_OK ){ |
| 105823 | rc = fts3DeleteTerms(p, apVal); |
| 105824 | if( rc==SQLITE_OK ){ |
| 105825 | rc = fts3SqlExec(p, SQL_DELETE_CONTENT, apVal); |
| 105826 | } |
| 105827 | } |
| 105828 | } |
| 105829 | } |
| 105830 | }else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){ |
| 105831 | return fts3SpecialInsert(p, apVal[p->nColumn+2]); |
| 105832 | } |
| 105833 | |
| 105834 | /* If this is an INSERT or UPDATE operation, insert the new record. */ |
| 105835 | if( nArg>1 && rc==SQLITE_OK ){ |
| @@ -105836,14 +107430,23 @@ | |
| 105836 | rc = fts3InsertData(p, apVal, pRowid); |
| 105837 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){ |
| 105838 | rc = fts3PendingTermsDocid(p, *pRowid); |
| 105839 | } |
| 105840 | if( rc==SQLITE_OK ){ |
| 105841 | rc = fts3InsertTerms(p, apVal); |
| 105842 | } |
| 105843 | } |
| 105844 | |
| 105845 | return rc; |
| 105846 | } |
| 105847 | |
| 105848 | /* |
| 105849 | ** Flush any data in the pending-terms hash table to disk. If successful, |
| @@ -105886,736 +107489,131 @@ | |
| 105886 | */ |
| 105887 | |
| 105888 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 105889 | |
| 105890 | |
| 105891 | typedef struct Snippet Snippet; |
| 105892 | |
| 105893 | /* |
| 105894 | ** An instance of the following structure keeps track of generated |
| 105895 | ** matching-word offset information and snippets. |
| 105896 | */ |
| 105897 | struct Snippet { |
| 105898 | int nMatch; /* Total number of matches */ |
| 105899 | int nAlloc; /* Space allocated for aMatch[] */ |
| 105900 | struct snippetMatch { /* One entry for each matching term */ |
| 105901 | char snStatus; /* Status flag for use while constructing snippets */ |
| 105902 | short int nByte; /* Number of bytes in the term */ |
| 105903 | short int iCol; /* The column that contains the match */ |
| 105904 | short int iTerm; /* The index in Query.pTerms[] of the matching term */ |
| 105905 | int iToken; /* The index of the matching document token */ |
| 105906 | int iStart; /* The offset to the first character of the term */ |
| 105907 | } *aMatch; /* Points to space obtained from malloc */ |
| 105908 | char *zOffset; /* Text rendering of aMatch[] */ |
| 105909 | int nOffset; /* strlen(zOffset) */ |
| 105910 | char *zSnippet; /* Snippet text */ |
| 105911 | int nSnippet; /* strlen(zSnippet) */ |
| 105912 | }; |
| 105913 | |
| 105914 | |
| 105915 | /* It is not safe to call isspace(), tolower(), or isalnum() on |
| 105916 | ** hi-bit-set characters. This is the same solution used in the |
| 105917 | ** tokenizer. |
| 105918 | */ |
| 105919 | static int fts3snippetIsspace(char c){ |
| 105920 | return (c&0x80)==0 ? isspace(c) : 0; |
| 105921 | } |
| 105922 | |
| 105923 | |
| 105924 | /* |
| 105925 | ** A StringBuffer object holds a zero-terminated string that grows |
| 105926 | ** arbitrarily by appending. Space to hold the string is obtained |
| 105927 | ** from sqlite3_malloc(). After any memory allocation failure, |
| 105928 | ** StringBuffer.z is set to NULL and no further allocation is attempted. |
| 105929 | */ |
| 105930 | typedef struct StringBuffer { |
| 105931 | char *z; /* Text of the string. Space from malloc. */ |
| 105932 | int nUsed; /* Number bytes of z[] used, not counting \000 terminator */ |
| 105933 | int nAlloc; /* Bytes allocated for z[] */ |
| 105934 | } StringBuffer; |
| 105935 | |
| 105936 | |
| 105937 | /* |
| 105938 | ** Initialize a new StringBuffer. |
| 105939 | */ |
| 105940 | static void fts3SnippetSbInit(StringBuffer *p){ |
| 105941 | p->nAlloc = 100; |
| 105942 | p->nUsed = 0; |
| 105943 | p->z = sqlite3_malloc( p->nAlloc ); |
| 105944 | } |
| 105945 | |
| 105946 | /* |
| 105947 | ** Append text to the string buffer. |
| 105948 | */ |
| 105949 | static void fts3SnippetAppend(StringBuffer *p, const char *zNew, int nNew){ |
| 105950 | if( p->z==0 ) return; |
| 105951 | if( nNew<0 ) nNew = (int)strlen(zNew); |
| 105952 | if( p->nUsed + nNew >= p->nAlloc ){ |
| 105953 | int nAlloc; |
| 105954 | char *zNew; |
| 105955 | |
| 105956 | nAlloc = p->nUsed + nNew + p->nAlloc; |
| 105957 | zNew = sqlite3_realloc(p->z, nAlloc); |
| 105958 | if( zNew==0 ){ |
| 105959 | sqlite3_free(p->z); |
| 105960 | p->z = 0; |
| 105961 | return; |
| 105962 | } |
| 105963 | p->z = zNew; |
| 105964 | p->nAlloc = nAlloc; |
| 105965 | } |
| 105966 | memcpy(&p->z[p->nUsed], zNew, nNew); |
| 105967 | p->nUsed += nNew; |
| 105968 | p->z[p->nUsed] = 0; |
| 105969 | } |
| 105970 | |
| 105971 | /* If the StringBuffer ends in something other than white space, add a |
| 105972 | ** single space character to the end. |
| 105973 | */ |
| 105974 | static void fts3SnippetAppendWhiteSpace(StringBuffer *p){ |
| 105975 | if( p->z && p->nUsed && !fts3snippetIsspace(p->z[p->nUsed-1]) ){ |
| 105976 | fts3SnippetAppend(p, " ", 1); |
| 105977 | } |
| 105978 | } |
| 105979 | |
| 105980 | /* Remove white space from the end of the StringBuffer */ |
| 105981 | static void fts3SnippetTrimWhiteSpace(StringBuffer *p){ |
| 105982 | if( p->z ){ |
| 105983 | while( p->nUsed && fts3snippetIsspace(p->z[p->nUsed-1]) ){ |
| 105984 | p->nUsed--; |
| 105985 | } |
| 105986 | p->z[p->nUsed] = 0; |
| 105987 | } |
| 105988 | } |
| 105989 | |
| 105990 | /* |
| 105991 | ** Release all memory associated with the Snippet structure passed as |
| 105992 | ** an argument. |
| 105993 | */ |
| 105994 | static void fts3SnippetFree(Snippet *p){ |
| 105995 | if( p ){ |
| 105996 | sqlite3_free(p->aMatch); |
| 105997 | sqlite3_free(p->zOffset); |
| 105998 | sqlite3_free(p->zSnippet); |
| 105999 | sqlite3_free(p); |
| 106000 | } |
| 106001 | } |
| 106002 | |
| 106003 | /* |
| 106004 | ** Append a single entry to the p->aMatch[] log. |
| 106005 | */ |
| 106006 | static int snippetAppendMatch( |
| 106007 | Snippet *p, /* Append the entry to this snippet */ |
| 106008 | int iCol, int iTerm, /* The column and query term */ |
| 106009 | int iToken, /* Matching token in document */ |
| 106010 | int iStart, int nByte /* Offset and size of the match */ |
| 106011 | ){ |
| 106012 | int i; |
| 106013 | struct snippetMatch *pMatch; |
| 106014 | if( p->nMatch+1>=p->nAlloc ){ |
| 106015 | struct snippetMatch *pNew; |
| 106016 | p->nAlloc = p->nAlloc*2 + 10; |
| 106017 | pNew = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); |
| 106018 | if( pNew==0 ){ |
| 106019 | p->aMatch = 0; |
| 106020 | p->nMatch = 0; |
| 106021 | p->nAlloc = 0; |
| 106022 | return SQLITE_NOMEM; |
| 106023 | } |
| 106024 | p->aMatch = pNew; |
| 106025 | } |
| 106026 | i = p->nMatch++; |
| 106027 | pMatch = &p->aMatch[i]; |
| 106028 | pMatch->iCol = (short)iCol; |
| 106029 | pMatch->iTerm = (short)iTerm; |
| 106030 | pMatch->iToken = iToken; |
| 106031 | pMatch->iStart = iStart; |
| 106032 | pMatch->nByte = (short)nByte; |
| 106033 | return SQLITE_OK; |
| 106034 | } |
| 106035 | |
| 106036 | /* |
| 106037 | ** Sizing information for the circular buffer used in snippetOffsetsOfColumn() |
| 106038 | */ |
| 106039 | #define FTS3_ROTOR_SZ (32) |
| 106040 | #define FTS3_ROTOR_MASK (FTS3_ROTOR_SZ-1) |
| 106041 | |
| 106042 | /* |
| 106043 | ** Function to iterate through the tokens of a compiled expression. |
| 106044 | ** |
| 106045 | ** Except, skip all tokens on the right-hand side of a NOT operator. |
| 106046 | ** This function is used to find tokens as part of snippet and offset |
| 106047 | ** generation and we do nt want snippets and offsets to report matches |
| 106048 | ** for tokens on the RHS of a NOT. |
| 106049 | */ |
| 106050 | static int fts3NextExprToken(Fts3Expr **ppExpr, int *piToken){ |
| 106051 | Fts3Expr *p = *ppExpr; |
| 106052 | int iToken = *piToken; |
| 106053 | if( iToken<0 ){ |
| 106054 | /* In this case the expression p is the root of an expression tree. |
| 106055 | ** Move to the first token in the expression tree. |
| 106056 | */ |
| 106057 | while( p->pLeft ){ |
| 106058 | p = p->pLeft; |
| 106059 | } |
| 106060 | iToken = 0; |
| 106061 | }else{ |
| 106062 | assert(p && p->eType==FTSQUERY_PHRASE ); |
| 106063 | if( iToken<(p->pPhrase->nToken-1) ){ |
| 106064 | iToken++; |
| 106065 | }else{ |
| 106066 | iToken = 0; |
| 106067 | while( p->pParent && p->pParent->pLeft!=p ){ |
| 106068 | assert( p->pParent->pRight==p ); |
| 106069 | p = p->pParent; |
| 106070 | } |
| 106071 | p = p->pParent; |
| 106072 | if( p ){ |
| 106073 | assert( p->pRight!=0 ); |
| 106074 | p = p->pRight; |
| 106075 | while( p->pLeft ){ |
| 106076 | p = p->pLeft; |
| 106077 | } |
| 106078 | } |
| 106079 | } |
| 106080 | } |
| 106081 | |
| 106082 | *ppExpr = p; |
| 106083 | *piToken = iToken; |
| 106084 | return p?1:0; |
| 106085 | } |
| 106086 | |
| 106087 | /* |
| 106088 | ** Return TRUE if the expression node pExpr is located beneath the |
| 106089 | ** RHS of a NOT operator. |
| 106090 | */ |
| 106091 | static int fts3ExprBeneathNot(Fts3Expr *p){ |
| 106092 | Fts3Expr *pParent; |
| 106093 | while( p ){ |
| 106094 | pParent = p->pParent; |
| 106095 | if( pParent && pParent->eType==FTSQUERY_NOT && pParent->pRight==p ){ |
| 106096 | return 1; |
| 106097 | } |
| 106098 | p = pParent; |
| 106099 | } |
| 106100 | return 0; |
| 106101 | } |
| 106102 | |
| 106103 | /* |
| 106104 | ** Add entries to pSnippet->aMatch[] for every match that occurs against |
| 106105 | ** document zDoc[0..nDoc-1] which is stored in column iColumn. |
| 106106 | */ |
| 106107 | static int snippetOffsetsOfColumn( |
| 106108 | Fts3Cursor *pCur, /* The fulltest search cursor */ |
| 106109 | Snippet *pSnippet, /* The Snippet object to be filled in */ |
| 106110 | int iColumn, /* Index of fulltext table column */ |
| 106111 | const char *zDoc, /* Text of the fulltext table column */ |
| 106112 | int nDoc /* Length of zDoc in bytes */ |
| 106113 | ){ |
| 106114 | const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */ |
| 106115 | sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */ |
| 106116 | sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */ |
| 106117 | Fts3Table *pVtab; /* The full text index */ |
| 106118 | int nColumn; /* Number of columns in the index */ |
| 106119 | int i, j; /* Loop counters */ |
| 106120 | int rc; /* Return code */ |
| 106121 | unsigned int match, prevMatch; /* Phrase search bitmasks */ |
| 106122 | const char *zToken; /* Next token from the tokenizer */ |
| 106123 | int nToken; /* Size of zToken */ |
| 106124 | int iBegin, iEnd, iPos; /* Offsets of beginning and end */ |
| 106125 | |
| 106126 | /* The following variables keep a circular buffer of the last |
| 106127 | ** few tokens */ |
| 106128 | unsigned int iRotor = 0; /* Index of current token */ |
| 106129 | int iRotorBegin[FTS3_ROTOR_SZ]; /* Beginning offset of token */ |
| 106130 | int iRotorLen[FTS3_ROTOR_SZ]; /* Length of token */ |
| 106131 | |
| 106132 | pVtab = (Fts3Table *)pCur->base.pVtab; |
| 106133 | nColumn = pVtab->nColumn; |
| 106134 | pTokenizer = pVtab->pTokenizer; |
| 106135 | pTModule = pTokenizer->pModule; |
| 106136 | rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor); |
| 106137 | if( rc ) return rc; |
| 106138 | pTCursor->pTokenizer = pTokenizer; |
| 106139 | |
| 106140 | prevMatch = 0; |
| 106141 | while( (rc = pTModule->xNext(pTCursor, &zToken, &nToken, |
| 106142 | &iBegin, &iEnd, &iPos))==SQLITE_OK ){ |
| 106143 | Fts3Expr *pIter = pCur->pExpr; |
| 106144 | int iIter = -1; |
| 106145 | iRotorBegin[iRotor&FTS3_ROTOR_MASK] = iBegin; |
| 106146 | iRotorLen[iRotor&FTS3_ROTOR_MASK] = iEnd-iBegin; |
| 106147 | match = 0; |
| 106148 | for(i=0; i<(FTS3_ROTOR_SZ-1) && fts3NextExprToken(&pIter, &iIter); i++){ |
| 106149 | int nPhrase; /* Number of tokens in current phrase */ |
| 106150 | struct PhraseToken *pToken; /* Current token */ |
| 106151 | int iCol; /* Column index */ |
| 106152 | |
| 106153 | if( fts3ExprBeneathNot(pIter) ) continue; |
| 106154 | nPhrase = pIter->pPhrase->nToken; |
| 106155 | pToken = &pIter->pPhrase->aToken[iIter]; |
| 106156 | iCol = pIter->pPhrase->iColumn; |
| 106157 | if( iCol>=0 && iCol<nColumn && iCol!=iColumn ) continue; |
| 106158 | if( pToken->n>nToken ) continue; |
| 106159 | if( !pToken->isPrefix && pToken->n<nToken ) continue; |
| 106160 | assert( pToken->n<=nToken ); |
| 106161 | if( memcmp(pToken->z, zToken, pToken->n) ) continue; |
| 106162 | if( iIter>0 && (prevMatch & (1<<i))==0 ) continue; |
| 106163 | match |= 1<<i; |
| 106164 | if( i==(FTS3_ROTOR_SZ-2) || nPhrase==iIter+1 ){ |
| 106165 | for(j=nPhrase-1; j>=0; j--){ |
| 106166 | int k = (iRotor-j) & FTS3_ROTOR_MASK; |
| 106167 | rc = snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j, |
| 106168 | iRotorBegin[k], iRotorLen[k]); |
| 106169 | if( rc ) goto end_offsets_of_column; |
| 106170 | } |
| 106171 | } |
| 106172 | } |
| 106173 | prevMatch = match<<1; |
| 106174 | iRotor++; |
| 106175 | } |
| 106176 | end_offsets_of_column: |
| 106177 | pTModule->xClose(pTCursor); |
| 106178 | return rc==SQLITE_DONE ? SQLITE_OK : rc; |
| 106179 | } |
| 106180 | |
| 106181 | /* |
| 106182 | ** Remove entries from the pSnippet structure to account for the NEAR |
| 106183 | ** operator. When this is called, pSnippet contains the list of token |
| 106184 | ** offsets produced by treating all NEAR operators as AND operators. |
| 106185 | ** This function removes any entries that should not be present after |
| 106186 | ** accounting for the NEAR restriction. For example, if the queried |
| 106187 | ** document is: |
| 106188 | ** |
| 106189 | ** "A B C D E A" |
| 106190 | ** |
| 106191 | ** and the query is: |
| 106192 | ** |
| 106193 | ** A NEAR/0 E |
| 106194 | ** |
| 106195 | ** then when this function is called the Snippet contains token offsets |
| 106196 | ** 0, 4 and 5. This function removes the "0" entry (because the first A |
| 106197 | ** is not near enough to an E). |
| 106198 | ** |
| 106199 | ** When this function is called, the value pointed to by parameter piLeft is |
| 106200 | ** the integer id of the left-most token in the expression tree headed by |
| 106201 | ** pExpr. This function increments *piLeft by the total number of tokens |
| 106202 | ** in the expression tree headed by pExpr. |
| 106203 | ** |
| 106204 | ** Return 1 if any trimming occurs. Return 0 if no trimming is required. |
| 106205 | */ |
| 106206 | static int trimSnippetOffsets( |
| 106207 | Fts3Expr *pExpr, /* The search expression */ |
| 106208 | Snippet *pSnippet, /* The set of snippet offsets to be trimmed */ |
| 106209 | int *piLeft /* Index of left-most token in pExpr */ |
| 106210 | ){ |
| 106211 | if( pExpr ){ |
| 106212 | if( trimSnippetOffsets(pExpr->pLeft, pSnippet, piLeft) ){ |
| 106213 | return 1; |
| 106214 | } |
| 106215 | |
| 106216 | switch( pExpr->eType ){ |
| 106217 | case FTSQUERY_PHRASE: |
| 106218 | *piLeft += pExpr->pPhrase->nToken; |
| 106219 | break; |
| 106220 | case FTSQUERY_NEAR: { |
| 106221 | /* The right-hand-side of a NEAR operator is always a phrase. The |
| 106222 | ** left-hand-side is either a phrase or an expression tree that is |
| 106223 | ** itself headed by a NEAR operator. The following initializations |
| 106224 | ** set local variable iLeft to the token number of the left-most |
| 106225 | ** token in the right-hand phrase, and iRight to the right most |
| 106226 | ** token in the same phrase. For example, if we had: |
| 106227 | ** |
| 106228 | ** <col> MATCH '"abc def" NEAR/2 "ghi jkl"' |
| 106229 | ** |
| 106230 | ** then iLeft will be set to 2 (token number of ghi) and nToken will |
| 106231 | ** be set to 4. |
| 106232 | */ |
| 106233 | Fts3Expr *pLeft = pExpr->pLeft; |
| 106234 | Fts3Expr *pRight = pExpr->pRight; |
| 106235 | int iLeft = *piLeft; |
| 106236 | int nNear = pExpr->nNear; |
| 106237 | int nToken = pRight->pPhrase->nToken; |
| 106238 | int jj, ii; |
| 106239 | if( pLeft->eType==FTSQUERY_NEAR ){ |
| 106240 | pLeft = pLeft->pRight; |
| 106241 | } |
| 106242 | assert( pRight->eType==FTSQUERY_PHRASE ); |
| 106243 | assert( pLeft->eType==FTSQUERY_PHRASE ); |
| 106244 | nToken += pLeft->pPhrase->nToken; |
| 106245 | |
| 106246 | for(ii=0; ii<pSnippet->nMatch; ii++){ |
| 106247 | struct snippetMatch *p = &pSnippet->aMatch[ii]; |
| 106248 | if( p->iTerm==iLeft ){ |
| 106249 | int isOk = 0; |
| 106250 | /* Snippet ii is an occurence of query term iLeft in the document. |
| 106251 | ** It occurs at position (p->iToken) of the document. We now |
| 106252 | ** search for an instance of token (iLeft-1) somewhere in the |
| 106253 | ** range (p->iToken - nNear)...(p->iToken + nNear + nToken) within |
| 106254 | ** the set of snippetMatch structures. If one is found, proceed. |
| 106255 | ** If one cannot be found, then remove snippets ii..(ii+N-1) |
| 106256 | ** from the matching snippets, where N is the number of tokens |
| 106257 | ** in phrase pRight->pPhrase. |
| 106258 | */ |
| 106259 | for(jj=0; isOk==0 && jj<pSnippet->nMatch; jj++){ |
| 106260 | struct snippetMatch *p2 = &pSnippet->aMatch[jj]; |
| 106261 | if( p2->iTerm==(iLeft-1) ){ |
| 106262 | if( p2->iToken>=(p->iToken-nNear-1) |
| 106263 | && p2->iToken<(p->iToken+nNear+nToken) |
| 106264 | ){ |
| 106265 | isOk = 1; |
| 106266 | } |
| 106267 | } |
| 106268 | } |
| 106269 | if( !isOk ){ |
| 106270 | int kk; |
| 106271 | for(kk=0; kk<pRight->pPhrase->nToken; kk++){ |
| 106272 | pSnippet->aMatch[kk+ii].iTerm = -2; |
| 106273 | } |
| 106274 | return 1; |
| 106275 | } |
| 106276 | } |
| 106277 | if( p->iTerm==(iLeft-1) ){ |
| 106278 | int isOk = 0; |
| 106279 | for(jj=0; isOk==0 && jj<pSnippet->nMatch; jj++){ |
| 106280 | struct snippetMatch *p2 = &pSnippet->aMatch[jj]; |
| 106281 | if( p2->iTerm==iLeft ){ |
| 106282 | if( p2->iToken<=(p->iToken+nNear+1) |
| 106283 | && p2->iToken>(p->iToken-nNear-nToken) |
| 106284 | ){ |
| 106285 | isOk = 1; |
| 106286 | } |
| 106287 | } |
| 106288 | } |
| 106289 | if( !isOk ){ |
| 106290 | int kk; |
| 106291 | for(kk=0; kk<pLeft->pPhrase->nToken; kk++){ |
| 106292 | pSnippet->aMatch[ii-kk].iTerm = -2; |
| 106293 | } |
| 106294 | return 1; |
| 106295 | } |
| 106296 | } |
| 106297 | } |
| 106298 | break; |
| 106299 | } |
| 106300 | } |
| 106301 | |
| 106302 | if( trimSnippetOffsets(pExpr->pRight, pSnippet, piLeft) ){ |
| 106303 | return 1; |
| 106304 | } |
| 106305 | } |
| 106306 | return 0; |
| 106307 | } |
| 106308 | |
| 106309 | /* |
| 106310 | ** Compute all offsets for the current row of the query. |
| 106311 | ** If the offsets have already been computed, this routine is a no-op. |
| 106312 | */ |
| 106313 | static int snippetAllOffsets(Fts3Cursor *pCsr, Snippet **ppSnippet){ |
| 106314 | Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; /* The FTS3 virtual table */ |
| 106315 | int nColumn; /* Number of columns. Docid does count */ |
| 106316 | int iColumn; /* Index of of a column */ |
| 106317 | int i; /* Loop index */ |
| 106318 | int iFirst; /* First column to search */ |
| 106319 | int iLast; /* Last coumn to search */ |
| 106320 | int iTerm = 0; |
| 106321 | Snippet *pSnippet; |
| 106322 | int rc = SQLITE_OK; |
| 106323 | |
| 106324 | if( pCsr->pExpr==0 ){ |
| 106325 | return SQLITE_OK; |
| 106326 | } |
| 106327 | |
| 106328 | pSnippet = (Snippet *)sqlite3_malloc(sizeof(Snippet)); |
| 106329 | *ppSnippet = pSnippet; |
| 106330 | if( !pSnippet ){ |
| 106331 | return SQLITE_NOMEM; |
| 106332 | } |
| 106333 | memset(pSnippet, 0, sizeof(Snippet)); |
| 106334 | |
| 106335 | nColumn = p->nColumn; |
| 106336 | iColumn = (pCsr->eSearch - 2); |
| 106337 | if( iColumn<0 || iColumn>=nColumn ){ |
| 106338 | /* Look for matches over all columns of the full-text index */ |
| 106339 | iFirst = 0; |
| 106340 | iLast = nColumn-1; |
| 106341 | }else{ |
| 106342 | /* Look for matches in the iColumn-th column of the index only */ |
| 106343 | iFirst = iColumn; |
| 106344 | iLast = iColumn; |
| 106345 | } |
| 106346 | for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){ |
| 106347 | const char *zDoc; |
| 106348 | int nDoc; |
| 106349 | zDoc = (const char*)sqlite3_column_text(pCsr->pStmt, i+1); |
| 106350 | nDoc = sqlite3_column_bytes(pCsr->pStmt, i+1); |
| 106351 | if( zDoc==0 && sqlite3_column_type(pCsr->pStmt, i+1)!=SQLITE_NULL ){ |
| 106352 | rc = SQLITE_NOMEM; |
| 106353 | }else{ |
| 106354 | rc = snippetOffsetsOfColumn(pCsr, pSnippet, i, zDoc, nDoc); |
| 106355 | } |
| 106356 | } |
| 106357 | |
| 106358 | while( trimSnippetOffsets(pCsr->pExpr, pSnippet, &iTerm) ){ |
| 106359 | iTerm = 0; |
| 106360 | } |
| 106361 | |
| 106362 | return rc; |
| 106363 | } |
| 106364 | |
| 106365 | /* |
| 106366 | ** Convert the information in the aMatch[] array of the snippet |
| 106367 | ** into the string zOffset[0..nOffset-1]. This string is used as |
| 106368 | ** the return of the SQL offsets() function. |
| 106369 | */ |
| 106370 | static void snippetOffsetText(Snippet *p){ |
| 106371 | int i; |
| 106372 | int cnt = 0; |
| 106373 | StringBuffer sb; |
| 106374 | char zBuf[200]; |
| 106375 | if( p->zOffset ) return; |
| 106376 | fts3SnippetSbInit(&sb); |
| 106377 | for(i=0; i<p->nMatch; i++){ |
| 106378 | struct snippetMatch *pMatch = &p->aMatch[i]; |
| 106379 | if( pMatch->iTerm>=0 ){ |
| 106380 | /* If snippetMatch.iTerm is less than 0, then the match was |
| 106381 | ** discarded as part of processing the NEAR operator (see the |
| 106382 | ** trimSnippetOffsetsForNear() function for details). Ignore |
| 106383 | ** it in this case |
| 106384 | */ |
| 106385 | zBuf[0] = ' '; |
| 106386 | sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d", |
| 106387 | pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte); |
| 106388 | fts3SnippetAppend(&sb, zBuf, -1); |
| 106389 | cnt++; |
| 106390 | } |
| 106391 | } |
| 106392 | p->zOffset = sb.z; |
| 106393 | p->nOffset = sb.z ? sb.nUsed : 0; |
| 106394 | } |
| 106395 | |
| 106396 | /* |
| 106397 | ** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set |
| 106398 | ** of matching words some of which might be in zDoc. zDoc is column |
| 106399 | ** number iCol. |
| 106400 | ** |
| 106401 | ** iBreak is suggested spot in zDoc where we could begin or end an |
| 106402 | ** excerpt. Return a value similar to iBreak but possibly adjusted |
| 106403 | ** to be a little left or right so that the break point is better. |
| 106404 | */ |
| 106405 | static int wordBoundary( |
| 106406 | int iBreak, /* The suggested break point */ |
| 106407 | const char *zDoc, /* Document text */ |
| 106408 | int nDoc, /* Number of bytes in zDoc[] */ |
| 106409 | struct snippetMatch *aMatch, /* Matching words */ |
| 106410 | int nMatch, /* Number of entries in aMatch[] */ |
| 106411 | int iCol /* The column number for zDoc[] */ |
| 106412 | ){ |
| 106413 | int i; |
| 106414 | if( iBreak<=10 ){ |
| 106415 | return 0; |
| 106416 | } |
| 106417 | if( iBreak>=nDoc-10 ){ |
| 106418 | return nDoc; |
| 106419 | } |
| 106420 | for(i=0; ALWAYS(i<nMatch) && aMatch[i].iCol<iCol; i++){} |
| 106421 | while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; } |
| 106422 | if( i<nMatch ){ |
| 106423 | if( aMatch[i].iStart<iBreak+10 ){ |
| 106424 | return aMatch[i].iStart; |
| 106425 | } |
| 106426 | if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){ |
| 106427 | return aMatch[i-1].iStart; |
| 106428 | } |
| 106429 | } |
| 106430 | for(i=1; i<=10; i++){ |
| 106431 | if( fts3snippetIsspace(zDoc[iBreak-i]) ){ |
| 106432 | return iBreak - i + 1; |
| 106433 | } |
| 106434 | if( fts3snippetIsspace(zDoc[iBreak+i]) ){ |
| 106435 | return iBreak + i + 1; |
| 106436 | } |
| 106437 | } |
| 106438 | return iBreak; |
| 106439 | } |
| 106440 | |
| 106441 | |
| 106442 | |
| 106443 | /* |
| 106444 | ** Allowed values for Snippet.aMatch[].snStatus |
| 106445 | */ |
| 106446 | #define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */ |
| 106447 | #define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */ |
| 106448 | |
| 106449 | /* |
| 106450 | ** Generate the text of a snippet. |
| 106451 | */ |
| 106452 | static void snippetText( |
| 106453 | Fts3Cursor *pCursor, /* The cursor we need the snippet for */ |
| 106454 | Snippet *pSnippet, |
| 106455 | const char *zStartMark, /* Markup to appear before each match */ |
| 106456 | const char *zEndMark, /* Markup to appear after each match */ |
| 106457 | const char *zEllipsis /* Ellipsis mark */ |
| 106458 | ){ |
| 106459 | int i, j; |
| 106460 | struct snippetMatch *aMatch; |
| 106461 | int nMatch; |
| 106462 | int nDesired; |
| 106463 | StringBuffer sb; |
| 106464 | int tailCol; |
| 106465 | int tailOffset; |
| 106466 | int iCol; |
| 106467 | int nDoc; |
| 106468 | const char *zDoc; |
| 106469 | int iStart, iEnd; |
| 106470 | int tailEllipsis = 0; |
| 106471 | int iMatch; |
| 106472 | |
| 106473 | |
| 106474 | sqlite3_free(pSnippet->zSnippet); |
| 106475 | pSnippet->zSnippet = 0; |
| 106476 | aMatch = pSnippet->aMatch; |
| 106477 | nMatch = pSnippet->nMatch; |
| 106478 | fts3SnippetSbInit(&sb); |
| 106479 | |
| 106480 | for(i=0; i<nMatch; i++){ |
| 106481 | aMatch[i].snStatus = SNIPPET_IGNORE; |
| 106482 | } |
| 106483 | nDesired = 0; |
| 106484 | for(i=0; i<FTS3_ROTOR_SZ; i++){ |
| 106485 | for(j=0; j<nMatch; j++){ |
| 106486 | if( aMatch[j].iTerm==i ){ |
| 106487 | aMatch[j].snStatus = SNIPPET_DESIRED; |
| 106488 | nDesired++; |
| 106489 | break; |
| 106490 | } |
| 106491 | } |
| 106492 | } |
| 106493 | |
| 106494 | iMatch = 0; |
| 106495 | tailCol = -1; |
| 106496 | tailOffset = 0; |
| 106497 | for(i=0; i<nMatch && nDesired>0; i++){ |
| 106498 | if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue; |
| 106499 | nDesired--; |
| 106500 | iCol = aMatch[i].iCol; |
| 106501 | zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1); |
| 106502 | nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1); |
| 106503 | iStart = aMatch[i].iStart - 40; |
| 106504 | iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol); |
| 106505 | if( iStart<=10 ){ |
| 106506 | iStart = 0; |
| 106507 | } |
| 106508 | if( iCol==tailCol && iStart<=tailOffset+20 ){ |
| 106509 | iStart = tailOffset; |
| 106510 | } |
| 106511 | if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){ |
| 106512 | fts3SnippetTrimWhiteSpace(&sb); |
| 106513 | fts3SnippetAppendWhiteSpace(&sb); |
| 106514 | fts3SnippetAppend(&sb, zEllipsis, -1); |
| 106515 | fts3SnippetAppendWhiteSpace(&sb); |
| 106516 | } |
| 106517 | iEnd = aMatch[i].iStart + aMatch[i].nByte + 40; |
| 106518 | iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol); |
| 106519 | if( iEnd>=nDoc-10 ){ |
| 106520 | iEnd = nDoc; |
| 106521 | tailEllipsis = 0; |
| 106522 | }else{ |
| 106523 | tailEllipsis = 1; |
| 106524 | } |
| 106525 | while( iMatch<nMatch && aMatch[iMatch].iCol<iCol ){ iMatch++; } |
| 106526 | while( iStart<iEnd ){ |
| 106527 | while( iMatch<nMatch && aMatch[iMatch].iStart<iStart |
| 106528 | && aMatch[iMatch].iCol<=iCol ){ |
| 106529 | iMatch++; |
| 106530 | } |
| 106531 | if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd |
| 106532 | && aMatch[iMatch].iCol==iCol ){ |
| 106533 | fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart); |
| 106534 | iStart = aMatch[iMatch].iStart; |
| 106535 | fts3SnippetAppend(&sb, zStartMark, -1); |
| 106536 | fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].nByte); |
| 106537 | fts3SnippetAppend(&sb, zEndMark, -1); |
| 106538 | iStart += aMatch[iMatch].nByte; |
| 106539 | for(j=iMatch+1; j<nMatch; j++){ |
| 106540 | if( aMatch[j].iTerm==aMatch[iMatch].iTerm |
| 106541 | && aMatch[j].snStatus==SNIPPET_DESIRED ){ |
| 106542 | nDesired--; |
| 106543 | aMatch[j].snStatus = SNIPPET_IGNORE; |
| 106544 | } |
| 106545 | } |
| 106546 | }else{ |
| 106547 | fts3SnippetAppend(&sb, &zDoc[iStart], iEnd - iStart); |
| 106548 | iStart = iEnd; |
| 106549 | } |
| 106550 | } |
| 106551 | tailCol = iCol; |
| 106552 | tailOffset = iEnd; |
| 106553 | } |
| 106554 | fts3SnippetTrimWhiteSpace(&sb); |
| 106555 | if( tailEllipsis ){ |
| 106556 | fts3SnippetAppendWhiteSpace(&sb); |
| 106557 | fts3SnippetAppend(&sb, zEllipsis, -1); |
| 106558 | } |
| 106559 | pSnippet->zSnippet = sb.z; |
| 106560 | pSnippet->nSnippet = sb.z ? sb.nUsed : 0; |
| 106561 | } |
| 106562 | |
| 106563 | SQLITE_PRIVATE void sqlite3Fts3Offsets( |
| 106564 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 106565 | Fts3Cursor *pCsr /* Cursor object */ |
| 106566 | ){ |
| 106567 | Snippet *p; /* Snippet structure */ |
| 106568 | int rc = snippetAllOffsets(pCsr, &p); |
| 106569 | if( rc==SQLITE_OK ){ |
| 106570 | snippetOffsetText(p); |
| 106571 | if( p->zOffset ){ |
| 106572 | sqlite3_result_text(pCtx, p->zOffset, p->nOffset, SQLITE_TRANSIENT); |
| 106573 | }else{ |
| 106574 | sqlite3_result_error_nomem(pCtx); |
| 106575 | } |
| 106576 | }else{ |
| 106577 | sqlite3_result_error_nomem(pCtx); |
| 106578 | } |
| 106579 | fts3SnippetFree(p); |
| 106580 | } |
| 106581 | |
| 106582 | SQLITE_PRIVATE void sqlite3Fts3Snippet( |
| 106583 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 106584 | Fts3Cursor *pCsr, /* Cursor object */ |
| 106585 | const char *zStart, /* Snippet start text - "<b>" */ |
| 106586 | const char *zEnd, /* Snippet end text - "</b>" */ |
| 106587 | const char *zEllipsis /* Snippet ellipsis text - "<b>...</b>" */ |
| 106588 | ){ |
| 106589 | Snippet *p; /* Snippet structure */ |
| 106590 | int rc = snippetAllOffsets(pCsr, &p); |
| 106591 | if( rc==SQLITE_OK ){ |
| 106592 | snippetText(pCsr, p, zStart, zEnd, zEllipsis); |
| 106593 | if( p->zSnippet ){ |
| 106594 | sqlite3_result_text(pCtx, p->zSnippet, p->nSnippet, SQLITE_TRANSIENT); |
| 106595 | }else{ |
| 106596 | sqlite3_result_error_nomem(pCtx); |
| 106597 | } |
| 106598 | }else{ |
| 106599 | sqlite3_result_error_nomem(pCtx); |
| 106600 | } |
| 106601 | fts3SnippetFree(p); |
| 106602 | } |
| 106603 | |
| 106604 | /************************************************************************* |
| 106605 | ** Below this point is the alternative, experimental snippet() implementation. |
| 106606 | */ |
| 106607 | |
| 106608 | #define SNIPPET_BUFFER_CHUNK 64 |
| 106609 | #define SNIPPET_BUFFER_SIZE SNIPPET_BUFFER_CHUNK*4 |
| 106610 | #define SNIPPET_BUFFER_MASK (SNIPPET_BUFFER_SIZE-1) |
| 106611 | |
| 106612 | static void fts3GetDeltaPosition(char **pp, int *piPos){ |
| 106613 | int iVal; |
| 106614 | *pp += sqlite3Fts3GetVarint32(*pp, &iVal); |
| 106615 | *piPos += (iVal-2); |
| 106616 | } |
| 106617 | |
| 106618 | /* |
| 106619 | ** Iterate through all phrase nodes in an FTS3 query, except those that |
| 106620 | ** are part of a sub-tree that is the right-hand-side of a NOT operator. |
| 106621 | ** For each phrase node found, the supplied callback function is invoked. |
| @@ -106625,289 +107623,391 @@ | |
| 106625 | ** Otherwise, SQLITE_OK is returned after a callback has been made for |
| 106626 | ** all eligible phrase nodes. |
| 106627 | */ |
| 106628 | static int fts3ExprIterate( |
| 106629 | Fts3Expr *pExpr, /* Expression to iterate phrases of */ |
| 106630 | int (*x)(Fts3Expr *, void *), /* Callback function to invoke for phrases */ |
| 106631 | void *pCtx /* Second argument to pass to callback */ |
| 106632 | ){ |
| 106633 | int rc; |
| 106634 | int eType = pExpr->eType; |
| 106635 | if( eType==FTSQUERY_NOT ){ |
| 106636 | rc = SQLITE_OK; |
| 106637 | }else if( eType!=FTSQUERY_PHRASE ){ |
| 106638 | assert( pExpr->pLeft && pExpr->pRight ); |
| 106639 | rc = fts3ExprIterate(pExpr->pLeft, x, pCtx); |
| 106640 | if( rc==SQLITE_OK ){ |
| 106641 | rc = fts3ExprIterate(pExpr->pRight, x, pCtx); |
| 106642 | } |
| 106643 | }else{ |
| 106644 | rc = x(pExpr, pCtx); |
| 106645 | } |
| 106646 | return rc; |
| 106647 | } |
| 106648 | |
| 106649 | typedef struct LoadDoclistCtx LoadDoclistCtx; |
| 106650 | struct LoadDoclistCtx { |
| 106651 | Fts3Table *pTab; /* FTS3 Table */ |
| 106652 | int nPhrase; /* Number of phrases so far */ |
| 106653 | }; |
| 106654 | |
| 106655 | static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, void *ctx){ |
| 106656 | int rc = SQLITE_OK; |
| 106657 | LoadDoclistCtx *p = (LoadDoclistCtx *)ctx; |
| 106658 | p->nPhrase++; |
| 106659 | if( pExpr->isLoaded==0 ){ |
| 106660 | rc = sqlite3Fts3ExprLoadDoclist(p->pTab, pExpr); |
| 106661 | pExpr->isLoaded = 1; |
| 106662 | if( rc==SQLITE_OK && pExpr->aDoclist ){ |
| 106663 | pExpr->pCurrent = pExpr->aDoclist; |
| 106664 | pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent,&pExpr->iCurrent); |
| 106665 | } |
| 106666 | } |
| 106667 | return rc; |
| 106668 | } |
| 106669 | |
| 106670 | static int fts3ExprLoadDoclists(Fts3Cursor *pCsr, int *pnPhrase){ |
| 106671 | int rc; |
| 106672 | LoadDoclistCtx sCtx = {0, 0}; |
| 106673 | sCtx.pTab = (Fts3Table *)pCsr->base.pVtab; |
| 106674 | rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx); |
| 106675 | *pnPhrase = sCtx.nPhrase; |
| 106676 | return rc; |
| 106677 | } |
| 106678 | |
| 106679 | /* |
| 106680 | ** Each call to this function populates a chunk of a snippet-buffer |
| 106681 | ** SNIPPET_BUFFER_CHUNK bytes in size. |
| 106682 | ** |
| 106683 | ** Return true if the end of the data has been reached (and all subsequent |
| 106684 | ** calls to fts3LoadSnippetBuffer() with the same arguments will be no-ops), |
| 106685 | ** or false otherwise. |
| 106686 | */ |
| 106687 | static int fts3LoadSnippetBuffer( |
| 106688 | int iPos, /* Document token offset to load data for */ |
| 106689 | u8 *aBuffer, /* Circular snippet buffer to populate */ |
| 106690 | int nList, /* Number of position lists in appList */ |
| 106691 | char **apList, /* IN/OUT: nList position list pointers */ |
| 106692 | int *aiPrev /* IN/OUT: Previous positions read */ |
| 106693 | ){ |
| 106694 | int i; |
| 106695 | int nFin = 0; |
| 106696 | |
| 106697 | assert( (iPos&(SNIPPET_BUFFER_CHUNK-1))==0 ); |
| 106698 | |
| 106699 | memset(&aBuffer[iPos&SNIPPET_BUFFER_MASK], 0, SNIPPET_BUFFER_CHUNK); |
| 106700 | |
| 106701 | for(i=0; i<nList; i++){ |
| 106702 | int iPrev = aiPrev[i]; |
| 106703 | char *pList = apList[i]; |
| 106704 | |
| 106705 | if( !pList ){ |
| 106706 | nFin++; |
| 106707 | continue; |
| 106708 | } |
| 106709 | |
| 106710 | while( iPrev<(iPos+SNIPPET_BUFFER_CHUNK) ){ |
| 106711 | if( iPrev>=iPos ){ |
| 106712 | aBuffer[iPrev&SNIPPET_BUFFER_MASK] = i+1; |
| 106713 | } |
| 106714 | if( 0==((*pList)&0xFE) ){ |
| 106715 | nFin++; |
| 106716 | break; |
| 106717 | } |
| 106718 | fts3GetDeltaPosition(&pList, &iPrev); |
| 106719 | } |
| 106720 | |
| 106721 | aiPrev[i] = iPrev; |
| 106722 | apList[i] = pList; |
| 106723 | } |
| 106724 | |
| 106725 | return (nFin==nList); |
| 106726 | } |
| 106727 | |
| 106728 | typedef struct SnippetCtx SnippetCtx; |
| 106729 | struct SnippetCtx { |
| 106730 | Fts3Cursor *pCsr; |
| 106731 | int iCol; |
| 106732 | int iPhrase; |
| 106733 | int *aiPrev; |
| 106734 | int *anToken; |
| 106735 | char **apList; |
| 106736 | }; |
| 106737 | |
| 106738 | static int fts3SnippetFindPositions(Fts3Expr *pExpr, void *ctx){ |
| 106739 | SnippetCtx *p = (SnippetCtx *)ctx; |
| 106740 | int iPhrase = p->iPhrase++; |
| 106741 | char *pCsr; |
| 106742 | |
| 106743 | p->anToken[iPhrase] = pExpr->pPhrase->nToken; |
| 106744 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCsr->iPrevId, p->iCol); |
| 106745 | |
| 106746 | if( pCsr ){ |
| 106747 | int iVal; |
| 106748 | pCsr += sqlite3Fts3GetVarint32(pCsr, &iVal); |
| 106749 | p->apList[iPhrase] = pCsr; |
| 106750 | p->aiPrev[iPhrase] = iVal-2; |
| 106751 | } |
| 106752 | return SQLITE_OK; |
| 106753 | } |
| 106754 | |
| 106755 | static void fts3SnippetCnt( |
| 106756 | int iIdx, |
| 106757 | int nSnippet, |
| 106758 | int *anCnt, |
| 106759 | u8 *aBuffer, |
| 106760 | int *anToken, |
| 106761 | u64 *pHlmask |
| 106762 | ){ |
| 106763 | int iSub = (iIdx-1)&SNIPPET_BUFFER_MASK; |
| 106764 | int iAdd = (iIdx+nSnippet-1)&SNIPPET_BUFFER_MASK; |
| 106765 | int iSub2 = (iIdx+(nSnippet/3)-1)&SNIPPET_BUFFER_MASK; |
| 106766 | int iAdd2 = (iIdx+(nSnippet*2/3)-1)&SNIPPET_BUFFER_MASK; |
| 106767 | |
| 106768 | u64 h = *pHlmask; |
| 106769 | |
| 106770 | anCnt[ aBuffer[iSub] ]--; |
| 106771 | anCnt[ aBuffer[iSub2] ]--; |
| 106772 | anCnt[ aBuffer[iAdd] ]++; |
| 106773 | anCnt[ aBuffer[iAdd2] ]++; |
| 106774 | |
| 106775 | h = h >> 1; |
| 106776 | if( aBuffer[iAdd] ){ |
| 106777 | int j; |
| 106778 | for(j=anToken[aBuffer[iAdd]-1]; j>=1; j--){ |
| 106779 | h |= (u64)1 << (nSnippet-j); |
| 106780 | } |
| 106781 | } |
| 106782 | *pHlmask = h; |
| 106783 | } |
| 106784 | |
| 106785 | static int fts3SnippetScore(int n, int *anCnt){ |
| 106786 | int j; |
| 106787 | int iScore = 0; |
| 106788 | for(j=1; j<=n; j++){ |
| 106789 | int nCnt = anCnt[j]; |
| 106790 | iScore += nCnt + (nCnt ? 1000 : 0); |
| 106791 | } |
| 106792 | return iScore; |
| 106793 | } |
| 106794 | |
| 106795 | static int fts3BestSnippet( |
| 106796 | int nSnippet, /* Desired snippet length */ |
| 106797 | Fts3Cursor *pCsr, /* Cursor to create snippet for */ |
| 106798 | int iCol, /* Index of column to create snippet from */ |
| 106799 | int *piPos, /* OUT: Starting token for best snippet */ |
| 106800 | u64 *pHlmask /* OUT: Highlight mask for best snippet */ |
| 106801 | ){ |
| 106802 | int rc; /* Return Code */ |
| 106803 | u8 aBuffer[SNIPPET_BUFFER_SIZE];/* Circular snippet buffer */ |
| 106804 | int *aiPrev; /* Used by fts3LoadSnippetBuffer() */ |
| 106805 | int *anToken; /* Number of tokens in each phrase */ |
| 106806 | char **apList; /* Array of position lists */ |
| 106807 | int *anCnt; /* Running totals of phrase occurences */ |
| 106808 | int nList; |
| 106809 | |
| 106810 | int i; |
| 106811 | |
| 106812 | u64 hlmask = 0; /* Current mask of highlighted terms */ |
| 106813 | u64 besthlmask = 0; /* Mask of highlighted terms for iBestPos */ |
| 106814 | int iBestPos = 0; /* Starting position of 'best' snippet */ |
| 106815 | int iBestScore = 0; /* Score of best snippet higher->better */ |
| 106816 | SnippetCtx sCtx; |
| 106817 | |
| 106818 | /* Iterate through the phrases in the expression to count them. The same |
| 106819 | ** callback makes sure the doclists are loaded for each phrase. |
| 106820 | */ |
| 106821 | rc = fts3ExprLoadDoclists(pCsr, &nList); |
| 106822 | if( rc!=SQLITE_OK ){ |
| 106823 | return rc; |
| 106824 | } |
| 106825 | |
| 106826 | /* Now that it is known how many phrases there are, allocate and zero |
| 106827 | ** the required arrays using malloc(). |
| 106828 | */ |
| 106829 | apList = sqlite3_malloc( |
| 106830 | sizeof(u8*)*nList + /* apList */ |
| 106831 | sizeof(int)*(nList) + /* anToken */ |
| 106832 | sizeof(int)*nList + /* aiPrev */ |
| 106833 | sizeof(int)*(nList+1) /* anCnt */ |
| 106834 | ); |
| 106835 | if( !apList ){ |
| 106836 | return SQLITE_NOMEM; |
| 106837 | } |
| 106838 | memset(apList, 0, sizeof(u8*)*nList+sizeof(int)*nList+sizeof(int)*nList); |
| 106839 | anToken = (int *)&apList[nList]; |
| 106840 | aiPrev = &anToken[nList]; |
| 106841 | anCnt = &aiPrev[nList]; |
| 106842 | |
| 106843 | /* Initialize the contents of the aiPrev and aiList arrays. */ |
| 106844 | sCtx.pCsr = pCsr; |
| 106845 | sCtx.iCol = iCol; |
| 106846 | sCtx.apList = apList; |
| 106847 | sCtx.aiPrev = aiPrev; |
| 106848 | sCtx.anToken = anToken; |
| 106849 | sCtx.iPhrase = 0; |
| 106850 | (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sCtx); |
| 106851 | |
| 106852 | /* Load the first two chunks of data into the buffer. */ |
| 106853 | memset(aBuffer, 0, SNIPPET_BUFFER_SIZE); |
| 106854 | fts3LoadSnippetBuffer(0, aBuffer, nList, apList, aiPrev); |
| 106855 | fts3LoadSnippetBuffer(SNIPPET_BUFFER_CHUNK, aBuffer, nList, apList, aiPrev); |
| 106856 | |
| 106857 | /* Set the initial contents of the highlight-mask and anCnt[] array. */ |
| 106858 | for(i=1-nSnippet; i<=0; i++){ |
| 106859 | fts3SnippetCnt(i, nSnippet, anCnt, aBuffer, anToken, &hlmask); |
| 106860 | } |
| 106861 | iBestScore = fts3SnippetScore(nList, anCnt); |
| 106862 | besthlmask = hlmask; |
| 106863 | iBestPos = 0; |
| 106864 | |
| 106865 | for(i=1; 1; i++){ |
| 106866 | int iScore; |
| 106867 | |
| 106868 | if( 0==(i&(SNIPPET_BUFFER_CHUNK-1)) ){ |
| 106869 | int iLoad = i + SNIPPET_BUFFER_CHUNK; |
| 106870 | if( fts3LoadSnippetBuffer(iLoad, aBuffer, nList, apList, aiPrev) ) break; |
| 106871 | } |
| 106872 | |
| 106873 | /* Figure out how highly a snippet starting at token offset i scores |
| 106874 | ** according to fts3SnippetScore(). If it is higher than any previously |
| 106875 | ** considered position, save the current position, score and hlmask as |
| 106876 | ** the best snippet candidate found so far. |
| 106877 | */ |
| 106878 | fts3SnippetCnt(i, nSnippet, anCnt, aBuffer, anToken, &hlmask); |
| 106879 | iScore = fts3SnippetScore(nList, anCnt); |
| 106880 | if( iScore>iBestScore ){ |
| 106881 | iBestPos = i; |
| 106882 | iBestScore = iScore; |
| 106883 | besthlmask = hlmask; |
| 106884 | } |
| 106885 | } |
| 106886 | |
| 106887 | sqlite3_free(apList); |
| 106888 | *piPos = iBestPos; |
| 106889 | *pHlmask = besthlmask; |
| 106890 | return SQLITE_OK; |
| 106891 | } |
| 106892 | |
| 106893 | typedef struct StrBuffer StrBuffer; |
| 106894 | struct StrBuffer { |
| 106895 | char *z; |
| 106896 | int n; |
| 106897 | int nAlloc; |
| 106898 | }; |
| 106899 | |
| 106900 | static int fts3StringAppend( |
| 106901 | StrBuffer *pStr, |
| 106902 | const char *zAppend, |
| 106903 | int nAppend |
| 106904 | ){ |
| 106905 | if( nAppend<0 ){ |
| 106906 | nAppend = strlen(zAppend); |
| 106907 | } |
| 106908 | |
| 106909 | if( pStr->n+nAppend+1>=pStr->nAlloc ){ |
| 106910 | int nAlloc = pStr->nAlloc+nAppend+100; |
| 106911 | char *zNew = sqlite3_realloc(pStr->z, nAlloc); |
| 106912 | if( !zNew ){ |
| 106913 | return SQLITE_NOMEM; |
| @@ -106914,137 +108014,213 @@ | |
| 106914 | } |
| 106915 | pStr->z = zNew; |
| 106916 | pStr->nAlloc = nAlloc; |
| 106917 | } |
| 106918 | |
| 106919 | memcpy(&pStr->z[pStr->n], zAppend, nAppend); |
| 106920 | pStr->n += nAppend; |
| 106921 | pStr->z[pStr->n] = '\0'; |
| 106922 | |
| 106923 | return SQLITE_OK; |
| 106924 | } |
| 106925 | |
| 106926 | static int fts3SnippetText( |
| 106927 | Fts3Cursor *pCsr, /* FTS3 Cursor */ |
| 106928 | const char *zDoc, /* Document to extract snippet from */ |
| 106929 | int nDoc, /* Size of zDoc in bytes */ |
| 106930 | int nSnippet, /* Number of tokens in extracted snippet */ |
| 106931 | int iPos, /* Index of first document token in snippet */ |
| 106932 | u64 hlmask, /* Bitmask of terms to highlight in snippet */ |
| 106933 | const char *zOpen, /* String inserted before highlighted term */ |
| 106934 | const char *zClose, /* String inserted after highlighted term */ |
| 106935 | const char *zEllipsis, |
| 106936 | char **pzSnippet /* OUT: Snippet text */ |
| 106937 | ){ |
| 106938 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 106939 | int rc; /* Return code */ |
| 106940 | int iCurrent = 0; |
| 106941 | int iStart = 0; |
| 106942 | int iEnd; |
| 106943 | |
| 106944 | sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ |
| 106945 | sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ |
| 106946 | const char *ZDUMMY; /* Dummy arguments used with tokenizer */ |
| 106947 | int DUMMY1, DUMMY2, DUMMY3; /* Dummy arguments used with tokenizer */ |
| 106948 | |
| 106949 | StrBuffer res = {0, 0, 0}; /* Result string */ |
| 106950 | |
| 106951 | /* Open a token cursor on the document. Read all tokens up to and |
| 106952 | ** including token iPos (the first token of the snippet). Set variable |
| 106953 | ** iStart to the byte offset in zDoc of the start of token iPos. |
| 106954 | */ |
| 106955 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 106956 | rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 106957 | while( rc==SQLITE_OK && iCurrent<iPos ){ |
| 106958 | rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iStart, &DUMMY2, &iCurrent); |
| 106959 | } |
| 106960 | iEnd = iStart; |
| 106961 | |
| 106962 | if( rc==SQLITE_OK && iStart>0 ){ |
| 106963 | rc = fts3StringAppend(&res, zEllipsis, -1); |
| 106964 | } |
| 106965 | |
| 106966 | while( rc==SQLITE_OK ){ |
| 106967 | int iBegin; |
| 106968 | int iFin; |
| 106969 | rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent); |
| 106970 | |
| 106971 | if( rc==SQLITE_OK ){ |
| 106972 | if( iCurrent>=(iPos+nSnippet) ){ |
| 106973 | rc = SQLITE_DONE; |
| 106974 | }else{ |
| 106975 | iEnd = iFin; |
| 106976 | if( hlmask & ((u64)1 << (iCurrent-iPos)) ){ |
| 106977 | if( fts3StringAppend(&res, &zDoc[iStart], iBegin-iStart) |
| 106978 | || fts3StringAppend(&res, zOpen, -1) |
| 106979 | || fts3StringAppend(&res, &zDoc[iBegin], iEnd-iBegin) |
| 106980 | || fts3StringAppend(&res, zClose, -1) |
| 106981 | ){ |
| 106982 | rc = SQLITE_NOMEM; |
| 106983 | } |
| 106984 | iStart = iEnd; |
| 106985 | } |
| 106986 | } |
| 106987 | } |
| 106988 | } |
| 106989 | assert( rc!=SQLITE_OK ); |
| 106990 | if( rc==SQLITE_DONE ){ |
| 106991 | rc = fts3StringAppend(&res, &zDoc[iStart], iEnd-iStart); |
| 106992 | if( rc==SQLITE_OK ){ |
| 106993 | rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); |
| 106994 | if( rc==SQLITE_OK ){ |
| 106995 | rc = fts3StringAppend(&res, zEllipsis, -1); |
| 106996 | }else if( rc==SQLITE_DONE ){ |
| 106997 | rc = fts3StringAppend(&res, &zDoc[iEnd], -1); |
| 106998 | } |
| 106999 | } |
| 107000 | } |
| 107001 | |
| 107002 | pMod->xClose(pC); |
| 107003 | if( rc!=SQLITE_OK ){ |
| 107004 | sqlite3_free(res.z); |
| 107005 | }else{ |
| 107006 | *pzSnippet = res.z; |
| 107007 | } |
| 107008 | return rc; |
| 107009 | } |
| 107010 | |
| 107011 | |
| 107012 | /* |
| 107013 | ** An instance of this structure is used to collect the 'global' part of |
| 107014 | ** the matchinfo statistics. The 'global' part consists of the following: |
| 107015 | ** |
| 107016 | ** 1. The number of phrases in the query (nPhrase). |
| 107017 | ** |
| 107018 | ** 2. The number of columns in the FTS3 table (nCol). |
| 107019 | ** |
| 107020 | ** 3. A matrix of (nPhrase*nCol) integers containing the sum of the |
| 107021 | ** number of hits for each phrase in each column across all rows |
| 107022 | ** of the table. |
| 107023 | ** |
| 107024 | ** The total size of the global matchinfo array, assuming the number of |
| 107025 | ** columns is N and the number of phrases is P is: |
| 107026 | ** |
| 107027 | ** 2 + P*(N+1) |
| 107028 | ** |
| 107029 | ** The number of hits for the 3rd phrase in the second column is found |
| 107030 | ** using the expression: |
| 107031 | ** |
| 107032 | ** aGlobal[2 + P*(1+2) + 1] |
| 107033 | */ |
| 107034 | typedef struct MatchInfo MatchInfo; |
| 107035 | struct MatchInfo { |
| 107036 | Fts3Table *pTab; /* FTS3 Table */ |
| 107037 | Fts3Cursor *pCursor; /* FTS3 Cursor */ |
| 107038 | int iPhrase; /* Number of phrases so far */ |
| 107039 | int nCol; /* Number of columns in table */ |
| 107040 | u32 *aGlobal; /* Pre-allocated buffer */ |
| 107041 | }; |
| 107042 | |
| 107043 | /* |
| 107044 | ** This function is used to count the entries in a column-list (delta-encoded |
| 107045 | ** list of term offsets within a single column of a single row). |
| 107046 | */ |
| 107047 | static int fts3ColumnlistCount(char **ppCollist){ |
| 107048 | char *pEnd = *ppCollist; |
| 107049 | char c = 0; |
| 107050 | int nEntry = 0; |
| @@ -107057,158 +108233,445 @@ | |
| 107057 | |
| 107058 | *ppCollist = pEnd; |
| 107059 | return nEntry; |
| 107060 | } |
| 107061 | |
| 107062 | static void fts3LoadColumnlistCounts(char **pp, u32 *aOut){ |
| 107063 | char *pCsr = *pp; |
| 107064 | while( *pCsr ){ |
| 107065 | sqlite3_int64 iCol = 0; |
| 107066 | if( *pCsr==0x01 ){ |
| 107067 | pCsr++; |
| 107068 | pCsr += sqlite3Fts3GetVarint(pCsr, &iCol); |
| 107069 | } |
| 107070 | aOut[iCol] += fts3ColumnlistCount(&pCsr); |
| 107071 | } |
| 107072 | pCsr++; |
| 107073 | *pp = pCsr; |
| 107074 | } |
| 107075 | |
| 107076 | /* |
| 107077 | ** fts3ExprIterate() callback used to collect the "global" matchinfo stats |
| 107078 | ** for a single query. |
| 107079 | */ |
| 107080 | static int fts3ExprGlobalMatchinfoCb( |
| 107081 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 107082 | void *pCtx /* Pointer to MatchInfo structure */ |
| 107083 | ){ |
| 107084 | MatchInfo *p = (MatchInfo *)pCtx; |
| 107085 | char *pCsr; |
| 107086 | char *pEnd; |
| 107087 | const int iStart = 2 + p->nCol*p->iPhrase; |
| 107088 | |
| 107089 | assert( pExpr->isLoaded ); |
| 107090 | |
| 107091 | /* Fill in the global hit count matrix row for this phrase. */ |
| 107092 | pCsr = pExpr->aDoclist; |
| 107093 | pEnd = &pExpr->aDoclist[pExpr->nDoclist]; |
| 107094 | while( pCsr<pEnd ){ |
| 107095 | while( *pCsr++ & 0x80 ); |
| 107096 | fts3LoadColumnlistCounts(&pCsr, &p->aGlobal[iStart]); |
| 107097 | } |
| 107098 | |
| 107099 | p->iPhrase++; |
| 107100 | return SQLITE_OK; |
| 107101 | } |
| 107102 | |
| 107103 | static int fts3ExprLocalMatchinfoCb( |
| 107104 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 107105 | void *pCtx /* Pointer to MatchInfo structure */ |
| 107106 | ){ |
| 107107 | MatchInfo *p = (MatchInfo *)pCtx; |
| 107108 | int iPhrase = p->iPhrase++; |
| 107109 | |
| 107110 | if( pExpr->aDoclist ){ |
| 107111 | char *pCsr; |
| 107112 | int iOffset = 2 + p->nCol*(p->aGlobal[0]+iPhrase); |
| 107113 | |
| 107114 | memset(&p->aGlobal[iOffset], 0, p->nCol*sizeof(u32)); |
| 107115 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1); |
| 107116 | if( pCsr ) fts3LoadColumnlistCounts(&pCsr, &p->aGlobal[iOffset]); |
| 107117 | } |
| 107118 | |
| 107119 | return SQLITE_OK; |
| 107120 | } |
| 107121 | |
| 107122 | /* |
| 107123 | ** Populate pCsr->aMatchinfo[] with data for the current row. The 'matchinfo' |
| 107124 | ** data is an array of 32-bit unsigned integers (C type u32). |
| 107125 | */ |
| 107126 | static int fts3GetMatchinfo(Fts3Cursor *pCsr){ |
| 107127 | MatchInfo g; |
| 107128 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 107129 | if( pCsr->aMatchinfo==0 ){ |
| 107130 | int rc; |
| 107131 | int nPhrase; |
| 107132 | int nMatchinfo; |
| 107133 | |
| 107134 | g.pTab = pTab; |
| 107135 | g.nCol = pTab->nColumn; |
| 107136 | g.iPhrase = 0; |
| 107137 | rc = fts3ExprLoadDoclists(pCsr, &nPhrase); |
| 107138 | if( rc!=SQLITE_OK ){ |
| 107139 | return rc; |
| 107140 | } |
| 107141 | |
| 107142 | nMatchinfo = 2 + 2*g.nCol*nPhrase; |
| 107143 | |
| 107144 | g.iPhrase = 0; |
| 107145 | g.aGlobal = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo); |
| 107146 | if( !g.aGlobal ){ |
| 107147 | return SQLITE_NOMEM; |
| 107148 | } |
| 107149 | memset(g.aGlobal, 0, sizeof(u32)*nMatchinfo); |
| 107150 | |
| 107151 | g.aGlobal[0] = nPhrase; |
| 107152 | g.aGlobal[1] = g.nCol; |
| 107153 | (void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb, (void *)&g); |
| 107154 | |
| 107155 | pCsr->aMatchinfo = g.aGlobal; |
| 107156 | } |
| 107157 | |
| 107158 | g.pTab = pTab; |
| 107159 | g.pCursor = pCsr; |
| 107160 | g.nCol = pTab->nColumn; |
| 107161 | g.iPhrase = 0; |
| 107162 | g.aGlobal = pCsr->aMatchinfo; |
| 107163 | |
| 107164 | if( pCsr->isMatchinfoOk ){ |
| 107165 | (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void *)&g); |
| 107166 | pCsr->isMatchinfoOk = 0; |
| 107167 | } |
| 107168 | |
| 107169 | return SQLITE_OK; |
| 107170 | } |
| 107171 | |
| 107172 | SQLITE_PRIVATE void sqlite3Fts3Snippet2( |
| 107173 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 107174 | Fts3Cursor *pCsr, /* Cursor object */ |
| 107175 | const char *zStart, /* Snippet start text - "<b>" */ |
| 107176 | const char *zEnd, /* Snippet end text - "</b>" */ |
| 107177 | const char *zEllipsis, /* Snippet ellipsis text - "<b>...</b>" */ |
| 107178 | int iCol, /* Extract snippet from this column */ |
| 107179 | int nToken /* Approximate number of tokens in snippet */ |
| 107180 | ){ |
| 107181 | int rc; |
| 107182 | int iPos = 0; |
| 107183 | u64 hlmask = 0; |
| 107184 | char *z = 0; |
| 107185 | int nDoc; |
| 107186 | const char *zDoc; |
| 107187 | |
| 107188 | rc = fts3BestSnippet(nToken, pCsr, iCol, &iPos, &hlmask); |
| 107189 | |
| 107190 | nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1); |
| 107191 | zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1); |
| 107192 | |
| 107193 | if( rc==SQLITE_OK ){ |
| 107194 | rc = fts3SnippetText( |
| 107195 | pCsr, zDoc, nDoc, nToken, iPos, hlmask, zStart, zEnd, zEllipsis, &z); |
| 107196 | } |
| 107197 | if( rc!=SQLITE_OK ){ |
| 107198 | sqlite3_result_error_code(pCtx, rc); |
| 107199 | }else{ |
| 107200 | sqlite3_result_text(pCtx, z, -1, sqlite3_free); |
| 107201 | } |
| 107202 | } |
| 107203 | |
| 107204 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *pCsr){ |
| 107205 | int rc = fts3GetMatchinfo(pCsr); |
| 107206 | if( rc!=SQLITE_OK ){ |
| 107207 | sqlite3_result_error_code(pContext, rc); |
| 107208 | }else{ |
| 107209 | int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*2); |
| 107210 | sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); |
| 107211 | } |
| 107212 | } |
| 107213 | |
| 107214 | #endif |
| @@ -107634,10 +109097,11 @@ | |
| 107634 | |
| 107635 | sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); |
| 107636 | rc = sqlite3_step(pRtree->pReadNode); |
| 107637 | if( rc==SQLITE_ROW ){ |
| 107638 | const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); |
| 107639 | memcpy(pNode->zData, zBlob, pRtree->iNodeSize); |
| 107640 | nodeReference(pParent); |
| 107641 | }else{ |
| 107642 | sqlite3_free(pNode); |
| 107643 | pNode = 0; |
| @@ -109830,35 +111294,73 @@ | |
| 109830 | |
| 109831 | return rc; |
| 109832 | } |
| 109833 | |
| 109834 | /* |
| 109835 | ** This routine queries database handle db for the page-size used by |
| 109836 | ** database zDb. If successful, the page-size in bytes is written to |
| 109837 | ** *piPageSize and SQLITE_OK returned. Otherwise, and an SQLite error |
| 109838 | ** code is returned. |
| 109839 | */ |
| 109840 | static int getPageSize(sqlite3 *db, const char *zDb, int *piPageSize){ |
| 109841 | int rc = SQLITE_NOMEM; |
| 109842 | char *zSql; |
| 109843 | sqlite3_stmt *pStmt = 0; |
| 109844 | |
| 109845 | zSql = sqlite3_mprintf("PRAGMA %Q.page_size", zDb); |
| 109846 | if( !zSql ){ |
| 109847 | return SQLITE_NOMEM; |
| 109848 | } |
| 109849 | |
| 109850 | rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
| 109851 | sqlite3_free(zSql); |
| 109852 | if( rc!=SQLITE_OK ){ |
| 109853 | return rc; |
| 109854 | } |
| 109855 | |
| 109856 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 109857 | *piPageSize = sqlite3_column_int(pStmt, 0); |
| 109858 | } |
| 109859 | return sqlite3_finalize(pStmt); |
| 109860 | } |
| 109861 | |
| 109862 | /* |
| 109863 | ** This function is the implementation of both the xConnect and xCreate |
| 109864 | ** methods of the r-tree virtual table. |
| @@ -109875,11 +111377,10 @@ | |
| 109875 | sqlite3_vtab **ppVtab, /* OUT: New virtual table */ |
| 109876 | char **pzErr, /* OUT: Error message, if any */ |
| 109877 | int isCreate /* True for xCreate, false for xConnect */ |
| 109878 | ){ |
| 109879 | int rc = SQLITE_OK; |
| 109880 | int iPageSize = 0; |
| 109881 | Rtree *pRtree; |
| 109882 | int nDb; /* Length of string argv[1] */ |
| 109883 | int nName; /* Length of string argv[2] */ |
| 109884 | int eCoordType = (int)pAux; |
| 109885 | |
| @@ -109894,15 +111395,10 @@ | |
| 109894 | if( aErrMsg[iErr] ){ |
| 109895 | *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); |
| 109896 | return SQLITE_ERROR; |
| 109897 | } |
| 109898 | |
| 109899 | rc = getPageSize(db, argv[1], &iPageSize); |
| 109900 | if( rc!=SQLITE_OK ){ |
| 109901 | return rc; |
| 109902 | } |
| 109903 | |
| 109904 | /* Allocate the sqlite3_vtab structure */ |
| 109905 | nDb = strlen(argv[1]); |
| 109906 | nName = strlen(argv[2]); |
| 109907 | pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); |
| 109908 | if( !pRtree ){ |
| @@ -109917,48 +111413,41 @@ | |
| 109917 | pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; |
| 109918 | pRtree->eCoordType = eCoordType; |
| 109919 | memcpy(pRtree->zDb, argv[1], nDb); |
| 109920 | memcpy(pRtree->zName, argv[2], nName); |
| 109921 | |
| 109922 | /* Figure out the node size to use. By default, use 64 bytes less than |
| 109923 | ** the database page-size. This ensures that each node is stored on |
| 109924 | ** a single database page. |
| 109925 | ** |
| 109926 | ** If the databasd page-size is so large that more than RTREE_MAXCELLS |
| 109927 | ** entries would fit in a single node, use a smaller node-size. |
| 109928 | */ |
| 109929 | pRtree->iNodeSize = iPageSize-64; |
| 109930 | if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ |
| 109931 | pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; |
| 109932 | } |
| 109933 | |
| 109934 | /* Create/Connect to the underlying relational database schema. If |
| 109935 | ** that is successful, call sqlite3_declare_vtab() to configure |
| 109936 | ** the r-tree table schema. |
| 109937 | */ |
| 109938 | if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ |
| 109939 | *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
| 109940 | }else{ |
| 109941 | char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); |
| 109942 | char *zTmp; |
| 109943 | int ii; |
| 109944 | for(ii=4; zSql && ii<argc; ii++){ |
| 109945 | zTmp = zSql; |
| 109946 | zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); |
| 109947 | sqlite3_free(zTmp); |
| 109948 | } |
| 109949 | if( zSql ){ |
| 109950 | zTmp = zSql; |
| 109951 | zSql = sqlite3_mprintf("%s);", zTmp); |
| 109952 | sqlite3_free(zTmp); |
| 109953 | } |
| 109954 | if( !zSql ){ |
| 109955 | rc = SQLITE_NOMEM; |
| 109956 | }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ |
| 109957 | *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
| 109958 | } |
| 109959 | sqlite3_free(zSql); |
| 109960 | } |
| 109961 | |
| 109962 | if( rc==SQLITE_OK ){ |
| 109963 | *ppVtab = (sqlite3_vtab *)pRtree; |
| 109964 | }else{ |
| 109965 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.6.23. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a one translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% are more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -305,10 +305,15 @@ | |
| 305 | #endif |
| 306 | #ifdef HAVE_INTTYPES_H |
| 307 | #include <inttypes.h> |
| 308 | #endif |
| 309 | |
| 310 | /* |
| 311 | ** The number of samples of an index that SQLite takes in order to |
| 312 | ** construct a histogram of the table content when running ANALYZE |
| 313 | ** and with SQLITE_ENABLE_STAT2 |
| 314 | */ |
| 315 | #define SQLITE_INDEX_SAMPLES 10 |
| 316 | |
| 317 | /* |
| 318 | ** This macro is used to "hide" some ugliness in casting an int |
| 319 | ** value to a ptr value under the MSVC 64-bit compiler. Casting |
| @@ -369,27 +374,22 @@ | |
| 374 | ** Exactly one of the following macros must be defined in order to |
| 375 | ** specify which memory allocation subsystem to use. |
| 376 | ** |
| 377 | ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() |
| 378 | ** SQLITE_MEMDEBUG // Debugging version of system malloc() |
| 379 | ** |
| 380 | ** (Historical note: There used to be several other options, but we've |
| 381 | ** pared it down to just these two.) |
| 382 | ** |
| 383 | ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as |
| 384 | ** the default. |
| 385 | */ |
| 386 | #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1 |
| 387 | # error "At most one of the following compile-time configuration options\ |
| 388 | is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG" |
| 389 | #endif |
| 390 | #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0 |
| 391 | # define SQLITE_SYSTEM_MALLOC 1 |
| 392 | #endif |
| 393 | |
| 394 | /* |
| 395 | ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the |
| @@ -629,17 +629,17 @@ | |
| 629 | ** |
| 630 | ** See also: [sqlite3_libversion()], |
| 631 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 632 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 633 | */ |
| 634 | #define SQLITE_VERSION "3.6.23" |
| 635 | #define SQLITE_VERSION_NUMBER 3006023 |
| 636 | #define SQLITE_SOURCE_ID "2010-02-26 13:07:37 8f29490da62df07ea922b03cab52b6edd2669edb" |
| 637 | |
| 638 | /* |
| 639 | ** CAPI3REF: Run-Time Library Version Numbers |
| 640 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 641 | ** |
| 642 | ** These interfaces provide the same information as the [SQLITE_VERSION], |
| 643 | ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| 644 | ** but are associated with the library instead of the header file. ^(Cautious |
| 645 | ** programmers might include assert() statements in their application to |
| @@ -657,21 +657,48 @@ | |
| 657 | ** macro. ^The sqlite3_libversion() function returns a pointer to the |
| 658 | ** to the sqlite3_version[] string constant. The sqlite3_libversion() |
| 659 | ** function is provided for use in DLLs since DLL users usually do not have |
| 660 | ** direct access to string constants within the DLL. ^The |
| 661 | ** sqlite3_libversion_number() function returns an integer equal to |
| 662 | ** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns |
| 663 | ** a pointer to a string constant whose value is the same as the |
| 664 | ** [SQLITE_SOURCE_ID] C preprocessor macro. |
| 665 | ** |
| 666 | ** See also: [sqlite_version()] and [sqlite_source_id()]. |
| 667 | */ |
| 668 | SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; |
| 669 | SQLITE_API const char *sqlite3_libversion(void); |
| 670 | SQLITE_API const char *sqlite3_sourceid(void); |
| 671 | SQLITE_API int sqlite3_libversion_number(void); |
| 672 | |
| 673 | /* |
| 674 | ** CAPI3REF: Run-Time Library Compilation Options Diagnostics |
| 675 | ** KEYWORDS: sqlite3_compileoption_used, sqlite3_compileoption_get |
| 676 | ** |
| 677 | ** ^The sqlite3_compileoption_used() function returns 0 or 1 |
| 678 | ** indicating whether the specified option was defined at |
| 679 | ** compile time. ^The SQLITE_ prefix may be omitted from the |
| 680 | ** option name passed to sqlite3_compileoption_used(). |
| 681 | ** |
| 682 | ** ^The sqlite3_compileoption_get() function allows interating |
| 683 | ** over the list of options that were defined at compile time by |
| 684 | ** returning the N-th compile time option string. ^If N is out of range, |
| 685 | ** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ |
| 686 | ** prefix is omitted from any strings returned by |
| 687 | ** sqlite3_compileoption_get(). |
| 688 | ** |
| 689 | ** ^Support for the diagnostic functions sqlite3_compileoption_used() |
| 690 | ** and sqlite3_compileoption_get() may be omitted by specifing the |
| 691 | ** SQLITE_OMIT_COMPILEOPTION_DIAGS option at compile time. |
| 692 | ** |
| 693 | ** See also: [sqlite_compile_option_used()] and [sqlite_compile_option_get()]. |
| 694 | */ |
| 695 | #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 696 | SQLITE_API int sqlite3_compileoption_used(const char *zOptName); |
| 697 | SQLITE_API const char *sqlite3_compileoption_get(int N); |
| 698 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 699 | |
| 700 | /* |
| 701 | ** CAPI3REF: Test To See If The Library Is Threadsafe |
| 702 | ** |
| 703 | ** ^The sqlite3_threadsafe() function returns zero if and only if |
| 704 | ** SQLite was compiled mutexing code omitted due to the |
| @@ -959,10 +986,11 @@ | |
| 986 | #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ |
| 987 | #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ |
| 988 | #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ |
| 989 | #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ |
| 990 | #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ |
| 991 | #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ |
| 992 | #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ |
| 993 | #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ |
| 994 | #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ |
| 995 | #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ |
| 996 | #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ |
| @@ -1440,11 +1468,10 @@ | |
| 1468 | SQLITE_API int sqlite3_os_init(void); |
| 1469 | SQLITE_API int sqlite3_os_end(void); |
| 1470 | |
| 1471 | /* |
| 1472 | ** CAPI3REF: Configuring The SQLite Library |
| 1473 | ** |
| 1474 | ** The sqlite3_config() interface is used to make global configuration |
| 1475 | ** changes to SQLite in order to tune SQLite to the specific needs of |
| 1476 | ** the application. The default configuration is recommended for most |
| 1477 | ** applications and so this routine is usually not necessary. It is |
| @@ -1781,10 +1808,11 @@ | |
| 1808 | #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ |
| 1809 | /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ |
| 1810 | #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ |
| 1811 | #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ |
| 1812 | #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ |
| 1813 | #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ |
| 1814 | |
| 1815 | /* |
| 1816 | ** CAPI3REF: Configuration Options |
| 1817 | ** EXPERIMENTAL |
| 1818 | ** |
| @@ -4183,10 +4211,11 @@ | |
| 4211 | sqlite3*, |
| 4212 | void*, |
| 4213 | void(*)(void*,sqlite3*,int eTextRep,const void*) |
| 4214 | ); |
| 4215 | |
| 4216 | #if SQLITE_HAS_CODEC |
| 4217 | /* |
| 4218 | ** Specify the key for an encrypted database. This routine should be |
| 4219 | ** called right after sqlite3_open(). |
| 4220 | ** |
| 4221 | ** The code to implement this API is not available in the public release |
| @@ -4208,10 +4237,29 @@ | |
| 4237 | SQLITE_API int sqlite3_rekey( |
| 4238 | sqlite3 *db, /* Database to be rekeyed */ |
| 4239 | const void *pKey, int nKey /* The new key */ |
| 4240 | ); |
| 4241 | |
| 4242 | /* |
| 4243 | ** Specify the activation key for a SEE database. Unless |
| 4244 | ** activated, none of the SEE routines will work. |
| 4245 | */ |
| 4246 | SQLITE_API void sqlite3_activate_see( |
| 4247 | const char *zPassPhrase /* Activation phrase */ |
| 4248 | ); |
| 4249 | #endif |
| 4250 | |
| 4251 | #ifdef SQLITE_ENABLE_CEROD |
| 4252 | /* |
| 4253 | ** Specify the activation key for a CEROD database. Unless |
| 4254 | ** activated, none of the CEROD routines will work. |
| 4255 | */ |
| 4256 | SQLITE_API void sqlite3_activate_cerod( |
| 4257 | const char *zPassPhrase /* Activation phrase */ |
| 4258 | ); |
| 4259 | #endif |
| 4260 | |
| 4261 | /* |
| 4262 | ** CAPI3REF: Suspend Execution For A Short Time |
| 4263 | ** |
| 4264 | ** ^The sqlite3_sleep() function causes the current thread to suspend execution |
| 4265 | ** for at least a number of milliseconds specified in its parameter. |
| @@ -6169,10 +6217,28 @@ | |
| 6217 | ** case-indendent fashion, using the same definition of case independence |
| 6218 | ** that SQLite uses internally when comparing identifiers. |
| 6219 | */ |
| 6220 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 6221 | |
| 6222 | /* |
| 6223 | ** CAPI3REF: Error Logging Interface |
| 6224 | ** EXPERIMENTAL |
| 6225 | ** |
| 6226 | ** ^The [sqlite3_log()] interface writes a message into the error log |
| 6227 | ** established by the [SQLITE_CONFIG_ERRORLOG] option to [sqlite3_config()]. |
| 6228 | ** ^If logging is enabled, the zFormat string and subsequent arguments are |
| 6229 | ** passed through to [sqlite3_vmprintf()] to generate the final output string. |
| 6230 | ** |
| 6231 | ** The sqlite3_log() interface is intended for use by extensions such as |
| 6232 | ** virtual tables, collating functions, and SQL functions. While there is |
| 6233 | ** nothing to prevent an application from calling sqlite3_log(), doing so |
| 6234 | ** is considered bad form. |
| 6235 | ** |
| 6236 | ** The zFormat string must not be NULL. |
| 6237 | */ |
| 6238 | SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); |
| 6239 | |
| 6240 | /* |
| 6241 | ** Undo the hack that converts floating point types to integer for |
| 6242 | ** builds on processors without floating point support. |
| 6243 | */ |
| 6244 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| @@ -6484,24 +6550,10 @@ | |
| 6550 | #define OMIT_TEMPDB 1 |
| 6551 | #else |
| 6552 | #define OMIT_TEMPDB 0 |
| 6553 | #endif |
| 6554 | |
| 6555 | /* |
| 6556 | ** The "file format" number is an integer that is incremented whenever |
| 6557 | ** the VDBE-level file format changes. The following macros define the |
| 6558 | ** the default file format for new databases and the maximum file format |
| 6559 | ** that the library can read. |
| @@ -6509,10 +6561,14 @@ | |
| 6561 | #define SQLITE_MAX_FILE_FORMAT 4 |
| 6562 | #ifndef SQLITE_DEFAULT_FILE_FORMAT |
| 6563 | # define SQLITE_DEFAULT_FILE_FORMAT 1 |
| 6564 | #endif |
| 6565 | |
| 6566 | /* |
| 6567 | ** Determine whether triggers are recursive by default. This can be |
| 6568 | ** changed at run-time using a pragma. |
| 6569 | */ |
| 6570 | #ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS |
| 6571 | # define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 |
| 6572 | #endif |
| 6573 | |
| 6574 | /* |
| @@ -6753,11 +6809,10 @@ | |
| 6809 | */ |
| 6810 | typedef struct AggInfo AggInfo; |
| 6811 | typedef struct AuthContext AuthContext; |
| 6812 | typedef struct AutoincInfo AutoincInfo; |
| 6813 | typedef struct Bitvec Bitvec; |
| 6814 | typedef struct CollSeq CollSeq; |
| 6815 | typedef struct Column Column; |
| 6816 | typedef struct Db Db; |
| 6817 | typedef struct Schema Schema; |
| 6818 | typedef struct Expr Expr; |
| @@ -6774,20 +6829,21 @@ | |
| 6829 | typedef struct Lookaside Lookaside; |
| 6830 | typedef struct LookasideSlot LookasideSlot; |
| 6831 | typedef struct Module Module; |
| 6832 | typedef struct NameContext NameContext; |
| 6833 | typedef struct Parse Parse; |
| 6834 | typedef struct RowSet RowSet; |
| 6835 | typedef struct Savepoint Savepoint; |
| 6836 | typedef struct Select Select; |
| 6837 | typedef struct SrcList SrcList; |
| 6838 | typedef struct StrAccum StrAccum; |
| 6839 | typedef struct Table Table; |
| 6840 | typedef struct TableLock TableLock; |
| 6841 | typedef struct Token Token; |
| 6842 | typedef struct Trigger Trigger; |
| 6843 | typedef struct TriggerPrg TriggerPrg; |
| 6844 | typedef struct TriggerStep TriggerStep; |
| 6845 | typedef struct UnpackedRecord UnpackedRecord; |
| 6846 | typedef struct VTable VTable; |
| 6847 | typedef struct Walker Walker; |
| 6848 | typedef struct WherePlan WherePlan; |
| 6849 | typedef struct WhereInfo WhereInfo; |
| @@ -6881,10 +6937,11 @@ | |
| 6937 | SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); |
| 6938 | SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); |
| 6939 | SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); |
| 6940 | SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); |
| 6941 | SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); |
| 6942 | SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); |
| 6943 | SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); |
| 6944 | SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); |
| 6945 | SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); |
| 6946 | SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); |
| 6947 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); |
| @@ -7413,10 +7470,11 @@ | |
| 7470 | SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); |
| 7471 | SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); |
| 7472 | SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); |
| 7473 | SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); |
| 7474 | SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); |
| 7475 | SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); |
| 7476 | SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); |
| 7477 | SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int); |
| 7478 | SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); |
| 7479 | SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); |
| 7480 | SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); |
| @@ -8186,19 +8244,19 @@ | |
| 8244 | #endif |
| 8245 | }; |
| 8246 | |
| 8247 | /* |
| 8248 | ** These macros can be used to test, set, or clear bits in the |
| 8249 | ** Db.pSchema->flags field. |
| 8250 | */ |
| 8251 | #define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) |
| 8252 | #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) |
| 8253 | #define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) |
| 8254 | #define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) |
| 8255 | |
| 8256 | /* |
| 8257 | ** Allowed values for the DB.pSchema->flags field. |
| 8258 | ** |
| 8259 | ** The DB_SchemaLoaded flag is set after the database schema has been |
| 8260 | ** read into internal hash tables. |
| 8261 | ** |
| 8262 | ** DB_UnresetViews means that one or more views have column names that |
| @@ -8258,11 +8316,11 @@ | |
| 8316 | struct FuncDefHash { |
| 8317 | FuncDef *a[23]; /* Hash table for functions */ |
| 8318 | }; |
| 8319 | |
| 8320 | /* |
| 8321 | ** Each database connection is an instance of the following structure. |
| 8322 | ** |
| 8323 | ** The sqlite.lastRowid records the last insert rowid generated by an |
| 8324 | ** insert statement. Inserts on views do not affect its value. Each |
| 8325 | ** trigger has its own context, so that lastRowid can be updated inside |
| 8326 | ** triggers as usual. The previous value will be restored once the trigger |
| @@ -8297,10 +8355,11 @@ | |
| 8355 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 8356 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 8357 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 8358 | u8 dfltJournalMode; /* Default journal mode for attached dbs */ |
| 8359 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| 8360 | u8 suppressErr; /* Do not issue error messages if true */ |
| 8361 | int nextPagesize; /* Pagesize after VACUUM if >0 */ |
| 8362 | int nTable; /* Number of tables in the database */ |
| 8363 | CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ |
| 8364 | i64 lastRowid; /* ROWID of most recent insert (see above) */ |
| 8365 | u32 magic; /* Magic number for detect library misuse */ |
| @@ -9873,10 +9932,12 @@ | |
| 9932 | int isMutexInit; /* True after mutexes are initialized */ |
| 9933 | int isMallocInit; /* True after malloc is initialized */ |
| 9934 | int isPCacheInit; /* True after malloc is initialized */ |
| 9935 | sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ |
| 9936 | int nRefInitMutex; /* Number of users of pInitMutex */ |
| 9937 | void (*xLog)(void*,int,const char*); /* Function for logging */ |
| 9938 | void *pLogArg; /* First argument to xLog() */ |
| 9939 | }; |
| 9940 | |
| 9941 | /* |
| 9942 | ** Context pointer passed down through the tree-walk. |
| 9943 | */ |
| @@ -9914,20 +9975,31 @@ | |
| 9975 | while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ |
| 9976 | } \ |
| 9977 | } |
| 9978 | |
| 9979 | /* |
| 9980 | ** The SQLITE_*_BKPT macros are substitutes for the error codes with |
| 9981 | ** the same name but without the _BKPT suffix. These macros invoke |
| 9982 | ** routines that report the line-number on which the error originated |
| 9983 | ** using sqlite3_log(). The routines also provide a convenient place |
| 9984 | ** to set a debugger breakpoint. |
| 9985 | */ |
| 9986 | SQLITE_PRIVATE int sqlite3CorruptError(int); |
| 9987 | SQLITE_PRIVATE int sqlite3MisuseError(int); |
| 9988 | SQLITE_PRIVATE int sqlite3CantopenError(int); |
| 9989 | #define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) |
| 9990 | #define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) |
| 9991 | #define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) |
| 9992 | |
| 9993 | |
| 9994 | /* |
| 9995 | ** FTS4 is really an extension for FTS3. It is enabled using the |
| 9996 | ** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all |
| 9997 | ** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3. |
| 9998 | */ |
| 9999 | #if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) |
| 10000 | # define SQLITE_ENABLE_FTS3 |
| 10001 | #endif |
| 10002 | |
| 10003 | /* |
| 10004 | ** The ctype.h header is needed for non-ASCII systems. It is also |
| 10005 | ** needed by FTS3 when FTS3 is included in the amalgamation. |
| @@ -10025,11 +10097,15 @@ | |
| 10097 | |
| 10098 | SQLITE_PRIVATE int sqlite3StatusValue(int); |
| 10099 | SQLITE_PRIVATE void sqlite3StatusAdd(int, int); |
| 10100 | SQLITE_PRIVATE void sqlite3StatusSet(int, int); |
| 10101 | |
| 10102 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 10103 | SQLITE_PRIVATE int sqlite3IsNaN(double); |
| 10104 | #else |
| 10105 | # define sqlite3IsNaN(X) 0 |
| 10106 | #endif |
| 10107 | |
| 10108 | SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); |
| 10109 | #ifndef SQLITE_OMIT_TRACE |
| 10110 | SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); |
| 10111 | #endif |
| @@ -10042,11 +10118,10 @@ | |
| 10118 | #if defined(SQLITE_TEST) |
| 10119 | SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); |
| 10120 | #endif |
| 10121 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...); |
| 10122 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); |
| 10123 | SQLITE_PRIVATE int sqlite3Dequote(char*); |
| 10124 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); |
| 10125 | SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); |
| 10126 | SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); |
| 10127 | SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); |
| @@ -10212,17 +10287,10 @@ | |
| 10287 | SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); |
| 10288 | SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); |
| 10289 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); |
| 10290 | SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); |
| 10291 | SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); |
| 10292 | SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); |
| 10293 | SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); |
| 10294 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); |
| 10295 | |
| 10296 | #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) |
| @@ -10754,10 +10822,12 @@ | |
| 10822 | 0, /* isMutexInit */ |
| 10823 | 0, /* isMallocInit */ |
| 10824 | 0, /* isPCacheInit */ |
| 10825 | 0, /* pInitMutex */ |
| 10826 | 0, /* nRefInitMutex */ |
| 10827 | 0, /* xLog */ |
| 10828 | 0, /* pLogArg */ |
| 10829 | }; |
| 10830 | |
| 10831 | |
| 10832 | /* |
| 10833 | ** Hash table for global functions - functions common to all |
| @@ -10878,11 +10948,11 @@ | |
| 10948 | ** then this routine is not threadsafe. |
| 10949 | */ |
| 10950 | SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ |
| 10951 | wsdStatInit; |
| 10952 | if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ |
| 10953 | return SQLITE_MISUSE_BKPT; |
| 10954 | } |
| 10955 | *pCurrent = wsdStat.nowValue[op]; |
| 10956 | *pHighwater = wsdStat.mxValue[op]; |
| 10957 | if( resetFlag ){ |
| 10958 | wsdStat.mxValue[op] = wsdStat.nowValue[op]; |
| @@ -12007,12 +12077,12 @@ | |
| 12077 | FUNCTION(current_time, 0, 0, 0, ctimeFunc ), |
| 12078 | FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), |
| 12079 | FUNCTION(current_date, 0, 0, 0, cdateFunc ), |
| 12080 | #else |
| 12081 | STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc), |
| 12082 | STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc), |
| 12083 | STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), |
| 12084 | #endif |
| 12085 | }; |
| 12086 | int i; |
| 12087 | FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); |
| 12088 | FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs); |
| @@ -12135,15 +12205,15 @@ | |
| 12205 | int flags, |
| 12206 | int *pFlagsOut |
| 12207 | ){ |
| 12208 | int rc; |
| 12209 | DO_OS_MALLOC_TEST(0); |
| 12210 | /* 0x7f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed |
| 12211 | ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, |
| 12212 | ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before |
| 12213 | ** reaching the VFS. */ |
| 12214 | rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f3f, pFlagsOut); |
| 12215 | assert( rc==SQLITE_OK || pFile->pMethods==0 ); |
| 12216 | return rc; |
| 12217 | } |
| 12218 | SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
| 12219 | return pVfs->xDelete(pVfs, zPath, dirSync); |
| @@ -12514,10 +12584,13 @@ | |
| 12584 | nByte = ROUND8(nByte); |
| 12585 | p = malloc( nByte+8 ); |
| 12586 | if( p ){ |
| 12587 | p[0] = nByte; |
| 12588 | p++; |
| 12589 | }else{ |
| 12590 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 12591 | sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); |
| 12592 | } |
| 12593 | return (void *)p; |
| 12594 | } |
| 12595 | |
| 12596 | /* |
| @@ -12532,10 +12605,22 @@ | |
| 12605 | sqlite3_int64 *p = (sqlite3_int64*)pPrior; |
| 12606 | assert( pPrior!=0 ); |
| 12607 | p--; |
| 12608 | free(p); |
| 12609 | } |
| 12610 | |
| 12611 | /* |
| 12612 | ** Report the allocated size of a prior return from xMalloc() |
| 12613 | ** or xRealloc(). |
| 12614 | */ |
| 12615 | static int sqlite3MemSize(void *pPrior){ |
| 12616 | sqlite3_int64 *p; |
| 12617 | if( pPrior==0 ) return 0; |
| 12618 | p = (sqlite3_int64*)pPrior; |
| 12619 | p--; |
| 12620 | return (int)p[0]; |
| 12621 | } |
| 12622 | |
| 12623 | /* |
| 12624 | ** Like realloc(). Resize an allocation previously obtained from |
| 12625 | ** sqlite3MemMalloc(). |
| 12626 | ** |
| @@ -12547,32 +12632,24 @@ | |
| 12632 | */ |
| 12633 | static void *sqlite3MemRealloc(void *pPrior, int nByte){ |
| 12634 | sqlite3_int64 *p = (sqlite3_int64*)pPrior; |
| 12635 | assert( pPrior!=0 && nByte>0 ); |
| 12636 | nByte = ROUND8(nByte); |
| 12637 | p--; |
| 12638 | p = realloc(p, nByte+8 ); |
| 12639 | if( p ){ |
| 12640 | p[0] = nByte; |
| 12641 | p++; |
| 12642 | }else{ |
| 12643 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 12644 | sqlite3_log(SQLITE_NOMEM, |
| 12645 | "failed memory resize %u to %u bytes", |
| 12646 | sqlite3MemSize(pPrior), nByte); |
| 12647 | } |
| 12648 | return (void*)p; |
| 12649 | } |
| 12650 | |
| 12651 | /* |
| 12652 | ** Round up a request size to the next valid allocation size. |
| 12653 | */ |
| 12654 | static int sqlite3MemRoundup(int n){ |
| 12655 | return ROUND8(n); |
| @@ -12825,10 +12902,35 @@ | |
| 12902 | ** Round up a request size to the next valid allocation size. |
| 12903 | */ |
| 12904 | static int sqlite3MemRoundup(int n){ |
| 12905 | return ROUND8(n); |
| 12906 | } |
| 12907 | |
| 12908 | /* |
| 12909 | ** Fill a buffer with pseudo-random bytes. This is used to preset |
| 12910 | ** the content of a new memory allocation to unpredictable values and |
| 12911 | ** to clear the content of a freed allocation to unpredictable values. |
| 12912 | */ |
| 12913 | static void randomFill(char *pBuf, int nByte){ |
| 12914 | unsigned int x, y, r; |
| 12915 | x = SQLITE_PTR_TO_INT(pBuf); |
| 12916 | y = nByte | 1; |
| 12917 | while( nByte >= 4 ){ |
| 12918 | x = (x>>1) ^ (-(x&1) & 0xd0000001); |
| 12919 | y = y*1103515245 + 12345; |
| 12920 | r = x ^ y; |
| 12921 | *(int*)pBuf = r; |
| 12922 | pBuf += 4; |
| 12923 | nByte -= 4; |
| 12924 | } |
| 12925 | while( nByte-- > 0 ){ |
| 12926 | x = (x>>1) ^ (-(x&1) & 0xd0000001); |
| 12927 | y = y*1103515245 + 12345; |
| 12928 | r = x ^ y; |
| 12929 | *(pBuf++) = r & 0xff; |
| 12930 | } |
| 12931 | } |
| 12932 | |
| 12933 | /* |
| 12934 | ** Allocate nByte bytes of memory. |
| 12935 | */ |
| 12936 | static void *sqlite3MemMalloc(int nByte){ |
| @@ -12876,11 +12978,12 @@ | |
| 12978 | } |
| 12979 | pHdr->iSize = nByte; |
| 12980 | adjustStats(nByte, +1); |
| 12981 | pInt = (int*)&pHdr[1]; |
| 12982 | pInt[nReserve/sizeof(int)] = REARGUARD; |
| 12983 | randomFill((char*)pInt, nByte); |
| 12984 | memset(((char*)pInt)+nByte, 0x65, nReserve-nByte); |
| 12985 | p = (void*)pInt; |
| 12986 | } |
| 12987 | sqlite3_mutex_leave(mem.mutex); |
| 12988 | return p; |
| 12989 | } |
| @@ -12912,12 +13015,12 @@ | |
| 13015 | mem.pLast = pHdr->pPrev; |
| 13016 | } |
| 13017 | z = (char*)pBt; |
| 13018 | z -= pHdr->nTitle; |
| 13019 | adjustStats(pHdr->iSize, -1); |
| 13020 | randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + |
| 13021 | pHdr->iSize + sizeof(int) + pHdr->nTitle); |
| 13022 | free(z); |
| 13023 | sqlite3_mutex_leave(mem.mutex); |
| 13024 | } |
| 13025 | |
| 13026 | /* |
| @@ -12936,11 +13039,11 @@ | |
| 13039 | pOldHdr = sqlite3MemsysGetHeader(pPrior); |
| 13040 | pNew = sqlite3MemMalloc(nByte); |
| 13041 | if( pNew ){ |
| 13042 | memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize); |
| 13043 | if( nByte>pOldHdr->iSize ){ |
| 13044 | randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize); |
| 13045 | } |
| 13046 | sqlite3MemFree(pPrior); |
| 13047 | } |
| 13048 | return pNew; |
| 13049 | } |
| @@ -14017,11 +14120,15 @@ | |
| 14120 | /* Make sure mem5.aiFreelist[iLogsize] contains at least one free |
| 14121 | ** block. If not, then split a block of the next larger power of |
| 14122 | ** two in order to create a new free block of size iLogsize. |
| 14123 | */ |
| 14124 | for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){} |
| 14125 | if( iBin>LOGMAX ){ |
| 14126 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 14127 | sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte); |
| 14128 | return 0; |
| 14129 | } |
| 14130 | i = memsys5UnlinkFirst(iBin); |
| 14131 | while( iBin>iLogsize ){ |
| 14132 | int newSize; |
| 14133 | |
| 14134 | iBin--; |
| @@ -15294,11 +15401,20 @@ | |
| 15401 | struct sqlite3_mutex { |
| 15402 | CRITICAL_SECTION mutex; /* Mutex controlling the lock */ |
| 15403 | int id; /* Mutex type */ |
| 15404 | int nRef; /* Number of enterances */ |
| 15405 | DWORD owner; /* Thread holding this mutex */ |
| 15406 | #ifdef SQLITE_DEBUG |
| 15407 | int trace; /* True to trace changes */ |
| 15408 | #endif |
| 15409 | }; |
| 15410 | #define SQLITE_W32_MUTEX_INITIALIZER { 0 } |
| 15411 | #ifdef SQLITE_DEBUG |
| 15412 | #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 } |
| 15413 | #else |
| 15414 | #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0 } |
| 15415 | #endif |
| 15416 | |
| 15417 | /* |
| 15418 | ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, |
| 15419 | ** or WinCE. Return false (zero) for Win95, Win98, or WinME. |
| 15420 | ** |
| @@ -15337,21 +15453,32 @@ | |
| 15453 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are |
| 15454 | ** intended for use only inside assert() statements. |
| 15455 | */ |
| 15456 | static int winMutexHeld(sqlite3_mutex *p){ |
| 15457 | return p->nRef!=0 && p->owner==GetCurrentThreadId(); |
| 15458 | } |
| 15459 | static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){ |
| 15460 | return p->nRef==0 || p->owner!=tid; |
| 15461 | } |
| 15462 | static int winMutexNotheld(sqlite3_mutex *p){ |
| 15463 | DWORD tid = GetCurrentThreadId(); |
| 15464 | return winMutexNotheld2(p, tid); |
| 15465 | } |
| 15466 | #endif |
| 15467 | |
| 15468 | |
| 15469 | /* |
| 15470 | ** Initialize and deinitialize the mutex subsystem. |
| 15471 | */ |
| 15472 | static sqlite3_mutex winMutex_staticMutexes[6] = { |
| 15473 | SQLITE3_MUTEX_INITIALIZER, |
| 15474 | SQLITE3_MUTEX_INITIALIZER, |
| 15475 | SQLITE3_MUTEX_INITIALIZER, |
| 15476 | SQLITE3_MUTEX_INITIALIZER, |
| 15477 | SQLITE3_MUTEX_INITIALIZER, |
| 15478 | SQLITE3_MUTEX_INITIALIZER |
| 15479 | }; |
| 15480 | static int winMutex_isInit = 0; |
| 15481 | /* As winMutexInit() and winMutexEnd() are called as part |
| 15482 | ** of the sqlite3_initialize and sqlite3_shutdown() |
| 15483 | ** processing, the "interlocked" magic is probably not |
| 15484 | ** strictly necessary. |
| @@ -15481,18 +15608,25 @@ | |
| 15608 | ** mutex must be exited an equal number of times before another thread |
| 15609 | ** can enter. If the same thread tries to enter any other kind of mutex |
| 15610 | ** more than once, the behavior is undefined. |
| 15611 | */ |
| 15612 | static void winMutexEnter(sqlite3_mutex *p){ |
| 15613 | DWORD tid = GetCurrentThreadId(); |
| 15614 | assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); |
| 15615 | EnterCriticalSection(&p->mutex); |
| 15616 | p->owner = tid; |
| 15617 | p->nRef++; |
| 15618 | #ifdef SQLITE_DEBUG |
| 15619 | if( p->trace ){ |
| 15620 | printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); |
| 15621 | } |
| 15622 | #endif |
| 15623 | } |
| 15624 | static int winMutexTry(sqlite3_mutex *p){ |
| 15625 | DWORD tid = GetCurrentThreadId(); |
| 15626 | int rc = SQLITE_BUSY; |
| 15627 | assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); |
| 15628 | /* |
| 15629 | ** The sqlite3_mutex_try() routine is very rarely used, and when it |
| 15630 | ** is used it is merely an optimization. So it is OK for it to always |
| 15631 | ** fail. |
| 15632 | ** |
| @@ -15502,16 +15636,21 @@ | |
| 15636 | ** For that reason, we will omit this optimization for now. See |
| 15637 | ** ticket #2685. |
| 15638 | */ |
| 15639 | #if 0 |
| 15640 | if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){ |
| 15641 | p->owner = tid; |
| 15642 | p->nRef++; |
| 15643 | rc = SQLITE_OK; |
| 15644 | } |
| 15645 | #else |
| 15646 | UNUSED_PARAMETER(p); |
| 15647 | #endif |
| 15648 | #ifdef SQLITE_DEBUG |
| 15649 | if( rc==SQLITE_OK && p->trace ){ |
| 15650 | printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); |
| 15651 | } |
| 15652 | #endif |
| 15653 | return rc; |
| 15654 | } |
| 15655 | |
| 15656 | /* |
| @@ -15519,15 +15658,21 @@ | |
| 15658 | ** previously entered by the same thread. The behavior |
| 15659 | ** is undefined if the mutex is not currently entered or |
| 15660 | ** is not currently allocated. SQLite will never do either. |
| 15661 | */ |
| 15662 | static void winMutexLeave(sqlite3_mutex *p){ |
| 15663 | DWORD tid = GetCurrentThreadId(); |
| 15664 | assert( p->nRef>0 ); |
| 15665 | assert( p->owner==tid ); |
| 15666 | p->nRef--; |
| 15667 | assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 15668 | LeaveCriticalSection(&p->mutex); |
| 15669 | #ifdef SQLITE_DEBUG |
| 15670 | if( p->trace ){ |
| 15671 | printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); |
| 15672 | } |
| 15673 | #endif |
| 15674 | } |
| 15675 | |
| 15676 | SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ |
| 15677 | static sqlite3_mutex_methods sMutex = { |
| 15678 | winMutexInit, |
| @@ -16868,11 +17013,13 @@ | |
| 17013 | } |
| 17014 | i = prefix!=0; |
| 17015 | while( nPad-- ) bufpt[i++] = '0'; |
| 17016 | length = width; |
| 17017 | } |
| 17018 | #else |
| 17019 | length = 0; |
| 17020 | #endif /* SQLITE_OMIT_FLOATING_POINT */ |
| 17021 | break; |
| 17022 | case etSIZE: |
| 17023 | *(va_arg(ap,int*)) = pAccum->nChar; |
| 17024 | length = width = 0; |
| 17025 | break; |
| @@ -17198,10 +17345,32 @@ | |
| 17345 | sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 17346 | va_end(ap); |
| 17347 | z = sqlite3StrAccumFinish(&acc); |
| 17348 | return z; |
| 17349 | } |
| 17350 | |
| 17351 | /* |
| 17352 | ** Format and write a message to the log if logging is enabled. |
| 17353 | */ |
| 17354 | SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){ |
| 17355 | void (*xLog)(void*, int, const char*); /* The global logger function */ |
| 17356 | void *pLogArg; /* First argument to the logger */ |
| 17357 | va_list ap; /* Vararg list */ |
| 17358 | char *zMsg; /* Complete log message */ |
| 17359 | |
| 17360 | xLog = sqlite3GlobalConfig.xLog; |
| 17361 | if( xLog ){ |
| 17362 | va_start(ap, zFormat); |
| 17363 | sqlite3BeginBenignMalloc(); |
| 17364 | zMsg = sqlite3_vmprintf(zFormat, ap); |
| 17365 | sqlite3EndBenignMalloc(); |
| 17366 | va_end(ap); |
| 17367 | pLogArg = sqlite3GlobalConfig.pLogArg; |
| 17368 | xLog(pLogArg, iErrCode, zMsg ? zMsg : zFormat); |
| 17369 | sqlite3_free(zMsg); |
| 17370 | } |
| 17371 | } |
| 17372 | |
| 17373 | #if defined(SQLITE_DEBUG) |
| 17374 | /* |
| 17375 | ** A version of printf() that understands %lld. Used for debugging. |
| 17376 | ** The printf() built into some versions of windows does not understand %lld |
| @@ -17721,10 +17890,11 @@ | |
| 17890 | int rc; /* Value to return */ |
| 17891 | char *zErrMsg; /* Error message written here */ |
| 17892 | u8 explain; /* True if EXPLAIN present on SQL command */ |
| 17893 | u8 changeCntOn; /* True to update the change-counter */ |
| 17894 | u8 expired; /* True if the VM needs to be recompiled */ |
| 17895 | u8 runOnlyOnce; /* Automatically expire on reset */ |
| 17896 | u8 minWriteFileFormat; /* Minimum file format for writable database files */ |
| 17897 | u8 inVtabMethod; /* See comments above */ |
| 17898 | u8 usesStmtJournal; /* True if uses a statement journal */ |
| 17899 | u8 readOnly; /* True for read-only statements */ |
| 17900 | u8 isPrepareV2; /* True if prepared with prepare_v2() */ |
| @@ -17782,11 +17952,15 @@ | |
| 17952 | SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); |
| 17953 | SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); |
| 17954 | SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); |
| 17955 | SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); |
| 17956 | SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); |
| 17957 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 17958 | # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 |
| 17959 | #else |
| 17960 | SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); |
| 17961 | #endif |
| 17962 | SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); |
| 17963 | SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); |
| 17964 | SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); |
| 17965 | SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); |
| 17966 | SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int); |
| @@ -18388,10 +18562,11 @@ | |
| 18562 | static int dummy = 0; |
| 18563 | dummy += x; |
| 18564 | } |
| 18565 | #endif |
| 18566 | |
| 18567 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 18568 | /* |
| 18569 | ** Return true if the floating point value is Not a Number (NaN). |
| 18570 | ** |
| 18571 | ** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN. |
| 18572 | ** Otherwise, we have our own implementation that works on most systems. |
| @@ -18432,10 +18607,11 @@ | |
| 18607 | rc = isnan(x); |
| 18608 | #endif /* SQLITE_HAVE_ISNAN */ |
| 18609 | testcase( rc ); |
| 18610 | return rc; |
| 18611 | } |
| 18612 | #endif /* SQLITE_OMIT_FLOATING_POINT */ |
| 18613 | |
| 18614 | /* |
| 18615 | ** Compute a string length that is limited to what can be stored in |
| 18616 | ** lower 30 bits of a 32-bit signed integer. |
| 18617 | ** |
| @@ -18503,27 +18679,24 @@ | |
| 18679 | ** stored by this function into the database handle using sqlite3Error(). |
| 18680 | ** Function sqlite3Error() should be used during statement execution |
| 18681 | ** (sqlite3_step() etc.). |
| 18682 | */ |
| 18683 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ |
| 18684 | char *zMsg; |
| 18685 | va_list ap; |
| 18686 | sqlite3 *db = pParse->db; |
| 18687 | va_start(ap, zFormat); |
| 18688 | zMsg = sqlite3VMPrintf(db, zFormat, ap); |
| 18689 | va_end(ap); |
| 18690 | if( db->suppressErr ){ |
| 18691 | sqlite3DbFree(db, zMsg); |
| 18692 | }else{ |
| 18693 | pParse->nErr++; |
| 18694 | sqlite3DbFree(db, pParse->zErrMsg); |
| 18695 | pParse->zErrMsg = zMsg; |
| 18696 | pParse->rc = SQLITE_ERROR; |
| 18697 | } |
| 18698 | } |
| 18699 | |
| 18700 | /* |
| 18701 | ** Convert an SQL-style quoted string into a normal string by removing |
| 18702 | ** the quote characters. The conversion is done in-place. If the |
| @@ -18612,10 +18785,11 @@ | |
| 18785 | return 0; |
| 18786 | } |
| 18787 | z += incr; |
| 18788 | *realnum = 0; |
| 18789 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18790 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 18791 | if( *z=='.' ){ |
| 18792 | z += incr; |
| 18793 | if( !sqlite3Isdigit(*z) ) return 0; |
| 18794 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18795 | *realnum = 1; |
| @@ -18625,10 +18799,11 @@ | |
| 18799 | if( *z=='+' || *z=='-' ) z += incr; |
| 18800 | if( !sqlite3Isdigit(*z) ) return 0; |
| 18801 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18802 | *realnum = 1; |
| 18803 | } |
| 18804 | #endif |
| 18805 | return *z==0; |
| 18806 | } |
| 18807 | |
| 18808 | /* |
| 18809 | ** The string z[] is an ASCII representation of a real number. |
| @@ -18786,10 +18961,13 @@ | |
| 18961 | static int compare2pow63(const char *zNum){ |
| 18962 | int c; |
| 18963 | c = memcmp(zNum,"922337203685477580",18)*10; |
| 18964 | if( c==0 ){ |
| 18965 | c = zNum[18] - '8'; |
| 18966 | testcase( c==(-1) ); |
| 18967 | testcase( c==0 ); |
| 18968 | testcase( c==(+1) ); |
| 18969 | } |
| 18970 | return c; |
| 18971 | } |
| 18972 | |
| 18973 | |
| @@ -18822,10 +19000,13 @@ | |
| 19000 | while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */ |
| 19001 | for(i=0; (c=zNum[i])>='0' && c<='9'; i++){ |
| 19002 | v = v*10 + c - '0'; |
| 19003 | } |
| 19004 | *pNum = neg ? -v : v; |
| 19005 | testcase( i==18 ); |
| 19006 | testcase( i==19 ); |
| 19007 | testcase( i==20 ); |
| 19008 | if( c!=0 || (i==0 && zStart==zNum) || i>19 ){ |
| 19009 | /* zNum is empty or contains non-numeric text or is longer |
| 19010 | ** than 19 digits (thus guaranting that it is too large) */ |
| 19011 | return 0; |
| 19012 | }else if( i<19 ){ |
| @@ -18865,10 +19046,13 @@ | |
| 19046 | if( negFlag ) neg = 1-neg; |
| 19047 | while( *zNum=='0' ){ |
| 19048 | zNum++; /* Skip leading zeros. Ticket #2454 */ |
| 19049 | } |
| 19050 | for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); } |
| 19051 | testcase( i==18 ); |
| 19052 | testcase( i==19 ); |
| 19053 | testcase( i==20 ); |
| 19054 | if( i<19 ){ |
| 19055 | /* Guaranteed to fit if less than 19 digits */ |
| 19056 | return 1; |
| 19057 | }else if( i>19 ){ |
| 19058 | /* Guaranteed to be too big if greater than 19 digits */ |
| @@ -18905,13 +19089,15 @@ | |
| 19089 | /* The longest decimal representation of a 32 bit integer is 10 digits: |
| 19090 | ** |
| 19091 | ** 1234567890 |
| 19092 | ** 2^31 -> 2147483648 |
| 19093 | */ |
| 19094 | testcase( i==10 ); |
| 19095 | if( i>10 ){ |
| 19096 | return 0; |
| 19097 | } |
| 19098 | testcase( v-neg==2147483647 ); |
| 19099 | if( v-neg>2147483647 ){ |
| 19100 | return 0; |
| 19101 | } |
| 19102 | if( neg ){ |
| 19103 | v = -v; |
| @@ -19354,68 +19540,21 @@ | |
| 19540 | } |
| 19541 | return zBlob; |
| 19542 | } |
| 19543 | #endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */ |
| 19544 | |
| 19545 | /* |
| 19546 | ** Log an error that is an API call on a connection pointer that should |
| 19547 | ** not have been used. The "type" of connection pointer is given as the |
| 19548 | ** argument. The zType is a word like "NULL" or "closed" or "invalid". |
| 19549 | */ |
| 19550 | static void logBadConnection(const char *zType){ |
| 19551 | sqlite3_log(SQLITE_MISUSE, |
| 19552 | "API call with %s database connection pointer", |
| 19553 | zType |
| 19554 | ); |
| 19555 | } |
| 19556 | |
| 19557 | /* |
| 19558 | ** Check to make sure we have a valid db pointer. This test is not |
| 19559 | ** foolproof but it does provide some measure of protection against |
| 19560 | ** misuse of the interface such as passing in db pointers that are |
| @@ -19429,17 +19568,20 @@ | |
| 19568 | ** open properly and is not fit for general use but which can be |
| 19569 | ** used as an argument to sqlite3_errmsg() or sqlite3_close(). |
| 19570 | */ |
| 19571 | SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){ |
| 19572 | u32 magic; |
| 19573 | if( db==0 ){ |
| 19574 | logBadConnection("NULL"); |
| 19575 | return 0; |
| 19576 | } |
| 19577 | magic = db->magic; |
| 19578 | if( magic!=SQLITE_MAGIC_OPEN ){ |
| 19579 | if( sqlite3SafetyCheckSickOrOk(db) ){ |
| 19580 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 19581 | logBadConnection("unopened"); |
| 19582 | } |
| 19583 | return 0; |
| 19584 | }else{ |
| 19585 | return 1; |
| 19586 | } |
| 19587 | } |
| @@ -19446,12 +19588,17 @@ | |
| 19588 | SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ |
| 19589 | u32 magic; |
| 19590 | magic = db->magic; |
| 19591 | if( magic!=SQLITE_MAGIC_SICK && |
| 19592 | magic!=SQLITE_MAGIC_OPEN && |
| 19593 | magic!=SQLITE_MAGIC_BUSY ){ |
| 19594 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 19595 | logBadConnection("invalid"); |
| 19596 | return 0; |
| 19597 | }else{ |
| 19598 | return 1; |
| 19599 | } |
| 19600 | } |
| 19601 | |
| 19602 | /************** End of util.c ************************************************/ |
| 19603 | /************** Begin file hash.c ********************************************/ |
| 19604 | /* |
| @@ -21365,10 +21512,15 @@ | |
| 21512 | # include <sys/param.h> |
| 21513 | # include <sys/mount.h> |
| 21514 | # endif |
| 21515 | #endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
| 21516 | |
| 21517 | /* |
| 21518 | ** Allowed values of unixFile.fsFlags |
| 21519 | */ |
| 21520 | #define SQLITE_FSFLAGS_IS_MSDOS 0x1 |
| 21521 | |
| 21522 | /* |
| 21523 | ** If we are to be thread-safe, include the pthreads header and define |
| 21524 | ** the SQLITE_UNIX_THREADS macro. |
| 21525 | */ |
| 21526 | #if SQLITE_THREADSAFE |
| @@ -21431,10 +21583,13 @@ | |
| 21583 | UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ |
| 21584 | int fileFlags; /* Miscellanous flags */ |
| 21585 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 21586 | int openFlags; /* The flags specified at open() */ |
| 21587 | #endif |
| 21588 | #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) |
| 21589 | unsigned fsFlags; /* cached details from statfs() */ |
| 21590 | #endif |
| 21591 | #if SQLITE_THREADSAFE && defined(__linux__) |
| 21592 | pthread_t tid; /* The thread that "owns" this unixFile */ |
| 21593 | #endif |
| 21594 | #if OS_VXWORKS |
| 21595 | int isDelete; /* Delete on close if true */ |
| @@ -22198,10 +22353,13 @@ | |
| 22353 | struct unixLockInfo { |
| 22354 | struct unixLockKey lockKey; /* The lookup key */ |
| 22355 | int cnt; /* Number of SHARED locks held */ |
| 22356 | int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ |
| 22357 | int nRef; /* Number of pointers to this structure */ |
| 22358 | #if defined(SQLITE_ENABLE_LOCKING_STYLE) |
| 22359 | unsigned long long sharedByte; /* for AFP simulated shared lock */ |
| 22360 | #endif |
| 22361 | struct unixLockInfo *pNext; /* List of all unixLockInfo objects */ |
| 22362 | struct unixLockInfo *pPrev; /* .... doubly linked */ |
| 22363 | }; |
| 22364 | |
| 22365 | /* |
| @@ -22441,13 +22599,14 @@ | |
| 22599 | ** an ASCII 'S' character which also happens to be the first byte |
| 22600 | ** in the header of every SQLite database. In this way, if there |
| 22601 | ** is a race condition such that another thread has already populated |
| 22602 | ** the first page of the database, no damage is done. |
| 22603 | */ |
| 22604 | if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){ |
| 22605 | rc = write(fd, "S", 1); |
| 22606 | if( rc!=1 ){ |
| 22607 | pFile->lastErrno = errno; |
| 22608 | return SQLITE_IOERR; |
| 22609 | } |
| 22610 | rc = fstat(fd, &statbuf); |
| 22611 | if( rc!=0 ){ |
| 22612 | pFile->lastErrno = errno; |
| @@ -22483,10 +22642,13 @@ | |
| 22642 | } |
| 22643 | memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey)); |
| 22644 | pLock->nRef = 1; |
| 22645 | pLock->cnt = 0; |
| 22646 | pLock->locktype = 0; |
| 22647 | #if defined(SQLITE_ENABLE_LOCKING_STYLE) |
| 22648 | pLock->sharedByte = 0; |
| 22649 | #endif |
| 22650 | pLock->pNext = lockList; |
| 22651 | pLock->pPrev = 0; |
| 22652 | if( lockList ) lockList->pPrev = pLock; |
| 22653 | lockList = pLock; |
| 22654 | }else{ |
| @@ -22547,11 +22709,11 @@ | |
| 22709 | OSTRACE1("No-transfer, same thread\n"); |
| 22710 | return SQLITE_OK; |
| 22711 | } |
| 22712 | if( pFile->locktype!=NO_LOCK ){ |
| 22713 | /* We cannot change ownership while we are holding a lock! */ |
| 22714 | return SQLITE_MISUSE_BKPT; |
| 22715 | } |
| 22716 | OSTRACE4("Transfer ownership of %d from %d to %d\n", |
| 22717 | pFile->h, pFile->tid, hSelf); |
| 22718 | pFile->tid = hSelf; |
| 22719 | if (pFile->pLock != NULL) { |
| @@ -22613,66 +22775,10 @@ | |
| 22775 | |
| 22776 | unixLeaveMutex(); |
| 22777 | OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved); |
| 22778 | |
| 22779 | *pResOut = reserved; |
| 22780 | return rc; |
| 22781 | } |
| 22782 | |
| 22783 | /* |
| 22784 | ** Lock the file with the lock specified by parameter locktype - one |
| @@ -22740,11 +22846,11 @@ | |
| 22846 | int rc = SQLITE_OK; |
| 22847 | unixFile *pFile = (unixFile*)id; |
| 22848 | struct unixLockInfo *pLock = pFile->pLock; |
| 22849 | struct flock lock; |
| 22850 | int s = 0; |
| 22851 | int tErrno = 0; |
| 22852 | |
| 22853 | assert( pFile ); |
| 22854 | OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, |
| 22855 | locktypeName(locktype), locktypeName(pFile->locktype), |
| 22856 | locktypeName(pLock->locktype), pLock->cnt , getpid()); |
| @@ -22836,12 +22942,15 @@ | |
| 22942 | if( locktype==SHARED_LOCK ){ |
| 22943 | assert( pLock->cnt==0 ); |
| 22944 | assert( pLock->locktype==0 ); |
| 22945 | |
| 22946 | /* Now get the read-lock */ |
| 22947 | lock.l_start = SHARED_FIRST; |
| 22948 | lock.l_len = SHARED_SIZE; |
| 22949 | if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){ |
| 22950 | tErrno = errno; |
| 22951 | } |
| 22952 | /* Drop the temporary PENDING lock */ |
| 22953 | lock.l_start = PENDING_BYTE; |
| 22954 | lock.l_len = 1L; |
| 22955 | lock.l_type = F_UNLCK; |
| 22956 | if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ |
| @@ -22877,20 +22986,21 @@ | |
| 22986 | assert( 0!=pFile->locktype ); |
| 22987 | lock.l_type = F_WRLCK; |
| 22988 | switch( locktype ){ |
| 22989 | case RESERVED_LOCK: |
| 22990 | lock.l_start = RESERVED_BYTE; |
| 22991 | break; |
| 22992 | case EXCLUSIVE_LOCK: |
| 22993 | lock.l_start = SHARED_FIRST; |
| 22994 | lock.l_len = SHARED_SIZE; |
| 22995 | break; |
| 22996 | default: |
| 22997 | assert(0); |
| 22998 | } |
| 22999 | s = fcntl(pFile->h, F_SETLK, &lock); |
| 23000 | if( s==(-1) ){ |
| 23001 | tErrno = errno; |
| 23002 | rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); |
| 23003 | if( IS_LOCK_ERROR(rc) ){ |
| 23004 | pFile->lastErrno = tErrno; |
| 23005 | } |
| 23006 | } |
| @@ -22976,17 +23086,23 @@ | |
| 23086 | ** Lower the locking level on file descriptor pFile to locktype. locktype |
| 23087 | ** must be either NO_LOCK or SHARED_LOCK. |
| 23088 | ** |
| 23089 | ** If the locking level of the file descriptor is already at or below |
| 23090 | ** the requested locking level, this routine is a no-op. |
| 23091 | ** |
| 23092 | ** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED |
| 23093 | ** the byte range is divided into 2 parts and the first part is unlocked then |
| 23094 | ** set to a read lock, then the other part is simply unlocked. This works |
| 23095 | ** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to |
| 23096 | ** remove the write lock on a region when a read lock is set. |
| 23097 | */ |
| 23098 | static int _posixUnlock(sqlite3_file *id, int locktype, int handleNFSUnlock){ |
| 23099 | unixFile *pFile = (unixFile*)id; |
| 23100 | struct unixLockInfo *pLock; |
| 23101 | struct flock lock; |
| 23102 | int rc = SQLITE_OK; |
| 23103 | int h; |
| 23104 | int tErrno; /* Error code from system call errors */ |
| 23105 | |
| 23106 | assert( pFile ); |
| 23107 | OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype, |
| 23108 | pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
| @@ -22994,11 +23110,11 @@ | |
| 23110 | assert( locktype<=SHARED_LOCK ); |
| 23111 | if( pFile->locktype<=locktype ){ |
| 23112 | return SQLITE_OK; |
| 23113 | } |
| 23114 | if( CHECK_THREADID(pFile) ){ |
| 23115 | return SQLITE_MISUSE_BKPT; |
| 23116 | } |
| 23117 | unixEnterMutex(); |
| 23118 | h = pFile->h; |
| 23119 | pLock = pFile->pLock; |
| 23120 | assert( pLock->cnt!=0 ); |
| @@ -23021,18 +23137,72 @@ | |
| 23137 | || pFile->dbUpdate==0 |
| 23138 | || pFile->transCntrChng==1 ); |
| 23139 | pFile->inNormalWrite = 0; |
| 23140 | #endif |
| 23141 | |
| 23142 | /* downgrading to a shared lock on NFS involves clearing the write lock |
| 23143 | ** before establishing the readlock - to avoid a race condition we downgrade |
| 23144 | ** the lock in 2 blocks, so that part of the range will be covered by a |
| 23145 | ** write lock until the rest is covered by a read lock: |
| 23146 | ** 1: [WWWWW] |
| 23147 | ** 2: [....W] |
| 23148 | ** 3: [RRRRW] |
| 23149 | ** 4: [RRRR.] |
| 23150 | */ |
| 23151 | if( locktype==SHARED_LOCK ){ |
| 23152 | if( handleNFSUnlock ){ |
| 23153 | off_t divSize = SHARED_SIZE - 1; |
| 23154 | |
| 23155 | lock.l_type = F_UNLCK; |
| 23156 | lock.l_whence = SEEK_SET; |
| 23157 | lock.l_start = SHARED_FIRST; |
| 23158 | lock.l_len = divSize; |
| 23159 | if( fcntl(h, F_SETLK, &lock)==(-1) ){ |
| 23160 | int tErrno = errno; |
| 23161 | rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); |
| 23162 | if( IS_LOCK_ERROR(rc) ){ |
| 23163 | pFile->lastErrno = tErrno; |
| 23164 | } |
| 23165 | goto end_unlock; |
| 23166 | } |
| 23167 | lock.l_type = F_RDLCK; |
| 23168 | lock.l_whence = SEEK_SET; |
| 23169 | lock.l_start = SHARED_FIRST; |
| 23170 | lock.l_len = divSize; |
| 23171 | if( fcntl(h, F_SETLK, &lock)==(-1) ){ |
| 23172 | int tErrno = errno; |
| 23173 | rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); |
| 23174 | if( IS_LOCK_ERROR(rc) ){ |
| 23175 | pFile->lastErrno = tErrno; |
| 23176 | } |
| 23177 | goto end_unlock; |
| 23178 | } |
| 23179 | lock.l_type = F_UNLCK; |
| 23180 | lock.l_whence = SEEK_SET; |
| 23181 | lock.l_start = SHARED_FIRST+divSize; |
| 23182 | lock.l_len = SHARED_SIZE-divSize; |
| 23183 | if( fcntl(h, F_SETLK, &lock)==(-1) ){ |
| 23184 | int tErrno = errno; |
| 23185 | rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); |
| 23186 | if( IS_LOCK_ERROR(rc) ){ |
| 23187 | pFile->lastErrno = tErrno; |
| 23188 | } |
| 23189 | goto end_unlock; |
| 23190 | } |
| 23191 | }else{ |
| 23192 | lock.l_type = F_RDLCK; |
| 23193 | lock.l_whence = SEEK_SET; |
| 23194 | lock.l_start = SHARED_FIRST; |
| 23195 | lock.l_len = SHARED_SIZE; |
| 23196 | if( fcntl(h, F_SETLK, &lock)==(-1) ){ |
| 23197 | int tErrno = errno; |
| 23198 | rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); |
| 23199 | if( IS_LOCK_ERROR(rc) ){ |
| 23200 | pFile->lastErrno = tErrno; |
| 23201 | } |
| 23202 | goto end_unlock; |
| 23203 | } |
| 23204 | } |
| 23205 | } |
| 23206 | lock.l_type = F_UNLCK; |
| 23207 | lock.l_whence = SEEK_SET; |
| 23208 | lock.l_start = PENDING_BYTE; |
| @@ -23094,10 +23264,21 @@ | |
| 23264 | end_unlock: |
| 23265 | unixLeaveMutex(); |
| 23266 | if( rc==SQLITE_OK ) pFile->locktype = locktype; |
| 23267 | return rc; |
| 23268 | } |
| 23269 | |
| 23270 | /* |
| 23271 | ** Lower the locking level on file descriptor pFile to locktype. locktype |
| 23272 | ** must be either NO_LOCK or SHARED_LOCK. |
| 23273 | ** |
| 23274 | ** If the locking level of the file descriptor is already at or below |
| 23275 | ** the requested locking level, this routine is a no-op. |
| 23276 | */ |
| 23277 | static int unixUnlock(sqlite3_file *id, int locktype){ |
| 23278 | return _posixUnlock(id, locktype, 0); |
| 23279 | } |
| 23280 | |
| 23281 | /* |
| 23282 | ** This function performs the parts of the "close file" operation |
| 23283 | ** common to all locking schemes. It closes the directory and file |
| 23284 | ** handles, if they are valid, and sets all fields of the unixFile |
| @@ -23806,11 +23987,11 @@ | |
| 23987 | /* |
| 23988 | ** The afpLockingContext structure contains all afp lock specific state |
| 23989 | */ |
| 23990 | typedef struct afpLockingContext afpLockingContext; |
| 23991 | struct afpLockingContext { |
| 23992 | int reserved; |
| 23993 | const char *dbPath; /* Name of the open file */ |
| 23994 | }; |
| 23995 | |
| 23996 | struct ByteRangeLockPB2 |
| 23997 | { |
| @@ -23883,13 +24064,18 @@ | |
| 24064 | |
| 24065 | SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); |
| 24066 | |
| 24067 | assert( pFile ); |
| 24068 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 24069 | if( context->reserved ){ |
| 24070 | *pResOut = 1; |
| 24071 | return SQLITE_OK; |
| 24072 | } |
| 24073 | unixEnterMutex(); /* Because pFile->pLock is shared across threads */ |
| 24074 | |
| 24075 | /* Check if a thread in this process holds such a lock */ |
| 24076 | if( pFile->pLock->locktype>SHARED_LOCK ){ |
| 24077 | reserved = 1; |
| 24078 | } |
| 24079 | |
| 24080 | /* Otherwise see if some other process holds it. |
| 24081 | */ |
| @@ -23907,10 +24093,11 @@ | |
| 24093 | if( IS_LOCK_ERROR(lrc) ){ |
| 24094 | rc=lrc; |
| 24095 | } |
| 24096 | } |
| 24097 | |
| 24098 | unixLeaveMutex(); |
| 24099 | OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved); |
| 24100 | |
| 24101 | *pResOut = reserved; |
| 24102 | return rc; |
| 24103 | } |
| @@ -23940,15 +24127,17 @@ | |
| 24127 | ** routine to lower a locking level. |
| 24128 | */ |
| 24129 | static int afpLock(sqlite3_file *id, int locktype){ |
| 24130 | int rc = SQLITE_OK; |
| 24131 | unixFile *pFile = (unixFile*)id; |
| 24132 | struct unixLockInfo *pLock = pFile->pLock; |
| 24133 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 24134 | |
| 24135 | assert( pFile ); |
| 24136 | OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h, |
| 24137 | locktypeName(locktype), locktypeName(pFile->locktype), |
| 24138 | locktypeName(pLock->locktype), pLock->cnt , getpid()); |
| 24139 | |
| 24140 | /* If there is already a lock of this type or more restrictive on the |
| 24141 | ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as |
| 24142 | ** unixEnterMutex() hasn't been called yet. |
| 24143 | */ |
| @@ -23957,10 +24146,13 @@ | |
| 24146 | locktypeName(locktype)); |
| 24147 | return SQLITE_OK; |
| 24148 | } |
| 24149 | |
| 24150 | /* Make sure the locking sequence is correct |
| 24151 | ** (1) We never move from unlocked to anything higher than shared lock. |
| 24152 | ** (2) SQLite never explicitly requests a pendig lock. |
| 24153 | ** (3) A shared lock is always held when a reserve lock is requested. |
| 24154 | */ |
| 24155 | assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); |
| 24156 | assert( locktype!=PENDING_LOCK ); |
| 24157 | assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); |
| 24158 | |
| @@ -23972,10 +24164,36 @@ | |
| 24164 | */ |
| 24165 | rc = transferOwnership(pFile); |
| 24166 | if( rc!=SQLITE_OK ){ |
| 24167 | unixLeaveMutex(); |
| 24168 | return rc; |
| 24169 | } |
| 24170 | pLock = pFile->pLock; |
| 24171 | |
| 24172 | /* If some thread using this PID has a lock via a different unixFile* |
| 24173 | ** handle that precludes the requested lock, return BUSY. |
| 24174 | */ |
| 24175 | if( (pFile->locktype!=pLock->locktype && |
| 24176 | (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) |
| 24177 | ){ |
| 24178 | rc = SQLITE_BUSY; |
| 24179 | goto afp_end_lock; |
| 24180 | } |
| 24181 | |
| 24182 | /* If a SHARED lock is requested, and some thread using this PID already |
| 24183 | ** has a SHARED or RESERVED lock, then increment reference counts and |
| 24184 | ** return SQLITE_OK. |
| 24185 | */ |
| 24186 | if( locktype==SHARED_LOCK && |
| 24187 | (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ |
| 24188 | assert( locktype==SHARED_LOCK ); |
| 24189 | assert( pFile->locktype==0 ); |
| 24190 | assert( pLock->cnt>0 ); |
| 24191 | pFile->locktype = SHARED_LOCK; |
| 24192 | pLock->cnt++; |
| 24193 | pFile->pOpen->nLock++; |
| 24194 | goto afp_end_lock; |
| 24195 | } |
| 24196 | |
| 24197 | /* A PENDING lock is needed before acquiring a SHARED lock and before |
| 24198 | ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will |
| 24199 | ** be released. |
| @@ -23993,19 +24211,23 @@ | |
| 24211 | |
| 24212 | /* If control gets to this point, then actually go ahead and make |
| 24213 | ** operating system calls for the specified lock. |
| 24214 | */ |
| 24215 | if( locktype==SHARED_LOCK ){ |
| 24216 | int lrc1, lrc2, lrc1Errno; |
| 24217 | long lk, mask; |
| 24218 | |
| 24219 | assert( pLock->cnt==0 ); |
| 24220 | assert( pLock->locktype==0 ); |
| 24221 | |
| 24222 | mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff; |
| 24223 | /* Now get the read-lock SHARED_LOCK */ |
| 24224 | /* note that the quality of the randomness doesn't matter that much */ |
| 24225 | lk = random(); |
| 24226 | pLock->sharedByte = (lk & mask)%(SHARED_SIZE - 1); |
| 24227 | lrc1 = afpSetLock(context->dbPath, pFile, |
| 24228 | SHARED_FIRST+pLock->sharedByte, 1, 1); |
| 24229 | if( IS_LOCK_ERROR(lrc1) ){ |
| 24230 | lrc1Errno = pFile->lastErrno; |
| 24231 | } |
| 24232 | /* Drop the temporary PENDING lock */ |
| 24233 | lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); |
| @@ -24020,11 +24242,16 @@ | |
| 24242 | } else if( lrc1 != SQLITE_OK ) { |
| 24243 | rc = lrc1; |
| 24244 | } else { |
| 24245 | pFile->locktype = SHARED_LOCK; |
| 24246 | pFile->pOpen->nLock++; |
| 24247 | pLock->cnt = 1; |
| 24248 | } |
| 24249 | }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ |
| 24250 | /* We are trying for an exclusive lock but another thread in this |
| 24251 | ** same process is still holding a shared lock. */ |
| 24252 | rc = SQLITE_BUSY; |
| 24253 | }else{ |
| 24254 | /* The request was for a RESERVED or EXCLUSIVE lock. It is |
| 24255 | ** assumed that there is a SHARED or greater lock on the file |
| 24256 | ** already. |
| 24257 | */ |
| @@ -24031,25 +24258,28 @@ | |
| 24258 | int failed = 0; |
| 24259 | assert( 0!=pFile->locktype ); |
| 24260 | if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) { |
| 24261 | /* Acquire a RESERVED lock */ |
| 24262 | failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); |
| 24263 | if( !failed ){ |
| 24264 | context->reserved = 1; |
| 24265 | } |
| 24266 | } |
| 24267 | if (!failed && locktype == EXCLUSIVE_LOCK) { |
| 24268 | /* Acquire an EXCLUSIVE lock */ |
| 24269 | |
| 24270 | /* Remove the shared lock before trying the range. we'll need to |
| 24271 | ** reestablish the shared lock if we can't get the afpUnlock |
| 24272 | */ |
| 24273 | if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + |
| 24274 | pLock->sharedByte, 1, 0)) ){ |
| 24275 | int failed2 = SQLITE_OK; |
| 24276 | /* now attemmpt to get the exclusive lock range */ |
| 24277 | failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, |
| 24278 | SHARED_SIZE, 1); |
| 24279 | if( failed && (failed2 = afpSetLock(context->dbPath, pFile, |
| 24280 | SHARED_FIRST + pLock->sharedByte, 1, 1)) ){ |
| 24281 | /* Can't reestablish the shared lock. Sqlite can't deal, this is |
| 24282 | ** a critical I/O error |
| 24283 | */ |
| 24284 | rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : |
| 24285 | SQLITE_IOERR_LOCK; |
| @@ -24064,12 +24294,14 @@ | |
| 24294 | } |
| 24295 | } |
| 24296 | |
| 24297 | if( rc==SQLITE_OK ){ |
| 24298 | pFile->locktype = locktype; |
| 24299 | pLock->locktype = locktype; |
| 24300 | }else if( locktype==EXCLUSIVE_LOCK ){ |
| 24301 | pFile->locktype = PENDING_LOCK; |
| 24302 | pLock->locktype = PENDING_LOCK; |
| 24303 | } |
| 24304 | |
| 24305 | afp_end_lock: |
| 24306 | unixLeaveMutex(); |
| 24307 | OSTRACE4("LOCK %d %s %s (afp)\n", pFile->h, locktypeName(locktype), |
| @@ -24085,67 +24317,116 @@ | |
| 24317 | ** the requested locking level, this routine is a no-op. |
| 24318 | */ |
| 24319 | static int afpUnlock(sqlite3_file *id, int locktype) { |
| 24320 | int rc = SQLITE_OK; |
| 24321 | unixFile *pFile = (unixFile*)id; |
| 24322 | struct unixLockInfo *pLock; |
| 24323 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 24324 | int skipShared = 0; |
| 24325 | #ifdef SQLITE_TEST |
| 24326 | int h = pFile->h; |
| 24327 | #endif |
| 24328 | |
| 24329 | assert( pFile ); |
| 24330 | OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, locktype, |
| 24331 | pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
| 24332 | |
| 24333 | assert( locktype<=SHARED_LOCK ); |
| 24334 | if( pFile->locktype<=locktype ){ |
| 24335 | return SQLITE_OK; |
| 24336 | } |
| 24337 | if( CHECK_THREADID(pFile) ){ |
| 24338 | return SQLITE_MISUSE_BKPT; |
| 24339 | } |
| 24340 | unixEnterMutex(); |
| 24341 | pLock = pFile->pLock; |
| 24342 | assert( pLock->cnt!=0 ); |
| 24343 | if( pFile->locktype>SHARED_LOCK ){ |
| 24344 | assert( pLock->locktype==pFile->locktype ); |
| 24345 | SimulateIOErrorBenign(1); |
| 24346 | SimulateIOError( h=(-1) ) |
| 24347 | SimulateIOErrorBenign(0); |
| 24348 | |
| 24349 | #ifndef NDEBUG |
| 24350 | /* When reducing a lock such that other processes can start |
| 24351 | ** reading the database file again, make sure that the |
| 24352 | ** transaction counter was updated if any part of the database |
| 24353 | ** file changed. If the transaction counter is not updated, |
| 24354 | ** other connections to the same file might not realize that |
| 24355 | ** the file has changed and hence might not know to flush their |
| 24356 | ** cache. The use of a stale cache can lead to database corruption. |
| 24357 | */ |
| 24358 | assert( pFile->inNormalWrite==0 |
| 24359 | || pFile->dbUpdate==0 |
| 24360 | || pFile->transCntrChng==1 ); |
| 24361 | pFile->inNormalWrite = 0; |
| 24362 | #endif |
| 24363 | |
| 24364 | if( pFile->locktype==EXCLUSIVE_LOCK ){ |
| 24365 | rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); |
| 24366 | if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1) ){ |
| 24367 | /* only re-establish the shared lock if necessary */ |
| 24368 | int sharedLockByte = SHARED_FIRST+pLock->sharedByte; |
| 24369 | rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1); |
| 24370 | } else { |
| 24371 | skipShared = 1; |
| 24372 | } |
| 24373 | } |
| 24374 | if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){ |
| 24375 | rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); |
| 24376 | } |
| 24377 | if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK && context->reserved ){ |
| 24378 | rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); |
| 24379 | if( !rc ){ |
| 24380 | context->reserved = 0; |
| 24381 | } |
| 24382 | } |
| 24383 | if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1)){ |
| 24384 | pLock->locktype = SHARED_LOCK; |
| 24385 | } |
| 24386 | } |
| 24387 | if( rc==SQLITE_OK && locktype==NO_LOCK ){ |
| 24388 | |
| 24389 | /* Decrement the shared lock counter. Release the lock using an |
| 24390 | ** OS call only when all threads in this same process have released |
| 24391 | ** the lock. |
| 24392 | */ |
| 24393 | unsigned long long sharedLockByte = SHARED_FIRST+pLock->sharedByte; |
| 24394 | pLock->cnt--; |
| 24395 | if( pLock->cnt==0 ){ |
| 24396 | SimulateIOErrorBenign(1); |
| 24397 | SimulateIOError( h=(-1) ) |
| 24398 | SimulateIOErrorBenign(0); |
| 24399 | if( !skipShared ){ |
| 24400 | rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); |
| 24401 | } |
| 24402 | if( !rc ){ |
| 24403 | pLock->locktype = NO_LOCK; |
| 24404 | pFile->locktype = NO_LOCK; |
| 24405 | } |
| 24406 | } |
| 24407 | if( rc==SQLITE_OK ){ |
| 24408 | struct unixOpenCnt *pOpen = pFile->pOpen; |
| 24409 | |
| 24410 | pOpen->nLock--; |
| 24411 | assert( pOpen->nLock>=0 ); |
| 24412 | if( pOpen->nLock==0 ){ |
| 24413 | rc = closePendingFds(pFile); |
| 24414 | } |
| 24415 | } |
| 24416 | } |
| 24417 | |
| 24418 | unixLeaveMutex(); |
| 24419 | if( rc==SQLITE_OK ) pFile->locktype = locktype; |
| 24420 | return rc; |
| 24421 | } |
| 24422 | |
| 24423 | /* |
| 24424 | ** Close a file & cleanup AFP specific locking context |
| 24425 | */ |
| 24426 | static int afpClose(sqlite3_file *id) { |
| 24427 | int rc = SQLITE_OK; |
| 24428 | if( id ){ |
| 24429 | unixFile *pFile = (unixFile*)id; |
| 24430 | afpUnlock(id, NO_LOCK); |
| 24431 | unixEnterMutex(); |
| 24432 | if( pFile->pOpen && pFile->pOpen->nLock ){ |
| @@ -24154,16 +24435,17 @@ | |
| 24435 | ** descriptor to pOpen->aPending. It will be automatically closed when |
| 24436 | ** the last lock is cleared. |
| 24437 | */ |
| 24438 | setPendingFd(pFile); |
| 24439 | } |
| 24440 | releaseLockInfo(pFile->pLock); |
| 24441 | releaseOpenCnt(pFile->pOpen); |
| 24442 | sqlite3_free(pFile->lockingContext); |
| 24443 | rc = closeUnixFile(id); |
| 24444 | unixLeaveMutex(); |
| 24445 | } |
| 24446 | return rc; |
| 24447 | } |
| 24448 | |
| 24449 | #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ |
| 24450 | /* |
| 24451 | ** The code above is the AFP lock implementation. The code is specific |
| @@ -24172,10 +24454,33 @@ | |
| 24454 | ** VFS is not available. |
| 24455 | ** |
| 24456 | ********************* End of the AFP lock implementation ********************** |
| 24457 | ******************************************************************************/ |
| 24458 | |
| 24459 | /****************************************************************************** |
| 24460 | *************************** Begin NFS Locking ********************************/ |
| 24461 | |
| 24462 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 24463 | /* |
| 24464 | ** Lower the locking level on file descriptor pFile to locktype. locktype |
| 24465 | ** must be either NO_LOCK or SHARED_LOCK. |
| 24466 | ** |
| 24467 | ** If the locking level of the file descriptor is already at or below |
| 24468 | ** the requested locking level, this routine is a no-op. |
| 24469 | */ |
| 24470 | static int nfsUnlock(sqlite3_file *id, int locktype){ |
| 24471 | return _posixUnlock(id, locktype, 1); |
| 24472 | } |
| 24473 | |
| 24474 | #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ |
| 24475 | /* |
| 24476 | ** The code above is the NFS lock implementation. The code is specific |
| 24477 | ** to MacOSX and does not work on other unix platforms. No alternative |
| 24478 | ** is available. |
| 24479 | ** |
| 24480 | ********************* End of the NFS lock implementation ********************** |
| 24481 | ******************************************************************************/ |
| 24482 | |
| 24483 | /****************************************************************************** |
| 24484 | **************** Non-locking sqlite3_file methods ***************************** |
| 24485 | ** |
| 24486 | ** The next division contains implementations for all methods of the |
| @@ -24198,11 +24503,13 @@ | |
| 24503 | ** To avoid stomping the errno value on a failed read the lastErrno value |
| 24504 | ** is set before returning. |
| 24505 | */ |
| 24506 | static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ |
| 24507 | int got; |
| 24508 | #if (!defined(USE_PREAD) && !defined(USE_PREAD64)) |
| 24509 | i64 newOffset; |
| 24510 | #endif |
| 24511 | TIMER_START; |
| 24512 | #if defined(USE_PREAD) |
| 24513 | got = pread(id->h, pBuf, cnt, offset); |
| 24514 | SimulateIOError( got = -1 ); |
| 24515 | #elif defined(USE_PREAD64) |
| @@ -24272,11 +24579,13 @@ | |
| 24579 | ** To avoid stomping the errno value on a failed write the lastErrno value |
| 24580 | ** is set before returning. |
| 24581 | */ |
| 24582 | static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ |
| 24583 | int got; |
| 24584 | #if (!defined(USE_PREAD) && !defined(USE_PREAD64)) |
| 24585 | i64 newOffset; |
| 24586 | #endif |
| 24587 | TIMER_START; |
| 24588 | #if defined(USE_PREAD) |
| 24589 | got = pwrite(id->h, pBuf, cnt, offset); |
| 24590 | #elif defined(USE_PREAD64) |
| 24591 | got = pwrite64(id->h, pBuf, cnt, offset); |
| @@ -24466,10 +24775,15 @@ | |
| 24775 | ** It'd be better to detect fullfsync support once and avoid |
| 24776 | ** the fcntl call every time sync is called. |
| 24777 | */ |
| 24778 | if( rc ) rc = fsync(fd); |
| 24779 | |
| 24780 | #elif defined(__APPLE__) |
| 24781 | /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly |
| 24782 | ** so currently we default to the macro that redefines fdatasync to fsync |
| 24783 | */ |
| 24784 | rc = fsync(fd); |
| 24785 | #else |
| 24786 | rc = fdatasync(fd); |
| 24787 | #if OS_VXWORKS |
| 24788 | if( rc==-1 && errno==ENOTSUP ){ |
| 24789 | rc = fsync(fd); |
| @@ -24800,27 +25114,10 @@ | |
| 25114 | afpUnlock, /* xUnlock method */ |
| 25115 | afpCheckReservedLock /* xCheckReservedLock method */ |
| 25116 | ) |
| 25117 | #endif |
| 25118 | |
| 25119 | /* |
| 25120 | ** The proxy locking method is a "super-method" in the sense that it |
| 25121 | ** opens secondary file descriptors for the conch and lock files and |
| 25122 | ** it uses proxy, dot-file, AFP, and flock() locking methods on those |
| 25123 | ** secondary files. For this reason, the division that implements |
| @@ -24841,10 +25138,21 @@ | |
| 25138 | proxyUnlock, /* xUnlock method */ |
| 25139 | proxyCheckReservedLock /* xCheckReservedLock method */ |
| 25140 | ) |
| 25141 | #endif |
| 25142 | |
| 25143 | /* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */ |
| 25144 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 25145 | IOMETHODS( |
| 25146 | nfsIoFinder, /* Finder function name */ |
| 25147 | nfsIoMethods, /* sqlite3_io_methods object name */ |
| 25148 | unixClose, /* xClose method */ |
| 25149 | unixLock, /* xLock method */ |
| 25150 | nfsUnlock, /* xUnlock method */ |
| 25151 | unixCheckReservedLock /* xCheckReservedLock method */ |
| 25152 | ) |
| 25153 | #endif |
| 25154 | |
| 25155 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 25156 | /* |
| 25157 | ** This "finder" function attempts to determine the best locking strategy |
| 25158 | ** for the database file "filePath". It then returns the sqlite3_io_methods |
| @@ -24861,15 +25169,11 @@ | |
| 25169 | const sqlite3_io_methods *pMethods; /* Appropriate locking method */ |
| 25170 | } aMap[] = { |
| 25171 | { "hfs", &posixIoMethods }, |
| 25172 | { "ufs", &posixIoMethods }, |
| 25173 | { "afpfs", &afpIoMethods }, |
| 25174 | { "smbfs", &afpIoMethods }, |
| 25175 | { "webdav", &nolockIoMethods }, |
| 25176 | { 0, 0 } |
| 25177 | }; |
| 25178 | int i; |
| 25179 | struct statfs fsInfo; |
| @@ -24898,12 +25202,15 @@ | |
| 25202 | lockInfo.l_len = 1; |
| 25203 | lockInfo.l_start = 0; |
| 25204 | lockInfo.l_whence = SEEK_SET; |
| 25205 | lockInfo.l_type = F_RDLCK; |
| 25206 | if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { |
| 25207 | if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){ |
| 25208 | return &nfsIoMethods; |
| 25209 | } else { |
| 25210 | return &posixIoMethods; |
| 25211 | } |
| 25212 | }else{ |
| 25213 | return &dotlockIoMethods; |
| 25214 | } |
| 25215 | } |
| 25216 | static const sqlite3_io_methods |
| @@ -25010,11 +25317,15 @@ | |
| 25317 | ** zFilename remains valid until file is closed, to support */ |
| 25318 | pNew->lockingContext = (void*)zFilename; |
| 25319 | #endif |
| 25320 | } |
| 25321 | |
| 25322 | if( pLockingStyle == &posixIoMethods |
| 25323 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 25324 | || pLockingStyle == &nfsIoMethods |
| 25325 | #endif |
| 25326 | ){ |
| 25327 | unixEnterMutex(); |
| 25328 | rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); |
| 25329 | if( rc!=SQLITE_OK ){ |
| 25330 | /* If an error occured in findLockInfo(), close the file descriptor |
| 25331 | ** immediately, before releasing the mutex. findLockInfo() may fail |
| @@ -25052,13 +25363,19 @@ | |
| 25363 | }else{ |
| 25364 | /* NB: zFilename exists and remains valid until the file is closed |
| 25365 | ** according to requirement F11141. So we do not need to make a |
| 25366 | ** copy of the filename. */ |
| 25367 | pCtx->dbPath = zFilename; |
| 25368 | pCtx->reserved = 0; |
| 25369 | srandomdev(); |
| 25370 | unixEnterMutex(); |
| 25371 | rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); |
| 25372 | if( rc!=SQLITE_OK ){ |
| 25373 | sqlite3_free(pNew->lockingContext); |
| 25374 | close(h); |
| 25375 | h = -1; |
| 25376 | } |
| 25377 | unixLeaveMutex(); |
| 25378 | } |
| 25379 | } |
| 25380 | #endif |
| 25381 | |
| @@ -25103,10 +25420,12 @@ | |
| 25420 | #endif |
| 25421 | |
| 25422 | pNew->lastErrno = 0; |
| 25423 | #if OS_VXWORKS |
| 25424 | if( rc!=SQLITE_OK ){ |
| 25425 | if( h>=0 ) close(h); |
| 25426 | h = -1; |
| 25427 | unlink(zFilename); |
| 25428 | isDelete = 0; |
| 25429 | } |
| 25430 | pNew->isDelete = isDelete; |
| 25431 | #endif |
| @@ -25146,11 +25465,11 @@ | |
| 25465 | #endif |
| 25466 | OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname); |
| 25467 | } |
| 25468 | } |
| 25469 | *pFd = fd; |
| 25470 | return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN_BKPT); |
| 25471 | } |
| 25472 | |
| 25473 | /* |
| 25474 | ** Create a temporary file name in zBuf. zBuf must be allocated |
| 25475 | ** by the calling process and must be big enough to hold at least |
| @@ -25255,20 +25574,21 @@ | |
| 25574 | ** descriptor on the same path, fail, and return an error to SQLite. |
| 25575 | ** |
| 25576 | ** Even if a subsequent open() call does succeed, the consequences of |
| 25577 | ** not searching for a resusable file descriptor are not dire. */ |
| 25578 | if( 0==stat(zPath, &sStat) ){ |
| 25579 | struct unixOpenCnt *pOpen; |
| 25580 | |
| 25581 | unixEnterMutex(); |
| 25582 | pOpen = openList; |
| 25583 | while( pOpen && (pOpen->fileId.dev!=sStat.st_dev |
| 25584 | || pOpen->fileId.ino!=sStat.st_ino) ){ |
| 25585 | pOpen = pOpen->pNext; |
| 25586 | } |
| 25587 | if( pOpen ){ |
| 25588 | UnixUnusedFd **pp; |
| 25589 | for(pp=&pOpen->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); |
| 25590 | pUnused = *pp; |
| 25591 | if( pUnused ){ |
| 25592 | *pp = pUnused->pNext; |
| 25593 | } |
| 25594 | } |
| @@ -25318,10 +25638,13 @@ | |
| 25638 | int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); |
| 25639 | int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); |
| 25640 | int isCreate = (flags & SQLITE_OPEN_CREATE); |
| 25641 | int isReadonly = (flags & SQLITE_OPEN_READONLY); |
| 25642 | int isReadWrite = (flags & SQLITE_OPEN_READWRITE); |
| 25643 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 25644 | int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY); |
| 25645 | #endif |
| 25646 | |
| 25647 | /* If creating a master or main-file journal, this function will open |
| 25648 | ** a file-descriptor on the directory too. The first time unixSync() |
| 25649 | ** is called the directory file descriptor will be fsync()ed and close()d. |
| 25650 | */ |
| @@ -25405,11 +25728,11 @@ | |
| 25728 | flags |= SQLITE_OPEN_READONLY; |
| 25729 | openFlags |= O_RDONLY; |
| 25730 | fd = open(zName, openFlags, openMode); |
| 25731 | } |
| 25732 | if( fd<0 ){ |
| 25733 | rc = SQLITE_CANTOPEN_BKPT; |
| 25734 | goto open_finished; |
| 25735 | } |
| 25736 | } |
| 25737 | assert( fd>=0 ); |
| 25738 | if( pOutFlags ){ |
| @@ -25451,12 +25774,29 @@ | |
| 25774 | fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 25775 | #endif |
| 25776 | |
| 25777 | noLock = eType!=SQLITE_OPEN_MAIN_DB; |
| 25778 | |
| 25779 | |
| 25780 | #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE |
| 25781 | struct statfs fsInfo; |
| 25782 | if( fstatfs(fd, &fsInfo) == -1 ){ |
| 25783 | ((unixFile*)pFile)->lastErrno = errno; |
| 25784 | if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */ |
| 25785 | close(fd); /* silently leak if fail, in error */ |
| 25786 | return SQLITE_IOERR_ACCESS; |
| 25787 | } |
| 25788 | if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { |
| 25789 | ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; |
| 25790 | } |
| 25791 | #endif |
| 25792 | |
| 25793 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 25794 | #if SQLITE_PREFER_PROXY_LOCKING |
| 25795 | isAutoProxy = 1; |
| 25796 | #endif |
| 25797 | if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){ |
| 25798 | char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); |
| 25799 | int useProxy = 0; |
| 25800 | |
| 25801 | /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means |
| 25802 | ** never use proxy, NULL means use proxy for non-local files only. */ |
| @@ -25484,10 +25824,18 @@ | |
| 25824 | } |
| 25825 | if( useProxy ){ |
| 25826 | rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); |
| 25827 | if( rc==SQLITE_OK ){ |
| 25828 | rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); |
| 25829 | if( rc!=SQLITE_OK ){ |
| 25830 | /* Use unixClose to clean up the resources added in fillInUnixFile |
| 25831 | ** and clear all the structure's references. Specifically, |
| 25832 | ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op |
| 25833 | */ |
| 25834 | unixClose(pFile); |
| 25835 | return rc; |
| 25836 | } |
| 25837 | } |
| 25838 | goto open_finished; |
| 25839 | } |
| 25840 | } |
| 25841 | #endif |
| @@ -25604,11 +25952,11 @@ | |
| 25952 | if( zPath[0]=='/' ){ |
| 25953 | sqlite3_snprintf(nOut, zOut, "%s", zPath); |
| 25954 | }else{ |
| 25955 | int nCwd; |
| 25956 | if( getcwd(zOut, nOut-1)==0 ){ |
| 25957 | return SQLITE_CANTOPEN_BKPT; |
| 25958 | } |
| 25959 | nCwd = (int)strlen(zOut); |
| 25960 | sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath); |
| 25961 | } |
| 25962 | return SQLITE_OK; |
| @@ -25911,15 +26259,10 @@ | |
| 26259 | ** The proxy file - a single-byte file used for all advisory file locks |
| 26260 | ** normally taken on the database file. This allows for safe sharing |
| 26261 | ** of the database file for multiple readers and writers on the same |
| 26262 | ** host (the conch ensures that they all use the same local lock file). |
| 26263 | ** |
| 26264 | ** Requesting the lock proxy does not immediately take the conch, it is |
| 26265 | ** only taken when the first request to lock database file is made. |
| 26266 | ** This matches the semantics of the traditional locking behavior, where |
| 26267 | ** opening a connection to a database file does not take a lock on it. |
| 26268 | ** The shared lock and an open file descriptor are maintained until |
| @@ -25941,14 +26284,10 @@ | |
| 26284 | ** SQLITE_PROXY_DEBUG |
| 26285 | ** |
| 26286 | ** Enables the logging of error messages during host id file |
| 26287 | ** retrieval and creation |
| 26288 | ** |
| 26289 | ** LOCKPROXYDIR |
| 26290 | ** |
| 26291 | ** Overrides the default directory used for lock proxy files that |
| 26292 | ** are named automatically via the ":auto:" setting |
| 26293 | ** |
| @@ -25969,15 +26308,10 @@ | |
| 26308 | /* |
| 26309 | ** Proxy locking is only available on MacOSX |
| 26310 | */ |
| 26311 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 26312 | |
| 26313 | /* |
| 26314 | ** The proxyLockingContext has the path and file structures for the remote |
| 26315 | ** and local proxy files in it |
| 26316 | */ |
| 26317 | typedef struct proxyLockingContext proxyLockingContext; |
| @@ -25985,138 +26319,20 @@ | |
| 26319 | unixFile *conchFile; /* Open conch file */ |
| 26320 | char *conchFilePath; /* Name of the conch file */ |
| 26321 | unixFile *lockProxy; /* Open proxy lock file */ |
| 26322 | char *lockProxyPath; /* Name of the proxy lock file */ |
| 26323 | char *dbPath; /* Name of the open file */ |
| 26324 | int conchHeld; /* 1 if the conch is held, -1 if lockless */ |
| 26325 | void *oldLockingContext; /* Original lockingcontext to restore on close */ |
| 26326 | sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ |
| 26327 | }; |
| 26328 | |
| 26329 | /* |
| 26330 | ** The proxy lock file path for the database at dbPath is written into lPath, |
| 26331 | ** which must point to valid, writable memory large enough for a maxLen length |
| 26332 | ** file path. |
| 26333 | */ |
| 26334 | static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ |
| 26335 | int len; |
| 26336 | int dbLen; |
| 26337 | int i; |
| 26338 | |
| @@ -26123,25 +26339,16 @@ | |
| 26339 | #ifdef LOCKPROXYDIR |
| 26340 | len = strlcpy(lPath, LOCKPROXYDIR, maxLen); |
| 26341 | #else |
| 26342 | # ifdef _CS_DARWIN_USER_TEMP_DIR |
| 26343 | { |
| 26344 | if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ |
| 26345 | OSTRACE4("GETLOCKPATH failed %s errno=%d pid=%d\n", |
| 26346 | lPath, errno, getpid()); |
| 26347 | return SQLITE_IOERR_LOCK; |
| 26348 | } |
| 26349 | len = strlcat(lPath, "sqliteplocks", maxLen); |
| 26350 | } |
| 26351 | # else |
| 26352 | len = strlcpy(lPath, "/tmp/", maxLen); |
| 26353 | # endif |
| 26354 | #endif |
| @@ -26156,213 +26363,535 @@ | |
| 26363 | char c = dbPath[i]; |
| 26364 | lPath[i+len] = (c=='/')?'_':c; |
| 26365 | } |
| 26366 | lPath[i+len]='\0'; |
| 26367 | strlcat(lPath, ":auto:", maxLen); |
| 26368 | OSTRACE3("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()); |
| 26369 | return SQLITE_OK; |
| 26370 | } |
| 26371 | |
| 26372 | /* |
| 26373 | ** Creates the lock file and any missing directories in lockPath |
| 26374 | */ |
| 26375 | static int proxyCreateLockPath(const char *lockPath){ |
| 26376 | int i, len; |
| 26377 | char buf[MAXPATHLEN]; |
| 26378 | int start = 0; |
| 26379 | |
| 26380 | assert(lockPath!=NULL); |
| 26381 | /* try to create all the intermediate directories */ |
| 26382 | len = (int)strlen(lockPath); |
| 26383 | buf[0] = lockPath[0]; |
| 26384 | for( i=1; i<len; i++ ){ |
| 26385 | if( lockPath[i] == '/' && (i - start > 0) ){ |
| 26386 | /* only mkdir if leaf dir != "." or "/" or ".." */ |
| 26387 | if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') |
| 26388 | || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){ |
| 26389 | buf[i]='\0'; |
| 26390 | if( mkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ |
| 26391 | int err=errno; |
| 26392 | if( err!=EEXIST ) { |
| 26393 | OSTRACE5("CREATELOCKPATH FAILED creating %s, " |
| 26394 | "'%s' proxy lock path=%s pid=%d\n", |
| 26395 | buf, strerror(err), lockPath, getpid()); |
| 26396 | return err; |
| 26397 | } |
| 26398 | } |
| 26399 | } |
| 26400 | start=i+1; |
| 26401 | } |
| 26402 | buf[i] = lockPath[i]; |
| 26403 | } |
| 26404 | OSTRACE3("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()); |
| 26405 | return 0; |
| 26406 | } |
| 26407 | |
| 26408 | /* |
| 26409 | ** Create a new VFS file descriptor (stored in memory obtained from |
| 26410 | ** sqlite3_malloc) and open the file named "path" in the file descriptor. |
| 26411 | ** |
| 26412 | ** The caller is responsible not only for closing the file descriptor |
| 26413 | ** but also for freeing the memory associated with the file descriptor. |
| 26414 | */ |
| 26415 | static int proxyCreateUnixFile( |
| 26416 | const char *path, /* path for the new unixFile */ |
| 26417 | unixFile **ppFile, /* unixFile created and returned by ref */ |
| 26418 | int islockfile /* if non zero missing dirs will be created */ |
| 26419 | ) { |
| 26420 | int fd = -1; |
| 26421 | int dirfd = -1; |
| 26422 | unixFile *pNew; |
| 26423 | int rc = SQLITE_OK; |
| 26424 | int openFlags = O_RDWR | O_CREAT; |
| 26425 | sqlite3_vfs dummyVfs; |
| 26426 | int terrno = 0; |
| 26427 | UnixUnusedFd *pUnused = NULL; |
| 26428 | |
| 26429 | /* 1. first try to open/create the file |
| 26430 | ** 2. if that fails, and this is a lock file (not-conch), try creating |
| 26431 | ** the parent directories and then try again. |
| 26432 | ** 3. if that fails, try to open the file read-only |
| 26433 | ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file |
| 26434 | */ |
| 26435 | pUnused = findReusableFd(path, openFlags); |
| 26436 | if( pUnused ){ |
| 26437 | fd = pUnused->fd; |
| 26438 | }else{ |
| 26439 | pUnused = sqlite3_malloc(sizeof(*pUnused)); |
| 26440 | if( !pUnused ){ |
| 26441 | return SQLITE_NOMEM; |
| 26442 | } |
| 26443 | } |
| 26444 | if( fd<0 ){ |
| 26445 | fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26446 | terrno = errno; |
| 26447 | if( fd<0 && errno==ENOENT && islockfile ){ |
| 26448 | if( proxyCreateLockPath(path) == SQLITE_OK ){ |
| 26449 | fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26450 | } |
| 26451 | } |
| 26452 | } |
| 26453 | if( fd<0 ){ |
| 26454 | openFlags = O_RDONLY; |
| 26455 | fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26456 | terrno = errno; |
| 26457 | } |
| 26458 | if( fd<0 ){ |
| 26459 | if( islockfile ){ |
| 26460 | return SQLITE_BUSY; |
| 26461 | } |
| 26462 | switch (terrno) { |
| 26463 | case EACCES: |
| 26464 | return SQLITE_PERM; |
| 26465 | case EIO: |
| 26466 | return SQLITE_IOERR_LOCK; /* even though it is the conch */ |
| 26467 | default: |
| 26468 | return SQLITE_CANTOPEN_BKPT; |
| 26469 | } |
| 26470 | } |
| 26471 | |
| 26472 | pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew)); |
| 26473 | if( pNew==NULL ){ |
| 26474 | rc = SQLITE_NOMEM; |
| 26475 | goto end_create_proxy; |
| 26476 | } |
| 26477 | memset(pNew, 0, sizeof(unixFile)); |
| 26478 | pNew->openFlags = openFlags; |
| 26479 | dummyVfs.pAppData = (void*)&autolockIoFinder; |
| 26480 | pUnused->fd = fd; |
| 26481 | pUnused->flags = openFlags; |
| 26482 | pNew->pUnused = pUnused; |
| 26483 | |
| 26484 | rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0); |
| 26485 | if( rc==SQLITE_OK ){ |
| 26486 | *ppFile = pNew; |
| 26487 | return SQLITE_OK; |
| 26488 | } |
| 26489 | end_create_proxy: |
| 26490 | close(fd); /* silently leak fd if error, we're already in error */ |
| 26491 | sqlite3_free(pNew); |
| 26492 | sqlite3_free(pUnused); |
| 26493 | return rc; |
| 26494 | } |
| 26495 | |
| 26496 | #ifdef SQLITE_TEST |
| 26497 | /* simulate multiple hosts by creating unique hostid file paths */ |
| 26498 | SQLITE_API int sqlite3_hostid_num = 0; |
| 26499 | #endif |
| 26500 | |
| 26501 | #define PROXY_HOSTIDLEN 16 /* conch file host id length */ |
| 26502 | |
| 26503 | /* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN |
| 26504 | ** bytes of writable memory. |
| 26505 | */ |
| 26506 | static int proxyGetHostID(unsigned char *pHostID, int *pError){ |
| 26507 | struct timespec timeout = {1, 0}; /* 1 sec timeout */ |
| 26508 | |
| 26509 | assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); |
| 26510 | memset(pHostID, 0, PROXY_HOSTIDLEN); |
| 26511 | if( gethostuuid(pHostID, &timeout) ){ |
| 26512 | int err = errno; |
| 26513 | if( pError ){ |
| 26514 | *pError = err; |
| 26515 | } |
| 26516 | return SQLITE_IOERR; |
| 26517 | } |
| 26518 | #ifdef SQLITE_TEST |
| 26519 | /* simulate multiple hosts by creating unique hostid file paths */ |
| 26520 | if( sqlite3_hostid_num != 0){ |
| 26521 | pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF)); |
| 26522 | } |
| 26523 | #endif |
| 26524 | |
| 26525 | return SQLITE_OK; |
| 26526 | } |
| 26527 | |
| 26528 | /* The conch file contains the header, host id and lock file path |
| 26529 | */ |
| 26530 | #define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */ |
| 26531 | #define PROXY_HEADERLEN 1 /* conch file header length */ |
| 26532 | #define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN) |
| 26533 | #define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN) |
| 26534 | |
| 26535 | /* |
| 26536 | ** Takes an open conch file, copies the contents to a new path and then moves |
| 26537 | ** it back. The newly created file's file descriptor is assigned to the |
| 26538 | ** conch file structure and finally the original conch file descriptor is |
| 26539 | ** closed. Returns zero if successful. |
| 26540 | */ |
| 26541 | static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ |
| 26542 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26543 | unixFile *conchFile = pCtx->conchFile; |
| 26544 | char tPath[MAXPATHLEN]; |
| 26545 | char buf[PROXY_MAXCONCHLEN]; |
| 26546 | char *cPath = pCtx->conchFilePath; |
| 26547 | size_t readLen = 0; |
| 26548 | size_t pathLen = 0; |
| 26549 | char errmsg[64] = ""; |
| 26550 | int fd = -1; |
| 26551 | int rc = -1; |
| 26552 | |
| 26553 | /* create a new path by replace the trailing '-conch' with '-break' */ |
| 26554 | pathLen = strlcpy(tPath, cPath, MAXPATHLEN); |
| 26555 | if( pathLen>MAXPATHLEN || pathLen<6 || |
| 26556 | (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){ |
| 26557 | sprintf(errmsg, "path error (len %d)", (int)pathLen); |
| 26558 | goto end_breaklock; |
| 26559 | } |
| 26560 | /* read the conch content */ |
| 26561 | readLen = pread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0); |
| 26562 | if( readLen<PROXY_PATHINDEX ){ |
| 26563 | sprintf(errmsg, "read error (len %d)", (int)readLen); |
| 26564 | goto end_breaklock; |
| 26565 | } |
| 26566 | /* write it out to the temporary break file */ |
| 26567 | fd = open(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26568 | if( fd<0 ){ |
| 26569 | sprintf(errmsg, "create failed (%d)", errno); |
| 26570 | goto end_breaklock; |
| 26571 | } |
| 26572 | if( pwrite(fd, buf, readLen, 0) != readLen ){ |
| 26573 | sprintf(errmsg, "write failed (%d)", errno); |
| 26574 | goto end_breaklock; |
| 26575 | } |
| 26576 | if( rename(tPath, cPath) ){ |
| 26577 | sprintf(errmsg, "rename failed (%d)", errno); |
| 26578 | goto end_breaklock; |
| 26579 | } |
| 26580 | rc = 0; |
| 26581 | fprintf(stderr, "broke stale lock on %s\n", cPath); |
| 26582 | close(conchFile->h); |
| 26583 | conchFile->h = fd; |
| 26584 | conchFile->openFlags = O_RDWR | O_CREAT; |
| 26585 | |
| 26586 | end_breaklock: |
| 26587 | if( rc ){ |
| 26588 | if( fd>=0 ){ |
| 26589 | unlink(tPath); |
| 26590 | close(fd); |
| 26591 | } |
| 26592 | fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); |
| 26593 | } |
| 26594 | return rc; |
| 26595 | } |
| 26596 | |
| 26597 | /* Take the requested lock on the conch file and break a stale lock if the |
| 26598 | ** host id matches. |
| 26599 | */ |
| 26600 | static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ |
| 26601 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26602 | unixFile *conchFile = pCtx->conchFile; |
| 26603 | int rc = SQLITE_OK; |
| 26604 | int nTries = 0; |
| 26605 | struct timespec conchModTime; |
| 26606 | |
| 26607 | do { |
| 26608 | rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); |
| 26609 | nTries ++; |
| 26610 | if( rc==SQLITE_BUSY ){ |
| 26611 | /* If the lock failed (busy): |
| 26612 | * 1st try: get the mod time of the conch, wait 0.5s and try again. |
| 26613 | * 2nd try: fail if the mod time changed or host id is different, wait |
| 26614 | * 10 sec and try again |
| 26615 | * 3rd try: break the lock unless the mod time has changed. |
| 26616 | */ |
| 26617 | struct stat buf; |
| 26618 | if( fstat(conchFile->h, &buf) ){ |
| 26619 | pFile->lastErrno = errno; |
| 26620 | return SQLITE_IOERR_LOCK; |
| 26621 | } |
| 26622 | |
| 26623 | if( nTries==1 ){ |
| 26624 | conchModTime = buf.st_mtimespec; |
| 26625 | usleep(500000); /* wait 0.5 sec and try the lock again*/ |
| 26626 | continue; |
| 26627 | } |
| 26628 | |
| 26629 | assert( nTries>1 ); |
| 26630 | if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || |
| 26631 | conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){ |
| 26632 | return SQLITE_BUSY; |
| 26633 | } |
| 26634 | |
| 26635 | if( nTries==2 ){ |
| 26636 | char tBuf[PROXY_MAXCONCHLEN]; |
| 26637 | int len = pread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); |
| 26638 | if( len<0 ){ |
| 26639 | pFile->lastErrno = errno; |
| 26640 | return SQLITE_IOERR_LOCK; |
| 26641 | } |
| 26642 | if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ |
| 26643 | /* don't break the lock if the host id doesn't match */ |
| 26644 | if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){ |
| 26645 | return SQLITE_BUSY; |
| 26646 | } |
| 26647 | }else{ |
| 26648 | /* don't break the lock on short read or a version mismatch */ |
| 26649 | return SQLITE_BUSY; |
| 26650 | } |
| 26651 | usleep(10000000); /* wait 10 sec and try the lock again */ |
| 26652 | continue; |
| 26653 | } |
| 26654 | |
| 26655 | assert( nTries==3 ); |
| 26656 | if( 0==proxyBreakConchLock(pFile, myHostID) ){ |
| 26657 | rc = SQLITE_OK; |
| 26658 | if( lockType==EXCLUSIVE_LOCK ){ |
| 26659 | rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); |
| 26660 | } |
| 26661 | if( !rc ){ |
| 26662 | rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); |
| 26663 | } |
| 26664 | } |
| 26665 | } |
| 26666 | } while( rc==SQLITE_BUSY && nTries<3 ); |
| 26667 | |
| 26668 | return rc; |
| 26669 | } |
| 26670 | |
| 26671 | /* Takes the conch by taking a shared lock and read the contents conch, if |
| 26672 | ** lockPath is non-NULL, the host ID and lock file path must match. A NULL |
| 26673 | ** lockPath means that the lockPath in the conch file will be used if the |
| 26674 | ** host IDs match, or a new lock path will be generated automatically |
| 26675 | ** and written to the conch file. |
| 26676 | */ |
| 26677 | static int proxyTakeConch(unixFile *pFile){ |
| 26678 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26679 | |
| 26680 | if( pCtx->conchHeld!=0 ){ |
| 26681 | return SQLITE_OK; |
| 26682 | }else{ |
| 26683 | unixFile *conchFile = pCtx->conchFile; |
| 26684 | uuid_t myHostID; |
| 26685 | int pError = 0; |
| 26686 | char readBuf[PROXY_MAXCONCHLEN]; |
| 26687 | char lockPath[MAXPATHLEN]; |
| 26688 | char *tempLockPath = NULL; |
| 26689 | int rc = SQLITE_OK; |
| 26690 | int createConch = 0; |
| 26691 | int hostIdMatch = 0; |
| 26692 | int readLen = 0; |
| 26693 | int tryOldLockPath = 0; |
| 26694 | int forceNewLockPath = 0; |
| 26695 | |
| 26696 | OSTRACE4("TAKECONCH %d for %s pid=%d\n", conchFile->h, |
| 26697 | (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()); |
| 26698 | |
| 26699 | rc = proxyGetHostID(myHostID, &pError); |
| 26700 | if( (rc&0xff)==SQLITE_IOERR ){ |
| 26701 | pFile->lastErrno = pError; |
| 26702 | goto end_takeconch; |
| 26703 | } |
| 26704 | rc = proxyConchLock(pFile, myHostID, SHARED_LOCK); |
| 26705 | if( rc!=SQLITE_OK ){ |
| 26706 | goto end_takeconch; |
| 26707 | } |
| 26708 | /* read the existing conch file */ |
| 26709 | readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN); |
| 26710 | if( readLen<0 ){ |
| 26711 | /* I/O error: lastErrno set by seekAndRead */ |
| 26712 | pFile->lastErrno = conchFile->lastErrno; |
| 26713 | rc = SQLITE_IOERR_READ; |
| 26714 | goto end_takeconch; |
| 26715 | }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || |
| 26716 | readBuf[0]!=(char)PROXY_CONCHVERSION ){ |
| 26717 | /* a short read or version format mismatch means we need to create a new |
| 26718 | ** conch file. |
| 26719 | */ |
| 26720 | createConch = 1; |
| 26721 | } |
| 26722 | /* if the host id matches and the lock path already exists in the conch |
| 26723 | ** we'll try to use the path there, if we can't open that path, we'll |
| 26724 | ** retry with a new auto-generated path |
| 26725 | */ |
| 26726 | do { /* in case we need to try again for an :auto: named lock file */ |
| 26727 | |
| 26728 | if( !createConch && !forceNewLockPath ){ |
| 26729 | hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, |
| 26730 | PROXY_HOSTIDLEN); |
| 26731 | /* if the conch has data compare the contents */ |
| 26732 | if( !pCtx->lockProxyPath ){ |
| 26733 | /* for auto-named local lock file, just check the host ID and we'll |
| 26734 | ** use the local lock file path that's already in there |
| 26735 | */ |
| 26736 | if( hostIdMatch ){ |
| 26737 | size_t pathLen = (readLen - PROXY_PATHINDEX); |
| 26738 | |
| 26739 | if( pathLen>=MAXPATHLEN ){ |
| 26740 | pathLen=MAXPATHLEN-1; |
| 26741 | } |
| 26742 | memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen); |
| 26743 | lockPath[pathLen] = 0; |
| 26744 | tempLockPath = lockPath; |
| 26745 | tryOldLockPath = 1; |
| 26746 | /* create a copy of the lock path if the conch is taken */ |
| 26747 | goto end_takeconch; |
| 26748 | } |
| 26749 | }else if( hostIdMatch |
| 26750 | && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX], |
| 26751 | readLen-PROXY_PATHINDEX) |
| 26752 | ){ |
| 26753 | /* conch host and lock path match */ |
| 26754 | goto end_takeconch; |
| 26755 | } |
| 26756 | } |
| 26757 | |
| 26758 | /* if the conch isn't writable and doesn't match, we can't take it */ |
| 26759 | if( (conchFile->openFlags&O_RDWR) == 0 ){ |
| 26760 | rc = SQLITE_BUSY; |
| 26761 | goto end_takeconch; |
| 26762 | } |
| 26763 | |
| 26764 | /* either the conch didn't match or we need to create a new one */ |
| 26765 | if( !pCtx->lockProxyPath ){ |
| 26766 | proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN); |
| 26767 | tempLockPath = lockPath; |
| 26768 | /* create a copy of the lock path _only_ if the conch is taken */ |
| 26769 | } |
| 26770 | |
| 26771 | /* update conch with host and path (this will fail if other process |
| 26772 | ** has a shared lock already), if the host id matches, use the big |
| 26773 | ** stick. |
| 26774 | */ |
| 26775 | futimes(conchFile->h, NULL); |
| 26776 | if( hostIdMatch && !createConch ){ |
| 26777 | if( conchFile->pLock && conchFile->pLock->cnt>1 ){ |
| 26778 | /* We are trying for an exclusive lock but another thread in this |
| 26779 | ** same process is still holding a shared lock. */ |
| 26780 | rc = SQLITE_BUSY; |
| 26781 | } else { |
| 26782 | rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); |
| 26783 | } |
| 26784 | }else{ |
| 26785 | rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK); |
| 26786 | } |
| 26787 | if( rc==SQLITE_OK ){ |
| 26788 | char writeBuffer[PROXY_MAXCONCHLEN]; |
| 26789 | int writeSize = 0; |
| 26790 | |
| 26791 | writeBuffer[0] = (char)PROXY_CONCHVERSION; |
| 26792 | memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); |
| 26793 | if( pCtx->lockProxyPath!=NULL ){ |
| 26794 | strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN); |
| 26795 | }else{ |
| 26796 | strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); |
| 26797 | } |
| 26798 | writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); |
| 26799 | ftruncate(conchFile->h, writeSize); |
| 26800 | rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); |
| 26801 | fsync(conchFile->h); |
| 26802 | /* If we created a new conch file (not just updated the contents of a |
| 26803 | ** valid conch file), try to match the permissions of the database |
| 26804 | */ |
| 26805 | if( rc==SQLITE_OK && createConch ){ |
| 26806 | struct stat buf; |
| 26807 | int err = fstat(pFile->h, &buf); |
| 26808 | if( err==0 ){ |
| 26809 | mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | |
| 26810 | S_IROTH|S_IWOTH); |
| 26811 | /* try to match the database file R/W permissions, ignore failure */ |
| 26812 | #ifndef SQLITE_PROXY_DEBUG |
| 26813 | fchmod(conchFile->h, cmode); |
| 26814 | #else |
| 26815 | if( fchmod(conchFile->h, cmode)!=0 ){ |
| 26816 | int code = errno; |
| 26817 | fprintf(stderr, "fchmod %o FAILED with %d %s\n", |
| 26818 | cmode, code, strerror(code)); |
| 26819 | } else { |
| 26820 | fprintf(stderr, "fchmod %o SUCCEDED\n",cmode); |
| 26821 | } |
| 26822 | }else{ |
| 26823 | int code = errno; |
| 26824 | fprintf(stderr, "STAT FAILED[%d] with %d %s\n", |
| 26825 | err, code, strerror(code)); |
| 26826 | #endif |
| 26827 | } |
| 26828 | } |
| 26829 | } |
| 26830 | conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); |
| 26831 | |
| 26832 | end_takeconch: |
| 26833 | OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h); |
| 26834 | if( rc==SQLITE_OK && pFile->openFlags ){ |
| 26835 | if( pFile->h>=0 ){ |
| 26836 | #ifdef STRICT_CLOSE_ERROR |
| 26837 | if( close(pFile->h) ){ |
| 26838 | pFile->lastErrno = errno; |
| 26839 | return SQLITE_IOERR_CLOSE; |
| 26840 | } |
| 26841 | #else |
| 26842 | close(pFile->h); /* silently leak fd if fail */ |
| 26843 | #endif |
| 26844 | } |
| 26845 | pFile->h = -1; |
| 26846 | int fd = open(pCtx->dbPath, pFile->openFlags, |
| 26847 | SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26848 | OSTRACE2("TRANSPROXY: OPEN %d\n", fd); |
| 26849 | if( fd>=0 ){ |
| 26850 | pFile->h = fd; |
| 26851 | }else{ |
| 26852 | rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called |
| 26853 | during locking */ |
| 26854 | } |
| 26855 | } |
| 26856 | if( rc==SQLITE_OK && !pCtx->lockProxy ){ |
| 26857 | char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath; |
| 26858 | rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1); |
| 26859 | if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){ |
| 26860 | /* we couldn't create the proxy lock file with the old lock file path |
| 26861 | ** so try again via auto-naming |
| 26862 | */ |
| 26863 | forceNewLockPath = 1; |
| 26864 | tryOldLockPath = 0; |
| 26865 | continue; /* go back to the do {} while start point, try again */ |
| 26866 | } |
| 26867 | } |
| 26868 | if( rc==SQLITE_OK ){ |
| 26869 | /* Need to make a copy of path if we extracted the value |
| 26870 | ** from the conch file or the path was allocated on the stack |
| 26871 | */ |
| 26872 | if( tempLockPath ){ |
| 26873 | pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath); |
| 26874 | if( !pCtx->lockProxyPath ){ |
| 26875 | rc = SQLITE_NOMEM; |
| 26876 | } |
| 26877 | } |
| 26878 | } |
| 26879 | if( rc==SQLITE_OK ){ |
| 26880 | pCtx->conchHeld = 1; |
| 26881 | |
| 26882 | if( pCtx->lockProxy->pMethod == &afpIoMethods ){ |
| 26883 | afpLockingContext *afpCtx; |
| 26884 | afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext; |
| 26885 | afpCtx->dbPath = pCtx->lockProxyPath; |
| 26886 | } |
| 26887 | } else { |
| 26888 | conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); |
| 26889 | } |
| 26890 | OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed"); |
| 26891 | return rc; |
| 26892 | } while (1); /* in case we need to retry the :auto: lock file - we should never get here except via the 'continue' call. */ |
| 26893 | } |
| 26894 | } |
| 26895 | |
| 26896 | /* |
| 26897 | ** If pFile holds a lock on a conch file, then release that lock. |
| @@ -26375,12 +26904,14 @@ | |
| 26904 | pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26905 | conchFile = pCtx->conchFile; |
| 26906 | OSTRACE4("RELEASECONCH %d for %s pid=%d\n", conchFile->h, |
| 26907 | (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), |
| 26908 | getpid()); |
| 26909 | if( pCtx->conchHeld>0 ){ |
| 26910 | rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); |
| 26911 | } |
| 26912 | pCtx->conchHeld = 0; |
| 26913 | OSTRACE3("RELEASECONCH %d %s\n", conchFile->h, |
| 26914 | (rc==SQLITE_OK ? "ok" : "failed")); |
| 26915 | return rc; |
| 26916 | } |
| 26917 | |
| @@ -26472,22 +27003,22 @@ | |
| 27003 | #if defined(__APPLE__) |
| 27004 | if( pFile->pMethod == &afpIoMethods ){ |
| 27005 | /* afp style keeps a reference to the db path in the filePath field |
| 27006 | ** of the struct */ |
| 27007 | assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); |
| 27008 | strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN); |
| 27009 | } else |
| 27010 | #endif |
| 27011 | if( pFile->pMethod == &dotlockIoMethods ){ |
| 27012 | /* dot lock style uses the locking context to store the dot lock |
| 27013 | ** file path */ |
| 27014 | int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX); |
| 27015 | memcpy(dbPath, (char *)pFile->lockingContext, len + 1); |
| 27016 | }else{ |
| 27017 | /* all other styles use the locking context to store the db file path */ |
| 27018 | assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); |
| 27019 | strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN); |
| 27020 | } |
| 27021 | return SQLITE_OK; |
| 27022 | } |
| 27023 | |
| 27024 | /* |
| @@ -26523,31 +27054,57 @@ | |
| 27054 | } |
| 27055 | memset(pCtx, 0, sizeof(*pCtx)); |
| 27056 | |
| 27057 | rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath); |
| 27058 | if( rc==SQLITE_OK ){ |
| 27059 | rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0); |
| 27060 | if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){ |
| 27061 | /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and |
| 27062 | ** (c) the file system is read-only, then enable no-locking access. |
| 27063 | ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts |
| 27064 | ** that openFlags will have only one of O_RDONLY or O_RDWR. |
| 27065 | */ |
| 27066 | struct statfs fsInfo; |
| 27067 | struct stat conchInfo; |
| 27068 | int goLockless = 0; |
| 27069 | |
| 27070 | if( stat(pCtx->conchFilePath, &conchInfo) == -1 ) { |
| 27071 | int err = errno; |
| 27072 | if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){ |
| 27073 | goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY; |
| 27074 | } |
| 27075 | } |
| 27076 | if( goLockless ){ |
| 27077 | pCtx->conchHeld = -1; /* read only FS/ lockless */ |
| 27078 | rc = SQLITE_OK; |
| 27079 | } |
| 27080 | } |
| 27081 | } |
| 27082 | if( rc==SQLITE_OK && lockPath ){ |
| 27083 | pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); |
| 27084 | } |
| 27085 | |
| 27086 | if( rc==SQLITE_OK ){ |
| 27087 | pCtx->dbPath = sqlite3DbStrDup(0, dbPath); |
| 27088 | if( pCtx->dbPath==NULL ){ |
| 27089 | rc = SQLITE_NOMEM; |
| 27090 | } |
| 27091 | } |
| 27092 | if( rc==SQLITE_OK ){ |
| 27093 | /* all memory is allocated, proxys are created and assigned, |
| 27094 | ** switch the locking context and pMethod then return. |
| 27095 | */ |
| 27096 | pCtx->oldLockingContext = pFile->lockingContext; |
| 27097 | pFile->lockingContext = pCtx; |
| 27098 | pCtx->pOldMethod = pFile->pMethod; |
| 27099 | pFile->pMethod = &proxyIoMethods; |
| 27100 | }else{ |
| 27101 | if( pCtx->conchFile ){ |
| 27102 | pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); |
| 27103 | sqlite3_free(pCtx->conchFile); |
| 27104 | } |
| 27105 | sqlite3_free(pCtx->lockProxyPath); |
| 27106 | sqlite3_free(pCtx->conchFilePath); |
| 27107 | sqlite3_free(pCtx); |
| 27108 | } |
| 27109 | OSTRACE3("TRANSPROXY %d %s\n", pFile->h, |
| 27110 | (rc==SQLITE_OK ? "ok" : "failed")); |
| @@ -26632,12 +27189,16 @@ | |
| 27189 | static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) { |
| 27190 | unixFile *pFile = (unixFile*)id; |
| 27191 | int rc = proxyTakeConch(pFile); |
| 27192 | if( rc==SQLITE_OK ){ |
| 27193 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 27194 | if( pCtx->conchHeld>0 ){ |
| 27195 | unixFile *proxy = pCtx->lockProxy; |
| 27196 | return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut); |
| 27197 | }else{ /* conchHeld < 0 is lockless */ |
| 27198 | pResOut=0; |
| 27199 | } |
| 27200 | } |
| 27201 | return rc; |
| 27202 | } |
| 27203 | |
| 27204 | /* |
| @@ -26667,13 +27228,17 @@ | |
| 27228 | static int proxyLock(sqlite3_file *id, int locktype) { |
| 27229 | unixFile *pFile = (unixFile*)id; |
| 27230 | int rc = proxyTakeConch(pFile); |
| 27231 | if( rc==SQLITE_OK ){ |
| 27232 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 27233 | if( pCtx->conchHeld>0 ){ |
| 27234 | unixFile *proxy = pCtx->lockProxy; |
| 27235 | rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype); |
| 27236 | pFile->locktype = proxy->locktype; |
| 27237 | }else{ |
| 27238 | /* conchHeld < 0 is lockless */ |
| 27239 | } |
| 27240 | } |
| 27241 | return rc; |
| 27242 | } |
| 27243 | |
| 27244 | |
| @@ -26687,13 +27252,17 @@ | |
| 27252 | static int proxyUnlock(sqlite3_file *id, int locktype) { |
| 27253 | unixFile *pFile = (unixFile*)id; |
| 27254 | int rc = proxyTakeConch(pFile); |
| 27255 | if( rc==SQLITE_OK ){ |
| 27256 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 27257 | if( pCtx->conchHeld>0 ){ |
| 27258 | unixFile *proxy = pCtx->lockProxy; |
| 27259 | rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype); |
| 27260 | pFile->locktype = proxy->locktype; |
| 27261 | }else{ |
| 27262 | /* conchHeld < 0 is lockless */ |
| 27263 | } |
| 27264 | } |
| 27265 | return rc; |
| 27266 | } |
| 27267 | |
| 27268 | /* |
| @@ -26816,11 +27385,10 @@ | |
| 27385 | #else |
| 27386 | UNIXVFS("unix", posixIoFinder ), |
| 27387 | #endif |
| 27388 | UNIXVFS("unix-none", nolockIoFinder ), |
| 27389 | UNIXVFS("unix-dotfile", dotlockIoFinder ), |
| 27390 | #if OS_VXWORKS |
| 27391 | UNIXVFS("unix-namedsem", semIoFinder ), |
| 27392 | #endif |
| 27393 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 27394 | UNIXVFS("unix-posix", posixIoFinder ), |
| @@ -26828,10 +27396,11 @@ | |
| 27396 | UNIXVFS("unix-flock", flockIoFinder ), |
| 27397 | #endif |
| 27398 | #endif |
| 27399 | #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) |
| 27400 | UNIXVFS("unix-afp", afpIoFinder ), |
| 27401 | UNIXVFS("unix-nfs", nfsIoFinder ), |
| 27402 | UNIXVFS("unix-proxy", proxyIoFinder ), |
| 27403 | #endif |
| 27404 | }; |
| 27405 | unsigned int i; /* Loop counter */ |
| 27406 | |
| @@ -28491,11 +29060,11 @@ | |
| 29060 | free(zConverted); |
| 29061 | if( flags & SQLITE_OPEN_READWRITE ){ |
| 29062 | return winOpen(pVfs, zName, id, |
| 29063 | ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); |
| 29064 | }else{ |
| 29065 | return SQLITE_CANTOPEN_BKPT; |
| 29066 | } |
| 29067 | } |
| 29068 | if( pOutFlags ){ |
| 29069 | if( flags & SQLITE_OPEN_READWRITE ){ |
| 29070 | *pOutFlags = SQLITE_OPEN_READWRITE; |
| @@ -28513,11 +29082,11 @@ | |
| 29082 | (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) |
| 29083 | && !winceCreateLock(zName, pFile) |
| 29084 | ){ |
| 29085 | CloseHandle(h); |
| 29086 | free(zConverted); |
| 29087 | return SQLITE_CANTOPEN_BKPT; |
| 29088 | } |
| 29089 | if( isTemp ){ |
| 29090 | pFile->zDeleteOnClose = zConverted; |
| 29091 | }else |
| 29092 | #endif |
| @@ -29653,10 +30222,11 @@ | |
| 30222 | expensive_assert( pcacheCheckSynced(pCache) ); |
| 30223 | for(pPg=pCache->pSynced; |
| 30224 | pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); |
| 30225 | pPg=pPg->pDirtyPrev |
| 30226 | ); |
| 30227 | pCache->pSynced = pPg; |
| 30228 | if( !pPg ){ |
| 30229 | for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); |
| 30230 | } |
| 30231 | if( pPg ){ |
| 30232 | int rc; |
| @@ -34067,13 +34637,11 @@ | |
| 34637 | ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to |
| 34638 | ** make the file smaller (presumably by auto-vacuum code). Do not write |
| 34639 | ** any such pages to the file. |
| 34640 | ** |
| 34641 | ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag |
| 34642 | ** set (set by sqlite3PagerDontWrite()). |
| 34643 | */ |
| 34644 | if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ |
| 34645 | i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ |
| 34646 | char *pData; /* Data to write */ |
| 34647 | |
| @@ -34356,11 +34924,11 @@ | |
| 34924 | ** the database being opened will be more than pVfs->mxPathname |
| 34925 | ** bytes in length. This means the database cannot be opened, |
| 34926 | ** as it will not be possible to open the journal file or even |
| 34927 | ** check for a hot-journal before reading. |
| 34928 | */ |
| 34929 | rc = SQLITE_CANTOPEN_BKPT; |
| 34930 | } |
| 34931 | if( rc!=SQLITE_OK ){ |
| 34932 | sqlite3_free(zPathname); |
| 34933 | return rc; |
| 34934 | } |
| @@ -34815,11 +35383,11 @@ | |
| 35383 | int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; |
| 35384 | assert( !pPager->tempFile ); |
| 35385 | rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); |
| 35386 | assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); |
| 35387 | if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ |
| 35388 | rc = SQLITE_CANTOPEN_BKPT; |
| 35389 | sqlite3OsClose(pPager->jfd); |
| 35390 | } |
| 35391 | }else{ |
| 35392 | /* If the journal does not exist, it usually means that some |
| 35393 | ** other connection managed to get in and roll it back before |
| @@ -35034,11 +35602,11 @@ | |
| 35602 | rc = sqlite3PagerPagecount(pPager, &nMax); |
| 35603 | if( rc!=SQLITE_OK ){ |
| 35604 | goto pager_acquire_err; |
| 35605 | } |
| 35606 | |
| 35607 | if( MEMDB || nMax<(int)pgno || noContent || !isOpen(pPager->fd) ){ |
| 35608 | if( pgno>pPager->mxPgno ){ |
| 35609 | rc = SQLITE_FULL; |
| 35610 | goto pager_acquire_err; |
| 35611 | } |
| 35612 | if( noContent ){ |
| @@ -35054,13 +35622,12 @@ | |
| 35622 | testcase( rc==SQLITE_NOMEM ); |
| 35623 | } |
| 35624 | TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); |
| 35625 | testcase( rc==SQLITE_NOMEM ); |
| 35626 | sqlite3EndBenignMalloc(); |
| 35627 | } |
| 35628 | memset(pPg->pData, 0, pPager->pageSize); |
| 35629 | IOTRACE(("ZERO %p %d\n", pPager, pgno)); |
| 35630 | }else{ |
| 35631 | assert( pPg->pPager==pPager ); |
| 35632 | rc = readDbPage(pPg); |
| 35633 | if( rc!=SQLITE_OK ){ |
| @@ -35578,11 +36145,10 @@ | |
| 36145 | SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ |
| 36146 | return pPg->flags&PGHDR_DIRTY; |
| 36147 | } |
| 36148 | #endif |
| 36149 | |
| 36150 | /* |
| 36151 | ** A call to this routine tells the pager that it is not necessary to |
| 36152 | ** write the information on page pPg back to the disk, even though |
| 36153 | ** that page might be marked as dirty. This happens, for example, when |
| 36154 | ** the page has been added as a leaf of the freelist and so its |
| @@ -35604,11 +36170,10 @@ | |
| 36170 | #ifdef SQLITE_CHECK_PAGES |
| 36171 | pPg->pageHash = pager_pagehash(pPg); |
| 36172 | #endif |
| 36173 | } |
| 36174 | } |
| 36175 | |
| 36176 | /* |
| 36177 | ** This routine is called to increment the value of the database file |
| 36178 | ** change-counter, stored as a 4-byte big-endian integer starting at |
| 36179 | ** byte offset 24 of the pager file. |
| @@ -36174,34 +36739,38 @@ | |
| 36739 | |
| 36740 | /* Figure out how many savepoints will still be active after this |
| 36741 | ** operation. Store this value in nNew. Then free resources associated |
| 36742 | ** with any savepoints that are destroyed by this operation. |
| 36743 | */ |
| 36744 | nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1); |
| 36745 | for(ii=nNew; ii<pPager->nSavepoint; ii++){ |
| 36746 | sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); |
| 36747 | } |
| 36748 | pPager->nSavepoint = nNew; |
| 36749 | |
| 36750 | /* If this is a release of the outermost savepoint, truncate |
| 36751 | ** the sub-journal to zero bytes in size. */ |
| 36752 | if( op==SAVEPOINT_RELEASE ){ |
| 36753 | if( nNew==0 && isOpen(pPager->sjfd) ){ |
| 36754 | /* Only truncate if it is an in-memory sub-journal. */ |
| 36755 | if( sqlite3IsMemJournal(pPager->sjfd) ){ |
| 36756 | rc = sqlite3OsTruncate(pPager->sjfd, 0); |
| 36757 | } |
| 36758 | pPager->nSubRec = 0; |
| 36759 | } |
| 36760 | } |
| 36761 | /* Else this is a rollback operation, playback the specified savepoint. |
| 36762 | ** If this is a temp-file, it is possible that the journal file has |
| 36763 | ** not yet been opened. In this case there have been no changes to |
| 36764 | ** the database file, so the playback operation can be skipped. |
| 36765 | */ |
| 36766 | else if( isOpen(pPager->jfd) ){ |
| 36767 | PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; |
| 36768 | rc = pagerPlaybackSavepoint(pPager, pSavepoint); |
| 36769 | assert(rc!=SQLITE_DONE); |
| 36770 | } |
| 36771 | |
| 36772 | } |
| 36773 | return rc; |
| 36774 | } |
| 36775 | |
| 36776 | /* |
| @@ -36957,10 +37526,11 @@ | |
| 37526 | sqlite3 *db; /* Database connection currently using this Btree */ |
| 37527 | BtCursor *pCursor; /* A list of all open cursors */ |
| 37528 | MemPage *pPage1; /* First page of the database */ |
| 37529 | u8 readOnly; /* True if the underlying file is readonly */ |
| 37530 | u8 pageSizeFixed; /* True if the page size can no longer be changed */ |
| 37531 | u8 secureDelete; /* True if secure_delete is enabled */ |
| 37532 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 37533 | u8 autoVacuum; /* True if auto-vacuum is enabled */ |
| 37534 | u8 incrVacuum; /* True if incr-vacuum is enabled */ |
| 37535 | #endif |
| 37536 | u16 pageSize; /* Total number of bytes on a page */ |
| @@ -38780,15 +39350,15 @@ | |
| 39350 | assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); |
| 39351 | assert( (start + size)<=pPage->pBt->usableSize ); |
| 39352 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 39353 | assert( size>=0 ); /* Minimum cell size is 4 */ |
| 39354 | |
| 39355 | if( pPage->pBt->secureDelete ){ |
| 39356 | /* Overwrite deleted information with zeros when the secure_delete |
| 39357 | ** option is enabled */ |
| 39358 | memset(&data[start], 0, size); |
| 39359 | } |
| 39360 | |
| 39361 | /* Add the space back into the linked list of freeblocks. Note that |
| 39362 | ** even though the freeblock list was checked by btreeInitPage(), |
| 39363 | ** btreeInitPage() did not detect overlapping cells or |
| 39364 | ** freeblocks that overlapped cells. Nor does it detect when the |
| @@ -39016,13 +39586,13 @@ | |
| 39586 | assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); |
| 39587 | assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); |
| 39588 | assert( sqlite3PagerGetData(pPage->pDbPage) == data ); |
| 39589 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 39590 | assert( sqlite3_mutex_held(pBt->mutex) ); |
| 39591 | if( pBt->secureDelete ){ |
| 39592 | memset(&data[hdr], 0, pBt->usableSize - hdr); |
| 39593 | } |
| 39594 | data[hdr] = (char)flags; |
| 39595 | first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); |
| 39596 | memset(&data[hdr+1], 0, 4); |
| 39597 | data[hdr+7] = 0; |
| 39598 | put2byte(&data[hdr+5], pBt->usableSize); |
| @@ -39338,10 +39908,13 @@ | |
| 39908 | p->pBt = pBt; |
| 39909 | |
| 39910 | pBt->pCursor = 0; |
| 39911 | pBt->pPage1 = 0; |
| 39912 | pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); |
| 39913 | #ifdef SQLITE_SECURE_DELETE |
| 39914 | pBt->secureDelete = 1; |
| 39915 | #endif |
| 39916 | pBt->pageSize = get2byte(&zDbHeader[16]); |
| 39917 | if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE |
| 39918 | || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ |
| 39919 | pBt->pageSize = 0; |
| 39920 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| @@ -39694,10 +40267,27 @@ | |
| 40267 | sqlite3BtreeEnter(p); |
| 40268 | n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); |
| 40269 | sqlite3BtreeLeave(p); |
| 40270 | return n; |
| 40271 | } |
| 40272 | |
| 40273 | /* |
| 40274 | ** Set the secureDelete flag if newFlag is 0 or 1. If newFlag is -1, |
| 40275 | ** then make no changes. Always return the value of the secureDelete |
| 40276 | ** setting after the change. |
| 40277 | */ |
| 40278 | SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ |
| 40279 | int b; |
| 40280 | if( p==0 ) return 0; |
| 40281 | sqlite3BtreeEnter(p); |
| 40282 | if( newFlag>=0 ){ |
| 40283 | p->pBt->secureDelete = (newFlag!=0) ? 1 : 0; |
| 40284 | } |
| 40285 | b = p->pBt->secureDelete; |
| 40286 | sqlite3BtreeLeave(p); |
| 40287 | return b; |
| 40288 | } |
| 40289 | #endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ |
| 40290 | |
| 40291 | /* |
| 40292 | ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' |
| 40293 | ** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it |
| @@ -42437,21 +43027,21 @@ | |
| 43027 | rc = sqlite3PagerWrite(pPage1->pDbPage); |
| 43028 | if( rc ) goto freepage_out; |
| 43029 | nFree = get4byte(&pPage1->aData[36]); |
| 43030 | put4byte(&pPage1->aData[36], nFree+1); |
| 43031 | |
| 43032 | if( pBt->secureDelete ){ |
| 43033 | /* If the secure_delete option is enabled, then |
| 43034 | ** always fully overwrite deleted information with zeros. |
| 43035 | */ |
| 43036 | if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) ) |
| 43037 | || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0) |
| 43038 | ){ |
| 43039 | goto freepage_out; |
| 43040 | } |
| 43041 | memset(pPage->aData, 0, pPage->pBt->pageSize); |
| 43042 | } |
| 43043 | |
| 43044 | /* If the database supports auto-vacuum, write an entry in the pointer-map |
| 43045 | ** to indicate that the page is free. |
| 43046 | */ |
| 43047 | if( ISAUTOVACUUM ){ |
| @@ -42498,15 +43088,13 @@ | |
| 43088 | */ |
| 43089 | rc = sqlite3PagerWrite(pTrunk->pDbPage); |
| 43090 | if( rc==SQLITE_OK ){ |
| 43091 | put4byte(&pTrunk->aData[4], nLeaf+1); |
| 43092 | put4byte(&pTrunk->aData[8+nLeaf*4], iPage); |
| 43093 | if( pPage && !pBt->secureDelete ){ |
| 43094 | sqlite3PagerDontWrite(pPage->pDbPage); |
| 43095 | } |
| 43096 | rc = btreeSetHasContent(pBt, iPage); |
| 43097 | } |
| 43098 | TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); |
| 43099 | goto freepage_out; |
| 43100 | } |
| @@ -42576,11 +43164,29 @@ | |
| 43164 | } |
| 43165 | if( nOvfl ){ |
| 43166 | rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); |
| 43167 | if( rc ) return rc; |
| 43168 | } |
| 43169 | |
| 43170 | if( (pOvfl || (pOvfl = btreePageLookup(pBt, ovflPgno))) |
| 43171 | && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1 |
| 43172 | ){ |
| 43173 | /* There is no reason any cursor should have an outstanding reference |
| 43174 | ** to an overflow page belonging to a cell that is being deleted/updated. |
| 43175 | ** So if there exists more than one reference to this page, then it |
| 43176 | ** must not really be an overflow page and the database must be corrupt. |
| 43177 | ** It is helpful to detect this before calling freePage2(), as |
| 43178 | ** freePage2() may zero the page contents if secure-delete mode is |
| 43179 | ** enabled. If this 'overflow' page happens to be a page that the |
| 43180 | ** caller is iterating through or using in some other way, this |
| 43181 | ** can be problematic. |
| 43182 | */ |
| 43183 | rc = SQLITE_CORRUPT_BKPT; |
| 43184 | }else{ |
| 43185 | rc = freePage2(pBt, pOvfl, ovflPgno); |
| 43186 | } |
| 43187 | |
| 43188 | if( pOvfl ){ |
| 43189 | sqlite3PagerUnref(pOvfl->pDbPage); |
| 43190 | } |
| 43191 | if( rc ) return rc; |
| 43192 | ovflPgno = iNext; |
| @@ -42820,11 +43426,11 @@ | |
| 43426 | int sz, /* Bytes of content in pCell */ |
| 43427 | u8 *pTemp, /* Temp storage space for pCell, if needed */ |
| 43428 | Pgno iChild, /* If non-zero, replace first 4 bytes with this value */ |
| 43429 | int *pRC /* Read and write return code from here */ |
| 43430 | ){ |
| 43431 | int idx = 0; /* Where to write new cell content in data[] */ |
| 43432 | int j; /* Loop counter */ |
| 43433 | int end; /* First byte past the last cell pointer in data[] */ |
| 43434 | int ins; /* Index in data[] where new cell pointer is inserted */ |
| 43435 | int cellOffset; /* Address of first cell pointer in data[] */ |
| 43436 | u8 *data; /* The content of the whole page */ |
| @@ -43311,14 +43917,14 @@ | |
| 43917 | ** Unless SQLite is compiled in secure-delete mode. In this case, |
| 43918 | ** the dropCell() routine will overwrite the entire cell with zeroes. |
| 43919 | ** In this case, temporarily copy the cell into the aOvflSpace[] |
| 43920 | ** buffer. It will be copied out again as soon as the aSpace[] buffer |
| 43921 | ** is allocated. */ |
| 43922 | if( pBt->secureDelete ){ |
| 43923 | memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]); |
| 43924 | apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; |
| 43925 | } |
| 43926 | dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); |
| 43927 | } |
| 43928 | } |
| 43929 | |
| 43930 | /* Make nMaxCells a multiple of 4 in order to preserve 8-byte |
| @@ -43434,11 +44040,11 @@ | |
| 44040 | szNew[k] = subtotal - szCell[i]; |
| 44041 | cntNew[k] = i; |
| 44042 | if( leafData ){ i--; } |
| 44043 | subtotal = 0; |
| 44044 | k++; |
| 44045 | if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } |
| 44046 | } |
| 44047 | } |
| 44048 | szNew[k] = subtotal; |
| 44049 | cntNew[k] = nCell; |
| 44050 | k++; |
| @@ -43488,11 +44094,11 @@ | |
| 44094 | |
| 44095 | /* |
| 44096 | ** Allocate k new pages. Reuse old pages where possible. |
| 44097 | */ |
| 44098 | if( apOld[0]->pgno<=1 ){ |
| 44099 | rc = SQLITE_CORRUPT_BKPT; |
| 44100 | goto balance_cleanup; |
| 44101 | } |
| 44102 | pageFlags = apOld[0]->aData[0]; |
| 44103 | for(i=0; i<k; i++){ |
| 44104 | MemPage *pNew; |
| @@ -44926,11 +45532,13 @@ | |
| 45532 | ** the root of the tree. |
| 45533 | */ |
| 45534 | static int checkTreePage( |
| 45535 | IntegrityCk *pCheck, /* Context for the sanity check */ |
| 45536 | int iPage, /* Page number of the page to check */ |
| 45537 | char *zParentContext, /* Parent context */ |
| 45538 | i64 *pnParentMinKey, |
| 45539 | i64 *pnParentMaxKey |
| 45540 | ){ |
| 45541 | MemPage *pPage; |
| 45542 | int i, rc, depth, d2, pgno, cnt; |
| 45543 | int hdr, cellStart; |
| 45544 | int nCell; |
| @@ -44937,10 +45545,12 @@ | |
| 45545 | u8 *data; |
| 45546 | BtShared *pBt; |
| 45547 | int usableSize; |
| 45548 | char zContext[100]; |
| 45549 | char *hit = 0; |
| 45550 | i64 nMinKey = 0; |
| 45551 | i64 nMaxKey = 0; |
| 45552 | |
| 45553 | sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); |
| 45554 | |
| 45555 | /* Check that the page exists |
| 45556 | */ |
| @@ -44979,10 +45589,20 @@ | |
| 45589 | "On tree page %d cell %d: ", iPage, i); |
| 45590 | pCell = findCell(pPage,i); |
| 45591 | btreeParseCellPtr(pPage, pCell, &info); |
| 45592 | sz = info.nData; |
| 45593 | if( !pPage->intKey ) sz += (int)info.nKey; |
| 45594 | /* For intKey pages, check that the keys are in order. |
| 45595 | */ |
| 45596 | else if( i==0 ) nMinKey = nMaxKey = info.nKey; |
| 45597 | else{ |
| 45598 | if( info.nKey <= nMaxKey ){ |
| 45599 | checkAppendMsg(pCheck, zContext, |
| 45600 | "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey); |
| 45601 | } |
| 45602 | nMaxKey = info.nKey; |
| 45603 | } |
| 45604 | assert( sz==info.nPayload ); |
| 45605 | if( (sz>info.nLocal) |
| 45606 | && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize]) |
| 45607 | ){ |
| 45608 | int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); |
| @@ -45002,29 +45622,66 @@ | |
| 45622 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45623 | if( pBt->autoVacuum ){ |
| 45624 | checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); |
| 45625 | } |
| 45626 | #endif |
| 45627 | d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey); |
| 45628 | if( i>0 && d2!=depth ){ |
| 45629 | checkAppendMsg(pCheck, zContext, "Child page depth differs"); |
| 45630 | } |
| 45631 | depth = d2; |
| 45632 | } |
| 45633 | } |
| 45634 | |
| 45635 | if( !pPage->leaf ){ |
| 45636 | pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); |
| 45637 | sqlite3_snprintf(sizeof(zContext), zContext, |
| 45638 | "On page %d at right child: ", iPage); |
| 45639 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45640 | if( pBt->autoVacuum ){ |
| 45641 | checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); |
| 45642 | } |
| 45643 | #endif |
| 45644 | checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey); |
| 45645 | } |
| 45646 | |
| 45647 | /* For intKey leaf pages, check that the min/max keys are in order |
| 45648 | ** with any left/parent/right pages. |
| 45649 | */ |
| 45650 | if( pPage->leaf && pPage->intKey ){ |
| 45651 | /* if we are a left child page */ |
| 45652 | if( pnParentMinKey ){ |
| 45653 | /* if we are the left most child page */ |
| 45654 | if( !pnParentMaxKey ){ |
| 45655 | if( nMaxKey > *pnParentMinKey ){ |
| 45656 | checkAppendMsg(pCheck, zContext, |
| 45657 | "Rowid %lld out of order (max larger than parent min of %lld)", |
| 45658 | nMaxKey, *pnParentMinKey); |
| 45659 | } |
| 45660 | }else{ |
| 45661 | if( nMinKey <= *pnParentMinKey ){ |
| 45662 | checkAppendMsg(pCheck, zContext, |
| 45663 | "Rowid %lld out of order (min less than parent min of %lld)", |
| 45664 | nMinKey, *pnParentMinKey); |
| 45665 | } |
| 45666 | if( nMaxKey > *pnParentMaxKey ){ |
| 45667 | checkAppendMsg(pCheck, zContext, |
| 45668 | "Rowid %lld out of order (max larger than parent max of %lld)", |
| 45669 | nMaxKey, *pnParentMaxKey); |
| 45670 | } |
| 45671 | *pnParentMinKey = nMaxKey; |
| 45672 | } |
| 45673 | /* else if we're a right child page */ |
| 45674 | } else if( pnParentMaxKey ){ |
| 45675 | if( nMinKey <= *pnParentMaxKey ){ |
| 45676 | checkAppendMsg(pCheck, zContext, |
| 45677 | "Rowid %lld out of order (min less than parent max of %lld)", |
| 45678 | nMinKey, *pnParentMaxKey); |
| 45679 | } |
| 45680 | } |
| 45681 | } |
| 45682 | |
| 45683 | /* Check for complete coverage of the page |
| 45684 | */ |
| 45685 | data = pPage->aData; |
| 45686 | hdr = pPage->hdrOffset; |
| 45687 | hit = sqlite3PageMalloc( pBt->pageSize ); |
| @@ -45044,11 +45701,11 @@ | |
| 45701 | if( pc<=usableSize-4 ){ |
| 45702 | size = cellSizePtr(pPage, &data[pc]); |
| 45703 | } |
| 45704 | if( (pc+size-1)>=usableSize ){ |
| 45705 | checkAppendMsg(pCheck, 0, |
| 45706 | "Corruption detected in cell %d on page %d",i,iPage); |
| 45707 | }else{ |
| 45708 | for(j=pc+size-1; j>=pc; j--) hit[j]++; |
| 45709 | } |
| 45710 | } |
| 45711 | i = get2byte(&data[hdr+1]); |
| @@ -45150,11 +45807,11 @@ | |
| 45807 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45808 | if( pBt->autoVacuum && aRoot[i]>1 ){ |
| 45809 | checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); |
| 45810 | } |
| 45811 | #endif |
| 45812 | checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL); |
| 45813 | } |
| 45814 | |
| 45815 | /* Make sure every page in the file is referenced |
| 45816 | */ |
| 45817 | for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ |
| @@ -45483,14 +46140,14 @@ | |
| 46140 | sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory"); |
| 46141 | rc = SQLITE_NOMEM; |
| 46142 | }else{ |
| 46143 | pParse->db = pDb; |
| 46144 | if( sqlite3OpenTempDatabase(pParse) ){ |
| 46145 | sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); |
| 46146 | rc = SQLITE_ERROR; |
| 46147 | } |
| 46148 | sqlite3DbFree(pErrorDb, pParse->zErrMsg); |
| 46149 | sqlite3StackFree(pErrorDb, pParse); |
| 46150 | } |
| 46151 | if( rc ){ |
| 46152 | return 0; |
| 46153 | } |
| @@ -46329,10 +46986,14 @@ | |
| 46986 | ** Because we do not completely understand the problem, we will |
| 46987 | ** take the conservative approach and always do range tests |
| 46988 | ** before attempting the conversion. |
| 46989 | */ |
| 46990 | static i64 doubleToInt64(double r){ |
| 46991 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 46992 | /* When floating-point is omitted, double and int64 are the same thing */ |
| 46993 | return r; |
| 46994 | #else |
| 46995 | /* |
| 46996 | ** Many compilers we encounter do not define constants for the |
| 46997 | ** minimum and maximum 64-bit integers, or they define them |
| 46998 | ** inconsistently. And many do not understand the "LL" notation. |
| 46999 | ** So we define our own static constants here using nothing |
| @@ -46350,10 +47011,11 @@ | |
| 47011 | ** does so for compatibility we will do the same in software. */ |
| 47012 | return minInt; |
| 47013 | }else{ |
| 47014 | return (i64)r; |
| 47015 | } |
| 47016 | #endif |
| 47017 | } |
| 47018 | |
| 47019 | /* |
| 47020 | ** Return some kind of integer value which is the best we can do |
| 47021 | ** at representing the value that *pMem describes as an integer. |
| @@ -46477,25 +47139,30 @@ | |
| 47139 | } |
| 47140 | |
| 47141 | /* |
| 47142 | ** Convert pMem so that it has types MEM_Real or MEM_Int or both. |
| 47143 | ** Invalidate any prior representations. |
| 47144 | ** |
| 47145 | ** Every effort is made to force the conversion, even if the input |
| 47146 | ** is a string that does not look completely like a number. Convert |
| 47147 | ** as much of the string as we can and ignore the rest. |
| 47148 | */ |
| 47149 | SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ |
| 47150 | int rc; |
| 47151 | assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ); |
| 47152 | assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); |
| 47153 | assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); |
| 47154 | rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8); |
| 47155 | if( rc ) return rc; |
| 47156 | rc = sqlite3VdbeMemNulTerminate(pMem); |
| 47157 | if( rc ) return rc; |
| 47158 | if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){ |
| 47159 | MemSetTypeFlag(pMem, MEM_Int); |
| 47160 | }else{ |
| 47161 | pMem->r = sqlite3VdbeRealValue(pMem); |
| 47162 | MemSetTypeFlag(pMem, MEM_Real); |
| 47163 | sqlite3VdbeIntegerAffinity(pMem); |
| 47164 | } |
| 47165 | return SQLITE_OK; |
| 47166 | } |
| 47167 | |
| 47168 | /* |
| @@ -46543,10 +47210,11 @@ | |
| 47210 | pMem->u.i = val; |
| 47211 | pMem->flags = MEM_Int; |
| 47212 | pMem->type = SQLITE_INTEGER; |
| 47213 | } |
| 47214 | |
| 47215 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 47216 | /* |
| 47217 | ** Delete any previous value and set the value stored in *pMem to val, |
| 47218 | ** manifest type REAL. |
| 47219 | */ |
| 47220 | SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ |
| @@ -46557,10 +47225,11 @@ | |
| 47225 | pMem->r = val; |
| 47226 | pMem->flags = MEM_Real; |
| 47227 | pMem->type = SQLITE_FLOAT; |
| 47228 | } |
| 47229 | } |
| 47230 | #endif |
| 47231 | |
| 47232 | /* |
| 47233 | ** Delete any previous value and set the value of pMem to be an |
| 47234 | ** empty boolean index. |
| 47235 | */ |
| @@ -47182,11 +47851,11 @@ | |
| 47851 | /* |
| 47852 | ** Return the SQL associated with a prepared statement |
| 47853 | */ |
| 47854 | SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ |
| 47855 | Vdbe *p = (Vdbe *)pStmt; |
| 47856 | return (p && p->isPrepareV2) ? p->zSql : 0; |
| 47857 | } |
| 47858 | |
| 47859 | /* |
| 47860 | ** Swap all content between two VDBE structures. |
| 47861 | */ |
| @@ -47370,10 +48039,17 @@ | |
| 48039 | assert( j>=0 && j<p->nLabel ); |
| 48040 | if( p->aLabel ){ |
| 48041 | p->aLabel[j] = p->nOp; |
| 48042 | } |
| 48043 | } |
| 48044 | |
| 48045 | /* |
| 48046 | ** Mark the VDBE as one that can only be run one time. |
| 48047 | */ |
| 48048 | SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){ |
| 48049 | p->runOnlyOnce = 1; |
| 48050 | } |
| 48051 | |
| 48052 | #ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ |
| 48053 | |
| 48054 | /* |
| 48055 | ** The following type and function are used to iterate through all opcodes |
| @@ -48175,11 +48851,10 @@ | |
| 48851 | int rc = SQLITE_OK; /* Return code */ |
| 48852 | Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */ |
| 48853 | |
| 48854 | assert( p->explain ); |
| 48855 | assert( p->magic==VDBE_MAGIC_RUN ); |
| 48856 | assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); |
| 48857 | |
| 48858 | /* Even though this opcode does not use dynamic strings for |
| 48859 | ** the result, result columns may become dynamic if the user calls |
| 48860 | ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. |
| @@ -48590,13 +49265,11 @@ | |
| 49265 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 49266 | if( pCx->pVtabCursor ){ |
| 49267 | sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; |
| 49268 | const sqlite3_module *pModule = pCx->pModule; |
| 49269 | p->inVtabMethod = 1; |
| 49270 | pModule->xClose(pVtabCursor); |
| 49271 | p->inVtabMethod = 0; |
| 49272 | } |
| 49273 | #endif |
| 49274 | } |
| 49275 | |
| @@ -48773,13 +49446,11 @@ | |
| 49446 | } |
| 49447 | } |
| 49448 | |
| 49449 | /* If there are any write-transactions at all, invoke the commit hook */ |
| 49450 | if( needXcommit && db->xCommitCallback ){ |
| 49451 | rc = db->xCommitCallback(db->pCommitArg); |
| 49452 | if( rc ){ |
| 49453 | return SQLITE_CONSTRAINT; |
| 49454 | } |
| 49455 | } |
| 49456 | |
| @@ -49329,13 +50000,11 @@ | |
| 50000 | |
| 50001 | /* If the VM did not run to completion or if it encountered an |
| 50002 | ** error, then it might not have been halted properly. So halt |
| 50003 | ** it now. |
| 50004 | */ |
| 50005 | sqlite3VdbeHalt(p); |
| 50006 | |
| 50007 | /* If the VDBE has be run even partially, then transfer the error code |
| 50008 | ** and error message from the VDBE into the main database structure. But |
| 50009 | ** if the VDBE has just been set to run but has not actually executed any |
| 50010 | ** instructions yet, leave the main database error information unchanged. |
| @@ -49351,10 +50020,11 @@ | |
| 50020 | }else if( p->rc ){ |
| 50021 | sqlite3Error(db, p->rc, 0); |
| 50022 | }else{ |
| 50023 | sqlite3Error(db, SQLITE_OK, 0); |
| 50024 | } |
| 50025 | if( p->runOnlyOnce ) p->expired = 1; |
| 50026 | }else if( p->rc && p->expired ){ |
| 50027 | /* The expired flag was set on the VDBE before the first call |
| 50028 | ** to sqlite3_step(). For consistency (since sqlite3_step() was |
| 50029 | ** called), set the database error in this case as well. |
| 50030 | */ |
| @@ -49452,10 +50122,11 @@ | |
| 50122 | sqlite3DbFree(db, p->aLabel); |
| 50123 | sqlite3DbFree(db, p->aColName); |
| 50124 | sqlite3DbFree(db, p->zSql); |
| 50125 | p->magic = VDBE_MAGIC_DEAD; |
| 50126 | sqlite3DbFree(db, p->pFree); |
| 50127 | p->db = 0; |
| 50128 | sqlite3DbFree(db, p); |
| 50129 | } |
| 50130 | |
| 50131 | /* |
| 50132 | ** Make sure the cursor p is ready to read or write the row to which it |
| @@ -50132,11 +50803,11 @@ | |
| 50803 | assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ |
| 50804 | /* nCellKey will always be between 0 and 0xffffffff because of the say |
| 50805 | ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ |
| 50806 | if( nCellKey<=0 || nCellKey>0x7fffffff ){ |
| 50807 | *res = 0; |
| 50808 | return SQLITE_CORRUPT_BKPT; |
| 50809 | } |
| 50810 | memset(&m, 0, sizeof(m)); |
| 50811 | rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m); |
| 50812 | if( rc ){ |
| 50813 | return rc; |
| @@ -50258,10 +50929,32 @@ | |
| 50929 | SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ |
| 50930 | Vdbe *p = (Vdbe*)pStmt; |
| 50931 | return p==0 || p->expired; |
| 50932 | } |
| 50933 | #endif |
| 50934 | |
| 50935 | /* |
| 50936 | ** Check on a Vdbe to make sure it has not been finalized. Log |
| 50937 | ** an error and return true if it has been finalized (or is otherwise |
| 50938 | ** invalid). Return false if it is ok. |
| 50939 | */ |
| 50940 | static int vdbeSafety(Vdbe *p){ |
| 50941 | if( p->db==0 ){ |
| 50942 | sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement"); |
| 50943 | return 1; |
| 50944 | }else{ |
| 50945 | return 0; |
| 50946 | } |
| 50947 | } |
| 50948 | static int vdbeSafetyNotNull(Vdbe *p){ |
| 50949 | if( p==0 ){ |
| 50950 | sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement"); |
| 50951 | return 1; |
| 50952 | }else{ |
| 50953 | return vdbeSafety(p); |
| 50954 | } |
| 50955 | } |
| 50956 | |
| 50957 | /* |
| 50958 | ** The following routine destroys a virtual machine that is created by |
| 50959 | ** the sqlite3_compile() routine. The integer returned is an SQLITE_ |
| 50960 | ** success/failure code that describes the result of executing the virtual |
| @@ -50276,11 +50969,15 @@ | |
| 50969 | rc = SQLITE_OK; |
| 50970 | }else{ |
| 50971 | Vdbe *v = (Vdbe*)pStmt; |
| 50972 | sqlite3 *db = v->db; |
| 50973 | #if SQLITE_THREADSAFE |
| 50974 | sqlite3_mutex *mutex; |
| 50975 | #endif |
| 50976 | if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; |
| 50977 | #if SQLITE_THREADSAFE |
| 50978 | mutex = v->db->mutex; |
| 50979 | #endif |
| 50980 | sqlite3_mutex_enter(mutex); |
| 50981 | rc = sqlite3VdbeFinalize(v); |
| 50982 | rc = sqlite3ApiExit(db, rc); |
| 50983 | sqlite3_mutex_leave(mutex); |
| @@ -50523,30 +51220,27 @@ | |
| 51220 | sqlite3 *db; |
| 51221 | int rc; |
| 51222 | |
| 51223 | assert(p); |
| 51224 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| 51225 | sqlite3_log(SQLITE_MISUSE, |
| 51226 | "attempt to step a halted statement: [%s]", p->zSql); |
| 51227 | return SQLITE_MISUSE_BKPT; |
| 51228 | } |
| 51229 | |
| 51230 | /* Check that malloc() has not failed. If it has, return early. */ |
| 51231 | db = p->db; |
| 51232 | if( db->mallocFailed ){ |
| 51233 | p->rc = SQLITE_NOMEM; |
| 51234 | return SQLITE_NOMEM; |
| 51235 | } |
| 51236 | |
| 51237 | if( p->pc<=0 && p->expired ){ |
| 51238 | p->rc = SQLITE_SCHEMA; |
| 51239 | rc = SQLITE_ERROR; |
| 51240 | goto end_of_step; |
| 51241 | } |
| 51242 | if( p->pc<0 ){ |
| 51243 | /* If there are no other statements currently running, then |
| 51244 | ** reset the interrupt flag. This prevents a call to sqlite3_interrupt |
| 51245 | ** from interrupting a statement that has not yet started. |
| 51246 | */ |
| @@ -50575,14 +51269,10 @@ | |
| 51269 | #endif /* SQLITE_OMIT_EXPLAIN */ |
| 51270 | { |
| 51271 | rc = sqlite3VdbeExec(p); |
| 51272 | } |
| 51273 | |
| 51274 | #ifndef SQLITE_OMIT_TRACE |
| 51275 | /* Invoke the profile callback if there is one |
| 51276 | */ |
| 51277 | if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){ |
| 51278 | double rNow; |
| @@ -50625,43 +51315,48 @@ | |
| 51315 | ** This is the top-level implementation of sqlite3_step(). Call |
| 51316 | ** sqlite3Step() to do most of the work. If a schema error occurs, |
| 51317 | ** call sqlite3Reprepare() and try again. |
| 51318 | */ |
| 51319 | SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ |
| 51320 | int rc = SQLITE_OK; /* Result from sqlite3Step() */ |
| 51321 | int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ |
| 51322 | Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ |
| 51323 | int cnt = 0; /* Counter to prevent infinite loop of reprepares */ |
| 51324 | sqlite3 *db; /* The database connection */ |
| 51325 | |
| 51326 | if( vdbeSafetyNotNull(v) ){ |
| 51327 | return SQLITE_MISUSE_BKPT; |
| 51328 | } |
| 51329 | db = v->db; |
| 51330 | sqlite3_mutex_enter(db->mutex); |
| 51331 | while( (rc = sqlite3Step(v))==SQLITE_SCHEMA |
| 51332 | && cnt++ < 5 |
| 51333 | && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ |
| 51334 | sqlite3_reset(pStmt); |
| 51335 | v->expired = 0; |
| 51336 | } |
| 51337 | if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ |
| 51338 | /* This case occurs after failing to recompile an sql statement. |
| 51339 | ** The error message from the SQL compiler has already been loaded |
| 51340 | ** into the database handle. This block copies the error message |
| 51341 | ** from the database handle into the statement and sets the statement |
| 51342 | ** program counter to 0 to ensure that when the statement is |
| 51343 | ** finalized or reset the parser error message is available via |
| 51344 | ** sqlite3_errmsg() and sqlite3_errcode(). |
| 51345 | */ |
| 51346 | const char *zErr = (const char *)sqlite3_value_text(db->pErr); |
| 51347 | sqlite3DbFree(db, v->zErrMsg); |
| 51348 | if( !db->mallocFailed ){ |
| 51349 | v->zErrMsg = sqlite3DbStrDup(db, zErr); |
| 51350 | v->rc = rc2; |
| 51351 | } else { |
| 51352 | v->zErrMsg = 0; |
| 51353 | v->rc = rc = SQLITE_NOMEM; |
| 51354 | } |
| 51355 | } |
| 51356 | rc = sqlite3ApiExit(db, rc); |
| 51357 | sqlite3_mutex_leave(db->mutex); |
| 51358 | return rc; |
| 51359 | } |
| 51360 | |
| 51361 | /* |
| 51362 | ** Extract the user data from a sqlite3_context structure and return a |
| @@ -51127,16 +51822,20 @@ | |
| 51822 | ** The error code stored in database p->db is overwritten with the return |
| 51823 | ** value in any case. |
| 51824 | */ |
| 51825 | static int vdbeUnbind(Vdbe *p, int i){ |
| 51826 | Mem *pVar; |
| 51827 | if( vdbeSafetyNotNull(p) ){ |
| 51828 | return SQLITE_MISUSE_BKPT; |
| 51829 | } |
| 51830 | sqlite3_mutex_enter(p->db->mutex); |
| 51831 | if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ |
| 51832 | sqlite3Error(p->db, SQLITE_MISUSE, 0); |
| 51833 | sqlite3_mutex_leave(p->db->mutex); |
| 51834 | sqlite3_log(SQLITE_MISUSE, |
| 51835 | "bind on a busy prepared statement: [%s]", p->zSql); |
| 51836 | return SQLITE_MISUSE_BKPT; |
| 51837 | } |
| 51838 | if( i<1 || i>p->nVar ){ |
| 51839 | sqlite3Error(p->db, SQLITE_RANGE, 0); |
| 51840 | sqlite3_mutex_leave(p->db->mutex); |
| 51841 | return SQLITE_RANGE; |
| @@ -52225,11 +52924,11 @@ | |
| 52924 | ** used to clean up the mess that was left behind. |
| 52925 | */ |
| 52926 | SQLITE_PRIVATE int sqlite3VdbeExec( |
| 52927 | Vdbe *p /* The VDBE */ |
| 52928 | ){ |
| 52929 | int pc=0; /* The program counter */ |
| 52930 | Op *aOp = p->aOp; /* Copy of p->aOp */ |
| 52931 | Op *pOp; /* Current operation */ |
| 52932 | int rc = SQLITE_OK; /* Value to return */ |
| 52933 | sqlite3 *db = p->db; /* The database */ |
| 52934 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */ |
| @@ -52336,11 +53035,11 @@ | |
| 53035 | Mem *pDest; /* Where to write the extracted value */ |
| 53036 | Mem sMem; /* For storing the record being decoded */ |
| 53037 | u8 *zIdx; /* Index into header */ |
| 53038 | u8 *zEndHdr; /* Pointer to first byte after the header */ |
| 53039 | u32 offset; /* Offset into the data */ |
| 53040 | u32 szField; /* Number of bytes in the content of a field */ |
| 53041 | int szHdr; /* Size of the header size field at start of record */ |
| 53042 | int avail; /* Number of bytes of available data */ |
| 53043 | Mem *pReg; /* PseudoTable input register */ |
| 53044 | } am; |
| 53045 | struct OP_Affinity_stack_vars { |
| @@ -52648,11 +53347,10 @@ | |
| 53347 | } u; |
| 53348 | /* End automatically generated code |
| 53349 | ********************************************************************/ |
| 53350 | |
| 53351 | assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ |
| 53352 | sqlite3VdbeMutexArrayEnter(p); |
| 53353 | if( p->rc==SQLITE_NOMEM ){ |
| 53354 | /* This happens if a malloc() inside a call to sqlite3_column_text() or |
| 53355 | ** sqlite3_column_text16() failed. */ |
| 53356 | goto no_mem; |
| @@ -52733,13 +53431,11 @@ | |
| 53431 | ** a return code SQLITE_ABORT. |
| 53432 | */ |
| 53433 | if( checkProgress ){ |
| 53434 | if( db->nProgressOps==nProgressOps ){ |
| 53435 | int prc; |
| 53436 | prc = db->xProgress(db->pProgressArg); |
| 53437 | if( prc!=0 ){ |
| 53438 | rc = SQLITE_INTERRUPT; |
| 53439 | goto vdbe_error_halt; |
| 53440 | } |
| 53441 | nProgressOps = 0; |
| @@ -52937,11 +53633,17 @@ | |
| 53633 | |
| 53634 | p->rc = pOp->p1; |
| 53635 | p->errorAction = (u8)pOp->p2; |
| 53636 | p->pc = pc; |
| 53637 | if( pOp->p4.z ){ |
| 53638 | assert( p->rc!=SQLITE_OK ); |
| 53639 | sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); |
| 53640 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 53641 | sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z); |
| 53642 | }else if( p->rc ){ |
| 53643 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 53644 | sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql); |
| 53645 | } |
| 53646 | rc = sqlite3VdbeHalt(p); |
| 53647 | assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); |
| 53648 | if( rc==SQLITE_BUSY ){ |
| 53649 | p->rc = rc = SQLITE_BUSY; |
| @@ -52971,10 +53673,11 @@ | |
| 53673 | assert( pOp->p4.pI64!=0 ); |
| 53674 | pOut->u.i = *pOp->p4.pI64; |
| 53675 | break; |
| 53676 | } |
| 53677 | |
| 53678 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 53679 | /* Opcode: Real * P2 * P4 * |
| 53680 | ** |
| 53681 | ** P4 is a pointer to a 64-bit floating point value. |
| 53682 | ** Write that value into register P2. |
| 53683 | */ |
| @@ -52982,10 +53685,11 @@ | |
| 53685 | pOut->flags = MEM_Real; |
| 53686 | assert( !sqlite3IsNaN(*pOp->p4.pReal) ); |
| 53687 | pOut->r = *pOp->p4.pReal; |
| 53688 | break; |
| 53689 | } |
| 53690 | #endif |
| 53691 | |
| 53692 | /* Opcode: String8 * P2 * P4 * |
| 53693 | ** |
| 53694 | ** P4 points to a nul terminated UTF-8 string. This opcode is transformed |
| 53695 | ** into an OP_String before it is executed for the first time. |
| @@ -53392,18 +54096,23 @@ | |
| 54096 | if( u.af.iA==-1 ) u.af.iA = 1; |
| 54097 | u.af.rB = (double)(u.af.iB % u.af.iA); |
| 54098 | break; |
| 54099 | } |
| 54100 | } |
| 54101 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 54102 | pOut->u.i = u.af.rB; |
| 54103 | MemSetTypeFlag(pOut, MEM_Int); |
| 54104 | #else |
| 54105 | if( sqlite3IsNaN(u.af.rB) ){ |
| 54106 | goto arithmetic_result_is_null; |
| 54107 | } |
| 54108 | pOut->r = u.af.rB; |
| 54109 | MemSetTypeFlag(pOut, MEM_Real); |
| 54110 | if( (u.af.flags & MEM_Real)==0 ){ |
| 54111 | sqlite3VdbeIntegerAffinity(pOut); |
| 54112 | } |
| 54113 | #endif |
| 54114 | } |
| 54115 | break; |
| 54116 | |
| 54117 | arithmetic_result_is_null: |
| 54118 | sqlite3VdbeMemSetNull(pOut); |
| @@ -53492,25 +54201,16 @@ | |
| 54201 | assert( pOp>aOp ); |
| 54202 | assert( pOp[-1].p4type==P4_COLLSEQ ); |
| 54203 | assert( pOp[-1].opcode==OP_CollSeq ); |
| 54204 | u.ag.ctx.pColl = pOp[-1].p4.pColl; |
| 54205 | } |
| 54206 | (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); |
| 54207 | if( db->mallocFailed ){ |
| 54208 | /* Even though a malloc() has failed, the implementation of the |
| 54209 | ** user function may have called an sqlite3_result_XXX() function |
| 54210 | ** to return a value. The following call releases any resources |
| 54211 | ** associated with such a value. |
| 54212 | */ |
| 54213 | sqlite3VdbeMemRelease(&u.ag.ctx.s); |
| 54214 | goto no_mem; |
| 54215 | } |
| 54216 | |
| @@ -53631,10 +54331,11 @@ | |
| 54331 | MemSetTypeFlag(pIn1, MEM_Int); |
| 54332 | } |
| 54333 | break; |
| 54334 | } |
| 54335 | |
| 54336 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 54337 | /* Opcode: RealAffinity P1 * * * * |
| 54338 | ** |
| 54339 | ** If register P1 holds an integer convert it to a real value. |
| 54340 | ** |
| 54341 | ** This opcode is used when extracting information from a column that |
| @@ -53647,10 +54348,11 @@ | |
| 54348 | if( pIn1->flags & MEM_Int ){ |
| 54349 | sqlite3VdbeMemRealify(pIn1); |
| 54350 | } |
| 54351 | break; |
| 54352 | } |
| 54353 | #endif |
| 54354 | |
| 54355 | #ifndef SQLITE_OMIT_CAST |
| 54356 | /* Opcode: ToText P1 * * * * |
| 54357 | ** |
| 54358 | ** Force the value in register P1 to be text. |
| @@ -53730,11 +54432,11 @@ | |
| 54432 | sqlite3VdbeMemIntegerify(pIn1); |
| 54433 | } |
| 54434 | break; |
| 54435 | } |
| 54436 | |
| 54437 | #if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) |
| 54438 | /* Opcode: ToReal P1 * * * * |
| 54439 | ** |
| 54440 | ** Force the value in register P1 to be a floating point number. |
| 54441 | ** If The value is currently an integer, convert it. |
| 54442 | ** If the value is text or blob, try to convert it to an integer using the |
| @@ -53747,11 +54449,11 @@ | |
| 54449 | if( (pIn1->flags & MEM_Null)==0 ){ |
| 54450 | sqlite3VdbeMemRealify(pIn1); |
| 54451 | } |
| 54452 | break; |
| 54453 | } |
| 54454 | #endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */ |
| 54455 | |
| 54456 | /* Opcode: Lt P1 P2 P3 P4 P5 |
| 54457 | ** |
| 54458 | ** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then |
| 54459 | ** jump to address P2. |
| @@ -54169,11 +54871,11 @@ | |
| 54871 | Mem *pDest; /* Where to write the extracted value */ |
| 54872 | Mem sMem; /* For storing the record being decoded */ |
| 54873 | u8 *zIdx; /* Index into header */ |
| 54874 | u8 *zEndHdr; /* Pointer to first byte after the header */ |
| 54875 | u32 offset; /* Offset into the data */ |
| 54876 | u32 szField; /* Number of bytes in the content of a field */ |
| 54877 | int szHdr; /* Size of the header size field at start of record */ |
| 54878 | int avail; /* Number of bytes of available data */ |
| 54879 | Mem *pReg; /* PseudoTable input register */ |
| 54880 | #endif /* local variables moved into u.am */ |
| 54881 | |
| @@ -54345,16 +55047,20 @@ | |
| 55047 | /* Scan the header and use it to fill in the u.am.aType[] and u.am.aOffset[] |
| 55048 | ** arrays. u.am.aType[u.am.i] will contain the type integer for the u.am.i-th |
| 55049 | ** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning |
| 55050 | ** of the record to the start of the data for the u.am.i-th column |
| 55051 | */ |
| 55052 | for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){ |
| 55053 | if( u.am.zIdx<u.am.zEndHdr ){ |
| 55054 | u.am.aOffset[u.am.i] = u.am.offset; |
| 55055 | u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]); |
| 55056 | u.am.szField = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]); |
| 55057 | u.am.offset += u.am.szField; |
| 55058 | if( u.am.offset<u.am.szField ){ /* True if u.am.offset overflows */ |
| 55059 | u.am.zIdx = &u.am.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */ |
| 55060 | break; |
| 55061 | } |
| 55062 | }else{ |
| 55063 | /* If u.am.i is less that u.am.nField, then there are less fields in this |
| 55064 | ** record than SetNumColumns indicated there are columns in the |
| 55065 | ** table. Set the u.am.offset for any extra columns not present in |
| 55066 | ** the record to 0. This tells code below to store a NULL |
| @@ -54370,12 +55076,12 @@ | |
| 55076 | ** or if the end of the last field appears to be past the end of the |
| 55077 | ** record, or if the end of the last field appears to be before the end |
| 55078 | ** of the record (when all fields present), then we must be dealing |
| 55079 | ** with a corrupt database. |
| 55080 | */ |
| 55081 | if( (u.am.zIdx > u.am.zEndHdr) || (u.am.offset > u.am.payloadSize) |
| 55082 | || (u.am.zIdx==u.am.zEndHdr && u.am.offset!=u.am.payloadSize) ){ |
| 55083 | rc = SQLITE_CORRUPT_BKPT; |
| 55084 | goto op_column_out; |
| 55085 | } |
| 55086 | } |
| 55087 | |
| @@ -55239,11 +55945,11 @@ | |
| 55945 | ** Open a new cursor that points to a fake table that contains a single |
| 55946 | ** row of data. The content of that one row in the content of memory |
| 55947 | ** register P2. In other words, cursor P1 becomes an alias for the |
| 55948 | ** MEM_Blob content contained in register P2. |
| 55949 | ** |
| 55950 | ** A pseudo-table created by this opcode is used to hold a single |
| 55951 | ** row output from the sorter so that the row can be decomposed into |
| 55952 | ** individual columns using the OP_Column opcode. The OP_Column opcode |
| 55953 | ** is the only cursor opcode that works with a pseudo-table. |
| 55954 | ** |
| 55955 | ** P3 is the number of fields in the records that will be stored by |
| @@ -56191,16 +56897,14 @@ | |
| 56897 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 56898 | }else if( u.bi.pC->pVtabCursor ){ |
| 56899 | u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab; |
| 56900 | u.bi.pModule = u.bi.pVtab->pModule; |
| 56901 | assert( u.bi.pModule->xRowid ); |
| 56902 | rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v); |
| 56903 | sqlite3DbFree(db, p->zErrMsg); |
| 56904 | p->zErrMsg = u.bi.pVtab->zErrMsg; |
| 56905 | u.bi.pVtab->zErrMsg = 0; |
| 56906 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 56907 | }else{ |
| 56908 | assert( u.bi.pC->pCursor!=0 ); |
| 56909 | rc = sqlite3VdbeCursorMoveto(u.bi.pC); |
| 56910 | if( rc ) goto abort_due_to_error; |
| @@ -56751,25 +57455,23 @@ | |
| 57455 | u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb); |
| 57456 | u.bu.initData.db = db; |
| 57457 | u.bu.initData.iDb = pOp->p1; |
| 57458 | u.bu.initData.pzErrMsg = &p->zErrMsg; |
| 57459 | u.bu.zSql = sqlite3MPrintf(db, |
| 57460 | "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", |
| 57461 | db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z); |
| 57462 | if( u.bu.zSql==0 ){ |
| 57463 | rc = SQLITE_NOMEM; |
| 57464 | }else{ |
| 57465 | assert( db->init.busy==0 ); |
| 57466 | db->init.busy = 1; |
| 57467 | u.bu.initData.rc = SQLITE_OK; |
| 57468 | assert( !db->mallocFailed ); |
| 57469 | rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0); |
| 57470 | if( rc==SQLITE_OK ) rc = u.bu.initData.rc; |
| 57471 | sqlite3DbFree(db, u.bu.zSql); |
| 57472 | db->init.busy = 0; |
| 57473 | } |
| 57474 | } |
| 57475 | sqlite3BtreeLeaveAll(db); |
| 57476 | if( rc==SQLITE_NOMEM ){ |
| 57477 | goto no_mem; |
| @@ -57351,13 +58053,11 @@ | |
| 58053 | ** Vacuum the entire database. This opcode will cause other virtual |
| 58054 | ** machines to be created and run. It may not be called from within |
| 58055 | ** a transaction. |
| 58056 | */ |
| 58057 | case OP_Vacuum: { |
| 58058 | rc = sqlite3RunVacuum(&p->zErrMsg, db); |
| 58059 | break; |
| 58060 | } |
| 58061 | #endif |
| 58062 | |
| 58063 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| @@ -57503,16 +58203,14 @@ | |
| 58203 | u.cf.pCur = 0; |
| 58204 | u.cf.pVtabCursor = 0; |
| 58205 | u.cf.pVtab = pOp->p4.pVtab->pVtab; |
| 58206 | u.cf.pModule = (sqlite3_module *)u.cf.pVtab->pModule; |
| 58207 | assert(u.cf.pVtab && u.cf.pModule); |
| 58208 | rc = u.cf.pModule->xOpen(u.cf.pVtab, &u.cf.pVtabCursor); |
| 58209 | sqlite3DbFree(db, p->zErrMsg); |
| 58210 | p->zErrMsg = u.cf.pVtab->zErrMsg; |
| 58211 | u.cf.pVtab->zErrMsg = 0; |
| 58212 | if( SQLITE_OK==rc ){ |
| 58213 | /* Initialize sqlite3_vtab_cursor base class */ |
| 58214 | u.cf.pVtabCursor->pVtab = u.cf.pVtab; |
| 58215 | |
| 58216 | /* Initialise vdbe cursor object */ |
| @@ -57584,21 +58282,19 @@ | |
| 58282 | for(u.cg.i = 0; u.cg.i<u.cg.nArg; u.cg.i++){ |
| 58283 | u.cg.apArg[u.cg.i] = &u.cg.pArgc[u.cg.i+1]; |
| 58284 | sqlite3VdbeMemStoreType(u.cg.apArg[u.cg.i]); |
| 58285 | } |
| 58286 | |
| 58287 | p->inVtabMethod = 1; |
| 58288 | rc = u.cg.pModule->xFilter(u.cg.pVtabCursor, u.cg.iQuery, pOp->p4.z, u.cg.nArg, u.cg.apArg); |
| 58289 | p->inVtabMethod = 0; |
| 58290 | sqlite3DbFree(db, p->zErrMsg); |
| 58291 | p->zErrMsg = u.cg.pVtab->zErrMsg; |
| 58292 | u.cg.pVtab->zErrMsg = 0; |
| 58293 | if( rc==SQLITE_OK ){ |
| 58294 | u.cg.res = u.cg.pModule->xEof(u.cg.pVtabCursor); |
| 58295 | } |
| 58296 | |
| 58297 | if( u.cg.res ){ |
| 58298 | pc = pOp->p2 - 1; |
| 58299 | } |
| 58300 | } |
| @@ -57642,11 +58338,10 @@ | |
| 58338 | ** new one. |
| 58339 | */ |
| 58340 | sqlite3VdbeMemMove(&u.ch.sContext.s, u.ch.pDest); |
| 58341 | MemSetTypeFlag(&u.ch.sContext.s, MEM_Null); |
| 58342 | |
| 58343 | rc = u.ch.pModule->xColumn(pCur->pVtabCursor, &u.ch.sContext, pOp->p2); |
| 58344 | sqlite3DbFree(db, p->zErrMsg); |
| 58345 | p->zErrMsg = u.ch.pVtab->zErrMsg; |
| 58346 | u.ch.pVtab->zErrMsg = 0; |
| 58347 | if( u.ch.sContext.isError ){ |
| @@ -57660,13 +58355,10 @@ | |
| 58355 | sqlite3VdbeChangeEncoding(&u.ch.sContext.s, encoding); |
| 58356 | sqlite3VdbeMemMove(u.ch.pDest, &u.ch.sContext.s); |
| 58357 | REGISTER_TRACE(pOp->p3, u.ch.pDest); |
| 58358 | UPDATE_MAX_BLOBSIZE(u.ch.pDest); |
| 58359 | |
| 58360 | if( sqlite3VdbeMemTooBig(u.ch.pDest) ){ |
| 58361 | goto too_big; |
| 58362 | } |
| 58363 | break; |
| 58364 | } |
| @@ -57701,21 +58393,19 @@ | |
| 58393 | ** underlying implementation to return an error if one occurs during |
| 58394 | ** xNext(). Instead, if an error occurs, true is returned (indicating that |
| 58395 | ** data is available) and the error code returned when xColumn or |
| 58396 | ** some other method is next invoked on the save virtual table cursor. |
| 58397 | */ |
| 58398 | p->inVtabMethod = 1; |
| 58399 | rc = u.ci.pModule->xNext(u.ci.pCur->pVtabCursor); |
| 58400 | p->inVtabMethod = 0; |
| 58401 | sqlite3DbFree(db, p->zErrMsg); |
| 58402 | p->zErrMsg = u.ci.pVtab->zErrMsg; |
| 58403 | u.ci.pVtab->zErrMsg = 0; |
| 58404 | if( rc==SQLITE_OK ){ |
| 58405 | u.ci.res = u.ci.pModule->xEof(u.ci.pCur->pVtabCursor); |
| 58406 | } |
| 58407 | |
| 58408 | if( !u.ci.res ){ |
| 58409 | /* If there is data, jump to P2 */ |
| 58410 | pc = pOp->p2 - 1; |
| 58411 | } |
| @@ -57739,16 +58429,14 @@ | |
| 58429 | u.cj.pVtab = pOp->p4.pVtab->pVtab; |
| 58430 | u.cj.pName = &aMem[pOp->p1]; |
| 58431 | assert( u.cj.pVtab->pModule->xRename ); |
| 58432 | REGISTER_TRACE(pOp->p1, u.cj.pName); |
| 58433 | assert( u.cj.pName->flags & MEM_Str ); |
| 58434 | rc = u.cj.pVtab->pModule->xRename(u.cj.pVtab, u.cj.pName->z); |
| 58435 | sqlite3DbFree(db, p->zErrMsg); |
| 58436 | p->zErrMsg = u.cj.pVtab->zErrMsg; |
| 58437 | u.cj.pVtab->zErrMsg = 0; |
| 58438 | |
| 58439 | break; |
| 58440 | } |
| 58441 | #endif |
| 58442 | |
| @@ -57797,16 +58485,14 @@ | |
| 58485 | for(u.ck.i=0; u.ck.i<u.ck.nArg; u.ck.i++){ |
| 58486 | sqlite3VdbeMemStoreType(u.ck.pX); |
| 58487 | u.ck.apArg[u.ck.i] = u.ck.pX; |
| 58488 | u.ck.pX++; |
| 58489 | } |
| 58490 | rc = u.ck.pModule->xUpdate(u.ck.pVtab, u.ck.nArg, u.ck.apArg, &u.ck.rowid); |
| 58491 | sqlite3DbFree(db, p->zErrMsg); |
| 58492 | p->zErrMsg = u.ck.pVtab->zErrMsg; |
| 58493 | u.ck.pVtab->zErrMsg = 0; |
| 58494 | if( rc==SQLITE_OK && pOp->p1 ){ |
| 58495 | assert( u.ck.nArg>1 && u.ck.apArg[0] && (u.ck.apArg[0]->flags&MEM_Null) ); |
| 58496 | db->lastRowid = u.ck.rowid; |
| 58497 | } |
| 58498 | p->nChange++; |
| @@ -57879,10 +58565,11 @@ | |
| 58565 | ** is to say when the EXPLAIN QUERY PLAN syntax is used.) |
| 58566 | ** This opcode records information from the optimizer. It is the |
| 58567 | ** the same as a no-op. This opcodesnever appears in a real VM program. |
| 58568 | */ |
| 58569 | default: { /* This is really OP_Noop and OP_Explain */ |
| 58570 | assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); |
| 58571 | break; |
| 58572 | } |
| 58573 | |
| 58574 | /***************************************************************************** |
| 58575 | ** The cases of the switch statement above this line should all be indented |
| @@ -57930,10 +58617,11 @@ | |
| 58617 | ** an error of some kind. |
| 58618 | */ |
| 58619 | vdbe_error_halt: |
| 58620 | assert( rc ); |
| 58621 | p->rc = rc; |
| 58622 | sqlite3_log(rc, "prepared statement aborts at %d: [%s]", pc, p->zSql); |
| 58623 | sqlite3VdbeHalt(p); |
| 58624 | if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; |
| 58625 | rc = SQLITE_ERROR; |
| 58626 | if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0); |
| 58627 | |
| @@ -57958,16 +58646,10 @@ | |
| 58646 | db->mallocFailed = 1; |
| 58647 | sqlite3SetString(&p->zErrMsg, db, "out of memory"); |
| 58648 | rc = SQLITE_NOMEM; |
| 58649 | goto vdbe_error_halt; |
| 58650 | |
| 58651 | /* Jump to here for any other kind of fatal error. The "rc" variable |
| 58652 | ** should hold the error number. |
| 58653 | */ |
| 58654 | abort_due_to_error: |
| 58655 | assert( p->zErrMsg==0 ); |
| @@ -58083,17 +58765,10 @@ | |
| 58765 | } |
| 58766 | do { |
| 58767 | memset(pParse, 0, sizeof(Parse)); |
| 58768 | pParse->db = db; |
| 58769 | |
| 58770 | sqlite3BtreeEnterAll(db); |
| 58771 | pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); |
| 58772 | if( pTab && IsVirtual(pTab) ){ |
| 58773 | pTab = 0; |
| 58774 | sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); |
| @@ -58109,11 +58784,10 @@ | |
| 58784 | sqlite3DbFree(db, zErr); |
| 58785 | zErr = pParse->zErrMsg; |
| 58786 | pParse->zErrMsg = 0; |
| 58787 | } |
| 58788 | rc = SQLITE_ERROR; |
| 58789 | sqlite3BtreeLeaveAll(db); |
| 58790 | goto blob_open_out; |
| 58791 | } |
| 58792 | |
| 58793 | /* Now search pTab for the exact column. */ |
| @@ -58124,11 +58798,10 @@ | |
| 58798 | } |
| 58799 | if( iCol==pTab->nCol ){ |
| 58800 | sqlite3DbFree(db, zErr); |
| 58801 | zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); |
| 58802 | rc = SQLITE_ERROR; |
| 58803 | sqlite3BtreeLeaveAll(db); |
| 58804 | goto blob_open_out; |
| 58805 | } |
| 58806 | |
| 58807 | /* If the value is being opened for writing, check that the |
| @@ -58165,11 +58838,10 @@ | |
| 58838 | } |
| 58839 | if( zFault ){ |
| 58840 | sqlite3DbFree(db, zErr); |
| 58841 | zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault); |
| 58842 | rc = SQLITE_ERROR; |
| 58843 | sqlite3BtreeLeaveAll(db); |
| 58844 | goto blob_open_out; |
| 58845 | } |
| 58846 | } |
| 58847 | |
| @@ -58215,12 +58887,11 @@ | |
| 58887 | sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0); |
| 58888 | } |
| 58889 | } |
| 58890 | |
| 58891 | sqlite3BtreeLeaveAll(db); |
| 58892 | if( db->mallocFailed ){ |
| 58893 | goto blob_open_out; |
| 58894 | } |
| 58895 | |
| 58896 | sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow); |
| 58897 | rc = sqlite3_step((sqlite3_stmt *)v); |
| @@ -58317,11 +58988,11 @@ | |
| 58988 | int rc; |
| 58989 | Incrblob *p = (Incrblob *)pBlob; |
| 58990 | Vdbe *v; |
| 58991 | sqlite3 *db; |
| 58992 | |
| 58993 | if( p==0 ) return SQLITE_MISUSE_BKPT; |
| 58994 | db = p->db; |
| 58995 | sqlite3_mutex_enter(db->mutex); |
| 58996 | v = (Vdbe*)p->pStmt; |
| 58997 | |
| 58998 | if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ |
| @@ -59675,10 +60346,13 @@ | |
| 60346 | Expr *pE /* The specific ORDER BY term */ |
| 60347 | ){ |
| 60348 | int i; /* Loop counter */ |
| 60349 | ExprList *pEList; /* The columns of the result set */ |
| 60350 | NameContext nc; /* Name context for resolving pE */ |
| 60351 | sqlite3 *db; /* Database connection */ |
| 60352 | int rc; /* Return code from subprocedures */ |
| 60353 | u8 savedSuppErr; /* Saved value of db->suppressErr */ |
| 60354 | |
| 60355 | assert( sqlite3ExprIsInteger(pE, &i)==0 ); |
| 60356 | pEList = pSelect->pEList; |
| 60357 | |
| 60358 | /* Resolve all names in the ORDER BY term expression |
| @@ -59687,21 +60361,23 @@ | |
| 60361 | nc.pParse = pParse; |
| 60362 | nc.pSrcList = pSelect->pSrc; |
| 60363 | nc.pEList = pEList; |
| 60364 | nc.allowAgg = 1; |
| 60365 | nc.nErr = 0; |
| 60366 | db = pParse->db; |
| 60367 | savedSuppErr = db->suppressErr; |
| 60368 | db->suppressErr = 1; |
| 60369 | rc = sqlite3ResolveExprNames(&nc, pE); |
| 60370 | db->suppressErr = savedSuppErr; |
| 60371 | if( rc ) return 0; |
| 60372 | |
| 60373 | /* Try to match the ORDER BY expression against an expression |
| 60374 | ** in the result set. Return an 1-based index of the matching |
| 60375 | ** result-set entry. |
| 60376 | */ |
| 60377 | for(i=0; i<pEList->nExpr; i++){ |
| 60378 | if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){ |
| 60379 | return i+1; |
| 60380 | } |
| 60381 | } |
| 60382 | |
| 60383 | /* If no match, return 0. */ |
| @@ -62091,10 +62767,11 @@ | |
| 62767 | memcpy(out, in, 8); |
| 62768 | } |
| 62769 | return out; |
| 62770 | } |
| 62771 | |
| 62772 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 62773 | /* |
| 62774 | ** Generate an instruction that will put the floating point |
| 62775 | ** value described by z[0..n-1] into register iMem. |
| 62776 | ** |
| 62777 | ** The z[] string will probably not be zero-terminated. But the |
| @@ -62110,10 +62787,11 @@ | |
| 62787 | if( negateFlag ) value = -value; |
| 62788 | zV = dup8bytes(v, (char*)&value); |
| 62789 | sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); |
| 62790 | } |
| 62791 | } |
| 62792 | #endif |
| 62793 | |
| 62794 | |
| 62795 | /* |
| 62796 | ** Generate an instruction that will put the integer describe by |
| 62797 | ** text z[0..n-1] into register iMem. |
| @@ -62120,11 +62798,12 @@ | |
| 62798 | ** |
| 62799 | ** The z[] string will probably not be zero-terminated. But the |
| 62800 | ** z[n] character is guaranteed to be something that does not look |
| 62801 | ** like the continuation of the number. |
| 62802 | */ |
| 62803 | static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ |
| 62804 | Vdbe *v = pParse->pVdbe; |
| 62805 | if( pExpr->flags & EP_IntValue ){ |
| 62806 | int i = pExpr->u.iValue; |
| 62807 | if( negFlag ) i = -i; |
| 62808 | sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); |
| 62809 | }else{ |
| @@ -62136,11 +62815,15 @@ | |
| 62815 | sqlite3Atoi64(z, &value); |
| 62816 | if( negFlag ) value = -value; |
| 62817 | zV = dup8bytes(v, (char*)&value); |
| 62818 | sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); |
| 62819 | }else{ |
| 62820 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 62821 | sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); |
| 62822 | #else |
| 62823 | codeReal(v, z, negFlag, iMem); |
| 62824 | #endif |
| 62825 | } |
| 62826 | } |
| 62827 | } |
| 62828 | |
| 62829 | /* |
| @@ -62523,18 +63206,20 @@ | |
| 63206 | pExpr->iColumn, pExpr->iTable, target); |
| 63207 | } |
| 63208 | break; |
| 63209 | } |
| 63210 | case TK_INTEGER: { |
| 63211 | codeInteger(pParse, pExpr, 0, target); |
| 63212 | break; |
| 63213 | } |
| 63214 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 63215 | case TK_FLOAT: { |
| 63216 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 63217 | codeReal(v, pExpr->u.zToken, 0, target); |
| 63218 | break; |
| 63219 | } |
| 63220 | #endif |
| 63221 | case TK_STRING: { |
| 63222 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 63223 | sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); |
| 63224 | break; |
| 63225 | } |
| @@ -62700,15 +63385,17 @@ | |
| 63385 | break; |
| 63386 | } |
| 63387 | case TK_UMINUS: { |
| 63388 | Expr *pLeft = pExpr->pLeft; |
| 63389 | assert( pLeft ); |
| 63390 | if( pLeft->op==TK_INTEGER ){ |
| 63391 | codeInteger(pParse, pLeft, 1, target); |
| 63392 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 63393 | }else if( pLeft->op==TK_FLOAT ){ |
| 63394 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 63395 | codeReal(v, pLeft->u.zToken, 1, target); |
| 63396 | #endif |
| 63397 | }else{ |
| 63398 | regFree1 = r1 = sqlite3GetTempReg(pParse); |
| 63399 | sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); |
| 63400 | r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); |
| 63401 | sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); |
| @@ -62952,17 +63639,19 @@ | |
| 63639 | (pExpr->iTable ? "new" : "old"), |
| 63640 | (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), |
| 63641 | target |
| 63642 | )); |
| 63643 | |
| 63644 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 63645 | /* If the column has REAL affinity, it may currently be stored as an |
| 63646 | ** integer. Use OP_RealAffinity to make sure it is really real. */ |
| 63647 | if( pExpr->iColumn>=0 |
| 63648 | && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL |
| 63649 | ){ |
| 63650 | sqlite3VdbeAddOp1(v, OP_RealAffinity, target); |
| 63651 | } |
| 63652 | #endif |
| 63653 | break; |
| 63654 | } |
| 63655 | |
| 63656 | |
| 63657 | /* |
| @@ -63624,61 +64313,65 @@ | |
| 64313 | sqlite3ReleaseTempReg(pParse, regFree1); |
| 64314 | sqlite3ReleaseTempReg(pParse, regFree2); |
| 64315 | } |
| 64316 | |
| 64317 | /* |
| 64318 | ** Do a deep comparison of two expression trees. Return 0 if the two |
| 64319 | ** expressions are completely identical. Return 1 if they differ only |
| 64320 | ** by a COLLATE operator at the top level. Return 2 if there are differences |
| 64321 | ** other than the top-level COLLATE operator. |
| 64322 | ** |
| 64323 | ** Sometimes this routine will return 2 even if the two expressions |
| 64324 | ** really are equivalent. If we cannot prove that the expressions are |
| 64325 | ** identical, we return 2 just to be safe. So if this routine |
| 64326 | ** returns 2, then you do not really know for certain if the two |
| 64327 | ** expressions are the same. But if you get a 0 or 1 return, then you |
| 64328 | ** can be sure the expressions are the same. In the places where |
| 64329 | ** this routine is used, it does not hurt to get an extra 2 - that |
| 64330 | ** just might result in some slightly slower code. But returning |
| 64331 | ** an incorrect 0 or 1 could lead to a malfunction. |
| 64332 | */ |
| 64333 | SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){ |
| 64334 | int i; |
| 64335 | if( pA==0||pB==0 ){ |
| 64336 | return pB==pA ? 0 : 2; |
| 64337 | } |
| 64338 | assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); |
| 64339 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 64340 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 64341 | return 2; |
| 64342 | } |
| 64343 | if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; |
| 64344 | if( pA->op!=pB->op ) return 2; |
| 64345 | if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; |
| 64346 | if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; |
| 64347 | |
| 64348 | if( pA->x.pList && pB->x.pList ){ |
| 64349 | if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 2; |
| 64350 | for(i=0; i<pA->x.pList->nExpr; i++){ |
| 64351 | Expr *pExprA = pA->x.pList->a[i].pExpr; |
| 64352 | Expr *pExprB = pB->x.pList->a[i].pExpr; |
| 64353 | if( sqlite3ExprCompare(pExprA, pExprB) ) return 2; |
| 64354 | } |
| 64355 | }else if( pA->x.pList || pB->x.pList ){ |
| 64356 | return 2; |
| 64357 | } |
| 64358 | |
| 64359 | if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; |
| 64360 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| 64361 | if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ |
| 64362 | return 2; |
| 64363 | } |
| 64364 | }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ |
| 64365 | if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; |
| 64366 | if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 64367 | return 2; |
| 64368 | } |
| 64369 | } |
| 64370 | if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; |
| 64371 | if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; |
| 64372 | return 0; |
| 64373 | } |
| 64374 | |
| 64375 | |
| 64376 | /* |
| 64377 | ** Add a new element to the pAggInfo->aCol[] array. Return the index of |
| @@ -63805,11 +64498,11 @@ | |
| 64498 | /* Check to see if pExpr is a duplicate of another aggregate |
| 64499 | ** function that is already in the pAggInfo structure |
| 64500 | */ |
| 64501 | struct AggInfo_func *pItem = pAggInfo->aFunc; |
| 64502 | for(i=0; i<pAggInfo->nFunc; i++, pItem++){ |
| 64503 | if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){ |
| 64504 | break; |
| 64505 | } |
| 64506 | } |
| 64507 | if( i>=pAggInfo->nFunc ){ |
| 64508 | /* pExpr is original. Make a new entry in pAggInfo->aFunc[] |
| @@ -64426,13 +65119,13 @@ | |
| 65119 | /* If foreign-key support is enabled, rewrite the CREATE TABLE |
| 65120 | ** statements corresponding to all child tables of foreign key constraints |
| 65121 | ** for which the renamed table is the parent table. */ |
| 65122 | if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ |
| 65123 | sqlite3NestedParse(pParse, |
| 65124 | "UPDATE \"%w\".%s SET " |
| 65125 | "sql = sqlite_rename_parent(sql, %Q, %Q) " |
| 65126 | "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere); |
| 65127 | sqlite3DbFree(db, zWhere); |
| 65128 | } |
| 65129 | } |
| 65130 | #endif |
| 65131 | |
| @@ -65301,13 +65994,11 @@ | |
| 65994 | zSql = sqlite3MPrintf(db, |
| 65995 | "SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase); |
| 65996 | if( zSql==0 ){ |
| 65997 | rc = SQLITE_NOMEM; |
| 65998 | }else{ |
| 65999 | rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); |
| 66000 | sqlite3DbFree(db, zSql); |
| 66001 | } |
| 66002 | |
| 66003 | |
| 66004 | /* Load the statistics from the sqlite_stat2 table. */ |
| @@ -65321,18 +66012,15 @@ | |
| 66012 | zSql = sqlite3MPrintf(db, |
| 66013 | "SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase); |
| 66014 | if( !zSql ){ |
| 66015 | rc = SQLITE_NOMEM; |
| 66016 | }else{ |
| 66017 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 66018 | sqlite3DbFree(db, zSql); |
| 66019 | } |
| 66020 | |
| 66021 | if( rc==SQLITE_OK ){ |
| 66022 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 66023 | char *zIndex = (char *)sqlite3_column_text(pStmt, 0); |
| 66024 | Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase); |
| 66025 | if( pIdx ){ |
| 66026 | int iSample = sqlite3_column_int(pStmt, 1); |
| @@ -65378,11 +66066,10 @@ | |
| 66066 | } |
| 66067 | } |
| 66068 | } |
| 66069 | } |
| 66070 | rc = sqlite3_finalize(pStmt); |
| 66071 | } |
| 66072 | } |
| 66073 | #endif |
| 66074 | |
| 66075 | if( rc==SQLITE_NOMEM ){ |
| @@ -65539,15 +66226,21 @@ | |
| 66226 | rc = SQLITE_ERROR; |
| 66227 | } |
| 66228 | pPager = sqlite3BtreePager(aNew->pBt); |
| 66229 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 66230 | sqlite3PagerJournalMode(pPager, db->dfltJournalMode); |
| 66231 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 66232 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 66233 | } |
| 66234 | aNew->safety_level = 3; |
| 66235 | aNew->zName = sqlite3DbStrDup(db, zName); |
| 66236 | if( rc==SQLITE_OK && aNew->zName==0 ){ |
| 66237 | rc = SQLITE_NOMEM; |
| 66238 | } |
| 66239 | |
| 66240 | |
| 66241 | #ifdef SQLITE_HAS_CODEC |
| 66242 | if( rc==SQLITE_OK ){ |
| 66243 | extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); |
| 66244 | extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); |
| 66245 | int nKey; |
| 66246 | char *zKey; |
| @@ -65579,15 +66272,13 @@ | |
| 66272 | ** If this fails, or if opening the file failed, then close the file and |
| 66273 | ** remove the entry from the db->aDb[] array. i.e. put everything back the way |
| 66274 | ** we found it. |
| 66275 | */ |
| 66276 | if( rc==SQLITE_OK ){ |
| 66277 | sqlite3BtreeEnterAll(db); |
| 66278 | rc = sqlite3Init(db, &zErrDyn); |
| 66279 | sqlite3BtreeLeaveAll(db); |
| 66280 | } |
| 66281 | if( rc ){ |
| 66282 | int iDb = db->nDb - 1; |
| 66283 | assert( iDb>=2 ); |
| 66284 | if( db->aDb[iDb].pBt ){ |
| @@ -66385,11 +67076,11 @@ | |
| 67076 | sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem, |
| 67077 | pParse->nTab, pParse->nMaxArg, pParse->explain, |
| 67078 | pParse->isMultiWrite && pParse->mayAbort); |
| 67079 | pParse->rc = SQLITE_DONE; |
| 67080 | pParse->colNamesSet = 0; |
| 67081 | }else{ |
| 67082 | pParse->rc = SQLITE_ERROR; |
| 67083 | } |
| 67084 | pParse->nTab = 0; |
| 67085 | pParse->nMem = 0; |
| 67086 | pParse->nSet = 0; |
| @@ -68157,17 +68848,16 @@ | |
| 68848 | if( db->mallocFailed ){ |
| 68849 | goto exit_drop_table; |
| 68850 | } |
| 68851 | assert( pParse->nErr==0 ); |
| 68852 | assert( pName->nSrc==1 ); |
| 68853 | if( noErr ) db->suppressErr++; |
| 68854 | pTab = sqlite3LocateTable(pParse, isView, |
| 68855 | pName->a[0].zName, pName->a[0].zDatabase); |
| 68856 | if( noErr ) db->suppressErr--; |
| 68857 | |
| 68858 | if( pTab==0 ){ |
| 68859 | goto exit_drop_table; |
| 68860 | } |
| 68861 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 68862 | assert( iDb>=0 && iDb<db->nDb ); |
| 68863 | |
| @@ -69585,28 +70275,32 @@ | |
| 70275 | */ |
| 70276 | SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ |
| 70277 | sqlite3 *db = pParse->db; |
| 70278 | if( db->aDb[1].pBt==0 && !pParse->explain ){ |
| 70279 | int rc; |
| 70280 | Btree *pBt; |
| 70281 | static const int flags = |
| 70282 | SQLITE_OPEN_READWRITE | |
| 70283 | SQLITE_OPEN_CREATE | |
| 70284 | SQLITE_OPEN_EXCLUSIVE | |
| 70285 | SQLITE_OPEN_DELETEONCLOSE | |
| 70286 | SQLITE_OPEN_TEMP_DB; |
| 70287 | |
| 70288 | rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, &pBt); |
| 70289 | if( rc!=SQLITE_OK ){ |
| 70290 | sqlite3ErrorMsg(pParse, "unable to open a temporary database " |
| 70291 | "file for storing temporary tables"); |
| 70292 | pParse->rc = rc; |
| 70293 | return 1; |
| 70294 | } |
| 70295 | db->aDb[1].pBt = pBt; |
| 70296 | assert( db->aDb[1].pSchema ); |
| 70297 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
| 70298 | db->mallocFailed = 1; |
| 70299 | return 1; |
| 70300 | } |
| 70301 | sqlite3PagerJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode); |
| 70302 | } |
| 70303 | return 0; |
| 70304 | } |
| 70305 | |
| 70306 | /* |
| @@ -70339,10 +71033,397 @@ | |
| 71033 | } |
| 71034 | return p; |
| 71035 | } |
| 71036 | |
| 71037 | /************** End of callback.c ********************************************/ |
| 71038 | /************** Begin file ctime.c *******************************************/ |
| 71039 | /* |
| 71040 | ** 2010 February 23 |
| 71041 | ** |
| 71042 | ** The author disclaims copyright to this source code. In place of |
| 71043 | ** a legal notice, here is a blessing: |
| 71044 | ** |
| 71045 | ** May you do good and not evil. |
| 71046 | ** May you find forgiveness for yourself and forgive others. |
| 71047 | ** May you share freely, never taking more than you give. |
| 71048 | ** |
| 71049 | ************************************************************************* |
| 71050 | ** |
| 71051 | ** This file implements routines used to report what compile-time options |
| 71052 | ** SQLite was built with. |
| 71053 | */ |
| 71054 | |
| 71055 | #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 71056 | |
| 71057 | |
| 71058 | /* |
| 71059 | ** An array of names of all compile-time options. This array should |
| 71060 | ** be sorted A-Z. |
| 71061 | ** |
| 71062 | ** This array looks large, but in a typical installation actually uses |
| 71063 | ** only a handful of compile-time options, so most times this array is usually |
| 71064 | ** rather short and uses little memory space. |
| 71065 | */ |
| 71066 | static const char * const azCompileOpt[] = { |
| 71067 | |
| 71068 | /* These macros are provided to "stringify" the value of the define |
| 71069 | ** for those options in which the value is meaningful. */ |
| 71070 | #define CTIMEOPT_VAL_(opt) #opt |
| 71071 | #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) |
| 71072 | |
| 71073 | #ifdef SQLITE_32BIT_ROWID |
| 71074 | "32BIT_ROWID", |
| 71075 | #endif |
| 71076 | #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC |
| 71077 | "4_BYTE_ALIGNED_MALLOC", |
| 71078 | #endif |
| 71079 | #ifdef SQLITE_CASE_SENSITIVE_LIKE |
| 71080 | "CASE_SENSITIVE_LIKE", |
| 71081 | #endif |
| 71082 | #ifdef SQLITE_CHECK_PAGES |
| 71083 | "CHECK_PAGES", |
| 71084 | #endif |
| 71085 | #ifdef SQLITE_COVERAGE_TEST |
| 71086 | "COVERAGE_TEST", |
| 71087 | #endif |
| 71088 | #ifdef SQLITE_DEBUG |
| 71089 | "DEBUG", |
| 71090 | #endif |
| 71091 | #ifdef SQLITE_DEFAULT_LOCKING_MODE |
| 71092 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 71093 | #endif |
| 71094 | #ifdef SQLITE_DISABLE_DIRSYNC |
| 71095 | "DISABLE_DIRSYNC", |
| 71096 | #endif |
| 71097 | #ifdef SQLITE_DISABLE_LFS |
| 71098 | "DISABLE_LFS", |
| 71099 | #endif |
| 71100 | #ifdef SQLITE_ENABLE_ATOMIC_WRITE |
| 71101 | "ENABLE_ATOMIC_WRITE", |
| 71102 | #endif |
| 71103 | #ifdef SQLITE_ENABLE_CEROD |
| 71104 | "ENABLE_CEROD", |
| 71105 | #endif |
| 71106 | #ifdef SQLITE_ENABLE_COLUMN_METADATA |
| 71107 | "ENABLE_COLUMN_METADATA", |
| 71108 | #endif |
| 71109 | #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT |
| 71110 | "ENABLE_EXPENSIVE_ASSERT", |
| 71111 | #endif |
| 71112 | #ifdef SQLITE_ENABLE_FTS1 |
| 71113 | "ENABLE_FTS1", |
| 71114 | #endif |
| 71115 | #ifdef SQLITE_ENABLE_FTS2 |
| 71116 | "ENABLE_FTS2", |
| 71117 | #endif |
| 71118 | #ifdef SQLITE_ENABLE_FTS3 |
| 71119 | "ENABLE_FTS3", |
| 71120 | #endif |
| 71121 | #ifdef SQLITE_ENABLE_FTS3_PARENTHESIS |
| 71122 | "ENABLE_FTS3_PARENTHESIS", |
| 71123 | #endif |
| 71124 | #ifdef SQLITE_ENABLE_FTS4 |
| 71125 | "ENABLE_FTS4", |
| 71126 | #endif |
| 71127 | #ifdef SQLITE_ENABLE_ICU |
| 71128 | "ENABLE_ICU", |
| 71129 | #endif |
| 71130 | #ifdef SQLITE_ENABLE_IOTRACE |
| 71131 | "ENABLE_IOTRACE", |
| 71132 | #endif |
| 71133 | #ifdef SQLITE_ENABLE_LOAD_EXTENSION |
| 71134 | "ENABLE_LOAD_EXTENSION", |
| 71135 | #endif |
| 71136 | #ifdef SQLITE_ENABLE_LOCKING_STYLE |
| 71137 | "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), |
| 71138 | #endif |
| 71139 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 71140 | "ENABLE_MEMORY_MANAGEMENT", |
| 71141 | #endif |
| 71142 | #ifdef SQLITE_ENABLE_MEMSYS3 |
| 71143 | "ENABLE_MEMSYS3", |
| 71144 | #endif |
| 71145 | #ifdef SQLITE_ENABLE_MEMSYS5 |
| 71146 | "ENABLE_MEMSYS5", |
| 71147 | #endif |
| 71148 | #ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK |
| 71149 | "ENABLE_OVERSIZE_CELL_CHECK", |
| 71150 | #endif |
| 71151 | #ifdef SQLITE_ENABLE_RTREE |
| 71152 | "ENABLE_RTREE", |
| 71153 | #endif |
| 71154 | #ifdef SQLITE_ENABLE_STAT2 |
| 71155 | "ENABLE_STAT2", |
| 71156 | #endif |
| 71157 | #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |
| 71158 | "ENABLE_UNLOCK_NOTIFY", |
| 71159 | #endif |
| 71160 | #ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT |
| 71161 | "ENABLE_UPDATE_DELETE_LIMIT", |
| 71162 | #endif |
| 71163 | #ifdef SQLITE_HAS_CODEC |
| 71164 | "HAS_CODEC", |
| 71165 | #endif |
| 71166 | #ifdef SQLITE_HAVE_ISNAN |
| 71167 | "HAVE_ISNAN", |
| 71168 | #endif |
| 71169 | #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX |
| 71170 | "HOMEGROWN_RECURSIVE_MUTEX", |
| 71171 | #endif |
| 71172 | #ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS |
| 71173 | "IGNORE_AFP_LOCK_ERRORS", |
| 71174 | #endif |
| 71175 | #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS |
| 71176 | "IGNORE_FLOCK_LOCK_ERRORS", |
| 71177 | #endif |
| 71178 | #ifdef SQLITE_INT64_TYPE |
| 71179 | "INT64_TYPE", |
| 71180 | #endif |
| 71181 | #ifdef SQLITE_LOCK_TRACE |
| 71182 | "LOCK_TRACE", |
| 71183 | #endif |
| 71184 | #ifdef SQLITE_MEMDEBUG |
| 71185 | "MEMDEBUG", |
| 71186 | #endif |
| 71187 | #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT |
| 71188 | "MIXED_ENDIAN_64BIT_FLOAT", |
| 71189 | #endif |
| 71190 | #ifdef SQLITE_NO_SYNC |
| 71191 | "NO_SYNC", |
| 71192 | #endif |
| 71193 | #ifdef SQLITE_OMIT_ALTERTABLE |
| 71194 | "OMIT_ALTERTABLE", |
| 71195 | #endif |
| 71196 | #ifdef SQLITE_OMIT_ANALYZE |
| 71197 | "OMIT_ANALYZE", |
| 71198 | #endif |
| 71199 | #ifdef SQLITE_OMIT_ATTACH |
| 71200 | "OMIT_ATTACH", |
| 71201 | #endif |
| 71202 | #ifdef SQLITE_OMIT_AUTHORIZATION |
| 71203 | "OMIT_AUTHORIZATION", |
| 71204 | #endif |
| 71205 | #ifdef SQLITE_OMIT_AUTOINCREMENT |
| 71206 | "OMIT_AUTOINCREMENT", |
| 71207 | #endif |
| 71208 | #ifdef SQLITE_OMIT_AUTOINIT |
| 71209 | "OMIT_AUTOINIT", |
| 71210 | #endif |
| 71211 | #ifdef SQLITE_OMIT_AUTOVACUUM |
| 71212 | "OMIT_AUTOVACUUM", |
| 71213 | #endif |
| 71214 | #ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION |
| 71215 | "OMIT_BETWEEN_OPTIMIZATION", |
| 71216 | #endif |
| 71217 | #ifdef SQLITE_OMIT_BLOB_LITERAL |
| 71218 | "OMIT_BLOB_LITERAL", |
| 71219 | #endif |
| 71220 | #ifdef SQLITE_OMIT_BTREECOUNT |
| 71221 | "OMIT_BTREECOUNT", |
| 71222 | #endif |
| 71223 | #ifdef SQLITE_OMIT_BUILTIN_TEST |
| 71224 | "OMIT_BUILTIN_TEST", |
| 71225 | #endif |
| 71226 | #ifdef SQLITE_OMIT_CAST |
| 71227 | "OMIT_CAST", |
| 71228 | #endif |
| 71229 | #ifdef SQLITE_OMIT_CHECK |
| 71230 | "OMIT_CHECK", |
| 71231 | #endif |
| 71232 | #ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 71233 | "OMIT_COMPILEOPTION_DIAGS", |
| 71234 | #endif |
| 71235 | #ifdef SQLITE_OMIT_COMPLETE |
| 71236 | "OMIT_COMPLETE", |
| 71237 | #endif |
| 71238 | #ifdef SQLITE_OMIT_COMPOUND_SELECT |
| 71239 | "OMIT_COMPOUND_SELECT", |
| 71240 | #endif |
| 71241 | #ifdef SQLITE_OMIT_DATETIME_FUNCS |
| 71242 | "OMIT_DATETIME_FUNCS", |
| 71243 | #endif |
| 71244 | #ifdef SQLITE_OMIT_DECLTYPE |
| 71245 | "OMIT_DECLTYPE", |
| 71246 | #endif |
| 71247 | #ifdef SQLITE_OMIT_DEPRECATED |
| 71248 | "OMIT_DEPRECATED", |
| 71249 | #endif |
| 71250 | #ifdef SQLITE_OMIT_DISKIO |
| 71251 | "OMIT_DISKIO", |
| 71252 | #endif |
| 71253 | #ifdef SQLITE_OMIT_EXPLAIN |
| 71254 | "OMIT_EXPLAIN", |
| 71255 | #endif |
| 71256 | #ifdef SQLITE_OMIT_FLAG_PRAGMAS |
| 71257 | "OMIT_FLAG_PRAGMAS", |
| 71258 | #endif |
| 71259 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 71260 | "OMIT_FLOATING_POINT", |
| 71261 | #endif |
| 71262 | #ifdef SQLITE_OMIT_FOREIGN_KEY |
| 71263 | "OMIT_FOREIGN_KEY", |
| 71264 | #endif |
| 71265 | #ifdef SQLITE_OMIT_GET_TABLE |
| 71266 | "OMIT_GET_TABLE", |
| 71267 | #endif |
| 71268 | #ifdef SQLITE_OMIT_GLOBALRECOVER |
| 71269 | "OMIT_GLOBALRECOVER", |
| 71270 | #endif |
| 71271 | #ifdef SQLITE_OMIT_INCRBLOB |
| 71272 | "OMIT_INCRBLOB", |
| 71273 | #endif |
| 71274 | #ifdef SQLITE_OMIT_INTEGRITY_CHECK |
| 71275 | "OMIT_INTEGRITY_CHECK", |
| 71276 | #endif |
| 71277 | #ifdef SQLITE_OMIT_LIKE_OPTIMIZATION |
| 71278 | "OMIT_LIKE_OPTIMIZATION", |
| 71279 | #endif |
| 71280 | #ifdef SQLITE_OMIT_LOAD_EXTENSION |
| 71281 | "OMIT_LOAD_EXTENSION", |
| 71282 | #endif |
| 71283 | #ifdef SQLITE_OMIT_LOCALTIME |
| 71284 | "OMIT_LOCALTIME", |
| 71285 | #endif |
| 71286 | #ifdef SQLITE_OMIT_LOOKASIDE |
| 71287 | "OMIT_LOOKASIDE", |
| 71288 | #endif |
| 71289 | #ifdef SQLITE_OMIT_MEMORYDB |
| 71290 | "OMIT_MEMORYDB", |
| 71291 | #endif |
| 71292 | #ifdef SQLITE_OMIT_OR_OPTIMIZATION |
| 71293 | "OMIT_OR_OPTIMIZATION", |
| 71294 | #endif |
| 71295 | #ifdef SQLITE_OMIT_PAGER_PRAGMAS |
| 71296 | "OMIT_PAGER_PRAGMAS", |
| 71297 | #endif |
| 71298 | #ifdef SQLITE_OMIT_PRAGMA |
| 71299 | "OMIT_PRAGMA", |
| 71300 | #endif |
| 71301 | #ifdef SQLITE_OMIT_PROGRESS_CALLBACK |
| 71302 | "OMIT_PROGRESS_CALLBACK", |
| 71303 | #endif |
| 71304 | #ifdef SQLITE_OMIT_QUICKBALANCE |
| 71305 | "OMIT_QUICKBALANCE", |
| 71306 | #endif |
| 71307 | #ifdef SQLITE_OMIT_REINDEX |
| 71308 | "OMIT_REINDEX", |
| 71309 | #endif |
| 71310 | #ifdef SQLITE_OMIT_SCHEMA_PRAGMAS |
| 71311 | "OMIT_SCHEMA_PRAGMAS", |
| 71312 | #endif |
| 71313 | #ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS |
| 71314 | "OMIT_SCHEMA_VERSION_PRAGMAS", |
| 71315 | #endif |
| 71316 | #ifdef SQLITE_OMIT_SHARED_CACHE |
| 71317 | "OMIT_SHARED_CACHE", |
| 71318 | #endif |
| 71319 | #ifdef SQLITE_OMIT_SUBQUERY |
| 71320 | "OMIT_SUBQUERY", |
| 71321 | #endif |
| 71322 | #ifdef SQLITE_OMIT_TCL_VARIABLE |
| 71323 | "OMIT_TCL_VARIABLE", |
| 71324 | #endif |
| 71325 | #ifdef SQLITE_OMIT_TEMPDB |
| 71326 | "OMIT_TEMPDB", |
| 71327 | #endif |
| 71328 | #ifdef SQLITE_OMIT_TRACE |
| 71329 | "OMIT_TRACE", |
| 71330 | #endif |
| 71331 | #ifdef SQLITE_OMIT_TRIGGER |
| 71332 | "OMIT_TRIGGER", |
| 71333 | #endif |
| 71334 | #ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION |
| 71335 | "OMIT_TRUNCATE_OPTIMIZATION", |
| 71336 | #endif |
| 71337 | #ifdef SQLITE_OMIT_UTF16 |
| 71338 | "OMIT_UTF16", |
| 71339 | #endif |
| 71340 | #ifdef SQLITE_OMIT_VACUUM |
| 71341 | "OMIT_VACUUM", |
| 71342 | #endif |
| 71343 | #ifdef SQLITE_OMIT_VIEW |
| 71344 | "OMIT_VIEW", |
| 71345 | #endif |
| 71346 | #ifdef SQLITE_OMIT_VIRTUALTABLE |
| 71347 | "OMIT_VIRTUALTABLE", |
| 71348 | #endif |
| 71349 | #ifdef SQLITE_OMIT_WSD |
| 71350 | "OMIT_WSD", |
| 71351 | #endif |
| 71352 | #ifdef SQLITE_OMIT_XFER_OPT |
| 71353 | "OMIT_XFER_OPT", |
| 71354 | #endif |
| 71355 | #ifdef SQLITE_PERFORMANCE_TRACE |
| 71356 | "PERFORMANCE_TRACE", |
| 71357 | #endif |
| 71358 | #ifdef SQLITE_PROXY_DEBUG |
| 71359 | "PROXY_DEBUG", |
| 71360 | #endif |
| 71361 | #ifdef SQLITE_SECURE_DELETE |
| 71362 | "SECURE_DELETE", |
| 71363 | #endif |
| 71364 | #ifdef SQLITE_SMALL_STACK |
| 71365 | "SMALL_STACK", |
| 71366 | #endif |
| 71367 | #ifdef SQLITE_SOUNDEX |
| 71368 | "SOUNDEX", |
| 71369 | #endif |
| 71370 | #ifdef SQLITE_TCL |
| 71371 | "TCL", |
| 71372 | #endif |
| 71373 | #ifdef SQLITE_TEMP_STORE |
| 71374 | "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), |
| 71375 | #endif |
| 71376 | #ifdef SQLITE_TEST |
| 71377 | "TEST", |
| 71378 | #endif |
| 71379 | #ifdef SQLITE_THREADSAFE |
| 71380 | "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), |
| 71381 | #endif |
| 71382 | #ifdef SQLITE_USE_ALLOCA |
| 71383 | "USE_ALLOCA", |
| 71384 | #endif |
| 71385 | #ifdef SQLITE_ZERO_MALLOC |
| 71386 | "ZERO_MALLOC" |
| 71387 | #endif |
| 71388 | }; |
| 71389 | |
| 71390 | /* |
| 71391 | ** Given the name of a compile-time option, return true if that option |
| 71392 | ** was used and false if not. |
| 71393 | ** |
| 71394 | ** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix |
| 71395 | ** is not required for a match. |
| 71396 | */ |
| 71397 | SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ |
| 71398 | int i, n; |
| 71399 | if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; |
| 71400 | n = sqlite3Strlen30(zOptName); |
| 71401 | |
| 71402 | /* Since ArraySize(azCompileOpt) is normally in single digits, a |
| 71403 | ** linear search is adequate. No need for a binary search. */ |
| 71404 | for(i=0; i<ArraySize(azCompileOpt); i++){ |
| 71405 | if( (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0) |
| 71406 | && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1; |
| 71407 | } |
| 71408 | return 0; |
| 71409 | } |
| 71410 | |
| 71411 | /* |
| 71412 | ** Return the N-th compile-time option string. If N is out of range, |
| 71413 | ** return a NULL pointer. |
| 71414 | */ |
| 71415 | SQLITE_API const char *sqlite3_compileoption_get(int N){ |
| 71416 | if( N>=0 && N<ArraySize(azCompileOpt) ){ |
| 71417 | return azCompileOpt[N]; |
| 71418 | } |
| 71419 | return 0; |
| 71420 | } |
| 71421 | |
| 71422 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 71423 | |
| 71424 | /************** End of ctime.c ***********************************************/ |
| 71425 | /************** Begin file delete.c ******************************************/ |
| 71426 | /* |
| 71427 | ** 2001 September 15 |
| 71428 | ** |
| 71429 | ** The author disclaims copyright to this source code. In place of |
| @@ -71247,18 +72328,28 @@ | |
| 72328 | if( n>30 ) n = 30; |
| 72329 | if( n<0 ) n = 0; |
| 72330 | } |
| 72331 | if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
| 72332 | r = sqlite3_value_double(argv[0]); |
| 72333 | /* If Y==0 and X will fit in a 64-bit int, |
| 72334 | ** handle the rounding directly, |
| 72335 | ** otherwise use printf. |
| 72336 | */ |
| 72337 | if( n==0 && r>=0 && r<LARGEST_INT64-1 ){ |
| 72338 | r = (double)((sqlite_int64)(r+0.5)); |
| 72339 | }else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){ |
| 72340 | r = -(double)((sqlite_int64)((-r)+0.5)); |
| 72341 | }else{ |
| 72342 | zBuf = sqlite3_mprintf("%.*f",n,r); |
| 72343 | if( zBuf==0 ){ |
| 72344 | sqlite3_result_error_nomem(context); |
| 72345 | return; |
| 72346 | } |
| 72347 | sqlite3AtoF(zBuf, &r); |
| 72348 | sqlite3_free(zBuf); |
| 72349 | } |
| 72350 | sqlite3_result_double(context, r); |
| 72351 | } |
| 72352 | #endif |
| 72353 | |
| 72354 | /* |
| 72355 | ** Allocate nByte bytes of space using sqlite3_malloc(). If the |
| @@ -71416,16 +72507,22 @@ | |
| 72507 | int NotUsed, |
| 72508 | sqlite3_value **NotUsed2 |
| 72509 | ){ |
| 72510 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 72511 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 72512 | /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a |
| 72513 | ** wrapper around the sqlite3_last_insert_rowid() C/C++ interface |
| 72514 | ** function. */ |
| 72515 | sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); |
| 72516 | } |
| 72517 | |
| 72518 | /* |
| 72519 | ** Implementation of the changes() SQL function. |
| 72520 | ** |
| 72521 | ** IMP: R-62073-11209 The changes() SQL function is a wrapper |
| 72522 | ** around the sqlite3_changes() C/C++ function and hence follows the same |
| 72523 | ** rules for counting changes. |
| 72524 | */ |
| 72525 | static void changes( |
| 72526 | sqlite3_context *context, |
| 72527 | int NotUsed, |
| 72528 | sqlite3_value **NotUsed2 |
| @@ -71444,10 +72541,12 @@ | |
| 72541 | int NotUsed, |
| 72542 | sqlite3_value **NotUsed2 |
| 72543 | ){ |
| 72544 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 72545 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 72546 | /* IMP: R-52756-41993 This function is a wrapper around the |
| 72547 | ** sqlite3_total_changes() C/C++ interface. */ |
| 72548 | sqlite3_result_int(context, sqlite3_total_changes(db)); |
| 72549 | } |
| 72550 | |
| 72551 | /* |
| 72552 | ** A structure defining how to do GLOB-style comparisons. |
| @@ -71711,11 +72810,13 @@ | |
| 72810 | sqlite3_context *context, |
| 72811 | int NotUsed, |
| 72812 | sqlite3_value **NotUsed2 |
| 72813 | ){ |
| 72814 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 72815 | /* IMP: R-48699-48617 This function is an SQL wrapper around the |
| 72816 | ** sqlite3_libversion() C-interface. */ |
| 72817 | sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC); |
| 72818 | } |
| 72819 | |
| 72820 | /* |
| 72821 | ** Implementation of the sqlite_source_id() function. The result is a string |
| 72822 | ** that identifies the particular version of the source code used to build |
| @@ -71725,13 +72826,58 @@ | |
| 72826 | sqlite3_context *context, |
| 72827 | int NotUsed, |
| 72828 | sqlite3_value **NotUsed2 |
| 72829 | ){ |
| 72830 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 72831 | /* IMP: R-24470-31136 This function is an SQL wrapper around the |
| 72832 | ** sqlite3_sourceid() C interface. */ |
| 72833 | sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC); |
| 72834 | } |
| 72835 | |
| 72836 | /* |
| 72837 | ** Implementation of the sqlite_compileoption_used() function. |
| 72838 | ** The result is an integer that identifies if the compiler option |
| 72839 | ** was used to build SQLite. |
| 72840 | */ |
| 72841 | #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 72842 | static void compileoptionusedFunc( |
| 72843 | sqlite3_context *context, |
| 72844 | int argc, |
| 72845 | sqlite3_value **argv |
| 72846 | ){ |
| 72847 | const char *zOptName; |
| 72848 | assert( argc==1 ); |
| 72849 | UNUSED_PARAMETER(argc); |
| 72850 | /* IMP: R-xxxx This function is an SQL wrapper around the |
| 72851 | ** sqlite3_compileoption_used() C interface. */ |
| 72852 | if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){ |
| 72853 | sqlite3_result_int(context, sqlite3_compileoption_used(zOptName)); |
| 72854 | } |
| 72855 | } |
| 72856 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 72857 | |
| 72858 | /* |
| 72859 | ** Implementation of the sqlite_compileoption_get() function. |
| 72860 | ** The result is a string that identifies the compiler options |
| 72861 | ** used to build SQLite. |
| 72862 | */ |
| 72863 | #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 72864 | static void compileoptiongetFunc( |
| 72865 | sqlite3_context *context, |
| 72866 | int argc, |
| 72867 | sqlite3_value **argv |
| 72868 | ){ |
| 72869 | int n; |
| 72870 | assert( argc==1 ); |
| 72871 | UNUSED_PARAMETER(argc); |
| 72872 | /* IMP: R-xxxx This function is an SQL wrapper around the |
| 72873 | ** sqlite3_compileoption_get() C interface. */ |
| 72874 | n = sqlite3_value_int(argv[0]); |
| 72875 | sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC); |
| 72876 | } |
| 72877 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 72878 | |
| 72879 | /* Array for converting from half-bytes (nybbles) into ASCII hex |
| 72880 | ** digits. */ |
| 72881 | static const char hexdigits[] = { |
| 72882 | '0', '1', '2', '3', '4', '5', '6', '7', |
| 72883 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' |
| @@ -71854,11 +73000,11 @@ | |
| 73000 | testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
| 73001 | testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); |
| 73002 | if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 73003 | sqlite3_result_error_toobig(context); |
| 73004 | }else{ |
| 73005 | sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */ |
| 73006 | } |
| 73007 | } |
| 73008 | |
| 73009 | /* |
| 73010 | ** The replace() function. Three arguments are all strings: call |
| @@ -72459,10 +73605,14 @@ | |
| 73605 | FUNCTION(random, 0, 0, 0, randomFunc ), |
| 73606 | FUNCTION(randomblob, 1, 0, 0, randomBlob ), |
| 73607 | FUNCTION(nullif, 2, 0, 1, nullifFunc ), |
| 73608 | FUNCTION(sqlite_version, 0, 0, 0, versionFunc ), |
| 73609 | FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), |
| 73610 | #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 73611 | FUNCTION(sqlite_compile_option_used,1, 0, 0, compileoptionusedFunc ), |
| 73612 | FUNCTION(sqlite_compile_option_get, 1, 0, 0, compileoptiongetFunc ), |
| 73613 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 73614 | FUNCTION(quote, 1, 0, 0, quoteFunc ), |
| 73615 | FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), |
| 73616 | FUNCTION(changes, 0, 0, 0, changes ), |
| 73617 | FUNCTION(total_changes, 0, 0, 0, total_changes ), |
| 73618 | FUNCTION(replace, 3, 0, 0, replaceFunc ), |
| @@ -74958,23 +76108,37 @@ | |
| 76108 | ** recursive-triggers flag is set, call GenerateRowDelete() to |
| 76109 | ** remove the conflicting row from the the table. This will fire |
| 76110 | ** the triggers and remove both the table and index b-tree entries. |
| 76111 | ** |
| 76112 | ** Otherwise, if there are no triggers or the recursive-triggers |
| 76113 | ** flag is not set, but the table has one or more indexes, call |
| 76114 | ** GenerateRowIndexDelete(). This removes the index b-tree entries |
| 76115 | ** only. The table b-tree entry will be replaced by the new entry |
| 76116 | ** when it is inserted. |
| 76117 | ** |
| 76118 | ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called, |
| 76119 | ** also invoke MultiWrite() to indicate that this VDBE may require |
| 76120 | ** statement rollback (if the statement is aborted after the delete |
| 76121 | ** takes place). Earlier versions called sqlite3MultiWrite() regardless, |
| 76122 | ** but being more selective here allows statements like: |
| 76123 | ** |
| 76124 | ** REPLACE INTO t(rowid) VALUES($newrowid) |
| 76125 | ** |
| 76126 | ** to run without a statement journal if there are no indexes on the |
| 76127 | ** table. |
| 76128 | */ |
| 76129 | Trigger *pTrigger = 0; |
| 76130 | if( pParse->db->flags&SQLITE_RecTriggers ){ |
| 76131 | pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
| 76132 | } |
| 76133 | if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ |
| 76134 | sqlite3MultiWrite(pParse); |
| 76135 | sqlite3GenerateRowDelete( |
| 76136 | pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace |
| 76137 | ); |
| 76138 | }else if( pTab->pIndex ){ |
| 76139 | sqlite3MultiWrite(pParse); |
| 76140 | sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); |
| 76141 | } |
| 76142 | seenReplace = 1; |
| 76143 | break; |
| 76144 | } |
| @@ -75412,11 +76576,11 @@ | |
| 76576 | if( pSrcIdx==0 ){ |
| 76577 | return 0; /* pDestIdx has no corresponding index in pSrc */ |
| 76578 | } |
| 76579 | } |
| 76580 | #ifndef SQLITE_OMIT_CHECK |
| 76581 | if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ |
| 76582 | return 0; /* Tables have different CHECK constraints. Ticket #2252 */ |
| 76583 | } |
| 76584 | #endif |
| 76585 | |
| 76586 | /* If we get this far, it means either: |
| @@ -75555,10 +76719,11 @@ | |
| 76719 | sqlite3_stmt *pStmt = 0; /* The current SQL statement */ |
| 76720 | char **azCols = 0; /* Names of result columns */ |
| 76721 | int nRetry = 0; /* Number of retry attempts */ |
| 76722 | int callbackIsInit; /* True if callback data is initialized */ |
| 76723 | |
| 76724 | if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
| 76725 | if( zSql==0 ) zSql = ""; |
| 76726 | |
| 76727 | sqlite3_mutex_enter(db->mutex); |
| 76728 | sqlite3Error(db, SQLITE_OK, 0); |
| 76729 | while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){ |
| @@ -76936,10 +78101,11 @@ | |
| 78101 | int iDb; /* Database index for <database> */ |
| 78102 | sqlite3 *db = pParse->db; |
| 78103 | Db *pDb; |
| 78104 | Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); |
| 78105 | if( v==0 ) return; |
| 78106 | sqlite3VdbeRunOnlyOnce(v); |
| 78107 | pParse->nMem = 2; |
| 78108 | |
| 78109 | /* Interpret the [database.] part of the pragma statement. iDb is the |
| 78110 | ** index of the database this pragma is being applied to in db.aDb[]. */ |
| 78111 | iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); |
| @@ -77067,10 +78233,35 @@ | |
| 78233 | newMax = sqlite3BtreeMaxPageCount(pBt, newMax); |
| 78234 | } |
| 78235 | returnSingleInt(pParse, "max_page_count", newMax); |
| 78236 | }else |
| 78237 | |
| 78238 | /* |
| 78239 | ** PRAGMA [database.]secure_delete |
| 78240 | ** PRAGMA [database.]secure_delete=ON/OFF |
| 78241 | ** |
| 78242 | ** The first form reports the current setting for the |
| 78243 | ** secure_delete flag. The second form changes the secure_delete |
| 78244 | ** flag setting and reports thenew value. |
| 78245 | */ |
| 78246 | if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){ |
| 78247 | Btree *pBt = pDb->pBt; |
| 78248 | int b = -1; |
| 78249 | assert( pBt!=0 ); |
| 78250 | if( zRight ){ |
| 78251 | b = getBoolean(zRight); |
| 78252 | } |
| 78253 | if( pId2->n==0 && b>=0 ){ |
| 78254 | int ii; |
| 78255 | for(ii=0; ii<db->nDb; ii++){ |
| 78256 | sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b); |
| 78257 | } |
| 78258 | } |
| 78259 | b = sqlite3BtreeSecureDelete(pBt, b); |
| 78260 | returnSingleInt(pParse, "secure_delete", b); |
| 78261 | }else |
| 78262 | |
| 78263 | /* |
| 78264 | ** PRAGMA [database.]page_count |
| 78265 | ** |
| 78266 | ** Return the number of pages in the specified database. |
| 78267 | */ |
| @@ -77985,10 +79176,38 @@ | |
| 79176 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); |
| 79177 | } |
| 79178 | }else |
| 79179 | #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ |
| 79180 | |
| 79181 | #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 79182 | /* |
| 79183 | ** PRAGMA compile_options |
| 79184 | ** PRAGMA compile_option(<option>) |
| 79185 | ** |
| 79186 | ** The first form returns a single row for each option that was |
| 79187 | ** defined at compile time. The second form returns 0 or 1 |
| 79188 | ** indicating whether the specified option was defined at |
| 79189 | ** compile time. |
| 79190 | */ |
| 79191 | if( sqlite3StrICmp(zLeft, "compile_option")==0 && zRight ){ |
| 79192 | int used = sqlite3_compileoption_used(zRight); |
| 79193 | returnSingleInt(pParse, zRight, used); |
| 79194 | }else |
| 79195 | |
| 79196 | if( sqlite3StrICmp(zLeft, "compile_options")==0 ){ |
| 79197 | int i = 0; |
| 79198 | const char *zOpt; |
| 79199 | sqlite3VdbeSetNumCols(v, 1); |
| 79200 | pParse->nMem = 1; |
| 79201 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC); |
| 79202 | while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ |
| 79203 | sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0); |
| 79204 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
| 79205 | } |
| 79206 | }else |
| 79207 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 79208 | |
| 79209 | #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
| 79210 | /* |
| 79211 | ** Report the current state of file logs for all databases |
| 79212 | */ |
| 79213 | if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ |
| @@ -78019,11 +79238,11 @@ | |
| 79238 | } |
| 79239 | |
| 79240 | }else |
| 79241 | #endif |
| 79242 | |
| 79243 | #ifdef SQLITE_HAS_CODEC |
| 79244 | if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){ |
| 79245 | sqlite3_key(db, zRight, sqlite3Strlen30(zRight)); |
| 79246 | }else |
| 79247 | if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){ |
| 79248 | sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight)); |
| @@ -78042,36 +79261,28 @@ | |
| 79261 | }else{ |
| 79262 | sqlite3_rekey(db, zKey, i/2); |
| 79263 | } |
| 79264 | }else |
| 79265 | #endif |
| 79266 | #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) |
| 79267 | if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){ |
| 79268 | #ifdef SQLITE_HAS_CODEC |
| 79269 | if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ |
| 79270 | sqlite3_activate_see(&zRight[4]); |
| 79271 | } |
| 79272 | #endif |
| 79273 | #ifdef SQLITE_ENABLE_CEROD |
| 79274 | if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ |
| 79275 | sqlite3_activate_cerod(&zRight[6]); |
| 79276 | } |
| 79277 | #endif |
| 79278 | }else |
| 79279 | #endif |
| 79280 | |
| 79281 | |
| 79282 | {/* Empty ELSE clause */} |
| 79283 | |
| 79284 | /* |
| 79285 | ** Reset the safety level, in case the fullfsync flag or synchronous |
| 79286 | ** setting changed. |
| 79287 | */ |
| 79288 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| @@ -78280,13 +79491,11 @@ | |
| 79491 | azArg[3] = 0; |
| 79492 | initData.db = db; |
| 79493 | initData.iDb = iDb; |
| 79494 | initData.rc = SQLITE_OK; |
| 79495 | initData.pzErrMsg = pzErrMsg; |
| 79496 | sqlite3InitCallback(&initData, 3, (char **)azArg, 0); |
| 79497 | if( initData.rc ){ |
| 79498 | rc = initData.rc; |
| 79499 | goto error_out; |
| 79500 | } |
| 79501 | pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); |
| @@ -78403,13 +79612,12 @@ | |
| 79612 | */ |
| 79613 | assert( db->init.busy ); |
| 79614 | { |
| 79615 | char *zSql; |
| 79616 | zSql = sqlite3MPrintf(db, |
| 79617 | "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid", |
| 79618 | db->aDb[iDb].zName, zMasterName); |
| 79619 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 79620 | { |
| 79621 | int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); |
| 79622 | xAuth = db->xAuth; |
| 79623 | db->xAuth = 0; |
| @@ -78418,11 +79626,10 @@ | |
| 79626 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 79627 | db->xAuth = xAuth; |
| 79628 | } |
| 79629 | #endif |
| 79630 | if( rc==SQLITE_OK ) rc = initData.rc; |
| 79631 | sqlite3DbFree(db, zSql); |
| 79632 | #ifndef SQLITE_OMIT_ANALYZE |
| 79633 | if( rc==SQLITE_OK ){ |
| 79634 | sqlite3AnalysisLoad(db, iDb); |
| 79635 | } |
| @@ -78627,15 +79834,10 @@ | |
| 79834 | if( pParse==0 ){ |
| 79835 | rc = SQLITE_NOMEM; |
| 79836 | goto end_prepare; |
| 79837 | } |
| 79838 | pParse->pReprepare = pReprepare; |
| 79839 | assert( ppStmt && *ppStmt==0 ); |
| 79840 | assert( !db->mallocFailed ); |
| 79841 | assert( sqlite3_mutex_held(db->mutex) ); |
| 79842 | |
| 79843 | /* Check to verify that it is possible to get a read lock on all |
| @@ -78667,11 +79869,10 @@ | |
| 79869 | assert( sqlite3BtreeHoldsMutex(pBt) ); |
| 79870 | rc = sqlite3BtreeSchemaLocked(pBt); |
| 79871 | if( rc ){ |
| 79872 | const char *zDb = db->aDb[i].zName; |
| 79873 | sqlite3Error(db, rc, "database schema is locked: %s", zDb); |
| 79874 | testcase( db->flags & SQLITE_ReadUncommitted ); |
| 79875 | goto end_prepare; |
| 79876 | } |
| 79877 | } |
| 79878 | } |
| @@ -78684,11 +79885,10 @@ | |
| 79885 | int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 79886 | testcase( nBytes==mxLen ); |
| 79887 | testcase( nBytes==mxLen+1 ); |
| 79888 | if( nBytes>mxLen ){ |
| 79889 | sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); |
| 79890 | rc = sqlite3ApiExit(db, SQLITE_TOOBIG); |
| 79891 | goto end_prepare; |
| 79892 | } |
| 79893 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 79894 | if( zSqlCopy ){ |
| @@ -78741,14 +79941,10 @@ | |
| 79941 | azColName[i], SQLITE_STATIC); |
| 79942 | } |
| 79943 | } |
| 79944 | #endif |
| 79945 | |
| 79946 | assert( db->init.busy==0 || saveSqlFlag==0 ); |
| 79947 | if( db->init.busy==0 ){ |
| 79948 | Vdbe *pVdbe = pParse->pVdbe; |
| 79949 | sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); |
| 79950 | } |
| @@ -78792,11 +79988,11 @@ | |
| 79988 | ){ |
| 79989 | int rc; |
| 79990 | assert( ppStmt!=0 ); |
| 79991 | *ppStmt = 0; |
| 79992 | if( !sqlite3SafetyCheckOk(db) ){ |
| 79993 | return SQLITE_MISUSE_BKPT; |
| 79994 | } |
| 79995 | sqlite3_mutex_enter(db->mutex); |
| 79996 | sqlite3BtreeEnterAll(db); |
| 79997 | rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); |
| 79998 | if( rc==SQLITE_SCHEMA ){ |
| @@ -78831,11 +80027,11 @@ | |
| 80027 | if( rc ){ |
| 80028 | if( rc==SQLITE_NOMEM ){ |
| 80029 | db->mallocFailed = 1; |
| 80030 | } |
| 80031 | assert( pNew==0 ); |
| 80032 | return rc; |
| 80033 | }else{ |
| 80034 | assert( pNew!=0 ); |
| 80035 | } |
| 80036 | sqlite3VdbeSwap((Vdbe*)pNew, p); |
| 80037 | sqlite3TransferBindings(pNew, (sqlite3_stmt*)p); |
| @@ -78900,11 +80096,11 @@ | |
| 80096 | int rc = SQLITE_OK; |
| 80097 | |
| 80098 | assert( ppStmt ); |
| 80099 | *ppStmt = 0; |
| 80100 | if( !sqlite3SafetyCheckOk(db) ){ |
| 80101 | return SQLITE_MISUSE_BKPT; |
| 80102 | } |
| 80103 | sqlite3_mutex_enter(db->mutex); |
| 80104 | zSql8 = sqlite3Utf16to8(db, zSql, nBytes); |
| 80105 | if( zSql8 ){ |
| 80106 | rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); |
| @@ -82288,22 +83484,23 @@ | |
| 83484 | int i; |
| 83485 | SrcList *pTabList; |
| 83486 | struct SrcList_item *pFrom; |
| 83487 | |
| 83488 | assert( p->selFlags & SF_Resolved ); |
| 83489 | if( (p->selFlags & SF_HasTypeInfo)==0 ){ |
| 83490 | p->selFlags |= SF_HasTypeInfo; |
| 83491 | pParse = pWalker->pParse; |
| 83492 | pTabList = p->pSrc; |
| 83493 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 83494 | Table *pTab = pFrom->pTab; |
| 83495 | if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
| 83496 | /* A sub-query in the FROM clause of a SELECT */ |
| 83497 | Select *pSel = pFrom->pSelect; |
| 83498 | assert( pSel ); |
| 83499 | while( pSel->pPrior ) pSel = pSel->pPrior; |
| 83500 | selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel); |
| 83501 | } |
| 83502 | } |
| 83503 | } |
| 83504 | return WRC_Continue; |
| 83505 | } |
| 83506 | #endif |
| @@ -83571,11 +84768,12 @@ | |
| 84768 | */ |
| 84769 | if( !pTableName || db->mallocFailed ){ |
| 84770 | goto trigger_cleanup; |
| 84771 | } |
| 84772 | pTab = sqlite3SrcListLookup(pParse, pTableName); |
| 84773 | if( db->init.busy==0 && pName2->n==0 && pTab |
| 84774 | && pTab->pSchema==db->aDb[1].pSchema ){ |
| 84775 | iDb = 1; |
| 84776 | } |
| 84777 | |
| 84778 | /* Ensure the table name matches database name and that the table exists */ |
| 84779 | if( db->mallocFailed ) goto trigger_cleanup; |
| @@ -83699,16 +84897,16 @@ | |
| 84897 | SQLITE_PRIVATE void sqlite3FinishTrigger( |
| 84898 | Parse *pParse, /* Parser context */ |
| 84899 | TriggerStep *pStepList, /* The triggered program */ |
| 84900 | Token *pAll /* Token that describes the complete CREATE TRIGGER */ |
| 84901 | ){ |
| 84902 | Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ |
| 84903 | char *zName; /* Name of trigger */ |
| 84904 | sqlite3 *db = pParse->db; /* The database */ |
| 84905 | DbFixer sFix; /* Fixer object */ |
| 84906 | int iDb; /* Database containing the trigger */ |
| 84907 | Token nameToken; /* Trigger name for error reporting */ |
| 84908 | |
| 84909 | pTrig = pParse->pNewTrigger; |
| 84910 | pParse->pNewTrigger = 0; |
| 84911 | if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; |
| 84912 | zName = pTrig->zName; |
| @@ -83723,11 +84921,11 @@ | |
| 84921 | if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) |
| 84922 | && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ |
| 84923 | goto triggerfinish_cleanup; |
| 84924 | } |
| 84925 | |
| 84926 | /* if we are not initializing, |
| 84927 | ** build the sqlite_master entry |
| 84928 | */ |
| 84929 | if( !db->init.busy ){ |
| 84930 | Vdbe *v; |
| 84931 | char *z; |
| @@ -85222,47 +86420,61 @@ | |
| 86420 | ** Most of the code in this file may be omitted by defining the |
| 86421 | ** SQLITE_OMIT_VACUUM macro. |
| 86422 | */ |
| 86423 | |
| 86424 | #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) |
| 86425 | /* |
| 86426 | ** Finalize a prepared statement. If there was an error, store the |
| 86427 | ** text of the error message in *pzErrMsg. Return the result code. |
| 86428 | */ |
| 86429 | static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){ |
| 86430 | int rc; |
| 86431 | rc = sqlite3VdbeFinalize((Vdbe*)pStmt); |
| 86432 | if( rc ){ |
| 86433 | sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); |
| 86434 | } |
| 86435 | return rc; |
| 86436 | } |
| 86437 | |
| 86438 | /* |
| 86439 | ** Execute zSql on database db. Return an error code. |
| 86440 | */ |
| 86441 | static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ |
| 86442 | sqlite3_stmt *pStmt; |
| 86443 | VVA_ONLY( int rc; ) |
| 86444 | if( !zSql ){ |
| 86445 | return SQLITE_NOMEM; |
| 86446 | } |
| 86447 | if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ |
| 86448 | sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); |
| 86449 | return sqlite3_errcode(db); |
| 86450 | } |
| 86451 | VVA_ONLY( rc = ) sqlite3_step(pStmt); |
| 86452 | assert( rc!=SQLITE_ROW ); |
| 86453 | return vacuumFinalize(db, pStmt, pzErrMsg); |
| 86454 | } |
| 86455 | |
| 86456 | /* |
| 86457 | ** Execute zSql on database db. The statement returns exactly |
| 86458 | ** one column. Execute this as SQL on the same database. |
| 86459 | */ |
| 86460 | static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ |
| 86461 | sqlite3_stmt *pStmt; |
| 86462 | int rc; |
| 86463 | |
| 86464 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 86465 | if( rc!=SQLITE_OK ) return rc; |
| 86466 | |
| 86467 | while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 86468 | rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0)); |
| 86469 | if( rc!=SQLITE_OK ){ |
| 86470 | vacuumFinalize(db, pStmt, pzErrMsg); |
| 86471 | return rc; |
| 86472 | } |
| 86473 | } |
| 86474 | |
| 86475 | return vacuumFinalize(db, pStmt, pzErrMsg); |
| 86476 | } |
| 86477 | |
| 86478 | /* |
| 86479 | ** The non-standard VACUUM command is used to clean up the database, |
| 86480 | ** collapse free space, etc. It is modelled after the VACUUM command |
| @@ -85308,11 +86520,11 @@ | |
| 86520 | saved_flags = db->flags; |
| 86521 | saved_nChange = db->nChange; |
| 86522 | saved_nTotalChange = db->nTotalChange; |
| 86523 | saved_xTrace = db->xTrace; |
| 86524 | db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; |
| 86525 | db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder); |
| 86526 | db->xTrace = 0; |
| 86527 | |
| 86528 | pMain = db->aDb[0].pBt; |
| 86529 | isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); |
| 86530 | |
| @@ -85329,11 +86541,11 @@ | |
| 86541 | ** empty. Only the journal header is written. Apparently it takes more |
| 86542 | ** time to parse and run the PRAGMA to turn journalling off than it does |
| 86543 | ** to write the journal header file. |
| 86544 | */ |
| 86545 | zSql = "ATTACH '' AS vacuum_db;"; |
| 86546 | rc = execSql(db, pzErrMsg, zSql); |
| 86547 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 86548 | pDb = &db->aDb[db->nDb-1]; |
| 86549 | assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); |
| 86550 | pTemp = db->aDb[db->nDb-1].pBt; |
| 86551 | |
| @@ -85361,11 +86573,11 @@ | |
| 86573 | || NEVER(db->mallocFailed) |
| 86574 | ){ |
| 86575 | rc = SQLITE_NOMEM; |
| 86576 | goto end_of_vacuum; |
| 86577 | } |
| 86578 | rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); |
| 86579 | if( rc!=SQLITE_OK ){ |
| 86580 | goto end_of_vacuum; |
| 86581 | } |
| 86582 | |
| 86583 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| @@ -85372,53 +86584,52 @@ | |
| 86584 | sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : |
| 86585 | sqlite3BtreeGetAutoVacuum(pMain)); |
| 86586 | #endif |
| 86587 | |
| 86588 | /* Begin a transaction */ |
| 86589 | rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;"); |
| 86590 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 86591 | |
| 86592 | /* Query the schema of the main database. Create a mirror schema |
| 86593 | ** in the temporary database. |
| 86594 | */ |
| 86595 | rc = execExecSql(db, pzErrMsg, |
| 86596 | "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " |
| 86597 | " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" |
| 86598 | " AND rootpage>0" |
| 86599 | ); |
| 86600 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 86601 | rc = execExecSql(db, pzErrMsg, |
| 86602 | "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)" |
| 86603 | " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "); |
| 86604 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 86605 | rc = execExecSql(db, pzErrMsg, |
| 86606 | "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " |
| 86607 | " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); |
| 86608 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 86609 | |
| 86610 | /* Loop through the tables in the main database. For each, do |
| 86611 | ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy |
| 86612 | ** the contents to the temporary database. |
| 86613 | */ |
| 86614 | rc = execExecSql(db, pzErrMsg, |
| 86615 | "SELECT 'INSERT INTO vacuum_db.' || quote(name) " |
| 86616 | "|| ' SELECT * FROM main.' || quote(name) || ';'" |
| 86617 | "FROM main.sqlite_master " |
| 86618 | "WHERE type = 'table' AND name!='sqlite_sequence' " |
| 86619 | " AND rootpage>0" |
| 86620 | ); |
| 86621 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 86622 | |
| 86623 | /* Copy over the sequence table |
| 86624 | */ |
| 86625 | rc = execExecSql(db, pzErrMsg, |
| 86626 | "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " |
| 86627 | "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " |
| 86628 | ); |
| 86629 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 86630 | rc = execExecSql(db, pzErrMsg, |
| 86631 | "SELECT 'INSERT INTO vacuum_db.' || quote(name) " |
| 86632 | "|| ' SELECT * FROM main.' || quote(name) || ';' " |
| 86633 | "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';" |
| 86634 | ); |
| 86635 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| @@ -85427,11 +86638,11 @@ | |
| 86638 | /* Copy the triggers, views, and virtual tables from the main database |
| 86639 | ** over to the temporary database. None of these objects has any |
| 86640 | ** associated storage, so all we have to do is copy their entries |
| 86641 | ** from the SQLITE_MASTER table. |
| 86642 | */ |
| 86643 | rc = execSql(db, pzErrMsg, |
| 86644 | "INSERT INTO vacuum_db.sqlite_master " |
| 86645 | " SELECT type, name, tbl_name, rootpage, sql" |
| 86646 | " FROM main.sqlite_master" |
| 86647 | " WHERE type='view' OR type='trigger'" |
| 86648 | " OR (type='table' AND rootpage=0)" |
| @@ -85639,20 +86850,11 @@ | |
| 86850 | |
| 86851 | pVTab->nRef--; |
| 86852 | if( pVTab->nRef==0 ){ |
| 86853 | sqlite3_vtab *p = pVTab->pVtab; |
| 86854 | if( p ){ |
| 86855 | p->pModule->xDisconnect(p); |
| 86856 | } |
| 86857 | sqlite3DbFree(db, pVTab); |
| 86858 | } |
| 86859 | } |
| 86860 | |
| @@ -85984,13 +87186,11 @@ | |
| 87186 | assert( !db->pVTab ); |
| 87187 | assert( xConstruct ); |
| 87188 | db->pVTab = pTab; |
| 87189 | |
| 87190 | /* Invoke the virtual table constructor */ |
| 87191 | rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
| 87192 | if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 87193 | |
| 87194 | if( SQLITE_OK!=rc ){ |
| 87195 | if( zErr==0 ){ |
| 87196 | *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
| @@ -86174,11 +87374,11 @@ | |
| 87374 | sqlite3_mutex_enter(db->mutex); |
| 87375 | pTab = db->pVTab; |
| 87376 | if( !pTab ){ |
| 87377 | sqlite3Error(db, SQLITE_MISUSE, 0); |
| 87378 | sqlite3_mutex_leave(db->mutex); |
| 87379 | return SQLITE_MISUSE_BKPT; |
| 87380 | } |
| 87381 | assert( (pTab->tabFlags & TF_Virtual)!=0 ); |
| 87382 | |
| 87383 | pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
| 87384 | if( pParse==0 ){ |
| @@ -86233,14 +87433,12 @@ | |
| 87433 | |
| 87434 | pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); |
| 87435 | if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ |
| 87436 | VTable *p = vtabDisconnectAll(db, pTab); |
| 87437 | |
| 87438 | assert( rc==SQLITE_OK ); |
| 87439 | rc = p->pMod->pModule->xDestroy(p->pVtab); |
| 87440 | |
| 87441 | /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ |
| 87442 | if( rc==SQLITE_OK ){ |
| 87443 | assert( pTab->pVTable==p && p->pNext==0 ); |
| 87444 | p->pVtab = 0; |
| @@ -86288,14 +87486,12 @@ | |
| 87486 | ** sqlite3DbFree() containing an error message, if one is available. |
| 87487 | */ |
| 87488 | SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){ |
| 87489 | int i; |
| 87490 | int rc = SQLITE_OK; |
| 87491 | VTable **aVTrans = db->aVTrans; |
| 87492 | |
| 87493 | db->aVTrans = 0; |
| 87494 | for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){ |
| 87495 | int (*x)(sqlite3_vtab *); |
| 87496 | sqlite3_vtab *pVtab = aVTrans[i]->pVtab; |
| 87497 | if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ |
| @@ -86304,15 +87500,10 @@ | |
| 87500 | *pzErrmsg = pVtab->zErrMsg; |
| 87501 | pVtab->zErrMsg = 0; |
| 87502 | } |
| 87503 | } |
| 87504 | db->aVTrans = aVTrans; |
| 87505 | return rc; |
| 87506 | } |
| 87507 | |
| 87508 | /* |
| 87509 | ** Invoke the xRollback method of all virtual tables in the |
| @@ -87131,11 +88322,11 @@ | |
| 88322 | ** be the name of an indexed column with TEXT affinity. */ |
| 88323 | return 0; |
| 88324 | } |
| 88325 | assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ |
| 88326 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 88327 | if( pColl==0 ) return 0; /* Happens when LHS has an undefined collation */ |
| 88328 | if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) && |
| 88329 | (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){ |
| 88330 | /* IMP: R-09003-32046 For the GLOB operator, the column must use the |
| 88331 | ** default BINARY collating sequence. |
| 88332 | ** IMP: R-41408-28306 For the LIKE operator, if case_sensitive_like mode |
| @@ -87574,11 +88765,11 @@ | |
| 88765 | WhereTerm *pTerm; /* The term to be analyzed */ |
| 88766 | WhereMaskSet *pMaskSet; /* Set of table index masks */ |
| 88767 | Expr *pExpr; /* The expression to be analyzed */ |
| 88768 | Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ |
| 88769 | Bitmask prereqAll; /* Prerequesites of pExpr */ |
| 88770 | Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ |
| 88771 | Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ |
| 88772 | int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ |
| 88773 | int noCase = 0; /* LIKE/GLOB distinguishes case */ |
| 88774 | int op; /* Top-level operator. pExpr->op */ |
| 88775 | Parse *pParse = pWC->pParse; /* Parsing context */ |
| @@ -87646,11 +88837,12 @@ | |
| 88837 | } |
| 88838 | exprCommute(pParse, pDup); |
| 88839 | pLeft = pDup->pLeft; |
| 88840 | pNew->leftCursor = pLeft->iTable; |
| 88841 | pNew->u.leftColumn = pLeft->iColumn; |
| 88842 | testcase( (prereqLeft | extraRight) != prereqLeft ); |
| 88843 | pNew->prereqRight = prereqLeft | extraRight; |
| 88844 | pNew->prereqAll = prereqAll; |
| 88845 | pNew->eOperator = operatorMask(pDup->op); |
| 88846 | } |
| 88847 | } |
| 88848 | |
| @@ -88236,16 +89428,14 @@ | |
| 89428 | static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ |
| 89429 | sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; |
| 89430 | int i; |
| 89431 | int rc; |
| 89432 | |
| 89433 | WHERETRACE(("xBestIndex for %s\n", pTab->zName)); |
| 89434 | TRACE_IDX_INPUTS(p); |
| 89435 | rc = pVtab->pModule->xBestIndex(pVtab, p); |
| 89436 | TRACE_IDX_OUTPUTS(p); |
| 89437 | |
| 89438 | if( rc!=SQLITE_OK ){ |
| 89439 | if( rc==SQLITE_NOMEM ){ |
| 89440 | pParse->db->mallocFailed = 1; |
| 89441 | }else if( !pVtab->zErrMsg ){ |
| @@ -90871,11 +92061,11 @@ | |
| 92061 | ** shifting terminals. |
| 92062 | ** yy_reduce_ofst[] For each state, the offset into yy_action for |
| 92063 | ** shifting non-terminals after a reduce. |
| 92064 | ** yy_default[] Default action for each state. |
| 92065 | */ |
| 92066 | #define YY_ACTTAB_COUNT (1550) |
| 92067 | static const YYACTIONTYPE yy_action[] = { |
| 92068 | /* 0 */ 313, 49, 556, 46, 147, 172, 628, 598, 55, 55, |
| 92069 | /* 10 */ 55, 55, 302, 53, 53, 53, 53, 52, 52, 51, |
| 92070 | /* 20 */ 51, 51, 50, 238, 603, 66, 624, 623, 604, 598, |
| 92071 | /* 30 */ 591, 585, 48, 53, 53, 53, 53, 52, 52, 51, |
| @@ -91021,17 +92211,17 @@ | |
| 92211 | /* 1430 */ 602, 81, 411, 514, 414, 512, 131, 602, 70, 229, |
| 92212 | /* 1440 */ 228, 227, 494, 602, 17, 411, 488, 414, 259, 346, |
| 92213 | /* 1450 */ 249, 389, 487, 486, 314, 164, 602, 79, 310, 240, |
| 92214 | /* 1460 */ 414, 373, 480, 163, 262, 371, 414, 162, 369, 602, |
| 92215 | /* 1470 */ 78, 212, 478, 26, 477, 602, 9, 161, 467, 363, |
| 92216 | /* 1480 */ 141, 122, 339, 187, 119, 457, 348, 347, 117, 116, |
| 92217 | /* 1490 */ 115, 112, 114, 448, 182, 22, 320, 433, 432, 431, |
| 92218 | /* 1500 */ 19, 428, 610, 597, 574, 193, 572, 63, 298, 404, |
| 92219 | /* 1510 */ 555, 552, 290, 281, 510, 460, 498, 499, 495, 447, |
| 92220 | /* 1520 */ 356, 497, 256, 380, 306, 570, 5, 250, 345, 238, |
| 92221 | /* 1530 */ 299, 550, 527, 490, 508, 525, 502, 401, 501, 963, |
| 92222 | /* 1540 */ 211, 963, 483, 963, 963, 963, 963, 963, 963, 370, |
| 92223 | }; |
| 92224 | static const YYCODETYPE yy_lookahead[] = { |
| 92225 | /* 0 */ 19, 222, 223, 224, 225, 24, 1, 26, 77, 78, |
| 92226 | /* 10 */ 79, 80, 15, 82, 83, 84, 85, 86, 87, 88, |
| 92227 | /* 20 */ 89, 90, 91, 92, 113, 22, 26, 27, 117, 26, |
| @@ -91178,22 +92368,22 @@ | |
| 92368 | /* 1430 */ 174, 175, 150, 178, 165, 176, 22, 174, 175, 230, |
| 92369 | /* 1440 */ 92, 230, 184, 174, 175, 150, 176, 165, 105, 106, |
| 92370 | /* 1450 */ 107, 150, 176, 176, 111, 156, 174, 175, 179, 116, |
| 92371 | /* 1460 */ 165, 18, 157, 156, 238, 157, 165, 156, 45, 174, |
| 92372 | /* 1470 */ 175, 157, 157, 135, 239, 174, 175, 156, 189, 157, |
| 92373 | /* 1480 */ 68, 189, 139, 219, 22, 199, 157, 18, 192, 192, |
| 92374 | /* 1490 */ 192, 189, 192, 199, 219, 243, 157, 40, 157, 157, |
| 92375 | /* 1500 */ 243, 38, 153, 166, 233, 196, 233, 246, 198, 228, |
| 92376 | /* 1510 */ 177, 177, 209, 177, 182, 199, 166, 177, 166, 199, |
| 92377 | /* 1520 */ 242, 177, 242, 178, 148, 166, 196, 209, 209, 92, |
| 92378 | /* 1530 */ 195, 208, 174, 186, 183, 174, 183, 191, 183, 253, |
| 92379 | /* 1540 */ 236, 253, 186, 253, 253, 253, 253, 253, 253, 237, |
| 92380 | }; |
| 92381 | #define YY_SHIFT_USE_DFLT (-90) |
| 92382 | #define YY_SHIFT_COUNT (418) |
| 92383 | #define YY_SHIFT_MIN (-89) |
| 92384 | #define YY_SHIFT_MAX (1469) |
| 92385 | static const short yy_shift_ofst[] = { |
| 92386 | /* 0 */ 993, 1114, 1343, 1114, 1213, 1213, 90, 90, 0, -19, |
| 92387 | /* 10 */ 1213, 1213, 1213, 1213, 1213, 352, 517, 721, 1091, 1213, |
| 92388 | /* 20 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, |
| 92389 | /* 30 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, |
| @@ -91204,11 +92394,11 @@ | |
| 92394 | /* 80 */ 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, |
| 92395 | /* 90 */ 795, 795, 795, 795, 795, 795, 869, 795, 943, 1017, |
| 92396 | /* 100 */ 1017, -69, -69, -69, -69, -1, -1, 58, 138, -44, |
| 92397 | /* 110 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 92398 | /* 120 */ 517, 517, 517, 517, 517, 517, 202, 579, 517, 517, |
| 92399 | /* 130 */ 517, 517, 517, 382, 885, 1437, -90, -90, -90, 1293, |
| 92400 | /* 140 */ 73, 272, 272, 309, 311, 297, 282, 216, 602, 538, |
| 92401 | /* 150 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 92402 | /* 160 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 92403 | /* 170 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 92404 | /* 180 */ 517, 517, 505, 231, 231, 231, 706, 64, 1177, 1177, |
| @@ -91215,12 +92405,12 @@ | |
| 92405 | /* 190 */ 1177, -90, -90, -90, 136, 168, 168, 12, 496, 496, |
| 92406 | /* 200 */ 496, 506, 423, 512, 370, 349, 335, 149, 149, 149, |
| 92407 | /* 210 */ 149, 604, 516, 149, 149, 508, 3, 299, 677, 871, |
| 92408 | /* 220 */ 613, 613, 879, 871, 879, 144, 382, 226, 382, 226, |
| 92409 | /* 230 */ 564, 226, 613, 226, 226, 404, 625, 625, 382, 426, |
| 92410 | /* 240 */ -89, 801, 1463, 1244, 1244, 1457, 1457, 1244, 1462, 1412, |
| 92411 | /* 250 */ 1188, 1469, 1469, 1469, 1469, 1244, 1188, 1462, 1412, 1412, |
| 92412 | /* 260 */ 1244, 1443, 1338, 1423, 1244, 1244, 1443, 1244, 1443, 1244, |
| 92413 | /* 270 */ 1443, 1414, 1306, 1306, 1306, 1365, 1348, 1348, 1414, 1306, |
| 92414 | /* 280 */ 1317, 1306, 1365, 1306, 1306, 1267, 1268, 1267, 1268, 1267, |
| 92415 | /* 290 */ 1268, 1244, 1244, 1216, 1214, 1215, 1192, 1173, 1188, 1177, |
| 92416 | /* 300 */ 1260, 1253, 1253, 1248, 1248, 1248, 1248, -90, -90, -90, |
| @@ -91237,11 +92427,11 @@ | |
| 92427 | /* 410 */ 152, 123, 68, -20, -42, 57, 39, -3, 5, |
| 92428 | }; |
| 92429 | #define YY_REDUCE_USE_DFLT (-222) |
| 92430 | #define YY_REDUCE_COUNT (312) |
| 92431 | #define YY_REDUCE_MIN (-221) |
| 92432 | #define YY_REDUCE_MAX (1376) |
| 92433 | static const short yy_reduce_ofst[] = { |
| 92434 | /* 0 */ 310, 994, 1134, 221, 169, 157, 89, 18, 83, 301, |
| 92435 | /* 10 */ 377, 316, 312, 16, 295, 238, 249, 391, 1301, 1295, |
| 92436 | /* 20 */ 1282, 1269, 1263, 1256, 1251, 1240, 1234, 1228, 1221, 1208, |
| 92437 | /* 30 */ 1109, 1103, 1077, 1054, 1022, 1016, 911, 908, 890, 888, |
| @@ -91258,17 +92448,17 @@ | |
| 92448 | /* 140 */ 823, 738, 712, 892, 1199, 1185, 1176, 1171, 673, 673, |
| 92449 | /* 150 */ 1168, 1167, 1162, 1159, 1148, 1145, 1139, 1117, 1111, 1107, |
| 92450 | /* 160 */ 1084, 1066, 1049, 1011, 1010, 1006, 1002, 999, 998, 973, |
| 92451 | /* 170 */ 972, 970, 966, 964, 895, 894, 892, 833, 822, 762, |
| 92452 | /* 180 */ 761, 229, 811, 804, 803, 389, 688, 808, 807, 737, |
| 92453 | /* 190 */ 460, 464, 572, 584, 1356, 1361, 1358, 1347, 1355, 1353, |
| 92454 | /* 200 */ 1351, 1323, 1335, 1346, 1335, 1335, 1335, 1335, 1335, 1335, |
| 92455 | /* 210 */ 1335, 1312, 1304, 1335, 1335, 1323, 1359, 1330, 1376, 1320, |
| 92456 | /* 220 */ 1319, 1318, 1280, 1316, 1278, 1345, 1352, 1344, 1350, 1340, |
| 92457 | /* 230 */ 1332, 1336, 1303, 1334, 1333, 1281, 1273, 1271, 1337, 1310, |
| 92458 | /* 240 */ 1309, 1349, 1261, 1342, 1341, 1257, 1252, 1339, 1275, 1302, |
| 92459 | /* 250 */ 1294, 1300, 1298, 1297, 1296, 1329, 1286, 1264, 1292, 1289, |
| 92460 | /* 260 */ 1322, 1321, 1235, 1226, 1315, 1314, 1311, 1308, 1307, 1305, |
| 92461 | /* 270 */ 1299, 1279, 1277, 1276, 1270, 1258, 1211, 1209, 1250, 1259, |
| 92462 | /* 280 */ 1255, 1242, 1243, 1241, 1201, 1200, 1184, 1186, 1182, 1178, |
| 92463 | /* 290 */ 1165, 1206, 1204, 1113, 1135, 1095, 1124, 1105, 1102, 1096, |
| 92464 | /* 300 */ 1112, 1140, 1136, 1121, 1116, 1115, 1089, 985, 961, 987, |
| @@ -94758,10 +95948,11 @@ | |
| 95948 | sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc)); |
| 95949 | } |
| 95950 | assert( pzErrMsg!=0 ); |
| 95951 | if( pParse->zErrMsg ){ |
| 95952 | *pzErrMsg = pParse->zErrMsg; |
| 95953 | sqlite3_log(pParse->rc, "%s", *pzErrMsg); |
| 95954 | pParse->zErrMsg = 0; |
| 95955 | nErr++; |
| 95956 | } |
| 95957 | if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ |
| 95958 | sqlite3VdbeDelete(pParse->pVdbe); |
| @@ -95436,11 +96627,11 @@ | |
| 96627 | va_list ap; |
| 96628 | int rc = SQLITE_OK; |
| 96629 | |
| 96630 | /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while |
| 96631 | ** the SQLite library is in use. */ |
| 96632 | if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT; |
| 96633 | |
| 96634 | va_start(ap, op); |
| 96635 | switch( op ){ |
| 96636 | |
| 96637 | /* Mutex configuration options are only available in a threadsafe |
| @@ -95557,10 +96748,25 @@ | |
| 96748 | case SQLITE_CONFIG_LOOKASIDE: { |
| 96749 | sqlite3GlobalConfig.szLookaside = va_arg(ap, int); |
| 96750 | sqlite3GlobalConfig.nLookaside = va_arg(ap, int); |
| 96751 | break; |
| 96752 | } |
| 96753 | |
| 96754 | /* Record a pointer to the logger funcction and its first argument. |
| 96755 | ** The default is NULL. Logging is disabled if the function pointer is |
| 96756 | ** NULL. |
| 96757 | */ |
| 96758 | case SQLITE_CONFIG_LOG: { |
| 96759 | /* MSVC is picky about pulling func ptrs from va lists. |
| 96760 | ** http://support.microsoft.com/kb/47961 |
| 96761 | ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*)); |
| 96762 | */ |
| 96763 | typedef void(*LOGFUNC_t)(void*,int,const char*); |
| 96764 | sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t); |
| 96765 | sqlite3GlobalConfig.pLogArg = va_arg(ap, void*); |
| 96766 | break; |
| 96767 | } |
| 96768 | |
| 96769 | default: { |
| 96770 | rc = SQLITE_ERROR; |
| 96771 | break; |
| 96772 | } |
| @@ -95770,11 +96976,11 @@ | |
| 96976 | |
| 96977 | if( !db ){ |
| 96978 | return SQLITE_OK; |
| 96979 | } |
| 96980 | if( !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96981 | return SQLITE_MISUSE_BKPT; |
| 96982 | } |
| 96983 | sqlite3_mutex_enter(db->mutex); |
| 96984 | |
| 96985 | sqlite3ResetInternalSchema(db, 0); |
| 96986 | |
| @@ -96117,11 +97323,11 @@ | |
| 97323 | (xFunc && (xFinal || xStep)) || |
| 97324 | (!xFunc && (xFinal && !xStep)) || |
| 97325 | (!xFunc && (!xFinal && xStep)) || |
| 97326 | (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || |
| 97327 | (255<(nName = sqlite3Strlen30( zFunctionName))) ){ |
| 97328 | return SQLITE_MISUSE_BKPT; |
| 97329 | } |
| 97330 | |
| 97331 | #ifndef SQLITE_OMIT_UTF16 |
| 97332 | /* If SQLITE_UTF16 is specified as the encoding type, transform this |
| 97333 | ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the |
| @@ -96448,11 +97654,11 @@ | |
| 97654 | const char *z; |
| 97655 | if( !db ){ |
| 97656 | return sqlite3ErrStr(SQLITE_NOMEM); |
| 97657 | } |
| 97658 | if( !sqlite3SafetyCheckSickOrOk(db) ){ |
| 97659 | return sqlite3ErrStr(SQLITE_MISUSE_BKPT); |
| 97660 | } |
| 97661 | sqlite3_mutex_enter(db->mutex); |
| 97662 | if( db->mallocFailed ){ |
| 97663 | z = sqlite3ErrStr(SQLITE_NOMEM); |
| 97664 | }else{ |
| @@ -96517,20 +97723,20 @@ | |
| 97723 | ** Return the most recent error code generated by an SQLite routine. If NULL is |
| 97724 | ** passed to this function, we assume a malloc() failed during sqlite3_open(). |
| 97725 | */ |
| 97726 | SQLITE_API int sqlite3_errcode(sqlite3 *db){ |
| 97727 | if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
| 97728 | return SQLITE_MISUSE_BKPT; |
| 97729 | } |
| 97730 | if( !db || db->mallocFailed ){ |
| 97731 | return SQLITE_NOMEM; |
| 97732 | } |
| 97733 | return db->errCode & db->errMask; |
| 97734 | } |
| 97735 | SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ |
| 97736 | if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
| 97737 | return SQLITE_MISUSE_BKPT; |
| 97738 | } |
| 97739 | if( !db || db->mallocFailed ){ |
| 97740 | return SQLITE_NOMEM; |
| 97741 | } |
| 97742 | return db->errCode; |
| @@ -96564,11 +97770,11 @@ | |
| 97770 | testcase( enc2==SQLITE_UTF16_ALIGNED ); |
| 97771 | if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){ |
| 97772 | enc2 = SQLITE_UTF16NATIVE; |
| 97773 | } |
| 97774 | if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){ |
| 97775 | return SQLITE_MISUSE_BKPT; |
| 97776 | } |
| 97777 | |
| 97778 | /* Check if this call is removing or replacing an existing collation |
| 97779 | ** sequence. If so, and there are active VMs, return busy. If there |
| 97780 | ** are no active VMs, invalidate any pre-compiled statements. |
| @@ -97108,20 +98314,38 @@ | |
| 98314 | */ |
| 98315 | SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ |
| 98316 | return db->autoCommit; |
| 98317 | } |
| 98318 | |
| 98319 | /* |
| 98320 | ** The following routines are subtitutes for constants SQLITE_CORRUPT, |
| 98321 | ** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error |
| 98322 | ** constants. They server two purposes: |
| 98323 | ** |
| 98324 | ** 1. Serve as a convenient place to set a breakpoint in a debugger |
| 98325 | ** to detect when version error conditions occurs. |
| 98326 | ** |
| 98327 | ** 2. Invoke sqlite3_log() to provide the source code location where |
| 98328 | ** a low-level error is first detected. |
| 98329 | */ |
| 98330 | SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ |
| 98331 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 98332 | sqlite3_log(SQLITE_CORRUPT, |
| 98333 | "database corruption found by source line %d", lineno); |
| 98334 | return SQLITE_CORRUPT; |
| 98335 | } |
| 98336 | SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ |
| 98337 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 98338 | sqlite3_log(SQLITE_MISUSE, "misuse detected by source line %d", lineno); |
| 98339 | return SQLITE_MISUSE; |
| 98340 | } |
| 98341 | SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ |
| 98342 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 98343 | sqlite3_log(SQLITE_CANTOPEN, "cannot open file at source line %d", lineno); |
| 98344 | return SQLITE_CANTOPEN; |
| 98345 | } |
| 98346 | |
| 98347 | |
| 98348 | #ifndef SQLITE_OMIT_DEPRECATED |
| 98349 | /* |
| 98350 | ** This is a convenience routine that makes sure that all thread-specific |
| 98351 | ** data for this thread has been deallocated. |
| @@ -97161,11 +98385,10 @@ | |
| 98385 | int primarykey = 0; |
| 98386 | int autoinc = 0; |
| 98387 | |
| 98388 | /* Ensure the database schema has been loaded */ |
| 98389 | sqlite3_mutex_enter(db->mutex); |
| 98390 | sqlite3BtreeEnterAll(db); |
| 98391 | rc = sqlite3Init(db, &zErrMsg); |
| 98392 | if( SQLITE_OK!=rc ){ |
| 98393 | goto error_out; |
| 98394 | } |
| @@ -97220,11 +98443,10 @@ | |
| 98443 | zCollSeq = "BINARY"; |
| 98444 | } |
| 98445 | |
| 98446 | error_out: |
| 98447 | sqlite3BtreeLeaveAll(db); |
| 98448 | |
| 98449 | /* Whether the function call succeeded or failed, set the output parameters |
| 98450 | ** to whatever their local counterparts contain. If an error did occur, |
| 98451 | ** this has the effect of zeroing all output parameters. |
| 98452 | */ |
| @@ -97859,13 +99081,10 @@ | |
| 99081 | ** |
| 99082 | ** * The FTS3 module is being built into the core of |
| 99083 | ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). |
| 99084 | */ |
| 99085 | |
| 99086 | /* The full-text index is stored in a series of b+tree (-like) |
| 99087 | ** structures called segments which map terms to doclists. The |
| 99088 | ** structures are like b+trees in layout, but are constructed from the |
| 99089 | ** bottom up in optimal fashion and are not updatable. Since trees |
| 99090 | ** are built from the bottom up, things will be described from the |
| @@ -97884,45 +99103,68 @@ | |
| 99103 | ** 7 bits - A |
| 99104 | ** 14 bits - BA |
| 99105 | ** 21 bits - BBA |
| 99106 | ** and so on. |
| 99107 | ** |
| 99108 | ** This is similar in concept to how sqlite encodes "varints" but |
| 99109 | ** the encoding is not the same. SQLite varints are big-endian |
| 99110 | ** are are limited to 9 bytes in length whereas FTS3 varints are |
| 99111 | ** little-endian and can be upt to 10 bytes in length (in theory). |
| 99112 | ** |
| 99113 | ** Example encodings: |
| 99114 | ** |
| 99115 | ** 1: 0x01 |
| 99116 | ** 127: 0x7f |
| 99117 | ** 128: 0x81 0x00 |
| 99118 | ** |
| 99119 | ** |
| 99120 | **** Document lists **** |
| 99121 | ** A doclist (document list) holds a docid-sorted list of hits for a |
| 99122 | ** given term. Doclists hold docids, and can optionally associate |
| 99123 | ** token positions and offsets with docids. A position is the index |
| 99124 | ** of a word within the document. The first word of the document has |
| 99125 | ** a position of 0. |
| 99126 | ** |
| 99127 | ** FTS3 used to optionally store character offsets using a compile-time |
| 99128 | ** option. But that functionality is no longer supported. |
| 99129 | ** |
| 99130 | ** A DL_POSITIONS_OFFSETS doclist is stored like this: |
| 99131 | ** |
| 99132 | ** array { |
| 99133 | ** varint docid; |
| 99134 | ** array { (position list for column 0) |
| 99135 | ** varint position; (delta from previous position plus POS_BASE) |
| 99136 | ** } |
| 99137 | ** array { |
| 99138 | ** varint POS_COLUMN; (marks start of position list for new column) |
| 99139 | ** varint column; (index of new column) |
| 99140 | ** array { |
| 99141 | ** varint position; (delta from previous position plus POS_BASE) |
| 99142 | ** } |
| 99143 | ** } |
| 99144 | ** varint POS_END; (marks end of positions for this document. |
| 99145 | ** } |
| 99146 | ** |
| 99147 | ** Here, array { X } means zero or more occurrences of X, adjacent in |
| 99148 | ** memory. A "position" is an index of a token in the token stream |
| 99149 | ** generated by the tokenizer. Note that POS_END and POS_COLUMN occur |
| 99150 | ** in the same logical place as the position element, and act as sentinals |
| 99151 | ** ending a position list array. POS_END is 0. POS_COLUMN is 1. |
| 99152 | ** The positions numbers are not stored literally but rather as two more |
| 99153 | ** the difference from the prior position, or the just the position plus |
| 99154 | ** 2 for the first position. Example: |
| 99155 | ** |
| 99156 | ** label: A B C D E F G H I J K |
| 99157 | ** value: 123 5 9 1 1 14 35 0 234 72 0 |
| 99158 | ** |
| 99159 | ** The 123 value is the first docid. For column zero in this document |
| 99160 | ** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1 |
| 99161 | ** at D signals the start of a new column; the 1 at E indicates that the |
| 99162 | ** new column is column number 1. There are two positions at 12 and 45 |
| 99163 | ** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The |
| 99164 | ** 234 at I is the next docid. It has one position 72 (72-2) and then |
| 99165 | ** terminates with the 0 at K. |
| 99166 | ** |
| 99167 | ** A DL_POSITIONS doclist omits the startOffset and endOffset |
| 99168 | ** information. A DL_DOCIDS doclist omits both the position and |
| 99169 | ** offset information, becoming an array of varint-encoded docids. |
| 99170 | ** |
| @@ -98492,11 +99734,11 @@ | |
| 99734 | sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ |
| 99735 | |
| 99736 | /* Precompiled statements used by the implementation. Each of these |
| 99737 | ** statements is run and reset within a single virtual table API call. |
| 99738 | */ |
| 99739 | sqlite3_stmt *aStmt[25]; |
| 99740 | |
| 99741 | /* Pointer to string containing the SQL: |
| 99742 | ** |
| 99743 | ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ? |
| 99744 | ** ORDER BY blockid" |
| @@ -98506,10 +99748,12 @@ | |
| 99748 | int nLeavesTotal; /* Total number of prepared leaves stmts */ |
| 99749 | int nLeavesAlloc; /* Allocated size of aLeavesStmt */ |
| 99750 | sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */ |
| 99751 | |
| 99752 | int nNodeSize; /* Soft limit for node size */ |
| 99753 | u8 bHasContent; /* True if %_content table exists */ |
| 99754 | u8 bHasDocsize; /* True if %_docsize table exists */ |
| 99755 | |
| 99756 | /* The following hash table is used to buffer pending index updates during |
| 99757 | ** transactions. Variable nPendingData estimates the memory size of the |
| 99758 | ** pending data, including hash table overhead, but not malloc overhead. |
| 99759 | ** When nPendingData exceeds nMaxPendingData, the buffer is flushed |
| @@ -98536,12 +99780,12 @@ | |
| 99780 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 99781 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 99782 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 99783 | char *aDoclist; /* List of docids for full-text queries */ |
| 99784 | int nDoclist; /* Size of buffer at aDoclist */ |
| 99785 | int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ |
| 99786 | u32 *aMatchinfo; /* Information about most recent match */ |
| 99787 | }; |
| 99788 | |
| 99789 | /* |
| 99790 | ** The Fts3Cursor.eSearch member is always set to one of the following. |
| 99791 | ** Actualy, Fts3Cursor.eSearch can be greater than or equal to |
| @@ -98643,10 +99887,12 @@ | |
| 99887 | Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, |
| 99888 | int (*)(Fts3Table *, void *, char *, int, char *, int), void * |
| 99889 | ); |
| 99890 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); |
| 99891 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
| 99892 | SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*); |
| 99893 | SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*); |
| 99894 | |
| 99895 | /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ |
| 99896 | #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 |
| 99897 | #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 |
| 99898 | #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 |
| @@ -98667,10 +99913,11 @@ | |
| 99913 | SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); |
| 99914 | SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); |
| 99915 | |
| 99916 | SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int); |
| 99917 | SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *, Fts3Expr *); |
| 99918 | SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int); |
| 99919 | |
| 99920 | /* fts3_tokenizer.c */ |
| 99921 | SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); |
| 99922 | SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); |
| 99923 | SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, |
| @@ -98677,14 +99924,11 @@ | |
| 99924 | const char *, sqlite3_tokenizer **, const char **, char ** |
| 99925 | ); |
| 99926 | |
| 99927 | /* fts3_snippet.c */ |
| 99928 | SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); |
| 99929 | SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, |
| 99930 | const char *, const char *, int, int |
| 99931 | ); |
| 99932 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *); |
| 99933 | |
| 99934 | /* fts3_expr.c */ |
| @@ -98800,16 +100044,27 @@ | |
| 100044 | } |
| 100045 | z[iOut] = '\0'; |
| 100046 | } |
| 100047 | } |
| 100048 | |
| 100049 | /* |
| 100050 | ** Read a single varint from the doclist at *pp and advance *pp to point |
| 100051 | ** to the next element of the varlist. Add the value of the varint |
| 100052 | ** to *pVal. |
| 100053 | */ |
| 100054 | static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){ |
| 100055 | sqlite3_int64 iVal; |
| 100056 | *pp += sqlite3Fts3GetVarint(*pp, &iVal); |
| 100057 | *pVal += iVal; |
| 100058 | } |
| 100059 | |
| 100060 | /* |
| 100061 | ** As long as *pp has not reached its end (pEnd), then do the same |
| 100062 | ** as fts3GetDeltaVarint(): read a single varint and add it to *pVal. |
| 100063 | ** But if we have reached the end of the varint, just set *pp=0 and |
| 100064 | ** leave *pVal unchanged. |
| 100065 | */ |
| 100066 | static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){ |
| 100067 | if( *pp>=pEnd ){ |
| 100068 | *pp = 0; |
| 100069 | }else{ |
| 100070 | fts3GetDeltaVarint(pp, pVal); |
| @@ -98839,35 +100094,52 @@ | |
| 100094 | p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
| 100095 | |
| 100096 | sqlite3_free(p); |
| 100097 | return SQLITE_OK; |
| 100098 | } |
| 100099 | |
| 100100 | /* |
| 100101 | ** Construct one or more SQL statements from the format string given |
| 100102 | ** and then evaluate those statements. The success code is writting |
| 100103 | ** into *pRc. |
| 100104 | ** |
| 100105 | ** If *pRc is initially non-zero then this routine is a no-op. |
| 100106 | */ |
| 100107 | void fts3DbExec( |
| 100108 | int *pRc, /* Success code */ |
| 100109 | sqlite3 *db, /* Database in which to run SQL */ |
| 100110 | const char *zFormat, /* Format string for SQL */ |
| 100111 | ... /* Arguments to the format string */ |
| 100112 | ){ |
| 100113 | va_list ap; |
| 100114 | char *zSql; |
| 100115 | if( *pRc ) return; |
| 100116 | va_start(ap, zFormat); |
| 100117 | zSql = sqlite3_vmprintf(zFormat, ap); |
| 100118 | va_end(ap); |
| 100119 | if( zSql==0 ){ |
| 100120 | *pRc = SQLITE_NOMEM; |
| 100121 | }else{ |
| 100122 | *pRc = sqlite3_exec(db, zSql, 0, 0, 0); |
| 100123 | sqlite3_free(zSql); |
| 100124 | } |
| 100125 | } |
| 100126 | |
| 100127 | /* |
| 100128 | ** The xDestroy() virtual table method. |
| 100129 | */ |
| 100130 | static int fts3DestroyMethod(sqlite3_vtab *pVtab){ |
| 100131 | int rc = SQLITE_OK; /* Return code */ |
| 100132 | Fts3Table *p = (Fts3Table *)pVtab; |
| 100133 | sqlite3 *db = p->db; |
| 100134 | |
| 100135 | /* Drop the shadow tables */ |
| 100136 | fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", p->zDb, p->zName); |
| 100137 | fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", p->zDb,p->zName); |
| 100138 | fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", p->zDb, p->zName); |
| 100139 | fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", p->zDb, p->zName); |
| 100140 | fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", p->zDb, p->zName); |
| 100141 | |
| 100142 | /* If everything has worked, invoke fts3DisconnectMethod() to free the |
| 100143 | ** memory associated with the Fts3Table structure and return SQLITE_OK. |
| 100144 | ** Otherwise, return an SQLite error code. |
| 100145 | */ |
| @@ -98912,50 +100184,77 @@ | |
| 100184 | ** Create the backing store tables (%_content, %_segments and %_segdir) |
| 100185 | ** required by the FTS3 table passed as the only argument. This is done |
| 100186 | ** as part of the vtab xCreate() method. |
| 100187 | */ |
| 100188 | static int fts3CreateTables(Fts3Table *p){ |
| 100189 | int rc = SQLITE_OK; /* Return code */ |
| 100190 | int i; /* Iterator variable */ |
| 100191 | char *zContentCols; /* Columns of %_content table */ |
| 100192 | sqlite3 *db = p->db; /* The database connection */ |
| 100193 | |
| 100194 | /* Create a list of user columns for the content table */ |
| 100195 | if( p->bHasContent ){ |
| 100196 | zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); |
| 100197 | for(i=0; zContentCols && i<p->nColumn; i++){ |
| 100198 | char *z = p->azColumn[i]; |
| 100199 | zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); |
| 100200 | } |
| 100201 | if( zContentCols==0 ) rc = SQLITE_NOMEM; |
| 100202 | |
| 100203 | /* Create the content table */ |
| 100204 | fts3DbExec(&rc, db, |
| 100205 | "CREATE TABLE %Q.'%q_content'(%s)", |
| 100206 | p->zDb, p->zName, zContentCols |
| 100207 | ); |
| 100208 | sqlite3_free(zContentCols); |
| 100209 | } |
| 100210 | /* Create other tables */ |
| 100211 | fts3DbExec(&rc, db, |
| 100212 | "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);", |
| 100213 | p->zDb, p->zName |
| 100214 | ); |
| 100215 | fts3DbExec(&rc, db, |
| 100216 | "CREATE TABLE %Q.'%q_segdir'(" |
| 100217 | "level INTEGER," |
| 100218 | "idx INTEGER," |
| 100219 | "start_block INTEGER," |
| 100220 | "leaves_end_block INTEGER," |
| 100221 | "end_block INTEGER," |
| 100222 | "root BLOB," |
| 100223 | "PRIMARY KEY(level, idx)" |
| 100224 | ");", |
| 100225 | p->zDb, p->zName |
| 100226 | ); |
| 100227 | if( p->bHasDocsize ){ |
| 100228 | fts3DbExec(&rc, db, |
| 100229 | "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", |
| 100230 | p->zDb, p->zName |
| 100231 | ); |
| 100232 | fts3DbExec(&rc, db, |
| 100233 | "CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);", |
| 100234 | p->zDb, p->zName |
| 100235 | ); |
| 100236 | } |
| 100237 | return rc; |
| 100238 | } |
| 100239 | |
| 100240 | /* |
| 100241 | ** Determine if a table currently exists in the database. |
| 100242 | */ |
| 100243 | static void fts3TableExists( |
| 100244 | int *pRc, /* Success code */ |
| 100245 | sqlite3 *db, /* The database connection to test */ |
| 100246 | const char *zDb, /* ATTACHed database within the connection */ |
| 100247 | const char *zName, /* Name of the FTS3 table */ |
| 100248 | const char *zSuffix, /* Shadow table extension */ |
| 100249 | u8 *pResult /* Write results here */ |
| 100250 | ){ |
| 100251 | int rc = SQLITE_OK; |
| 100252 | if( *pRc ) return; |
| 100253 | fts3DbExec(&rc, db, "SELECT 1 FROM %Q.'%q%s'", zDb, zName, zSuffix); |
| 100254 | *pResult = (rc==SQLITE_OK) ? 1 : 0; |
| 100255 | if( rc!=SQLITE_ERROR ) *pRc = rc; |
| 100256 | } |
| 100257 | |
| 100258 | /* |
| 100259 | ** This function is the implementation of both the xConnect and xCreate |
| 100260 | ** methods of the FTS3 virtual table. |
| @@ -99070,13 +100369,19 @@ | |
| 100369 | |
| 100370 | /* If this is an xCreate call, create the underlying tables in the |
| 100371 | ** database. TODO: For xConnect(), it could verify that said tables exist. |
| 100372 | */ |
| 100373 | if( isCreate ){ |
| 100374 | p->bHasContent = 1; |
| 100375 | p->bHasDocsize = argv[0][3]=='4'; |
| 100376 | rc = fts3CreateTables(p); |
| 100377 | }else{ |
| 100378 | rc = SQLITE_OK; |
| 100379 | fts3TableExists(&rc, db, argv[1], argv[2], "_content", &p->bHasContent); |
| 100380 | fts3TableExists(&rc, db, argv[1], argv[2], "_docsize", &p->bHasDocsize); |
| 100381 | } |
| 100382 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 100383 | |
| 100384 | rc = fts3DeclareVtab(p); |
| 100385 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 100386 | |
| 100387 | *ppVTab = &p->base; |
| @@ -99193,16 +100498,10 @@ | |
| 100498 | return SQLITE_NOMEM; |
| 100499 | } |
| 100500 | memset(pCsr, 0, sizeof(Fts3Cursor)); |
| 100501 | return SQLITE_OK; |
| 100502 | } |
| 100503 | |
| 100504 | /* |
| 100505 | ** Close the cursor. For additional information see the documentation |
| 100506 | ** on the xClose method of the virtual table interface. |
| 100507 | */ |
| @@ -99255,11 +100554,11 @@ | |
| 100554 | pCsr->isEof = 1; |
| 100555 | }else{ |
| 100556 | sqlite3_reset(pCsr->pStmt); |
| 100557 | fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId); |
| 100558 | pCsr->isRequireSeek = 1; |
| 100559 | pCsr->isMatchinfoNeeded = 1; |
| 100560 | } |
| 100561 | return rc; |
| 100562 | } |
| 100563 | |
| 100564 | |
| @@ -100120,10 +101419,78 @@ | |
| 101419 | }else{ |
| 101420 | sqlite3_free(pOut); |
| 101421 | } |
| 101422 | return rc; |
| 101423 | } |
| 101424 | |
| 101425 | static int fts3NearMerge( |
| 101426 | int mergetype, /* MERGE_POS_NEAR or MERGE_NEAR */ |
| 101427 | int nNear, /* Parameter to NEAR operator */ |
| 101428 | int nTokenLeft, /* Number of tokens in LHS phrase arg */ |
| 101429 | char *aLeft, /* Doclist for LHS (incl. positions) */ |
| 101430 | int nLeft, /* Size of LHS doclist in bytes */ |
| 101431 | int nTokenRight, /* As nTokenLeft */ |
| 101432 | char *aRight, /* As aLeft */ |
| 101433 | int nRight, /* As nRight */ |
| 101434 | char **paOut, /* OUT: Results of merge (malloced) */ |
| 101435 | int *pnOut /* OUT: Sized of output buffer */ |
| 101436 | ){ |
| 101437 | char *aOut; |
| 101438 | int rc; |
| 101439 | |
| 101440 | assert( mergetype==MERGE_POS_NEAR || MERGE_NEAR ); |
| 101441 | |
| 101442 | aOut = sqlite3_malloc(nLeft+nRight+1); |
| 101443 | if( aOut==0 ){ |
| 101444 | rc = SQLITE_NOMEM; |
| 101445 | }else{ |
| 101446 | rc = fts3DoclistMerge(mergetype, nNear+nTokenRight, nNear+nTokenLeft, |
| 101447 | aOut, pnOut, aLeft, nLeft, aRight, nRight |
| 101448 | ); |
| 101449 | if( rc!=SQLITE_OK ){ |
| 101450 | sqlite3_free(aOut); |
| 101451 | aOut = 0; |
| 101452 | } |
| 101453 | } |
| 101454 | |
| 101455 | *paOut = aOut; |
| 101456 | return rc; |
| 101457 | } |
| 101458 | |
| 101459 | SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *pLeft, Fts3Expr *pRight, int nNear){ |
| 101460 | int rc; |
| 101461 | if( pLeft->aDoclist==0 || pRight->aDoclist==0 ){ |
| 101462 | sqlite3_free(pLeft->aDoclist); |
| 101463 | sqlite3_free(pRight->aDoclist); |
| 101464 | pRight->aDoclist = 0; |
| 101465 | pLeft->aDoclist = 0; |
| 101466 | rc = SQLITE_OK; |
| 101467 | }else{ |
| 101468 | char *aOut; |
| 101469 | int nOut; |
| 101470 | |
| 101471 | rc = fts3NearMerge(MERGE_POS_NEAR, nNear, |
| 101472 | pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist, |
| 101473 | pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist, |
| 101474 | &aOut, &nOut |
| 101475 | ); |
| 101476 | if( rc!=SQLITE_OK ) return rc; |
| 101477 | sqlite3_free(pRight->aDoclist); |
| 101478 | pRight->aDoclist = aOut; |
| 101479 | pRight->nDoclist = nOut; |
| 101480 | |
| 101481 | rc = fts3NearMerge(MERGE_POS_NEAR, nNear, |
| 101482 | pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist, |
| 101483 | pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist, |
| 101484 | &aOut, &nOut |
| 101485 | ); |
| 101486 | sqlite3_free(pLeft->aDoclist); |
| 101487 | pLeft->aDoclist = aOut; |
| 101488 | pLeft->nDoclist = nOut; |
| 101489 | } |
| 101490 | return rc; |
| 101491 | } |
| 101492 | |
| 101493 | /* |
| 101494 | ** Evaluate the full-text expression pExpr against fts3 table pTab. Store |
| 101495 | ** the resulting doclist in *paOut and *pnOut. |
| 101496 | */ |
| @@ -100165,13 +101532,10 @@ | |
| 101532 | switch( pExpr->eType ){ |
| 101533 | case FTSQUERY_NEAR: { |
| 101534 | Fts3Expr *pLeft; |
| 101535 | Fts3Expr *pRight; |
| 101536 | int mergetype = isReqPos ? MERGE_POS_NEAR : MERGE_NEAR; |
| 101537 | |
| 101538 | if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){ |
| 101539 | mergetype = MERGE_POS_NEAR; |
| 101540 | } |
| 101541 | pLeft = pExpr->pLeft; |
| @@ -100180,21 +101544,15 @@ | |
| 101544 | } |
| 101545 | pRight = pExpr->pRight; |
| 101546 | assert( pRight->eType==FTSQUERY_PHRASE ); |
| 101547 | assert( pLeft->eType==FTSQUERY_PHRASE ); |
| 101548 | |
| 101549 | rc = fts3NearMerge(mergetype, pExpr->nNear, |
| 101550 | pLeft->pPhrase->nToken, aLeft, nLeft, |
| 101551 | pRight->pPhrase->nToken, aRight, nRight, |
| 101552 | paOut, pnOut |
| 101553 | ); |
| 101554 | sqlite3_free(aLeft); |
| 101555 | break; |
| 101556 | } |
| 101557 | |
| 101558 | case FTSQUERY_OR: { |
| @@ -100441,11 +101799,11 @@ | |
| 101799 | return evalFts3Expr(pTab, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1); |
| 101800 | } |
| 101801 | |
| 101802 | /* |
| 101803 | ** After ExprLoadDoclist() (see above) has been called, this function is |
| 101804 | ** used to iterate/search through the position lists that make up the doclist |
| 101805 | ** stored in pExpr->aDoclist. |
| 101806 | */ |
| 101807 | SQLITE_PRIVATE char *sqlite3Fts3FindPositions( |
| 101808 | Fts3Expr *pExpr, /* Access this expressions doclist */ |
| 101809 | sqlite3_int64 iDocid, /* Docid associated with requested pos-list */ |
| @@ -100476,11 +101834,11 @@ | |
| 101834 | fts3ColumnlistCopy(0, &pCsr); |
| 101835 | if( *pCsr==0x00 ) return 0; |
| 101836 | pCsr++; |
| 101837 | pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis); |
| 101838 | } |
| 101839 | if( iCol==iThis && (*pCsr&0xFE) ) return pCsr; |
| 101840 | } |
| 101841 | return 0; |
| 101842 | } |
| 101843 | } |
| 101844 | } |
| @@ -100528,49 +101886,12 @@ | |
| 101886 | ){ |
| 101887 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 101888 | const char *zStart = "<b>"; |
| 101889 | const char *zEnd = "</b>"; |
| 101890 | const char *zEllipsis = "<b>...</b>"; |
| 101891 | int iCol = -1; |
| 101892 | int nToken = 15; /* Default number of tokens in snippet */ |
| 101893 | |
| 101894 | /* There must be at least one argument passed to this function (otherwise |
| 101895 | ** the non-overloaded version would have been called instead of this one). |
| 101896 | */ |
| 101897 | assert( nVal>=1 ); |
| @@ -100590,11 +101911,11 @@ | |
| 101911 | case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); |
| 101912 | } |
| 101913 | if( !zEllipsis || !zEnd || !zStart ){ |
| 101914 | sqlite3_result_error_nomem(pContext); |
| 101915 | }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ |
| 101916 | sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); |
| 101917 | } |
| 101918 | } |
| 101919 | |
| 101920 | /* |
| 101921 | ** Implementation of the offsets() function for FTS3 |
| @@ -100691,11 +102012,10 @@ | |
| 102012 | struct Overloaded { |
| 102013 | const char *zName; |
| 102014 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**); |
| 102015 | } aOverload[] = { |
| 102016 | { "snippet", fts3SnippetFunc }, |
| 102017 | { "offsets", fts3OffsetsFunc }, |
| 102018 | { "optimize", fts3OptimizeFunc }, |
| 102019 | { "matchinfo", fts3MatchinfoFunc }, |
| 102020 | }; |
| 102021 | int i; /* Iterator variable */ |
| @@ -100720,26 +102040,39 @@ | |
| 102040 | */ |
| 102041 | static int fts3RenameMethod( |
| 102042 | sqlite3_vtab *pVtab, /* Virtual table handle */ |
| 102043 | const char *zName /* New name of table */ |
| 102044 | ){ |
| 102045 | Fts3Table *p = (Fts3Table *)pVtab; |
| 102046 | sqlite3 *db; /* Database connection */ |
| 102047 | int rc; /* Return Code */ |
| 102048 | |
| 102049 | db = p->db; |
| 102050 | rc = SQLITE_OK; |
| 102051 | fts3DbExec(&rc, db, |
| 102052 | "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", |
| 102053 | p->zDb, p->zName, zName |
| 102054 | ); |
| 102055 | if( rc==SQLITE_ERROR ) rc = SQLITE_OK; |
| 102056 | if( p->bHasDocsize ){ |
| 102057 | fts3DbExec(&rc, db, |
| 102058 | "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';", |
| 102059 | p->zDb, p->zName, zName |
| 102060 | ); |
| 102061 | fts3DbExec(&rc, db, |
| 102062 | "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';", |
| 102063 | p->zDb, p->zName, zName |
| 102064 | ); |
| 102065 | } |
| 102066 | fts3DbExec(&rc, db, |
| 102067 | "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';", |
| 102068 | p->zDb, p->zName, zName |
| 102069 | ); |
| 102070 | fts3DbExec(&rc, db, |
| 102071 | "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';", |
| 102072 | p->zDb, p->zName, zName |
| 102073 | ); |
| 102074 | return rc; |
| 102075 | } |
| 102076 | |
| 102077 | static const sqlite3_module fts3Module = { |
| 102078 | /* iVersion */ 0, |
| @@ -100841,18 +102174,23 @@ | |
| 102174 | ** module with sqlite. |
| 102175 | */ |
| 102176 | if( SQLITE_OK==rc |
| 102177 | && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) |
| 102178 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) |
| 102179 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) |
| 102180 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", -1)) |
| 102181 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) |
| 102182 | ){ |
| 102183 | rc = sqlite3_create_module_v2( |
| 102184 | db, "fts3", &fts3Module, (void *)pHash, hashDestroy |
| 102185 | ); |
| 102186 | if( rc==SQLITE_OK ){ |
| 102187 | rc = sqlite3_create_module_v2( |
| 102188 | db, "fts4", &fts3Module, (void *)pHash, 0 |
| 102189 | ); |
| 102190 | } |
| 102191 | return rc; |
| 102192 | } |
| 102193 | |
| 102194 | /* An error has occurred. Delete the hash table and return the error code. */ |
| 102195 | assert( rc!=SQLITE_OK ); |
| 102196 | if( pHash ){ |
| @@ -102778,13 +104116,15 @@ | |
| 104116 | } |
| 104117 | |
| 104118 | if( c->iOffset>iStartOffset ){ |
| 104119 | int n = c->iOffset-iStartOffset; |
| 104120 | if( n>c->nAllocated ){ |
| 104121 | char *pNew; |
| 104122 | c->nAllocated = n+20; |
| 104123 | pNew = sqlite3_realloc(c->zToken, c->nAllocated); |
| 104124 | if( !pNew ) return SQLITE_NOMEM; |
| 104125 | c->zToken = pNew; |
| 104126 | } |
| 104127 | porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); |
| 104128 | *pzToken = c->zToken; |
| 104129 | *piStartOffset = iStartOffset; |
| 104130 | *piEndOffset = c->iOffset; |
| @@ -103491,13 +104831,15 @@ | |
| 104831 | } |
| 104832 | |
| 104833 | if( c->iOffset>iStartOffset ){ |
| 104834 | int i, n = c->iOffset-iStartOffset; |
| 104835 | if( n>c->nTokenAllocated ){ |
| 104836 | char *pNew; |
| 104837 | c->nTokenAllocated = n+20; |
| 104838 | pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated); |
| 104839 | if( !pNew ) return SQLITE_NOMEM; |
| 104840 | c->pToken = pNew; |
| 104841 | } |
| 104842 | for(i=0; i<n; i++){ |
| 104843 | /* TODO(shess) This needs expansion to handle UTF-8 |
| 104844 | ** case-insensitivity. |
| 104845 | */ |
| @@ -103677,23 +105019,30 @@ | |
| 105019 | #define SQL_DELETE_CONTENT 0 |
| 105020 | #define SQL_IS_EMPTY 1 |
| 105021 | #define SQL_DELETE_ALL_CONTENT 2 |
| 105022 | #define SQL_DELETE_ALL_SEGMENTS 3 |
| 105023 | #define SQL_DELETE_ALL_SEGDIR 4 |
| 105024 | #define SQL_DELETE_ALL_DOCSIZE 5 |
| 105025 | #define SQL_DELETE_ALL_STAT 6 |
| 105026 | #define SQL_SELECT_CONTENT_BY_ROWID 7 |
| 105027 | #define SQL_NEXT_SEGMENT_INDEX 8 |
| 105028 | #define SQL_INSERT_SEGMENTS 9 |
| 105029 | #define SQL_NEXT_SEGMENTS_ID 10 |
| 105030 | #define SQL_INSERT_SEGDIR 11 |
| 105031 | #define SQL_SELECT_LEVEL 12 |
| 105032 | #define SQL_SELECT_ALL_LEVEL 13 |
| 105033 | #define SQL_SELECT_LEVEL_COUNT 14 |
| 105034 | #define SQL_SELECT_SEGDIR_COUNT_MAX 15 |
| 105035 | #define SQL_DELETE_SEGDIR_BY_LEVEL 16 |
| 105036 | #define SQL_DELETE_SEGMENTS_RANGE 17 |
| 105037 | #define SQL_CONTENT_INSERT 18 |
| 105038 | #define SQL_GET_BLOCK 19 |
| 105039 | #define SQL_DELETE_DOCSIZE 20 |
| 105040 | #define SQL_REPLACE_DOCSIZE 21 |
| 105041 | #define SQL_SELECT_DOCSIZE 22 |
| 105042 | #define SQL_SELECT_DOCTOTAL 23 |
| 105043 | #define SQL_REPLACE_DOCTOTAL 24 |
| 105044 | |
| 105045 | /* |
| 105046 | ** This function is used to obtain an SQLite prepared statement handle |
| 105047 | ** for the statement identified by the second argument. If successful, |
| 105048 | ** *pp is set to the requested statement handle and SQLITE_OK returned. |
| @@ -103714,29 +105063,36 @@ | |
| 105063 | /* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?", |
| 105064 | /* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)", |
| 105065 | /* 2 */ "DELETE FROM %Q.'%q_content'", |
| 105066 | /* 3 */ "DELETE FROM %Q.'%q_segments'", |
| 105067 | /* 4 */ "DELETE FROM %Q.'%q_segdir'", |
| 105068 | /* 5 */ "DELETE FROM %Q.'%q_docsize'", |
| 105069 | /* 6 */ "DELETE FROM %Q.'%q_stat'", |
| 105070 | /* 7 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?", |
| 105071 | /* 8 */ "SELECT coalesce(max(idx)+1, 0) FROM %Q.'%q_segdir' WHERE level=?", |
| 105072 | /* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", |
| 105073 | /* 10 */ "SELECT coalesce(max(blockid)+1, 1) FROM %Q.'%q_segments'", |
| 105074 | /* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", |
| 105075 | |
| 105076 | /* Return segments in order from oldest to newest.*/ |
| 105077 | /* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root " |
| 105078 | "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC", |
| 105079 | /* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root " |
| 105080 | "FROM %Q.'%q_segdir' ORDER BY level DESC, idx ASC", |
| 105081 | |
| 105082 | /* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", |
| 105083 | /* 15 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'", |
| 105084 | |
| 105085 | /* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?", |
| 105086 | /* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?", |
| 105087 | /* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%z)", |
| 105088 | /* 19 */ "SELECT block FROM %Q.'%q_segments' WHERE blockid = ?", |
| 105089 | /* 20 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", |
| 105090 | /* 21 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", |
| 105091 | /* 22 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", |
| 105092 | /* 23 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0", |
| 105093 | /* 24 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)", |
| 105094 | }; |
| 105095 | int rc = SQLITE_OK; |
| 105096 | sqlite3_stmt *pStmt; |
| 105097 | |
| 105098 | assert( SizeofArray(azSql)==SizeofArray(p->aStmt) ); |
| @@ -103789,18 +105145,25 @@ | |
| 105145 | ** is executed. |
| 105146 | ** |
| 105147 | ** Returns SQLITE_OK if the statement is successfully executed, or an |
| 105148 | ** SQLite error code otherwise. |
| 105149 | */ |
| 105150 | static void fts3SqlExec( |
| 105151 | int *pRC, /* Result code */ |
| 105152 | Fts3Table *p, /* The FTS3 table */ |
| 105153 | int eStmt, /* Index of statement to evaluate */ |
| 105154 | sqlite3_value **apVal /* Parameters to bind */ |
| 105155 | ){ |
| 105156 | sqlite3_stmt *pStmt; |
| 105157 | int rc; |
| 105158 | if( *pRC ) return; |
| 105159 | rc = fts3SqlStmt(p, eStmt, &pStmt, apVal); |
| 105160 | if( rc==SQLITE_OK ){ |
| 105161 | sqlite3_step(pStmt); |
| 105162 | rc = sqlite3_reset(pStmt); |
| 105163 | } |
| 105164 | *pRC = rc; |
| 105165 | } |
| 105166 | |
| 105167 | |
| 105168 | /* |
| 105169 | ** Read a single block from the %_segments table. If the specified block |
| @@ -103976,15 +105339,21 @@ | |
| 105339 | ** pending-terms hash-table. The docid used is that currently stored in |
| 105340 | ** p->iPrevDocid, and the column is specified by argument iCol. |
| 105341 | ** |
| 105342 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. |
| 105343 | */ |
| 105344 | static int fts3PendingTermsAdd( |
| 105345 | Fts3Table *p, /* FTS table into which text will be inserted */ |
| 105346 | const char *zText, /* Text of document to be inseted */ |
| 105347 | int iCol, /* Column number into which text is inserted */ |
| 105348 | u32 *pnWord /* OUT: Number of tokens inserted */ |
| 105349 | ){ |
| 105350 | int rc; |
| 105351 | int iStart; |
| 105352 | int iEnd; |
| 105353 | int iPos; |
| 105354 | int nWord = 0; |
| 105355 | |
| 105356 | char const *zToken; |
| 105357 | int nToken; |
| 105358 | |
| 105359 | sqlite3_tokenizer *pTokenizer = p->pTokenizer; |
| @@ -104004,10 +105373,12 @@ | |
| 105373 | xNext = pModule->xNext; |
| 105374 | while( SQLITE_OK==rc |
| 105375 | && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) |
| 105376 | ){ |
| 105377 | PendingList *pList; |
| 105378 | |
| 105379 | if( iPos>=nWord ) nWord = iPos+1; |
| 105380 | |
| 105381 | /* Positions cannot be negative; we use -1 as a terminator internally. |
| 105382 | ** Tokens must have a non-zero length. |
| 105383 | */ |
| 105384 | if( iPos<0 || !zToken || nToken<=0 ){ |
| @@ -104033,10 +105404,11 @@ | |
| 105404 | p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem)); |
| 105405 | } |
| 105406 | } |
| 105407 | |
| 105408 | pModule->xClose(pCsr); |
| 105409 | *pnWord = nWord; |
| 105410 | return (rc==SQLITE_DONE ? SQLITE_OK : rc); |
| 105411 | } |
| 105412 | |
| 105413 | /* |
| 105414 | ** Calling this function indicates that subsequent calls to |
| @@ -104073,16 +105445,16 @@ | |
| 105445 | ** pendingTerms hash table. |
| 105446 | ** |
| 105447 | ** Argument apVal is the same as the similarly named argument passed to |
| 105448 | ** fts3InsertData(). Parameter iDocid is the docid of the new row. |
| 105449 | */ |
| 105450 | static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){ |
| 105451 | int i; /* Iterator variable */ |
| 105452 | for(i=2; i<p->nColumn+2; i++){ |
| 105453 | const char *zText = (const char *)sqlite3_value_text(apVal[i]); |
| 105454 | if( zText ){ |
| 105455 | int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]); |
| 105456 | if( rc!=SQLITE_OK ){ |
| 105457 | return rc; |
| 105458 | } |
| 105459 | } |
| 105460 | } |
| @@ -104159,53 +105531,60 @@ | |
| 105531 | /* |
| 105532 | ** Remove all data from the FTS3 table. Clear the hash table containing |
| 105533 | ** pending terms. |
| 105534 | */ |
| 105535 | static int fts3DeleteAll(Fts3Table *p){ |
| 105536 | int rc = SQLITE_OK; /* Return code */ |
| 105537 | |
| 105538 | /* Discard the contents of the pending-terms hash table. */ |
| 105539 | sqlite3Fts3PendingTermsClear(p); |
| 105540 | |
| 105541 | /* Delete everything from the %_content, %_segments and %_segdir tables. */ |
| 105542 | fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0); |
| 105543 | fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0); |
| 105544 | fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); |
| 105545 | if( p->bHasDocsize ){ |
| 105546 | fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0); |
| 105547 | fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); |
| 105548 | } |
| 105549 | return rc; |
| 105550 | } |
| 105551 | |
| 105552 | /* |
| 105553 | ** The first element in the apVal[] array is assumed to contain the docid |
| 105554 | ** (an integer) of a row about to be deleted. Remove all terms from the |
| 105555 | ** full-text index. |
| 105556 | */ |
| 105557 | static void fts3DeleteTerms( |
| 105558 | int *pRC, /* Result code */ |
| 105559 | Fts3Table *p, /* The FTS table to delete from */ |
| 105560 | sqlite3_value **apVal, /* apVal[] contains the docid to be deleted */ |
| 105561 | u32 *aSz /* Sizes of deleted document written here */ |
| 105562 | ){ |
| 105563 | int rc; |
| 105564 | sqlite3_stmt *pSelect; |
| 105565 | |
| 105566 | if( *pRC ) return; |
| 105567 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, apVal); |
| 105568 | if( rc==SQLITE_OK ){ |
| 105569 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 105570 | int i; |
| 105571 | for(i=1; i<=p->nColumn; i++){ |
| 105572 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 105573 | rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]); |
| 105574 | if( rc!=SQLITE_OK ){ |
| 105575 | sqlite3_reset(pSelect); |
| 105576 | *pRC = rc; |
| 105577 | return; |
| 105578 | } |
| 105579 | } |
| 105580 | } |
| 105581 | rc = sqlite3_reset(pSelect); |
| 105582 | }else{ |
| 105583 | sqlite3_reset(pSelect); |
| 105584 | } |
| 105585 | *pRC = rc; |
| 105586 | } |
| 105587 | |
| 105588 | /* |
| 105589 | ** Forward declaration to account for the circular dependency between |
| 105590 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| @@ -105321,11 +106700,11 @@ | |
| 106700 | sqlite3_bind_int(pDelete, 1, iLevel); |
| 106701 | sqlite3_step(pDelete); |
| 106702 | rc = sqlite3_reset(pDelete); |
| 106703 | } |
| 106704 | }else{ |
| 106705 | fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); |
| 106706 | } |
| 106707 | |
| 106708 | return rc; |
| 106709 | } |
| 106710 | |
| @@ -105748,10 +107127,215 @@ | |
| 107127 | if( rc==SQLITE_OK ){ |
| 107128 | sqlite3Fts3PendingTermsClear(p); |
| 107129 | } |
| 107130 | return rc; |
| 107131 | } |
| 107132 | |
| 107133 | /* |
| 107134 | ** Encode N integers as varints into a blob. |
| 107135 | */ |
| 107136 | static void fts3EncodeIntArray( |
| 107137 | int N, /* The number of integers to encode */ |
| 107138 | u32 *a, /* The integer values */ |
| 107139 | char *zBuf, /* Write the BLOB here */ |
| 107140 | int *pNBuf /* Write number of bytes if zBuf[] used here */ |
| 107141 | ){ |
| 107142 | int i, j; |
| 107143 | for(i=j=0; i<N; i++){ |
| 107144 | j += sqlite3Fts3PutVarint(&zBuf[j], (sqlite3_int64)a[i]); |
| 107145 | } |
| 107146 | *pNBuf = j; |
| 107147 | } |
| 107148 | |
| 107149 | /* |
| 107150 | ** Decode a blob of varints into N integers |
| 107151 | */ |
| 107152 | static void fts3DecodeIntArray( |
| 107153 | int N, /* The number of integers to decode */ |
| 107154 | u32 *a, /* Write the integer values */ |
| 107155 | const char *zBuf, /* The BLOB containing the varints */ |
| 107156 | int nBuf /* size of the BLOB */ |
| 107157 | ){ |
| 107158 | int i, j; |
| 107159 | UNUSED_PARAMETER(nBuf); |
| 107160 | for(i=j=0; i<N; i++){ |
| 107161 | sqlite3_int64 x; |
| 107162 | j += sqlite3Fts3GetVarint(&zBuf[j], &x); |
| 107163 | assert(j<=nBuf); |
| 107164 | a[i] = (u32)(x & 0xffffffff); |
| 107165 | } |
| 107166 | } |
| 107167 | |
| 107168 | /* |
| 107169 | ** Fill in the document size auxiliary information for the matchinfo |
| 107170 | ** structure. The auxiliary information is: |
| 107171 | ** |
| 107172 | ** N Total number of documents in the full-text index |
| 107173 | ** a0 Average length of column 0 over the whole index |
| 107174 | ** n0 Length of column 0 on the matching row |
| 107175 | ** ... |
| 107176 | ** aM Average length of column M over the whole index |
| 107177 | ** nM Length of column M on the matching row |
| 107178 | ** |
| 107179 | ** The fts3MatchinfoDocsizeLocal() routine fills in the nX values. |
| 107180 | ** The fts3MatchinfoDocsizeGlobal() routine fills in N and the aX values. |
| 107181 | */ |
| 107182 | SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor *pCur, u32 *a){ |
| 107183 | const char *pBlob; /* The BLOB holding %_docsize info */ |
| 107184 | int nBlob; /* Size of the BLOB */ |
| 107185 | sqlite3_stmt *pStmt; /* Statement for reading and writing */ |
| 107186 | int i, j; /* Loop counters */ |
| 107187 | sqlite3_int64 x; /* Varint value */ |
| 107188 | int rc; /* Result code from subfunctions */ |
| 107189 | Fts3Table *p; /* The FTS table */ |
| 107190 | |
| 107191 | p = (Fts3Table*)pCur->base.pVtab; |
| 107192 | rc = fts3SqlStmt(p, SQL_SELECT_DOCSIZE, &pStmt, 0); |
| 107193 | if( rc ){ |
| 107194 | return rc; |
| 107195 | } |
| 107196 | sqlite3_bind_int64(pStmt, 1, pCur->iPrevId); |
| 107197 | if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 107198 | nBlob = sqlite3_column_bytes(pStmt, 0); |
| 107199 | pBlob = (const char*)sqlite3_column_blob(pStmt, 0); |
| 107200 | for(i=j=0; i<p->nColumn && j<nBlob; i++){ |
| 107201 | j = sqlite3Fts3GetVarint(&pBlob[j], &x); |
| 107202 | a[2+i*2] = (u32)(x & 0xffffffff); |
| 107203 | } |
| 107204 | } |
| 107205 | sqlite3_reset(pStmt); |
| 107206 | return SQLITE_OK; |
| 107207 | } |
| 107208 | SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor *pCur, u32 *a){ |
| 107209 | const char *pBlob; /* The BLOB holding %_stat info */ |
| 107210 | int nBlob; /* Size of the BLOB */ |
| 107211 | sqlite3_stmt *pStmt; /* Statement for reading and writing */ |
| 107212 | int i, j; /* Loop counters */ |
| 107213 | sqlite3_int64 x; /* Varint value */ |
| 107214 | int nDoc; /* Number of documents */ |
| 107215 | int rc; /* Result code from subfunctions */ |
| 107216 | Fts3Table *p; /* The FTS table */ |
| 107217 | |
| 107218 | p = (Fts3Table*)pCur->base.pVtab; |
| 107219 | rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0); |
| 107220 | if( rc ){ |
| 107221 | return rc; |
| 107222 | } |
| 107223 | if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 107224 | nBlob = sqlite3_column_bytes(pStmt, 0); |
| 107225 | pBlob = (const char*)sqlite3_column_blob(pStmt, 0); |
| 107226 | j = sqlite3Fts3GetVarint(pBlob, &x); |
| 107227 | a[0] = nDoc = (u32)(x & 0xffffffff); |
| 107228 | for(i=0; i<p->nColumn && j<nBlob; i++){ |
| 107229 | j = sqlite3Fts3GetVarint(&pBlob[j], &x); |
| 107230 | a[1+i*2] = ((u32)(x & 0xffffffff) + nDoc/2)/nDoc; |
| 107231 | } |
| 107232 | } |
| 107233 | sqlite3_reset(pStmt); |
| 107234 | return SQLITE_OK; |
| 107235 | } |
| 107236 | |
| 107237 | /* |
| 107238 | ** Insert the sizes (in tokens) for each column of the document |
| 107239 | ** with docid equal to p->iPrevDocid. The sizes are encoded as |
| 107240 | ** a blob of varints. |
| 107241 | */ |
| 107242 | static void fts3InsertDocsize( |
| 107243 | int *pRC, /* Result code */ |
| 107244 | Fts3Table *p, /* Table into which to insert */ |
| 107245 | u32 *aSz /* Sizes of each column */ |
| 107246 | ){ |
| 107247 | char *pBlob; /* The BLOB encoding of the document size */ |
| 107248 | int nBlob; /* Number of bytes in the BLOB */ |
| 107249 | sqlite3_stmt *pStmt; /* Statement used to insert the encoding */ |
| 107250 | int rc; /* Result code from subfunctions */ |
| 107251 | |
| 107252 | if( *pRC ) return; |
| 107253 | pBlob = sqlite3_malloc( 10*p->nColumn ); |
| 107254 | if( pBlob==0 ){ |
| 107255 | *pRC = SQLITE_NOMEM; |
| 107256 | return; |
| 107257 | } |
| 107258 | fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob); |
| 107259 | rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0); |
| 107260 | if( rc ){ |
| 107261 | sqlite3_free(pBlob); |
| 107262 | *pRC = rc; |
| 107263 | return; |
| 107264 | } |
| 107265 | sqlite3_bind_int64(pStmt, 1, p->iPrevDocid); |
| 107266 | sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free); |
| 107267 | sqlite3_step(pStmt); |
| 107268 | *pRC = sqlite3_reset(pStmt); |
| 107269 | } |
| 107270 | |
| 107271 | /* |
| 107272 | ** Update the 0 record of the %_stat table so that it holds a blob |
| 107273 | ** which contains the document count followed by the cumulative |
| 107274 | ** document sizes for all columns. |
| 107275 | */ |
| 107276 | static void fts3UpdateDocTotals( |
| 107277 | int *pRC, /* The result code */ |
| 107278 | Fts3Table *p, /* Table being updated */ |
| 107279 | u32 *aSzIns, /* Size increases */ |
| 107280 | u32 *aSzDel, /* Size decreases */ |
| 107281 | int nChng /* Change in the number of documents */ |
| 107282 | ){ |
| 107283 | char *pBlob; /* Storage for BLOB written into %_stat */ |
| 107284 | int nBlob; /* Size of BLOB written into %_stat */ |
| 107285 | u32 *a; /* Array of integers that becomes the BLOB */ |
| 107286 | sqlite3_stmt *pStmt; /* Statement for reading and writing */ |
| 107287 | int i; /* Loop counter */ |
| 107288 | int rc; /* Result code from subfunctions */ |
| 107289 | |
| 107290 | if( *pRC ) return; |
| 107291 | a = sqlite3_malloc( (sizeof(u32)+10)*(p->nColumn+1) ); |
| 107292 | if( a==0 ){ |
| 107293 | *pRC = SQLITE_NOMEM; |
| 107294 | return; |
| 107295 | } |
| 107296 | pBlob = (char*)&a[p->nColumn+1]; |
| 107297 | rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0); |
| 107298 | if( rc ){ |
| 107299 | sqlite3_free(a); |
| 107300 | *pRC = rc; |
| 107301 | return; |
| 107302 | } |
| 107303 | if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 107304 | fts3DecodeIntArray(p->nColumn+1, a, |
| 107305 | sqlite3_column_blob(pStmt, 0), |
| 107306 | sqlite3_column_bytes(pStmt, 0)); |
| 107307 | }else{ |
| 107308 | memset(a, 0, sizeof(u32)*(p->nColumn+1) ); |
| 107309 | } |
| 107310 | sqlite3_reset(pStmt); |
| 107311 | if( nChng<0 && a[0]<(u32)(-nChng) ){ |
| 107312 | a[0] = 0; |
| 107313 | }else{ |
| 107314 | a[0] += nChng; |
| 107315 | } |
| 107316 | for(i=0; i<p->nColumn; i++){ |
| 107317 | u32 x = a[i+1]; |
| 107318 | if( x+aSzIns[i] < aSzDel[i] ){ |
| 107319 | x = 0; |
| 107320 | }else{ |
| 107321 | x = x + aSzIns[i] - aSzDel[i]; |
| 107322 | } |
| 107323 | a[i+1] = x; |
| 107324 | } |
| 107325 | fts3EncodeIntArray(p->nColumn+1, a, pBlob, &nBlob); |
| 107326 | rc = fts3SqlStmt(p, SQL_REPLACE_DOCTOTAL, &pStmt, 0); |
| 107327 | if( rc ){ |
| 107328 | sqlite3_free(a); |
| 107329 | *pRC = rc; |
| 107330 | return; |
| 107331 | } |
| 107332 | sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC); |
| 107333 | sqlite3_step(pStmt); |
| 107334 | *pRC = sqlite3_reset(pStmt); |
| 107335 | sqlite3_free(a); |
| 107336 | } |
| 107337 | |
| 107338 | /* |
| 107339 | ** Handle a 'special' INSERT of the form: |
| 107340 | ** |
| 107341 | ** "INSERT INTO tbl(tbl) VALUES(<expr>)" |
| @@ -105800,11 +107384,20 @@ | |
| 107384 | ){ |
| 107385 | Fts3Table *p = (Fts3Table *)pVtab; |
| 107386 | int rc = SQLITE_OK; /* Return Code */ |
| 107387 | int isRemove = 0; /* True for an UPDATE or DELETE */ |
| 107388 | sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */ |
| 107389 | u32 *aSzIns; /* Sizes of inserted documents */ |
| 107390 | u32 *aSzDel; /* Sizes of deleted documents */ |
| 107391 | int nChng = 0; /* Net change in number of documents */ |
| 107392 | |
| 107393 | |
| 107394 | /* Allocate space to hold the change in document sizes */ |
| 107395 | aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*p->nColumn*2 ); |
| 107396 | if( aSzIns==0 ) return SQLITE_NOMEM; |
| 107397 | aSzDel = &aSzIns[p->nColumn]; |
| 107398 | memset(aSzIns, 0, sizeof(aSzIns[0])*p->nColumn*2); |
| 107399 | |
| 107400 | /* If this is a DELETE or UPDATE operation, remove the old record. */ |
| 107401 | if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 107402 | int isEmpty; |
| 107403 | rc = fts3IsEmpty(p, apVal, &isEmpty); |
| @@ -105817,19 +107410,20 @@ | |
| 107410 | rc = fts3DeleteAll(p); |
| 107411 | }else{ |
| 107412 | isRemove = 1; |
| 107413 | iRemove = sqlite3_value_int64(apVal[0]); |
| 107414 | rc = fts3PendingTermsDocid(p, iRemove); |
| 107415 | fts3DeleteTerms(&rc, p, apVal, aSzDel); |
| 107416 | fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, apVal); |
| 107417 | if( p->bHasDocsize ){ |
| 107418 | fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, apVal); |
| 107419 | nChng--; |
| 107420 | } |
| 107421 | } |
| 107422 | } |
| 107423 | }else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){ |
| 107424 | sqlite3_free(aSzIns); |
| 107425 | return fts3SpecialInsert(p, apVal[p->nColumn+2]); |
| 107426 | } |
| 107427 | |
| 107428 | /* If this is an INSERT or UPDATE operation, insert the new record. */ |
| 107429 | if( nArg>1 && rc==SQLITE_OK ){ |
| @@ -105836,14 +107430,23 @@ | |
| 107430 | rc = fts3InsertData(p, apVal, pRowid); |
| 107431 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){ |
| 107432 | rc = fts3PendingTermsDocid(p, *pRowid); |
| 107433 | } |
| 107434 | if( rc==SQLITE_OK ){ |
| 107435 | rc = fts3InsertTerms(p, apVal, aSzIns); |
| 107436 | } |
| 107437 | if( p->bHasDocsize ){ |
| 107438 | nChng++; |
| 107439 | fts3InsertDocsize(&rc, p, aSzIns); |
| 107440 | } |
| 107441 | } |
| 107442 | |
| 107443 | if( p->bHasDocsize ){ |
| 107444 | fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); |
| 107445 | } |
| 107446 | |
| 107447 | sqlite3_free(aSzIns); |
| 107448 | return rc; |
| 107449 | } |
| 107450 | |
| 107451 | /* |
| 107452 | ** Flush any data in the pending-terms hash table to disk. If successful, |
| @@ -105886,736 +107489,131 @@ | |
| 107489 | */ |
| 107490 | |
| 107491 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 107492 | |
| 107493 | |
| 107494 | |
| 107495 | /* |
| 107496 | ** Used as an fts3ExprIterate() context when loading phrase doclists to |
| 107497 | ** Fts3Expr.aDoclist[]/nDoclist. |
| 107498 | */ |
| 107499 | typedef struct LoadDoclistCtx LoadDoclistCtx; |
| 107500 | struct LoadDoclistCtx { |
| 107501 | Fts3Table *pTab; /* FTS3 Table */ |
| 107502 | int nPhrase; /* Number of phrases seen so far */ |
| 107503 | int nToken; /* Number of tokens seen so far */ |
| 107504 | }; |
| 107505 | |
| 107506 | /* |
| 107507 | ** The following types are used as part of the implementation of the |
| 107508 | ** fts3BestSnippet() routine. |
| 107509 | */ |
| 107510 | typedef struct SnippetIter SnippetIter; |
| 107511 | typedef struct SnippetPhrase SnippetPhrase; |
| 107512 | typedef struct SnippetFragment SnippetFragment; |
| 107513 | |
| 107514 | struct SnippetIter { |
| 107515 | Fts3Cursor *pCsr; /* Cursor snippet is being generated from */ |
| 107516 | int iCol; /* Extract snippet from this column */ |
| 107517 | int nSnippet; /* Requested snippet length (in tokens) */ |
| 107518 | int nPhrase; /* Number of phrases in query */ |
| 107519 | SnippetPhrase *aPhrase; /* Array of size nPhrase */ |
| 107520 | int iCurrent; /* First token of current snippet */ |
| 107521 | }; |
| 107522 | |
| 107523 | struct SnippetPhrase { |
| 107524 | int nToken; /* Number of tokens in phrase */ |
| 107525 | char *pList; /* Pointer to start of phrase position list */ |
| 107526 | int iHead; /* Next value in position list */ |
| 107527 | char *pHead; /* Position list data following iHead */ |
| 107528 | int iTail; /* Next value in trailing position list */ |
| 107529 | char *pTail; /* Position list data following iTail */ |
| 107530 | }; |
| 107531 | |
| 107532 | struct SnippetFragment { |
| 107533 | int iCol; /* Column snippet is extracted from */ |
| 107534 | int iPos; /* Index of first token in snippet */ |
| 107535 | u64 covered; /* Mask of query phrases covered */ |
| 107536 | u64 hlmask; /* Mask of snippet terms to highlight */ |
| 107537 | }; |
| 107538 | |
| 107539 | /* |
| 107540 | ** This type is used as an fts3ExprIterate() context object while |
| 107541 | ** accumulating the data returned by the matchinfo() function. |
| 107542 | */ |
| 107543 | typedef struct MatchInfo MatchInfo; |
| 107544 | struct MatchInfo { |
| 107545 | Fts3Cursor *pCursor; /* FTS3 Cursor */ |
| 107546 | int nCol; /* Number of columns in table */ |
| 107547 | u32 *aMatchinfo; /* Pre-allocated buffer */ |
| 107548 | }; |
| 107549 | |
| 107550 | |
| 107551 | |
| 107552 | /* |
| 107553 | ** The snippet() and offsets() functions both return text values. An instance |
| 107554 | ** of the following structure is used to accumulate those values while the |
| 107555 | ** functions are running. See fts3StringAppend() for details. |
| 107556 | */ |
| 107557 | typedef struct StrBuffer StrBuffer; |
| 107558 | struct StrBuffer { |
| 107559 | char *z; /* Pointer to buffer containing string */ |
| 107560 | int n; /* Length of z in bytes (excl. nul-term) */ |
| 107561 | int nAlloc; /* Allocated size of buffer z in bytes */ |
| 107562 | }; |
| 107563 | |
| 107564 | |
| 107565 | /* |
| 107566 | ** This function is used to help iterate through a position-list. A position |
| 107567 | ** list is a list of unique integers, sorted from smallest to largest. Each |
| 107568 | ** element of the list is represented by an FTS3 varint that takes the value |
| 107569 | ** of the difference between the current element and the previous one plus |
| 107570 | ** two. For example, to store the position-list: |
| 107571 | ** |
| 107572 | ** 4 9 113 |
| 107573 | ** |
| 107574 | ** the three varints: |
| 107575 | ** |
| 107576 | ** 6 7 106 |
| 107577 | ** |
| 107578 | ** are encoded. |
| 107579 | ** |
| 107580 | ** When this function is called, *pp points to the start of an element of |
| 107581 | ** the list. *piPos contains the value of the previous entry in the list. |
| 107582 | ** After it returns, *piPos contains the value of the next element of the |
| 107583 | ** list and *pp is advanced to the following varint. |
| 107584 | */ |
| 107585 | static void fts3GetDeltaPosition(char **pp, int *piPos){ |
| 107586 | int iVal; |
| 107587 | *pp += sqlite3Fts3GetVarint32(*pp, &iVal); |
| 107588 | *piPos += (iVal-2); |
| 107589 | } |
| 107590 | |
| 107591 | /* |
| 107592 | ** Helper function for fts3ExprIterate() (see below). |
| 107593 | */ |
| 107594 | static int fts3ExprIterate2( |
| 107595 | Fts3Expr *pExpr, /* Expression to iterate phrases of */ |
| 107596 | int *piPhrase, /* Pointer to phrase counter */ |
| 107597 | int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ |
| 107598 | void *pCtx /* Second argument to pass to callback */ |
| 107599 | ){ |
| 107600 | int rc; /* Return code */ |
| 107601 | int eType = pExpr->eType; /* Type of expression node pExpr */ |
| 107602 | |
| 107603 | if( eType!=FTSQUERY_PHRASE ){ |
| 107604 | assert( pExpr->pLeft && pExpr->pRight ); |
| 107605 | rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx); |
| 107606 | if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){ |
| 107607 | rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx); |
| 107608 | } |
| 107609 | }else{ |
| 107610 | rc = x(pExpr, *piPhrase, pCtx); |
| 107611 | (*piPhrase)++; |
| 107612 | } |
| 107613 | return rc; |
| 107614 | } |
| 107615 | |
| 107616 | /* |
| 107617 | ** Iterate through all phrase nodes in an FTS3 query, except those that |
| 107618 | ** are part of a sub-tree that is the right-hand-side of a NOT operator. |
| 107619 | ** For each phrase node found, the supplied callback function is invoked. |
| @@ -106625,289 +107623,391 @@ | |
| 107623 | ** Otherwise, SQLITE_OK is returned after a callback has been made for |
| 107624 | ** all eligible phrase nodes. |
| 107625 | */ |
| 107626 | static int fts3ExprIterate( |
| 107627 | Fts3Expr *pExpr, /* Expression to iterate phrases of */ |
| 107628 | int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ |
| 107629 | void *pCtx /* Second argument to pass to callback */ |
| 107630 | ){ |
| 107631 | int iPhrase = 0; /* Variable used as the phrase counter */ |
| 107632 | return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); |
| 107633 | } |
| 107634 | |
| 107635 | /* |
| 107636 | ** The argument to this function is always a phrase node. Its doclist |
| 107637 | ** (Fts3Expr.aDoclist[]) and the doclists associated with all phrase nodes |
| 107638 | ** to the left of this one in the query tree have already been loaded. |
| 107639 | ** |
| 107640 | ** If this phrase node is part of a series of phrase nodes joined by |
| 107641 | ** NEAR operators (and is not the left-most of said series), then elements are |
| 107642 | ** removed from the phrases doclist consistent with the NEAR restriction. If |
| 107643 | ** required, elements may be removed from the doclists of phrases to the |
| 107644 | ** left of this one that are part of the same series of NEAR operator |
| 107645 | ** connected phrases. |
| 107646 | ** |
| 107647 | ** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK. |
| 107648 | */ |
| 107649 | static int fts3ExprNearTrim(Fts3Expr *pExpr){ |
| 107650 | int rc = SQLITE_OK; |
| 107651 | Fts3Expr *pParent = pExpr->pParent; |
| 107652 | |
| 107653 | assert( pExpr->eType==FTSQUERY_PHRASE ); |
| 107654 | while( rc==SQLITE_OK |
| 107655 | && pParent |
| 107656 | && pParent->eType==FTSQUERY_NEAR |
| 107657 | && pParent->pRight==pExpr |
| 107658 | ){ |
| 107659 | /* This expression (pExpr) is the right-hand-side of a NEAR operator. |
| 107660 | ** Find the expression to the left of the same operator. |
| 107661 | */ |
| 107662 | int nNear = pParent->nNear; |
| 107663 | Fts3Expr *pLeft = pParent->pLeft; |
| 107664 | |
| 107665 | if( pLeft->eType!=FTSQUERY_PHRASE ){ |
| 107666 | assert( pLeft->eType==FTSQUERY_NEAR ); |
| 107667 | assert( pLeft->pRight->eType==FTSQUERY_PHRASE ); |
| 107668 | pLeft = pLeft->pRight; |
| 107669 | } |
| 107670 | |
| 107671 | rc = sqlite3Fts3ExprNearTrim(pLeft, pExpr, nNear); |
| 107672 | |
| 107673 | pExpr = pLeft; |
| 107674 | pParent = pExpr->pParent; |
| 107675 | } |
| 107676 | |
| 107677 | return rc; |
| 107678 | } |
| 107679 | |
| 107680 | /* |
| 107681 | ** This is an fts3ExprIterate() callback used while loading the doclists |
| 107682 | ** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also |
| 107683 | ** fts3ExprLoadDoclists(). |
| 107684 | */ |
| 107685 | static int fts3ExprLoadDoclistsCb1(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 107686 | int rc = SQLITE_OK; |
| 107687 | LoadDoclistCtx *p = (LoadDoclistCtx *)ctx; |
| 107688 | |
| 107689 | UNUSED_PARAMETER(iPhrase); |
| 107690 | |
| 107691 | p->nPhrase++; |
| 107692 | p->nToken += pExpr->pPhrase->nToken; |
| 107693 | |
| 107694 | if( pExpr->isLoaded==0 ){ |
| 107695 | rc = sqlite3Fts3ExprLoadDoclist(p->pTab, pExpr); |
| 107696 | pExpr->isLoaded = 1; |
| 107697 | if( rc==SQLITE_OK ){ |
| 107698 | rc = fts3ExprNearTrim(pExpr); |
| 107699 | } |
| 107700 | } |
| 107701 | |
| 107702 | return rc; |
| 107703 | } |
| 107704 | |
| 107705 | /* |
| 107706 | ** This is an fts3ExprIterate() callback used while loading the doclists |
| 107707 | ** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also |
| 107708 | ** fts3ExprLoadDoclists(). |
| 107709 | */ |
| 107710 | static int fts3ExprLoadDoclistsCb2(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 107711 | UNUSED_PARAMETER(iPhrase); |
| 107712 | UNUSED_PARAMETER(ctx); |
| 107713 | if( pExpr->aDoclist ){ |
| 107714 | pExpr->pCurrent = pExpr->aDoclist; |
| 107715 | pExpr->iCurrent = 0; |
| 107716 | pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent, &pExpr->iCurrent); |
| 107717 | } |
| 107718 | return SQLITE_OK; |
| 107719 | } |
| 107720 | |
| 107721 | /* |
| 107722 | ** Load the doclists for each phrase in the query associated with FTS3 cursor |
| 107723 | ** pCsr. |
| 107724 | ** |
| 107725 | ** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable |
| 107726 | ** phrases in the expression (all phrases except those directly or |
| 107727 | ** indirectly descended from the right-hand-side of a NOT operator). If |
| 107728 | ** pnToken is not NULL, then it is set to the number of tokens in all |
| 107729 | ** matchable phrases of the expression. |
| 107730 | */ |
| 107731 | static int fts3ExprLoadDoclists( |
| 107732 | Fts3Cursor *pCsr, /* Fts3 cursor for current query */ |
| 107733 | int *pnPhrase, /* OUT: Number of phrases in query */ |
| 107734 | int *pnToken /* OUT: Number of tokens in query */ |
| 107735 | ){ |
| 107736 | int rc; /* Return Code */ |
| 107737 | LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */ |
| 107738 | sCtx.pTab = (Fts3Table *)pCsr->base.pVtab; |
| 107739 | rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb1, (void *)&sCtx); |
| 107740 | if( rc==SQLITE_OK ){ |
| 107741 | (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb2, 0); |
| 107742 | } |
| 107743 | if( pnPhrase ) *pnPhrase = sCtx.nPhrase; |
| 107744 | if( pnToken ) *pnToken = sCtx.nToken; |
| 107745 | return rc; |
| 107746 | } |
| 107747 | |
| 107748 | /* |
| 107749 | ** Advance the position list iterator specified by the first two |
| 107750 | ** arguments so that it points to the first element with a value greater |
| 107751 | ** than or equal to parameter iNext. |
| 107752 | */ |
| 107753 | static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){ |
| 107754 | char *pIter = *ppIter; |
| 107755 | if( pIter ){ |
| 107756 | int iIter = *piIter; |
| 107757 | |
| 107758 | while( iIter<iNext ){ |
| 107759 | if( 0==(*pIter & 0xFE) ){ |
| 107760 | iIter = -1; |
| 107761 | pIter = 0; |
| 107762 | break; |
| 107763 | } |
| 107764 | fts3GetDeltaPosition(&pIter, &iIter); |
| 107765 | } |
| 107766 | |
| 107767 | *piIter = iIter; |
| 107768 | *ppIter = pIter; |
| 107769 | } |
| 107770 | } |
| 107771 | |
| 107772 | /* |
| 107773 | ** Advance the snippet iterator to the next candidate snippet. |
| 107774 | */ |
| 107775 | static int fts3SnippetNextCandidate(SnippetIter *pIter){ |
| 107776 | int i; /* Loop counter */ |
| 107777 | |
| 107778 | if( pIter->iCurrent<0 ){ |
| 107779 | /* The SnippetIter object has just been initialized. The first snippet |
| 107780 | ** candidate always starts at offset 0 (even if this candidate has a |
| 107781 | ** score of 0.0). |
| 107782 | */ |
| 107783 | pIter->iCurrent = 0; |
| 107784 | |
| 107785 | /* Advance the 'head' iterator of each phrase to the first offset that |
| 107786 | ** is greater than or equal to (iNext+nSnippet). |
| 107787 | */ |
| 107788 | for(i=0; i<pIter->nPhrase; i++){ |
| 107789 | SnippetPhrase *pPhrase = &pIter->aPhrase[i]; |
| 107790 | fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet); |
| 107791 | } |
| 107792 | }else{ |
| 107793 | int iStart; |
| 107794 | int iEnd = 0x7FFFFFFF; |
| 107795 | |
| 107796 | for(i=0; i<pIter->nPhrase; i++){ |
| 107797 | SnippetPhrase *pPhrase = &pIter->aPhrase[i]; |
| 107798 | if( pPhrase->pHead && pPhrase->iHead<iEnd ){ |
| 107799 | iEnd = pPhrase->iHead; |
| 107800 | } |
| 107801 | } |
| 107802 | if( iEnd==0x7FFFFFFF ){ |
| 107803 | return 1; |
| 107804 | } |
| 107805 | |
| 107806 | pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1; |
| 107807 | for(i=0; i<pIter->nPhrase; i++){ |
| 107808 | SnippetPhrase *pPhrase = &pIter->aPhrase[i]; |
| 107809 | fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1); |
| 107810 | fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart); |
| 107811 | } |
| 107812 | } |
| 107813 | |
| 107814 | return 0; |
| 107815 | } |
| 107816 | |
| 107817 | /* |
| 107818 | ** Retrieve information about the current candidate snippet of snippet |
| 107819 | ** iterator pIter. |
| 107820 | */ |
| 107821 | static void fts3SnippetDetails( |
| 107822 | SnippetIter *pIter, /* Snippet iterator */ |
| 107823 | u64 mCovered, /* Bitmask of phrases already covered */ |
| 107824 | int *piToken, /* OUT: First token of proposed snippet */ |
| 107825 | int *piScore, /* OUT: "Score" for this snippet */ |
| 107826 | u64 *pmCover, /* OUT: Bitmask of phrases covered */ |
| 107827 | u64 *pmHighlight /* OUT: Bitmask of terms to highlight */ |
| 107828 | ){ |
| 107829 | int iStart = pIter->iCurrent; /* First token of snippet */ |
| 107830 | int iScore = 0; /* Score of this snippet */ |
| 107831 | int i; /* Loop counter */ |
| 107832 | u64 mCover = 0; /* Mask of phrases covered by this snippet */ |
| 107833 | u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */ |
| 107834 | |
| 107835 | for(i=0; i<pIter->nPhrase; i++){ |
| 107836 | SnippetPhrase *pPhrase = &pIter->aPhrase[i]; |
| 107837 | if( pPhrase->pTail ){ |
| 107838 | char *pCsr = pPhrase->pTail; |
| 107839 | int iCsr = pPhrase->iTail; |
| 107840 | |
| 107841 | while( iCsr<(iStart+pIter->nSnippet) ){ |
| 107842 | int j; |
| 107843 | u64 mPhrase = (u64)1 << i; |
| 107844 | u64 mPos = (u64)1 << (iCsr - iStart); |
| 107845 | assert( iCsr>=iStart ); |
| 107846 | if( (mCover|mCovered)&mPhrase ){ |
| 107847 | iScore++; |
| 107848 | }else{ |
| 107849 | iScore += 1000; |
| 107850 | } |
| 107851 | mCover |= mPhrase; |
| 107852 | |
| 107853 | for(j=0; j<pPhrase->nToken; j++){ |
| 107854 | mHighlight |= (mPos>>j); |
| 107855 | } |
| 107856 | |
| 107857 | if( 0==(*pCsr & 0x0FE) ) break; |
| 107858 | fts3GetDeltaPosition(&pCsr, &iCsr); |
| 107859 | } |
| 107860 | } |
| 107861 | } |
| 107862 | |
| 107863 | /* Set the output variables before returning. */ |
| 107864 | *piToken = iStart; |
| 107865 | *piScore = iScore; |
| 107866 | *pmCover = mCover; |
| 107867 | *pmHighlight = mHighlight; |
| 107868 | } |
| 107869 | |
| 107870 | /* |
| 107871 | ** This function is an fts3ExprIterate() callback used by fts3BestSnippet(). |
| 107872 | ** Each invocation populates an element of the SnippetIter.aPhrase[] array. |
| 107873 | */ |
| 107874 | static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 107875 | SnippetIter *p = (SnippetIter *)ctx; |
| 107876 | SnippetPhrase *pPhrase = &p->aPhrase[iPhrase]; |
| 107877 | char *pCsr; |
| 107878 | |
| 107879 | pPhrase->nToken = pExpr->pPhrase->nToken; |
| 107880 | |
| 107881 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCsr->iPrevId, p->iCol); |
| 107882 | if( pCsr ){ |
| 107883 | int iFirst = 0; |
| 107884 | pPhrase->pList = pCsr; |
| 107885 | fts3GetDeltaPosition(&pCsr, &iFirst); |
| 107886 | pPhrase->pHead = pCsr; |
| 107887 | pPhrase->pTail = pCsr; |
| 107888 | pPhrase->iHead = iFirst; |
| 107889 | pPhrase->iTail = iFirst; |
| 107890 | }else{ |
| 107891 | assert( pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 ); |
| 107892 | } |
| 107893 | |
| 107894 | return SQLITE_OK; |
| 107895 | } |
| 107896 | |
| 107897 | /* |
| 107898 | ** Select the fragment of text consisting of nFragment contiguous tokens |
| 107899 | ** from column iCol that represent the "best" snippet. The best snippet |
| 107900 | ** is the snippet with the highest score, where scores are calculated |
| 107901 | ** by adding: |
| 107902 | ** |
| 107903 | ** (a) +1 point for each occurence of a matchable phrase in the snippet. |
| 107904 | ** |
| 107905 | ** (b) +1000 points for the first occurence of each matchable phrase in |
| 107906 | ** the snippet for which the corresponding mCovered bit is not set. |
| 107907 | ** |
| 107908 | ** The selected snippet parameters are stored in structure *pFragment before |
| 107909 | ** returning. The score of the selected snippet is stored in *piScore |
| 107910 | ** before returning. |
| 107911 | */ |
| 107912 | static int fts3BestSnippet( |
| 107913 | int nSnippet, /* Desired snippet length */ |
| 107914 | Fts3Cursor *pCsr, /* Cursor to create snippet for */ |
| 107915 | int iCol, /* Index of column to create snippet from */ |
| 107916 | u64 mCovered, /* Mask of phrases already covered */ |
| 107917 | u64 *pmSeen, /* IN/OUT: Mask of phrases seen */ |
| 107918 | SnippetFragment *pFragment, /* OUT: Best snippet found */ |
| 107919 | int *piScore /* OUT: Score of snippet pFragment */ |
| 107920 | ){ |
| 107921 | int rc; /* Return Code */ |
| 107922 | int nList; /* Number of phrases in expression */ |
| 107923 | SnippetIter sIter; /* Iterates through snippet candidates */ |
| 107924 | int nByte; /* Number of bytes of space to allocate */ |
| 107925 | int iBestScore = -1; /* Best snippet score found so far */ |
| 107926 | int i; /* Loop counter */ |
| 107927 | |
| 107928 | memset(&sIter, 0, sizeof(sIter)); |
| 107929 | |
| 107930 | /* Iterate through the phrases in the expression to count them. The same |
| 107931 | ** callback makes sure the doclists are loaded for each phrase. |
| 107932 | */ |
| 107933 | rc = fts3ExprLoadDoclists(pCsr, &nList, 0); |
| 107934 | if( rc!=SQLITE_OK ){ |
| 107935 | return rc; |
| 107936 | } |
| 107937 | |
| 107938 | /* Now that it is known how many phrases there are, allocate and zero |
| 107939 | ** the required space using malloc(). |
| 107940 | */ |
| 107941 | nByte = sizeof(SnippetPhrase) * nList; |
| 107942 | sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte); |
| 107943 | if( !sIter.aPhrase ){ |
| 107944 | return SQLITE_NOMEM; |
| 107945 | } |
| 107946 | memset(sIter.aPhrase, 0, nByte); |
| 107947 | |
| 107948 | /* Initialize the contents of the SnippetIter object. Then iterate through |
| 107949 | ** the set of phrases in the expression to populate the aPhrase[] array. |
| 107950 | */ |
| 107951 | sIter.pCsr = pCsr; |
| 107952 | sIter.iCol = iCol; |
| 107953 | sIter.nSnippet = nSnippet; |
| 107954 | sIter.nPhrase = nList; |
| 107955 | sIter.iCurrent = -1; |
| 107956 | (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter); |
| 107957 | |
| 107958 | /* Set the *pmSeen output variable. */ |
| 107959 | for(i=0; i<nList; i++){ |
| 107960 | if( sIter.aPhrase[i].pHead ){ |
| 107961 | *pmSeen |= (u64)1 << i; |
| 107962 | } |
| 107963 | } |
| 107964 | |
| 107965 | /* Loop through all candidate snippets. Store the best snippet in |
| 107966 | ** *pFragment. Store its associated 'score' in iBestScore. |
| 107967 | */ |
| 107968 | pFragment->iCol = iCol; |
| 107969 | while( !fts3SnippetNextCandidate(&sIter) ){ |
| 107970 | int iPos; |
| 107971 | int iScore; |
| 107972 | u64 mCover; |
| 107973 | u64 mHighlight; |
| 107974 | fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight); |
| 107975 | assert( iScore>=0 ); |
| 107976 | if( iScore>iBestScore ){ |
| 107977 | pFragment->iPos = iPos; |
| 107978 | pFragment->hlmask = mHighlight; |
| 107979 | pFragment->covered = mCover; |
| 107980 | iBestScore = iScore; |
| 107981 | } |
| 107982 | } |
| 107983 | |
| 107984 | sqlite3_free(sIter.aPhrase); |
| 107985 | *piScore = iBestScore; |
| 107986 | return SQLITE_OK; |
| 107987 | } |
| 107988 | |
| 107989 | |
| 107990 | /* |
| 107991 | ** Append a string to the string-buffer passed as the first argument. |
| 107992 | ** |
| 107993 | ** If nAppend is negative, then the length of the string zAppend is |
| 107994 | ** determined using strlen(). |
| 107995 | */ |
| 107996 | static int fts3StringAppend( |
| 107997 | StrBuffer *pStr, /* Buffer to append to */ |
| 107998 | const char *zAppend, /* Pointer to data to append to buffer */ |
| 107999 | int nAppend /* Size of zAppend in bytes (or -1) */ |
| 108000 | ){ |
| 108001 | if( nAppend<0 ){ |
| 108002 | nAppend = (int)strlen(zAppend); |
| 108003 | } |
| 108004 | |
| 108005 | /* If there is insufficient space allocated at StrBuffer.z, use realloc() |
| 108006 | ** to grow the buffer until so that it is big enough to accomadate the |
| 108007 | ** appended data. |
| 108008 | */ |
| 108009 | if( pStr->n+nAppend+1>=pStr->nAlloc ){ |
| 108010 | int nAlloc = pStr->nAlloc+nAppend+100; |
| 108011 | char *zNew = sqlite3_realloc(pStr->z, nAlloc); |
| 108012 | if( !zNew ){ |
| 108013 | return SQLITE_NOMEM; |
| @@ -106914,137 +108014,213 @@ | |
| 108014 | } |
| 108015 | pStr->z = zNew; |
| 108016 | pStr->nAlloc = nAlloc; |
| 108017 | } |
| 108018 | |
| 108019 | /* Append the data to the string buffer. */ |
| 108020 | memcpy(&pStr->z[pStr->n], zAppend, nAppend); |
| 108021 | pStr->n += nAppend; |
| 108022 | pStr->z[pStr->n] = '\0'; |
| 108023 | |
| 108024 | return SQLITE_OK; |
| 108025 | } |
| 108026 | |
| 108027 | /* |
| 108028 | ** The fts3BestSnippet() function often selects snippets that end with a |
| 108029 | ** query term. That is, the final term of the snippet is always a term |
| 108030 | ** that requires highlighting. For example, if 'X' is a highlighted term |
| 108031 | ** and '.' is a non-highlighted term, BestSnippet() may select: |
| 108032 | ** |
| 108033 | ** ........X.....X |
| 108034 | ** |
| 108035 | ** This function "shifts" the beginning of the snippet forward in the |
| 108036 | ** document so that there are approximately the same number of |
| 108037 | ** non-highlighted terms to the right of the final highlighted term as there |
| 108038 | ** are to the left of the first highlighted term. For example, to this: |
| 108039 | ** |
| 108040 | ** ....X.....X.... |
| 108041 | ** |
| 108042 | ** This is done as part of extracting the snippet text, not when selecting |
| 108043 | ** the snippet. Snippet selection is done based on doclists only, so there |
| 108044 | ** is no way for fts3BestSnippet() to know whether or not the document |
| 108045 | ** actually contains terms that follow the final highlighted term. |
| 108046 | */ |
| 108047 | int fts3SnippetShift( |
| 108048 | Fts3Table *pTab, /* FTS3 table snippet comes from */ |
| 108049 | int nSnippet, /* Number of tokens desired for snippet */ |
| 108050 | const char *zDoc, /* Document text to extract snippet from */ |
| 108051 | int nDoc, /* Size of buffer zDoc in bytes */ |
| 108052 | int *piPos, /* IN/OUT: First token of snippet */ |
| 108053 | u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */ |
| 108054 | ){ |
| 108055 | u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */ |
| 108056 | |
| 108057 | if( hlmask ){ |
| 108058 | int nLeft; /* Tokens to the left of first highlight */ |
| 108059 | int nRight; /* Tokens to the right of last highlight */ |
| 108060 | int nDesired; /* Ideal number of tokens to shift forward */ |
| 108061 | |
| 108062 | for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++); |
| 108063 | for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++); |
| 108064 | nDesired = (nLeft-nRight)/2; |
| 108065 | |
| 108066 | /* Ideally, the start of the snippet should be pushed forward in the |
| 108067 | ** document nDesired tokens. This block checks if there are actually |
| 108068 | ** nDesired tokens to the right of the snippet. If so, *piPos and |
| 108069 | ** *pHlMask are updated to shift the snippet nDesired tokens to the |
| 108070 | ** right. Otherwise, the snippet is shifted by the number of tokens |
| 108071 | ** available. |
| 108072 | */ |
| 108073 | if( nDesired>0 ){ |
| 108074 | int nShift; /* Number of tokens to shift snippet by */ |
| 108075 | int iCurrent = 0; /* Token counter */ |
| 108076 | int rc; /* Return Code */ |
| 108077 | sqlite3_tokenizer_module *pMod; |
| 108078 | sqlite3_tokenizer_cursor *pC; |
| 108079 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 108080 | |
| 108081 | /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) |
| 108082 | ** or more tokens in zDoc/nDoc. |
| 108083 | */ |
| 108084 | rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 108085 | if( rc!=SQLITE_OK ){ |
| 108086 | return rc; |
| 108087 | } |
| 108088 | pC->pTokenizer = pTab->pTokenizer; |
| 108089 | while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ |
| 108090 | const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3; |
| 108091 | rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); |
| 108092 | } |
| 108093 | pMod->xClose(pC); |
| 108094 | if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; } |
| 108095 | |
| 108096 | nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet; |
| 108097 | assert( nShift<=nDesired ); |
| 108098 | if( nShift>0 ){ |
| 108099 | *piPos += nShift; |
| 108100 | *pHlmask = hlmask >> nShift; |
| 108101 | } |
| 108102 | } |
| 108103 | } |
| 108104 | return SQLITE_OK; |
| 108105 | } |
| 108106 | |
| 108107 | /* |
| 108108 | ** Extract the snippet text for fragment pFragment from cursor pCsr and |
| 108109 | ** append it to string buffer pOut. |
| 108110 | */ |
| 108111 | static int fts3SnippetText( |
| 108112 | Fts3Cursor *pCsr, /* FTS3 Cursor */ |
| 108113 | SnippetFragment *pFragment, /* Snippet to extract */ |
| 108114 | int iFragment, /* Fragment number */ |
| 108115 | int isLast, /* True for final fragment in snippet */ |
| 108116 | int nSnippet, /* Number of tokens in extracted snippet */ |
| 108117 | const char *zOpen, /* String inserted before highlighted term */ |
| 108118 | const char *zClose, /* String inserted after highlighted term */ |
| 108119 | const char *zEllipsis, /* String inserted between snippets */ |
| 108120 | StrBuffer *pOut /* Write output here */ |
| 108121 | ){ |
| 108122 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 108123 | int rc; /* Return code */ |
| 108124 | const char *zDoc; /* Document text to extract snippet from */ |
| 108125 | int nDoc; /* Size of zDoc in bytes */ |
| 108126 | int iCurrent = 0; /* Current token number of document */ |
| 108127 | int iEnd = 0; /* Byte offset of end of current token */ |
| 108128 | int isShiftDone = 0; /* True after snippet is shifted */ |
| 108129 | int iPos = pFragment->iPos; /* First token of snippet */ |
| 108130 | u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ |
| 108131 | int iCol = pFragment->iCol+1; /* Query column to extract text from */ |
| 108132 | sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ |
| 108133 | sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ |
| 108134 | const char *ZDUMMY; /* Dummy argument used with tokenizer */ |
| 108135 | int DUMMY1; /* Dummy argument used with tokenizer */ |
| 108136 | |
| 108137 | zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); |
| 108138 | if( zDoc==0 ){ |
| 108139 | if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ |
| 108140 | return SQLITE_NOMEM; |
| 108141 | } |
| 108142 | return SQLITE_OK; |
| 108143 | } |
| 108144 | nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); |
| 108145 | |
| 108146 | /* Open a token cursor on the document. */ |
| 108147 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 108148 | rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 108149 | if( rc!=SQLITE_OK ){ |
| 108150 | return rc; |
| 108151 | } |
| 108152 | pC->pTokenizer = pTab->pTokenizer; |
| 108153 | |
| 108154 | while( rc==SQLITE_OK ){ |
| 108155 | int iBegin; /* Offset in zDoc of start of token */ |
| 108156 | int iFin; /* Offset in zDoc of end of token */ |
| 108157 | int isHighlight; /* True for highlighted terms */ |
| 108158 | |
| 108159 | rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent); |
| 108160 | if( rc!=SQLITE_OK ){ |
| 108161 | if( rc==SQLITE_DONE ){ |
| 108162 | /* Special case - the last token of the snippet is also the last token |
| 108163 | ** of the column. Append any punctuation that occurred between the end |
| 108164 | ** of the previous token and the end of the document to the output. |
| 108165 | ** Then break out of the loop. */ |
| 108166 | rc = fts3StringAppend(pOut, &zDoc[iEnd], -1); |
| 108167 | } |
| 108168 | break; |
| 108169 | } |
| 108170 | if( iCurrent<iPos ){ continue; } |
| 108171 | |
| 108172 | if( !isShiftDone ){ |
| 108173 | int n = nDoc - iBegin; |
| 108174 | rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask); |
| 108175 | isShiftDone = 1; |
| 108176 | |
| 108177 | /* Now that the shift has been done, check if the initial "..." are |
| 108178 | ** required. They are required if (a) this is not the first fragment, |
| 108179 | ** or (b) this fragment does not begin at position 0 of its column. |
| 108180 | */ |
| 108181 | if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){ |
| 108182 | rc = fts3StringAppend(pOut, zEllipsis, -1); |
| 108183 | } |
| 108184 | if( rc!=SQLITE_OK || iCurrent<iPos ) continue; |
| 108185 | } |
| 108186 | |
| 108187 | if( iCurrent>=(iPos+nSnippet) ){ |
| 108188 | if( isLast ){ |
| 108189 | rc = fts3StringAppend(pOut, zEllipsis, -1); |
| 108190 | } |
| 108191 | break; |
| 108192 | } |
| 108193 | |
| 108194 | /* Set isHighlight to true if this term should be highlighted. */ |
| 108195 | isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0; |
| 108196 | |
| 108197 | if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd); |
| 108198 | if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1); |
| 108199 | if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin); |
| 108200 | if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1); |
| 108201 | |
| 108202 | iEnd = iFin; |
| 108203 | } |
| 108204 | |
| 108205 | pMod->xClose(pC); |
| 108206 | return rc; |
| 108207 | } |
| 108208 | |
| 108209 | |
| 108210 | /* |
| 108211 | ** This function is used to count the entries in a column-list (a |
| 108212 | ** delta-encoded list of term offsets within a single column of a single |
| 108213 | ** row). When this function is called, *ppCollist should point to the |
| 108214 | ** beginning of the first varint in the column-list (the varint that |
| 108215 | ** contains the position of the first matching term in the column data). |
| 108216 | ** Before returning, *ppCollist is set to point to the first byte after |
| 108217 | ** the last varint in the column-list (either the 0x00 signifying the end |
| 108218 | ** of the position-list, or the 0x01 that precedes the column number of |
| 108219 | ** the next column in the position-list). |
| 108220 | ** |
| 108221 | ** The number of elements in the column-list is returned. |
| 108222 | */ |
| 108223 | static int fts3ColumnlistCount(char **ppCollist){ |
| 108224 | char *pEnd = *ppCollist; |
| 108225 | char c = 0; |
| 108226 | int nEntry = 0; |
| @@ -107057,158 +108233,445 @@ | |
| 108233 | |
| 108234 | *ppCollist = pEnd; |
| 108235 | return nEntry; |
| 108236 | } |
| 108237 | |
| 108238 | static void fts3LoadColumnlistCounts(char **pp, u32 *aOut, int isGlobal){ |
| 108239 | char *pCsr = *pp; |
| 108240 | while( *pCsr ){ |
| 108241 | int nHit; |
| 108242 | sqlite3_int64 iCol = 0; |
| 108243 | if( *pCsr==0x01 ){ |
| 108244 | pCsr++; |
| 108245 | pCsr += sqlite3Fts3GetVarint(pCsr, &iCol); |
| 108246 | } |
| 108247 | nHit = fts3ColumnlistCount(&pCsr); |
| 108248 | assert( nHit>0 ); |
| 108249 | if( isGlobal ){ |
| 108250 | aOut[iCol*3+1]++; |
| 108251 | } |
| 108252 | aOut[iCol*3] += nHit; |
| 108253 | } |
| 108254 | pCsr++; |
| 108255 | *pp = pCsr; |
| 108256 | } |
| 108257 | |
| 108258 | /* |
| 108259 | ** fts3ExprIterate() callback used to collect the "global" matchinfo stats |
| 108260 | ** for a single query. The "global" stats are those elements of the matchinfo |
| 108261 | ** array that are constant for all rows returned by the current query. |
| 108262 | */ |
| 108263 | static int fts3ExprGlobalMatchinfoCb( |
| 108264 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 108265 | int iPhrase, /* Phrase number (numbered from zero) */ |
| 108266 | void *pCtx /* Pointer to MatchInfo structure */ |
| 108267 | ){ |
| 108268 | MatchInfo *p = (MatchInfo *)pCtx; |
| 108269 | char *pCsr; |
| 108270 | char *pEnd; |
| 108271 | const int iStart = 2 + (iPhrase * p->nCol * 3) + 1; |
| 108272 | |
| 108273 | assert( pExpr->isLoaded ); |
| 108274 | |
| 108275 | /* Fill in the global hit count matrix row for this phrase. */ |
| 108276 | pCsr = pExpr->aDoclist; |
| 108277 | pEnd = &pExpr->aDoclist[pExpr->nDoclist]; |
| 108278 | while( pCsr<pEnd ){ |
| 108279 | while( *pCsr++ & 0x80 ); /* Skip past docid. */ |
| 108280 | fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 1); |
| 108281 | } |
| 108282 | |
| 108283 | return SQLITE_OK; |
| 108284 | } |
| 108285 | |
| 108286 | /* |
| 108287 | ** fts3ExprIterate() callback used to collect the "local" matchinfo stats |
| 108288 | ** for a single query. The "local" stats are those elements of the matchinfo |
| 108289 | ** array that are different for each row returned by the query. |
| 108290 | */ |
| 108291 | static int fts3ExprLocalMatchinfoCb( |
| 108292 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 108293 | int iPhrase, /* Phrase number */ |
| 108294 | void *pCtx /* Pointer to MatchInfo structure */ |
| 108295 | ){ |
| 108296 | MatchInfo *p = (MatchInfo *)pCtx; |
| 108297 | |
| 108298 | if( pExpr->aDoclist ){ |
| 108299 | char *pCsr; |
| 108300 | int iStart = 2 + (iPhrase * p->nCol * 3); |
| 108301 | int i; |
| 108302 | |
| 108303 | for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0; |
| 108304 | |
| 108305 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1); |
| 108306 | if( pCsr ){ |
| 108307 | fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0); |
| 108308 | } |
| 108309 | } |
| 108310 | |
| 108311 | return SQLITE_OK; |
| 108312 | } |
| 108313 | |
| 108314 | /* |
| 108315 | ** Populate pCsr->aMatchinfo[] with data for the current row. The |
| 108316 | ** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). |
| 108317 | */ |
| 108318 | static int fts3GetMatchinfo(Fts3Cursor *pCsr){ |
| 108319 | MatchInfo sInfo; |
| 108320 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 108321 | int rc = SQLITE_OK; |
| 108322 | |
| 108323 | sInfo.pCursor = pCsr; |
| 108324 | sInfo.nCol = pTab->nColumn; |
| 108325 | |
| 108326 | if( pCsr->aMatchinfo==0 ){ |
| 108327 | /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the |
| 108328 | ** matchinfo function has been called for this query. In this case |
| 108329 | ** allocate the array used to accumulate the matchinfo data and |
| 108330 | ** initialize those elements that are constant for every row. |
| 108331 | */ |
| 108332 | int nPhrase; /* Number of phrases */ |
| 108333 | int nMatchinfo; /* Number of u32 elements in match-info */ |
| 108334 | |
| 108335 | /* Load doclists for each phrase in the query. */ |
| 108336 | rc = fts3ExprLoadDoclists(pCsr, &nPhrase, 0); |
| 108337 | if( rc!=SQLITE_OK ){ |
| 108338 | return rc; |
| 108339 | } |
| 108340 | nMatchinfo = 2 + 3*sInfo.nCol*nPhrase; |
| 108341 | if( pTab->bHasDocsize ){ |
| 108342 | nMatchinfo += 1 + 2*pTab->nColumn; |
| 108343 | } |
| 108344 | |
| 108345 | sInfo.aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo); |
| 108346 | if( !sInfo.aMatchinfo ){ |
| 108347 | return SQLITE_NOMEM; |
| 108348 | } |
| 108349 | memset(sInfo.aMatchinfo, 0, sizeof(u32)*nMatchinfo); |
| 108350 | |
| 108351 | |
| 108352 | /* First element of match-info is the number of phrases in the query */ |
| 108353 | sInfo.aMatchinfo[0] = nPhrase; |
| 108354 | sInfo.aMatchinfo[1] = sInfo.nCol; |
| 108355 | (void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo); |
| 108356 | if( pTab->bHasDocsize ){ |
| 108357 | int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; |
| 108358 | rc = sqlite3Fts3MatchinfoDocsizeGlobal(pCsr, &sInfo.aMatchinfo[ofst]); |
| 108359 | } |
| 108360 | pCsr->aMatchinfo = sInfo.aMatchinfo; |
| 108361 | pCsr->isMatchinfoNeeded = 1; |
| 108362 | } |
| 108363 | |
| 108364 | sInfo.aMatchinfo = pCsr->aMatchinfo; |
| 108365 | if( rc==SQLITE_OK && pCsr->isMatchinfoNeeded ){ |
| 108366 | (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void*)&sInfo); |
| 108367 | if( pTab->bHasDocsize ){ |
| 108368 | int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; |
| 108369 | rc = sqlite3Fts3MatchinfoDocsizeLocal(pCsr, &sInfo.aMatchinfo[ofst]); |
| 108370 | } |
| 108371 | pCsr->isMatchinfoNeeded = 0; |
| 108372 | } |
| 108373 | |
| 108374 | return SQLITE_OK; |
| 108375 | } |
| 108376 | |
| 108377 | /* |
| 108378 | ** Implementation of snippet() function. |
| 108379 | */ |
| 108380 | SQLITE_PRIVATE void sqlite3Fts3Snippet( |
| 108381 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 108382 | Fts3Cursor *pCsr, /* Cursor object */ |
| 108383 | const char *zStart, /* Snippet start text - "<b>" */ |
| 108384 | const char *zEnd, /* Snippet end text - "</b>" */ |
| 108385 | const char *zEllipsis, /* Snippet ellipsis text - "<b>...</b>" */ |
| 108386 | int iCol, /* Extract snippet from this column */ |
| 108387 | int nToken /* Approximate number of tokens in snippet */ |
| 108388 | ){ |
| 108389 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 108390 | int rc = SQLITE_OK; |
| 108391 | int i; |
| 108392 | StrBuffer res = {0, 0, 0}; |
| 108393 | |
| 108394 | /* The returned text includes up to four fragments of text extracted from |
| 108395 | ** the data in the current row. The first iteration of the for(...) loop |
| 108396 | ** below attempts to locate a single fragment of text nToken tokens in |
| 108397 | ** size that contains at least one instance of all phrases in the query |
| 108398 | ** expression that appear in the current row. If such a fragment of text |
| 108399 | ** cannot be found, the second iteration of the loop attempts to locate |
| 108400 | ** a pair of fragments, and so on. |
| 108401 | */ |
| 108402 | int nSnippet = 0; /* Number of fragments in this snippet */ |
| 108403 | SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */ |
| 108404 | int nFToken = -1; /* Number of tokens in each fragment */ |
| 108405 | |
| 108406 | if( !pCsr->pExpr ){ |
| 108407 | sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); |
| 108408 | return; |
| 108409 | } |
| 108410 | |
| 108411 | for(nSnippet=1; 1; nSnippet++){ |
| 108412 | |
| 108413 | int iSnip; /* Loop counter 0..nSnippet-1 */ |
| 108414 | u64 mCovered = 0; /* Bitmask of phrases covered by snippet */ |
| 108415 | u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */ |
| 108416 | |
| 108417 | if( nToken>=0 ){ |
| 108418 | nFToken = (nToken+nSnippet-1) / nSnippet; |
| 108419 | }else{ |
| 108420 | nFToken = -1 * nToken; |
| 108421 | } |
| 108422 | |
| 108423 | for(iSnip=0; iSnip<nSnippet; iSnip++){ |
| 108424 | int iBestScore = -1; /* Best score of columns checked so far */ |
| 108425 | int iRead; /* Used to iterate through columns */ |
| 108426 | SnippetFragment *pFragment = &aSnippet[iSnip]; |
| 108427 | |
| 108428 | memset(pFragment, 0, sizeof(*pFragment)); |
| 108429 | |
| 108430 | /* Loop through all columns of the table being considered for snippets. |
| 108431 | ** If the iCol argument to this function was negative, this means all |
| 108432 | ** columns of the FTS3 table. Otherwise, only column iCol is considered. |
| 108433 | */ |
| 108434 | for(iRead=0; iRead<pTab->nColumn; iRead++){ |
| 108435 | SnippetFragment sF; |
| 108436 | int iS; |
| 108437 | if( iCol>=0 && iRead!=iCol ) continue; |
| 108438 | |
| 108439 | /* Find the best snippet of nFToken tokens in column iRead. */ |
| 108440 | rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS); |
| 108441 | if( rc!=SQLITE_OK ){ |
| 108442 | goto snippet_out; |
| 108443 | } |
| 108444 | if( iS>iBestScore ){ |
| 108445 | *pFragment = sF; |
| 108446 | iBestScore = iS; |
| 108447 | } |
| 108448 | } |
| 108449 | |
| 108450 | mCovered |= pFragment->covered; |
| 108451 | } |
| 108452 | |
| 108453 | /* If all query phrases seen by fts3BestSnippet() are present in at least |
| 108454 | ** one of the nSnippet snippet fragments, break out of the loop. |
| 108455 | */ |
| 108456 | assert( (mCovered&mSeen)==mCovered ); |
| 108457 | if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break; |
| 108458 | } |
| 108459 | |
| 108460 | assert( nFToken>0 ); |
| 108461 | |
| 108462 | for(i=0; i<nSnippet && rc==SQLITE_OK; i++){ |
| 108463 | rc = fts3SnippetText(pCsr, &aSnippet[i], |
| 108464 | i, (i==nSnippet-1), nFToken, zStart, zEnd, zEllipsis, &res |
| 108465 | ); |
| 108466 | } |
| 108467 | |
| 108468 | snippet_out: |
| 108469 | if( rc!=SQLITE_OK ){ |
| 108470 | sqlite3_result_error_code(pCtx, rc); |
| 108471 | sqlite3_free(res.z); |
| 108472 | }else{ |
| 108473 | sqlite3_result_text(pCtx, res.z, -1, sqlite3_free); |
| 108474 | } |
| 108475 | } |
| 108476 | |
| 108477 | |
| 108478 | typedef struct TermOffset TermOffset; |
| 108479 | typedef struct TermOffsetCtx TermOffsetCtx; |
| 108480 | |
| 108481 | struct TermOffset { |
| 108482 | char *pList; /* Position-list */ |
| 108483 | int iPos; /* Position just read from pList */ |
| 108484 | int iOff; /* Offset of this term from read positions */ |
| 108485 | }; |
| 108486 | |
| 108487 | struct TermOffsetCtx { |
| 108488 | int iCol; /* Column of table to populate aTerm for */ |
| 108489 | int iTerm; |
| 108490 | sqlite3_int64 iDocid; |
| 108491 | TermOffset *aTerm; |
| 108492 | }; |
| 108493 | |
| 108494 | /* |
| 108495 | ** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets(). |
| 108496 | */ |
| 108497 | static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 108498 | TermOffsetCtx *p = (TermOffsetCtx *)ctx; |
| 108499 | int nTerm; /* Number of tokens in phrase */ |
| 108500 | int iTerm; /* For looping through nTerm phrase terms */ |
| 108501 | char *pList; /* Pointer to position list for phrase */ |
| 108502 | int iPos = 0; /* First position in position-list */ |
| 108503 | |
| 108504 | UNUSED_PARAMETER(iPhrase); |
| 108505 | pList = sqlite3Fts3FindPositions(pExpr, p->iDocid, p->iCol); |
| 108506 | nTerm = pExpr->pPhrase->nToken; |
| 108507 | if( pList ){ |
| 108508 | fts3GetDeltaPosition(&pList, &iPos); |
| 108509 | assert( iPos>=0 ); |
| 108510 | } |
| 108511 | |
| 108512 | for(iTerm=0; iTerm<nTerm; iTerm++){ |
| 108513 | TermOffset *pT = &p->aTerm[p->iTerm++]; |
| 108514 | pT->iOff = nTerm-iTerm-1; |
| 108515 | pT->pList = pList; |
| 108516 | pT->iPos = iPos; |
| 108517 | } |
| 108518 | |
| 108519 | return SQLITE_OK; |
| 108520 | } |
| 108521 | |
| 108522 | /* |
| 108523 | ** Implementation of offsets() function. |
| 108524 | */ |
| 108525 | SQLITE_PRIVATE void sqlite3Fts3Offsets( |
| 108526 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 108527 | Fts3Cursor *pCsr /* Cursor object */ |
| 108528 | ){ |
| 108529 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 108530 | sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; |
| 108531 | const char *ZDUMMY; /* Dummy argument used with xNext() */ |
| 108532 | int NDUMMY; /* Dummy argument used with xNext() */ |
| 108533 | int rc; /* Return Code */ |
| 108534 | int nToken; /* Number of tokens in query */ |
| 108535 | int iCol; /* Column currently being processed */ |
| 108536 | StrBuffer res = {0, 0, 0}; /* Result string */ |
| 108537 | TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */ |
| 108538 | |
| 108539 | if( !pCsr->pExpr ){ |
| 108540 | sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); |
| 108541 | return; |
| 108542 | } |
| 108543 | |
| 108544 | memset(&sCtx, 0, sizeof(sCtx)); |
| 108545 | assert( pCsr->isRequireSeek==0 ); |
| 108546 | |
| 108547 | /* Count the number of terms in the query */ |
| 108548 | rc = fts3ExprLoadDoclists(pCsr, 0, &nToken); |
| 108549 | if( rc!=SQLITE_OK ) goto offsets_out; |
| 108550 | |
| 108551 | /* Allocate the array of TermOffset iterators. */ |
| 108552 | sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken); |
| 108553 | if( 0==sCtx.aTerm ){ |
| 108554 | rc = SQLITE_NOMEM; |
| 108555 | goto offsets_out; |
| 108556 | } |
| 108557 | sCtx.iDocid = pCsr->iPrevId; |
| 108558 | |
| 108559 | /* Loop through the table columns, appending offset information to |
| 108560 | ** string-buffer res for each column. |
| 108561 | */ |
| 108562 | for(iCol=0; iCol<pTab->nColumn; iCol++){ |
| 108563 | sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ |
| 108564 | int iStart; |
| 108565 | int iEnd; |
| 108566 | int iCurrent; |
| 108567 | const char *zDoc; |
| 108568 | int nDoc; |
| 108569 | |
| 108570 | /* Initialize the contents of sCtx.aTerm[] for column iCol. There is |
| 108571 | ** no way that this operation can fail, so the return code from |
| 108572 | ** fts3ExprIterate() can be discarded. |
| 108573 | */ |
| 108574 | sCtx.iCol = iCol; |
| 108575 | sCtx.iTerm = 0; |
| 108576 | (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx); |
| 108577 | |
| 108578 | /* Retreive the text stored in column iCol. If an SQL NULL is stored |
| 108579 | ** in column iCol, jump immediately to the next iteration of the loop. |
| 108580 | ** If an OOM occurs while retrieving the data (this can happen if SQLite |
| 108581 | ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM |
| 108582 | ** to the caller. |
| 108583 | */ |
| 108584 | zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1); |
| 108585 | nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1); |
| 108586 | if( zDoc==0 ){ |
| 108587 | if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){ |
| 108588 | continue; |
| 108589 | } |
| 108590 | rc = SQLITE_NOMEM; |
| 108591 | goto offsets_out; |
| 108592 | } |
| 108593 | |
| 108594 | /* Initialize a tokenizer iterator to iterate through column iCol. */ |
| 108595 | rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 108596 | if( rc!=SQLITE_OK ) goto offsets_out; |
| 108597 | pC->pTokenizer = pTab->pTokenizer; |
| 108598 | |
| 108599 | rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); |
| 108600 | while( rc==SQLITE_OK ){ |
| 108601 | int i; /* Used to loop through terms */ |
| 108602 | int iMinPos = 0x7FFFFFFF; /* Position of next token */ |
| 108603 | TermOffset *pTerm = 0; /* TermOffset associated with next token */ |
| 108604 | |
| 108605 | for(i=0; i<nToken; i++){ |
| 108606 | TermOffset *pT = &sCtx.aTerm[i]; |
| 108607 | if( pT->pList && (pT->iPos-pT->iOff)<iMinPos ){ |
| 108608 | iMinPos = pT->iPos-pT->iOff; |
| 108609 | pTerm = pT; |
| 108610 | } |
| 108611 | } |
| 108612 | |
| 108613 | if( !pTerm ){ |
| 108614 | /* All offsets for this column have been gathered. */ |
| 108615 | break; |
| 108616 | }else{ |
| 108617 | assert( iCurrent<=iMinPos ); |
| 108618 | if( 0==(0xFE&*pTerm->pList) ){ |
| 108619 | pTerm->pList = 0; |
| 108620 | }else{ |
| 108621 | fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos); |
| 108622 | } |
| 108623 | while( rc==SQLITE_OK && iCurrent<iMinPos ){ |
| 108624 | rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); |
| 108625 | } |
| 108626 | if( rc==SQLITE_OK ){ |
| 108627 | char aBuffer[64]; |
| 108628 | sqlite3_snprintf(sizeof(aBuffer), aBuffer, |
| 108629 | "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart |
| 108630 | ); |
| 108631 | rc = fts3StringAppend(&res, aBuffer, -1); |
| 108632 | } |
| 108633 | } |
| 108634 | } |
| 108635 | if( rc==SQLITE_DONE ){ |
| 108636 | rc = SQLITE_CORRUPT; |
| 108637 | } |
| 108638 | |
| 108639 | pMod->xClose(pC); |
| 108640 | if( rc!=SQLITE_OK ) goto offsets_out; |
| 108641 | } |
| 108642 | |
| 108643 | offsets_out: |
| 108644 | sqlite3_free(sCtx.aTerm); |
| 108645 | assert( rc!=SQLITE_DONE ); |
| 108646 | if( rc!=SQLITE_OK ){ |
| 108647 | sqlite3_result_error_code(pCtx, rc); |
| 108648 | sqlite3_free(res.z); |
| 108649 | }else{ |
| 108650 | sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free); |
| 108651 | } |
| 108652 | return; |
| 108653 | } |
| 108654 | |
| 108655 | /* |
| 108656 | ** Implementation of matchinfo() function. |
| 108657 | */ |
| 108658 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *pCsr){ |
| 108659 | int rc; |
| 108660 | if( !pCsr->pExpr ){ |
| 108661 | sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); |
| 108662 | return; |
| 108663 | } |
| 108664 | rc = fts3GetMatchinfo(pCsr); |
| 108665 | if( rc!=SQLITE_OK ){ |
| 108666 | sqlite3_result_error_code(pContext, rc); |
| 108667 | }else{ |
| 108668 | Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab; |
| 108669 | int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*3); |
| 108670 | if( pTab->bHasDocsize ){ |
| 108671 | n += sizeof(u32)*(1 + 2*pTab->nColumn); |
| 108672 | } |
| 108673 | sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); |
| 108674 | } |
| 108675 | } |
| 108676 | |
| 108677 | #endif |
| @@ -107634,10 +109097,11 @@ | |
| 109097 | |
| 109098 | sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); |
| 109099 | rc = sqlite3_step(pRtree->pReadNode); |
| 109100 | if( rc==SQLITE_ROW ){ |
| 109101 | const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); |
| 109102 | assert( sqlite3_column_bytes(pRtree->pReadNode, 0)==pRtree->iNodeSize ); |
| 109103 | memcpy(pNode->zData, zBlob, pRtree->iNodeSize); |
| 109104 | nodeReference(pParent); |
| 109105 | }else{ |
| 109106 | sqlite3_free(pNode); |
| 109107 | pNode = 0; |
| @@ -109830,35 +111294,73 @@ | |
| 111294 | |
| 111295 | return rc; |
| 111296 | } |
| 111297 | |
| 111298 | /* |
| 111299 | ** The second argument to this function contains the text of an SQL statement |
| 111300 | ** that returns a single integer value. The statement is compiled and executed |
| 111301 | ** using database connection db. If successful, the integer value returned |
| 111302 | ** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error |
| 111303 | ** code is returned and the value of *piVal after returning is not defined. |
| 111304 | */ |
| 111305 | static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){ |
| 111306 | int rc = SQLITE_NOMEM; |
| 111307 | if( zSql ){ |
| 111308 | sqlite3_stmt *pStmt = 0; |
| 111309 | rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
| 111310 | if( rc==SQLITE_OK ){ |
| 111311 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 111312 | *piVal = sqlite3_column_int(pStmt, 0); |
| 111313 | } |
| 111314 | rc = sqlite3_finalize(pStmt); |
| 111315 | } |
| 111316 | } |
| 111317 | return rc; |
| 111318 | } |
| 111319 | |
| 111320 | /* |
| 111321 | ** This function is called from within the xConnect() or xCreate() method to |
| 111322 | ** determine the node-size used by the rtree table being created or connected |
| 111323 | ** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned. |
| 111324 | ** Otherwise, an SQLite error code is returned. |
| 111325 | ** |
| 111326 | ** If this function is being called as part of an xConnect(), then the rtree |
| 111327 | ** table already exists. In this case the node-size is determined by inspecting |
| 111328 | ** the root node of the tree. |
| 111329 | ** |
| 111330 | ** Otherwise, for an xCreate(), use 64 bytes less than the database page-size. |
| 111331 | ** This ensures that each node is stored on a single database page. If the |
| 111332 | ** database page-size is so large that more than RTREE_MAXCELLS entries |
| 111333 | ** would fit in a single node, use a smaller node-size. |
| 111334 | */ |
| 111335 | static int getNodeSize( |
| 111336 | sqlite3 *db, /* Database handle */ |
| 111337 | Rtree *pRtree, /* Rtree handle */ |
| 111338 | int isCreate /* True for xCreate, false for xConnect */ |
| 111339 | ){ |
| 111340 | int rc; |
| 111341 | char *zSql; |
| 111342 | if( isCreate ){ |
| 111343 | int iPageSize; |
| 111344 | zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb); |
| 111345 | rc = getIntFromStmt(db, zSql, &iPageSize); |
| 111346 | if( rc==SQLITE_OK ){ |
| 111347 | pRtree->iNodeSize = iPageSize-64; |
| 111348 | if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ |
| 111349 | pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; |
| 111350 | } |
| 111351 | } |
| 111352 | }else{ |
| 111353 | zSql = sqlite3_mprintf( |
| 111354 | "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1", |
| 111355 | pRtree->zDb, pRtree->zName |
| 111356 | ); |
| 111357 | rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); |
| 111358 | } |
| 111359 | |
| 111360 | sqlite3_free(zSql); |
| 111361 | return rc; |
| 111362 | } |
| 111363 | |
| 111364 | /* |
| 111365 | ** This function is the implementation of both the xConnect and xCreate |
| 111366 | ** methods of the r-tree virtual table. |
| @@ -109875,11 +111377,10 @@ | |
| 111377 | sqlite3_vtab **ppVtab, /* OUT: New virtual table */ |
| 111378 | char **pzErr, /* OUT: Error message, if any */ |
| 111379 | int isCreate /* True for xCreate, false for xConnect */ |
| 111380 | ){ |
| 111381 | int rc = SQLITE_OK; |
| 111382 | Rtree *pRtree; |
| 111383 | int nDb; /* Length of string argv[1] */ |
| 111384 | int nName; /* Length of string argv[2] */ |
| 111385 | int eCoordType = (int)pAux; |
| 111386 | |
| @@ -109894,15 +111395,10 @@ | |
| 111395 | if( aErrMsg[iErr] ){ |
| 111396 | *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); |
| 111397 | return SQLITE_ERROR; |
| 111398 | } |
| 111399 | |
| 111400 | /* Allocate the sqlite3_vtab structure */ |
| 111401 | nDb = strlen(argv[1]); |
| 111402 | nName = strlen(argv[2]); |
| 111403 | pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); |
| 111404 | if( !pRtree ){ |
| @@ -109917,48 +111413,41 @@ | |
| 111413 | pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; |
| 111414 | pRtree->eCoordType = eCoordType; |
| 111415 | memcpy(pRtree->zDb, argv[1], nDb); |
| 111416 | memcpy(pRtree->zName, argv[2], nName); |
| 111417 | |
| 111418 | /* Figure out the node size to use. */ |
| 111419 | rc = getNodeSize(db, pRtree, isCreate); |
| 111420 | |
| 111421 | /* Create/Connect to the underlying relational database schema. If |
| 111422 | ** that is successful, call sqlite3_declare_vtab() to configure |
| 111423 | ** the r-tree table schema. |
| 111424 | */ |
| 111425 | if( rc==SQLITE_OK ){ |
| 111426 | if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ |
| 111427 | *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
| 111428 | }else{ |
| 111429 | char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); |
| 111430 | char *zTmp; |
| 111431 | int ii; |
| 111432 | for(ii=4; zSql && ii<argc; ii++){ |
| 111433 | zTmp = zSql; |
| 111434 | zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); |
| 111435 | sqlite3_free(zTmp); |
| 111436 | } |
| 111437 | if( zSql ){ |
| 111438 | zTmp = zSql; |
| 111439 | zSql = sqlite3_mprintf("%s);", zTmp); |
| 111440 | sqlite3_free(zTmp); |
| 111441 | } |
| 111442 | if( !zSql ){ |
| 111443 | rc = SQLITE_NOMEM; |
| 111444 | }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ |
| 111445 | *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
| 111446 | } |
| 111447 | sqlite3_free(zSql); |
| 111448 | } |
| 111449 | } |
| 111450 | |
| 111451 | if( rc==SQLITE_OK ){ |
| 111452 | *ppVtab = (sqlite3_vtab *)pRtree; |
| 111453 | }else{ |
| 111454 |
+74
-8
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -105,17 +105,17 @@ | ||
| 105 | 105 | ** |
| 106 | 106 | ** See also: [sqlite3_libversion()], |
| 107 | 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | 109 | */ |
| 110 | -#define SQLITE_VERSION "3.6.22" | |
| 111 | -#define SQLITE_VERSION_NUMBER 3006022 | |
| 112 | -#define SQLITE_SOURCE_ID "2010-01-02 19:02:02 51f7ee844057086789dcfcdcba7daf45343cae62" | |
| 110 | +#define SQLITE_VERSION "3.6.23" | |
| 111 | +#define SQLITE_VERSION_NUMBER 3006023 | |
| 112 | +#define SQLITE_SOURCE_ID "2010-02-26 13:07:37 8f29490da62df07ea922b03cab52b6edd2669edb" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | -** KEYWORDS: sqlite3_version | |
| 116 | +** KEYWORDS: sqlite3_version, sqlite3_sourceid | |
| 117 | 117 | ** |
| 118 | 118 | ** These interfaces provide the same information as the [SQLITE_VERSION], |
| 119 | 119 | ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| 120 | 120 | ** but are associated with the library instead of the header file. ^(Cautious |
| 121 | 121 | ** programmers might include assert() statements in their application to |
| @@ -133,21 +133,48 @@ | ||
| 133 | 133 | ** macro. ^The sqlite3_libversion() function returns a pointer to the |
| 134 | 134 | ** to the sqlite3_version[] string constant. The sqlite3_libversion() |
| 135 | 135 | ** function is provided for use in DLLs since DLL users usually do not have |
| 136 | 136 | ** direct access to string constants within the DLL. ^The |
| 137 | 137 | ** sqlite3_libversion_number() function returns an integer equal to |
| 138 | -** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function a pointer | |
| 139 | -** to a string constant whose value is the same as the [SQLITE_SOURCE_ID] | |
| 140 | -** C preprocessor macro. | |
| 138 | +** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns | |
| 139 | +** a pointer to a string constant whose value is the same as the | |
| 140 | +** [SQLITE_SOURCE_ID] C preprocessor macro. | |
| 141 | 141 | ** |
| 142 | 142 | ** See also: [sqlite_version()] and [sqlite_source_id()]. |
| 143 | 143 | */ |
| 144 | 144 | SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; |
| 145 | 145 | SQLITE_API const char *sqlite3_libversion(void); |
| 146 | 146 | SQLITE_API const char *sqlite3_sourceid(void); |
| 147 | 147 | SQLITE_API int sqlite3_libversion_number(void); |
| 148 | 148 | |
| 149 | +/* | |
| 150 | +** CAPI3REF: Run-Time Library Compilation Options Diagnostics | |
| 151 | +** KEYWORDS: sqlite3_compileoption_used, sqlite3_compileoption_get | |
| 152 | +** | |
| 153 | +** ^The sqlite3_compileoption_used() function returns 0 or 1 | |
| 154 | +** indicating whether the specified option was defined at | |
| 155 | +** compile time. ^The SQLITE_ prefix may be omitted from the | |
| 156 | +** option name passed to sqlite3_compileoption_used(). | |
| 157 | +** | |
| 158 | +** ^The sqlite3_compileoption_get() function allows interating | |
| 159 | +** over the list of options that were defined at compile time by | |
| 160 | +** returning the N-th compile time option string. ^If N is out of range, | |
| 161 | +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ | |
| 162 | +** prefix is omitted from any strings returned by | |
| 163 | +** sqlite3_compileoption_get(). | |
| 164 | +** | |
| 165 | +** ^Support for the diagnostic functions sqlite3_compileoption_used() | |
| 166 | +** and sqlite3_compileoption_get() may be omitted by specifing the | |
| 167 | +** SQLITE_OMIT_COMPILEOPTION_DIAGS option at compile time. | |
| 168 | +** | |
| 169 | +** See also: [sqlite_compile_option_used()] and [sqlite_compile_option_get()]. | |
| 170 | +*/ | |
| 171 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS | |
| 172 | +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); | |
| 173 | +SQLITE_API const char *sqlite3_compileoption_get(int N); | |
| 174 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ | |
| 175 | + | |
| 149 | 176 | /* |
| 150 | 177 | ** CAPI3REF: Test To See If The Library Is Threadsafe |
| 151 | 178 | ** |
| 152 | 179 | ** ^The sqlite3_threadsafe() function returns zero if and only if |
| 153 | 180 | ** SQLite was compiled mutexing code omitted due to the |
| @@ -435,10 +462,11 @@ | ||
| 435 | 462 | #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ |
| 436 | 463 | #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ |
| 437 | 464 | #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ |
| 438 | 465 | #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ |
| 439 | 466 | #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ |
| 467 | +#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ | |
| 440 | 468 | #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ |
| 441 | 469 | #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ |
| 442 | 470 | #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ |
| 443 | 471 | #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ |
| 444 | 472 | #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ |
| @@ -916,11 +944,10 @@ | ||
| 916 | 944 | SQLITE_API int sqlite3_os_init(void); |
| 917 | 945 | SQLITE_API int sqlite3_os_end(void); |
| 918 | 946 | |
| 919 | 947 | /* |
| 920 | 948 | ** CAPI3REF: Configuring The SQLite Library |
| 921 | -** EXPERIMENTAL | |
| 922 | 949 | ** |
| 923 | 950 | ** The sqlite3_config() interface is used to make global configuration |
| 924 | 951 | ** changes to SQLite in order to tune SQLite to the specific needs of |
| 925 | 952 | ** the application. The default configuration is recommended for most |
| 926 | 953 | ** applications and so this routine is usually not necessary. It is |
| @@ -1257,10 +1284,11 @@ | ||
| 1257 | 1284 | #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ |
| 1258 | 1285 | /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ |
| 1259 | 1286 | #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ |
| 1260 | 1287 | #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ |
| 1261 | 1288 | #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ |
| 1289 | +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ | |
| 1262 | 1290 | |
| 1263 | 1291 | /* |
| 1264 | 1292 | ** CAPI3REF: Configuration Options |
| 1265 | 1293 | ** EXPERIMENTAL |
| 1266 | 1294 | ** |
| @@ -3659,10 +3687,11 @@ | ||
| 3659 | 3687 | sqlite3*, |
| 3660 | 3688 | void*, |
| 3661 | 3689 | void(*)(void*,sqlite3*,int eTextRep,const void*) |
| 3662 | 3690 | ); |
| 3663 | 3691 | |
| 3692 | +#if SQLITE_HAS_CODEC | |
| 3664 | 3693 | /* |
| 3665 | 3694 | ** Specify the key for an encrypted database. This routine should be |
| 3666 | 3695 | ** called right after sqlite3_open(). |
| 3667 | 3696 | ** |
| 3668 | 3697 | ** The code to implement this API is not available in the public release |
| @@ -3684,10 +3713,29 @@ | ||
| 3684 | 3713 | SQLITE_API int sqlite3_rekey( |
| 3685 | 3714 | sqlite3 *db, /* Database to be rekeyed */ |
| 3686 | 3715 | const void *pKey, int nKey /* The new key */ |
| 3687 | 3716 | ); |
| 3688 | 3717 | |
| 3718 | +/* | |
| 3719 | +** Specify the activation key for a SEE database. Unless | |
| 3720 | +** activated, none of the SEE routines will work. | |
| 3721 | +*/ | |
| 3722 | +SQLITE_API void sqlite3_activate_see( | |
| 3723 | + const char *zPassPhrase /* Activation phrase */ | |
| 3724 | +); | |
| 3725 | +#endif | |
| 3726 | + | |
| 3727 | +#ifdef SQLITE_ENABLE_CEROD | |
| 3728 | +/* | |
| 3729 | +** Specify the activation key for a CEROD database. Unless | |
| 3730 | +** activated, none of the CEROD routines will work. | |
| 3731 | +*/ | |
| 3732 | +SQLITE_API void sqlite3_activate_cerod( | |
| 3733 | + const char *zPassPhrase /* Activation phrase */ | |
| 3734 | +); | |
| 3735 | +#endif | |
| 3736 | + | |
| 3689 | 3737 | /* |
| 3690 | 3738 | ** CAPI3REF: Suspend Execution For A Short Time |
| 3691 | 3739 | ** |
| 3692 | 3740 | ** ^The sqlite3_sleep() function causes the current thread to suspend execution |
| 3693 | 3741 | ** for at least a number of milliseconds specified in its parameter. |
| @@ -5645,10 +5693,28 @@ | ||
| 5645 | 5693 | ** case-indendent fashion, using the same definition of case independence |
| 5646 | 5694 | ** that SQLite uses internally when comparing identifiers. |
| 5647 | 5695 | */ |
| 5648 | 5696 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 5649 | 5697 | |
| 5698 | +/* | |
| 5699 | +** CAPI3REF: Error Logging Interface | |
| 5700 | +** EXPERIMENTAL | |
| 5701 | +** | |
| 5702 | +** ^The [sqlite3_log()] interface writes a message into the error log | |
| 5703 | +** established by the [SQLITE_CONFIG_ERRORLOG] option to [sqlite3_config()]. | |
| 5704 | +** ^If logging is enabled, the zFormat string and subsequent arguments are | |
| 5705 | +** passed through to [sqlite3_vmprintf()] to generate the final output string. | |
| 5706 | +** | |
| 5707 | +** The sqlite3_log() interface is intended for use by extensions such as | |
| 5708 | +** virtual tables, collating functions, and SQL functions. While there is | |
| 5709 | +** nothing to prevent an application from calling sqlite3_log(), doing so | |
| 5710 | +** is considered bad form. | |
| 5711 | +** | |
| 5712 | +** The zFormat string must not be NULL. | |
| 5713 | +*/ | |
| 5714 | +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); | |
| 5715 | + | |
| 5650 | 5716 | /* |
| 5651 | 5717 | ** Undo the hack that converts floating point types to integer for |
| 5652 | 5718 | ** builds on processors without floating point support. |
| 5653 | 5719 | */ |
| 5654 | 5720 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 5655 | 5721 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -105,17 +105,17 @@ | |
| 105 | ** |
| 106 | ** See also: [sqlite3_libversion()], |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.6.22" |
| 111 | #define SQLITE_VERSION_NUMBER 3006022 |
| 112 | #define SQLITE_SOURCE_ID "2010-01-02 19:02:02 51f7ee844057086789dcfcdcba7daf45343cae62" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version |
| 117 | ** |
| 118 | ** These interfaces provide the same information as the [SQLITE_VERSION], |
| 119 | ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| 120 | ** but are associated with the library instead of the header file. ^(Cautious |
| 121 | ** programmers might include assert() statements in their application to |
| @@ -133,21 +133,48 @@ | |
| 133 | ** macro. ^The sqlite3_libversion() function returns a pointer to the |
| 134 | ** to the sqlite3_version[] string constant. The sqlite3_libversion() |
| 135 | ** function is provided for use in DLLs since DLL users usually do not have |
| 136 | ** direct access to string constants within the DLL. ^The |
| 137 | ** sqlite3_libversion_number() function returns an integer equal to |
| 138 | ** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function a pointer |
| 139 | ** to a string constant whose value is the same as the [SQLITE_SOURCE_ID] |
| 140 | ** C preprocessor macro. |
| 141 | ** |
| 142 | ** See also: [sqlite_version()] and [sqlite_source_id()]. |
| 143 | */ |
| 144 | SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; |
| 145 | SQLITE_API const char *sqlite3_libversion(void); |
| 146 | SQLITE_API const char *sqlite3_sourceid(void); |
| 147 | SQLITE_API int sqlite3_libversion_number(void); |
| 148 | |
| 149 | /* |
| 150 | ** CAPI3REF: Test To See If The Library Is Threadsafe |
| 151 | ** |
| 152 | ** ^The sqlite3_threadsafe() function returns zero if and only if |
| 153 | ** SQLite was compiled mutexing code omitted due to the |
| @@ -435,10 +462,11 @@ | |
| 435 | #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ |
| 436 | #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ |
| 437 | #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ |
| 438 | #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ |
| 439 | #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ |
| 440 | #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ |
| 441 | #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ |
| 442 | #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ |
| 443 | #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ |
| 444 | #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ |
| @@ -916,11 +944,10 @@ | |
| 916 | SQLITE_API int sqlite3_os_init(void); |
| 917 | SQLITE_API int sqlite3_os_end(void); |
| 918 | |
| 919 | /* |
| 920 | ** CAPI3REF: Configuring The SQLite Library |
| 921 | ** EXPERIMENTAL |
| 922 | ** |
| 923 | ** The sqlite3_config() interface is used to make global configuration |
| 924 | ** changes to SQLite in order to tune SQLite to the specific needs of |
| 925 | ** the application. The default configuration is recommended for most |
| 926 | ** applications and so this routine is usually not necessary. It is |
| @@ -1257,10 +1284,11 @@ | |
| 1257 | #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ |
| 1258 | /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ |
| 1259 | #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ |
| 1260 | #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ |
| 1261 | #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ |
| 1262 | |
| 1263 | /* |
| 1264 | ** CAPI3REF: Configuration Options |
| 1265 | ** EXPERIMENTAL |
| 1266 | ** |
| @@ -3659,10 +3687,11 @@ | |
| 3659 | sqlite3*, |
| 3660 | void*, |
| 3661 | void(*)(void*,sqlite3*,int eTextRep,const void*) |
| 3662 | ); |
| 3663 | |
| 3664 | /* |
| 3665 | ** Specify the key for an encrypted database. This routine should be |
| 3666 | ** called right after sqlite3_open(). |
| 3667 | ** |
| 3668 | ** The code to implement this API is not available in the public release |
| @@ -3684,10 +3713,29 @@ | |
| 3684 | SQLITE_API int sqlite3_rekey( |
| 3685 | sqlite3 *db, /* Database to be rekeyed */ |
| 3686 | const void *pKey, int nKey /* The new key */ |
| 3687 | ); |
| 3688 | |
| 3689 | /* |
| 3690 | ** CAPI3REF: Suspend Execution For A Short Time |
| 3691 | ** |
| 3692 | ** ^The sqlite3_sleep() function causes the current thread to suspend execution |
| 3693 | ** for at least a number of milliseconds specified in its parameter. |
| @@ -5645,10 +5693,28 @@ | |
| 5645 | ** case-indendent fashion, using the same definition of case independence |
| 5646 | ** that SQLite uses internally when comparing identifiers. |
| 5647 | */ |
| 5648 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 5649 | |
| 5650 | /* |
| 5651 | ** Undo the hack that converts floating point types to integer for |
| 5652 | ** builds on processors without floating point support. |
| 5653 | */ |
| 5654 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 5655 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -105,17 +105,17 @@ | |
| 105 | ** |
| 106 | ** See also: [sqlite3_libversion()], |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.6.23" |
| 111 | #define SQLITE_VERSION_NUMBER 3006023 |
| 112 | #define SQLITE_SOURCE_ID "2010-02-26 13:07:37 8f29490da62df07ea922b03cab52b6edd2669edb" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| 118 | ** These interfaces provide the same information as the [SQLITE_VERSION], |
| 119 | ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| 120 | ** but are associated with the library instead of the header file. ^(Cautious |
| 121 | ** programmers might include assert() statements in their application to |
| @@ -133,21 +133,48 @@ | |
| 133 | ** macro. ^The sqlite3_libversion() function returns a pointer to the |
| 134 | ** to the sqlite3_version[] string constant. The sqlite3_libversion() |
| 135 | ** function is provided for use in DLLs since DLL users usually do not have |
| 136 | ** direct access to string constants within the DLL. ^The |
| 137 | ** sqlite3_libversion_number() function returns an integer equal to |
| 138 | ** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns |
| 139 | ** a pointer to a string constant whose value is the same as the |
| 140 | ** [SQLITE_SOURCE_ID] C preprocessor macro. |
| 141 | ** |
| 142 | ** See also: [sqlite_version()] and [sqlite_source_id()]. |
| 143 | */ |
| 144 | SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; |
| 145 | SQLITE_API const char *sqlite3_libversion(void); |
| 146 | SQLITE_API const char *sqlite3_sourceid(void); |
| 147 | SQLITE_API int sqlite3_libversion_number(void); |
| 148 | |
| 149 | /* |
| 150 | ** CAPI3REF: Run-Time Library Compilation Options Diagnostics |
| 151 | ** KEYWORDS: sqlite3_compileoption_used, sqlite3_compileoption_get |
| 152 | ** |
| 153 | ** ^The sqlite3_compileoption_used() function returns 0 or 1 |
| 154 | ** indicating whether the specified option was defined at |
| 155 | ** compile time. ^The SQLITE_ prefix may be omitted from the |
| 156 | ** option name passed to sqlite3_compileoption_used(). |
| 157 | ** |
| 158 | ** ^The sqlite3_compileoption_get() function allows interating |
| 159 | ** over the list of options that were defined at compile time by |
| 160 | ** returning the N-th compile time option string. ^If N is out of range, |
| 161 | ** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ |
| 162 | ** prefix is omitted from any strings returned by |
| 163 | ** sqlite3_compileoption_get(). |
| 164 | ** |
| 165 | ** ^Support for the diagnostic functions sqlite3_compileoption_used() |
| 166 | ** and sqlite3_compileoption_get() may be omitted by specifing the |
| 167 | ** SQLITE_OMIT_COMPILEOPTION_DIAGS option at compile time. |
| 168 | ** |
| 169 | ** See also: [sqlite_compile_option_used()] and [sqlite_compile_option_get()]. |
| 170 | */ |
| 171 | #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 172 | SQLITE_API int sqlite3_compileoption_used(const char *zOptName); |
| 173 | SQLITE_API const char *sqlite3_compileoption_get(int N); |
| 174 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 175 | |
| 176 | /* |
| 177 | ** CAPI3REF: Test To See If The Library Is Threadsafe |
| 178 | ** |
| 179 | ** ^The sqlite3_threadsafe() function returns zero if and only if |
| 180 | ** SQLite was compiled mutexing code omitted due to the |
| @@ -435,10 +462,11 @@ | |
| 462 | #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ |
| 463 | #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ |
| 464 | #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ |
| 465 | #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ |
| 466 | #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ |
| 467 | #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ |
| 468 | #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ |
| 469 | #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ |
| 470 | #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ |
| 471 | #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ |
| 472 | #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ |
| @@ -916,11 +944,10 @@ | |
| 944 | SQLITE_API int sqlite3_os_init(void); |
| 945 | SQLITE_API int sqlite3_os_end(void); |
| 946 | |
| 947 | /* |
| 948 | ** CAPI3REF: Configuring The SQLite Library |
| 949 | ** |
| 950 | ** The sqlite3_config() interface is used to make global configuration |
| 951 | ** changes to SQLite in order to tune SQLite to the specific needs of |
| 952 | ** the application. The default configuration is recommended for most |
| 953 | ** applications and so this routine is usually not necessary. It is |
| @@ -1257,10 +1284,11 @@ | |
| 1284 | #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ |
| 1285 | /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ |
| 1286 | #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ |
| 1287 | #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ |
| 1288 | #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ |
| 1289 | #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ |
| 1290 | |
| 1291 | /* |
| 1292 | ** CAPI3REF: Configuration Options |
| 1293 | ** EXPERIMENTAL |
| 1294 | ** |
| @@ -3659,10 +3687,11 @@ | |
| 3687 | sqlite3*, |
| 3688 | void*, |
| 3689 | void(*)(void*,sqlite3*,int eTextRep,const void*) |
| 3690 | ); |
| 3691 | |
| 3692 | #if SQLITE_HAS_CODEC |
| 3693 | /* |
| 3694 | ** Specify the key for an encrypted database. This routine should be |
| 3695 | ** called right after sqlite3_open(). |
| 3696 | ** |
| 3697 | ** The code to implement this API is not available in the public release |
| @@ -3684,10 +3713,29 @@ | |
| 3713 | SQLITE_API int sqlite3_rekey( |
| 3714 | sqlite3 *db, /* Database to be rekeyed */ |
| 3715 | const void *pKey, int nKey /* The new key */ |
| 3716 | ); |
| 3717 | |
| 3718 | /* |
| 3719 | ** Specify the activation key for a SEE database. Unless |
| 3720 | ** activated, none of the SEE routines will work. |
| 3721 | */ |
| 3722 | SQLITE_API void sqlite3_activate_see( |
| 3723 | const char *zPassPhrase /* Activation phrase */ |
| 3724 | ); |
| 3725 | #endif |
| 3726 | |
| 3727 | #ifdef SQLITE_ENABLE_CEROD |
| 3728 | /* |
| 3729 | ** Specify the activation key for a CEROD database. Unless |
| 3730 | ** activated, none of the CEROD routines will work. |
| 3731 | */ |
| 3732 | SQLITE_API void sqlite3_activate_cerod( |
| 3733 | const char *zPassPhrase /* Activation phrase */ |
| 3734 | ); |
| 3735 | #endif |
| 3736 | |
| 3737 | /* |
| 3738 | ** CAPI3REF: Suspend Execution For A Short Time |
| 3739 | ** |
| 3740 | ** ^The sqlite3_sleep() function causes the current thread to suspend execution |
| 3741 | ** for at least a number of milliseconds specified in its parameter. |
| @@ -5645,10 +5693,28 @@ | |
| 5693 | ** case-indendent fashion, using the same definition of case independence |
| 5694 | ** that SQLite uses internally when comparing identifiers. |
| 5695 | */ |
| 5696 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 5697 | |
| 5698 | /* |
| 5699 | ** CAPI3REF: Error Logging Interface |
| 5700 | ** EXPERIMENTAL |
| 5701 | ** |
| 5702 | ** ^The [sqlite3_log()] interface writes a message into the error log |
| 5703 | ** established by the [SQLITE_CONFIG_ERRORLOG] option to [sqlite3_config()]. |
| 5704 | ** ^If logging is enabled, the zFormat string and subsequent arguments are |
| 5705 | ** passed through to [sqlite3_vmprintf()] to generate the final output string. |
| 5706 | ** |
| 5707 | ** The sqlite3_log() interface is intended for use by extensions such as |
| 5708 | ** virtual tables, collating functions, and SQL functions. While there is |
| 5709 | ** nothing to prevent an application from calling sqlite3_log(), doing so |
| 5710 | ** is considered bad form. |
| 5711 | ** |
| 5712 | ** The zFormat string must not be NULL. |
| 5713 | */ |
| 5714 | SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); |
| 5715 | |
| 5716 | /* |
| 5717 | ** Undo the hack that converts floating point types to integer for |
| 5718 | ** builds on processors without floating point support. |
| 5719 | */ |
| 5720 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 5721 |