| | @@ -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,44 +305,46 @@ |
| 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 | | -** 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 |
| 315 | | -** non 64-bit values to ptr types results in a "hard" error with |
| 316 | | -** the MSVC 64-bit compiler which this attempts to avoid. |
| 317 | | -** |
| 318 | | -** A simple compiler pragma or casting sequence could not be found |
| 319 | | -** to correct this in all situations, so this macro was introduced. |
| 320 | | -** |
| 321 | | -** It could be argued that the intptr_t type could be used in this |
| 322 | | -** case, but that type is not available on all compilers, or |
| 323 | | -** requires the #include of specific headers which differs between |
| 324 | | -** platforms. |
| 318 | +** The following macros are used to cast pointers to integers and |
| 319 | +** integers to pointers. The way you do this varies from one compiler |
| 320 | +** to the next, so we have developed the following set of #if statements |
| 321 | +** to generate appropriate macros for a wide range of compilers. |
| 322 | +** |
| 323 | +** The correct "ANSI" way to do this is to use the intptr_t type. |
| 324 | +** Unfortunately, that typedef is not available on all compilers, or |
| 325 | +** if it is available, it requires an #include of specific headers |
| 326 | +** that very from one machine to the next. |
| 325 | 327 | ** |
| 326 | 328 | ** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on |
| 327 | 329 | ** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). |
| 328 | 330 | ** So we have to define the macros in different ways depending on the |
| 329 | 331 | ** compiler. |
| 330 | 332 | */ |
| 331 | | -#if defined(__GNUC__) |
| 332 | | -# if defined(HAVE_STDINT_H) |
| 333 | | -# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) |
| 334 | | -# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) |
| 335 | | -# else |
| 336 | | -# define SQLITE_INT_TO_PTR(X) ((void*)(X)) |
| 337 | | -# define SQLITE_PTR_TO_INT(X) ((int)(X)) |
| 338 | | -# endif |
| 339 | | -#else |
| 340 | | -# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) |
| 341 | | -# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) |
| 333 | +#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ |
| 334 | +# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) |
| 335 | +# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) |
| 336 | +#elif !defined(__GNUC__) /* Works for compilers other than LLVM */ |
| 337 | +# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) |
| 338 | +# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) |
| 339 | +#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ |
| 340 | +# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) |
| 341 | +# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) |
| 342 | +#else /* Generates a warning - but it always works */ |
| 343 | +# define SQLITE_INT_TO_PTR(X) ((void*)(X)) |
| 344 | +# define SQLITE_PTR_TO_INT(X) ((int)(X)) |
| 342 | 345 | #endif |
| 343 | | - |
| 344 | 346 | |
| 345 | 347 | /* |
| 346 | 348 | ** The SQLITE_THREADSAFE macro must be defined as either 0 or 1. |
| 347 | 349 | ** Older versions of SQLite used an optional THREADSAFE macro. |
| 348 | 350 | ** We support that for legacy |
| | @@ -369,27 +371,22 @@ |
| 369 | 371 | ** Exactly one of the following macros must be defined in order to |
| 370 | 372 | ** specify which memory allocation subsystem to use. |
| 371 | 373 | ** |
| 372 | 374 | ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() |
| 373 | 375 | ** 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 |
| 376 | +** |
| 377 | +** (Historical note: There used to be several other options, but we've |
| 378 | +** pared it down to just these two.) |
| 377 | 379 | ** |
| 378 | 380 | ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as |
| 379 | 381 | ** the default. |
| 380 | 382 | */ |
| 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 |
| 383 | +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1 |
| 384 | 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" |
| 385 | + is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG" |
| 387 | 386 | #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 |
| 387 | +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0 |
| 391 | 388 | # define SQLITE_SYSTEM_MALLOC 1 |
| 392 | 389 | #endif |
| 393 | 390 | |
| 394 | 391 | /* |
| 395 | 392 | ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the |
| | @@ -629,17 +626,17 @@ |
| 629 | 626 | ** |
| 630 | 627 | ** See also: [sqlite3_libversion()], |
| 631 | 628 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 632 | 629 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 633 | 630 | */ |
| 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" |
| 631 | +#define SQLITE_VERSION "3.6.23" |
| 632 | +#define SQLITE_VERSION_NUMBER 3006023 |
| 633 | +#define SQLITE_SOURCE_ID "2010-03-04 17:58:45 5e472896e02eed05c6c0886a48acd0bdc7a38731" |
| 637 | 634 | |
| 638 | 635 | /* |
| 639 | 636 | ** CAPI3REF: Run-Time Library Version Numbers |
| 640 | | -** KEYWORDS: sqlite3_version |
| 637 | +** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 641 | 638 | ** |
| 642 | 639 | ** These interfaces provide the same information as the [SQLITE_VERSION], |
| 643 | 640 | ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| 644 | 641 | ** but are associated with the library instead of the header file. ^(Cautious |
| 645 | 642 | ** programmers might include assert() statements in their application to |
| | @@ -657,21 +654,48 @@ |
| 657 | 654 | ** macro. ^The sqlite3_libversion() function returns a pointer to the |
| 658 | 655 | ** to the sqlite3_version[] string constant. The sqlite3_libversion() |
| 659 | 656 | ** function is provided for use in DLLs since DLL users usually do not have |
| 660 | 657 | ** direct access to string constants within the DLL. ^The |
| 661 | 658 | ** 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. |
| 659 | +** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns |
| 660 | +** a pointer to a string constant whose value is the same as the |
| 661 | +** [SQLITE_SOURCE_ID] C preprocessor macro. |
| 665 | 662 | ** |
| 666 | 663 | ** See also: [sqlite_version()] and [sqlite_source_id()]. |
| 667 | 664 | */ |
| 668 | 665 | SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; |
| 669 | 666 | SQLITE_API const char *sqlite3_libversion(void); |
| 670 | 667 | SQLITE_API const char *sqlite3_sourceid(void); |
| 671 | 668 | SQLITE_API int sqlite3_libversion_number(void); |
| 672 | 669 | |
| 670 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 671 | +/* |
| 672 | +** CAPI3REF: Run-Time Library Compilation Options Diagnostics |
| 673 | +** |
| 674 | +** ^The sqlite3_compileoption_used() function returns 0 or 1 |
| 675 | +** indicating whether the specified option was defined at |
| 676 | +** compile time. ^The SQLITE_ prefix may be omitted from the |
| 677 | +** option name passed to sqlite3_compileoption_used(). |
| 678 | +** |
| 679 | +** ^The sqlite3_compileoption_get() function allows interating |
| 680 | +** over the list of options that were defined at compile time by |
| 681 | +** returning the N-th compile time option string. ^If N is out of range, |
| 682 | +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ |
| 683 | +** prefix is omitted from any strings returned by |
| 684 | +** sqlite3_compileoption_get(). |
| 685 | +** |
| 686 | +** ^Support for the diagnostic functions sqlite3_compileoption_used() |
| 687 | +** and sqlite3_compileoption_get() may be omitted by specifing the |
| 688 | +** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. |
| 689 | +** |
| 690 | +** See also: SQL functions [sqlite_compileoption_used()] and |
| 691 | +** [sqlite_compileoption_get()] and the [compile_options pragma]. |
| 692 | +*/ |
| 693 | +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); |
| 694 | +SQLITE_API const char *sqlite3_compileoption_get(int N); |
| 695 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 696 | + |
| 673 | 697 | /* |
| 674 | 698 | ** CAPI3REF: Test To See If The Library Is Threadsafe |
| 675 | 699 | ** |
| 676 | 700 | ** ^The sqlite3_threadsafe() function returns zero if and only if |
| 677 | 701 | ** SQLite was compiled mutexing code omitted due to the |
| | @@ -959,10 +983,11 @@ |
| 959 | 983 | #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ |
| 960 | 984 | #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ |
| 961 | 985 | #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ |
| 962 | 986 | #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ |
| 963 | 987 | #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ |
| 988 | +#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ |
| 964 | 989 | #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ |
| 965 | 990 | #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ |
| 966 | 991 | #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ |
| 967 | 992 | #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ |
| 968 | 993 | #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ |
| | @@ -1440,11 +1465,10 @@ |
| 1440 | 1465 | SQLITE_API int sqlite3_os_init(void); |
| 1441 | 1466 | SQLITE_API int sqlite3_os_end(void); |
| 1442 | 1467 | |
| 1443 | 1468 | /* |
| 1444 | 1469 | ** CAPI3REF: Configuring The SQLite Library |
| 1445 | | -** EXPERIMENTAL |
| 1446 | 1470 | ** |
| 1447 | 1471 | ** The sqlite3_config() interface is used to make global configuration |
| 1448 | 1472 | ** changes to SQLite in order to tune SQLite to the specific needs of |
| 1449 | 1473 | ** the application. The default configuration is recommended for most |
| 1450 | 1474 | ** applications and so this routine is usually not necessary. It is |
| | @@ -1781,10 +1805,11 @@ |
| 1781 | 1805 | #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ |
| 1782 | 1806 | /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ |
| 1783 | 1807 | #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ |
| 1784 | 1808 | #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ |
| 1785 | 1809 | #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ |
| 1810 | +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ |
| 1786 | 1811 | |
| 1787 | 1812 | /* |
| 1788 | 1813 | ** CAPI3REF: Configuration Options |
| 1789 | 1814 | ** EXPERIMENTAL |
| 1790 | 1815 | ** |
| | @@ -4183,10 +4208,11 @@ |
| 4183 | 4208 | sqlite3*, |
| 4184 | 4209 | void*, |
| 4185 | 4210 | void(*)(void*,sqlite3*,int eTextRep,const void*) |
| 4186 | 4211 | ); |
| 4187 | 4212 | |
| 4213 | +#if SQLITE_HAS_CODEC |
| 4188 | 4214 | /* |
| 4189 | 4215 | ** Specify the key for an encrypted database. This routine should be |
| 4190 | 4216 | ** called right after sqlite3_open(). |
| 4191 | 4217 | ** |
| 4192 | 4218 | ** The code to implement this API is not available in the public release |
| | @@ -4208,10 +4234,29 @@ |
| 4208 | 4234 | SQLITE_API int sqlite3_rekey( |
| 4209 | 4235 | sqlite3 *db, /* Database to be rekeyed */ |
| 4210 | 4236 | const void *pKey, int nKey /* The new key */ |
| 4211 | 4237 | ); |
| 4212 | 4238 | |
| 4239 | +/* |
| 4240 | +** Specify the activation key for a SEE database. Unless |
| 4241 | +** activated, none of the SEE routines will work. |
| 4242 | +*/ |
| 4243 | +SQLITE_API void sqlite3_activate_see( |
| 4244 | + const char *zPassPhrase /* Activation phrase */ |
| 4245 | +); |
| 4246 | +#endif |
| 4247 | + |
| 4248 | +#ifdef SQLITE_ENABLE_CEROD |
| 4249 | +/* |
| 4250 | +** Specify the activation key for a CEROD database. Unless |
| 4251 | +** activated, none of the CEROD routines will work. |
| 4252 | +*/ |
| 4253 | +SQLITE_API void sqlite3_activate_cerod( |
| 4254 | + const char *zPassPhrase /* Activation phrase */ |
| 4255 | +); |
| 4256 | +#endif |
| 4257 | + |
| 4213 | 4258 | /* |
| 4214 | 4259 | ** CAPI3REF: Suspend Execution For A Short Time |
| 4215 | 4260 | ** |
| 4216 | 4261 | ** ^The sqlite3_sleep() function causes the current thread to suspend execution |
| 4217 | 4262 | ** for at least a number of milliseconds specified in its parameter. |
| | @@ -6169,10 +6214,34 @@ |
| 6169 | 6214 | ** case-indendent fashion, using the same definition of case independence |
| 6170 | 6215 | ** that SQLite uses internally when comparing identifiers. |
| 6171 | 6216 | */ |
| 6172 | 6217 | SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); |
| 6173 | 6218 | |
| 6219 | +/* |
| 6220 | +** CAPI3REF: Error Logging Interface |
| 6221 | +** EXPERIMENTAL |
| 6222 | +** |
| 6223 | +** ^The [sqlite3_log()] interface writes a message into the error log |
| 6224 | +** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. |
| 6225 | +** ^If logging is enabled, the zFormat string and subsequent arguments are |
| 6226 | +** passed through to [sqlite3_vmprintf()] to generate the final output string. |
| 6227 | +** |
| 6228 | +** The sqlite3_log() interface is intended for use by extensions such as |
| 6229 | +** virtual tables, collating functions, and SQL functions. While there is |
| 6230 | +** nothing to prevent an application from calling sqlite3_log(), doing so |
| 6231 | +** is considered bad form. |
| 6232 | +** |
| 6233 | +** The zFormat string must not be NULL. |
| 6234 | +** |
| 6235 | +** To avoid deadlocks and other threading problems, the sqlite3_log() routine |
| 6236 | +** will not use dynamically allocated memory. The log message is stored in |
| 6237 | +** a fixed-length buffer on the stack. If the log message is longer than |
| 6238 | +** a few hundred characters, it will be truncated to the length of the |
| 6239 | +** buffer. |
| 6240 | +*/ |
| 6241 | +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); |
| 6242 | + |
| 6174 | 6243 | /* |
| 6175 | 6244 | ** Undo the hack that converts floating point types to integer for |
| 6176 | 6245 | ** builds on processors without floating point support. |
| 6177 | 6246 | */ |
| 6178 | 6247 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| | @@ -6484,24 +6553,10 @@ |
| 6484 | 6553 | #define OMIT_TEMPDB 1 |
| 6485 | 6554 | #else |
| 6486 | 6555 | #define OMIT_TEMPDB 0 |
| 6487 | 6556 | #endif |
| 6488 | 6557 | |
| 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 | 6558 | /* |
| 6504 | 6559 | ** The "file format" number is an integer that is incremented whenever |
| 6505 | 6560 | ** the VDBE-level file format changes. The following macros define the |
| 6506 | 6561 | ** the default file format for new databases and the maximum file format |
| 6507 | 6562 | ** that the library can read. |
| | @@ -6509,10 +6564,14 @@ |
| 6509 | 6564 | #define SQLITE_MAX_FILE_FORMAT 4 |
| 6510 | 6565 | #ifndef SQLITE_DEFAULT_FILE_FORMAT |
| 6511 | 6566 | # define SQLITE_DEFAULT_FILE_FORMAT 1 |
| 6512 | 6567 | #endif |
| 6513 | 6568 | |
| 6569 | +/* |
| 6570 | +** Determine whether triggers are recursive by default. This can be |
| 6571 | +** changed at run-time using a pragma. |
| 6572 | +*/ |
| 6514 | 6573 | #ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS |
| 6515 | 6574 | # define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 |
| 6516 | 6575 | #endif |
| 6517 | 6576 | |
| 6518 | 6577 | /* |
| | @@ -6753,11 +6812,10 @@ |
| 6753 | 6812 | */ |
| 6754 | 6813 | typedef struct AggInfo AggInfo; |
| 6755 | 6814 | typedef struct AuthContext AuthContext; |
| 6756 | 6815 | typedef struct AutoincInfo AutoincInfo; |
| 6757 | 6816 | typedef struct Bitvec Bitvec; |
| 6758 | | -typedef struct RowSet RowSet; |
| 6759 | 6817 | typedef struct CollSeq CollSeq; |
| 6760 | 6818 | typedef struct Column Column; |
| 6761 | 6819 | typedef struct Db Db; |
| 6762 | 6820 | typedef struct Schema Schema; |
| 6763 | 6821 | typedef struct Expr Expr; |
| | @@ -6774,20 +6832,21 @@ |
| 6774 | 6832 | typedef struct Lookaside Lookaside; |
| 6775 | 6833 | typedef struct LookasideSlot LookasideSlot; |
| 6776 | 6834 | typedef struct Module Module; |
| 6777 | 6835 | typedef struct NameContext NameContext; |
| 6778 | 6836 | typedef struct Parse Parse; |
| 6837 | +typedef struct RowSet RowSet; |
| 6779 | 6838 | typedef struct Savepoint Savepoint; |
| 6780 | 6839 | typedef struct Select Select; |
| 6781 | 6840 | typedef struct SrcList SrcList; |
| 6782 | 6841 | typedef struct StrAccum StrAccum; |
| 6783 | 6842 | typedef struct Table Table; |
| 6784 | 6843 | typedef struct TableLock TableLock; |
| 6785 | 6844 | typedef struct Token Token; |
| 6845 | +typedef struct Trigger Trigger; |
| 6786 | 6846 | typedef struct TriggerPrg TriggerPrg; |
| 6787 | 6847 | typedef struct TriggerStep TriggerStep; |
| 6788 | | -typedef struct Trigger Trigger; |
| 6789 | 6848 | typedef struct UnpackedRecord UnpackedRecord; |
| 6790 | 6849 | typedef struct VTable VTable; |
| 6791 | 6850 | typedef struct Walker Walker; |
| 6792 | 6851 | typedef struct WherePlan WherePlan; |
| 6793 | 6852 | typedef struct WhereInfo WhereInfo; |
| | @@ -6881,10 +6940,11 @@ |
| 6881 | 6940 | SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); |
| 6882 | 6941 | SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); |
| 6883 | 6942 | SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); |
| 6884 | 6943 | SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); |
| 6885 | 6944 | SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); |
| 6945 | +SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); |
| 6886 | 6946 | SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); |
| 6887 | 6947 | SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); |
| 6888 | 6948 | SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); |
| 6889 | 6949 | SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); |
| 6890 | 6950 | SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); |
| | @@ -7413,10 +7473,11 @@ |
| 7413 | 7473 | SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); |
| 7414 | 7474 | SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); |
| 7415 | 7475 | SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); |
| 7416 | 7476 | SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); |
| 7417 | 7477 | SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); |
| 7478 | +SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); |
| 7418 | 7479 | SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); |
| 7419 | 7480 | SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int); |
| 7420 | 7481 | SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); |
| 7421 | 7482 | SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); |
| 7422 | 7483 | SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); |
| | @@ -8186,19 +8247,19 @@ |
| 8186 | 8247 | #endif |
| 8187 | 8248 | }; |
| 8188 | 8249 | |
| 8189 | 8250 | /* |
| 8190 | 8251 | ** These macros can be used to test, set, or clear bits in the |
| 8191 | | -** Db.flags field. |
| 8252 | +** Db.pSchema->flags field. |
| 8192 | 8253 | */ |
| 8193 | 8254 | #define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) |
| 8194 | 8255 | #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) |
| 8195 | 8256 | #define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) |
| 8196 | 8257 | #define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) |
| 8197 | 8258 | |
| 8198 | 8259 | /* |
| 8199 | | -** Allowed values for the DB.flags field. |
| 8260 | +** Allowed values for the DB.pSchema->flags field. |
| 8200 | 8261 | ** |
| 8201 | 8262 | ** The DB_SchemaLoaded flag is set after the database schema has been |
| 8202 | 8263 | ** read into internal hash tables. |
| 8203 | 8264 | ** |
| 8204 | 8265 | ** DB_UnresetViews means that one or more views have column names that |
| | @@ -8258,11 +8319,11 @@ |
| 8258 | 8319 | struct FuncDefHash { |
| 8259 | 8320 | FuncDef *a[23]; /* Hash table for functions */ |
| 8260 | 8321 | }; |
| 8261 | 8322 | |
| 8262 | 8323 | /* |
| 8263 | | -** Each database is an instance of the following structure. |
| 8324 | +** Each database connection is an instance of the following structure. |
| 8264 | 8325 | ** |
| 8265 | 8326 | ** The sqlite.lastRowid records the last insert rowid generated by an |
| 8266 | 8327 | ** insert statement. Inserts on views do not affect its value. Each |
| 8267 | 8328 | ** trigger has its own context, so that lastRowid can be updated inside |
| 8268 | 8329 | ** triggers as usual. The previous value will be restored once the trigger |
| | @@ -8297,10 +8358,11 @@ |
| 8297 | 8358 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 8298 | 8359 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 8299 | 8360 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 8300 | 8361 | u8 dfltJournalMode; /* Default journal mode for attached dbs */ |
| 8301 | 8362 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| 8363 | + u8 suppressErr; /* Do not issue error messages if true */ |
| 8302 | 8364 | int nextPagesize; /* Pagesize after VACUUM if >0 */ |
| 8303 | 8365 | int nTable; /* Number of tables in the database */ |
| 8304 | 8366 | CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ |
| 8305 | 8367 | i64 lastRowid; /* ROWID of most recent insert (see above) */ |
| 8306 | 8368 | u32 magic; /* Magic number for detect library misuse */ |
| | @@ -9873,10 +9935,12 @@ |
| 9873 | 9935 | int isMutexInit; /* True after mutexes are initialized */ |
| 9874 | 9936 | int isMallocInit; /* True after malloc is initialized */ |
| 9875 | 9937 | int isPCacheInit; /* True after malloc is initialized */ |
| 9876 | 9938 | sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ |
| 9877 | 9939 | int nRefInitMutex; /* Number of users of pInitMutex */ |
| 9940 | + void (*xLog)(void*,int,const char*); /* Function for logging */ |
| 9941 | + void *pLogArg; /* First argument to xLog() */ |
| 9878 | 9942 | }; |
| 9879 | 9943 | |
| 9880 | 9944 | /* |
| 9881 | 9945 | ** Context pointer passed down through the tree-walk. |
| 9882 | 9946 | */ |
| | @@ -9914,20 +9978,31 @@ |
| 9914 | 9978 | while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ |
| 9915 | 9979 | } \ |
| 9916 | 9980 | } |
| 9917 | 9981 | |
| 9918 | 9982 | /* |
| 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. |
| 9983 | +** The SQLITE_*_BKPT macros are substitutes for the error codes with |
| 9984 | +** the same name but without the _BKPT suffix. These macros invoke |
| 9985 | +** routines that report the line-number on which the error originated |
| 9986 | +** using sqlite3_log(). The routines also provide a convenient place |
| 9987 | +** to set a debugger breakpoint. |
| 9923 | 9988 | */ |
| 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 |
| 9989 | +SQLITE_PRIVATE int sqlite3CorruptError(int); |
| 9990 | +SQLITE_PRIVATE int sqlite3MisuseError(int); |
| 9991 | +SQLITE_PRIVATE int sqlite3CantopenError(int); |
| 9992 | +#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) |
| 9993 | +#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) |
| 9994 | +#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) |
| 9995 | + |
| 9996 | + |
| 9997 | +/* |
| 9998 | +** FTS4 is really an extension for FTS3. It is enabled using the |
| 9999 | +** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all |
| 10000 | +** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3. |
| 10001 | +*/ |
| 10002 | +#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) |
| 10003 | +# define SQLITE_ENABLE_FTS3 |
| 9929 | 10004 | #endif |
| 9930 | 10005 | |
| 9931 | 10006 | /* |
| 9932 | 10007 | ** The ctype.h header is needed for non-ASCII systems. It is also |
| 9933 | 10008 | ** needed by FTS3 when FTS3 is included in the amalgamation. |
| | @@ -10025,11 +10100,15 @@ |
| 10025 | 10100 | |
| 10026 | 10101 | SQLITE_PRIVATE int sqlite3StatusValue(int); |
| 10027 | 10102 | SQLITE_PRIVATE void sqlite3StatusAdd(int, int); |
| 10028 | 10103 | SQLITE_PRIVATE void sqlite3StatusSet(int, int); |
| 10029 | 10104 | |
| 10030 | | -SQLITE_PRIVATE int sqlite3IsNaN(double); |
| 10105 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 10106 | +SQLITE_PRIVATE int sqlite3IsNaN(double); |
| 10107 | +#else |
| 10108 | +# define sqlite3IsNaN(X) 0 |
| 10109 | +#endif |
| 10031 | 10110 | |
| 10032 | 10111 | SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); |
| 10033 | 10112 | #ifndef SQLITE_OMIT_TRACE |
| 10034 | 10113 | SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); |
| 10035 | 10114 | #endif |
| | @@ -10042,11 +10121,10 @@ |
| 10042 | 10121 | #if defined(SQLITE_TEST) |
| 10043 | 10122 | SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); |
| 10044 | 10123 | #endif |
| 10045 | 10124 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...); |
| 10046 | 10125 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); |
| 10047 | | -SQLITE_PRIVATE void sqlite3ErrorClear(Parse*); |
| 10048 | 10126 | SQLITE_PRIVATE int sqlite3Dequote(char*); |
| 10049 | 10127 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); |
| 10050 | 10128 | SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); |
| 10051 | 10129 | SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); |
| 10052 | 10130 | SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); |
| | @@ -10212,17 +10290,10 @@ |
| 10212 | 10290 | SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); |
| 10213 | 10291 | SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); |
| 10214 | 10292 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); |
| 10215 | 10293 | SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); |
| 10216 | 10294 | 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 | 10295 | SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); |
| 10225 | 10296 | SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); |
| 10226 | 10297 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); |
| 10227 | 10298 | |
| 10228 | 10299 | #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) |
| | @@ -10754,10 +10825,12 @@ |
| 10754 | 10825 | 0, /* isMutexInit */ |
| 10755 | 10826 | 0, /* isMallocInit */ |
| 10756 | 10827 | 0, /* isPCacheInit */ |
| 10757 | 10828 | 0, /* pInitMutex */ |
| 10758 | 10829 | 0, /* nRefInitMutex */ |
| 10830 | + 0, /* xLog */ |
| 10831 | + 0, /* pLogArg */ |
| 10759 | 10832 | }; |
| 10760 | 10833 | |
| 10761 | 10834 | |
| 10762 | 10835 | /* |
| 10763 | 10836 | ** Hash table for global functions - functions common to all |
| | @@ -10878,11 +10951,11 @@ |
| 10878 | 10951 | ** then this routine is not threadsafe. |
| 10879 | 10952 | */ |
| 10880 | 10953 | SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ |
| 10881 | 10954 | wsdStatInit; |
| 10882 | 10955 | if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ |
| 10883 | | - return SQLITE_MISUSE; |
| 10956 | + return SQLITE_MISUSE_BKPT; |
| 10884 | 10957 | } |
| 10885 | 10958 | *pCurrent = wsdStat.nowValue[op]; |
| 10886 | 10959 | *pHighwater = wsdStat.mxValue[op]; |
| 10887 | 10960 | if( resetFlag ){ |
| 10888 | 10961 | wsdStat.mxValue[op] = wsdStat.nowValue[op]; |
| | @@ -12007,12 +12080,12 @@ |
| 12007 | 12080 | FUNCTION(current_time, 0, 0, 0, ctimeFunc ), |
| 12008 | 12081 | FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), |
| 12009 | 12082 | FUNCTION(current_date, 0, 0, 0, cdateFunc ), |
| 12010 | 12083 | #else |
| 12011 | 12084 | 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), |
| 12085 | + STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc), |
| 12086 | + STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), |
| 12014 | 12087 | #endif |
| 12015 | 12088 | }; |
| 12016 | 12089 | int i; |
| 12017 | 12090 | FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); |
| 12018 | 12091 | FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs); |
| | @@ -12135,15 +12208,15 @@ |
| 12135 | 12208 | int flags, |
| 12136 | 12209 | int *pFlagsOut |
| 12137 | 12210 | ){ |
| 12138 | 12211 | int rc; |
| 12139 | 12212 | DO_OS_MALLOC_TEST(0); |
| 12140 | | - /* 0x7f1f is a mask of SQLITE_OPEN_ flags that are valid to be passed |
| 12213 | + /* 0x7f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed |
| 12141 | 12214 | ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, |
| 12142 | 12215 | ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before |
| 12143 | 12216 | ** reaching the VFS. */ |
| 12144 | | - rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f1f, pFlagsOut); |
| 12217 | + rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f3f, pFlagsOut); |
| 12145 | 12218 | assert( rc==SQLITE_OK || pFile->pMethods==0 ); |
| 12146 | 12219 | return rc; |
| 12147 | 12220 | } |
| 12148 | 12221 | SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
| 12149 | 12222 | return pVfs->xDelete(pVfs, zPath, dirSync); |
| | @@ -12514,10 +12587,13 @@ |
| 12514 | 12587 | nByte = ROUND8(nByte); |
| 12515 | 12588 | p = malloc( nByte+8 ); |
| 12516 | 12589 | if( p ){ |
| 12517 | 12590 | p[0] = nByte; |
| 12518 | 12591 | p++; |
| 12592 | + }else{ |
| 12593 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 12594 | + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); |
| 12519 | 12595 | } |
| 12520 | 12596 | return (void *)p; |
| 12521 | 12597 | } |
| 12522 | 12598 | |
| 12523 | 12599 | /* |
| | @@ -12532,10 +12608,22 @@ |
| 12532 | 12608 | sqlite3_int64 *p = (sqlite3_int64*)pPrior; |
| 12533 | 12609 | assert( pPrior!=0 ); |
| 12534 | 12610 | p--; |
| 12535 | 12611 | free(p); |
| 12536 | 12612 | } |
| 12613 | + |
| 12614 | +/* |
| 12615 | +** Report the allocated size of a prior return from xMalloc() |
| 12616 | +** or xRealloc(). |
| 12617 | +*/ |
| 12618 | +static int sqlite3MemSize(void *pPrior){ |
| 12619 | + sqlite3_int64 *p; |
| 12620 | + if( pPrior==0 ) return 0; |
| 12621 | + p = (sqlite3_int64*)pPrior; |
| 12622 | + p--; |
| 12623 | + return (int)p[0]; |
| 12624 | +} |
| 12537 | 12625 | |
| 12538 | 12626 | /* |
| 12539 | 12627 | ** Like realloc(). Resize an allocation previously obtained from |
| 12540 | 12628 | ** sqlite3MemMalloc(). |
| 12541 | 12629 | ** |
| | @@ -12547,32 +12635,24 @@ |
| 12547 | 12635 | */ |
| 12548 | 12636 | static void *sqlite3MemRealloc(void *pPrior, int nByte){ |
| 12549 | 12637 | sqlite3_int64 *p = (sqlite3_int64*)pPrior; |
| 12550 | 12638 | assert( pPrior!=0 && nByte>0 ); |
| 12551 | 12639 | nByte = ROUND8(nByte); |
| 12552 | | - p = (sqlite3_int64*)pPrior; |
| 12553 | 12640 | p--; |
| 12554 | 12641 | p = realloc(p, nByte+8 ); |
| 12555 | 12642 | if( p ){ |
| 12556 | 12643 | p[0] = nByte; |
| 12557 | 12644 | p++; |
| 12645 | + }else{ |
| 12646 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 12647 | + sqlite3_log(SQLITE_NOMEM, |
| 12648 | + "failed memory resize %u to %u bytes", |
| 12649 | + sqlite3MemSize(pPrior), nByte); |
| 12558 | 12650 | } |
| 12559 | 12651 | return (void*)p; |
| 12560 | 12652 | } |
| 12561 | 12653 | |
| 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 | 12654 | /* |
| 12575 | 12655 | ** Round up a request size to the next valid allocation size. |
| 12576 | 12656 | */ |
| 12577 | 12657 | static int sqlite3MemRoundup(int n){ |
| 12578 | 12658 | return ROUND8(n); |
| | @@ -12825,10 +12905,35 @@ |
| 12825 | 12905 | ** Round up a request size to the next valid allocation size. |
| 12826 | 12906 | */ |
| 12827 | 12907 | static int sqlite3MemRoundup(int n){ |
| 12828 | 12908 | return ROUND8(n); |
| 12829 | 12909 | } |
| 12910 | + |
| 12911 | +/* |
| 12912 | +** Fill a buffer with pseudo-random bytes. This is used to preset |
| 12913 | +** the content of a new memory allocation to unpredictable values and |
| 12914 | +** to clear the content of a freed allocation to unpredictable values. |
| 12915 | +*/ |
| 12916 | +static void randomFill(char *pBuf, int nByte){ |
| 12917 | + unsigned int x, y, r; |
| 12918 | + x = SQLITE_PTR_TO_INT(pBuf); |
| 12919 | + y = nByte | 1; |
| 12920 | + while( nByte >= 4 ){ |
| 12921 | + x = (x>>1) ^ (-(x&1) & 0xd0000001); |
| 12922 | + y = y*1103515245 + 12345; |
| 12923 | + r = x ^ y; |
| 12924 | + *(int*)pBuf = r; |
| 12925 | + pBuf += 4; |
| 12926 | + nByte -= 4; |
| 12927 | + } |
| 12928 | + while( nByte-- > 0 ){ |
| 12929 | + x = (x>>1) ^ (-(x&1) & 0xd0000001); |
| 12930 | + y = y*1103515245 + 12345; |
| 12931 | + r = x ^ y; |
| 12932 | + *(pBuf++) = r & 0xff; |
| 12933 | + } |
| 12934 | +} |
| 12830 | 12935 | |
| 12831 | 12936 | /* |
| 12832 | 12937 | ** Allocate nByte bytes of memory. |
| 12833 | 12938 | */ |
| 12834 | 12939 | static void *sqlite3MemMalloc(int nByte){ |
| | @@ -12876,11 +12981,12 @@ |
| 12876 | 12981 | } |
| 12877 | 12982 | pHdr->iSize = nByte; |
| 12878 | 12983 | adjustStats(nByte, +1); |
| 12879 | 12984 | pInt = (int*)&pHdr[1]; |
| 12880 | 12985 | pInt[nReserve/sizeof(int)] = REARGUARD; |
| 12881 | | - memset(pInt, 0x65, nReserve); |
| 12986 | + randomFill((char*)pInt, nByte); |
| 12987 | + memset(((char*)pInt)+nByte, 0x65, nReserve-nByte); |
| 12882 | 12988 | p = (void*)pInt; |
| 12883 | 12989 | } |
| 12884 | 12990 | sqlite3_mutex_leave(mem.mutex); |
| 12885 | 12991 | return p; |
| 12886 | 12992 | } |
| | @@ -12912,12 +13018,12 @@ |
| 12912 | 13018 | mem.pLast = pHdr->pPrev; |
| 12913 | 13019 | } |
| 12914 | 13020 | z = (char*)pBt; |
| 12915 | 13021 | z -= pHdr->nTitle; |
| 12916 | 13022 | adjustStats(pHdr->iSize, -1); |
| 12917 | | - memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + |
| 12918 | | - pHdr->iSize + sizeof(int) + pHdr->nTitle); |
| 13023 | + randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + |
| 13024 | + pHdr->iSize + sizeof(int) + pHdr->nTitle); |
| 12919 | 13025 | free(z); |
| 12920 | 13026 | sqlite3_mutex_leave(mem.mutex); |
| 12921 | 13027 | } |
| 12922 | 13028 | |
| 12923 | 13029 | /* |
| | @@ -12936,11 +13042,11 @@ |
| 12936 | 13042 | pOldHdr = sqlite3MemsysGetHeader(pPrior); |
| 12937 | 13043 | pNew = sqlite3MemMalloc(nByte); |
| 12938 | 13044 | if( pNew ){ |
| 12939 | 13045 | memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize); |
| 12940 | 13046 | if( nByte>pOldHdr->iSize ){ |
| 12941 | | - memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize); |
| 13047 | + randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize); |
| 12942 | 13048 | } |
| 12943 | 13049 | sqlite3MemFree(pPrior); |
| 12944 | 13050 | } |
| 12945 | 13051 | return pNew; |
| 12946 | 13052 | } |
| | @@ -14017,11 +14123,15 @@ |
| 14017 | 14123 | /* Make sure mem5.aiFreelist[iLogsize] contains at least one free |
| 14018 | 14124 | ** block. If not, then split a block of the next larger power of |
| 14019 | 14125 | ** two in order to create a new free block of size iLogsize. |
| 14020 | 14126 | */ |
| 14021 | 14127 | for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){} |
| 14022 | | - if( iBin>LOGMAX ) return 0; |
| 14128 | + if( iBin>LOGMAX ){ |
| 14129 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 14130 | + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte); |
| 14131 | + return 0; |
| 14132 | + } |
| 14023 | 14133 | i = memsys5UnlinkFirst(iBin); |
| 14024 | 14134 | while( iBin>iLogsize ){ |
| 14025 | 14135 | int newSize; |
| 14026 | 14136 | |
| 14027 | 14137 | iBin--; |
| | @@ -15294,11 +15404,20 @@ |
| 15294 | 15404 | struct sqlite3_mutex { |
| 15295 | 15405 | CRITICAL_SECTION mutex; /* Mutex controlling the lock */ |
| 15296 | 15406 | int id; /* Mutex type */ |
| 15297 | 15407 | int nRef; /* Number of enterances */ |
| 15298 | 15408 | DWORD owner; /* Thread holding this mutex */ |
| 15409 | +#ifdef SQLITE_DEBUG |
| 15410 | + int trace; /* True to trace changes */ |
| 15411 | +#endif |
| 15299 | 15412 | }; |
| 15413 | +#define SQLITE_W32_MUTEX_INITIALIZER { 0 } |
| 15414 | +#ifdef SQLITE_DEBUG |
| 15415 | +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 } |
| 15416 | +#else |
| 15417 | +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0 } |
| 15418 | +#endif |
| 15300 | 15419 | |
| 15301 | 15420 | /* |
| 15302 | 15421 | ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, |
| 15303 | 15422 | ** or WinCE. Return false (zero) for Win95, Win98, or WinME. |
| 15304 | 15423 | ** |
| | @@ -15337,21 +15456,32 @@ |
| 15337 | 15456 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are |
| 15338 | 15457 | ** intended for use only inside assert() statements. |
| 15339 | 15458 | */ |
| 15340 | 15459 | static int winMutexHeld(sqlite3_mutex *p){ |
| 15341 | 15460 | return p->nRef!=0 && p->owner==GetCurrentThreadId(); |
| 15461 | +} |
| 15462 | +static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){ |
| 15463 | + return p->nRef==0 || p->owner!=tid; |
| 15342 | 15464 | } |
| 15343 | 15465 | static int winMutexNotheld(sqlite3_mutex *p){ |
| 15344 | | - return p->nRef==0 || p->owner!=GetCurrentThreadId(); |
| 15466 | + DWORD tid = GetCurrentThreadId(); |
| 15467 | + return winMutexNotheld2(p, tid); |
| 15345 | 15468 | } |
| 15346 | 15469 | #endif |
| 15347 | 15470 | |
| 15348 | 15471 | |
| 15349 | 15472 | /* |
| 15350 | 15473 | ** Initialize and deinitialize the mutex subsystem. |
| 15351 | 15474 | */ |
| 15352 | | -static sqlite3_mutex winMutex_staticMutexes[6]; |
| 15475 | +static sqlite3_mutex winMutex_staticMutexes[6] = { |
| 15476 | + SQLITE3_MUTEX_INITIALIZER, |
| 15477 | + SQLITE3_MUTEX_INITIALIZER, |
| 15478 | + SQLITE3_MUTEX_INITIALIZER, |
| 15479 | + SQLITE3_MUTEX_INITIALIZER, |
| 15480 | + SQLITE3_MUTEX_INITIALIZER, |
| 15481 | + SQLITE3_MUTEX_INITIALIZER |
| 15482 | +}; |
| 15353 | 15483 | static int winMutex_isInit = 0; |
| 15354 | 15484 | /* As winMutexInit() and winMutexEnd() are called as part |
| 15355 | 15485 | ** of the sqlite3_initialize and sqlite3_shutdown() |
| 15356 | 15486 | ** processing, the "interlocked" magic is probably not |
| 15357 | 15487 | ** strictly necessary. |
| | @@ -15481,18 +15611,25 @@ |
| 15481 | 15611 | ** mutex must be exited an equal number of times before another thread |
| 15482 | 15612 | ** can enter. If the same thread tries to enter any other kind of mutex |
| 15483 | 15613 | ** more than once, the behavior is undefined. |
| 15484 | 15614 | */ |
| 15485 | 15615 | static void winMutexEnter(sqlite3_mutex *p){ |
| 15486 | | - assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); |
| 15616 | + DWORD tid = GetCurrentThreadId(); |
| 15617 | + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); |
| 15487 | 15618 | EnterCriticalSection(&p->mutex); |
| 15488 | | - p->owner = GetCurrentThreadId(); |
| 15619 | + p->owner = tid; |
| 15489 | 15620 | p->nRef++; |
| 15621 | +#ifdef SQLITE_DEBUG |
| 15622 | + if( p->trace ){ |
| 15623 | + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); |
| 15624 | + } |
| 15625 | +#endif |
| 15490 | 15626 | } |
| 15491 | 15627 | static int winMutexTry(sqlite3_mutex *p){ |
| 15628 | + DWORD tid = GetCurrentThreadId(); |
| 15492 | 15629 | int rc = SQLITE_BUSY; |
| 15493 | | - assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); |
| 15630 | + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); |
| 15494 | 15631 | /* |
| 15495 | 15632 | ** The sqlite3_mutex_try() routine is very rarely used, and when it |
| 15496 | 15633 | ** is used it is merely an optimization. So it is OK for it to always |
| 15497 | 15634 | ** fail. |
| 15498 | 15635 | ** |
| | @@ -15502,16 +15639,21 @@ |
| 15502 | 15639 | ** For that reason, we will omit this optimization for now. See |
| 15503 | 15640 | ** ticket #2685. |
| 15504 | 15641 | */ |
| 15505 | 15642 | #if 0 |
| 15506 | 15643 | if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){ |
| 15507 | | - p->owner = GetCurrentThreadId(); |
| 15644 | + p->owner = tid; |
| 15508 | 15645 | p->nRef++; |
| 15509 | 15646 | rc = SQLITE_OK; |
| 15510 | 15647 | } |
| 15511 | 15648 | #else |
| 15512 | 15649 | UNUSED_PARAMETER(p); |
| 15650 | +#endif |
| 15651 | +#ifdef SQLITE_DEBUG |
| 15652 | + if( rc==SQLITE_OK && p->trace ){ |
| 15653 | + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); |
| 15654 | + } |
| 15513 | 15655 | #endif |
| 15514 | 15656 | return rc; |
| 15515 | 15657 | } |
| 15516 | 15658 | |
| 15517 | 15659 | /* |
| | @@ -15519,15 +15661,21 @@ |
| 15519 | 15661 | ** previously entered by the same thread. The behavior |
| 15520 | 15662 | ** is undefined if the mutex is not currently entered or |
| 15521 | 15663 | ** is not currently allocated. SQLite will never do either. |
| 15522 | 15664 | */ |
| 15523 | 15665 | static void winMutexLeave(sqlite3_mutex *p){ |
| 15666 | + DWORD tid = GetCurrentThreadId(); |
| 15524 | 15667 | assert( p->nRef>0 ); |
| 15525 | | - assert( p->owner==GetCurrentThreadId() ); |
| 15668 | + assert( p->owner==tid ); |
| 15526 | 15669 | p->nRef--; |
| 15527 | 15670 | assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); |
| 15528 | 15671 | LeaveCriticalSection(&p->mutex); |
| 15672 | +#ifdef SQLITE_DEBUG |
| 15673 | + if( p->trace ){ |
| 15674 | + printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); |
| 15675 | + } |
| 15676 | +#endif |
| 15529 | 15677 | } |
| 15530 | 15678 | |
| 15531 | 15679 | SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ |
| 15532 | 15680 | static sqlite3_mutex_methods sMutex = { |
| 15533 | 15681 | winMutexInit, |
| | @@ -16722,11 +16870,13 @@ |
| 16722 | 16870 | break; |
| 16723 | 16871 | case etFLOAT: |
| 16724 | 16872 | case etEXP: |
| 16725 | 16873 | case etGENERIC: |
| 16726 | 16874 | realvalue = va_arg(ap,double); |
| 16727 | | -#ifndef SQLITE_OMIT_FLOATING_POINT |
| 16875 | +#ifdef SQLITE_OMIT_FLOATING_POINT |
| 16876 | + length = 0; |
| 16877 | +#else |
| 16728 | 16878 | if( precision<0 ) precision = 6; /* Set default precision */ |
| 16729 | 16879 | if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10; |
| 16730 | 16880 | if( realvalue<0.0 ){ |
| 16731 | 16881 | realvalue = -realvalue; |
| 16732 | 16882 | prefix = '-'; |
| | @@ -16868,11 +17018,11 @@ |
| 16868 | 17018 | } |
| 16869 | 17019 | i = prefix!=0; |
| 16870 | 17020 | while( nPad-- ) bufpt[i++] = '0'; |
| 16871 | 17021 | length = width; |
| 16872 | 17022 | } |
| 16873 | | -#endif |
| 17023 | +#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */ |
| 16874 | 17024 | break; |
| 16875 | 17025 | case etSIZE: |
| 16876 | 17026 | *(va_arg(ap,int*)) = pAccum->nChar; |
| 16877 | 17027 | length = width = 0; |
| 16878 | 17028 | break; |
| | @@ -16915,11 +17065,11 @@ |
| 16915 | 17065 | char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ |
| 16916 | 17066 | char *escarg = va_arg(ap,char*); |
| 16917 | 17067 | isnull = escarg==0; |
| 16918 | 17068 | if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); |
| 16919 | 17069 | k = precision; |
| 16920 | | - for(i=n=0; (ch=escarg[i])!=0 && k!=0; i++, k--){ |
| 17070 | + for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){ |
| 16921 | 17071 | if( ch==q ) n++; |
| 16922 | 17072 | } |
| 16923 | 17073 | needQuote = !isnull && xtype==etSQLESCAPE2; |
| 16924 | 17074 | n += i + 1 + needQuote*2; |
| 16925 | 17075 | if( n>etBUFSIZE ){ |
| | @@ -17198,10 +17348,42 @@ |
| 17198 | 17348 | sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 17199 | 17349 | va_end(ap); |
| 17200 | 17350 | z = sqlite3StrAccumFinish(&acc); |
| 17201 | 17351 | return z; |
| 17202 | 17352 | } |
| 17353 | + |
| 17354 | +/* |
| 17355 | +** This is the routine that actually formats the sqlite3_log() message. |
| 17356 | +** We house it in a separate routine from sqlite3_log() to avoid using |
| 17357 | +** stack space on small-stack systems when logging is disabled. |
| 17358 | +** |
| 17359 | +** sqlite3_log() must render into a static buffer. It cannot dynamically |
| 17360 | +** allocate memory because it might be called while the memory allocator |
| 17361 | +** mutex is held. |
| 17362 | +*/ |
| 17363 | +static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ |
| 17364 | + StrAccum acc; /* String accumulator */ |
| 17365 | + char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ |
| 17366 | + |
| 17367 | + sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0); |
| 17368 | + acc.useMalloc = 0; |
| 17369 | + sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 17370 | + sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, |
| 17371 | + sqlite3StrAccumFinish(&acc)); |
| 17372 | +} |
| 17373 | + |
| 17374 | +/* |
| 17375 | +** Format and write a message to the log if logging is enabled. |
| 17376 | +*/ |
| 17377 | +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){ |
| 17378 | + va_list ap; /* Vararg list */ |
| 17379 | + if( sqlite3GlobalConfig.xLog ){ |
| 17380 | + va_start(ap, zFormat); |
| 17381 | + renderLogMsg(iErrCode, zFormat, ap); |
| 17382 | + va_end(ap); |
| 17383 | + } |
| 17384 | +} |
| 17203 | 17385 | |
| 17204 | 17386 | #if defined(SQLITE_DEBUG) |
| 17205 | 17387 | /* |
| 17206 | 17388 | ** A version of printf() that understands %lld. Used for debugging. |
| 17207 | 17389 | ** The printf() built into some versions of windows does not understand %lld |
| | @@ -17721,10 +17903,11 @@ |
| 17721 | 17903 | int rc; /* Value to return */ |
| 17722 | 17904 | char *zErrMsg; /* Error message written here */ |
| 17723 | 17905 | u8 explain; /* True if EXPLAIN present on SQL command */ |
| 17724 | 17906 | u8 changeCntOn; /* True to update the change-counter */ |
| 17725 | 17907 | u8 expired; /* True if the VM needs to be recompiled */ |
| 17908 | + u8 runOnlyOnce; /* Automatically expire on reset */ |
| 17726 | 17909 | u8 minWriteFileFormat; /* Minimum file format for writable database files */ |
| 17727 | 17910 | u8 inVtabMethod; /* See comments above */ |
| 17728 | 17911 | u8 usesStmtJournal; /* True if uses a statement journal */ |
| 17729 | 17912 | u8 readOnly; /* True for read-only statements */ |
| 17730 | 17913 | u8 isPrepareV2; /* True if prepared with prepare_v2() */ |
| | @@ -17782,11 +17965,15 @@ |
| 17782 | 17965 | SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); |
| 17783 | 17966 | SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); |
| 17784 | 17967 | SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); |
| 17785 | 17968 | SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); |
| 17786 | 17969 | SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); |
| 17787 | | -SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); |
| 17970 | +#ifdef SQLITE_OMIT_FLOATING_POINT |
| 17971 | +# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 |
| 17972 | +#else |
| 17973 | +SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); |
| 17974 | +#endif |
| 17788 | 17975 | SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); |
| 17789 | 17976 | SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); |
| 17790 | 17977 | SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); |
| 17791 | 17978 | SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); |
| 17792 | 17979 | SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int); |
| | @@ -18388,10 +18575,11 @@ |
| 18388 | 18575 | static int dummy = 0; |
| 18389 | 18576 | dummy += x; |
| 18390 | 18577 | } |
| 18391 | 18578 | #endif |
| 18392 | 18579 | |
| 18580 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 18393 | 18581 | /* |
| 18394 | 18582 | ** Return true if the floating point value is Not a Number (NaN). |
| 18395 | 18583 | ** |
| 18396 | 18584 | ** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN. |
| 18397 | 18585 | ** Otherwise, we have our own implementation that works on most systems. |
| | @@ -18432,10 +18620,11 @@ |
| 18432 | 18620 | rc = isnan(x); |
| 18433 | 18621 | #endif /* SQLITE_HAVE_ISNAN */ |
| 18434 | 18622 | testcase( rc ); |
| 18435 | 18623 | return rc; |
| 18436 | 18624 | } |
| 18625 | +#endif /* SQLITE_OMIT_FLOATING_POINT */ |
| 18437 | 18626 | |
| 18438 | 18627 | /* |
| 18439 | 18628 | ** Compute a string length that is limited to what can be stored in |
| 18440 | 18629 | ** lower 30 bits of a 32-bit signed integer. |
| 18441 | 18630 | ** |
| | @@ -18503,27 +18692,24 @@ |
| 18503 | 18692 | ** stored by this function into the database handle using sqlite3Error(). |
| 18504 | 18693 | ** Function sqlite3Error() should be used during statement execution |
| 18505 | 18694 | ** (sqlite3_step() etc.). |
| 18506 | 18695 | */ |
| 18507 | 18696 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ |
| 18697 | + char *zMsg; |
| 18508 | 18698 | va_list ap; |
| 18509 | 18699 | sqlite3 *db = pParse->db; |
| 18510 | | - pParse->nErr++; |
| 18511 | | - sqlite3DbFree(db, pParse->zErrMsg); |
| 18512 | 18700 | va_start(ap, zFormat); |
| 18513 | | - pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap); |
| 18701 | + zMsg = sqlite3VMPrintf(db, zFormat, ap); |
| 18514 | 18702 | 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; |
| 18703 | + if( db->suppressErr ){ |
| 18704 | + sqlite3DbFree(db, zMsg); |
| 18705 | + }else{ |
| 18706 | + pParse->nErr++; |
| 18707 | + sqlite3DbFree(db, pParse->zErrMsg); |
| 18708 | + pParse->zErrMsg = zMsg; |
| 18709 | + pParse->rc = SQLITE_ERROR; |
| 18710 | + } |
| 18525 | 18711 | } |
| 18526 | 18712 | |
| 18527 | 18713 | /* |
| 18528 | 18714 | ** Convert an SQL-style quoted string into a normal string by removing |
| 18529 | 18715 | ** the quote characters. The conversion is done in-place. If the |
| | @@ -18612,10 +18798,11 @@ |
| 18612 | 18798 | return 0; |
| 18613 | 18799 | } |
| 18614 | 18800 | z += incr; |
| 18615 | 18801 | *realnum = 0; |
| 18616 | 18802 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18803 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 18617 | 18804 | if( *z=='.' ){ |
| 18618 | 18805 | z += incr; |
| 18619 | 18806 | if( !sqlite3Isdigit(*z) ) return 0; |
| 18620 | 18807 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18621 | 18808 | *realnum = 1; |
| | @@ -18625,10 +18812,11 @@ |
| 18625 | 18812 | if( *z=='+' || *z=='-' ) z += incr; |
| 18626 | 18813 | if( !sqlite3Isdigit(*z) ) return 0; |
| 18627 | 18814 | while( sqlite3Isdigit(*z) ){ z += incr; } |
| 18628 | 18815 | *realnum = 1; |
| 18629 | 18816 | } |
| 18817 | +#endif |
| 18630 | 18818 | return *z==0; |
| 18631 | 18819 | } |
| 18632 | 18820 | |
| 18633 | 18821 | /* |
| 18634 | 18822 | ** The string z[] is an ASCII representation of a real number. |
| | @@ -18786,10 +18974,13 @@ |
| 18786 | 18974 | static int compare2pow63(const char *zNum){ |
| 18787 | 18975 | int c; |
| 18788 | 18976 | c = memcmp(zNum,"922337203685477580",18)*10; |
| 18789 | 18977 | if( c==0 ){ |
| 18790 | 18978 | c = zNum[18] - '8'; |
| 18979 | + testcase( c==(-1) ); |
| 18980 | + testcase( c==0 ); |
| 18981 | + testcase( c==(+1) ); |
| 18791 | 18982 | } |
| 18792 | 18983 | return c; |
| 18793 | 18984 | } |
| 18794 | 18985 | |
| 18795 | 18986 | |
| | @@ -18822,10 +19013,13 @@ |
| 18822 | 19013 | while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */ |
| 18823 | 19014 | for(i=0; (c=zNum[i])>='0' && c<='9'; i++){ |
| 18824 | 19015 | v = v*10 + c - '0'; |
| 18825 | 19016 | } |
| 18826 | 19017 | *pNum = neg ? -v : v; |
| 19018 | + testcase( i==18 ); |
| 19019 | + testcase( i==19 ); |
| 19020 | + testcase( i==20 ); |
| 18827 | 19021 | if( c!=0 || (i==0 && zStart==zNum) || i>19 ){ |
| 18828 | 19022 | /* zNum is empty or contains non-numeric text or is longer |
| 18829 | 19023 | ** than 19 digits (thus guaranting that it is too large) */ |
| 18830 | 19024 | return 0; |
| 18831 | 19025 | }else if( i<19 ){ |
| | @@ -18865,10 +19059,13 @@ |
| 18865 | 19059 | if( negFlag ) neg = 1-neg; |
| 18866 | 19060 | while( *zNum=='0' ){ |
| 18867 | 19061 | zNum++; /* Skip leading zeros. Ticket #2454 */ |
| 18868 | 19062 | } |
| 18869 | 19063 | for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); } |
| 19064 | + testcase( i==18 ); |
| 19065 | + testcase( i==19 ); |
| 19066 | + testcase( i==20 ); |
| 18870 | 19067 | if( i<19 ){ |
| 18871 | 19068 | /* Guaranteed to fit if less than 19 digits */ |
| 18872 | 19069 | return 1; |
| 18873 | 19070 | }else if( i>19 ){ |
| 18874 | 19071 | /* Guaranteed to be too big if greater than 19 digits */ |
| | @@ -18905,13 +19102,15 @@ |
| 18905 | 19102 | /* The longest decimal representation of a 32 bit integer is 10 digits: |
| 18906 | 19103 | ** |
| 18907 | 19104 | ** 1234567890 |
| 18908 | 19105 | ** 2^31 -> 2147483648 |
| 18909 | 19106 | */ |
| 19107 | + testcase( i==10 ); |
| 18910 | 19108 | if( i>10 ){ |
| 18911 | 19109 | return 0; |
| 18912 | 19110 | } |
| 19111 | + testcase( v-neg==2147483647 ); |
| 18913 | 19112 | if( v-neg>2147483647 ){ |
| 18914 | 19113 | return 0; |
| 18915 | 19114 | } |
| 18916 | 19115 | if( neg ){ |
| 18917 | 19116 | v = -v; |
| | @@ -18994,10 +19193,23 @@ |
| 18994 | 19193 | p[1] = (u8)(v & 0x7f); |
| 18995 | 19194 | return 2; |
| 18996 | 19195 | } |
| 18997 | 19196 | return sqlite3PutVarint(p, v); |
| 18998 | 19197 | } |
| 19198 | + |
| 19199 | +/* |
| 19200 | +** Bitmasks used by sqlite3GetVarint(). These precomputed constants |
| 19201 | +** are defined here rather than simply putting the constant expressions |
| 19202 | +** inline in order to work around bugs in the RVT compiler. |
| 19203 | +** |
| 19204 | +** SLOT_2_0 A mask for (0x7f<<14) | 0x7f |
| 19205 | +** |
| 19206 | +** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0 |
| 19207 | +*/ |
| 19208 | +#define SLOT_2_0 0x001fc07f |
| 19209 | +#define SLOT_4_2_0 0xf01fc07f |
| 19210 | + |
| 18999 | 19211 | |
| 19000 | 19212 | /* |
| 19001 | 19213 | ** Read a 64-bit variable-length integer from memory starting at p[0]. |
| 19002 | 19214 | ** Return the number of bytes read. The value is stored in *v. |
| 19003 | 19215 | */ |
| | @@ -19022,33 +19234,37 @@ |
| 19022 | 19234 | a |= b; |
| 19023 | 19235 | *v = a; |
| 19024 | 19236 | return 2; |
| 19025 | 19237 | } |
| 19026 | 19238 | |
| 19239 | + /* Verify that constants are precomputed correctly */ |
| 19240 | + assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) ); |
| 19241 | + assert( SLOT_4_2_0 == ((0xf<<28) | (0x7f<<14) | (0x7f)) ); |
| 19242 | + |
| 19027 | 19243 | p++; |
| 19028 | 19244 | a = a<<14; |
| 19029 | 19245 | a |= *p; |
| 19030 | 19246 | /* a: p0<<14 | p2 (unmasked) */ |
| 19031 | 19247 | if (!(a&0x80)) |
| 19032 | 19248 | { |
| 19033 | | - a &= (0x7f<<14)|(0x7f); |
| 19249 | + a &= SLOT_2_0; |
| 19034 | 19250 | b &= 0x7f; |
| 19035 | 19251 | b = b<<7; |
| 19036 | 19252 | a |= b; |
| 19037 | 19253 | *v = a; |
| 19038 | 19254 | return 3; |
| 19039 | 19255 | } |
| 19040 | 19256 | |
| 19041 | 19257 | /* CSE1 from below */ |
| 19042 | | - a &= (0x7f<<14)|(0x7f); |
| 19258 | + a &= SLOT_2_0; |
| 19043 | 19259 | p++; |
| 19044 | 19260 | b = b<<14; |
| 19045 | 19261 | b |= *p; |
| 19046 | 19262 | /* b: p1<<14 | p3 (unmasked) */ |
| 19047 | 19263 | if (!(b&0x80)) |
| 19048 | 19264 | { |
| 19049 | | - b &= (0x7f<<14)|(0x7f); |
| 19265 | + b &= SLOT_2_0; |
| 19050 | 19266 | /* moved CSE1 up */ |
| 19051 | 19267 | /* a &= (0x7f<<14)|(0x7f); */ |
| 19052 | 19268 | a = a<<7; |
| 19053 | 19269 | a |= b; |
| 19054 | 19270 | *v = a; |
| | @@ -19058,11 +19274,11 @@ |
| 19058 | 19274 | /* a: p0<<14 | p2 (masked) */ |
| 19059 | 19275 | /* b: p1<<14 | p3 (unmasked) */ |
| 19060 | 19276 | /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ |
| 19061 | 19277 | /* moved CSE1 up */ |
| 19062 | 19278 | /* a &= (0x7f<<14)|(0x7f); */ |
| 19063 | | - b &= (0x7f<<14)|(0x7f); |
| 19279 | + b &= SLOT_2_0; |
| 19064 | 19280 | s = a; |
| 19065 | 19281 | /* s: p0<<14 | p2 (masked) */ |
| 19066 | 19282 | |
| 19067 | 19283 | p++; |
| 19068 | 19284 | a = a<<14; |
| | @@ -19091,11 +19307,11 @@ |
| 19091 | 19307 | /* b: p1<<28 | p3<<14 | p5 (unmasked) */ |
| 19092 | 19308 | if (!(b&0x80)) |
| 19093 | 19309 | { |
| 19094 | 19310 | /* we can skip this cause it was (effectively) done above in calc'ing s */ |
| 19095 | 19311 | /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ |
| 19096 | | - a &= (0x7f<<14)|(0x7f); |
| 19312 | + a &= SLOT_2_0; |
| 19097 | 19313 | a = a<<7; |
| 19098 | 19314 | a |= b; |
| 19099 | 19315 | s = s>>18; |
| 19100 | 19316 | *v = ((u64)s)<<32 | a; |
| 19101 | 19317 | return 6; |
| | @@ -19105,28 +19321,28 @@ |
| 19105 | 19321 | a = a<<14; |
| 19106 | 19322 | a |= *p; |
| 19107 | 19323 | /* a: p2<<28 | p4<<14 | p6 (unmasked) */ |
| 19108 | 19324 | if (!(a&0x80)) |
| 19109 | 19325 | { |
| 19110 | | - a &= (0x1f<<28)|(0x7f<<14)|(0x7f); |
| 19111 | | - b &= (0x7f<<14)|(0x7f); |
| 19326 | + a &= SLOT_4_2_0; |
| 19327 | + b &= SLOT_2_0; |
| 19112 | 19328 | b = b<<7; |
| 19113 | 19329 | a |= b; |
| 19114 | 19330 | s = s>>11; |
| 19115 | 19331 | *v = ((u64)s)<<32 | a; |
| 19116 | 19332 | return 7; |
| 19117 | 19333 | } |
| 19118 | 19334 | |
| 19119 | 19335 | /* CSE2 from below */ |
| 19120 | | - a &= (0x7f<<14)|(0x7f); |
| 19336 | + a &= SLOT_2_0; |
| 19121 | 19337 | p++; |
| 19122 | 19338 | b = b<<14; |
| 19123 | 19339 | b |= *p; |
| 19124 | 19340 | /* b: p3<<28 | p5<<14 | p7 (unmasked) */ |
| 19125 | 19341 | if (!(b&0x80)) |
| 19126 | 19342 | { |
| 19127 | | - b &= (0x1f<<28)|(0x7f<<14)|(0x7f); |
| 19343 | + b &= SLOT_4_2_0; |
| 19128 | 19344 | /* moved CSE2 up */ |
| 19129 | 19345 | /* a &= (0x7f<<14)|(0x7f); */ |
| 19130 | 19346 | a = a<<7; |
| 19131 | 19347 | a |= b; |
| 19132 | 19348 | s = s>>4; |
| | @@ -19139,11 +19355,11 @@ |
| 19139 | 19355 | a |= *p; |
| 19140 | 19356 | /* a: p4<<29 | p6<<15 | p8 (unmasked) */ |
| 19141 | 19357 | |
| 19142 | 19358 | /* moved CSE2 up */ |
| 19143 | 19359 | /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */ |
| 19144 | | - b &= (0x7f<<14)|(0x7f); |
| 19360 | + b &= SLOT_2_0; |
| 19145 | 19361 | b = b<<8; |
| 19146 | 19362 | a |= b; |
| 19147 | 19363 | |
| 19148 | 19364 | s = s<<4; |
| 19149 | 19365 | b = p[-4]; |
| | @@ -19259,13 +19475,13 @@ |
| 19259 | 19475 | a = a<<14; |
| 19260 | 19476 | a |= *p; |
| 19261 | 19477 | /* a: p0<<28 | p2<<14 | p4 (unmasked) */ |
| 19262 | 19478 | if (!(a&0x80)) |
| 19263 | 19479 | { |
| 19264 | | - /* Walues between 268435456 and 34359738367 */ |
| 19265 | | - a &= (0x1f<<28)|(0x7f<<14)|(0x7f); |
| 19266 | | - b &= (0x1f<<28)|(0x7f<<14)|(0x7f); |
| 19480 | + /* Values between 268435456 and 34359738367 */ |
| 19481 | + a &= SLOT_4_2_0; |
| 19482 | + b &= SLOT_4_2_0; |
| 19267 | 19483 | b = b<<7; |
| 19268 | 19484 | *v = a | b; |
| 19269 | 19485 | return 5; |
| 19270 | 19486 | } |
| 19271 | 19487 | |
| | @@ -19354,68 +19570,21 @@ |
| 19354 | 19570 | } |
| 19355 | 19571 | return zBlob; |
| 19356 | 19572 | } |
| 19357 | 19573 | #endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */ |
| 19358 | 19574 | |
| 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 |
| 19575 | +/* |
| 19576 | +** Log an error that is an API call on a connection pointer that should |
| 19577 | +** not have been used. The "type" of connection pointer is given as the |
| 19578 | +** argument. The zType is a word like "NULL" or "closed" or "invalid". |
| 19579 | +*/ |
| 19580 | +static void logBadConnection(const char *zType){ |
| 19581 | + sqlite3_log(SQLITE_MISUSE, |
| 19582 | + "API call with %s database connection pointer", |
| 19583 | + zType |
| 19584 | + ); |
| 19585 | +} |
| 19417 | 19586 | |
| 19418 | 19587 | /* |
| 19419 | 19588 | ** Check to make sure we have a valid db pointer. This test is not |
| 19420 | 19589 | ** foolproof but it does provide some measure of protection against |
| 19421 | 19590 | ** misuse of the interface such as passing in db pointers that are |
| | @@ -19429,17 +19598,20 @@ |
| 19429 | 19598 | ** open properly and is not fit for general use but which can be |
| 19430 | 19599 | ** used as an argument to sqlite3_errmsg() or sqlite3_close(). |
| 19431 | 19600 | */ |
| 19432 | 19601 | SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){ |
| 19433 | 19602 | u32 magic; |
| 19434 | | - if( db==0 ) return 0; |
| 19603 | + if( db==0 ){ |
| 19604 | + logBadConnection("NULL"); |
| 19605 | + return 0; |
| 19606 | + } |
| 19435 | 19607 | magic = db->magic; |
| 19436 | | - if( magic!=SQLITE_MAGIC_OPEN |
| 19437 | | -#ifdef SQLITE_DEBUG |
| 19438 | | - && magic!=SQLITE_MAGIC_BUSY |
| 19439 | | -#endif |
| 19440 | | - ){ |
| 19608 | + if( magic!=SQLITE_MAGIC_OPEN ){ |
| 19609 | + if( sqlite3SafetyCheckSickOrOk(db) ){ |
| 19610 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 19611 | + logBadConnection("unopened"); |
| 19612 | + } |
| 19441 | 19613 | return 0; |
| 19442 | 19614 | }else{ |
| 19443 | 19615 | return 1; |
| 19444 | 19616 | } |
| 19445 | 19617 | } |
| | @@ -19446,12 +19618,17 @@ |
| 19446 | 19618 | SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ |
| 19447 | 19619 | u32 magic; |
| 19448 | 19620 | magic = db->magic; |
| 19449 | 19621 | if( magic!=SQLITE_MAGIC_SICK && |
| 19450 | 19622 | magic!=SQLITE_MAGIC_OPEN && |
| 19451 | | - magic!=SQLITE_MAGIC_BUSY ) return 0; |
| 19452 | | - return 1; |
| 19623 | + magic!=SQLITE_MAGIC_BUSY ){ |
| 19624 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 19625 | + logBadConnection("invalid"); |
| 19626 | + return 0; |
| 19627 | + }else{ |
| 19628 | + return 1; |
| 19629 | + } |
| 19453 | 19630 | } |
| 19454 | 19631 | |
| 19455 | 19632 | /************** End of util.c ************************************************/ |
| 19456 | 19633 | /************** Begin file hash.c ********************************************/ |
| 19457 | 19634 | /* |
| | @@ -21365,10 +21542,15 @@ |
| 21365 | 21542 | # include <sys/param.h> |
| 21366 | 21543 | # include <sys/mount.h> |
| 21367 | 21544 | # endif |
| 21368 | 21545 | #endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
| 21369 | 21546 | |
| 21547 | +/* |
| 21548 | +** Allowed values of unixFile.fsFlags |
| 21549 | +*/ |
| 21550 | +#define SQLITE_FSFLAGS_IS_MSDOS 0x1 |
| 21551 | + |
| 21370 | 21552 | /* |
| 21371 | 21553 | ** If we are to be thread-safe, include the pthreads header and define |
| 21372 | 21554 | ** the SQLITE_UNIX_THREADS macro. |
| 21373 | 21555 | */ |
| 21374 | 21556 | #if SQLITE_THREADSAFE |
| | @@ -21431,10 +21613,13 @@ |
| 21431 | 21613 | UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ |
| 21432 | 21614 | int fileFlags; /* Miscellanous flags */ |
| 21433 | 21615 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 21434 | 21616 | int openFlags; /* The flags specified at open() */ |
| 21435 | 21617 | #endif |
| 21618 | +#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) |
| 21619 | + unsigned fsFlags; /* cached details from statfs() */ |
| 21620 | +#endif |
| 21436 | 21621 | #if SQLITE_THREADSAFE && defined(__linux__) |
| 21437 | 21622 | pthread_t tid; /* The thread that "owns" this unixFile */ |
| 21438 | 21623 | #endif |
| 21439 | 21624 | #if OS_VXWORKS |
| 21440 | 21625 | int isDelete; /* Delete on close if true */ |
| | @@ -22198,10 +22383,13 @@ |
| 22198 | 22383 | struct unixLockInfo { |
| 22199 | 22384 | struct unixLockKey lockKey; /* The lookup key */ |
| 22200 | 22385 | int cnt; /* Number of SHARED locks held */ |
| 22201 | 22386 | int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ |
| 22202 | 22387 | int nRef; /* Number of pointers to this structure */ |
| 22388 | +#if defined(SQLITE_ENABLE_LOCKING_STYLE) |
| 22389 | + unsigned long long sharedByte; /* for AFP simulated shared lock */ |
| 22390 | +#endif |
| 22203 | 22391 | struct unixLockInfo *pNext; /* List of all unixLockInfo objects */ |
| 22204 | 22392 | struct unixLockInfo *pPrev; /* .... doubly linked */ |
| 22205 | 22393 | }; |
| 22206 | 22394 | |
| 22207 | 22395 | /* |
| | @@ -22441,13 +22629,14 @@ |
| 22441 | 22629 | ** an ASCII 'S' character which also happens to be the first byte |
| 22442 | 22630 | ** in the header of every SQLite database. In this way, if there |
| 22443 | 22631 | ** is a race condition such that another thread has already populated |
| 22444 | 22632 | ** the first page of the database, no damage is done. |
| 22445 | 22633 | */ |
| 22446 | | - if( statbuf.st_size==0 ){ |
| 22634 | + if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){ |
| 22447 | 22635 | rc = write(fd, "S", 1); |
| 22448 | 22636 | if( rc!=1 ){ |
| 22637 | + pFile->lastErrno = errno; |
| 22449 | 22638 | return SQLITE_IOERR; |
| 22450 | 22639 | } |
| 22451 | 22640 | rc = fstat(fd, &statbuf); |
| 22452 | 22641 | if( rc!=0 ){ |
| 22453 | 22642 | pFile->lastErrno = errno; |
| | @@ -22483,10 +22672,13 @@ |
| 22483 | 22672 | } |
| 22484 | 22673 | memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey)); |
| 22485 | 22674 | pLock->nRef = 1; |
| 22486 | 22675 | pLock->cnt = 0; |
| 22487 | 22676 | pLock->locktype = 0; |
| 22677 | +#if defined(SQLITE_ENABLE_LOCKING_STYLE) |
| 22678 | + pLock->sharedByte = 0; |
| 22679 | +#endif |
| 22488 | 22680 | pLock->pNext = lockList; |
| 22489 | 22681 | pLock->pPrev = 0; |
| 22490 | 22682 | if( lockList ) lockList->pPrev = pLock; |
| 22491 | 22683 | lockList = pLock; |
| 22492 | 22684 | }else{ |
| | @@ -22547,11 +22739,11 @@ |
| 22547 | 22739 | OSTRACE1("No-transfer, same thread\n"); |
| 22548 | 22740 | return SQLITE_OK; |
| 22549 | 22741 | } |
| 22550 | 22742 | if( pFile->locktype!=NO_LOCK ){ |
| 22551 | 22743 | /* We cannot change ownership while we are holding a lock! */ |
| 22552 | | - return SQLITE_MISUSE; |
| 22744 | + return SQLITE_MISUSE_BKPT; |
| 22553 | 22745 | } |
| 22554 | 22746 | OSTRACE4("Transfer ownership of %d from %d to %d\n", |
| 22555 | 22747 | pFile->h, pFile->tid, hSelf); |
| 22556 | 22748 | pFile->tid = hSelf; |
| 22557 | 22749 | if (pFile->pLock != NULL) { |
| | @@ -22613,66 +22805,10 @@ |
| 22613 | 22805 | |
| 22614 | 22806 | unixLeaveMutex(); |
| 22615 | 22807 | OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved); |
| 22616 | 22808 | |
| 22617 | 22809 | *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 | 22810 | return rc; |
| 22675 | 22811 | } |
| 22676 | 22812 | |
| 22677 | 22813 | /* |
| 22678 | 22814 | ** Lock the file with the lock specified by parameter locktype - one |
| | @@ -22740,11 +22876,11 @@ |
| 22740 | 22876 | int rc = SQLITE_OK; |
| 22741 | 22877 | unixFile *pFile = (unixFile*)id; |
| 22742 | 22878 | struct unixLockInfo *pLock = pFile->pLock; |
| 22743 | 22879 | struct flock lock; |
| 22744 | 22880 | int s = 0; |
| 22745 | | - int tErrno; |
| 22881 | + int tErrno = 0; |
| 22746 | 22882 | |
| 22747 | 22883 | assert( pFile ); |
| 22748 | 22884 | OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, |
| 22749 | 22885 | locktypeName(locktype), locktypeName(pFile->locktype), |
| 22750 | 22886 | locktypeName(pLock->locktype), pLock->cnt , getpid()); |
| | @@ -22836,12 +22972,15 @@ |
| 22836 | 22972 | if( locktype==SHARED_LOCK ){ |
| 22837 | 22973 | assert( pLock->cnt==0 ); |
| 22838 | 22974 | assert( pLock->locktype==0 ); |
| 22839 | 22975 | |
| 22840 | 22976 | /* Now get the read-lock */ |
| 22841 | | - s = rangeLock(pFile, F_RDLCK, &tErrno); |
| 22842 | | - |
| 22977 | + lock.l_start = SHARED_FIRST; |
| 22978 | + lock.l_len = SHARED_SIZE; |
| 22979 | + if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){ |
| 22980 | + tErrno = errno; |
| 22981 | + } |
| 22843 | 22982 | /* Drop the temporary PENDING lock */ |
| 22844 | 22983 | lock.l_start = PENDING_BYTE; |
| 22845 | 22984 | lock.l_len = 1L; |
| 22846 | 22985 | lock.l_type = F_UNLCK; |
| 22847 | 22986 | if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ |
| | @@ -22877,20 +23016,21 @@ |
| 22877 | 23016 | assert( 0!=pFile->locktype ); |
| 22878 | 23017 | lock.l_type = F_WRLCK; |
| 22879 | 23018 | switch( locktype ){ |
| 22880 | 23019 | case RESERVED_LOCK: |
| 22881 | 23020 | lock.l_start = RESERVED_BYTE; |
| 22882 | | - s = fcntl(pFile->h, F_SETLK, &lock); |
| 22883 | | - tErrno = errno; |
| 22884 | 23021 | break; |
| 22885 | 23022 | case EXCLUSIVE_LOCK: |
| 22886 | | - s = rangeLock(pFile, F_WRLCK, &tErrno); |
| 23023 | + lock.l_start = SHARED_FIRST; |
| 23024 | + lock.l_len = SHARED_SIZE; |
| 22887 | 23025 | break; |
| 22888 | 23026 | default: |
| 22889 | 23027 | assert(0); |
| 22890 | 23028 | } |
| 23029 | + s = fcntl(pFile->h, F_SETLK, &lock); |
| 22891 | 23030 | if( s==(-1) ){ |
| 23031 | + tErrno = errno; |
| 22892 | 23032 | rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); |
| 22893 | 23033 | if( IS_LOCK_ERROR(rc) ){ |
| 22894 | 23034 | pFile->lastErrno = tErrno; |
| 22895 | 23035 | } |
| 22896 | 23036 | } |
| | @@ -22976,17 +23116,23 @@ |
| 22976 | 23116 | ** Lower the locking level on file descriptor pFile to locktype. locktype |
| 22977 | 23117 | ** must be either NO_LOCK or SHARED_LOCK. |
| 22978 | 23118 | ** |
| 22979 | 23119 | ** If the locking level of the file descriptor is already at or below |
| 22980 | 23120 | ** the requested locking level, this routine is a no-op. |
| 23121 | +** |
| 23122 | +** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED |
| 23123 | +** the byte range is divided into 2 parts and the first part is unlocked then |
| 23124 | +** set to a read lock, then the other part is simply unlocked. This works |
| 23125 | +** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to |
| 23126 | +** remove the write lock on a region when a read lock is set. |
| 22981 | 23127 | */ |
| 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 */ |
| 23128 | +static int _posixUnlock(sqlite3_file *id, int locktype, int handleNFSUnlock){ |
| 23129 | + unixFile *pFile = (unixFile*)id; |
| 23130 | + struct unixLockInfo *pLock; |
| 23131 | + struct flock lock; |
| 23132 | + int rc = SQLITE_OK; |
| 23133 | + int h; |
| 22988 | 23134 | int tErrno; /* Error code from system call errors */ |
| 22989 | 23135 | |
| 22990 | 23136 | assert( pFile ); |
| 22991 | 23137 | OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype, |
| 22992 | 23138 | pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
| | @@ -22994,11 +23140,11 @@ |
| 22994 | 23140 | assert( locktype<=SHARED_LOCK ); |
| 22995 | 23141 | if( pFile->locktype<=locktype ){ |
| 22996 | 23142 | return SQLITE_OK; |
| 22997 | 23143 | } |
| 22998 | 23144 | if( CHECK_THREADID(pFile) ){ |
| 22999 | | - return SQLITE_MISUSE; |
| 23145 | + return SQLITE_MISUSE_BKPT; |
| 23000 | 23146 | } |
| 23001 | 23147 | unixEnterMutex(); |
| 23002 | 23148 | h = pFile->h; |
| 23003 | 23149 | pLock = pFile->pLock; |
| 23004 | 23150 | assert( pLock->cnt!=0 ); |
| | @@ -23021,18 +23167,72 @@ |
| 23021 | 23167 | || pFile->dbUpdate==0 |
| 23022 | 23168 | || pFile->transCntrChng==1 ); |
| 23023 | 23169 | pFile->inNormalWrite = 0; |
| 23024 | 23170 | #endif |
| 23025 | 23171 | |
| 23026 | | - |
| 23172 | + /* downgrading to a shared lock on NFS involves clearing the write lock |
| 23173 | + ** before establishing the readlock - to avoid a race condition we downgrade |
| 23174 | + ** the lock in 2 blocks, so that part of the range will be covered by a |
| 23175 | + ** write lock until the rest is covered by a read lock: |
| 23176 | + ** 1: [WWWWW] |
| 23177 | + ** 2: [....W] |
| 23178 | + ** 3: [RRRRW] |
| 23179 | + ** 4: [RRRR.] |
| 23180 | + */ |
| 23027 | 23181 | 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; |
| 23182 | + if( handleNFSUnlock ){ |
| 23183 | + off_t divSize = SHARED_SIZE - 1; |
| 23184 | + |
| 23185 | + lock.l_type = F_UNLCK; |
| 23186 | + lock.l_whence = SEEK_SET; |
| 23187 | + lock.l_start = SHARED_FIRST; |
| 23188 | + lock.l_len = divSize; |
| 23189 | + if( fcntl(h, F_SETLK, &lock)==(-1) ){ |
| 23190 | + tErrno = errno; |
| 23191 | + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); |
| 23192 | + if( IS_LOCK_ERROR(rc) ){ |
| 23193 | + pFile->lastErrno = tErrno; |
| 23194 | + } |
| 23195 | + goto end_unlock; |
| 23032 | 23196 | } |
| 23033 | | - goto end_unlock; |
| 23197 | + lock.l_type = F_RDLCK; |
| 23198 | + lock.l_whence = SEEK_SET; |
| 23199 | + lock.l_start = SHARED_FIRST; |
| 23200 | + lock.l_len = divSize; |
| 23201 | + if( fcntl(h, F_SETLK, &lock)==(-1) ){ |
| 23202 | + tErrno = errno; |
| 23203 | + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); |
| 23204 | + if( IS_LOCK_ERROR(rc) ){ |
| 23205 | + pFile->lastErrno = tErrno; |
| 23206 | + } |
| 23207 | + goto end_unlock; |
| 23208 | + } |
| 23209 | + lock.l_type = F_UNLCK; |
| 23210 | + lock.l_whence = SEEK_SET; |
| 23211 | + lock.l_start = SHARED_FIRST+divSize; |
| 23212 | + lock.l_len = SHARED_SIZE-divSize; |
| 23213 | + if( fcntl(h, F_SETLK, &lock)==(-1) ){ |
| 23214 | + tErrno = errno; |
| 23215 | + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); |
| 23216 | + if( IS_LOCK_ERROR(rc) ){ |
| 23217 | + pFile->lastErrno = tErrno; |
| 23218 | + } |
| 23219 | + goto end_unlock; |
| 23220 | + } |
| 23221 | + }else{ |
| 23222 | + lock.l_type = F_RDLCK; |
| 23223 | + lock.l_whence = SEEK_SET; |
| 23224 | + lock.l_start = SHARED_FIRST; |
| 23225 | + lock.l_len = SHARED_SIZE; |
| 23226 | + if( fcntl(h, F_SETLK, &lock)==(-1) ){ |
| 23227 | + tErrno = errno; |
| 23228 | + rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); |
| 23229 | + if( IS_LOCK_ERROR(rc) ){ |
| 23230 | + pFile->lastErrno = tErrno; |
| 23231 | + } |
| 23232 | + goto end_unlock; |
| 23233 | + } |
| 23034 | 23234 | } |
| 23035 | 23235 | } |
| 23036 | 23236 | lock.l_type = F_UNLCK; |
| 23037 | 23237 | lock.l_whence = SEEK_SET; |
| 23038 | 23238 | lock.l_start = PENDING_BYTE; |
| | @@ -23094,10 +23294,21 @@ |
| 23094 | 23294 | end_unlock: |
| 23095 | 23295 | unixLeaveMutex(); |
| 23096 | 23296 | if( rc==SQLITE_OK ) pFile->locktype = locktype; |
| 23097 | 23297 | return rc; |
| 23098 | 23298 | } |
| 23299 | + |
| 23300 | +/* |
| 23301 | +** Lower the locking level on file descriptor pFile to locktype. locktype |
| 23302 | +** must be either NO_LOCK or SHARED_LOCK. |
| 23303 | +** |
| 23304 | +** If the locking level of the file descriptor is already at or below |
| 23305 | +** the requested locking level, this routine is a no-op. |
| 23306 | +*/ |
| 23307 | +static int unixUnlock(sqlite3_file *id, int locktype){ |
| 23308 | + return _posixUnlock(id, locktype, 0); |
| 23309 | +} |
| 23099 | 23310 | |
| 23100 | 23311 | /* |
| 23101 | 23312 | ** This function performs the parts of the "close file" operation |
| 23102 | 23313 | ** common to all locking schemes. It closes the directory and file |
| 23103 | 23314 | ** handles, if they are valid, and sets all fields of the unixFile |
| | @@ -23806,11 +24017,11 @@ |
| 23806 | 24017 | /* |
| 23807 | 24018 | ** The afpLockingContext structure contains all afp lock specific state |
| 23808 | 24019 | */ |
| 23809 | 24020 | typedef struct afpLockingContext afpLockingContext; |
| 23810 | 24021 | struct afpLockingContext { |
| 23811 | | - unsigned long long sharedByte; |
| 24022 | + int reserved; |
| 23812 | 24023 | const char *dbPath; /* Name of the open file */ |
| 23813 | 24024 | }; |
| 23814 | 24025 | |
| 23815 | 24026 | struct ByteRangeLockPB2 |
| 23816 | 24027 | { |
| | @@ -23883,13 +24094,18 @@ |
| 23883 | 24094 | |
| 23884 | 24095 | SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); |
| 23885 | 24096 | |
| 23886 | 24097 | assert( pFile ); |
| 23887 | 24098 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 24099 | + if( context->reserved ){ |
| 24100 | + *pResOut = 1; |
| 24101 | + return SQLITE_OK; |
| 24102 | + } |
| 24103 | + unixEnterMutex(); /* Because pFile->pLock is shared across threads */ |
| 23888 | 24104 | |
| 23889 | 24105 | /* Check if a thread in this process holds such a lock */ |
| 23890 | | - if( pFile->locktype>SHARED_LOCK ){ |
| 24106 | + if( pFile->pLock->locktype>SHARED_LOCK ){ |
| 23891 | 24107 | reserved = 1; |
| 23892 | 24108 | } |
| 23893 | 24109 | |
| 23894 | 24110 | /* Otherwise see if some other process holds it. |
| 23895 | 24111 | */ |
| | @@ -23907,10 +24123,11 @@ |
| 23907 | 24123 | if( IS_LOCK_ERROR(lrc) ){ |
| 23908 | 24124 | rc=lrc; |
| 23909 | 24125 | } |
| 23910 | 24126 | } |
| 23911 | 24127 | |
| 24128 | + unixLeaveMutex(); |
| 23912 | 24129 | OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved); |
| 23913 | 24130 | |
| 23914 | 24131 | *pResOut = reserved; |
| 23915 | 24132 | return rc; |
| 23916 | 24133 | } |
| | @@ -23940,15 +24157,17 @@ |
| 23940 | 24157 | ** routine to lower a locking level. |
| 23941 | 24158 | */ |
| 23942 | 24159 | static int afpLock(sqlite3_file *id, int locktype){ |
| 23943 | 24160 | int rc = SQLITE_OK; |
| 23944 | 24161 | unixFile *pFile = (unixFile*)id; |
| 24162 | + struct unixLockInfo *pLock = pFile->pLock; |
| 23945 | 24163 | afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 23946 | 24164 | |
| 23947 | 24165 | assert( pFile ); |
| 23948 | | - OSTRACE5("LOCK %d %s was %s pid=%d (afp)\n", pFile->h, |
| 23949 | | - locktypeName(locktype), locktypeName(pFile->locktype), getpid()); |
| 24166 | + OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h, |
| 24167 | + locktypeName(locktype), locktypeName(pFile->locktype), |
| 24168 | + locktypeName(pLock->locktype), pLock->cnt , getpid()); |
| 23950 | 24169 | |
| 23951 | 24170 | /* If there is already a lock of this type or more restrictive on the |
| 23952 | 24171 | ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as |
| 23953 | 24172 | ** unixEnterMutex() hasn't been called yet. |
| 23954 | 24173 | */ |
| | @@ -23957,10 +24176,13 @@ |
| 23957 | 24176 | locktypeName(locktype)); |
| 23958 | 24177 | return SQLITE_OK; |
| 23959 | 24178 | } |
| 23960 | 24179 | |
| 23961 | 24180 | /* Make sure the locking sequence is correct |
| 24181 | + ** (1) We never move from unlocked to anything higher than shared lock. |
| 24182 | + ** (2) SQLite never explicitly requests a pendig lock. |
| 24183 | + ** (3) A shared lock is always held when a reserve lock is requested. |
| 23962 | 24184 | */ |
| 23963 | 24185 | assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); |
| 23964 | 24186 | assert( locktype!=PENDING_LOCK ); |
| 23965 | 24187 | assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); |
| 23966 | 24188 | |
| | @@ -23972,10 +24194,36 @@ |
| 23972 | 24194 | */ |
| 23973 | 24195 | rc = transferOwnership(pFile); |
| 23974 | 24196 | if( rc!=SQLITE_OK ){ |
| 23975 | 24197 | unixLeaveMutex(); |
| 23976 | 24198 | return rc; |
| 24199 | + } |
| 24200 | + pLock = pFile->pLock; |
| 24201 | + |
| 24202 | + /* If some thread using this PID has a lock via a different unixFile* |
| 24203 | + ** handle that precludes the requested lock, return BUSY. |
| 24204 | + */ |
| 24205 | + if( (pFile->locktype!=pLock->locktype && |
| 24206 | + (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) |
| 24207 | + ){ |
| 24208 | + rc = SQLITE_BUSY; |
| 24209 | + goto afp_end_lock; |
| 24210 | + } |
| 24211 | + |
| 24212 | + /* If a SHARED lock is requested, and some thread using this PID already |
| 24213 | + ** has a SHARED or RESERVED lock, then increment reference counts and |
| 24214 | + ** return SQLITE_OK. |
| 24215 | + */ |
| 24216 | + if( locktype==SHARED_LOCK && |
| 24217 | + (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ |
| 24218 | + assert( locktype==SHARED_LOCK ); |
| 24219 | + assert( pFile->locktype==0 ); |
| 24220 | + assert( pLock->cnt>0 ); |
| 24221 | + pFile->locktype = SHARED_LOCK; |
| 24222 | + pLock->cnt++; |
| 24223 | + pFile->pOpen->nLock++; |
| 24224 | + goto afp_end_lock; |
| 23977 | 24225 | } |
| 23978 | 24226 | |
| 23979 | 24227 | /* A PENDING lock is needed before acquiring a SHARED lock and before |
| 23980 | 24228 | ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will |
| 23981 | 24229 | ** be released. |
| | @@ -23993,19 +24241,23 @@ |
| 23993 | 24241 | |
| 23994 | 24242 | /* If control gets to this point, then actually go ahead and make |
| 23995 | 24243 | ** operating system calls for the specified lock. |
| 23996 | 24244 | */ |
| 23997 | 24245 | if( locktype==SHARED_LOCK ){ |
| 23998 | | - int lk, lrc1, lrc2; |
| 23999 | | - int lrc1Errno = 0; |
| 24246 | + int lrc1, lrc2, lrc1Errno; |
| 24247 | + long lk, mask; |
| 24000 | 24248 | |
| 24249 | + assert( pLock->cnt==0 ); |
| 24250 | + assert( pLock->locktype==0 ); |
| 24251 | + |
| 24252 | + mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff; |
| 24001 | 24253 | /* Now get the read-lock SHARED_LOCK */ |
| 24002 | 24254 | /* note that the quality of the randomness doesn't matter that much */ |
| 24003 | 24255 | lk = random(); |
| 24004 | | - context->sharedByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); |
| 24256 | + pLock->sharedByte = (lk & mask)%(SHARED_SIZE - 1); |
| 24005 | 24257 | lrc1 = afpSetLock(context->dbPath, pFile, |
| 24006 | | - SHARED_FIRST+context->sharedByte, 1, 1); |
| 24258 | + SHARED_FIRST+pLock->sharedByte, 1, 1); |
| 24007 | 24259 | if( IS_LOCK_ERROR(lrc1) ){ |
| 24008 | 24260 | lrc1Errno = pFile->lastErrno; |
| 24009 | 24261 | } |
| 24010 | 24262 | /* Drop the temporary PENDING lock */ |
| 24011 | 24263 | lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); |
| | @@ -24020,11 +24272,16 @@ |
| 24020 | 24272 | } else if( lrc1 != SQLITE_OK ) { |
| 24021 | 24273 | rc = lrc1; |
| 24022 | 24274 | } else { |
| 24023 | 24275 | pFile->locktype = SHARED_LOCK; |
| 24024 | 24276 | pFile->pOpen->nLock++; |
| 24277 | + pLock->cnt = 1; |
| 24025 | 24278 | } |
| 24279 | + }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ |
| 24280 | + /* We are trying for an exclusive lock but another thread in this |
| 24281 | + ** same process is still holding a shared lock. */ |
| 24282 | + rc = SQLITE_BUSY; |
| 24026 | 24283 | }else{ |
| 24027 | 24284 | /* The request was for a RESERVED or EXCLUSIVE lock. It is |
| 24028 | 24285 | ** assumed that there is a SHARED or greater lock on the file |
| 24029 | 24286 | ** already. |
| 24030 | 24287 | */ |
| | @@ -24031,25 +24288,28 @@ |
| 24031 | 24288 | int failed = 0; |
| 24032 | 24289 | assert( 0!=pFile->locktype ); |
| 24033 | 24290 | if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) { |
| 24034 | 24291 | /* Acquire a RESERVED lock */ |
| 24035 | 24292 | failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); |
| 24293 | + if( !failed ){ |
| 24294 | + context->reserved = 1; |
| 24295 | + } |
| 24036 | 24296 | } |
| 24037 | 24297 | if (!failed && locktype == EXCLUSIVE_LOCK) { |
| 24038 | 24298 | /* Acquire an EXCLUSIVE lock */ |
| 24039 | 24299 | |
| 24040 | 24300 | /* Remove the shared lock before trying the range. we'll need to |
| 24041 | 24301 | ** reestablish the shared lock if we can't get the afpUnlock |
| 24042 | 24302 | */ |
| 24043 | 24303 | if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + |
| 24044 | | - context->sharedByte, 1, 0)) ){ |
| 24304 | + pLock->sharedByte, 1, 0)) ){ |
| 24045 | 24305 | int failed2 = SQLITE_OK; |
| 24046 | 24306 | /* now attemmpt to get the exclusive lock range */ |
| 24047 | 24307 | failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, |
| 24048 | 24308 | SHARED_SIZE, 1); |
| 24049 | 24309 | if( failed && (failed2 = afpSetLock(context->dbPath, pFile, |
| 24050 | | - SHARED_FIRST + context->sharedByte, 1, 1)) ){ |
| 24310 | + SHARED_FIRST + pLock->sharedByte, 1, 1)) ){ |
| 24051 | 24311 | /* Can't reestablish the shared lock. Sqlite can't deal, this is |
| 24052 | 24312 | ** a critical I/O error |
| 24053 | 24313 | */ |
| 24054 | 24314 | rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : |
| 24055 | 24315 | SQLITE_IOERR_LOCK; |
| | @@ -24064,12 +24324,14 @@ |
| 24064 | 24324 | } |
| 24065 | 24325 | } |
| 24066 | 24326 | |
| 24067 | 24327 | if( rc==SQLITE_OK ){ |
| 24068 | 24328 | pFile->locktype = locktype; |
| 24329 | + pLock->locktype = locktype; |
| 24069 | 24330 | }else if( locktype==EXCLUSIVE_LOCK ){ |
| 24070 | 24331 | pFile->locktype = PENDING_LOCK; |
| 24332 | + pLock->locktype = PENDING_LOCK; |
| 24071 | 24333 | } |
| 24072 | 24334 | |
| 24073 | 24335 | afp_end_lock: |
| 24074 | 24336 | unixLeaveMutex(); |
| 24075 | 24337 | OSTRACE4("LOCK %d %s %s (afp)\n", pFile->h, locktypeName(locktype), |
| | @@ -24085,67 +24347,116 @@ |
| 24085 | 24347 | ** the requested locking level, this routine is a no-op. |
| 24086 | 24348 | */ |
| 24087 | 24349 | static int afpUnlock(sqlite3_file *id, int locktype) { |
| 24088 | 24350 | int rc = SQLITE_OK; |
| 24089 | 24351 | unixFile *pFile = (unixFile*)id; |
| 24090 | | - afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext; |
| 24352 | + struct unixLockInfo *pLock; |
| 24353 | + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; |
| 24354 | + int skipShared = 0; |
| 24355 | +#ifdef SQLITE_TEST |
| 24356 | + int h = pFile->h; |
| 24357 | +#endif |
| 24091 | 24358 | |
| 24092 | 24359 | assert( pFile ); |
| 24093 | | - OSTRACE5("UNLOCK %d %d was %d pid=%d (afp)\n", pFile->h, locktype, |
| 24094 | | - pFile->locktype, getpid()); |
| 24360 | + OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, locktype, |
| 24361 | + pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
| 24095 | 24362 | |
| 24096 | 24363 | assert( locktype<=SHARED_LOCK ); |
| 24097 | 24364 | if( pFile->locktype<=locktype ){ |
| 24098 | 24365 | return SQLITE_OK; |
| 24099 | 24366 | } |
| 24100 | 24367 | if( CHECK_THREADID(pFile) ){ |
| 24101 | | - return SQLITE_MISUSE; |
| 24368 | + return SQLITE_MISUSE_BKPT; |
| 24102 | 24369 | } |
| 24103 | 24370 | unixEnterMutex(); |
| 24371 | + pLock = pFile->pLock; |
| 24372 | + assert( pLock->cnt!=0 ); |
| 24104 | 24373 | if( pFile->locktype>SHARED_LOCK ){ |
| 24374 | + assert( pLock->locktype==pFile->locktype ); |
| 24375 | + SimulateIOErrorBenign(1); |
| 24376 | + SimulateIOError( h=(-1) ) |
| 24377 | + SimulateIOErrorBenign(0); |
| 24378 | + |
| 24379 | +#ifndef NDEBUG |
| 24380 | + /* When reducing a lock such that other processes can start |
| 24381 | + ** reading the database file again, make sure that the |
| 24382 | + ** transaction counter was updated if any part of the database |
| 24383 | + ** file changed. If the transaction counter is not updated, |
| 24384 | + ** other connections to the same file might not realize that |
| 24385 | + ** the file has changed and hence might not know to flush their |
| 24386 | + ** cache. The use of a stale cache can lead to database corruption. |
| 24387 | + */ |
| 24388 | + assert( pFile->inNormalWrite==0 |
| 24389 | + || pFile->dbUpdate==0 |
| 24390 | + || pFile->transCntrChng==1 ); |
| 24391 | + pFile->inNormalWrite = 0; |
| 24392 | +#endif |
| 24105 | 24393 | |
| 24106 | 24394 | if( pFile->locktype==EXCLUSIVE_LOCK ){ |
| 24107 | | - rc = afpSetLock(pCtx->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); |
| 24108 | | - if( rc==SQLITE_OK && locktype==SHARED_LOCK ){ |
| 24395 | + rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); |
| 24396 | + if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1) ){ |
| 24109 | 24397 | /* only re-establish the shared lock if necessary */ |
| 24110 | | - int sharedLockByte = SHARED_FIRST+pCtx->sharedByte; |
| 24111 | | - rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 1); |
| 24398 | + int sharedLockByte = SHARED_FIRST+pLock->sharedByte; |
| 24399 | + rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1); |
| 24400 | + } else { |
| 24401 | + skipShared = 1; |
| 24112 | 24402 | } |
| 24113 | 24403 | } |
| 24114 | 24404 | 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; |
| 24405 | + rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); |
| 24406 | + } |
| 24407 | + if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK && context->reserved ){ |
| 24408 | + rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); |
| 24409 | + if( !rc ){ |
| 24410 | + context->reserved = 0; |
| 24411 | + } |
| 24412 | + } |
| 24413 | + if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1)){ |
| 24414 | + pLock->locktype = SHARED_LOCK; |
| 24415 | + } |
| 24416 | + } |
| 24417 | + if( rc==SQLITE_OK && locktype==NO_LOCK ){ |
| 24418 | + |
| 24419 | + /* Decrement the shared lock counter. Release the lock using an |
| 24420 | + ** OS call only when all threads in this same process have released |
| 24421 | + ** the lock. |
| 24422 | + */ |
| 24423 | + unsigned long long sharedLockByte = SHARED_FIRST+pLock->sharedByte; |
| 24424 | + pLock->cnt--; |
| 24425 | + if( pLock->cnt==0 ){ |
| 24426 | + SimulateIOErrorBenign(1); |
| 24427 | + SimulateIOError( h=(-1) ) |
| 24428 | + SimulateIOErrorBenign(0); |
| 24429 | + if( !skipShared ){ |
| 24430 | + rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); |
| 24431 | + } |
| 24432 | + if( !rc ){ |
| 24433 | + pLock->locktype = NO_LOCK; |
| 24434 | + pFile->locktype = NO_LOCK; |
| 24435 | + } |
| 24436 | + } |
| 24437 | + if( rc==SQLITE_OK ){ |
| 24438 | + struct unixOpenCnt *pOpen = pFile->pOpen; |
| 24439 | + |
| 24129 | 24440 | pOpen->nLock--; |
| 24130 | 24441 | assert( pOpen->nLock>=0 ); |
| 24131 | 24442 | if( pOpen->nLock==0 ){ |
| 24132 | 24443 | rc = closePendingFds(pFile); |
| 24133 | 24444 | } |
| 24134 | 24445 | } |
| 24135 | 24446 | } |
| 24447 | + |
| 24136 | 24448 | unixLeaveMutex(); |
| 24137 | | - if( rc==SQLITE_OK ){ |
| 24138 | | - pFile->locktype = locktype; |
| 24139 | | - } |
| 24449 | + if( rc==SQLITE_OK ) pFile->locktype = locktype; |
| 24140 | 24450 | return rc; |
| 24141 | 24451 | } |
| 24142 | 24452 | |
| 24143 | 24453 | /* |
| 24144 | 24454 | ** Close a file & cleanup AFP specific locking context |
| 24145 | 24455 | */ |
| 24146 | 24456 | static int afpClose(sqlite3_file *id) { |
| 24457 | + int rc = SQLITE_OK; |
| 24147 | 24458 | if( id ){ |
| 24148 | 24459 | unixFile *pFile = (unixFile*)id; |
| 24149 | 24460 | afpUnlock(id, NO_LOCK); |
| 24150 | 24461 | unixEnterMutex(); |
| 24151 | 24462 | if( pFile->pOpen && pFile->pOpen->nLock ){ |
| | @@ -24154,16 +24465,17 @@ |
| 24154 | 24465 | ** descriptor to pOpen->aPending. It will be automatically closed when |
| 24155 | 24466 | ** the last lock is cleared. |
| 24156 | 24467 | */ |
| 24157 | 24468 | setPendingFd(pFile); |
| 24158 | 24469 | } |
| 24470 | + releaseLockInfo(pFile->pLock); |
| 24159 | 24471 | releaseOpenCnt(pFile->pOpen); |
| 24160 | 24472 | sqlite3_free(pFile->lockingContext); |
| 24161 | | - closeUnixFile(id); |
| 24473 | + rc = closeUnixFile(id); |
| 24162 | 24474 | unixLeaveMutex(); |
| 24163 | 24475 | } |
| 24164 | | - return SQLITE_OK; |
| 24476 | + return rc; |
| 24165 | 24477 | } |
| 24166 | 24478 | |
| 24167 | 24479 | #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ |
| 24168 | 24480 | /* |
| 24169 | 24481 | ** The code above is the AFP lock implementation. The code is specific |
| | @@ -24172,10 +24484,33 @@ |
| 24172 | 24484 | ** VFS is not available. |
| 24173 | 24485 | ** |
| 24174 | 24486 | ********************* End of the AFP lock implementation ********************** |
| 24175 | 24487 | ******************************************************************************/ |
| 24176 | 24488 | |
| 24489 | +/****************************************************************************** |
| 24490 | +*************************** Begin NFS Locking ********************************/ |
| 24491 | + |
| 24492 | +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 24493 | +/* |
| 24494 | + ** Lower the locking level on file descriptor pFile to locktype. locktype |
| 24495 | + ** must be either NO_LOCK or SHARED_LOCK. |
| 24496 | + ** |
| 24497 | + ** If the locking level of the file descriptor is already at or below |
| 24498 | + ** the requested locking level, this routine is a no-op. |
| 24499 | + */ |
| 24500 | +static int nfsUnlock(sqlite3_file *id, int locktype){ |
| 24501 | + return _posixUnlock(id, locktype, 1); |
| 24502 | +} |
| 24503 | + |
| 24504 | +#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ |
| 24505 | +/* |
| 24506 | +** The code above is the NFS lock implementation. The code is specific |
| 24507 | +** to MacOSX and does not work on other unix platforms. No alternative |
| 24508 | +** is available. |
| 24509 | +** |
| 24510 | +********************* End of the NFS lock implementation ********************** |
| 24511 | +******************************************************************************/ |
| 24177 | 24512 | |
| 24178 | 24513 | /****************************************************************************** |
| 24179 | 24514 | **************** Non-locking sqlite3_file methods ***************************** |
| 24180 | 24515 | ** |
| 24181 | 24516 | ** The next division contains implementations for all methods of the |
| | @@ -24198,11 +24533,13 @@ |
| 24198 | 24533 | ** To avoid stomping the errno value on a failed read the lastErrno value |
| 24199 | 24534 | ** is set before returning. |
| 24200 | 24535 | */ |
| 24201 | 24536 | static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ |
| 24202 | 24537 | int got; |
| 24538 | +#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) |
| 24203 | 24539 | i64 newOffset; |
| 24540 | +#endif |
| 24204 | 24541 | TIMER_START; |
| 24205 | 24542 | #if defined(USE_PREAD) |
| 24206 | 24543 | got = pread(id->h, pBuf, cnt, offset); |
| 24207 | 24544 | SimulateIOError( got = -1 ); |
| 24208 | 24545 | #elif defined(USE_PREAD64) |
| | @@ -24272,11 +24609,13 @@ |
| 24272 | 24609 | ** To avoid stomping the errno value on a failed write the lastErrno value |
| 24273 | 24610 | ** is set before returning. |
| 24274 | 24611 | */ |
| 24275 | 24612 | static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ |
| 24276 | 24613 | int got; |
| 24614 | +#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) |
| 24277 | 24615 | i64 newOffset; |
| 24616 | +#endif |
| 24278 | 24617 | TIMER_START; |
| 24279 | 24618 | #if defined(USE_PREAD) |
| 24280 | 24619 | got = pwrite(id->h, pBuf, cnt, offset); |
| 24281 | 24620 | #elif defined(USE_PREAD64) |
| 24282 | 24621 | got = pwrite64(id->h, pBuf, cnt, offset); |
| | @@ -24466,10 +24805,15 @@ |
| 24466 | 24805 | ** It'd be better to detect fullfsync support once and avoid |
| 24467 | 24806 | ** the fcntl call every time sync is called. |
| 24468 | 24807 | */ |
| 24469 | 24808 | if( rc ) rc = fsync(fd); |
| 24470 | 24809 | |
| 24810 | +#elif defined(__APPLE__) |
| 24811 | + /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly |
| 24812 | + ** so currently we default to the macro that redefines fdatasync to fsync |
| 24813 | + */ |
| 24814 | + rc = fsync(fd); |
| 24471 | 24815 | #else |
| 24472 | 24816 | rc = fdatasync(fd); |
| 24473 | 24817 | #if OS_VXWORKS |
| 24474 | 24818 | if( rc==-1 && errno==ENOTSUP ){ |
| 24475 | 24819 | rc = fsync(fd); |
| | @@ -24800,27 +25144,10 @@ |
| 24800 | 25144 | afpUnlock, /* xUnlock method */ |
| 24801 | 25145 | afpCheckReservedLock /* xCheckReservedLock method */ |
| 24802 | 25146 | ) |
| 24803 | 25147 | #endif |
| 24804 | 25148 | |
| 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 | 25149 | /* |
| 24823 | 25150 | ** The proxy locking method is a "super-method" in the sense that it |
| 24824 | 25151 | ** opens secondary file descriptors for the conch and lock files and |
| 24825 | 25152 | ** it uses proxy, dot-file, AFP, and flock() locking methods on those |
| 24826 | 25153 | ** secondary files. For this reason, the division that implements |
| | @@ -24841,10 +25168,21 @@ |
| 24841 | 25168 | proxyUnlock, /* xUnlock method */ |
| 24842 | 25169 | proxyCheckReservedLock /* xCheckReservedLock method */ |
| 24843 | 25170 | ) |
| 24844 | 25171 | #endif |
| 24845 | 25172 | |
| 25173 | +/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */ |
| 25174 | +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 25175 | +IOMETHODS( |
| 25176 | + nfsIoFinder, /* Finder function name */ |
| 25177 | + nfsIoMethods, /* sqlite3_io_methods object name */ |
| 25178 | + unixClose, /* xClose method */ |
| 25179 | + unixLock, /* xLock method */ |
| 25180 | + nfsUnlock, /* xUnlock method */ |
| 25181 | + unixCheckReservedLock /* xCheckReservedLock method */ |
| 25182 | +) |
| 25183 | +#endif |
| 24846 | 25184 | |
| 24847 | 25185 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 24848 | 25186 | /* |
| 24849 | 25187 | ** This "finder" function attempts to determine the best locking strategy |
| 24850 | 25188 | ** for the database file "filePath". It then returns the sqlite3_io_methods |
| | @@ -24861,15 +25199,11 @@ |
| 24861 | 25199 | const sqlite3_io_methods *pMethods; /* Appropriate locking method */ |
| 24862 | 25200 | } aMap[] = { |
| 24863 | 25201 | { "hfs", &posixIoMethods }, |
| 24864 | 25202 | { "ufs", &posixIoMethods }, |
| 24865 | 25203 | { "afpfs", &afpIoMethods }, |
| 24866 | | -#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB |
| 24867 | 25204 | { "smbfs", &afpIoMethods }, |
| 24868 | | -#else |
| 24869 | | - { "smbfs", &flockIoMethods }, |
| 24870 | | -#endif |
| 24871 | 25205 | { "webdav", &nolockIoMethods }, |
| 24872 | 25206 | { 0, 0 } |
| 24873 | 25207 | }; |
| 24874 | 25208 | int i; |
| 24875 | 25209 | struct statfs fsInfo; |
| | @@ -24898,12 +25232,15 @@ |
| 24898 | 25232 | lockInfo.l_len = 1; |
| 24899 | 25233 | lockInfo.l_start = 0; |
| 24900 | 25234 | lockInfo.l_whence = SEEK_SET; |
| 24901 | 25235 | lockInfo.l_type = F_RDLCK; |
| 24902 | 25236 | if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) { |
| 24903 | | - pNew->fileFlags = SQLITE_WHOLE_FILE_LOCKING; |
| 24904 | | - return &posixIoMethods; |
| 25237 | + if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){ |
| 25238 | + return &nfsIoMethods; |
| 25239 | + } else { |
| 25240 | + return &posixIoMethods; |
| 25241 | + } |
| 24905 | 25242 | }else{ |
| 24906 | 25243 | return &dotlockIoMethods; |
| 24907 | 25244 | } |
| 24908 | 25245 | } |
| 24909 | 25246 | static const sqlite3_io_methods |
| | @@ -25010,11 +25347,15 @@ |
| 25010 | 25347 | ** zFilename remains valid until file is closed, to support */ |
| 25011 | 25348 | pNew->lockingContext = (void*)zFilename; |
| 25012 | 25349 | #endif |
| 25013 | 25350 | } |
| 25014 | 25351 | |
| 25015 | | - if( pLockingStyle == &posixIoMethods ){ |
| 25352 | + if( pLockingStyle == &posixIoMethods |
| 25353 | +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 25354 | + || pLockingStyle == &nfsIoMethods |
| 25355 | +#endif |
| 25356 | + ){ |
| 25016 | 25357 | unixEnterMutex(); |
| 25017 | 25358 | rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); |
| 25018 | 25359 | if( rc!=SQLITE_OK ){ |
| 25019 | 25360 | /* If an error occured in findLockInfo(), close the file descriptor |
| 25020 | 25361 | ** immediately, before releasing the mutex. findLockInfo() may fail |
| | @@ -25052,13 +25393,19 @@ |
| 25052 | 25393 | }else{ |
| 25053 | 25394 | /* NB: zFilename exists and remains valid until the file is closed |
| 25054 | 25395 | ** according to requirement F11141. So we do not need to make a |
| 25055 | 25396 | ** copy of the filename. */ |
| 25056 | 25397 | pCtx->dbPath = zFilename; |
| 25398 | + pCtx->reserved = 0; |
| 25057 | 25399 | srandomdev(); |
| 25058 | 25400 | unixEnterMutex(); |
| 25059 | | - rc = findLockInfo(pNew, NULL, &pNew->pOpen); |
| 25401 | + rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); |
| 25402 | + if( rc!=SQLITE_OK ){ |
| 25403 | + sqlite3_free(pNew->lockingContext); |
| 25404 | + close(h); |
| 25405 | + h = -1; |
| 25406 | + } |
| 25060 | 25407 | unixLeaveMutex(); |
| 25061 | 25408 | } |
| 25062 | 25409 | } |
| 25063 | 25410 | #endif |
| 25064 | 25411 | |
| | @@ -25103,10 +25450,12 @@ |
| 25103 | 25450 | #endif |
| 25104 | 25451 | |
| 25105 | 25452 | pNew->lastErrno = 0; |
| 25106 | 25453 | #if OS_VXWORKS |
| 25107 | 25454 | if( rc!=SQLITE_OK ){ |
| 25455 | + if( h>=0 ) close(h); |
| 25456 | + h = -1; |
| 25108 | 25457 | unlink(zFilename); |
| 25109 | 25458 | isDelete = 0; |
| 25110 | 25459 | } |
| 25111 | 25460 | pNew->isDelete = isDelete; |
| 25112 | 25461 | #endif |
| | @@ -25146,11 +25495,11 @@ |
| 25146 | 25495 | #endif |
| 25147 | 25496 | OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname); |
| 25148 | 25497 | } |
| 25149 | 25498 | } |
| 25150 | 25499 | *pFd = fd; |
| 25151 | | - return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN); |
| 25500 | + return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN_BKPT); |
| 25152 | 25501 | } |
| 25153 | 25502 | |
| 25154 | 25503 | /* |
| 25155 | 25504 | ** Create a temporary file name in zBuf. zBuf must be allocated |
| 25156 | 25505 | ** by the calling process and must be big enough to hold at least |
| | @@ -25255,20 +25604,21 @@ |
| 25255 | 25604 | ** descriptor on the same path, fail, and return an error to SQLite. |
| 25256 | 25605 | ** |
| 25257 | 25606 | ** Even if a subsequent open() call does succeed, the consequences of |
| 25258 | 25607 | ** not searching for a resusable file descriptor are not dire. */ |
| 25259 | 25608 | 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; |
| 25609 | + struct unixOpenCnt *pOpen; |
| 25264 | 25610 | |
| 25265 | 25611 | unixEnterMutex(); |
| 25266 | | - for(pO=openList; pO && memcmp(&id, &pO->fileId, sizeof(id)); pO=pO->pNext); |
| 25267 | | - if( pO ){ |
| 25612 | + pOpen = openList; |
| 25613 | + while( pOpen && (pOpen->fileId.dev!=sStat.st_dev |
| 25614 | + || pOpen->fileId.ino!=sStat.st_ino) ){ |
| 25615 | + pOpen = pOpen->pNext; |
| 25616 | + } |
| 25617 | + if( pOpen ){ |
| 25268 | 25618 | UnixUnusedFd **pp; |
| 25269 | | - for(pp=&pO->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); |
| 25619 | + for(pp=&pOpen->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); |
| 25270 | 25620 | pUnused = *pp; |
| 25271 | 25621 | if( pUnused ){ |
| 25272 | 25622 | *pp = pUnused->pNext; |
| 25273 | 25623 | } |
| 25274 | 25624 | } |
| | @@ -25318,10 +25668,13 @@ |
| 25318 | 25668 | int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); |
| 25319 | 25669 | int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); |
| 25320 | 25670 | int isCreate = (flags & SQLITE_OPEN_CREATE); |
| 25321 | 25671 | int isReadonly = (flags & SQLITE_OPEN_READONLY); |
| 25322 | 25672 | int isReadWrite = (flags & SQLITE_OPEN_READWRITE); |
| 25673 | +#if SQLITE_ENABLE_LOCKING_STYLE |
| 25674 | + int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY); |
| 25675 | +#endif |
| 25323 | 25676 | |
| 25324 | 25677 | /* If creating a master or main-file journal, this function will open |
| 25325 | 25678 | ** a file-descriptor on the directory too. The first time unixSync() |
| 25326 | 25679 | ** is called the directory file descriptor will be fsync()ed and close()d. |
| 25327 | 25680 | */ |
| | @@ -25405,11 +25758,11 @@ |
| 25405 | 25758 | flags |= SQLITE_OPEN_READONLY; |
| 25406 | 25759 | openFlags |= O_RDONLY; |
| 25407 | 25760 | fd = open(zName, openFlags, openMode); |
| 25408 | 25761 | } |
| 25409 | 25762 | if( fd<0 ){ |
| 25410 | | - rc = SQLITE_CANTOPEN; |
| 25763 | + rc = SQLITE_CANTOPEN_BKPT; |
| 25411 | 25764 | goto open_finished; |
| 25412 | 25765 | } |
| 25413 | 25766 | } |
| 25414 | 25767 | assert( fd>=0 ); |
| 25415 | 25768 | if( pOutFlags ){ |
| | @@ -25451,12 +25804,29 @@ |
| 25451 | 25804 | fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 25452 | 25805 | #endif |
| 25453 | 25806 | |
| 25454 | 25807 | noLock = eType!=SQLITE_OPEN_MAIN_DB; |
| 25455 | 25808 | |
| 25809 | + |
| 25810 | +#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE |
| 25811 | + struct statfs fsInfo; |
| 25812 | + if( fstatfs(fd, &fsInfo) == -1 ){ |
| 25813 | + ((unixFile*)pFile)->lastErrno = errno; |
| 25814 | + if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */ |
| 25815 | + close(fd); /* silently leak if fail, in error */ |
| 25816 | + return SQLITE_IOERR_ACCESS; |
| 25817 | + } |
| 25818 | + if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { |
| 25819 | + ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; |
| 25820 | + } |
| 25821 | +#endif |
| 25822 | + |
| 25823 | +#if SQLITE_ENABLE_LOCKING_STYLE |
| 25456 | 25824 | #if SQLITE_PREFER_PROXY_LOCKING |
| 25457 | | - if( zPath!=NULL && !noLock && pVfs->xOpen ){ |
| 25825 | + isAutoProxy = 1; |
| 25826 | +#endif |
| 25827 | + if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){ |
| 25458 | 25828 | char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); |
| 25459 | 25829 | int useProxy = 0; |
| 25460 | 25830 | |
| 25461 | 25831 | /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means |
| 25462 | 25832 | ** never use proxy, NULL means use proxy for non-local files only. */ |
| | @@ -25484,10 +25854,18 @@ |
| 25484 | 25854 | } |
| 25485 | 25855 | if( useProxy ){ |
| 25486 | 25856 | rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); |
| 25487 | 25857 | if( rc==SQLITE_OK ){ |
| 25488 | 25858 | rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); |
| 25859 | + if( rc!=SQLITE_OK ){ |
| 25860 | + /* Use unixClose to clean up the resources added in fillInUnixFile |
| 25861 | + ** and clear all the structure's references. Specifically, |
| 25862 | + ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op |
| 25863 | + */ |
| 25864 | + unixClose(pFile); |
| 25865 | + return rc; |
| 25866 | + } |
| 25489 | 25867 | } |
| 25490 | 25868 | goto open_finished; |
| 25491 | 25869 | } |
| 25492 | 25870 | } |
| 25493 | 25871 | #endif |
| | @@ -25604,11 +25982,11 @@ |
| 25604 | 25982 | if( zPath[0]=='/' ){ |
| 25605 | 25983 | sqlite3_snprintf(nOut, zOut, "%s", zPath); |
| 25606 | 25984 | }else{ |
| 25607 | 25985 | int nCwd; |
| 25608 | 25986 | if( getcwd(zOut, nOut-1)==0 ){ |
| 25609 | | - return SQLITE_CANTOPEN; |
| 25987 | + return SQLITE_CANTOPEN_BKPT; |
| 25610 | 25988 | } |
| 25611 | 25989 | nCwd = (int)strlen(zOut); |
| 25612 | 25990 | sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath); |
| 25613 | 25991 | } |
| 25614 | 25992 | return SQLITE_OK; |
| | @@ -25911,15 +26289,10 @@ |
| 25911 | 26289 | ** The proxy file - a single-byte file used for all advisory file locks |
| 25912 | 26290 | ** normally taken on the database file. This allows for safe sharing |
| 25913 | 26291 | ** of the database file for multiple readers and writers on the same |
| 25914 | 26292 | ** host (the conch ensures that they all use the same local lock file). |
| 25915 | 26293 | ** |
| 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 | 26294 | ** Requesting the lock proxy does not immediately take the conch, it is |
| 25922 | 26295 | ** only taken when the first request to lock database file is made. |
| 25923 | 26296 | ** This matches the semantics of the traditional locking behavior, where |
| 25924 | 26297 | ** opening a connection to a database file does not take a lock on it. |
| 25925 | 26298 | ** The shared lock and an open file descriptor are maintained until |
| | @@ -25941,14 +26314,10 @@ |
| 25941 | 26314 | ** SQLITE_PROXY_DEBUG |
| 25942 | 26315 | ** |
| 25943 | 26316 | ** Enables the logging of error messages during host id file |
| 25944 | 26317 | ** retrieval and creation |
| 25945 | 26318 | ** |
| 25946 | | -** HOSTIDPATH |
| 25947 | | -** |
| 25948 | | -** Overrides the default host ID file path location |
| 25949 | | -** |
| 25950 | 26319 | ** LOCKPROXYDIR |
| 25951 | 26320 | ** |
| 25952 | 26321 | ** Overrides the default directory used for lock proxy files that |
| 25953 | 26322 | ** are named automatically via the ":auto:" setting |
| 25954 | 26323 | ** |
| | @@ -25969,15 +26338,10 @@ |
| 25969 | 26338 | /* |
| 25970 | 26339 | ** Proxy locking is only available on MacOSX |
| 25971 | 26340 | */ |
| 25972 | 26341 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE |
| 25973 | 26342 | |
| 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 | 26343 | /* |
| 25980 | 26344 | ** The proxyLockingContext has the path and file structures for the remote |
| 25981 | 26345 | ** and local proxy files in it |
| 25982 | 26346 | */ |
| 25983 | 26347 | typedef struct proxyLockingContext proxyLockingContext; |
| | @@ -25985,138 +26349,20 @@ |
| 25985 | 26349 | unixFile *conchFile; /* Open conch file */ |
| 25986 | 26350 | char *conchFilePath; /* Name of the conch file */ |
| 25987 | 26351 | unixFile *lockProxy; /* Open proxy lock file */ |
| 25988 | 26352 | char *lockProxyPath; /* Name of the proxy lock file */ |
| 25989 | 26353 | char *dbPath; /* Name of the open file */ |
| 25990 | | - int conchHeld; /* True if the conch is currently held */ |
| 26354 | + int conchHeld; /* 1 if the conch is held, -1 if lockless */ |
| 25991 | 26355 | void *oldLockingContext; /* Original lockingcontext to restore on close */ |
| 25992 | 26356 | sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ |
| 25993 | 26357 | }; |
| 25994 | 26358 | |
| 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 | | - |
| 26359 | +/* |
| 26360 | +** The proxy lock file path for the database at dbPath is written into lPath, |
| 26361 | +** which must point to valid, writable memory large enough for a maxLen length |
| 26362 | +** file path. |
| 26363 | +*/ |
| 26118 | 26364 | static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ |
| 26119 | 26365 | int len; |
| 26120 | 26366 | int dbLen; |
| 26121 | 26367 | int i; |
| 26122 | 26368 | |
| | @@ -26123,25 +26369,16 @@ |
| 26123 | 26369 | #ifdef LOCKPROXYDIR |
| 26124 | 26370 | len = strlcpy(lPath, LOCKPROXYDIR, maxLen); |
| 26125 | 26371 | #else |
| 26126 | 26372 | # ifdef _CS_DARWIN_USER_TEMP_DIR |
| 26127 | 26373 | { |
| 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 | | - |
| 26374 | + if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ |
| 26375 | + OSTRACE4("GETLOCKPATH failed %s errno=%d pid=%d\n", |
| 26376 | + lPath, errno, getpid()); |
| 26377 | + return SQLITE_IOERR_LOCK; |
| 26378 | + } |
| 26379 | + len = strlcat(lPath, "sqliteplocks", maxLen); |
| 26143 | 26380 | } |
| 26144 | 26381 | # else |
| 26145 | 26382 | len = strlcpy(lPath, "/tmp/", maxLen); |
| 26146 | 26383 | # endif |
| 26147 | 26384 | #endif |
| | @@ -26156,213 +26393,535 @@ |
| 26156 | 26393 | char c = dbPath[i]; |
| 26157 | 26394 | lPath[i+len] = (c=='/')?'_':c; |
| 26158 | 26395 | } |
| 26159 | 26396 | lPath[i+len]='\0'; |
| 26160 | 26397 | strlcat(lPath, ":auto:", maxLen); |
| 26398 | + OSTRACE3("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()); |
| 26161 | 26399 | return SQLITE_OK; |
| 26162 | 26400 | } |
| 26401 | + |
| 26402 | +/* |
| 26403 | + ** Creates the lock file and any missing directories in lockPath |
| 26404 | + */ |
| 26405 | +static int proxyCreateLockPath(const char *lockPath){ |
| 26406 | + int i, len; |
| 26407 | + char buf[MAXPATHLEN]; |
| 26408 | + int start = 0; |
| 26409 | + |
| 26410 | + assert(lockPath!=NULL); |
| 26411 | + /* try to create all the intermediate directories */ |
| 26412 | + len = (int)strlen(lockPath); |
| 26413 | + buf[0] = lockPath[0]; |
| 26414 | + for( i=1; i<len; i++ ){ |
| 26415 | + if( lockPath[i] == '/' && (i - start > 0) ){ |
| 26416 | + /* only mkdir if leaf dir != "." or "/" or ".." */ |
| 26417 | + if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') |
| 26418 | + || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){ |
| 26419 | + buf[i]='\0'; |
| 26420 | + if( mkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ |
| 26421 | + int err=errno; |
| 26422 | + if( err!=EEXIST ) { |
| 26423 | + OSTRACE5("CREATELOCKPATH FAILED creating %s, " |
| 26424 | + "'%s' proxy lock path=%s pid=%d\n", |
| 26425 | + buf, strerror(err), lockPath, getpid()); |
| 26426 | + return err; |
| 26427 | + } |
| 26428 | + } |
| 26429 | + } |
| 26430 | + start=i+1; |
| 26431 | + } |
| 26432 | + buf[i] = lockPath[i]; |
| 26433 | + } |
| 26434 | + OSTRACE3("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()); |
| 26435 | + return 0; |
| 26436 | +} |
| 26163 | 26437 | |
| 26164 | 26438 | /* |
| 26165 | 26439 | ** Create a new VFS file descriptor (stored in memory obtained from |
| 26166 | 26440 | ** sqlite3_malloc) and open the file named "path" in the file descriptor. |
| 26167 | 26441 | ** |
| 26168 | 26442 | ** The caller is responsible not only for closing the file descriptor |
| 26169 | 26443 | ** but also for freeing the memory associated with the file descriptor. |
| 26170 | 26444 | */ |
| 26171 | | -static int proxyCreateUnixFile(const char *path, unixFile **ppFile) { |
| 26445 | +static int proxyCreateUnixFile( |
| 26446 | + const char *path, /* path for the new unixFile */ |
| 26447 | + unixFile **ppFile, /* unixFile created and returned by ref */ |
| 26448 | + int islockfile /* if non zero missing dirs will be created */ |
| 26449 | +) { |
| 26450 | + int fd = -1; |
| 26451 | + int dirfd = -1; |
| 26172 | 26452 | unixFile *pNew; |
| 26173 | | - int flags = SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE; |
| 26174 | 26453 | int rc = SQLITE_OK; |
| 26454 | + int openFlags = O_RDWR | O_CREAT; |
| 26175 | 26455 | sqlite3_vfs dummyVfs; |
| 26456 | + int terrno = 0; |
| 26457 | + UnixUnusedFd *pUnused = NULL; |
| 26176 | 26458 | |
| 26177 | | - pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile)); |
| 26178 | | - if( !pNew ){ |
| 26179 | | - return SQLITE_NOMEM; |
| 26459 | + /* 1. first try to open/create the file |
| 26460 | + ** 2. if that fails, and this is a lock file (not-conch), try creating |
| 26461 | + ** the parent directories and then try again. |
| 26462 | + ** 3. if that fails, try to open the file read-only |
| 26463 | + ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file |
| 26464 | + */ |
| 26465 | + pUnused = findReusableFd(path, openFlags); |
| 26466 | + if( pUnused ){ |
| 26467 | + fd = pUnused->fd; |
| 26468 | + }else{ |
| 26469 | + pUnused = sqlite3_malloc(sizeof(*pUnused)); |
| 26470 | + if( !pUnused ){ |
| 26471 | + return SQLITE_NOMEM; |
| 26472 | + } |
| 26473 | + } |
| 26474 | + if( fd<0 ){ |
| 26475 | + fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26476 | + terrno = errno; |
| 26477 | + if( fd<0 && errno==ENOENT && islockfile ){ |
| 26478 | + if( proxyCreateLockPath(path) == SQLITE_OK ){ |
| 26479 | + fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26480 | + } |
| 26481 | + } |
| 26482 | + } |
| 26483 | + if( fd<0 ){ |
| 26484 | + openFlags = O_RDONLY; |
| 26485 | + fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26486 | + terrno = errno; |
| 26487 | + } |
| 26488 | + if( fd<0 ){ |
| 26489 | + if( islockfile ){ |
| 26490 | + return SQLITE_BUSY; |
| 26491 | + } |
| 26492 | + switch (terrno) { |
| 26493 | + case EACCES: |
| 26494 | + return SQLITE_PERM; |
| 26495 | + case EIO: |
| 26496 | + return SQLITE_IOERR_LOCK; /* even though it is the conch */ |
| 26497 | + default: |
| 26498 | + return SQLITE_CANTOPEN_BKPT; |
| 26499 | + } |
| 26500 | + } |
| 26501 | + |
| 26502 | + pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew)); |
| 26503 | + if( pNew==NULL ){ |
| 26504 | + rc = SQLITE_NOMEM; |
| 26505 | + goto end_create_proxy; |
| 26180 | 26506 | } |
| 26181 | 26507 | 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 | | - */ |
| 26508 | + pNew->openFlags = openFlags; |
| 26195 | 26509 | 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 |
| 26510 | + pUnused->fd = fd; |
| 26511 | + pUnused->flags = openFlags; |
| 26512 | + pNew->pUnused = pUnused; |
| 26513 | + |
| 26514 | + rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0); |
| 26515 | + if( rc==SQLITE_OK ){ |
| 26516 | + *ppFile = pNew; |
| 26517 | + return SQLITE_OK; |
| 26518 | + } |
| 26519 | +end_create_proxy: |
| 26520 | + close(fd); /* silently leak fd if error, we're already in error */ |
| 26521 | + sqlite3_free(pNew); |
| 26522 | + sqlite3_free(pUnused); |
| 26523 | + return rc; |
| 26524 | +} |
| 26525 | + |
| 26526 | +#ifdef SQLITE_TEST |
| 26527 | +/* simulate multiple hosts by creating unique hostid file paths */ |
| 26528 | +SQLITE_API int sqlite3_hostid_num = 0; |
| 26529 | +#endif |
| 26530 | + |
| 26531 | +#define PROXY_HOSTIDLEN 16 /* conch file host id length */ |
| 26532 | + |
| 26533 | +/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN |
| 26534 | +** bytes of writable memory. |
| 26535 | +*/ |
| 26536 | +static int proxyGetHostID(unsigned char *pHostID, int *pError){ |
| 26537 | + struct timespec timeout = {1, 0}; /* 1 sec timeout */ |
| 26538 | + |
| 26539 | + assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); |
| 26540 | + memset(pHostID, 0, PROXY_HOSTIDLEN); |
| 26541 | + if( gethostuuid(pHostID, &timeout) ){ |
| 26542 | + int err = errno; |
| 26543 | + if( pError ){ |
| 26544 | + *pError = err; |
| 26545 | + } |
| 26546 | + return SQLITE_IOERR; |
| 26547 | + } |
| 26548 | +#ifdef SQLITE_TEST |
| 26549 | + /* simulate multiple hosts by creating unique hostid file paths */ |
| 26550 | + if( sqlite3_hostid_num != 0){ |
| 26551 | + pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF)); |
| 26552 | + } |
| 26553 | +#endif |
| 26554 | + |
| 26555 | + return SQLITE_OK; |
| 26556 | +} |
| 26557 | + |
| 26558 | +/* The conch file contains the header, host id and lock file path |
| 26559 | + */ |
| 26560 | +#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */ |
| 26561 | +#define PROXY_HEADERLEN 1 /* conch file header length */ |
| 26562 | +#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN) |
| 26563 | +#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN) |
| 26564 | + |
| 26565 | +/* |
| 26566 | +** Takes an open conch file, copies the contents to a new path and then moves |
| 26567 | +** it back. The newly created file's file descriptor is assigned to the |
| 26568 | +** conch file structure and finally the original conch file descriptor is |
| 26569 | +** closed. Returns zero if successful. |
| 26570 | +*/ |
| 26571 | +static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ |
| 26572 | + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26573 | + unixFile *conchFile = pCtx->conchFile; |
| 26574 | + char tPath[MAXPATHLEN]; |
| 26575 | + char buf[PROXY_MAXCONCHLEN]; |
| 26576 | + char *cPath = pCtx->conchFilePath; |
| 26577 | + size_t readLen = 0; |
| 26578 | + size_t pathLen = 0; |
| 26579 | + char errmsg[64] = ""; |
| 26580 | + int fd = -1; |
| 26581 | + int rc = -1; |
| 26582 | + |
| 26583 | + /* create a new path by replace the trailing '-conch' with '-break' */ |
| 26584 | + pathLen = strlcpy(tPath, cPath, MAXPATHLEN); |
| 26585 | + if( pathLen>MAXPATHLEN || pathLen<6 || |
| 26586 | + (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){ |
| 26587 | + sprintf(errmsg, "path error (len %d)", (int)pathLen); |
| 26588 | + goto end_breaklock; |
| 26589 | + } |
| 26590 | + /* read the conch content */ |
| 26591 | + readLen = pread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0); |
| 26592 | + if( readLen<PROXY_PATHINDEX ){ |
| 26593 | + sprintf(errmsg, "read error (len %d)", (int)readLen); |
| 26594 | + goto end_breaklock; |
| 26595 | + } |
| 26596 | + /* write it out to the temporary break file */ |
| 26597 | + fd = open(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26598 | + if( fd<0 ){ |
| 26599 | + sprintf(errmsg, "create failed (%d)", errno); |
| 26600 | + goto end_breaklock; |
| 26601 | + } |
| 26602 | + if( pwrite(fd, buf, readLen, 0) != readLen ){ |
| 26603 | + sprintf(errmsg, "write failed (%d)", errno); |
| 26604 | + goto end_breaklock; |
| 26605 | + } |
| 26606 | + if( rename(tPath, cPath) ){ |
| 26607 | + sprintf(errmsg, "rename failed (%d)", errno); |
| 26608 | + goto end_breaklock; |
| 26609 | + } |
| 26610 | + rc = 0; |
| 26611 | + fprintf(stderr, "broke stale lock on %s\n", cPath); |
| 26612 | + close(conchFile->h); |
| 26613 | + conchFile->h = fd; |
| 26614 | + conchFile->openFlags = O_RDWR | O_CREAT; |
| 26615 | + |
| 26616 | +end_breaklock: |
| 26617 | + if( rc ){ |
| 26618 | + if( fd>=0 ){ |
| 26619 | + unlink(tPath); |
| 26620 | + close(fd); |
| 26621 | + } |
| 26622 | + fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); |
| 26623 | + } |
| 26624 | + return rc; |
| 26625 | +} |
| 26626 | + |
| 26627 | +/* Take the requested lock on the conch file and break a stale lock if the |
| 26628 | +** host id matches. |
| 26629 | +*/ |
| 26630 | +static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ |
| 26631 | + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26632 | + unixFile *conchFile = pCtx->conchFile; |
| 26633 | + int rc = SQLITE_OK; |
| 26634 | + int nTries = 0; |
| 26635 | + struct timespec conchModTime; |
| 26636 | + |
| 26637 | + do { |
| 26638 | + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); |
| 26639 | + nTries ++; |
| 26640 | + if( rc==SQLITE_BUSY ){ |
| 26641 | + /* If the lock failed (busy): |
| 26642 | + * 1st try: get the mod time of the conch, wait 0.5s and try again. |
| 26643 | + * 2nd try: fail if the mod time changed or host id is different, wait |
| 26644 | + * 10 sec and try again |
| 26645 | + * 3rd try: break the lock unless the mod time has changed. |
| 26646 | + */ |
| 26647 | + struct stat buf; |
| 26648 | + if( fstat(conchFile->h, &buf) ){ |
| 26649 | + pFile->lastErrno = errno; |
| 26650 | + return SQLITE_IOERR_LOCK; |
| 26651 | + } |
| 26652 | + |
| 26653 | + if( nTries==1 ){ |
| 26654 | + conchModTime = buf.st_mtimespec; |
| 26655 | + usleep(500000); /* wait 0.5 sec and try the lock again*/ |
| 26656 | + continue; |
| 26657 | + } |
| 26658 | + |
| 26659 | + assert( nTries>1 ); |
| 26660 | + if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || |
| 26661 | + conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){ |
| 26662 | + return SQLITE_BUSY; |
| 26663 | + } |
| 26664 | + |
| 26665 | + if( nTries==2 ){ |
| 26666 | + char tBuf[PROXY_MAXCONCHLEN]; |
| 26667 | + int len = pread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); |
| 26668 | + if( len<0 ){ |
| 26669 | + pFile->lastErrno = errno; |
| 26670 | + return SQLITE_IOERR_LOCK; |
| 26671 | + } |
| 26672 | + if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ |
| 26673 | + /* don't break the lock if the host id doesn't match */ |
| 26674 | + if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){ |
| 26675 | + return SQLITE_BUSY; |
| 26676 | + } |
| 26677 | + }else{ |
| 26678 | + /* don't break the lock on short read or a version mismatch */ |
| 26679 | + return SQLITE_BUSY; |
| 26680 | + } |
| 26681 | + usleep(10000000); /* wait 10 sec and try the lock again */ |
| 26682 | + continue; |
| 26683 | + } |
| 26684 | + |
| 26685 | + assert( nTries==3 ); |
| 26686 | + if( 0==proxyBreakConchLock(pFile, myHostID) ){ |
| 26687 | + rc = SQLITE_OK; |
| 26688 | + if( lockType==EXCLUSIVE_LOCK ){ |
| 26689 | + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); |
| 26690 | + } |
| 26691 | + if( !rc ){ |
| 26692 | + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); |
| 26693 | + } |
| 26694 | + } |
| 26695 | + } |
| 26696 | + } while( rc==SQLITE_BUSY && nTries<3 ); |
| 26697 | + |
| 26698 | + return rc; |
| 26699 | +} |
| 26700 | + |
| 26701 | +/* Takes the conch by taking a shared lock and read the contents conch, if |
| 26213 | 26702 | ** lockPath is non-NULL, the host ID and lock file path must match. A NULL |
| 26214 | 26703 | ** lockPath means that the lockPath in the conch file will be used if the |
| 26215 | 26704 | ** host IDs match, or a new lock path will be generated automatically |
| 26216 | 26705 | ** and written to the conch file. |
| 26217 | 26706 | */ |
| 26218 | 26707 | static int proxyTakeConch(unixFile *pFile){ |
| 26219 | 26708 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26220 | 26709 | |
| 26221 | | - if( pCtx->conchHeld>0 ){ |
| 26710 | + if( pCtx->conchHeld!=0 ){ |
| 26222 | 26711 | return SQLITE_OK; |
| 26223 | 26712 | }else{ |
| 26224 | 26713 | unixFile *conchFile = pCtx->conchFile; |
| 26225 | | - char testValue[CONCHLEN]; |
| 26226 | | - char conchValue[CONCHLEN]; |
| 26714 | + uuid_t myHostID; |
| 26715 | + int pError = 0; |
| 26716 | + char readBuf[PROXY_MAXCONCHLEN]; |
| 26227 | 26717 | char lockPath[MAXPATHLEN]; |
| 26228 | | - char *tLockPath = NULL; |
| 26718 | + char *tempLockPath = NULL; |
| 26229 | 26719 | int rc = SQLITE_OK; |
| 26230 | | - int readRc = SQLITE_OK; |
| 26231 | | - int syncPerms = 0; |
| 26232 | | - |
| 26720 | + int createConch = 0; |
| 26721 | + int hostIdMatch = 0; |
| 26722 | + int readLen = 0; |
| 26723 | + int tryOldLockPath = 0; |
| 26724 | + int forceNewLockPath = 0; |
| 26725 | + |
| 26233 | 26726 | OSTRACE4("TAKECONCH %d for %s pid=%d\n", conchFile->h, |
| 26234 | 26727 | (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()); |
| 26235 | 26728 | |
| 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; |
| 26729 | + rc = proxyGetHostID(myHostID, &pError); |
| 26730 | + if( (rc&0xff)==SQLITE_IOERR ){ |
| 26731 | + pFile->lastErrno = pError; |
| 26732 | + goto end_takeconch; |
| 26733 | + } |
| 26734 | + rc = proxyConchLock(pFile, myHostID, SHARED_LOCK); |
| 26735 | + if( rc!=SQLITE_OK ){ |
| 26736 | + goto end_takeconch; |
| 26737 | + } |
| 26738 | + /* read the existing conch file */ |
| 26739 | + readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN); |
| 26740 | + if( readLen<0 ){ |
| 26741 | + /* I/O error: lastErrno set by seekAndRead */ |
| 26742 | + pFile->lastErrno = conchFile->lastErrno; |
| 26743 | + rc = SQLITE_IOERR_READ; |
| 26744 | + goto end_takeconch; |
| 26745 | + }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || |
| 26746 | + readBuf[0]!=(char)PROXY_CONCHVERSION ){ |
| 26747 | + /* a short read or version format mismatch means we need to create a new |
| 26748 | + ** conch file. |
| 26749 | + */ |
| 26750 | + createConch = 1; |
| 26751 | + } |
| 26752 | + /* if the host id matches and the lock path already exists in the conch |
| 26753 | + ** we'll try to use the path there, if we can't open that path, we'll |
| 26754 | + ** retry with a new auto-generated path |
| 26755 | + */ |
| 26756 | + do { /* in case we need to try again for an :auto: named lock file */ |
| 26757 | + |
| 26758 | + if( !createConch && !forceNewLockPath ){ |
| 26759 | + hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, |
| 26760 | + PROXY_HOSTIDLEN); |
| 26761 | + /* if the conch has data compare the contents */ |
| 26762 | + if( !pCtx->lockProxyPath ){ |
| 26763 | + /* for auto-named local lock file, just check the host ID and we'll |
| 26764 | + ** use the local lock file path that's already in there |
| 26765 | + */ |
| 26766 | + if( hostIdMatch ){ |
| 26767 | + size_t pathLen = (readLen - PROXY_PATHINDEX); |
| 26768 | + |
| 26769 | + if( pathLen>=MAXPATHLEN ){ |
| 26770 | + pathLen=MAXPATHLEN-1; |
| 26771 | + } |
| 26772 | + memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen); |
| 26773 | + lockPath[pathLen] = 0; |
| 26774 | + tempLockPath = lockPath; |
| 26775 | + tryOldLockPath = 1; |
| 26776 | + /* create a copy of the lock path if the conch is taken */ |
| 26777 | + goto end_takeconch; |
| 26778 | + } |
| 26779 | + }else if( hostIdMatch |
| 26780 | + && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX], |
| 26781 | + readLen-PROXY_PATHINDEX) |
| 26782 | + ){ |
| 26783 | + /* conch host and lock path match */ |
| 26784 | + goto end_takeconch; |
| 26785 | + } |
| 26786 | + } |
| 26787 | + |
| 26788 | + /* if the conch isn't writable and doesn't match, we can't take it */ |
| 26789 | + if( (conchFile->openFlags&O_RDWR) == 0 ){ |
| 26790 | + rc = SQLITE_BUSY; |
| 26791 | + goto end_takeconch; |
| 26792 | + } |
| 26793 | + |
| 26794 | + /* either the conch didn't match or we need to create a new one */ |
| 26795 | + if( !pCtx->lockProxyPath ){ |
| 26796 | + proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN); |
| 26797 | + tempLockPath = lockPath; |
| 26798 | + /* create a copy of the lock path _only_ if the conch is taken */ |
| 26799 | + } |
| 26800 | + |
| 26801 | + /* update conch with host and path (this will fail if other process |
| 26802 | + ** has a shared lock already), if the host id matches, use the big |
| 26803 | + ** stick. |
| 26804 | + */ |
| 26805 | + futimes(conchFile->h, NULL); |
| 26806 | + if( hostIdMatch && !createConch ){ |
| 26807 | + if( conchFile->pLock && conchFile->pLock->cnt>1 ){ |
| 26808 | + /* We are trying for an exclusive lock but another thread in this |
| 26809 | + ** same process is still holding a shared lock. */ |
| 26810 | + rc = SQLITE_BUSY; |
| 26811 | + } else { |
| 26812 | + rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); |
| 26813 | + } |
| 26814 | + }else{ |
| 26815 | + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK); |
| 26816 | + } |
| 26817 | + if( rc==SQLITE_OK ){ |
| 26818 | + char writeBuffer[PROXY_MAXCONCHLEN]; |
| 26819 | + int writeSize = 0; |
| 26820 | + |
| 26821 | + writeBuffer[0] = (char)PROXY_CONCHVERSION; |
| 26822 | + memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); |
| 26823 | + if( pCtx->lockProxyPath!=NULL ){ |
| 26824 | + strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN); |
| 26825 | + }else{ |
| 26826 | + strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); |
| 26827 | + } |
| 26828 | + writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); |
| 26829 | + ftruncate(conchFile->h, writeSize); |
| 26830 | + rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); |
| 26831 | + fsync(conchFile->h); |
| 26832 | + /* If we created a new conch file (not just updated the contents of a |
| 26833 | + ** valid conch file), try to match the permissions of the database |
| 26834 | + */ |
| 26835 | + if( rc==SQLITE_OK && createConch ){ |
| 26836 | + struct stat buf; |
| 26837 | + int err = fstat(pFile->h, &buf); |
| 26838 | + if( err==0 ){ |
| 26839 | + mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | |
| 26840 | + S_IROTH|S_IWOTH); |
| 26841 | + /* try to match the database file R/W permissions, ignore failure */ |
| 26842 | +#ifndef SQLITE_PROXY_DEBUG |
| 26843 | + fchmod(conchFile->h, cmode); |
| 26844 | +#else |
| 26845 | + if( fchmod(conchFile->h, cmode)!=0 ){ |
| 26846 | + int code = errno; |
| 26847 | + fprintf(stderr, "fchmod %o FAILED with %d %s\n", |
| 26848 | + cmode, code, strerror(code)); |
| 26849 | + } else { |
| 26850 | + fprintf(stderr, "fchmod %o SUCCEDED\n",cmode); |
| 26851 | + } |
| 26852 | + }else{ |
| 26853 | + int code = errno; |
| 26854 | + fprintf(stderr, "STAT FAILED[%d] with %d %s\n", |
| 26855 | + err, code, strerror(code)); |
| 26856 | +#endif |
| 26857 | + } |
| 26858 | + } |
| 26859 | + } |
| 26860 | + conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); |
| 26861 | + |
| 26862 | + end_takeconch: |
| 26863 | + OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h); |
| 26864 | + if( rc==SQLITE_OK && pFile->openFlags ){ |
| 26865 | + if( pFile->h>=0 ){ |
| 26866 | +#ifdef STRICT_CLOSE_ERROR |
| 26867 | + if( close(pFile->h) ){ |
| 26868 | + pFile->lastErrno = errno; |
| 26869 | + return SQLITE_IOERR_CLOSE; |
| 26870 | + } |
| 26871 | +#else |
| 26872 | + close(pFile->h); /* silently leak fd if fail */ |
| 26873 | +#endif |
| 26874 | + } |
| 26875 | + pFile->h = -1; |
| 26876 | + int fd = open(pCtx->dbPath, pFile->openFlags, |
| 26877 | + SQLITE_DEFAULT_FILE_PERMISSIONS); |
| 26878 | + OSTRACE2("TRANSPROXY: OPEN %d\n", fd); |
| 26879 | + if( fd>=0 ){ |
| 26880 | + pFile->h = fd; |
| 26881 | + }else{ |
| 26882 | + rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called |
| 26883 | + during locking */ |
| 26884 | + } |
| 26885 | + } |
| 26886 | + if( rc==SQLITE_OK && !pCtx->lockProxy ){ |
| 26887 | + char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath; |
| 26888 | + rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1); |
| 26889 | + if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){ |
| 26890 | + /* we couldn't create the proxy lock file with the old lock file path |
| 26891 | + ** so try again via auto-naming |
| 26892 | + */ |
| 26893 | + forceNewLockPath = 1; |
| 26894 | + tryOldLockPath = 0; |
| 26895 | + continue; /* go back to the do {} while start point, try again */ |
| 26896 | + } |
| 26897 | + } |
| 26898 | + if( rc==SQLITE_OK ){ |
| 26899 | + /* Need to make a copy of path if we extracted the value |
| 26900 | + ** from the conch file or the path was allocated on the stack |
| 26901 | + */ |
| 26902 | + if( tempLockPath ){ |
| 26903 | + pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath); |
| 26904 | + if( !pCtx->lockProxyPath ){ |
| 26905 | + rc = SQLITE_NOMEM; |
| 26906 | + } |
| 26907 | + } |
| 26908 | + } |
| 26909 | + if( rc==SQLITE_OK ){ |
| 26910 | + pCtx->conchHeld = 1; |
| 26911 | + |
| 26912 | + if( pCtx->lockProxy->pMethod == &afpIoMethods ){ |
| 26913 | + afpLockingContext *afpCtx; |
| 26914 | + afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext; |
| 26915 | + afpCtx->dbPath = pCtx->lockProxyPath; |
| 26916 | + } |
| 26917 | + } else { |
| 26918 | + conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); |
| 26919 | + } |
| 26920 | + OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed"); |
| 26921 | + return rc; |
| 26922 | + } while (1); /* in case we need to retry the :auto: lock file - we should never get here except via the 'continue' call. */ |
| 26364 | 26923 | } |
| 26365 | 26924 | } |
| 26366 | 26925 | |
| 26367 | 26926 | /* |
| 26368 | 26927 | ** If pFile holds a lock on a conch file, then release that lock. |
| | @@ -26375,12 +26934,14 @@ |
| 26375 | 26934 | pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26376 | 26935 | conchFile = pCtx->conchFile; |
| 26377 | 26936 | OSTRACE4("RELEASECONCH %d for %s pid=%d\n", conchFile->h, |
| 26378 | 26937 | (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), |
| 26379 | 26938 | getpid()); |
| 26939 | + if( pCtx->conchHeld>0 ){ |
| 26940 | + rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); |
| 26941 | + } |
| 26380 | 26942 | pCtx->conchHeld = 0; |
| 26381 | | - rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); |
| 26382 | 26943 | OSTRACE3("RELEASECONCH %d %s\n", conchFile->h, |
| 26383 | 26944 | (rc==SQLITE_OK ? "ok" : "failed")); |
| 26384 | 26945 | return rc; |
| 26385 | 26946 | } |
| 26386 | 26947 | |
| | @@ -26472,22 +27033,22 @@ |
| 26472 | 27033 | #if defined(__APPLE__) |
| 26473 | 27034 | if( pFile->pMethod == &afpIoMethods ){ |
| 26474 | 27035 | /* afp style keeps a reference to the db path in the filePath field |
| 26475 | 27036 | ** of the struct */ |
| 26476 | 27037 | assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); |
| 26477 | | - strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath); |
| 26478 | | - }else |
| 27038 | + strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN); |
| 27039 | + } else |
| 26479 | 27040 | #endif |
| 26480 | 27041 | if( pFile->pMethod == &dotlockIoMethods ){ |
| 26481 | 27042 | /* dot lock style uses the locking context to store the dot lock |
| 26482 | 27043 | ** file path */ |
| 26483 | 27044 | int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX); |
| 26484 | 27045 | memcpy(dbPath, (char *)pFile->lockingContext, len + 1); |
| 26485 | 27046 | }else{ |
| 26486 | 27047 | /* all other styles use the locking context to store the db file path */ |
| 26487 | 27048 | assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); |
| 26488 | | - strcpy(dbPath, (char *)pFile->lockingContext); |
| 27049 | + strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN); |
| 26489 | 27050 | } |
| 26490 | 27051 | return SQLITE_OK; |
| 26491 | 27052 | } |
| 26492 | 27053 | |
| 26493 | 27054 | /* |
| | @@ -26523,31 +27084,57 @@ |
| 26523 | 27084 | } |
| 26524 | 27085 | memset(pCtx, 0, sizeof(*pCtx)); |
| 26525 | 27086 | |
| 26526 | 27087 | rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath); |
| 26527 | 27088 | if( rc==SQLITE_OK ){ |
| 26528 | | - rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile); |
| 27089 | + rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0); |
| 27090 | + if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){ |
| 27091 | + /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and |
| 27092 | + ** (c) the file system is read-only, then enable no-locking access. |
| 27093 | + ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts |
| 27094 | + ** that openFlags will have only one of O_RDONLY or O_RDWR. |
| 27095 | + */ |
| 27096 | + struct statfs fsInfo; |
| 27097 | + struct stat conchInfo; |
| 27098 | + int goLockless = 0; |
| 27099 | + |
| 27100 | + if( stat(pCtx->conchFilePath, &conchInfo) == -1 ) { |
| 27101 | + int err = errno; |
| 27102 | + if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){ |
| 27103 | + goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY; |
| 27104 | + } |
| 27105 | + } |
| 27106 | + if( goLockless ){ |
| 27107 | + pCtx->conchHeld = -1; /* read only FS/ lockless */ |
| 27108 | + rc = SQLITE_OK; |
| 27109 | + } |
| 27110 | + } |
| 26529 | 27111 | } |
| 26530 | 27112 | if( rc==SQLITE_OK && lockPath ){ |
| 26531 | 27113 | pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); |
| 26532 | 27114 | } |
| 26533 | 27115 | |
| 27116 | + if( rc==SQLITE_OK ){ |
| 27117 | + pCtx->dbPath = sqlite3DbStrDup(0, dbPath); |
| 27118 | + if( pCtx->dbPath==NULL ){ |
| 27119 | + rc = SQLITE_NOMEM; |
| 27120 | + } |
| 27121 | + } |
| 26534 | 27122 | if( rc==SQLITE_OK ){ |
| 26535 | 27123 | /* all memory is allocated, proxys are created and assigned, |
| 26536 | 27124 | ** switch the locking context and pMethod then return. |
| 26537 | 27125 | */ |
| 26538 | | - pCtx->dbPath = sqlite3DbStrDup(0, dbPath); |
| 26539 | 27126 | pCtx->oldLockingContext = pFile->lockingContext; |
| 26540 | 27127 | pFile->lockingContext = pCtx; |
| 26541 | 27128 | pCtx->pOldMethod = pFile->pMethod; |
| 26542 | 27129 | pFile->pMethod = &proxyIoMethods; |
| 26543 | 27130 | }else{ |
| 26544 | 27131 | if( pCtx->conchFile ){ |
| 26545 | | - rc = pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); |
| 26546 | | - if( rc ) return rc; |
| 27132 | + pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); |
| 26547 | 27133 | sqlite3_free(pCtx->conchFile); |
| 26548 | 27134 | } |
| 27135 | + sqlite3_free(pCtx->lockProxyPath); |
| 26549 | 27136 | sqlite3_free(pCtx->conchFilePath); |
| 26550 | 27137 | sqlite3_free(pCtx); |
| 26551 | 27138 | } |
| 26552 | 27139 | OSTRACE3("TRANSPROXY %d %s\n", pFile->h, |
| 26553 | 27140 | (rc==SQLITE_OK ? "ok" : "failed")); |
| | @@ -26632,12 +27219,16 @@ |
| 26632 | 27219 | static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) { |
| 26633 | 27220 | unixFile *pFile = (unixFile*)id; |
| 26634 | 27221 | int rc = proxyTakeConch(pFile); |
| 26635 | 27222 | if( rc==SQLITE_OK ){ |
| 26636 | 27223 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26637 | | - unixFile *proxy = pCtx->lockProxy; |
| 26638 | | - return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut); |
| 27224 | + if( pCtx->conchHeld>0 ){ |
| 27225 | + unixFile *proxy = pCtx->lockProxy; |
| 27226 | + return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut); |
| 27227 | + }else{ /* conchHeld < 0 is lockless */ |
| 27228 | + pResOut=0; |
| 27229 | + } |
| 26639 | 27230 | } |
| 26640 | 27231 | return rc; |
| 26641 | 27232 | } |
| 26642 | 27233 | |
| 26643 | 27234 | /* |
| | @@ -26667,13 +27258,17 @@ |
| 26667 | 27258 | static int proxyLock(sqlite3_file *id, int locktype) { |
| 26668 | 27259 | unixFile *pFile = (unixFile*)id; |
| 26669 | 27260 | int rc = proxyTakeConch(pFile); |
| 26670 | 27261 | if( rc==SQLITE_OK ){ |
| 26671 | 27262 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26672 | | - unixFile *proxy = pCtx->lockProxy; |
| 26673 | | - rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype); |
| 26674 | | - pFile->locktype = proxy->locktype; |
| 27263 | + if( pCtx->conchHeld>0 ){ |
| 27264 | + unixFile *proxy = pCtx->lockProxy; |
| 27265 | + rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype); |
| 27266 | + pFile->locktype = proxy->locktype; |
| 27267 | + }else{ |
| 27268 | + /* conchHeld < 0 is lockless */ |
| 27269 | + } |
| 26675 | 27270 | } |
| 26676 | 27271 | return rc; |
| 26677 | 27272 | } |
| 26678 | 27273 | |
| 26679 | 27274 | |
| | @@ -26687,13 +27282,17 @@ |
| 26687 | 27282 | static int proxyUnlock(sqlite3_file *id, int locktype) { |
| 26688 | 27283 | unixFile *pFile = (unixFile*)id; |
| 26689 | 27284 | int rc = proxyTakeConch(pFile); |
| 26690 | 27285 | if( rc==SQLITE_OK ){ |
| 26691 | 27286 | proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; |
| 26692 | | - unixFile *proxy = pCtx->lockProxy; |
| 26693 | | - rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype); |
| 26694 | | - pFile->locktype = proxy->locktype; |
| 27287 | + if( pCtx->conchHeld>0 ){ |
| 27288 | + unixFile *proxy = pCtx->lockProxy; |
| 27289 | + rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype); |
| 27290 | + pFile->locktype = proxy->locktype; |
| 27291 | + }else{ |
| 27292 | + /* conchHeld < 0 is lockless */ |
| 27293 | + } |
| 26695 | 27294 | } |
| 26696 | 27295 | return rc; |
| 26697 | 27296 | } |
| 26698 | 27297 | |
| 26699 | 27298 | /* |
| | @@ -26816,11 +27415,10 @@ |
| 26816 | 27415 | #else |
| 26817 | 27416 | UNIXVFS("unix", posixIoFinder ), |
| 26818 | 27417 | #endif |
| 26819 | 27418 | UNIXVFS("unix-none", nolockIoFinder ), |
| 26820 | 27419 | UNIXVFS("unix-dotfile", dotlockIoFinder ), |
| 26821 | | - UNIXVFS("unix-wfl", posixWflIoFinder ), |
| 26822 | 27420 | #if OS_VXWORKS |
| 26823 | 27421 | UNIXVFS("unix-namedsem", semIoFinder ), |
| 26824 | 27422 | #endif |
| 26825 | 27423 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 26826 | 27424 | UNIXVFS("unix-posix", posixIoFinder ), |
| | @@ -26828,10 +27426,11 @@ |
| 26828 | 27426 | UNIXVFS("unix-flock", flockIoFinder ), |
| 26829 | 27427 | #endif |
| 26830 | 27428 | #endif |
| 26831 | 27429 | #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) |
| 26832 | 27430 | UNIXVFS("unix-afp", afpIoFinder ), |
| 27431 | + UNIXVFS("unix-nfs", nfsIoFinder ), |
| 26833 | 27432 | UNIXVFS("unix-proxy", proxyIoFinder ), |
| 26834 | 27433 | #endif |
| 26835 | 27434 | }; |
| 26836 | 27435 | unsigned int i; /* Loop counter */ |
| 26837 | 27436 | |
| | @@ -28491,11 +29090,11 @@ |
| 28491 | 29090 | free(zConverted); |
| 28492 | 29091 | if( flags & SQLITE_OPEN_READWRITE ){ |
| 28493 | 29092 | return winOpen(pVfs, zName, id, |
| 28494 | 29093 | ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); |
| 28495 | 29094 | }else{ |
| 28496 | | - return SQLITE_CANTOPEN; |
| 29095 | + return SQLITE_CANTOPEN_BKPT; |
| 28497 | 29096 | } |
| 28498 | 29097 | } |
| 28499 | 29098 | if( pOutFlags ){ |
| 28500 | 29099 | if( flags & SQLITE_OPEN_READWRITE ){ |
| 28501 | 29100 | *pOutFlags = SQLITE_OPEN_READWRITE; |
| | @@ -28513,11 +29112,11 @@ |
| 28513 | 29112 | (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) |
| 28514 | 29113 | && !winceCreateLock(zName, pFile) |
| 28515 | 29114 | ){ |
| 28516 | 29115 | CloseHandle(h); |
| 28517 | 29116 | free(zConverted); |
| 28518 | | - return SQLITE_CANTOPEN; |
| 29117 | + return SQLITE_CANTOPEN_BKPT; |
| 28519 | 29118 | } |
| 28520 | 29119 | if( isTemp ){ |
| 28521 | 29120 | pFile->zDeleteOnClose = zConverted; |
| 28522 | 29121 | }else |
| 28523 | 29122 | #endif |
| | @@ -29600,10 +30199,11 @@ |
| 29600 | 30199 | SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ |
| 29601 | 30200 | assert( pCache->nRef==0 && pCache->pDirty==0 ); |
| 29602 | 30201 | if( pCache->pCache ){ |
| 29603 | 30202 | sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache); |
| 29604 | 30203 | pCache->pCache = 0; |
| 30204 | + pCache->pPage1 = 0; |
| 29605 | 30205 | } |
| 29606 | 30206 | pCache->szPage = szPage; |
| 29607 | 30207 | } |
| 29608 | 30208 | |
| 29609 | 30209 | /* |
| | @@ -29653,10 +30253,11 @@ |
| 29653 | 30253 | expensive_assert( pcacheCheckSynced(pCache) ); |
| 29654 | 30254 | for(pPg=pCache->pSynced; |
| 29655 | 30255 | pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); |
| 29656 | 30256 | pPg=pPg->pDirtyPrev |
| 29657 | 30257 | ); |
| 30258 | + pCache->pSynced = pPg; |
| 29658 | 30259 | if( !pPg ){ |
| 29659 | 30260 | for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); |
| 29660 | 30261 | } |
| 29661 | 30262 | if( pPg ){ |
| 29662 | 30263 | int rc; |
| | @@ -34067,13 +34668,11 @@ |
| 34067 | 34668 | ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to |
| 34068 | 34669 | ** make the file smaller (presumably by auto-vacuum code). Do not write |
| 34069 | 34670 | ** any such pages to the file. |
| 34070 | 34671 | ** |
| 34071 | 34672 | ** 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. |
| 34673 | + ** set (set by sqlite3PagerDontWrite()). |
| 34075 | 34674 | */ |
| 34076 | 34675 | if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ |
| 34077 | 34676 | i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ |
| 34078 | 34677 | char *pData; /* Data to write */ |
| 34079 | 34678 | |
| | @@ -34356,11 +34955,11 @@ |
| 34356 | 34955 | ** the database being opened will be more than pVfs->mxPathname |
| 34357 | 34956 | ** bytes in length. This means the database cannot be opened, |
| 34358 | 34957 | ** as it will not be possible to open the journal file or even |
| 34359 | 34958 | ** check for a hot-journal before reading. |
| 34360 | 34959 | */ |
| 34361 | | - rc = SQLITE_CANTOPEN; |
| 34960 | + rc = SQLITE_CANTOPEN_BKPT; |
| 34362 | 34961 | } |
| 34363 | 34962 | if( rc!=SQLITE_OK ){ |
| 34364 | 34963 | sqlite3_free(zPathname); |
| 34365 | 34964 | return rc; |
| 34366 | 34965 | } |
| | @@ -34815,11 +35414,11 @@ |
| 34815 | 35414 | int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; |
| 34816 | 35415 | assert( !pPager->tempFile ); |
| 34817 | 35416 | rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); |
| 34818 | 35417 | assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); |
| 34819 | 35418 | if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ |
| 34820 | | - rc = SQLITE_CANTOPEN; |
| 35419 | + rc = SQLITE_CANTOPEN_BKPT; |
| 34821 | 35420 | sqlite3OsClose(pPager->jfd); |
| 34822 | 35421 | } |
| 34823 | 35422 | }else{ |
| 34824 | 35423 | /* If the journal does not exist, it usually means that some |
| 34825 | 35424 | ** other connection managed to get in and roll it back before |
| | @@ -35034,11 +35633,11 @@ |
| 35034 | 35633 | rc = sqlite3PagerPagecount(pPager, &nMax); |
| 35035 | 35634 | if( rc!=SQLITE_OK ){ |
| 35036 | 35635 | goto pager_acquire_err; |
| 35037 | 35636 | } |
| 35038 | 35637 | |
| 35039 | | - if( MEMDB || nMax<(int)pgno || noContent ){ |
| 35638 | + if( MEMDB || nMax<(int)pgno || noContent || !isOpen(pPager->fd) ){ |
| 35040 | 35639 | if( pgno>pPager->mxPgno ){ |
| 35041 | 35640 | rc = SQLITE_FULL; |
| 35042 | 35641 | goto pager_acquire_err; |
| 35043 | 35642 | } |
| 35044 | 35643 | if( noContent ){ |
| | @@ -35054,13 +35653,12 @@ |
| 35054 | 35653 | testcase( rc==SQLITE_NOMEM ); |
| 35055 | 35654 | } |
| 35056 | 35655 | TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); |
| 35057 | 35656 | testcase( rc==SQLITE_NOMEM ); |
| 35058 | 35657 | sqlite3EndBenignMalloc(); |
| 35059 | | - }else{ |
| 35060 | | - memset(pPg->pData, 0, pPager->pageSize); |
| 35061 | 35658 | } |
| 35659 | + memset(pPg->pData, 0, pPager->pageSize); |
| 35062 | 35660 | IOTRACE(("ZERO %p %d\n", pPager, pgno)); |
| 35063 | 35661 | }else{ |
| 35064 | 35662 | assert( pPg->pPager==pPager ); |
| 35065 | 35663 | rc = readDbPage(pPg); |
| 35066 | 35664 | if( rc!=SQLITE_OK ){ |
| | @@ -35578,11 +36176,10 @@ |
| 35578 | 36176 | SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ |
| 35579 | 36177 | return pPg->flags&PGHDR_DIRTY; |
| 35580 | 36178 | } |
| 35581 | 36179 | #endif |
| 35582 | 36180 | |
| 35583 | | -#ifndef SQLITE_SECURE_DELETE |
| 35584 | 36181 | /* |
| 35585 | 36182 | ** A call to this routine tells the pager that it is not necessary to |
| 35586 | 36183 | ** write the information on page pPg back to the disk, even though |
| 35587 | 36184 | ** that page might be marked as dirty. This happens, for example, when |
| 35588 | 36185 | ** the page has been added as a leaf of the freelist and so its |
| | @@ -35604,11 +36201,10 @@ |
| 35604 | 36201 | #ifdef SQLITE_CHECK_PAGES |
| 35605 | 36202 | pPg->pageHash = pager_pagehash(pPg); |
| 35606 | 36203 | #endif |
| 35607 | 36204 | } |
| 35608 | 36205 | } |
| 35609 | | -#endif /* !defined(SQLITE_SECURE_DELETE) */ |
| 35610 | 36206 | |
| 35611 | 36207 | /* |
| 35612 | 36208 | ** This routine is called to increment the value of the database file |
| 35613 | 36209 | ** change-counter, stored as a 4-byte big-endian integer starting at |
| 35614 | 36210 | ** byte offset 24 of the pager file. |
| | @@ -36174,34 +36770,38 @@ |
| 36174 | 36770 | |
| 36175 | 36771 | /* Figure out how many savepoints will still be active after this |
| 36176 | 36772 | ** operation. Store this value in nNew. Then free resources associated |
| 36177 | 36773 | ** with any savepoints that are destroyed by this operation. |
| 36178 | 36774 | */ |
| 36179 | | - nNew = iSavepoint + (op==SAVEPOINT_ROLLBACK); |
| 36775 | + nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1); |
| 36180 | 36776 | for(ii=nNew; ii<pPager->nSavepoint; ii++){ |
| 36181 | 36777 | sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); |
| 36182 | 36778 | } |
| 36183 | 36779 | pPager->nSavepoint = nNew; |
| 36184 | 36780 | |
| 36185 | | - /* If this is a rollback operation, playback the specified savepoint. |
| 36781 | + /* If this is a release of the outermost savepoint, truncate |
| 36782 | + ** the sub-journal to zero bytes in size. */ |
| 36783 | + if( op==SAVEPOINT_RELEASE ){ |
| 36784 | + if( nNew==0 && isOpen(pPager->sjfd) ){ |
| 36785 | + /* Only truncate if it is an in-memory sub-journal. */ |
| 36786 | + if( sqlite3IsMemJournal(pPager->sjfd) ){ |
| 36787 | + rc = sqlite3OsTruncate(pPager->sjfd, 0); |
| 36788 | + } |
| 36789 | + pPager->nSubRec = 0; |
| 36790 | + } |
| 36791 | + } |
| 36792 | + /* Else this is a rollback operation, playback the specified savepoint. |
| 36186 | 36793 | ** If this is a temp-file, it is possible that the journal file has |
| 36187 | 36794 | ** not yet been opened. In this case there have been no changes to |
| 36188 | 36795 | ** the database file, so the playback operation can be skipped. |
| 36189 | 36796 | */ |
| 36190 | | - if( op==SAVEPOINT_ROLLBACK && isOpen(pPager->jfd) ){ |
| 36797 | + else if( isOpen(pPager->jfd) ){ |
| 36191 | 36798 | PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; |
| 36192 | 36799 | rc = pagerPlaybackSavepoint(pPager, pSavepoint); |
| 36193 | 36800 | assert(rc!=SQLITE_DONE); |
| 36194 | 36801 | } |
| 36195 | 36802 | |
| 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 | 36803 | } |
| 36204 | 36804 | return rc; |
| 36205 | 36805 | } |
| 36206 | 36806 | |
| 36207 | 36807 | /* |
| | @@ -36957,10 +37557,11 @@ |
| 36957 | 37557 | sqlite3 *db; /* Database connection currently using this Btree */ |
| 36958 | 37558 | BtCursor *pCursor; /* A list of all open cursors */ |
| 36959 | 37559 | MemPage *pPage1; /* First page of the database */ |
| 36960 | 37560 | u8 readOnly; /* True if the underlying file is readonly */ |
| 36961 | 37561 | u8 pageSizeFixed; /* True if the page size can no longer be changed */ |
| 37562 | + u8 secureDelete; /* True if secure_delete is enabled */ |
| 36962 | 37563 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 36963 | 37564 | u8 autoVacuum; /* True if auto-vacuum is enabled */ |
| 36964 | 37565 | u8 incrVacuum; /* True if incr-vacuum is enabled */ |
| 36965 | 37566 | #endif |
| 36966 | 37567 | u16 pageSize; /* Total number of bytes on a page */ |
| | @@ -38780,15 +39381,15 @@ |
| 38780 | 39381 | assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); |
| 38781 | 39382 | assert( (start + size)<=pPage->pBt->usableSize ); |
| 38782 | 39383 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 38783 | 39384 | assert( size>=0 ); /* Minimum cell size is 4 */ |
| 38784 | 39385 | |
| 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 |
| 39386 | + if( pPage->pBt->secureDelete ){ |
| 39387 | + /* Overwrite deleted information with zeros when the secure_delete |
| 39388 | + ** option is enabled */ |
| 39389 | + memset(&data[start], 0, size); |
| 39390 | + } |
| 38790 | 39391 | |
| 38791 | 39392 | /* Add the space back into the linked list of freeblocks. Note that |
| 38792 | 39393 | ** even though the freeblock list was checked by btreeInitPage(), |
| 38793 | 39394 | ** btreeInitPage() did not detect overlapping cells or |
| 38794 | 39395 | ** freeblocks that overlapped cells. Nor does it detect when the |
| | @@ -39016,13 +39617,13 @@ |
| 39016 | 39617 | assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); |
| 39017 | 39618 | assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); |
| 39018 | 39619 | assert( sqlite3PagerGetData(pPage->pDbPage) == data ); |
| 39019 | 39620 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 39020 | 39621 | assert( sqlite3_mutex_held(pBt->mutex) ); |
| 39021 | | -#ifdef SQLITE_SECURE_DELETE |
| 39022 | | - memset(&data[hdr], 0, pBt->usableSize - hdr); |
| 39023 | | -#endif |
| 39622 | + if( pBt->secureDelete ){ |
| 39623 | + memset(&data[hdr], 0, pBt->usableSize - hdr); |
| 39624 | + } |
| 39024 | 39625 | data[hdr] = (char)flags; |
| 39025 | 39626 | first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); |
| 39026 | 39627 | memset(&data[hdr+1], 0, 4); |
| 39027 | 39628 | data[hdr+7] = 0; |
| 39028 | 39629 | put2byte(&data[hdr+5], pBt->usableSize); |
| | @@ -39338,10 +39939,13 @@ |
| 39338 | 39939 | p->pBt = pBt; |
| 39339 | 39940 | |
| 39340 | 39941 | pBt->pCursor = 0; |
| 39341 | 39942 | pBt->pPage1 = 0; |
| 39342 | 39943 | pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); |
| 39944 | +#ifdef SQLITE_SECURE_DELETE |
| 39945 | + pBt->secureDelete = 1; |
| 39946 | +#endif |
| 39343 | 39947 | pBt->pageSize = get2byte(&zDbHeader[16]); |
| 39344 | 39948 | if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE |
| 39345 | 39949 | || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ |
| 39346 | 39950 | pBt->pageSize = 0; |
| 39347 | 39951 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| | @@ -39694,10 +40298,27 @@ |
| 39694 | 40298 | sqlite3BtreeEnter(p); |
| 39695 | 40299 | n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); |
| 39696 | 40300 | sqlite3BtreeLeave(p); |
| 39697 | 40301 | return n; |
| 39698 | 40302 | } |
| 40303 | + |
| 40304 | +/* |
| 40305 | +** Set the secureDelete flag if newFlag is 0 or 1. If newFlag is -1, |
| 40306 | +** then make no changes. Always return the value of the secureDelete |
| 40307 | +** setting after the change. |
| 40308 | +*/ |
| 40309 | +SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ |
| 40310 | + int b; |
| 40311 | + if( p==0 ) return 0; |
| 40312 | + sqlite3BtreeEnter(p); |
| 40313 | + if( newFlag>=0 ){ |
| 40314 | + p->pBt->secureDelete = (newFlag!=0) ? 1 : 0; |
| 40315 | + } |
| 40316 | + b = p->pBt->secureDelete; |
| 40317 | + sqlite3BtreeLeave(p); |
| 40318 | + return b; |
| 40319 | +} |
| 39699 | 40320 | #endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ |
| 39700 | 40321 | |
| 39701 | 40322 | /* |
| 39702 | 40323 | ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' |
| 39703 | 40324 | ** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it |
| | @@ -42437,21 +43058,21 @@ |
| 42437 | 43058 | rc = sqlite3PagerWrite(pPage1->pDbPage); |
| 42438 | 43059 | if( rc ) goto freepage_out; |
| 42439 | 43060 | nFree = get4byte(&pPage1->aData[36]); |
| 42440 | 43061 | put4byte(&pPage1->aData[36], nFree+1); |
| 42441 | 43062 | |
| 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 |
| 43063 | + if( pBt->secureDelete ){ |
| 43064 | + /* If the secure_delete option is enabled, then |
| 43065 | + ** always fully overwrite deleted information with zeros. |
| 43066 | + */ |
| 43067 | + if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) ) |
| 43068 | + || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0) |
| 43069 | + ){ |
| 43070 | + goto freepage_out; |
| 43071 | + } |
| 43072 | + memset(pPage->aData, 0, pPage->pBt->pageSize); |
| 43073 | + } |
| 42453 | 43074 | |
| 42454 | 43075 | /* If the database supports auto-vacuum, write an entry in the pointer-map |
| 42455 | 43076 | ** to indicate that the page is free. |
| 42456 | 43077 | */ |
| 42457 | 43078 | if( ISAUTOVACUUM ){ |
| | @@ -42498,15 +43119,13 @@ |
| 42498 | 43119 | */ |
| 42499 | 43120 | rc = sqlite3PagerWrite(pTrunk->pDbPage); |
| 42500 | 43121 | if( rc==SQLITE_OK ){ |
| 42501 | 43122 | put4byte(&pTrunk->aData[4], nLeaf+1); |
| 42502 | 43123 | put4byte(&pTrunk->aData[8+nLeaf*4], iPage); |
| 42503 | | -#ifndef SQLITE_SECURE_DELETE |
| 42504 | | - if( pPage ){ |
| 43124 | + if( pPage && !pBt->secureDelete ){ |
| 42505 | 43125 | sqlite3PagerDontWrite(pPage->pDbPage); |
| 42506 | 43126 | } |
| 42507 | | -#endif |
| 42508 | 43127 | rc = btreeSetHasContent(pBt, iPage); |
| 42509 | 43128 | } |
| 42510 | 43129 | TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); |
| 42511 | 43130 | goto freepage_out; |
| 42512 | 43131 | } |
| | @@ -42576,11 +43195,29 @@ |
| 42576 | 43195 | } |
| 42577 | 43196 | if( nOvfl ){ |
| 42578 | 43197 | rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); |
| 42579 | 43198 | if( rc ) return rc; |
| 42580 | 43199 | } |
| 42581 | | - rc = freePage2(pBt, pOvfl, ovflPgno); |
| 43200 | + |
| 43201 | + if( (pOvfl || (pOvfl = btreePageLookup(pBt, ovflPgno))) |
| 43202 | + && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1 |
| 43203 | + ){ |
| 43204 | + /* There is no reason any cursor should have an outstanding reference |
| 43205 | + ** to an overflow page belonging to a cell that is being deleted/updated. |
| 43206 | + ** So if there exists more than one reference to this page, then it |
| 43207 | + ** must not really be an overflow page and the database must be corrupt. |
| 43208 | + ** It is helpful to detect this before calling freePage2(), as |
| 43209 | + ** freePage2() may zero the page contents if secure-delete mode is |
| 43210 | + ** enabled. If this 'overflow' page happens to be a page that the |
| 43211 | + ** caller is iterating through or using in some other way, this |
| 43212 | + ** can be problematic. |
| 43213 | + */ |
| 43214 | + rc = SQLITE_CORRUPT_BKPT; |
| 43215 | + }else{ |
| 43216 | + rc = freePage2(pBt, pOvfl, ovflPgno); |
| 43217 | + } |
| 43218 | + |
| 42582 | 43219 | if( pOvfl ){ |
| 42583 | 43220 | sqlite3PagerUnref(pOvfl->pDbPage); |
| 42584 | 43221 | } |
| 42585 | 43222 | if( rc ) return rc; |
| 42586 | 43223 | ovflPgno = iNext; |
| | @@ -42820,11 +43457,11 @@ |
| 42820 | 43457 | int sz, /* Bytes of content in pCell */ |
| 42821 | 43458 | u8 *pTemp, /* Temp storage space for pCell, if needed */ |
| 42822 | 43459 | Pgno iChild, /* If non-zero, replace first 4 bytes with this value */ |
| 42823 | 43460 | int *pRC /* Read and write return code from here */ |
| 42824 | 43461 | ){ |
| 42825 | | - int idx; /* Where to write new cell content in data[] */ |
| 43462 | + int idx = 0; /* Where to write new cell content in data[] */ |
| 42826 | 43463 | int j; /* Loop counter */ |
| 42827 | 43464 | int end; /* First byte past the last cell pointer in data[] */ |
| 42828 | 43465 | int ins; /* Index in data[] where new cell pointer is inserted */ |
| 42829 | 43466 | int cellOffset; /* Address of first cell pointer in data[] */ |
| 42830 | 43467 | u8 *data; /* The content of the whole page */ |
| | @@ -43311,14 +43948,21 @@ |
| 43311 | 43948 | ** Unless SQLite is compiled in secure-delete mode. In this case, |
| 43312 | 43949 | ** the dropCell() routine will overwrite the entire cell with zeroes. |
| 43313 | 43950 | ** In this case, temporarily copy the cell into the aOvflSpace[] |
| 43314 | 43951 | ** buffer. It will be copied out again as soon as the aSpace[] buffer |
| 43315 | 43952 | ** 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 |
| 43953 | + if( pBt->secureDelete ){ |
| 43954 | + int iOff = apDiv[i] - pParent->aData; |
| 43955 | + if( (iOff+szNew[i])>pBt->usableSize ){ |
| 43956 | + rc = SQLITE_CORRUPT_BKPT; |
| 43957 | + memset(apOld, 0, (i+1)*sizeof(MemPage*)); |
| 43958 | + goto balance_cleanup; |
| 43959 | + }else{ |
| 43960 | + memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]); |
| 43961 | + apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; |
| 43962 | + } |
| 43963 | + } |
| 43320 | 43964 | dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); |
| 43321 | 43965 | } |
| 43322 | 43966 | } |
| 43323 | 43967 | |
| 43324 | 43968 | /* Make nMaxCells a multiple of 4 in order to preserve 8-byte |
| | @@ -43434,11 +44078,11 @@ |
| 43434 | 44078 | szNew[k] = subtotal - szCell[i]; |
| 43435 | 44079 | cntNew[k] = i; |
| 43436 | 44080 | if( leafData ){ i--; } |
| 43437 | 44081 | subtotal = 0; |
| 43438 | 44082 | k++; |
| 43439 | | - if( k>NB+1 ){ rc = SQLITE_CORRUPT; goto balance_cleanup; } |
| 44083 | + if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } |
| 43440 | 44084 | } |
| 43441 | 44085 | } |
| 43442 | 44086 | szNew[k] = subtotal; |
| 43443 | 44087 | cntNew[k] = nCell; |
| 43444 | 44088 | k++; |
| | @@ -43488,11 +44132,11 @@ |
| 43488 | 44132 | |
| 43489 | 44133 | /* |
| 43490 | 44134 | ** Allocate k new pages. Reuse old pages where possible. |
| 43491 | 44135 | */ |
| 43492 | 44136 | if( apOld[0]->pgno<=1 ){ |
| 43493 | | - rc = SQLITE_CORRUPT; |
| 44137 | + rc = SQLITE_CORRUPT_BKPT; |
| 43494 | 44138 | goto balance_cleanup; |
| 43495 | 44139 | } |
| 43496 | 44140 | pageFlags = apOld[0]->aData[0]; |
| 43497 | 44141 | for(i=0; i<k; i++){ |
| 43498 | 44142 | MemPage *pNew; |
| | @@ -44926,11 +45570,13 @@ |
| 44926 | 45570 | ** the root of the tree. |
| 44927 | 45571 | */ |
| 44928 | 45572 | static int checkTreePage( |
| 44929 | 45573 | IntegrityCk *pCheck, /* Context for the sanity check */ |
| 44930 | 45574 | int iPage, /* Page number of the page to check */ |
| 44931 | | - char *zParentContext /* Parent context */ |
| 45575 | + char *zParentContext, /* Parent context */ |
| 45576 | + i64 *pnParentMinKey, |
| 45577 | + i64 *pnParentMaxKey |
| 44932 | 45578 | ){ |
| 44933 | 45579 | MemPage *pPage; |
| 44934 | 45580 | int i, rc, depth, d2, pgno, cnt; |
| 44935 | 45581 | int hdr, cellStart; |
| 44936 | 45582 | int nCell; |
| | @@ -44937,10 +45583,12 @@ |
| 44937 | 45583 | u8 *data; |
| 44938 | 45584 | BtShared *pBt; |
| 44939 | 45585 | int usableSize; |
| 44940 | 45586 | char zContext[100]; |
| 44941 | 45587 | char *hit = 0; |
| 45588 | + i64 nMinKey = 0; |
| 45589 | + i64 nMaxKey = 0; |
| 44942 | 45590 | |
| 44943 | 45591 | sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); |
| 44944 | 45592 | |
| 44945 | 45593 | /* Check that the page exists |
| 44946 | 45594 | */ |
| | @@ -44979,10 +45627,20 @@ |
| 44979 | 45627 | "On tree page %d cell %d: ", iPage, i); |
| 44980 | 45628 | pCell = findCell(pPage,i); |
| 44981 | 45629 | btreeParseCellPtr(pPage, pCell, &info); |
| 44982 | 45630 | sz = info.nData; |
| 44983 | 45631 | if( !pPage->intKey ) sz += (int)info.nKey; |
| 45632 | + /* For intKey pages, check that the keys are in order. |
| 45633 | + */ |
| 45634 | + else if( i==0 ) nMinKey = nMaxKey = info.nKey; |
| 45635 | + else{ |
| 45636 | + if( info.nKey <= nMaxKey ){ |
| 45637 | + checkAppendMsg(pCheck, zContext, |
| 45638 | + "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey); |
| 45639 | + } |
| 45640 | + nMaxKey = info.nKey; |
| 45641 | + } |
| 44984 | 45642 | assert( sz==info.nPayload ); |
| 44985 | 45643 | if( (sz>info.nLocal) |
| 44986 | 45644 | && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize]) |
| 44987 | 45645 | ){ |
| 44988 | 45646 | int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); |
| | @@ -45002,29 +45660,66 @@ |
| 45002 | 45660 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45003 | 45661 | if( pBt->autoVacuum ){ |
| 45004 | 45662 | checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); |
| 45005 | 45663 | } |
| 45006 | 45664 | #endif |
| 45007 | | - d2 = checkTreePage(pCheck, pgno, zContext); |
| 45665 | + d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey); |
| 45008 | 45666 | if( i>0 && d2!=depth ){ |
| 45009 | 45667 | checkAppendMsg(pCheck, zContext, "Child page depth differs"); |
| 45010 | 45668 | } |
| 45011 | 45669 | depth = d2; |
| 45012 | 45670 | } |
| 45013 | 45671 | } |
| 45672 | + |
| 45014 | 45673 | if( !pPage->leaf ){ |
| 45015 | 45674 | pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); |
| 45016 | 45675 | sqlite3_snprintf(sizeof(zContext), zContext, |
| 45017 | 45676 | "On page %d at right child: ", iPage); |
| 45018 | 45677 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45019 | 45678 | if( pBt->autoVacuum ){ |
| 45020 | | - checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0); |
| 45679 | + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); |
| 45021 | 45680 | } |
| 45022 | 45681 | #endif |
| 45023 | | - checkTreePage(pCheck, pgno, zContext); |
| 45682 | + checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey); |
| 45024 | 45683 | } |
| 45025 | 45684 | |
| 45685 | + /* For intKey leaf pages, check that the min/max keys are in order |
| 45686 | + ** with any left/parent/right pages. |
| 45687 | + */ |
| 45688 | + if( pPage->leaf && pPage->intKey ){ |
| 45689 | + /* if we are a left child page */ |
| 45690 | + if( pnParentMinKey ){ |
| 45691 | + /* if we are the left most child page */ |
| 45692 | + if( !pnParentMaxKey ){ |
| 45693 | + if( nMaxKey > *pnParentMinKey ){ |
| 45694 | + checkAppendMsg(pCheck, zContext, |
| 45695 | + "Rowid %lld out of order (max larger than parent min of %lld)", |
| 45696 | + nMaxKey, *pnParentMinKey); |
| 45697 | + } |
| 45698 | + }else{ |
| 45699 | + if( nMinKey <= *pnParentMinKey ){ |
| 45700 | + checkAppendMsg(pCheck, zContext, |
| 45701 | + "Rowid %lld out of order (min less than parent min of %lld)", |
| 45702 | + nMinKey, *pnParentMinKey); |
| 45703 | + } |
| 45704 | + if( nMaxKey > *pnParentMaxKey ){ |
| 45705 | + checkAppendMsg(pCheck, zContext, |
| 45706 | + "Rowid %lld out of order (max larger than parent max of %lld)", |
| 45707 | + nMaxKey, *pnParentMaxKey); |
| 45708 | + } |
| 45709 | + *pnParentMinKey = nMaxKey; |
| 45710 | + } |
| 45711 | + /* else if we're a right child page */ |
| 45712 | + } else if( pnParentMaxKey ){ |
| 45713 | + if( nMinKey <= *pnParentMaxKey ){ |
| 45714 | + checkAppendMsg(pCheck, zContext, |
| 45715 | + "Rowid %lld out of order (min less than parent max of %lld)", |
| 45716 | + nMinKey, *pnParentMaxKey); |
| 45717 | + } |
| 45718 | + } |
| 45719 | + } |
| 45720 | + |
| 45026 | 45721 | /* Check for complete coverage of the page |
| 45027 | 45722 | */ |
| 45028 | 45723 | data = pPage->aData; |
| 45029 | 45724 | hdr = pPage->hdrOffset; |
| 45030 | 45725 | hit = sqlite3PageMalloc( pBt->pageSize ); |
| | @@ -45044,11 +45739,11 @@ |
| 45044 | 45739 | if( pc<=usableSize-4 ){ |
| 45045 | 45740 | size = cellSizePtr(pPage, &data[pc]); |
| 45046 | 45741 | } |
| 45047 | 45742 | if( (pc+size-1)>=usableSize ){ |
| 45048 | 45743 | checkAppendMsg(pCheck, 0, |
| 45049 | | - "Corruption detected in cell %d on page %d",i,iPage,0); |
| 45744 | + "Corruption detected in cell %d on page %d",i,iPage); |
| 45050 | 45745 | }else{ |
| 45051 | 45746 | for(j=pc+size-1; j>=pc; j--) hit[j]++; |
| 45052 | 45747 | } |
| 45053 | 45748 | } |
| 45054 | 45749 | i = get2byte(&data[hdr+1]); |
| | @@ -45150,11 +45845,11 @@ |
| 45150 | 45845 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 45151 | 45846 | if( pBt->autoVacuum && aRoot[i]>1 ){ |
| 45152 | 45847 | checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); |
| 45153 | 45848 | } |
| 45154 | 45849 | #endif |
| 45155 | | - checkTreePage(&sCheck, aRoot[i], "List of tree roots: "); |
| 45850 | + checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL); |
| 45156 | 45851 | } |
| 45157 | 45852 | |
| 45158 | 45853 | /* Make sure every page in the file is referenced |
| 45159 | 45854 | */ |
| 45160 | 45855 | for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ |
| | @@ -45483,14 +46178,14 @@ |
| 45483 | 46178 | sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory"); |
| 45484 | 46179 | rc = SQLITE_NOMEM; |
| 45485 | 46180 | }else{ |
| 45486 | 46181 | pParse->db = pDb; |
| 45487 | 46182 | if( sqlite3OpenTempDatabase(pParse) ){ |
| 45488 | | - sqlite3ErrorClear(pParse); |
| 45489 | 46183 | sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); |
| 45490 | 46184 | rc = SQLITE_ERROR; |
| 45491 | 46185 | } |
| 46186 | + sqlite3DbFree(pErrorDb, pParse->zErrMsg); |
| 45492 | 46187 | sqlite3StackFree(pErrorDb, pParse); |
| 45493 | 46188 | } |
| 45494 | 46189 | if( rc ){ |
| 45495 | 46190 | return 0; |
| 45496 | 46191 | } |
| | @@ -46329,10 +47024,14 @@ |
| 46329 | 47024 | ** Because we do not completely understand the problem, we will |
| 46330 | 47025 | ** take the conservative approach and always do range tests |
| 46331 | 47026 | ** before attempting the conversion. |
| 46332 | 47027 | */ |
| 46333 | 47028 | static i64 doubleToInt64(double r){ |
| 47029 | +#ifdef SQLITE_OMIT_FLOATING_POINT |
| 47030 | + /* When floating-point is omitted, double and int64 are the same thing */ |
| 47031 | + return r; |
| 47032 | +#else |
| 46334 | 47033 | /* |
| 46335 | 47034 | ** Many compilers we encounter do not define constants for the |
| 46336 | 47035 | ** minimum and maximum 64-bit integers, or they define them |
| 46337 | 47036 | ** inconsistently. And many do not understand the "LL" notation. |
| 46338 | 47037 | ** So we define our own static constants here using nothing |
| | @@ -46350,10 +47049,11 @@ |
| 46350 | 47049 | ** does so for compatibility we will do the same in software. */ |
| 46351 | 47050 | return minInt; |
| 46352 | 47051 | }else{ |
| 46353 | 47052 | return (i64)r; |
| 46354 | 47053 | } |
| 47054 | +#endif |
| 46355 | 47055 | } |
| 46356 | 47056 | |
| 46357 | 47057 | /* |
| 46358 | 47058 | ** Return some kind of integer value which is the best we can do |
| 46359 | 47059 | ** at representing the value that *pMem describes as an integer. |
| | @@ -46477,25 +47177,30 @@ |
| 46477 | 47177 | } |
| 46478 | 47178 | |
| 46479 | 47179 | /* |
| 46480 | 47180 | ** Convert pMem so that it has types MEM_Real or MEM_Int or both. |
| 46481 | 47181 | ** Invalidate any prior representations. |
| 47182 | +** |
| 47183 | +** Every effort is made to force the conversion, even if the input |
| 47184 | +** is a string that does not look completely like a number. Convert |
| 47185 | +** as much of the string as we can and ignore the rest. |
| 46482 | 47186 | */ |
| 46483 | 47187 | SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ |
| 46484 | | - double r1, r2; |
| 46485 | | - i64 i; |
| 47188 | + int rc; |
| 46486 | 47189 | assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ); |
| 46487 | 47190 | assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); |
| 46488 | 47191 | 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); |
| 47192 | + rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8); |
| 47193 | + if( rc ) return rc; |
| 47194 | + rc = sqlite3VdbeMemNulTerminate(pMem); |
| 47195 | + if( rc ) return rc; |
| 47196 | + if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){ |
| 47197 | + MemSetTypeFlag(pMem, MEM_Int); |
| 46494 | 47198 | }else{ |
| 46495 | | - pMem->r = r1; |
| 47199 | + pMem->r = sqlite3VdbeRealValue(pMem); |
| 46496 | 47200 | MemSetTypeFlag(pMem, MEM_Real); |
| 47201 | + sqlite3VdbeIntegerAffinity(pMem); |
| 46497 | 47202 | } |
| 46498 | 47203 | return SQLITE_OK; |
| 46499 | 47204 | } |
| 46500 | 47205 | |
| 46501 | 47206 | /* |
| | @@ -46543,10 +47248,11 @@ |
| 46543 | 47248 | pMem->u.i = val; |
| 46544 | 47249 | pMem->flags = MEM_Int; |
| 46545 | 47250 | pMem->type = SQLITE_INTEGER; |
| 46546 | 47251 | } |
| 46547 | 47252 | |
| 47253 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 46548 | 47254 | /* |
| 46549 | 47255 | ** Delete any previous value and set the value stored in *pMem to val, |
| 46550 | 47256 | ** manifest type REAL. |
| 46551 | 47257 | */ |
| 46552 | 47258 | SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ |
| | @@ -46557,10 +47263,11 @@ |
| 46557 | 47263 | pMem->r = val; |
| 46558 | 47264 | pMem->flags = MEM_Real; |
| 46559 | 47265 | pMem->type = SQLITE_FLOAT; |
| 46560 | 47266 | } |
| 46561 | 47267 | } |
| 47268 | +#endif |
| 46562 | 47269 | |
| 46563 | 47270 | /* |
| 46564 | 47271 | ** Delete any previous value and set the value of pMem to be an |
| 46565 | 47272 | ** empty boolean index. |
| 46566 | 47273 | */ |
| | @@ -47182,11 +47889,11 @@ |
| 47182 | 47889 | /* |
| 47183 | 47890 | ** Return the SQL associated with a prepared statement |
| 47184 | 47891 | */ |
| 47185 | 47892 | SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ |
| 47186 | 47893 | Vdbe *p = (Vdbe *)pStmt; |
| 47187 | | - return (p->isPrepareV2 ? p->zSql : 0); |
| 47894 | + return (p && p->isPrepareV2) ? p->zSql : 0; |
| 47188 | 47895 | } |
| 47189 | 47896 | |
| 47190 | 47897 | /* |
| 47191 | 47898 | ** Swap all content between two VDBE structures. |
| 47192 | 47899 | */ |
| | @@ -47370,10 +48077,17 @@ |
| 47370 | 48077 | assert( j>=0 && j<p->nLabel ); |
| 47371 | 48078 | if( p->aLabel ){ |
| 47372 | 48079 | p->aLabel[j] = p->nOp; |
| 47373 | 48080 | } |
| 47374 | 48081 | } |
| 48082 | + |
| 48083 | +/* |
| 48084 | +** Mark the VDBE as one that can only be run one time. |
| 48085 | +*/ |
| 48086 | +SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){ |
| 48087 | + p->runOnlyOnce = 1; |
| 48088 | +} |
| 47375 | 48089 | |
| 47376 | 48090 | #ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ |
| 47377 | 48091 | |
| 47378 | 48092 | /* |
| 47379 | 48093 | ** The following type and function are used to iterate through all opcodes |
| | @@ -48175,11 +48889,10 @@ |
| 48175 | 48889 | int rc = SQLITE_OK; /* Return code */ |
| 48176 | 48890 | Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */ |
| 48177 | 48891 | |
| 48178 | 48892 | assert( p->explain ); |
| 48179 | 48893 | assert( p->magic==VDBE_MAGIC_RUN ); |
| 48180 | | - assert( db->magic==SQLITE_MAGIC_BUSY ); |
| 48181 | 48894 | assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); |
| 48182 | 48895 | |
| 48183 | 48896 | /* Even though this opcode does not use dynamic strings for |
| 48184 | 48897 | ** the result, result columns may become dynamic if the user calls |
| 48185 | 48898 | ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. |
| | @@ -48590,13 +49303,11 @@ |
| 48590 | 49303 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 48591 | 49304 | if( pCx->pVtabCursor ){ |
| 48592 | 49305 | sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; |
| 48593 | 49306 | const sqlite3_module *pModule = pCx->pModule; |
| 48594 | 49307 | p->inVtabMethod = 1; |
| 48595 | | - (void)sqlite3SafetyOff(p->db); |
| 48596 | 49308 | pModule->xClose(pVtabCursor); |
| 48597 | | - (void)sqlite3SafetyOn(p->db); |
| 48598 | 49309 | p->inVtabMethod = 0; |
| 48599 | 49310 | } |
| 48600 | 49311 | #endif |
| 48601 | 49312 | } |
| 48602 | 49313 | |
| | @@ -48773,13 +49484,11 @@ |
| 48773 | 49484 | } |
| 48774 | 49485 | } |
| 48775 | 49486 | |
| 48776 | 49487 | /* If there are any write-transactions at all, invoke the commit hook */ |
| 48777 | 49488 | if( needXcommit && db->xCommitCallback ){ |
| 48778 | | - (void)sqlite3SafetyOff(db); |
| 48779 | 49489 | rc = db->xCommitCallback(db->pCommitArg); |
| 48780 | | - (void)sqlite3SafetyOn(db); |
| 48781 | 49490 | if( rc ){ |
| 48782 | 49491 | return SQLITE_CONSTRAINT; |
| 48783 | 49492 | } |
| 48784 | 49493 | } |
| 48785 | 49494 | |
| | @@ -49329,13 +50038,11 @@ |
| 49329 | 50038 | |
| 49330 | 50039 | /* If the VM did not run to completion or if it encountered an |
| 49331 | 50040 | ** error, then it might not have been halted properly. So halt |
| 49332 | 50041 | ** it now. |
| 49333 | 50042 | */ |
| 49334 | | - (void)sqlite3SafetyOn(db); |
| 49335 | 50043 | sqlite3VdbeHalt(p); |
| 49336 | | - (void)sqlite3SafetyOff(db); |
| 49337 | 50044 | |
| 49338 | 50045 | /* If the VDBE has be run even partially, then transfer the error code |
| 49339 | 50046 | ** and error message from the VDBE into the main database structure. But |
| 49340 | 50047 | ** if the VDBE has just been set to run but has not actually executed any |
| 49341 | 50048 | ** instructions yet, leave the main database error information unchanged. |
| | @@ -49351,10 +50058,11 @@ |
| 49351 | 50058 | }else if( p->rc ){ |
| 49352 | 50059 | sqlite3Error(db, p->rc, 0); |
| 49353 | 50060 | }else{ |
| 49354 | 50061 | sqlite3Error(db, SQLITE_OK, 0); |
| 49355 | 50062 | } |
| 50063 | + if( p->runOnlyOnce ) p->expired = 1; |
| 49356 | 50064 | }else if( p->rc && p->expired ){ |
| 49357 | 50065 | /* The expired flag was set on the VDBE before the first call |
| 49358 | 50066 | ** to sqlite3_step(). For consistency (since sqlite3_step() was |
| 49359 | 50067 | ** called), set the database error in this case as well. |
| 49360 | 50068 | */ |
| | @@ -49452,10 +50160,11 @@ |
| 49452 | 50160 | sqlite3DbFree(db, p->aLabel); |
| 49453 | 50161 | sqlite3DbFree(db, p->aColName); |
| 49454 | 50162 | sqlite3DbFree(db, p->zSql); |
| 49455 | 50163 | p->magic = VDBE_MAGIC_DEAD; |
| 49456 | 50164 | sqlite3DbFree(db, p->pFree); |
| 50165 | + p->db = 0; |
| 49457 | 50166 | sqlite3DbFree(db, p); |
| 49458 | 50167 | } |
| 49459 | 50168 | |
| 49460 | 50169 | /* |
| 49461 | 50170 | ** Make sure the cursor p is ready to read or write the row to which it |
| | @@ -50132,11 +50841,11 @@ |
| 50132 | 50841 | assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ |
| 50133 | 50842 | /* nCellKey will always be between 0 and 0xffffffff because of the say |
| 50134 | 50843 | ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ |
| 50135 | 50844 | if( nCellKey<=0 || nCellKey>0x7fffffff ){ |
| 50136 | 50845 | *res = 0; |
| 50137 | | - return SQLITE_CORRUPT; |
| 50846 | + return SQLITE_CORRUPT_BKPT; |
| 50138 | 50847 | } |
| 50139 | 50848 | memset(&m, 0, sizeof(m)); |
| 50140 | 50849 | rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m); |
| 50141 | 50850 | if( rc ){ |
| 50142 | 50851 | return rc; |
| | @@ -50258,10 +50967,32 @@ |
| 50258 | 50967 | SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ |
| 50259 | 50968 | Vdbe *p = (Vdbe*)pStmt; |
| 50260 | 50969 | return p==0 || p->expired; |
| 50261 | 50970 | } |
| 50262 | 50971 | #endif |
| 50972 | + |
| 50973 | +/* |
| 50974 | +** Check on a Vdbe to make sure it has not been finalized. Log |
| 50975 | +** an error and return true if it has been finalized (or is otherwise |
| 50976 | +** invalid). Return false if it is ok. |
| 50977 | +*/ |
| 50978 | +static int vdbeSafety(Vdbe *p){ |
| 50979 | + if( p->db==0 ){ |
| 50980 | + sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement"); |
| 50981 | + return 1; |
| 50982 | + }else{ |
| 50983 | + return 0; |
| 50984 | + } |
| 50985 | +} |
| 50986 | +static int vdbeSafetyNotNull(Vdbe *p){ |
| 50987 | + if( p==0 ){ |
| 50988 | + sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement"); |
| 50989 | + return 1; |
| 50990 | + }else{ |
| 50991 | + return vdbeSafety(p); |
| 50992 | + } |
| 50993 | +} |
| 50263 | 50994 | |
| 50264 | 50995 | /* |
| 50265 | 50996 | ** The following routine destroys a virtual machine that is created by |
| 50266 | 50997 | ** the sqlite3_compile() routine. The integer returned is an SQLITE_ |
| 50267 | 50998 | ** success/failure code that describes the result of executing the virtual |
| | @@ -50276,11 +51007,15 @@ |
| 50276 | 51007 | rc = SQLITE_OK; |
| 50277 | 51008 | }else{ |
| 50278 | 51009 | Vdbe *v = (Vdbe*)pStmt; |
| 50279 | 51010 | sqlite3 *db = v->db; |
| 50280 | 51011 | #if SQLITE_THREADSAFE |
| 50281 | | - sqlite3_mutex *mutex = v->db->mutex; |
| 51012 | + sqlite3_mutex *mutex; |
| 51013 | +#endif |
| 51014 | + if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; |
| 51015 | +#if SQLITE_THREADSAFE |
| 51016 | + mutex = v->db->mutex; |
| 50282 | 51017 | #endif |
| 50283 | 51018 | sqlite3_mutex_enter(mutex); |
| 50284 | 51019 | rc = sqlite3VdbeFinalize(v); |
| 50285 | 51020 | rc = sqlite3ApiExit(db, rc); |
| 50286 | 51021 | sqlite3_mutex_leave(mutex); |
| | @@ -50523,30 +51258,27 @@ |
| 50523 | 51258 | sqlite3 *db; |
| 50524 | 51259 | int rc; |
| 50525 | 51260 | |
| 50526 | 51261 | assert(p); |
| 50527 | 51262 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| 50528 | | - return SQLITE_MISUSE; |
| 51263 | + sqlite3_log(SQLITE_MISUSE, |
| 51264 | + "attempt to step a halted statement: [%s]", p->zSql); |
| 51265 | + return SQLITE_MISUSE_BKPT; |
| 50529 | 51266 | } |
| 50530 | 51267 | |
| 50531 | | - /* Assert that malloc() has not failed */ |
| 51268 | + /* Check that malloc() has not failed. If it has, return early. */ |
| 50532 | 51269 | db = p->db; |
| 50533 | 51270 | if( db->mallocFailed ){ |
| 51271 | + p->rc = SQLITE_NOMEM; |
| 50534 | 51272 | return SQLITE_NOMEM; |
| 50535 | 51273 | } |
| 50536 | 51274 | |
| 50537 | 51275 | if( p->pc<=0 && p->expired ){ |
| 50538 | | - if( ALWAYS(p->rc==SQLITE_OK || p->rc==SQLITE_SCHEMA) ){ |
| 50539 | | - p->rc = SQLITE_SCHEMA; |
| 50540 | | - } |
| 51276 | + p->rc = SQLITE_SCHEMA; |
| 50541 | 51277 | rc = SQLITE_ERROR; |
| 50542 | 51278 | goto end_of_step; |
| 50543 | 51279 | } |
| 50544 | | - if( sqlite3SafetyOn(db) ){ |
| 50545 | | - p->rc = SQLITE_MISUSE; |
| 50546 | | - return SQLITE_MISUSE; |
| 50547 | | - } |
| 50548 | 51280 | if( p->pc<0 ){ |
| 50549 | 51281 | /* If there are no other statements currently running, then |
| 50550 | 51282 | ** reset the interrupt flag. This prevents a call to sqlite3_interrupt |
| 50551 | 51283 | ** from interrupting a statement that has not yet started. |
| 50552 | 51284 | */ |
| | @@ -50575,14 +51307,10 @@ |
| 50575 | 51307 | #endif /* SQLITE_OMIT_EXPLAIN */ |
| 50576 | 51308 | { |
| 50577 | 51309 | rc = sqlite3VdbeExec(p); |
| 50578 | 51310 | } |
| 50579 | 51311 | |
| 50580 | | - if( sqlite3SafetyOff(db) ){ |
| 50581 | | - rc = SQLITE_MISUSE; |
| 50582 | | - } |
| 50583 | | - |
| 50584 | 51312 | #ifndef SQLITE_OMIT_TRACE |
| 50585 | 51313 | /* Invoke the profile callback if there is one |
| 50586 | 51314 | */ |
| 50587 | 51315 | if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){ |
| 50588 | 51316 | double rNow; |
| | @@ -50625,43 +51353,48 @@ |
| 50625 | 51353 | ** This is the top-level implementation of sqlite3_step(). Call |
| 50626 | 51354 | ** sqlite3Step() to do most of the work. If a schema error occurs, |
| 50627 | 51355 | ** call sqlite3Reprepare() and try again. |
| 50628 | 51356 | */ |
| 50629 | 51357 | 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 | | - } |
| 51358 | + int rc = SQLITE_OK; /* Result from sqlite3Step() */ |
| 51359 | + int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ |
| 51360 | + Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ |
| 51361 | + int cnt = 0; /* Counter to prevent infinite loop of reprepares */ |
| 51362 | + sqlite3 *db; /* The database connection */ |
| 51363 | + |
| 51364 | + if( vdbeSafetyNotNull(v) ){ |
| 51365 | + return SQLITE_MISUSE_BKPT; |
| 51366 | + } |
| 51367 | + db = v->db; |
| 51368 | + sqlite3_mutex_enter(db->mutex); |
| 51369 | + while( (rc = sqlite3Step(v))==SQLITE_SCHEMA |
| 51370 | + && cnt++ < 5 |
| 51371 | + && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ |
| 51372 | + sqlite3_reset(pStmt); |
| 51373 | + v->expired = 0; |
| 51374 | + } |
| 51375 | + if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ |
| 51376 | + /* This case occurs after failing to recompile an sql statement. |
| 51377 | + ** The error message from the SQL compiler has already been loaded |
| 51378 | + ** into the database handle. This block copies the error message |
| 51379 | + ** from the database handle into the statement and sets the statement |
| 51380 | + ** program counter to 0 to ensure that when the statement is |
| 51381 | + ** finalized or reset the parser error message is available via |
| 51382 | + ** sqlite3_errmsg() and sqlite3_errcode(). |
| 51383 | + */ |
| 51384 | + const char *zErr = (const char *)sqlite3_value_text(db->pErr); |
| 51385 | + sqlite3DbFree(db, v->zErrMsg); |
| 51386 | + if( !db->mallocFailed ){ |
| 51387 | + v->zErrMsg = sqlite3DbStrDup(db, zErr); |
| 51388 | + v->rc = rc2; |
| 51389 | + } else { |
| 51390 | + v->zErrMsg = 0; |
| 51391 | + v->rc = rc = SQLITE_NOMEM; |
| 51392 | + } |
| 51393 | + } |
| 51394 | + rc = sqlite3ApiExit(db, rc); |
| 51395 | + sqlite3_mutex_leave(db->mutex); |
| 50663 | 51396 | return rc; |
| 50664 | 51397 | } |
| 50665 | 51398 | |
| 50666 | 51399 | /* |
| 50667 | 51400 | ** Extract the user data from a sqlite3_context structure and return a |
| | @@ -51127,16 +51860,20 @@ |
| 51127 | 51860 | ** The error code stored in database p->db is overwritten with the return |
| 51128 | 51861 | ** value in any case. |
| 51129 | 51862 | */ |
| 51130 | 51863 | static int vdbeUnbind(Vdbe *p, int i){ |
| 51131 | 51864 | Mem *pVar; |
| 51132 | | - if( p==0 ) return SQLITE_MISUSE; |
| 51865 | + if( vdbeSafetyNotNull(p) ){ |
| 51866 | + return SQLITE_MISUSE_BKPT; |
| 51867 | + } |
| 51133 | 51868 | sqlite3_mutex_enter(p->db->mutex); |
| 51134 | 51869 | if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ |
| 51135 | 51870 | sqlite3Error(p->db, SQLITE_MISUSE, 0); |
| 51136 | 51871 | sqlite3_mutex_leave(p->db->mutex); |
| 51137 | | - return SQLITE_MISUSE; |
| 51872 | + sqlite3_log(SQLITE_MISUSE, |
| 51873 | + "bind on a busy prepared statement: [%s]", p->zSql); |
| 51874 | + return SQLITE_MISUSE_BKPT; |
| 51138 | 51875 | } |
| 51139 | 51876 | if( i<1 || i>p->nVar ){ |
| 51140 | 51877 | sqlite3Error(p->db, SQLITE_RANGE, 0); |
| 51141 | 51878 | sqlite3_mutex_leave(p->db->mutex); |
| 51142 | 51879 | return SQLITE_RANGE; |
| | @@ -52225,11 +52962,11 @@ |
| 52225 | 52962 | ** used to clean up the mess that was left behind. |
| 52226 | 52963 | */ |
| 52227 | 52964 | SQLITE_PRIVATE int sqlite3VdbeExec( |
| 52228 | 52965 | Vdbe *p /* The VDBE */ |
| 52229 | 52966 | ){ |
| 52230 | | - int pc; /* The program counter */ |
| 52967 | + int pc=0; /* The program counter */ |
| 52231 | 52968 | Op *aOp = p->aOp; /* Copy of p->aOp */ |
| 52232 | 52969 | Op *pOp; /* Current operation */ |
| 52233 | 52970 | int rc = SQLITE_OK; /* Value to return */ |
| 52234 | 52971 | sqlite3 *db = p->db; /* The database */ |
| 52235 | 52972 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */ |
| | @@ -52336,11 +53073,11 @@ |
| 52336 | 53073 | Mem *pDest; /* Where to write the extracted value */ |
| 52337 | 53074 | Mem sMem; /* For storing the record being decoded */ |
| 52338 | 53075 | u8 *zIdx; /* Index into header */ |
| 52339 | 53076 | u8 *zEndHdr; /* Pointer to first byte after the header */ |
| 52340 | 53077 | u32 offset; /* Offset into the data */ |
| 52341 | | - u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */ |
| 53078 | + u32 szField; /* Number of bytes in the content of a field */ |
| 52342 | 53079 | int szHdr; /* Size of the header size field at start of record */ |
| 52343 | 53080 | int avail; /* Number of bytes of available data */ |
| 52344 | 53081 | Mem *pReg; /* PseudoTable input register */ |
| 52345 | 53082 | } am; |
| 52346 | 53083 | struct OP_Affinity_stack_vars { |
| | @@ -52648,11 +53385,10 @@ |
| 52648 | 53385 | } u; |
| 52649 | 53386 | /* End automatically generated code |
| 52650 | 53387 | ********************************************************************/ |
| 52651 | 53388 | |
| 52652 | 53389 | assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ |
| 52653 | | - assert( db->magic==SQLITE_MAGIC_BUSY ); |
| 52654 | 53390 | sqlite3VdbeMutexArrayEnter(p); |
| 52655 | 53391 | if( p->rc==SQLITE_NOMEM ){ |
| 52656 | 53392 | /* This happens if a malloc() inside a call to sqlite3_column_text() or |
| 52657 | 53393 | ** sqlite3_column_text16() failed. */ |
| 52658 | 53394 | goto no_mem; |
| | @@ -52733,13 +53469,11 @@ |
| 52733 | 53469 | ** a return code SQLITE_ABORT. |
| 52734 | 53470 | */ |
| 52735 | 53471 | if( checkProgress ){ |
| 52736 | 53472 | if( db->nProgressOps==nProgressOps ){ |
| 52737 | 53473 | 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; |
| 53474 | + prc = db->xProgress(db->pProgressArg); |
| 52741 | 53475 | if( prc!=0 ){ |
| 52742 | 53476 | rc = SQLITE_INTERRUPT; |
| 52743 | 53477 | goto vdbe_error_halt; |
| 52744 | 53478 | } |
| 52745 | 53479 | nProgressOps = 0; |
| | @@ -52937,11 +53671,17 @@ |
| 52937 | 53671 | |
| 52938 | 53672 | p->rc = pOp->p1; |
| 52939 | 53673 | p->errorAction = (u8)pOp->p2; |
| 52940 | 53674 | p->pc = pc; |
| 52941 | 53675 | if( pOp->p4.z ){ |
| 53676 | + assert( p->rc!=SQLITE_OK ); |
| 52942 | 53677 | sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); |
| 53678 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 53679 | + sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z); |
| 53680 | + }else if( p->rc ){ |
| 53681 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 53682 | + sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql); |
| 52943 | 53683 | } |
| 52944 | 53684 | rc = sqlite3VdbeHalt(p); |
| 52945 | 53685 | assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); |
| 52946 | 53686 | if( rc==SQLITE_BUSY ){ |
| 52947 | 53687 | p->rc = rc = SQLITE_BUSY; |
| | @@ -52971,10 +53711,11 @@ |
| 52971 | 53711 | assert( pOp->p4.pI64!=0 ); |
| 52972 | 53712 | pOut->u.i = *pOp->p4.pI64; |
| 52973 | 53713 | break; |
| 52974 | 53714 | } |
| 52975 | 53715 | |
| 53716 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 52976 | 53717 | /* Opcode: Real * P2 * P4 * |
| 52977 | 53718 | ** |
| 52978 | 53719 | ** P4 is a pointer to a 64-bit floating point value. |
| 52979 | 53720 | ** Write that value into register P2. |
| 52980 | 53721 | */ |
| | @@ -52982,10 +53723,11 @@ |
| 52982 | 53723 | pOut->flags = MEM_Real; |
| 52983 | 53724 | assert( !sqlite3IsNaN(*pOp->p4.pReal) ); |
| 52984 | 53725 | pOut->r = *pOp->p4.pReal; |
| 52985 | 53726 | break; |
| 52986 | 53727 | } |
| 53728 | +#endif |
| 52987 | 53729 | |
| 52988 | 53730 | /* Opcode: String8 * P2 * P4 * |
| 52989 | 53731 | ** |
| 52990 | 53732 | ** P4 points to a nul terminated UTF-8 string. This opcode is transformed |
| 52991 | 53733 | ** into an OP_String before it is executed for the first time. |
| | @@ -53392,18 +54134,23 @@ |
| 53392 | 54134 | if( u.af.iA==-1 ) u.af.iA = 1; |
| 53393 | 54135 | u.af.rB = (double)(u.af.iB % u.af.iA); |
| 53394 | 54136 | break; |
| 53395 | 54137 | } |
| 53396 | 54138 | } |
| 54139 | +#ifdef SQLITE_OMIT_FLOATING_POINT |
| 54140 | + pOut->u.i = u.af.rB; |
| 54141 | + MemSetTypeFlag(pOut, MEM_Int); |
| 54142 | +#else |
| 53397 | 54143 | if( sqlite3IsNaN(u.af.rB) ){ |
| 53398 | 54144 | goto arithmetic_result_is_null; |
| 53399 | 54145 | } |
| 53400 | 54146 | pOut->r = u.af.rB; |
| 53401 | 54147 | MemSetTypeFlag(pOut, MEM_Real); |
| 53402 | 54148 | if( (u.af.flags & MEM_Real)==0 ){ |
| 53403 | 54149 | sqlite3VdbeIntegerAffinity(pOut); |
| 53404 | 54150 | } |
| 54151 | +#endif |
| 53405 | 54152 | } |
| 53406 | 54153 | break; |
| 53407 | 54154 | |
| 53408 | 54155 | arithmetic_result_is_null: |
| 53409 | 54156 | sqlite3VdbeMemSetNull(pOut); |
| | @@ -53492,25 +54239,16 @@ |
| 53492 | 54239 | assert( pOp>aOp ); |
| 53493 | 54240 | assert( pOp[-1].p4type==P4_COLLSEQ ); |
| 53494 | 54241 | assert( pOp[-1].opcode==OP_CollSeq ); |
| 53495 | 54242 | u.ag.ctx.pColl = pOp[-1].p4.pColl; |
| 53496 | 54243 | } |
| 53497 | | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 53498 | 54244 | (*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 | 54245 | if( db->mallocFailed ){ |
| 53504 | 54246 | /* Even though a malloc() has failed, the implementation of the |
| 53505 | 54247 | ** user function may have called an sqlite3_result_XXX() function |
| 53506 | 54248 | ** to return a value. The following call releases any resources |
| 53507 | 54249 | ** 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 | 54250 | */ |
| 53513 | 54251 | sqlite3VdbeMemRelease(&u.ag.ctx.s); |
| 53514 | 54252 | goto no_mem; |
| 53515 | 54253 | } |
| 53516 | 54254 | |
| | @@ -53631,10 +54369,11 @@ |
| 53631 | 54369 | MemSetTypeFlag(pIn1, MEM_Int); |
| 53632 | 54370 | } |
| 53633 | 54371 | break; |
| 53634 | 54372 | } |
| 53635 | 54373 | |
| 54374 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 53636 | 54375 | /* Opcode: RealAffinity P1 * * * * |
| 53637 | 54376 | ** |
| 53638 | 54377 | ** If register P1 holds an integer convert it to a real value. |
| 53639 | 54378 | ** |
| 53640 | 54379 | ** This opcode is used when extracting information from a column that |
| | @@ -53647,10 +54386,11 @@ |
| 53647 | 54386 | if( pIn1->flags & MEM_Int ){ |
| 53648 | 54387 | sqlite3VdbeMemRealify(pIn1); |
| 53649 | 54388 | } |
| 53650 | 54389 | break; |
| 53651 | 54390 | } |
| 54391 | +#endif |
| 53652 | 54392 | |
| 53653 | 54393 | #ifndef SQLITE_OMIT_CAST |
| 53654 | 54394 | /* Opcode: ToText P1 * * * * |
| 53655 | 54395 | ** |
| 53656 | 54396 | ** Force the value in register P1 to be text. |
| | @@ -53730,11 +54470,11 @@ |
| 53730 | 54470 | sqlite3VdbeMemIntegerify(pIn1); |
| 53731 | 54471 | } |
| 53732 | 54472 | break; |
| 53733 | 54473 | } |
| 53734 | 54474 | |
| 53735 | | -#ifndef SQLITE_OMIT_CAST |
| 54475 | +#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) |
| 53736 | 54476 | /* Opcode: ToReal P1 * * * * |
| 53737 | 54477 | ** |
| 53738 | 54478 | ** Force the value in register P1 to be a floating point number. |
| 53739 | 54479 | ** If The value is currently an integer, convert it. |
| 53740 | 54480 | ** If the value is text or blob, try to convert it to an integer using the |
| | @@ -53747,11 +54487,11 @@ |
| 53747 | 54487 | if( (pIn1->flags & MEM_Null)==0 ){ |
| 53748 | 54488 | sqlite3VdbeMemRealify(pIn1); |
| 53749 | 54489 | } |
| 53750 | 54490 | break; |
| 53751 | 54491 | } |
| 53752 | | -#endif /* SQLITE_OMIT_CAST */ |
| 54492 | +#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */ |
| 53753 | 54493 | |
| 53754 | 54494 | /* Opcode: Lt P1 P2 P3 P4 P5 |
| 53755 | 54495 | ** |
| 53756 | 54496 | ** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then |
| 53757 | 54497 | ** jump to address P2. |
| | @@ -54169,11 +54909,11 @@ |
| 54169 | 54909 | Mem *pDest; /* Where to write the extracted value */ |
| 54170 | 54910 | Mem sMem; /* For storing the record being decoded */ |
| 54171 | 54911 | u8 *zIdx; /* Index into header */ |
| 54172 | 54912 | u8 *zEndHdr; /* Pointer to first byte after the header */ |
| 54173 | 54913 | u32 offset; /* Offset into the data */ |
| 54174 | | - u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */ |
| 54914 | + u32 szField; /* Number of bytes in the content of a field */ |
| 54175 | 54915 | int szHdr; /* Size of the header size field at start of record */ |
| 54176 | 54916 | int avail; /* Number of bytes of available data */ |
| 54177 | 54917 | Mem *pReg; /* PseudoTable input register */ |
| 54178 | 54918 | #endif /* local variables moved into u.am */ |
| 54179 | 54919 | |
| | @@ -54345,16 +55085,20 @@ |
| 54345 | 55085 | /* Scan the header and use it to fill in the u.am.aType[] and u.am.aOffset[] |
| 54346 | 55086 | ** arrays. u.am.aType[u.am.i] will contain the type integer for the u.am.i-th |
| 54347 | 55087 | ** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning |
| 54348 | 55088 | ** of the record to the start of the data for the u.am.i-th column |
| 54349 | 55089 | */ |
| 54350 | | - u.am.offset64 = u.am.offset; |
| 54351 | 55090 | for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){ |
| 54352 | 55091 | if( u.am.zIdx<u.am.zEndHdr ){ |
| 54353 | | - u.am.aOffset[u.am.i] = (u32)u.am.offset64; |
| 55092 | + u.am.aOffset[u.am.i] = u.am.offset; |
| 54354 | 55093 | u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]); |
| 54355 | | - u.am.offset64 += sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]); |
| 55094 | + u.am.szField = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]); |
| 55095 | + u.am.offset += u.am.szField; |
| 55096 | + if( u.am.offset<u.am.szField ){ /* True if u.am.offset overflows */ |
| 55097 | + u.am.zIdx = &u.am.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */ |
| 55098 | + break; |
| 55099 | + } |
| 54356 | 55100 | }else{ |
| 54357 | 55101 | /* If u.am.i is less that u.am.nField, then there are less fields in this |
| 54358 | 55102 | ** record than SetNumColumns indicated there are columns in the |
| 54359 | 55103 | ** table. Set the u.am.offset for any extra columns not present in |
| 54360 | 55104 | ** the record to 0. This tells code below to store a NULL |
| | @@ -54370,12 +55114,12 @@ |
| 54370 | 55114 | ** or if the end of the last field appears to be past the end of the |
| 54371 | 55115 | ** record, or if the end of the last field appears to be before the end |
| 54372 | 55116 | ** of the record (when all fields present), then we must be dealing |
| 54373 | 55117 | ** with a corrupt database. |
| 54374 | 55118 | */ |
| 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) ){ |
| 55119 | + if( (u.am.zIdx > u.am.zEndHdr) || (u.am.offset > u.am.payloadSize) |
| 55120 | + || (u.am.zIdx==u.am.zEndHdr && u.am.offset!=u.am.payloadSize) ){ |
| 54377 | 55121 | rc = SQLITE_CORRUPT_BKPT; |
| 54378 | 55122 | goto op_column_out; |
| 54379 | 55123 | } |
| 54380 | 55124 | } |
| 54381 | 55125 | |
| | @@ -55239,11 +55983,11 @@ |
| 55239 | 55983 | ** Open a new cursor that points to a fake table that contains a single |
| 55240 | 55984 | ** row of data. The content of that one row in the content of memory |
| 55241 | 55985 | ** register P2. In other words, cursor P1 becomes an alias for the |
| 55242 | 55986 | ** MEM_Blob content contained in register P2. |
| 55243 | 55987 | ** |
| 55244 | | -** A pseudo-table created by this opcode is used to hold the a single |
| 55988 | +** A pseudo-table created by this opcode is used to hold a single |
| 55245 | 55989 | ** row output from the sorter so that the row can be decomposed into |
| 55246 | 55990 | ** individual columns using the OP_Column opcode. The OP_Column opcode |
| 55247 | 55991 | ** is the only cursor opcode that works with a pseudo-table. |
| 55248 | 55992 | ** |
| 55249 | 55993 | ** P3 is the number of fields in the records that will be stored by |
| | @@ -56191,16 +56935,14 @@ |
| 56191 | 56935 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 56192 | 56936 | }else if( u.bi.pC->pVtabCursor ){ |
| 56193 | 56937 | u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab; |
| 56194 | 56938 | u.bi.pModule = u.bi.pVtab->pModule; |
| 56195 | 56939 | assert( u.bi.pModule->xRowid ); |
| 56196 | | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 56197 | 56940 | rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v); |
| 56198 | 56941 | sqlite3DbFree(db, p->zErrMsg); |
| 56199 | 56942 | p->zErrMsg = u.bi.pVtab->zErrMsg; |
| 56200 | 56943 | u.bi.pVtab->zErrMsg = 0; |
| 56201 | | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 56202 | 56944 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 56203 | 56945 | }else{ |
| 56204 | 56946 | assert( u.bi.pC->pCursor!=0 ); |
| 56205 | 56947 | rc = sqlite3VdbeCursorMoveto(u.bi.pC); |
| 56206 | 56948 | if( rc ) goto abort_due_to_error; |
| | @@ -56751,25 +57493,23 @@ |
| 56751 | 57493 | u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb); |
| 56752 | 57494 | u.bu.initData.db = db; |
| 56753 | 57495 | u.bu.initData.iDb = pOp->p1; |
| 56754 | 57496 | u.bu.initData.pzErrMsg = &p->zErrMsg; |
| 56755 | 57497 | u.bu.zSql = sqlite3MPrintf(db, |
| 56756 | | - "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s", |
| 57498 | + "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", |
| 56757 | 57499 | db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z); |
| 56758 | 57500 | if( u.bu.zSql==0 ){ |
| 56759 | 57501 | rc = SQLITE_NOMEM; |
| 56760 | 57502 | }else{ |
| 56761 | | - (void)sqlite3SafetyOff(db); |
| 56762 | 57503 | assert( db->init.busy==0 ); |
| 56763 | 57504 | db->init.busy = 1; |
| 56764 | 57505 | u.bu.initData.rc = SQLITE_OK; |
| 56765 | 57506 | assert( !db->mallocFailed ); |
| 56766 | 57507 | rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0); |
| 56767 | 57508 | if( rc==SQLITE_OK ) rc = u.bu.initData.rc; |
| 56768 | 57509 | sqlite3DbFree(db, u.bu.zSql); |
| 56769 | 57510 | db->init.busy = 0; |
| 56770 | | - (void)sqlite3SafetyOn(db); |
| 56771 | 57511 | } |
| 56772 | 57512 | } |
| 56773 | 57513 | sqlite3BtreeLeaveAll(db); |
| 56774 | 57514 | if( rc==SQLITE_NOMEM ){ |
| 56775 | 57515 | goto no_mem; |
| | @@ -57351,13 +58091,11 @@ |
| 57351 | 58091 | ** Vacuum the entire database. This opcode will cause other virtual |
| 57352 | 58092 | ** machines to be created and run. It may not be called from within |
| 57353 | 58093 | ** a transaction. |
| 57354 | 58094 | */ |
| 57355 | 58095 | case OP_Vacuum: { |
| 57356 | | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57357 | 58096 | rc = sqlite3RunVacuum(&p->zErrMsg, db); |
| 57358 | | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57359 | 58097 | break; |
| 57360 | 58098 | } |
| 57361 | 58099 | #endif |
| 57362 | 58100 | |
| 57363 | 58101 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| | @@ -57503,16 +58241,14 @@ |
| 57503 | 58241 | u.cf.pCur = 0; |
| 57504 | 58242 | u.cf.pVtabCursor = 0; |
| 57505 | 58243 | u.cf.pVtab = pOp->p4.pVtab->pVtab; |
| 57506 | 58244 | u.cf.pModule = (sqlite3_module *)u.cf.pVtab->pModule; |
| 57507 | 58245 | assert(u.cf.pVtab && u.cf.pModule); |
| 57508 | | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57509 | 58246 | rc = u.cf.pModule->xOpen(u.cf.pVtab, &u.cf.pVtabCursor); |
| 57510 | 58247 | sqlite3DbFree(db, p->zErrMsg); |
| 57511 | 58248 | p->zErrMsg = u.cf.pVtab->zErrMsg; |
| 57512 | 58249 | u.cf.pVtab->zErrMsg = 0; |
| 57513 | | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57514 | 58250 | if( SQLITE_OK==rc ){ |
| 57515 | 58251 | /* Initialize sqlite3_vtab_cursor base class */ |
| 57516 | 58252 | u.cf.pVtabCursor->pVtab = u.cf.pVtab; |
| 57517 | 58253 | |
| 57518 | 58254 | /* Initialise vdbe cursor object */ |
| | @@ -57584,21 +58320,19 @@ |
| 57584 | 58320 | for(u.cg.i = 0; u.cg.i<u.cg.nArg; u.cg.i++){ |
| 57585 | 58321 | u.cg.apArg[u.cg.i] = &u.cg.pArgc[u.cg.i+1]; |
| 57586 | 58322 | sqlite3VdbeMemStoreType(u.cg.apArg[u.cg.i]); |
| 57587 | 58323 | } |
| 57588 | 58324 | |
| 57589 | | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57590 | 58325 | p->inVtabMethod = 1; |
| 57591 | 58326 | rc = u.cg.pModule->xFilter(u.cg.pVtabCursor, u.cg.iQuery, pOp->p4.z, u.cg.nArg, u.cg.apArg); |
| 57592 | 58327 | p->inVtabMethod = 0; |
| 57593 | 58328 | sqlite3DbFree(db, p->zErrMsg); |
| 57594 | 58329 | p->zErrMsg = u.cg.pVtab->zErrMsg; |
| 57595 | 58330 | u.cg.pVtab->zErrMsg = 0; |
| 57596 | 58331 | if( rc==SQLITE_OK ){ |
| 57597 | 58332 | u.cg.res = u.cg.pModule->xEof(u.cg.pVtabCursor); |
| 57598 | 58333 | } |
| 57599 | | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57600 | 58334 | |
| 57601 | 58335 | if( u.cg.res ){ |
| 57602 | 58336 | pc = pOp->p2 - 1; |
| 57603 | 58337 | } |
| 57604 | 58338 | } |
| | @@ -57642,11 +58376,10 @@ |
| 57642 | 58376 | ** new one. |
| 57643 | 58377 | */ |
| 57644 | 58378 | sqlite3VdbeMemMove(&u.ch.sContext.s, u.ch.pDest); |
| 57645 | 58379 | MemSetTypeFlag(&u.ch.sContext.s, MEM_Null); |
| 57646 | 58380 | |
| 57647 | | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57648 | 58381 | rc = u.ch.pModule->xColumn(pCur->pVtabCursor, &u.ch.sContext, pOp->p2); |
| 57649 | 58382 | sqlite3DbFree(db, p->zErrMsg); |
| 57650 | 58383 | p->zErrMsg = u.ch.pVtab->zErrMsg; |
| 57651 | 58384 | u.ch.pVtab->zErrMsg = 0; |
| 57652 | 58385 | if( u.ch.sContext.isError ){ |
| | @@ -57660,13 +58393,10 @@ |
| 57660 | 58393 | sqlite3VdbeChangeEncoding(&u.ch.sContext.s, encoding); |
| 57661 | 58394 | sqlite3VdbeMemMove(u.ch.pDest, &u.ch.sContext.s); |
| 57662 | 58395 | REGISTER_TRACE(pOp->p3, u.ch.pDest); |
| 57663 | 58396 | UPDATE_MAX_BLOBSIZE(u.ch.pDest); |
| 57664 | 58397 | |
| 57665 | | - if( sqlite3SafetyOn(db) ){ |
| 57666 | | - goto abort_due_to_misuse; |
| 57667 | | - } |
| 57668 | 58398 | if( sqlite3VdbeMemTooBig(u.ch.pDest) ){ |
| 57669 | 58399 | goto too_big; |
| 57670 | 58400 | } |
| 57671 | 58401 | break; |
| 57672 | 58402 | } |
| | @@ -57701,21 +58431,19 @@ |
| 57701 | 58431 | ** underlying implementation to return an error if one occurs during |
| 57702 | 58432 | ** xNext(). Instead, if an error occurs, true is returned (indicating that |
| 57703 | 58433 | ** data is available) and the error code returned when xColumn or |
| 57704 | 58434 | ** some other method is next invoked on the save virtual table cursor. |
| 57705 | 58435 | */ |
| 57706 | | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57707 | 58436 | p->inVtabMethod = 1; |
| 57708 | 58437 | rc = u.ci.pModule->xNext(u.ci.pCur->pVtabCursor); |
| 57709 | 58438 | p->inVtabMethod = 0; |
| 57710 | 58439 | sqlite3DbFree(db, p->zErrMsg); |
| 57711 | 58440 | p->zErrMsg = u.ci.pVtab->zErrMsg; |
| 57712 | 58441 | u.ci.pVtab->zErrMsg = 0; |
| 57713 | 58442 | if( rc==SQLITE_OK ){ |
| 57714 | 58443 | u.ci.res = u.ci.pModule->xEof(u.ci.pCur->pVtabCursor); |
| 57715 | 58444 | } |
| 57716 | | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57717 | 58445 | |
| 57718 | 58446 | if( !u.ci.res ){ |
| 57719 | 58447 | /* If there is data, jump to P2 */ |
| 57720 | 58448 | pc = pOp->p2 - 1; |
| 57721 | 58449 | } |
| | @@ -57739,16 +58467,14 @@ |
| 57739 | 58467 | u.cj.pVtab = pOp->p4.pVtab->pVtab; |
| 57740 | 58468 | u.cj.pName = &aMem[pOp->p1]; |
| 57741 | 58469 | assert( u.cj.pVtab->pModule->xRename ); |
| 57742 | 58470 | REGISTER_TRACE(pOp->p1, u.cj.pName); |
| 57743 | 58471 | assert( u.cj.pName->flags & MEM_Str ); |
| 57744 | | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57745 | 58472 | rc = u.cj.pVtab->pModule->xRename(u.cj.pVtab, u.cj.pName->z); |
| 57746 | 58473 | sqlite3DbFree(db, p->zErrMsg); |
| 57747 | 58474 | p->zErrMsg = u.cj.pVtab->zErrMsg; |
| 57748 | 58475 | u.cj.pVtab->zErrMsg = 0; |
| 57749 | | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57750 | 58476 | |
| 57751 | 58477 | break; |
| 57752 | 58478 | } |
| 57753 | 58479 | #endif |
| 57754 | 58480 | |
| | @@ -57797,16 +58523,14 @@ |
| 57797 | 58523 | for(u.ck.i=0; u.ck.i<u.ck.nArg; u.ck.i++){ |
| 57798 | 58524 | sqlite3VdbeMemStoreType(u.ck.pX); |
| 57799 | 58525 | u.ck.apArg[u.ck.i] = u.ck.pX; |
| 57800 | 58526 | u.ck.pX++; |
| 57801 | 58527 | } |
| 57802 | | - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; |
| 57803 | 58528 | rc = u.ck.pModule->xUpdate(u.ck.pVtab, u.ck.nArg, u.ck.apArg, &u.ck.rowid); |
| 57804 | 58529 | sqlite3DbFree(db, p->zErrMsg); |
| 57805 | 58530 | p->zErrMsg = u.ck.pVtab->zErrMsg; |
| 57806 | 58531 | u.ck.pVtab->zErrMsg = 0; |
| 57807 | | - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; |
| 57808 | 58532 | if( rc==SQLITE_OK && pOp->p1 ){ |
| 57809 | 58533 | assert( u.ck.nArg>1 && u.ck.apArg[0] && (u.ck.apArg[0]->flags&MEM_Null) ); |
| 57810 | 58534 | db->lastRowid = u.ck.rowid; |
| 57811 | 58535 | } |
| 57812 | 58536 | p->nChange++; |
| | @@ -57879,10 +58603,11 @@ |
| 57879 | 58603 | ** is to say when the EXPLAIN QUERY PLAN syntax is used.) |
| 57880 | 58604 | ** This opcode records information from the optimizer. It is the |
| 57881 | 58605 | ** the same as a no-op. This opcodesnever appears in a real VM program. |
| 57882 | 58606 | */ |
| 57883 | 58607 | default: { /* This is really OP_Noop and OP_Explain */ |
| 58608 | + assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); |
| 57884 | 58609 | break; |
| 57885 | 58610 | } |
| 57886 | 58611 | |
| 57887 | 58612 | /***************************************************************************** |
| 57888 | 58613 | ** The cases of the switch statement above this line should all be indented |
| | @@ -57930,10 +58655,13 @@ |
| 57930 | 58655 | ** an error of some kind. |
| 57931 | 58656 | */ |
| 57932 | 58657 | vdbe_error_halt: |
| 57933 | 58658 | assert( rc ); |
| 57934 | 58659 | p->rc = rc; |
| 58660 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 58661 | + sqlite3_log(rc, "statement aborts at %d: [%s] %s", |
| 58662 | + pc, p->zSql, p->zErrMsg); |
| 57935 | 58663 | sqlite3VdbeHalt(p); |
| 57936 | 58664 | if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; |
| 57937 | 58665 | rc = SQLITE_ERROR; |
| 57938 | 58666 | if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0); |
| 57939 | 58667 | |
| | @@ -57958,16 +58686,10 @@ |
| 57958 | 58686 | db->mallocFailed = 1; |
| 57959 | 58687 | sqlite3SetString(&p->zErrMsg, db, "out of memory"); |
| 57960 | 58688 | rc = SQLITE_NOMEM; |
| 57961 | 58689 | goto vdbe_error_halt; |
| 57962 | 58690 | |
| 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 | 58691 | /* Jump to here for any other kind of fatal error. The "rc" variable |
| 57970 | 58692 | ** should hold the error number. |
| 57971 | 58693 | */ |
| 57972 | 58694 | abort_due_to_error: |
| 57973 | 58695 | assert( p->zErrMsg==0 ); |
| | @@ -58083,17 +58805,10 @@ |
| 58083 | 58805 | } |
| 58084 | 58806 | do { |
| 58085 | 58807 | memset(pParse, 0, sizeof(Parse)); |
| 58086 | 58808 | pParse->db = db; |
| 58087 | 58809 | |
| 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 | 58810 | sqlite3BtreeEnterAll(db); |
| 58096 | 58811 | pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); |
| 58097 | 58812 | if( pTab && IsVirtual(pTab) ){ |
| 58098 | 58813 | pTab = 0; |
| 58099 | 58814 | sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); |
| | @@ -58109,11 +58824,10 @@ |
| 58109 | 58824 | sqlite3DbFree(db, zErr); |
| 58110 | 58825 | zErr = pParse->zErrMsg; |
| 58111 | 58826 | pParse->zErrMsg = 0; |
| 58112 | 58827 | } |
| 58113 | 58828 | rc = SQLITE_ERROR; |
| 58114 | | - (void)sqlite3SafetyOff(db); |
| 58115 | 58829 | sqlite3BtreeLeaveAll(db); |
| 58116 | 58830 | goto blob_open_out; |
| 58117 | 58831 | } |
| 58118 | 58832 | |
| 58119 | 58833 | /* Now search pTab for the exact column. */ |
| | @@ -58124,11 +58838,10 @@ |
| 58124 | 58838 | } |
| 58125 | 58839 | if( iCol==pTab->nCol ){ |
| 58126 | 58840 | sqlite3DbFree(db, zErr); |
| 58127 | 58841 | zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); |
| 58128 | 58842 | rc = SQLITE_ERROR; |
| 58129 | | - (void)sqlite3SafetyOff(db); |
| 58130 | 58843 | sqlite3BtreeLeaveAll(db); |
| 58131 | 58844 | goto blob_open_out; |
| 58132 | 58845 | } |
| 58133 | 58846 | |
| 58134 | 58847 | /* If the value is being opened for writing, check that the |
| | @@ -58165,11 +58878,10 @@ |
| 58165 | 58878 | } |
| 58166 | 58879 | if( zFault ){ |
| 58167 | 58880 | sqlite3DbFree(db, zErr); |
| 58168 | 58881 | zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault); |
| 58169 | 58882 | rc = SQLITE_ERROR; |
| 58170 | | - (void)sqlite3SafetyOff(db); |
| 58171 | 58883 | sqlite3BtreeLeaveAll(db); |
| 58172 | 58884 | goto blob_open_out; |
| 58173 | 58885 | } |
| 58174 | 58886 | } |
| 58175 | 58887 | |
| | @@ -58215,12 +58927,11 @@ |
| 58215 | 58927 | sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0); |
| 58216 | 58928 | } |
| 58217 | 58929 | } |
| 58218 | 58930 | |
| 58219 | 58931 | sqlite3BtreeLeaveAll(db); |
| 58220 | | - rc = sqlite3SafetyOff(db); |
| 58221 | | - if( NEVER(rc!=SQLITE_OK) || db->mallocFailed ){ |
| 58932 | + if( db->mallocFailed ){ |
| 58222 | 58933 | goto blob_open_out; |
| 58223 | 58934 | } |
| 58224 | 58935 | |
| 58225 | 58936 | sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow); |
| 58226 | 58937 | rc = sqlite3_step((sqlite3_stmt *)v); |
| | @@ -58317,11 +59028,11 @@ |
| 58317 | 59028 | int rc; |
| 58318 | 59029 | Incrblob *p = (Incrblob *)pBlob; |
| 58319 | 59030 | Vdbe *v; |
| 58320 | 59031 | sqlite3 *db; |
| 58321 | 59032 | |
| 58322 | | - if( p==0 ) return SQLITE_MISUSE; |
| 59033 | + if( p==0 ) return SQLITE_MISUSE_BKPT; |
| 58323 | 59034 | db = p->db; |
| 58324 | 59035 | sqlite3_mutex_enter(db->mutex); |
| 58325 | 59036 | v = (Vdbe*)p->pStmt; |
| 58326 | 59037 | |
| 58327 | 59038 | if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ |
| | @@ -59675,10 +60386,13 @@ |
| 59675 | 60386 | Expr *pE /* The specific ORDER BY term */ |
| 59676 | 60387 | ){ |
| 59677 | 60388 | int i; /* Loop counter */ |
| 59678 | 60389 | ExprList *pEList; /* The columns of the result set */ |
| 59679 | 60390 | NameContext nc; /* Name context for resolving pE */ |
| 60391 | + sqlite3 *db; /* Database connection */ |
| 60392 | + int rc; /* Return code from subprocedures */ |
| 60393 | + u8 savedSuppErr; /* Saved value of db->suppressErr */ |
| 59680 | 60394 | |
| 59681 | 60395 | assert( sqlite3ExprIsInteger(pE, &i)==0 ); |
| 59682 | 60396 | pEList = pSelect->pEList; |
| 59683 | 60397 | |
| 59684 | 60398 | /* Resolve all names in the ORDER BY term expression |
| | @@ -59687,21 +60401,23 @@ |
| 59687 | 60401 | nc.pParse = pParse; |
| 59688 | 60402 | nc.pSrcList = pSelect->pSrc; |
| 59689 | 60403 | nc.pEList = pEList; |
| 59690 | 60404 | nc.allowAgg = 1; |
| 59691 | 60405 | nc.nErr = 0; |
| 59692 | | - if( sqlite3ResolveExprNames(&nc, pE) ){ |
| 59693 | | - sqlite3ErrorClear(pParse); |
| 59694 | | - return 0; |
| 59695 | | - } |
| 60406 | + db = pParse->db; |
| 60407 | + savedSuppErr = db->suppressErr; |
| 60408 | + db->suppressErr = 1; |
| 60409 | + rc = sqlite3ResolveExprNames(&nc, pE); |
| 60410 | + db->suppressErr = savedSuppErr; |
| 60411 | + if( rc ) return 0; |
| 59696 | 60412 | |
| 59697 | 60413 | /* Try to match the ORDER BY expression against an expression |
| 59698 | 60414 | ** in the result set. Return an 1-based index of the matching |
| 59699 | 60415 | ** result-set entry. |
| 59700 | 60416 | */ |
| 59701 | 60417 | for(i=0; i<pEList->nExpr; i++){ |
| 59702 | | - if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){ |
| 60418 | + if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){ |
| 59703 | 60419 | return i+1; |
| 59704 | 60420 | } |
| 59705 | 60421 | } |
| 59706 | 60422 | |
| 59707 | 60423 | /* If no match, return 0. */ |
| | @@ -62091,10 +62807,11 @@ |
| 62091 | 62807 | memcpy(out, in, 8); |
| 62092 | 62808 | } |
| 62093 | 62809 | return out; |
| 62094 | 62810 | } |
| 62095 | 62811 | |
| 62812 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 62096 | 62813 | /* |
| 62097 | 62814 | ** Generate an instruction that will put the floating point |
| 62098 | 62815 | ** value described by z[0..n-1] into register iMem. |
| 62099 | 62816 | ** |
| 62100 | 62817 | ** The z[] string will probably not be zero-terminated. But the |
| | @@ -62110,10 +62827,11 @@ |
| 62110 | 62827 | if( negateFlag ) value = -value; |
| 62111 | 62828 | zV = dup8bytes(v, (char*)&value); |
| 62112 | 62829 | sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); |
| 62113 | 62830 | } |
| 62114 | 62831 | } |
| 62832 | +#endif |
| 62115 | 62833 | |
| 62116 | 62834 | |
| 62117 | 62835 | /* |
| 62118 | 62836 | ** Generate an instruction that will put the integer describe by |
| 62119 | 62837 | ** text z[0..n-1] into register iMem. |
| | @@ -62120,11 +62838,12 @@ |
| 62120 | 62838 | ** |
| 62121 | 62839 | ** The z[] string will probably not be zero-terminated. But the |
| 62122 | 62840 | ** z[n] character is guaranteed to be something that does not look |
| 62123 | 62841 | ** like the continuation of the number. |
| 62124 | 62842 | */ |
| 62125 | | -static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ |
| 62843 | +static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ |
| 62844 | + Vdbe *v = pParse->pVdbe; |
| 62126 | 62845 | if( pExpr->flags & EP_IntValue ){ |
| 62127 | 62846 | int i = pExpr->u.iValue; |
| 62128 | 62847 | if( negFlag ) i = -i; |
| 62129 | 62848 | sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); |
| 62130 | 62849 | }else{ |
| | @@ -62136,11 +62855,15 @@ |
| 62136 | 62855 | sqlite3Atoi64(z, &value); |
| 62137 | 62856 | if( negFlag ) value = -value; |
| 62138 | 62857 | zV = dup8bytes(v, (char*)&value); |
| 62139 | 62858 | sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); |
| 62140 | 62859 | }else{ |
| 62860 | +#ifdef SQLITE_OMIT_FLOATING_POINT |
| 62861 | + sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); |
| 62862 | +#else |
| 62141 | 62863 | codeReal(v, z, negFlag, iMem); |
| 62864 | +#endif |
| 62142 | 62865 | } |
| 62143 | 62866 | } |
| 62144 | 62867 | } |
| 62145 | 62868 | |
| 62146 | 62869 | /* |
| | @@ -62523,18 +63246,20 @@ |
| 62523 | 63246 | pExpr->iColumn, pExpr->iTable, target); |
| 62524 | 63247 | } |
| 62525 | 63248 | break; |
| 62526 | 63249 | } |
| 62527 | 63250 | case TK_INTEGER: { |
| 62528 | | - codeInteger(v, pExpr, 0, target); |
| 63251 | + codeInteger(pParse, pExpr, 0, target); |
| 62529 | 63252 | break; |
| 62530 | 63253 | } |
| 63254 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 62531 | 63255 | case TK_FLOAT: { |
| 62532 | 63256 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 62533 | 63257 | codeReal(v, pExpr->u.zToken, 0, target); |
| 62534 | 63258 | break; |
| 62535 | 63259 | } |
| 63260 | +#endif |
| 62536 | 63261 | case TK_STRING: { |
| 62537 | 63262 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 62538 | 63263 | sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); |
| 62539 | 63264 | break; |
| 62540 | 63265 | } |
| | @@ -62700,15 +63425,17 @@ |
| 62700 | 63425 | break; |
| 62701 | 63426 | } |
| 62702 | 63427 | case TK_UMINUS: { |
| 62703 | 63428 | Expr *pLeft = pExpr->pLeft; |
| 62704 | 63429 | assert( pLeft ); |
| 62705 | | - if( pLeft->op==TK_FLOAT ){ |
| 63430 | + if( pLeft->op==TK_INTEGER ){ |
| 63431 | + codeInteger(pParse, pLeft, 1, target); |
| 63432 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 63433 | + }else if( pLeft->op==TK_FLOAT ){ |
| 62706 | 63434 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 62707 | 63435 | codeReal(v, pLeft->u.zToken, 1, target); |
| 62708 | | - }else if( pLeft->op==TK_INTEGER ){ |
| 62709 | | - codeInteger(v, pLeft, 1, target); |
| 63436 | +#endif |
| 62710 | 63437 | }else{ |
| 62711 | 63438 | regFree1 = r1 = sqlite3GetTempReg(pParse); |
| 62712 | 63439 | sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); |
| 62713 | 63440 | r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); |
| 62714 | 63441 | sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); |
| | @@ -62952,17 +63679,19 @@ |
| 62952 | 63679 | (pExpr->iTable ? "new" : "old"), |
| 62953 | 63680 | (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), |
| 62954 | 63681 | target |
| 62955 | 63682 | )); |
| 62956 | 63683 | |
| 63684 | +#ifndef SQLITE_OMIT_FLOATING_POINT |
| 62957 | 63685 | /* If the column has REAL affinity, it may currently be stored as an |
| 62958 | 63686 | ** integer. Use OP_RealAffinity to make sure it is really real. */ |
| 62959 | 63687 | if( pExpr->iColumn>=0 |
| 62960 | 63688 | && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL |
| 62961 | 63689 | ){ |
| 62962 | 63690 | sqlite3VdbeAddOp1(v, OP_RealAffinity, target); |
| 62963 | 63691 | } |
| 63692 | +#endif |
| 62964 | 63693 | break; |
| 62965 | 63694 | } |
| 62966 | 63695 | |
| 62967 | 63696 | |
| 62968 | 63697 | /* |
| | @@ -63624,61 +64353,65 @@ |
| 63624 | 64353 | sqlite3ReleaseTempReg(pParse, regFree1); |
| 63625 | 64354 | sqlite3ReleaseTempReg(pParse, regFree2); |
| 63626 | 64355 | } |
| 63627 | 64356 | |
| 63628 | 64357 | /* |
| 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. |
| 64358 | +** Do a deep comparison of two expression trees. Return 0 if the two |
| 64359 | +** expressions are completely identical. Return 1 if they differ only |
| 64360 | +** by a COLLATE operator at the top level. Return 2 if there are differences |
| 64361 | +** other than the top-level COLLATE operator. |
| 63631 | 64362 | ** |
| 63632 | | -** Sometimes this routine will return FALSE even if the two expressions |
| 64363 | +** Sometimes this routine will return 2 even if the two expressions |
| 63633 | 64364 | ** 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 |
| 64365 | +** identical, we return 2 just to be safe. So if this routine |
| 64366 | +** returns 2, then you do not really know for certain if the two |
| 64367 | +** expressions are the same. But if you get a 0 or 1 return, then you |
| 63637 | 64368 | ** 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 |
| 64369 | +** this routine is used, it does not hurt to get an extra 2 - that |
| 63639 | 64370 | ** just might result in some slightly slower code. But returning |
| 63640 | | -** an incorrect TRUE could lead to a malfunction. |
| 64371 | +** an incorrect 0 or 1 could lead to a malfunction. |
| 63641 | 64372 | */ |
| 63642 | 64373 | SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){ |
| 63643 | 64374 | int i; |
| 63644 | 64375 | if( pA==0||pB==0 ){ |
| 63645 | | - return pB==pA; |
| 64376 | + return pB==pA ? 0 : 2; |
| 63646 | 64377 | } |
| 63647 | 64378 | assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); |
| 63648 | 64379 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 63649 | 64380 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 63650 | | - return 0; |
| 64381 | + return 2; |
| 63651 | 64382 | } |
| 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; |
| 64383 | + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; |
| 64384 | + if( pA->op!=pB->op ) return 2; |
| 64385 | + if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; |
| 64386 | + if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; |
| 63656 | 64387 | |
| 63657 | 64388 | if( pA->x.pList && pB->x.pList ){ |
| 63658 | | - if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 0; |
| 64389 | + if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 2; |
| 63659 | 64390 | for(i=0; i<pA->x.pList->nExpr; i++){ |
| 63660 | 64391 | Expr *pExprA = pA->x.pList->a[i].pExpr; |
| 63661 | 64392 | Expr *pExprB = pB->x.pList->a[i].pExpr; |
| 63662 | | - if( !sqlite3ExprCompare(pExprA, pExprB) ) return 0; |
| 64393 | + if( sqlite3ExprCompare(pExprA, pExprB) ) return 2; |
| 63663 | 64394 | } |
| 63664 | 64395 | }else if( pA->x.pList || pB->x.pList ){ |
| 63665 | | - return 0; |
| 64396 | + return 2; |
| 63666 | 64397 | } |
| 63667 | 64398 | |
| 63668 | | - if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; |
| 64399 | + if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; |
| 63669 | 64400 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| 63670 | 64401 | if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ |
| 63671 | | - return 0; |
| 64402 | + return 2; |
| 63672 | 64403 | } |
| 63673 | 64404 | }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ |
| 63674 | | - if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 0; |
| 64405 | + if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; |
| 63675 | 64406 | if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 63676 | | - return 0; |
| 64407 | + return 2; |
| 63677 | 64408 | } |
| 63678 | 64409 | } |
| 63679 | | - return 1; |
| 64410 | + if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; |
| 64411 | + if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; |
| 64412 | + return 0; |
| 63680 | 64413 | } |
| 63681 | 64414 | |
| 63682 | 64415 | |
| 63683 | 64416 | /* |
| 63684 | 64417 | ** Add a new element to the pAggInfo->aCol[] array. Return the index of |
| | @@ -63805,11 +64538,11 @@ |
| 63805 | 64538 | /* Check to see if pExpr is a duplicate of another aggregate |
| 63806 | 64539 | ** function that is already in the pAggInfo structure |
| 63807 | 64540 | */ |
| 63808 | 64541 | struct AggInfo_func *pItem = pAggInfo->aFunc; |
| 63809 | 64542 | for(i=0; i<pAggInfo->nFunc; i++, pItem++){ |
| 63810 | | - if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){ |
| 64543 | + if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){ |
| 63811 | 64544 | break; |
| 63812 | 64545 | } |
| 63813 | 64546 | } |
| 63814 | 64547 | if( i>=pAggInfo->nFunc ){ |
| 63815 | 64548 | /* pExpr is original. Make a new entry in pAggInfo->aFunc[] |
| | @@ -64426,13 +65159,13 @@ |
| 64426 | 65159 | /* If foreign-key support is enabled, rewrite the CREATE TABLE |
| 64427 | 65160 | ** statements corresponding to all child tables of foreign key constraints |
| 64428 | 65161 | ** for which the renamed table is the parent table. */ |
| 64429 | 65162 | if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ |
| 64430 | 65163 | sqlite3NestedParse(pParse, |
| 64431 | | - "UPDATE sqlite_master SET " |
| 65164 | + "UPDATE \"%w\".%s SET " |
| 64432 | 65165 | "sql = sqlite_rename_parent(sql, %Q, %Q) " |
| 64433 | | - "WHERE %s;", zTabName, zName, zWhere); |
| 65166 | + "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere); |
| 64434 | 65167 | sqlite3DbFree(db, zWhere); |
| 64435 | 65168 | } |
| 64436 | 65169 | } |
| 64437 | 65170 | #endif |
| 64438 | 65171 | |
| | @@ -65301,13 +66034,11 @@ |
| 65301 | 66034 | zSql = sqlite3MPrintf(db, |
| 65302 | 66035 | "SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase); |
| 65303 | 66036 | if( zSql==0 ){ |
| 65304 | 66037 | rc = SQLITE_NOMEM; |
| 65305 | 66038 | }else{ |
| 65306 | | - (void)sqlite3SafetyOff(db); |
| 65307 | 66039 | rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); |
| 65308 | | - (void)sqlite3SafetyOn(db); |
| 65309 | 66040 | sqlite3DbFree(db, zSql); |
| 65310 | 66041 | } |
| 65311 | 66042 | |
| 65312 | 66043 | |
| 65313 | 66044 | /* Load the statistics from the sqlite_stat2 table. */ |
| | @@ -65321,18 +66052,15 @@ |
| 65321 | 66052 | zSql = sqlite3MPrintf(db, |
| 65322 | 66053 | "SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase); |
| 65323 | 66054 | if( !zSql ){ |
| 65324 | 66055 | rc = SQLITE_NOMEM; |
| 65325 | 66056 | }else{ |
| 65326 | | - (void)sqlite3SafetyOff(db); |
| 65327 | 66057 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 65328 | | - (void)sqlite3SafetyOn(db); |
| 65329 | 66058 | sqlite3DbFree(db, zSql); |
| 65330 | 66059 | } |
| 65331 | 66060 | |
| 65332 | 66061 | if( rc==SQLITE_OK ){ |
| 65333 | | - (void)sqlite3SafetyOff(db); |
| 65334 | 66062 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 65335 | 66063 | char *zIndex = (char *)sqlite3_column_text(pStmt, 0); |
| 65336 | 66064 | Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase); |
| 65337 | 66065 | if( pIdx ){ |
| 65338 | 66066 | int iSample = sqlite3_column_int(pStmt, 1); |
| | @@ -65378,11 +66106,10 @@ |
| 65378 | 66106 | } |
| 65379 | 66107 | } |
| 65380 | 66108 | } |
| 65381 | 66109 | } |
| 65382 | 66110 | rc = sqlite3_finalize(pStmt); |
| 65383 | | - (void)sqlite3SafetyOn(db); |
| 65384 | 66111 | } |
| 65385 | 66112 | } |
| 65386 | 66113 | #endif |
| 65387 | 66114 | |
| 65388 | 66115 | if( rc==SQLITE_NOMEM ){ |
| | @@ -65539,15 +66266,21 @@ |
| 65539 | 66266 | rc = SQLITE_ERROR; |
| 65540 | 66267 | } |
| 65541 | 66268 | pPager = sqlite3BtreePager(aNew->pBt); |
| 65542 | 66269 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 65543 | 66270 | sqlite3PagerJournalMode(pPager, db->dfltJournalMode); |
| 66271 | + sqlite3BtreeSecureDelete(aNew->pBt, |
| 66272 | + sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 65544 | 66273 | } |
| 65545 | | - aNew->zName = sqlite3DbStrDup(db, zName); |
| 65546 | 66274 | aNew->safety_level = 3; |
| 66275 | + aNew->zName = sqlite3DbStrDup(db, zName); |
| 66276 | + if( rc==SQLITE_OK && aNew->zName==0 ){ |
| 66277 | + rc = SQLITE_NOMEM; |
| 66278 | + } |
| 65547 | 66279 | |
| 65548 | | -#if SQLITE_HAS_CODEC |
| 66280 | + |
| 66281 | +#ifdef SQLITE_HAS_CODEC |
| 65549 | 66282 | if( rc==SQLITE_OK ){ |
| 65550 | 66283 | extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); |
| 65551 | 66284 | extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); |
| 65552 | 66285 | int nKey; |
| 65553 | 66286 | char *zKey; |
| | @@ -65579,15 +66312,13 @@ |
| 65579 | 66312 | ** If this fails, or if opening the file failed, then close the file and |
| 65580 | 66313 | ** remove the entry from the db->aDb[] array. i.e. put everything back the way |
| 65581 | 66314 | ** we found it. |
| 65582 | 66315 | */ |
| 65583 | 66316 | if( rc==SQLITE_OK ){ |
| 65584 | | - (void)sqlite3SafetyOn(db); |
| 65585 | 66317 | sqlite3BtreeEnterAll(db); |
| 65586 | 66318 | rc = sqlite3Init(db, &zErrDyn); |
| 65587 | 66319 | sqlite3BtreeLeaveAll(db); |
| 65588 | | - (void)sqlite3SafetyOff(db); |
| 65589 | 66320 | } |
| 65590 | 66321 | if( rc ){ |
| 65591 | 66322 | int iDb = db->nDb - 1; |
| 65592 | 66323 | assert( iDb>=2 ); |
| 65593 | 66324 | if( db->aDb[iDb].pBt ){ |
| | @@ -66385,11 +67116,11 @@ |
| 66385 | 67116 | sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem, |
| 66386 | 67117 | pParse->nTab, pParse->nMaxArg, pParse->explain, |
| 66387 | 67118 | pParse->isMultiWrite && pParse->mayAbort); |
| 66388 | 67119 | pParse->rc = SQLITE_DONE; |
| 66389 | 67120 | pParse->colNamesSet = 0; |
| 66390 | | - }else if( pParse->rc==SQLITE_OK ){ |
| 67121 | + }else{ |
| 66391 | 67122 | pParse->rc = SQLITE_ERROR; |
| 66392 | 67123 | } |
| 66393 | 67124 | pParse->nTab = 0; |
| 66394 | 67125 | pParse->nMem = 0; |
| 66395 | 67126 | pParse->nSet = 0; |
| | @@ -68157,17 +68888,16 @@ |
| 68157 | 68888 | if( db->mallocFailed ){ |
| 68158 | 68889 | goto exit_drop_table; |
| 68159 | 68890 | } |
| 68160 | 68891 | assert( pParse->nErr==0 ); |
| 68161 | 68892 | assert( pName->nSrc==1 ); |
| 68893 | + if( noErr ) db->suppressErr++; |
| 68162 | 68894 | pTab = sqlite3LocateTable(pParse, isView, |
| 68163 | 68895 | pName->a[0].zName, pName->a[0].zDatabase); |
| 68896 | + if( noErr ) db->suppressErr--; |
| 68164 | 68897 | |
| 68165 | 68898 | if( pTab==0 ){ |
| 68166 | | - if( noErr ){ |
| 68167 | | - sqlite3ErrorClear(pParse); |
| 68168 | | - } |
| 68169 | 68899 | goto exit_drop_table; |
| 68170 | 68900 | } |
| 68171 | 68901 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 68172 | 68902 | assert( iDb>=0 && iDb<db->nDb ); |
| 68173 | 68903 | |
| | @@ -69585,28 +70315,32 @@ |
| 69585 | 70315 | */ |
| 69586 | 70316 | SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ |
| 69587 | 70317 | sqlite3 *db = pParse->db; |
| 69588 | 70318 | if( db->aDb[1].pBt==0 && !pParse->explain ){ |
| 69589 | 70319 | int rc; |
| 70320 | + Btree *pBt; |
| 69590 | 70321 | static const int flags = |
| 69591 | 70322 | SQLITE_OPEN_READWRITE | |
| 69592 | 70323 | SQLITE_OPEN_CREATE | |
| 69593 | 70324 | SQLITE_OPEN_EXCLUSIVE | |
| 69594 | 70325 | SQLITE_OPEN_DELETEONCLOSE | |
| 69595 | 70326 | SQLITE_OPEN_TEMP_DB; |
| 69596 | 70327 | |
| 69597 | | - rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, |
| 69598 | | - &db->aDb[1].pBt); |
| 70328 | + rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, &pBt); |
| 69599 | 70329 | if( rc!=SQLITE_OK ){ |
| 69600 | 70330 | sqlite3ErrorMsg(pParse, "unable to open a temporary database " |
| 69601 | 70331 | "file for storing temporary tables"); |
| 69602 | 70332 | pParse->rc = rc; |
| 69603 | 70333 | return 1; |
| 69604 | 70334 | } |
| 70335 | + db->aDb[1].pBt = pBt; |
| 69605 | 70336 | assert( db->aDb[1].pSchema ); |
| 69606 | | - sqlite3PagerJournalMode(sqlite3BtreePager(db->aDb[1].pBt), |
| 69607 | | - db->dfltJournalMode); |
| 70337 | + if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
| 70338 | + db->mallocFailed = 1; |
| 70339 | + return 1; |
| 70340 | + } |
| 70341 | + sqlite3PagerJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode); |
| 69608 | 70342 | } |
| 69609 | 70343 | return 0; |
| 69610 | 70344 | } |
| 69611 | 70345 | |
| 69612 | 70346 | /* |
| | @@ -70339,10 +71073,397 @@ |
| 70339 | 71073 | } |
| 70340 | 71074 | return p; |
| 70341 | 71075 | } |
| 70342 | 71076 | |
| 70343 | 71077 | /************** End of callback.c ********************************************/ |
| 71078 | +/************** Begin file ctime.c *******************************************/ |
| 71079 | +/* |
| 71080 | +** 2010 February 23 |
| 71081 | +** |
| 71082 | +** The author disclaims copyright to this source code. In place of |
| 71083 | +** a legal notice, here is a blessing: |
| 71084 | +** |
| 71085 | +** May you do good and not evil. |
| 71086 | +** May you find forgiveness for yourself and forgive others. |
| 71087 | +** May you share freely, never taking more than you give. |
| 71088 | +** |
| 71089 | +************************************************************************* |
| 71090 | +** |
| 71091 | +** This file implements routines used to report what compile-time options |
| 71092 | +** SQLite was built with. |
| 71093 | +*/ |
| 71094 | + |
| 71095 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 71096 | + |
| 71097 | + |
| 71098 | +/* |
| 71099 | +** An array of names of all compile-time options. This array should |
| 71100 | +** be sorted A-Z. |
| 71101 | +** |
| 71102 | +** This array looks large, but in a typical installation actually uses |
| 71103 | +** only a handful of compile-time options, so most times this array is usually |
| 71104 | +** rather short and uses little memory space. |
| 71105 | +*/ |
| 71106 | +static const char * const azCompileOpt[] = { |
| 71107 | + |
| 71108 | +/* These macros are provided to "stringify" the value of the define |
| 71109 | +** for those options in which the value is meaningful. */ |
| 71110 | +#define CTIMEOPT_VAL_(opt) #opt |
| 71111 | +#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) |
| 71112 | + |
| 71113 | +#ifdef SQLITE_32BIT_ROWID |
| 71114 | + "32BIT_ROWID", |
| 71115 | +#endif |
| 71116 | +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC |
| 71117 | + "4_BYTE_ALIGNED_MALLOC", |
| 71118 | +#endif |
| 71119 | +#ifdef SQLITE_CASE_SENSITIVE_LIKE |
| 71120 | + "CASE_SENSITIVE_LIKE", |
| 71121 | +#endif |
| 71122 | +#ifdef SQLITE_CHECK_PAGES |
| 71123 | + "CHECK_PAGES", |
| 71124 | +#endif |
| 71125 | +#ifdef SQLITE_COVERAGE_TEST |
| 71126 | + "COVERAGE_TEST", |
| 71127 | +#endif |
| 71128 | +#ifdef SQLITE_DEBUG |
| 71129 | + "DEBUG", |
| 71130 | +#endif |
| 71131 | +#ifdef SQLITE_DEFAULT_LOCKING_MODE |
| 71132 | + "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 71133 | +#endif |
| 71134 | +#ifdef SQLITE_DISABLE_DIRSYNC |
| 71135 | + "DISABLE_DIRSYNC", |
| 71136 | +#endif |
| 71137 | +#ifdef SQLITE_DISABLE_LFS |
| 71138 | + "DISABLE_LFS", |
| 71139 | +#endif |
| 71140 | +#ifdef SQLITE_ENABLE_ATOMIC_WRITE |
| 71141 | + "ENABLE_ATOMIC_WRITE", |
| 71142 | +#endif |
| 71143 | +#ifdef SQLITE_ENABLE_CEROD |
| 71144 | + "ENABLE_CEROD", |
| 71145 | +#endif |
| 71146 | +#ifdef SQLITE_ENABLE_COLUMN_METADATA |
| 71147 | + "ENABLE_COLUMN_METADATA", |
| 71148 | +#endif |
| 71149 | +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT |
| 71150 | + "ENABLE_EXPENSIVE_ASSERT", |
| 71151 | +#endif |
| 71152 | +#ifdef SQLITE_ENABLE_FTS1 |
| 71153 | + "ENABLE_FTS1", |
| 71154 | +#endif |
| 71155 | +#ifdef SQLITE_ENABLE_FTS2 |
| 71156 | + "ENABLE_FTS2", |
| 71157 | +#endif |
| 71158 | +#ifdef SQLITE_ENABLE_FTS3 |
| 71159 | + "ENABLE_FTS3", |
| 71160 | +#endif |
| 71161 | +#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS |
| 71162 | + "ENABLE_FTS3_PARENTHESIS", |
| 71163 | +#endif |
| 71164 | +#ifdef SQLITE_ENABLE_FTS4 |
| 71165 | + "ENABLE_FTS4", |
| 71166 | +#endif |
| 71167 | +#ifdef SQLITE_ENABLE_ICU |
| 71168 | + "ENABLE_ICU", |
| 71169 | +#endif |
| 71170 | +#ifdef SQLITE_ENABLE_IOTRACE |
| 71171 | + "ENABLE_IOTRACE", |
| 71172 | +#endif |
| 71173 | +#ifdef SQLITE_ENABLE_LOAD_EXTENSION |
| 71174 | + "ENABLE_LOAD_EXTENSION", |
| 71175 | +#endif |
| 71176 | +#ifdef SQLITE_ENABLE_LOCKING_STYLE |
| 71177 | + "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), |
| 71178 | +#endif |
| 71179 | +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 71180 | + "ENABLE_MEMORY_MANAGEMENT", |
| 71181 | +#endif |
| 71182 | +#ifdef SQLITE_ENABLE_MEMSYS3 |
| 71183 | + "ENABLE_MEMSYS3", |
| 71184 | +#endif |
| 71185 | +#ifdef SQLITE_ENABLE_MEMSYS5 |
| 71186 | + "ENABLE_MEMSYS5", |
| 71187 | +#endif |
| 71188 | +#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK |
| 71189 | + "ENABLE_OVERSIZE_CELL_CHECK", |
| 71190 | +#endif |
| 71191 | +#ifdef SQLITE_ENABLE_RTREE |
| 71192 | + "ENABLE_RTREE", |
| 71193 | +#endif |
| 71194 | +#ifdef SQLITE_ENABLE_STAT2 |
| 71195 | + "ENABLE_STAT2", |
| 71196 | +#endif |
| 71197 | +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |
| 71198 | + "ENABLE_UNLOCK_NOTIFY", |
| 71199 | +#endif |
| 71200 | +#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT |
| 71201 | + "ENABLE_UPDATE_DELETE_LIMIT", |
| 71202 | +#endif |
| 71203 | +#ifdef SQLITE_HAS_CODEC |
| 71204 | + "HAS_CODEC", |
| 71205 | +#endif |
| 71206 | +#ifdef SQLITE_HAVE_ISNAN |
| 71207 | + "HAVE_ISNAN", |
| 71208 | +#endif |
| 71209 | +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX |
| 71210 | + "HOMEGROWN_RECURSIVE_MUTEX", |
| 71211 | +#endif |
| 71212 | +#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS |
| 71213 | + "IGNORE_AFP_LOCK_ERRORS", |
| 71214 | +#endif |
| 71215 | +#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS |
| 71216 | + "IGNORE_FLOCK_LOCK_ERRORS", |
| 71217 | +#endif |
| 71218 | +#ifdef SQLITE_INT64_TYPE |
| 71219 | + "INT64_TYPE", |
| 71220 | +#endif |
| 71221 | +#ifdef SQLITE_LOCK_TRACE |
| 71222 | + "LOCK_TRACE", |
| 71223 | +#endif |
| 71224 | +#ifdef SQLITE_MEMDEBUG |
| 71225 | + "MEMDEBUG", |
| 71226 | +#endif |
| 71227 | +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT |
| 71228 | + "MIXED_ENDIAN_64BIT_FLOAT", |
| 71229 | +#endif |
| 71230 | +#ifdef SQLITE_NO_SYNC |
| 71231 | + "NO_SYNC", |
| 71232 | +#endif |
| 71233 | +#ifdef SQLITE_OMIT_ALTERTABLE |
| 71234 | + "OMIT_ALTERTABLE", |
| 71235 | +#endif |
| 71236 | +#ifdef SQLITE_OMIT_ANALYZE |
| 71237 | + "OMIT_ANALYZE", |
| 71238 | +#endif |
| 71239 | +#ifdef SQLITE_OMIT_ATTACH |
| 71240 | + "OMIT_ATTACH", |
| 71241 | +#endif |
| 71242 | +#ifdef SQLITE_OMIT_AUTHORIZATION |
| 71243 | + "OMIT_AUTHORIZATION", |
| 71244 | +#endif |
| 71245 | +#ifdef SQLITE_OMIT_AUTOINCREMENT |
| 71246 | + "OMIT_AUTOINCREMENT", |
| 71247 | +#endif |
| 71248 | +#ifdef SQLITE_OMIT_AUTOINIT |
| 71249 | + "OMIT_AUTOINIT", |
| 71250 | +#endif |
| 71251 | +#ifdef SQLITE_OMIT_AUTOVACUUM |
| 71252 | + "OMIT_AUTOVACUUM", |
| 71253 | +#endif |
| 71254 | +#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION |
| 71255 | + "OMIT_BETWEEN_OPTIMIZATION", |
| 71256 | +#endif |
| 71257 | +#ifdef SQLITE_OMIT_BLOB_LITERAL |
| 71258 | + "OMIT_BLOB_LITERAL", |
| 71259 | +#endif |
| 71260 | +#ifdef SQLITE_OMIT_BTREECOUNT |
| 71261 | + "OMIT_BTREECOUNT", |
| 71262 | +#endif |
| 71263 | +#ifdef SQLITE_OMIT_BUILTIN_TEST |
| 71264 | + "OMIT_BUILTIN_TEST", |
| 71265 | +#endif |
| 71266 | +#ifdef SQLITE_OMIT_CAST |
| 71267 | + "OMIT_CAST", |
| 71268 | +#endif |
| 71269 | +#ifdef SQLITE_OMIT_CHECK |
| 71270 | + "OMIT_CHECK", |
| 71271 | +#endif |
| 71272 | +#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 71273 | + "OMIT_COMPILEOPTION_DIAGS", |
| 71274 | +#endif |
| 71275 | +#ifdef SQLITE_OMIT_COMPLETE |
| 71276 | + "OMIT_COMPLETE", |
| 71277 | +#endif |
| 71278 | +#ifdef SQLITE_OMIT_COMPOUND_SELECT |
| 71279 | + "OMIT_COMPOUND_SELECT", |
| 71280 | +#endif |
| 71281 | +#ifdef SQLITE_OMIT_DATETIME_FUNCS |
| 71282 | + "OMIT_DATETIME_FUNCS", |
| 71283 | +#endif |
| 71284 | +#ifdef SQLITE_OMIT_DECLTYPE |
| 71285 | + "OMIT_DECLTYPE", |
| 71286 | +#endif |
| 71287 | +#ifdef SQLITE_OMIT_DEPRECATED |
| 71288 | + "OMIT_DEPRECATED", |
| 71289 | +#endif |
| 71290 | +#ifdef SQLITE_OMIT_DISKIO |
| 71291 | + "OMIT_DISKIO", |
| 71292 | +#endif |
| 71293 | +#ifdef SQLITE_OMIT_EXPLAIN |
| 71294 | + "OMIT_EXPLAIN", |
| 71295 | +#endif |
| 71296 | +#ifdef SQLITE_OMIT_FLAG_PRAGMAS |
| 71297 | + "OMIT_FLAG_PRAGMAS", |
| 71298 | +#endif |
| 71299 | +#ifdef SQLITE_OMIT_FLOATING_POINT |
| 71300 | + "OMIT_FLOATING_POINT", |
| 71301 | +#endif |
| 71302 | +#ifdef SQLITE_OMIT_FOREIGN_KEY |
| 71303 | + "OMIT_FOREIGN_KEY", |
| 71304 | +#endif |
| 71305 | +#ifdef SQLITE_OMIT_GET_TABLE |
| 71306 | + "OMIT_GET_TABLE", |
| 71307 | +#endif |
| 71308 | +#ifdef SQLITE_OMIT_GLOBALRECOVER |
| 71309 | + "OMIT_GLOBALRECOVER", |
| 71310 | +#endif |
| 71311 | +#ifdef SQLITE_OMIT_INCRBLOB |
| 71312 | + "OMIT_INCRBLOB", |
| 71313 | +#endif |
| 71314 | +#ifdef SQLITE_OMIT_INTEGRITY_CHECK |
| 71315 | + "OMIT_INTEGRITY_CHECK", |
| 71316 | +#endif |
| 71317 | +#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION |
| 71318 | + "OMIT_LIKE_OPTIMIZATION", |
| 71319 | +#endif |
| 71320 | +#ifdef SQLITE_OMIT_LOAD_EXTENSION |
| 71321 | + "OMIT_LOAD_EXTENSION", |
| 71322 | +#endif |
| 71323 | +#ifdef SQLITE_OMIT_LOCALTIME |
| 71324 | + "OMIT_LOCALTIME", |
| 71325 | +#endif |
| 71326 | +#ifdef SQLITE_OMIT_LOOKASIDE |
| 71327 | + "OMIT_LOOKASIDE", |
| 71328 | +#endif |
| 71329 | +#ifdef SQLITE_OMIT_MEMORYDB |
| 71330 | + "OMIT_MEMORYDB", |
| 71331 | +#endif |
| 71332 | +#ifdef SQLITE_OMIT_OR_OPTIMIZATION |
| 71333 | + "OMIT_OR_OPTIMIZATION", |
| 71334 | +#endif |
| 71335 | +#ifdef SQLITE_OMIT_PAGER_PRAGMAS |
| 71336 | + "OMIT_PAGER_PRAGMAS", |
| 71337 | +#endif |
| 71338 | +#ifdef SQLITE_OMIT_PRAGMA |
| 71339 | + "OMIT_PRAGMA", |
| 71340 | +#endif |
| 71341 | +#ifdef SQLITE_OMIT_PROGRESS_CALLBACK |
| 71342 | + "OMIT_PROGRESS_CALLBACK", |
| 71343 | +#endif |
| 71344 | +#ifdef SQLITE_OMIT_QUICKBALANCE |
| 71345 | + "OMIT_QUICKBALANCE", |
| 71346 | +#endif |
| 71347 | +#ifdef SQLITE_OMIT_REINDEX |
| 71348 | + "OMIT_REINDEX", |
| 71349 | +#endif |
| 71350 | +#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS |
| 71351 | + "OMIT_SCHEMA_PRAGMAS", |
| 71352 | +#endif |
| 71353 | +#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS |
| 71354 | + "OMIT_SCHEMA_VERSION_PRAGMAS", |
| 71355 | +#endif |
| 71356 | +#ifdef SQLITE_OMIT_SHARED_CACHE |
| 71357 | + "OMIT_SHARED_CACHE", |
| 71358 | +#endif |
| 71359 | +#ifdef SQLITE_OMIT_SUBQUERY |
| 71360 | + "OMIT_SUBQUERY", |
| 71361 | +#endif |
| 71362 | +#ifdef SQLITE_OMIT_TCL_VARIABLE |
| 71363 | + "OMIT_TCL_VARIABLE", |
| 71364 | +#endif |
| 71365 | +#ifdef SQLITE_OMIT_TEMPDB |
| 71366 | + "OMIT_TEMPDB", |
| 71367 | +#endif |
| 71368 | +#ifdef SQLITE_OMIT_TRACE |
| 71369 | + "OMIT_TRACE", |
| 71370 | +#endif |
| 71371 | +#ifdef SQLITE_OMIT_TRIGGER |
| 71372 | + "OMIT_TRIGGER", |
| 71373 | +#endif |
| 71374 | +#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION |
| 71375 | + "OMIT_TRUNCATE_OPTIMIZATION", |
| 71376 | +#endif |
| 71377 | +#ifdef SQLITE_OMIT_UTF16 |
| 71378 | + "OMIT_UTF16", |
| 71379 | +#endif |
| 71380 | +#ifdef SQLITE_OMIT_VACUUM |
| 71381 | + "OMIT_VACUUM", |
| 71382 | +#endif |
| 71383 | +#ifdef SQLITE_OMIT_VIEW |
| 71384 | + "OMIT_VIEW", |
| 71385 | +#endif |
| 71386 | +#ifdef SQLITE_OMIT_VIRTUALTABLE |
| 71387 | + "OMIT_VIRTUALTABLE", |
| 71388 | +#endif |
| 71389 | +#ifdef SQLITE_OMIT_WSD |
| 71390 | + "OMIT_WSD", |
| 71391 | +#endif |
| 71392 | +#ifdef SQLITE_OMIT_XFER_OPT |
| 71393 | + "OMIT_XFER_OPT", |
| 71394 | +#endif |
| 71395 | +#ifdef SQLITE_PERFORMANCE_TRACE |
| 71396 | + "PERFORMANCE_TRACE", |
| 71397 | +#endif |
| 71398 | +#ifdef SQLITE_PROXY_DEBUG |
| 71399 | + "PROXY_DEBUG", |
| 71400 | +#endif |
| 71401 | +#ifdef SQLITE_SECURE_DELETE |
| 71402 | + "SECURE_DELETE", |
| 71403 | +#endif |
| 71404 | +#ifdef SQLITE_SMALL_STACK |
| 71405 | + "SMALL_STACK", |
| 71406 | +#endif |
| 71407 | +#ifdef SQLITE_SOUNDEX |
| 71408 | + "SOUNDEX", |
| 71409 | +#endif |
| 71410 | +#ifdef SQLITE_TCL |
| 71411 | + "TCL", |
| 71412 | +#endif |
| 71413 | +#ifdef SQLITE_TEMP_STORE |
| 71414 | + "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), |
| 71415 | +#endif |
| 71416 | +#ifdef SQLITE_TEST |
| 71417 | + "TEST", |
| 71418 | +#endif |
| 71419 | +#ifdef SQLITE_THREADSAFE |
| 71420 | + "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), |
| 71421 | +#endif |
| 71422 | +#ifdef SQLITE_USE_ALLOCA |
| 71423 | + "USE_ALLOCA", |
| 71424 | +#endif |
| 71425 | +#ifdef SQLITE_ZERO_MALLOC |
| 71426 | + "ZERO_MALLOC" |
| 71427 | +#endif |
| 71428 | +}; |
| 71429 | + |
| 71430 | +/* |
| 71431 | +** Given the name of a compile-time option, return true if that option |
| 71432 | +** was used and false if not. |
| 71433 | +** |
| 71434 | +** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix |
| 71435 | +** is not required for a match. |
| 71436 | +*/ |
| 71437 | +SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ |
| 71438 | + int i, n; |
| 71439 | + if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; |
| 71440 | + n = sqlite3Strlen30(zOptName); |
| 71441 | + |
| 71442 | + /* Since ArraySize(azCompileOpt) is normally in single digits, a |
| 71443 | + ** linear search is adequate. No need for a binary search. */ |
| 71444 | + for(i=0; i<ArraySize(azCompileOpt); i++){ |
| 71445 | + if( (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0) |
| 71446 | + && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1; |
| 71447 | + } |
| 71448 | + return 0; |
| 71449 | +} |
| 71450 | + |
| 71451 | +/* |
| 71452 | +** Return the N-th compile-time option string. If N is out of range, |
| 71453 | +** return a NULL pointer. |
| 71454 | +*/ |
| 71455 | +SQLITE_API const char *sqlite3_compileoption_get(int N){ |
| 71456 | + if( N>=0 && N<ArraySize(azCompileOpt) ){ |
| 71457 | + return azCompileOpt[N]; |
| 71458 | + } |
| 71459 | + return 0; |
| 71460 | +} |
| 71461 | + |
| 71462 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 71463 | + |
| 71464 | +/************** End of ctime.c ***********************************************/ |
| 70344 | 71465 | /************** Begin file delete.c ******************************************/ |
| 70345 | 71466 | /* |
| 70346 | 71467 | ** 2001 September 15 |
| 70347 | 71468 | ** |
| 70348 | 71469 | ** The author disclaims copyright to this source code. In place of |
| | @@ -71247,18 +72368,28 @@ |
| 71247 | 72368 | if( n>30 ) n = 30; |
| 71248 | 72369 | if( n<0 ) n = 0; |
| 71249 | 72370 | } |
| 71250 | 72371 | if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
| 71251 | 72372 | r = sqlite3_value_double(argv[0]); |
| 71252 | | - zBuf = sqlite3_mprintf("%.*f",n,r); |
| 71253 | | - if( zBuf==0 ){ |
| 71254 | | - sqlite3_result_error_nomem(context); |
| 72373 | + /* If Y==0 and X will fit in a 64-bit int, |
| 72374 | + ** handle the rounding directly, |
| 72375 | + ** otherwise use printf. |
| 72376 | + */ |
| 72377 | + if( n==0 && r>=0 && r<LARGEST_INT64-1 ){ |
| 72378 | + r = (double)((sqlite_int64)(r+0.5)); |
| 72379 | + }else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){ |
| 72380 | + r = -(double)((sqlite_int64)((-r)+0.5)); |
| 71255 | 72381 | }else{ |
| 72382 | + zBuf = sqlite3_mprintf("%.*f",n,r); |
| 72383 | + if( zBuf==0 ){ |
| 72384 | + sqlite3_result_error_nomem(context); |
| 72385 | + return; |
| 72386 | + } |
| 71256 | 72387 | sqlite3AtoF(zBuf, &r); |
| 71257 | 72388 | sqlite3_free(zBuf); |
| 71258 | | - sqlite3_result_double(context, r); |
| 71259 | 72389 | } |
| 72390 | + sqlite3_result_double(context, r); |
| 71260 | 72391 | } |
| 71261 | 72392 | #endif |
| 71262 | 72393 | |
| 71263 | 72394 | /* |
| 71264 | 72395 | ** Allocate nByte bytes of space using sqlite3_malloc(). If the |
| | @@ -71416,16 +72547,22 @@ |
| 71416 | 72547 | int NotUsed, |
| 71417 | 72548 | sqlite3_value **NotUsed2 |
| 71418 | 72549 | ){ |
| 71419 | 72550 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 71420 | 72551 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 72552 | + /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a |
| 72553 | + ** wrapper around the sqlite3_last_insert_rowid() C/C++ interface |
| 72554 | + ** function. */ |
| 71421 | 72555 | sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); |
| 71422 | 72556 | } |
| 71423 | 72557 | |
| 71424 | 72558 | /* |
| 71425 | | -** Implementation of the changes() SQL function. The return value is the |
| 71426 | | -** same as the sqlite3_changes() API function. |
| 72559 | +** Implementation of the changes() SQL function. |
| 72560 | +** |
| 72561 | +** IMP: R-62073-11209 The changes() SQL function is a wrapper |
| 72562 | +** around the sqlite3_changes() C/C++ function and hence follows the same |
| 72563 | +** rules for counting changes. |
| 71427 | 72564 | */ |
| 71428 | 72565 | static void changes( |
| 71429 | 72566 | sqlite3_context *context, |
| 71430 | 72567 | int NotUsed, |
| 71431 | 72568 | sqlite3_value **NotUsed2 |
| | @@ -71444,10 +72581,12 @@ |
| 71444 | 72581 | int NotUsed, |
| 71445 | 72582 | sqlite3_value **NotUsed2 |
| 71446 | 72583 | ){ |
| 71447 | 72584 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 71448 | 72585 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 72586 | + /* IMP: R-52756-41993 This function is a wrapper around the |
| 72587 | + ** sqlite3_total_changes() C/C++ interface. */ |
| 71449 | 72588 | sqlite3_result_int(context, sqlite3_total_changes(db)); |
| 71450 | 72589 | } |
| 71451 | 72590 | |
| 71452 | 72591 | /* |
| 71453 | 72592 | ** A structure defining how to do GLOB-style comparisons. |
| | @@ -71711,11 +72850,13 @@ |
| 71711 | 72850 | sqlite3_context *context, |
| 71712 | 72851 | int NotUsed, |
| 71713 | 72852 | sqlite3_value **NotUsed2 |
| 71714 | 72853 | ){ |
| 71715 | 72854 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 71716 | | - sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC); |
| 72855 | + /* IMP: R-48699-48617 This function is an SQL wrapper around the |
| 72856 | + ** sqlite3_libversion() C-interface. */ |
| 72857 | + sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC); |
| 71717 | 72858 | } |
| 71718 | 72859 | |
| 71719 | 72860 | /* |
| 71720 | 72861 | ** Implementation of the sqlite_source_id() function. The result is a string |
| 71721 | 72862 | ** that identifies the particular version of the source code used to build |
| | @@ -71725,13 +72866,58 @@ |
| 71725 | 72866 | sqlite3_context *context, |
| 71726 | 72867 | int NotUsed, |
| 71727 | 72868 | sqlite3_value **NotUsed2 |
| 71728 | 72869 | ){ |
| 71729 | 72870 | UNUSED_PARAMETER2(NotUsed, NotUsed2); |
| 71730 | | - sqlite3_result_text(context, SQLITE_SOURCE_ID, -1, SQLITE_STATIC); |
| 72871 | + /* IMP: R-24470-31136 This function is an SQL wrapper around the |
| 72872 | + ** sqlite3_sourceid() C interface. */ |
| 72873 | + sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC); |
| 71731 | 72874 | } |
| 71732 | 72875 | |
| 72876 | +/* |
| 72877 | +** Implementation of the sqlite_compileoption_used() function. |
| 72878 | +** The result is an integer that identifies if the compiler option |
| 72879 | +** was used to build SQLite. |
| 72880 | +*/ |
| 72881 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 72882 | +static void compileoptionusedFunc( |
| 72883 | + sqlite3_context *context, |
| 72884 | + int argc, |
| 72885 | + sqlite3_value **argv |
| 72886 | +){ |
| 72887 | + const char *zOptName; |
| 72888 | + assert( argc==1 ); |
| 72889 | + UNUSED_PARAMETER(argc); |
| 72890 | + /* IMP: R-xxxx This function is an SQL wrapper around the |
| 72891 | + ** sqlite3_compileoption_used() C interface. */ |
| 72892 | + if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){ |
| 72893 | + sqlite3_result_int(context, sqlite3_compileoption_used(zOptName)); |
| 72894 | + } |
| 72895 | +} |
| 72896 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 72897 | + |
| 72898 | +/* |
| 72899 | +** Implementation of the sqlite_compileoption_get() function. |
| 72900 | +** The result is a string that identifies the compiler options |
| 72901 | +** used to build SQLite. |
| 72902 | +*/ |
| 72903 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 72904 | +static void compileoptiongetFunc( |
| 72905 | + sqlite3_context *context, |
| 72906 | + int argc, |
| 72907 | + sqlite3_value **argv |
| 72908 | +){ |
| 72909 | + int n; |
| 72910 | + assert( argc==1 ); |
| 72911 | + UNUSED_PARAMETER(argc); |
| 72912 | + /* IMP: R-xxxx This function is an SQL wrapper around the |
| 72913 | + ** sqlite3_compileoption_get() C interface. */ |
| 72914 | + n = sqlite3_value_int(argv[0]); |
| 72915 | + sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC); |
| 72916 | +} |
| 72917 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 72918 | + |
| 71733 | 72919 | /* Array for converting from half-bytes (nybbles) into ASCII hex |
| 71734 | 72920 | ** digits. */ |
| 71735 | 72921 | static const char hexdigits[] = { |
| 71736 | 72922 | '0', '1', '2', '3', '4', '5', '6', '7', |
| 71737 | 72923 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' |
| | @@ -71854,11 +73040,11 @@ |
| 71854 | 73040 | testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
| 71855 | 73041 | testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); |
| 71856 | 73042 | if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 71857 | 73043 | sqlite3_result_error_toobig(context); |
| 71858 | 73044 | }else{ |
| 71859 | | - sqlite3_result_zeroblob(context, (int)n); |
| 73045 | + sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */ |
| 71860 | 73046 | } |
| 71861 | 73047 | } |
| 71862 | 73048 | |
| 71863 | 73049 | /* |
| 71864 | 73050 | ** The replace() function. Three arguments are all strings: call |
| | @@ -72459,10 +73645,14 @@ |
| 72459 | 73645 | FUNCTION(random, 0, 0, 0, randomFunc ), |
| 72460 | 73646 | FUNCTION(randomblob, 1, 0, 0, randomBlob ), |
| 72461 | 73647 | FUNCTION(nullif, 2, 0, 1, nullifFunc ), |
| 72462 | 73648 | FUNCTION(sqlite_version, 0, 0, 0, versionFunc ), |
| 72463 | 73649 | FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), |
| 73650 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 73651 | + FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ), |
| 73652 | + FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ), |
| 73653 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 72464 | 73654 | FUNCTION(quote, 1, 0, 0, quoteFunc ), |
| 72465 | 73655 | FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), |
| 72466 | 73656 | FUNCTION(changes, 0, 0, 0, changes ), |
| 72467 | 73657 | FUNCTION(total_changes, 0, 0, 0, total_changes ), |
| 72468 | 73658 | FUNCTION(replace, 3, 0, 0, replaceFunc ), |
| | @@ -74958,23 +76148,37 @@ |
| 74958 | 76148 | ** recursive-triggers flag is set, call GenerateRowDelete() to |
| 74959 | 76149 | ** remove the conflicting row from the the table. This will fire |
| 74960 | 76150 | ** the triggers and remove both the table and index b-tree entries. |
| 74961 | 76151 | ** |
| 74962 | 76152 | ** 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. */ |
| 76153 | + ** flag is not set, but the table has one or more indexes, call |
| 76154 | + ** GenerateRowIndexDelete(). This removes the index b-tree entries |
| 76155 | + ** only. The table b-tree entry will be replaced by the new entry |
| 76156 | + ** when it is inserted. |
| 76157 | + ** |
| 76158 | + ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called, |
| 76159 | + ** also invoke MultiWrite() to indicate that this VDBE may require |
| 76160 | + ** statement rollback (if the statement is aborted after the delete |
| 76161 | + ** takes place). Earlier versions called sqlite3MultiWrite() regardless, |
| 76162 | + ** but being more selective here allows statements like: |
| 76163 | + ** |
| 76164 | + ** REPLACE INTO t(rowid) VALUES($newrowid) |
| 76165 | + ** |
| 76166 | + ** to run without a statement journal if there are no indexes on the |
| 76167 | + ** table. |
| 76168 | + */ |
| 74966 | 76169 | Trigger *pTrigger = 0; |
| 74967 | 76170 | if( pParse->db->flags&SQLITE_RecTriggers ){ |
| 74968 | 76171 | pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
| 74969 | 76172 | } |
| 74970 | | - sqlite3MultiWrite(pParse); |
| 74971 | 76173 | if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ |
| 76174 | + sqlite3MultiWrite(pParse); |
| 74972 | 76175 | sqlite3GenerateRowDelete( |
| 74973 | 76176 | pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace |
| 74974 | 76177 | ); |
| 74975 | | - }else{ |
| 76178 | + }else if( pTab->pIndex ){ |
| 76179 | + sqlite3MultiWrite(pParse); |
| 74976 | 76180 | sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); |
| 74977 | 76181 | } |
| 74978 | 76182 | seenReplace = 1; |
| 74979 | 76183 | break; |
| 74980 | 76184 | } |
| | @@ -75412,11 +76616,11 @@ |
| 75412 | 76616 | if( pSrcIdx==0 ){ |
| 75413 | 76617 | return 0; /* pDestIdx has no corresponding index in pSrc */ |
| 75414 | 76618 | } |
| 75415 | 76619 | } |
| 75416 | 76620 | #ifndef SQLITE_OMIT_CHECK |
| 75417 | | - if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ |
| 76621 | + if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ |
| 75418 | 76622 | return 0; /* Tables have different CHECK constraints. Ticket #2252 */ |
| 75419 | 76623 | } |
| 75420 | 76624 | #endif |
| 75421 | 76625 | |
| 75422 | 76626 | /* If we get this far, it means either: |
| | @@ -75555,10 +76759,11 @@ |
| 75555 | 76759 | sqlite3_stmt *pStmt = 0; /* The current SQL statement */ |
| 75556 | 76760 | char **azCols = 0; /* Names of result columns */ |
| 75557 | 76761 | int nRetry = 0; /* Number of retry attempts */ |
| 75558 | 76762 | int callbackIsInit; /* True if callback data is initialized */ |
| 75559 | 76763 | |
| 76764 | + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
| 75560 | 76765 | if( zSql==0 ) zSql = ""; |
| 75561 | 76766 | |
| 75562 | 76767 | sqlite3_mutex_enter(db->mutex); |
| 75563 | 76768 | sqlite3Error(db, SQLITE_OK, 0); |
| 75564 | 76769 | while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){ |
| | @@ -76936,10 +78141,11 @@ |
| 76936 | 78141 | int iDb; /* Database index for <database> */ |
| 76937 | 78142 | sqlite3 *db = pParse->db; |
| 76938 | 78143 | Db *pDb; |
| 76939 | 78144 | Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); |
| 76940 | 78145 | if( v==0 ) return; |
| 78146 | + sqlite3VdbeRunOnlyOnce(v); |
| 76941 | 78147 | pParse->nMem = 2; |
| 76942 | 78148 | |
| 76943 | 78149 | /* Interpret the [database.] part of the pragma statement. iDb is the |
| 76944 | 78150 | ** index of the database this pragma is being applied to in db.aDb[]. */ |
| 76945 | 78151 | iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); |
| | @@ -77067,10 +78273,35 @@ |
| 77067 | 78273 | newMax = sqlite3BtreeMaxPageCount(pBt, newMax); |
| 77068 | 78274 | } |
| 77069 | 78275 | returnSingleInt(pParse, "max_page_count", newMax); |
| 77070 | 78276 | }else |
| 77071 | 78277 | |
| 78278 | + /* |
| 78279 | + ** PRAGMA [database.]secure_delete |
| 78280 | + ** PRAGMA [database.]secure_delete=ON/OFF |
| 78281 | + ** |
| 78282 | + ** The first form reports the current setting for the |
| 78283 | + ** secure_delete flag. The second form changes the secure_delete |
| 78284 | + ** flag setting and reports thenew value. |
| 78285 | + */ |
| 78286 | + if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){ |
| 78287 | + Btree *pBt = pDb->pBt; |
| 78288 | + int b = -1; |
| 78289 | + assert( pBt!=0 ); |
| 78290 | + if( zRight ){ |
| 78291 | + b = getBoolean(zRight); |
| 78292 | + } |
| 78293 | + if( pId2->n==0 && b>=0 ){ |
| 78294 | + int ii; |
| 78295 | + for(ii=0; ii<db->nDb; ii++){ |
| 78296 | + sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b); |
| 78297 | + } |
| 78298 | + } |
| 78299 | + b = sqlite3BtreeSecureDelete(pBt, b); |
| 78300 | + returnSingleInt(pParse, "secure_delete", b); |
| 78301 | + }else |
| 78302 | + |
| 77072 | 78303 | /* |
| 77073 | 78304 | ** PRAGMA [database.]page_count |
| 77074 | 78305 | ** |
| 77075 | 78306 | ** Return the number of pages in the specified database. |
| 77076 | 78307 | */ |
| | @@ -77985,10 +79216,30 @@ |
| 77985 | 79216 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); |
| 77986 | 79217 | } |
| 77987 | 79218 | }else |
| 77988 | 79219 | #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ |
| 77989 | 79220 | |
| 79221 | +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
| 79222 | + /* |
| 79223 | + ** PRAGMA compile_options |
| 79224 | + ** |
| 79225 | + ** Return the names of all compile-time options used in this build, |
| 79226 | + ** one option per row. |
| 79227 | + */ |
| 79228 | + if( sqlite3StrICmp(zLeft, "compile_options")==0 ){ |
| 79229 | + int i = 0; |
| 79230 | + const char *zOpt; |
| 79231 | + sqlite3VdbeSetNumCols(v, 1); |
| 79232 | + pParse->nMem = 1; |
| 79233 | + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC); |
| 79234 | + while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ |
| 79235 | + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0); |
| 79236 | + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
| 79237 | + } |
| 79238 | + }else |
| 79239 | +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 79240 | + |
| 77990 | 79241 | #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
| 77991 | 79242 | /* |
| 77992 | 79243 | ** Report the current state of file logs for all databases |
| 77993 | 79244 | */ |
| 77994 | 79245 | if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ |
| | @@ -78019,11 +79270,11 @@ |
| 78019 | 79270 | } |
| 78020 | 79271 | |
| 78021 | 79272 | }else |
| 78022 | 79273 | #endif |
| 78023 | 79274 | |
| 78024 | | -#if SQLITE_HAS_CODEC |
| 79275 | +#ifdef SQLITE_HAS_CODEC |
| 78025 | 79276 | if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){ |
| 78026 | 79277 | sqlite3_key(db, zRight, sqlite3Strlen30(zRight)); |
| 78027 | 79278 | }else |
| 78028 | 79279 | if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){ |
| 78029 | 79280 | sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight)); |
| | @@ -78042,36 +79293,28 @@ |
| 78042 | 79293 | }else{ |
| 78043 | 79294 | sqlite3_rekey(db, zKey, i/2); |
| 78044 | 79295 | } |
| 78045 | 79296 | }else |
| 78046 | 79297 | #endif |
| 78047 | | -#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD) |
| 79298 | +#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) |
| 78048 | 79299 | if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){ |
| 78049 | | -#if SQLITE_HAS_CODEC |
| 79300 | +#ifdef SQLITE_HAS_CODEC |
| 78050 | 79301 | if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ |
| 78051 | | - extern void sqlite3_activate_see(const char*); |
| 78052 | 79302 | sqlite3_activate_see(&zRight[4]); |
| 78053 | 79303 | } |
| 78054 | 79304 | #endif |
| 78055 | 79305 | #ifdef SQLITE_ENABLE_CEROD |
| 78056 | 79306 | if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ |
| 78057 | | - extern void sqlite3_activate_cerod(const char*); |
| 78058 | 79307 | sqlite3_activate_cerod(&zRight[6]); |
| 78059 | 79308 | } |
| 78060 | 79309 | #endif |
| 78061 | 79310 | }else |
| 78062 | 79311 | #endif |
| 78063 | 79312 | |
| 78064 | 79313 | |
| 78065 | 79314 | {/* Empty ELSE clause */} |
| 78066 | 79315 | |
| 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 | 79316 | /* |
| 78074 | 79317 | ** Reset the safety level, in case the fullfsync flag or synchronous |
| 78075 | 79318 | ** setting changed. |
| 78076 | 79319 | */ |
| 78077 | 79320 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| | @@ -78280,13 +79523,11 @@ |
| 78280 | 79523 | azArg[3] = 0; |
| 78281 | 79524 | initData.db = db; |
| 78282 | 79525 | initData.iDb = iDb; |
| 78283 | 79526 | initData.rc = SQLITE_OK; |
| 78284 | 79527 | initData.pzErrMsg = pzErrMsg; |
| 78285 | | - (void)sqlite3SafetyOff(db); |
| 78286 | 79528 | sqlite3InitCallback(&initData, 3, (char **)azArg, 0); |
| 78287 | | - (void)sqlite3SafetyOn(db); |
| 78288 | 79529 | if( initData.rc ){ |
| 78289 | 79530 | rc = initData.rc; |
| 78290 | 79531 | goto error_out; |
| 78291 | 79532 | } |
| 78292 | 79533 | pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); |
| | @@ -78403,13 +79644,12 @@ |
| 78403 | 79644 | */ |
| 78404 | 79645 | assert( db->init.busy ); |
| 78405 | 79646 | { |
| 78406 | 79647 | char *zSql; |
| 78407 | 79648 | zSql = sqlite3MPrintf(db, |
| 78408 | | - "SELECT name, rootpage, sql FROM '%q'.%s", |
| 79649 | + "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid", |
| 78409 | 79650 | db->aDb[iDb].zName, zMasterName); |
| 78410 | | - (void)sqlite3SafetyOff(db); |
| 78411 | 79651 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 78412 | 79652 | { |
| 78413 | 79653 | int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); |
| 78414 | 79654 | xAuth = db->xAuth; |
| 78415 | 79655 | db->xAuth = 0; |
| | @@ -78418,11 +79658,10 @@ |
| 78418 | 79658 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 78419 | 79659 | db->xAuth = xAuth; |
| 78420 | 79660 | } |
| 78421 | 79661 | #endif |
| 78422 | 79662 | if( rc==SQLITE_OK ) rc = initData.rc; |
| 78423 | | - (void)sqlite3SafetyOn(db); |
| 78424 | 79663 | sqlite3DbFree(db, zSql); |
| 78425 | 79664 | #ifndef SQLITE_OMIT_ANALYZE |
| 78426 | 79665 | if( rc==SQLITE_OK ){ |
| 78427 | 79666 | sqlite3AnalysisLoad(db, iDb); |
| 78428 | 79667 | } |
| | @@ -78627,15 +79866,10 @@ |
| 78627 | 79866 | if( pParse==0 ){ |
| 78628 | 79867 | rc = SQLITE_NOMEM; |
| 78629 | 79868 | goto end_prepare; |
| 78630 | 79869 | } |
| 78631 | 79870 | pParse->pReprepare = pReprepare; |
| 78632 | | - |
| 78633 | | - if( sqlite3SafetyOn(db) ){ |
| 78634 | | - rc = SQLITE_MISUSE; |
| 78635 | | - goto end_prepare; |
| 78636 | | - } |
| 78637 | 79871 | assert( ppStmt && *ppStmt==0 ); |
| 78638 | 79872 | assert( !db->mallocFailed ); |
| 78639 | 79873 | assert( sqlite3_mutex_held(db->mutex) ); |
| 78640 | 79874 | |
| 78641 | 79875 | /* Check to verify that it is possible to get a read lock on all |
| | @@ -78667,11 +79901,10 @@ |
| 78667 | 79901 | assert( sqlite3BtreeHoldsMutex(pBt) ); |
| 78668 | 79902 | rc = sqlite3BtreeSchemaLocked(pBt); |
| 78669 | 79903 | if( rc ){ |
| 78670 | 79904 | const char *zDb = db->aDb[i].zName; |
| 78671 | 79905 | sqlite3Error(db, rc, "database schema is locked: %s", zDb); |
| 78672 | | - (void)sqlite3SafetyOff(db); |
| 78673 | 79906 | testcase( db->flags & SQLITE_ReadUncommitted ); |
| 78674 | 79907 | goto end_prepare; |
| 78675 | 79908 | } |
| 78676 | 79909 | } |
| 78677 | 79910 | } |
| | @@ -78684,11 +79917,10 @@ |
| 78684 | 79917 | int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 78685 | 79918 | testcase( nBytes==mxLen ); |
| 78686 | 79919 | testcase( nBytes==mxLen+1 ); |
| 78687 | 79920 | if( nBytes>mxLen ){ |
| 78688 | 79921 | sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); |
| 78689 | | - (void)sqlite3SafetyOff(db); |
| 78690 | 79922 | rc = sqlite3ApiExit(db, SQLITE_TOOBIG); |
| 78691 | 79923 | goto end_prepare; |
| 78692 | 79924 | } |
| 78693 | 79925 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 78694 | 79926 | if( zSqlCopy ){ |
| | @@ -78741,14 +79973,10 @@ |
| 78741 | 79973 | azColName[i], SQLITE_STATIC); |
| 78742 | 79974 | } |
| 78743 | 79975 | } |
| 78744 | 79976 | #endif |
| 78745 | 79977 | |
| 78746 | | - if( sqlite3SafetyOff(db) ){ |
| 78747 | | - rc = SQLITE_MISUSE; |
| 78748 | | - } |
| 78749 | | - |
| 78750 | 79978 | assert( db->init.busy==0 || saveSqlFlag==0 ); |
| 78751 | 79979 | if( db->init.busy==0 ){ |
| 78752 | 79980 | Vdbe *pVdbe = pParse->pVdbe; |
| 78753 | 79981 | sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); |
| 78754 | 79982 | } |
| | @@ -78792,11 +80020,11 @@ |
| 78792 | 80020 | ){ |
| 78793 | 80021 | int rc; |
| 78794 | 80022 | assert( ppStmt!=0 ); |
| 78795 | 80023 | *ppStmt = 0; |
| 78796 | 80024 | if( !sqlite3SafetyCheckOk(db) ){ |
| 78797 | | - return SQLITE_MISUSE; |
| 80025 | + return SQLITE_MISUSE_BKPT; |
| 78798 | 80026 | } |
| 78799 | 80027 | sqlite3_mutex_enter(db->mutex); |
| 78800 | 80028 | sqlite3BtreeEnterAll(db); |
| 78801 | 80029 | rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); |
| 78802 | 80030 | if( rc==SQLITE_SCHEMA ){ |
| | @@ -78831,11 +80059,11 @@ |
| 78831 | 80059 | if( rc ){ |
| 78832 | 80060 | if( rc==SQLITE_NOMEM ){ |
| 78833 | 80061 | db->mallocFailed = 1; |
| 78834 | 80062 | } |
| 78835 | 80063 | assert( pNew==0 ); |
| 78836 | | - return (rc==SQLITE_LOCKED) ? SQLITE_LOCKED : SQLITE_SCHEMA; |
| 80064 | + return rc; |
| 78837 | 80065 | }else{ |
| 78838 | 80066 | assert( pNew!=0 ); |
| 78839 | 80067 | } |
| 78840 | 80068 | sqlite3VdbeSwap((Vdbe*)pNew, p); |
| 78841 | 80069 | sqlite3TransferBindings(pNew, (sqlite3_stmt*)p); |
| | @@ -78900,11 +80128,11 @@ |
| 78900 | 80128 | int rc = SQLITE_OK; |
| 78901 | 80129 | |
| 78902 | 80130 | assert( ppStmt ); |
| 78903 | 80131 | *ppStmt = 0; |
| 78904 | 80132 | if( !sqlite3SafetyCheckOk(db) ){ |
| 78905 | | - return SQLITE_MISUSE; |
| 80133 | + return SQLITE_MISUSE_BKPT; |
| 78906 | 80134 | } |
| 78907 | 80135 | sqlite3_mutex_enter(db->mutex); |
| 78908 | 80136 | zSql8 = sqlite3Utf16to8(db, zSql, nBytes); |
| 78909 | 80137 | if( zSql8 ){ |
| 78910 | 80138 | rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); |
| | @@ -82288,22 +83516,23 @@ |
| 82288 | 83516 | int i; |
| 82289 | 83517 | SrcList *pTabList; |
| 82290 | 83518 | struct SrcList_item *pFrom; |
| 82291 | 83519 | |
| 82292 | 83520 | 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); |
| 83521 | + if( (p->selFlags & SF_HasTypeInfo)==0 ){ |
| 83522 | + p->selFlags |= SF_HasTypeInfo; |
| 83523 | + pParse = pWalker->pParse; |
| 83524 | + pTabList = p->pSrc; |
| 83525 | + for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 83526 | + Table *pTab = pFrom->pTab; |
| 83527 | + if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
| 83528 | + /* A sub-query in the FROM clause of a SELECT */ |
| 83529 | + Select *pSel = pFrom->pSelect; |
| 83530 | + assert( pSel ); |
| 83531 | + while( pSel->pPrior ) pSel = pSel->pPrior; |
| 83532 | + selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel); |
| 83533 | + } |
| 82305 | 83534 | } |
| 82306 | 83535 | } |
| 82307 | 83536 | return WRC_Continue; |
| 82308 | 83537 | } |
| 82309 | 83538 | #endif |
| | @@ -83571,11 +84800,12 @@ |
| 83571 | 84800 | */ |
| 83572 | 84801 | if( !pTableName || db->mallocFailed ){ |
| 83573 | 84802 | goto trigger_cleanup; |
| 83574 | 84803 | } |
| 83575 | 84804 | pTab = sqlite3SrcListLookup(pParse, pTableName); |
| 83576 | | - if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ |
| 84805 | + if( db->init.busy==0 && pName2->n==0 && pTab |
| 84806 | + && pTab->pSchema==db->aDb[1].pSchema ){ |
| 83577 | 84807 | iDb = 1; |
| 83578 | 84808 | } |
| 83579 | 84809 | |
| 83580 | 84810 | /* Ensure the table name matches database name and that the table exists */ |
| 83581 | 84811 | if( db->mallocFailed ) goto trigger_cleanup; |
| | @@ -83699,16 +84929,16 @@ |
| 83699 | 84929 | SQLITE_PRIVATE void sqlite3FinishTrigger( |
| 83700 | 84930 | Parse *pParse, /* Parser context */ |
| 83701 | 84931 | TriggerStep *pStepList, /* The triggered program */ |
| 83702 | 84932 | Token *pAll /* Token that describes the complete CREATE TRIGGER */ |
| 83703 | 84933 | ){ |
| 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 */ |
| 84934 | + Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ |
| 84935 | + char *zName; /* Name of trigger */ |
| 84936 | + sqlite3 *db = pParse->db; /* The database */ |
| 84937 | + DbFixer sFix; /* Fixer object */ |
| 84938 | + int iDb; /* Database containing the trigger */ |
| 84939 | + Token nameToken; /* Trigger name for error reporting */ |
| 83710 | 84940 | |
| 83711 | 84941 | pTrig = pParse->pNewTrigger; |
| 83712 | 84942 | pParse->pNewTrigger = 0; |
| 83713 | 84943 | if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; |
| 83714 | 84944 | zName = pTrig->zName; |
| | @@ -83723,11 +84953,11 @@ |
| 83723 | 84953 | if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) |
| 83724 | 84954 | && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ |
| 83725 | 84955 | goto triggerfinish_cleanup; |
| 83726 | 84956 | } |
| 83727 | 84957 | |
| 83728 | | - /* if we are not initializing, and this trigger is not on a TEMP table, |
| 84958 | + /* if we are not initializing, |
| 83729 | 84959 | ** build the sqlite_master entry |
| 83730 | 84960 | */ |
| 83731 | 84961 | if( !db->init.busy ){ |
| 83732 | 84962 | Vdbe *v; |
| 83733 | 84963 | char *z; |
| | @@ -85222,47 +86452,61 @@ |
| 85222 | 86452 | ** Most of the code in this file may be omitted by defining the |
| 85223 | 86453 | ** SQLITE_OMIT_VACUUM macro. |
| 85224 | 86454 | */ |
| 85225 | 86455 | |
| 85226 | 86456 | #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) |
| 86457 | +/* |
| 86458 | +** Finalize a prepared statement. If there was an error, store the |
| 86459 | +** text of the error message in *pzErrMsg. Return the result code. |
| 86460 | +*/ |
| 86461 | +static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){ |
| 86462 | + int rc; |
| 86463 | + rc = sqlite3VdbeFinalize((Vdbe*)pStmt); |
| 86464 | + if( rc ){ |
| 86465 | + sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); |
| 86466 | + } |
| 86467 | + return rc; |
| 86468 | +} |
| 86469 | + |
| 85227 | 86470 | /* |
| 85228 | 86471 | ** Execute zSql on database db. Return an error code. |
| 85229 | 86472 | */ |
| 85230 | | -static int execSql(sqlite3 *db, const char *zSql){ |
| 86473 | +static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ |
| 85231 | 86474 | sqlite3_stmt *pStmt; |
| 85232 | 86475 | VVA_ONLY( int rc; ) |
| 85233 | 86476 | if( !zSql ){ |
| 85234 | 86477 | return SQLITE_NOMEM; |
| 85235 | 86478 | } |
| 85236 | 86479 | if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ |
| 86480 | + sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); |
| 85237 | 86481 | return sqlite3_errcode(db); |
| 85238 | 86482 | } |
| 85239 | 86483 | VVA_ONLY( rc = ) sqlite3_step(pStmt); |
| 85240 | 86484 | assert( rc!=SQLITE_ROW ); |
| 85241 | | - return sqlite3_finalize(pStmt); |
| 86485 | + return vacuumFinalize(db, pStmt, pzErrMsg); |
| 85242 | 86486 | } |
| 85243 | 86487 | |
| 85244 | 86488 | /* |
| 85245 | 86489 | ** Execute zSql on database db. The statement returns exactly |
| 85246 | 86490 | ** one column. Execute this as SQL on the same database. |
| 85247 | 86491 | */ |
| 85248 | | -static int execExecSql(sqlite3 *db, const char *zSql){ |
| 86492 | +static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ |
| 85249 | 86493 | sqlite3_stmt *pStmt; |
| 85250 | 86494 | int rc; |
| 85251 | 86495 | |
| 85252 | 86496 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| 85253 | 86497 | if( rc!=SQLITE_OK ) return rc; |
| 85254 | 86498 | |
| 85255 | 86499 | while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 85256 | | - rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0)); |
| 86500 | + rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0)); |
| 85257 | 86501 | if( rc!=SQLITE_OK ){ |
| 85258 | | - sqlite3_finalize(pStmt); |
| 86502 | + vacuumFinalize(db, pStmt, pzErrMsg); |
| 85259 | 86503 | return rc; |
| 85260 | 86504 | } |
| 85261 | 86505 | } |
| 85262 | 86506 | |
| 85263 | | - return sqlite3_finalize(pStmt); |
| 86507 | + return vacuumFinalize(db, pStmt, pzErrMsg); |
| 85264 | 86508 | } |
| 85265 | 86509 | |
| 85266 | 86510 | /* |
| 85267 | 86511 | ** The non-standard VACUUM command is used to clean up the database, |
| 85268 | 86512 | ** collapse free space, etc. It is modelled after the VACUUM command |
| | @@ -85308,11 +86552,11 @@ |
| 85308 | 86552 | saved_flags = db->flags; |
| 85309 | 86553 | saved_nChange = db->nChange; |
| 85310 | 86554 | saved_nTotalChange = db->nTotalChange; |
| 85311 | 86555 | saved_xTrace = db->xTrace; |
| 85312 | 86556 | db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; |
| 85313 | | - db->flags &= ~SQLITE_ForeignKeys; |
| 86557 | + db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder); |
| 85314 | 86558 | db->xTrace = 0; |
| 85315 | 86559 | |
| 85316 | 86560 | pMain = db->aDb[0].pBt; |
| 85317 | 86561 | isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); |
| 85318 | 86562 | |
| | @@ -85328,12 +86572,16 @@ |
| 85328 | 86572 | ** actually occurs when doing a vacuum since the vacuum_db is initially |
| 85329 | 86573 | ** empty. Only the journal header is written. Apparently it takes more |
| 85330 | 86574 | ** time to parse and run the PRAGMA to turn journalling off than it does |
| 85331 | 86575 | ** to write the journal header file. |
| 85332 | 86576 | */ |
| 85333 | | - zSql = "ATTACH '' AS vacuum_db;"; |
| 85334 | | - rc = execSql(db, zSql); |
| 86577 | + if( sqlite3TempInMemory(db) ){ |
| 86578 | + zSql = "ATTACH ':memory:' AS vacuum_db;"; |
| 86579 | + }else{ |
| 86580 | + zSql = "ATTACH '' AS vacuum_db;"; |
| 86581 | + } |
| 86582 | + rc = execSql(db, pzErrMsg, zSql); |
| 85335 | 86583 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85336 | 86584 | pDb = &db->aDb[db->nDb-1]; |
| 85337 | 86585 | assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); |
| 85338 | 86586 | pTemp = db->aDb[db->nDb-1].pBt; |
| 85339 | 86587 | |
| | @@ -85361,11 +86609,11 @@ |
| 85361 | 86609 | || NEVER(db->mallocFailed) |
| 85362 | 86610 | ){ |
| 85363 | 86611 | rc = SQLITE_NOMEM; |
| 85364 | 86612 | goto end_of_vacuum; |
| 85365 | 86613 | } |
| 85366 | | - rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); |
| 86614 | + rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); |
| 85367 | 86615 | if( rc!=SQLITE_OK ){ |
| 85368 | 86616 | goto end_of_vacuum; |
| 85369 | 86617 | } |
| 85370 | 86618 | |
| 85371 | 86619 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| | @@ -85372,53 +86620,52 @@ |
| 85372 | 86620 | sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : |
| 85373 | 86621 | sqlite3BtreeGetAutoVacuum(pMain)); |
| 85374 | 86622 | #endif |
| 85375 | 86623 | |
| 85376 | 86624 | /* Begin a transaction */ |
| 85377 | | - rc = execSql(db, "BEGIN EXCLUSIVE;"); |
| 86625 | + rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;"); |
| 85378 | 86626 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85379 | 86627 | |
| 85380 | 86628 | /* Query the schema of the main database. Create a mirror schema |
| 85381 | 86629 | ** in the temporary database. |
| 85382 | 86630 | */ |
| 85383 | | - rc = execExecSql(db, |
| 86631 | + rc = execExecSql(db, pzErrMsg, |
| 85384 | 86632 | "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " |
| 85385 | 86633 | " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" |
| 85386 | 86634 | " AND rootpage>0" |
| 85387 | 86635 | ); |
| 85388 | 86636 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85389 | | - rc = execExecSql(db, |
| 86637 | + rc = execExecSql(db, pzErrMsg, |
| 85390 | 86638 | "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)" |
| 85391 | 86639 | " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "); |
| 85392 | 86640 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85393 | | - rc = execExecSql(db, |
| 86641 | + rc = execExecSql(db, pzErrMsg, |
| 85394 | 86642 | "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " |
| 85395 | 86643 | " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); |
| 85396 | 86644 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85397 | 86645 | |
| 85398 | 86646 | /* Loop through the tables in the main database. For each, do |
| 85399 | 86647 | ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy |
| 85400 | 86648 | ** the contents to the temporary database. |
| 85401 | 86649 | */ |
| 85402 | | - rc = execExecSql(db, |
| 86650 | + rc = execExecSql(db, pzErrMsg, |
| 85403 | 86651 | "SELECT 'INSERT INTO vacuum_db.' || quote(name) " |
| 85404 | 86652 | "|| ' SELECT * FROM main.' || quote(name) || ';'" |
| 85405 | 86653 | "FROM main.sqlite_master " |
| 85406 | 86654 | "WHERE type = 'table' AND name!='sqlite_sequence' " |
| 85407 | 86655 | " AND rootpage>0" |
| 85408 | | - |
| 85409 | 86656 | ); |
| 85410 | 86657 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85411 | 86658 | |
| 85412 | 86659 | /* Copy over the sequence table |
| 85413 | 86660 | */ |
| 85414 | | - rc = execExecSql(db, |
| 86661 | + rc = execExecSql(db, pzErrMsg, |
| 85415 | 86662 | "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " |
| 85416 | 86663 | "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " |
| 85417 | 86664 | ); |
| 85418 | 86665 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 85419 | | - rc = execExecSql(db, |
| 86666 | + rc = execExecSql(db, pzErrMsg, |
| 85420 | 86667 | "SELECT 'INSERT INTO vacuum_db.' || quote(name) " |
| 85421 | 86668 | "|| ' SELECT * FROM main.' || quote(name) || ';' " |
| 85422 | 86669 | "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';" |
| 85423 | 86670 | ); |
| 85424 | 86671 | if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| | @@ -85427,11 +86674,11 @@ |
| 85427 | 86674 | /* Copy the triggers, views, and virtual tables from the main database |
| 85428 | 86675 | ** over to the temporary database. None of these objects has any |
| 85429 | 86676 | ** associated storage, so all we have to do is copy their entries |
| 85430 | 86677 | ** from the SQLITE_MASTER table. |
| 85431 | 86678 | */ |
| 85432 | | - rc = execSql(db, |
| 86679 | + rc = execSql(db, pzErrMsg, |
| 85433 | 86680 | "INSERT INTO vacuum_db.sqlite_master " |
| 85434 | 86681 | " SELECT type, name, tbl_name, rootpage, sql" |
| 85435 | 86682 | " FROM main.sqlite_master" |
| 85436 | 86683 | " WHERE type='view' OR type='trigger'" |
| 85437 | 86684 | " OR (type='table' AND rootpage=0)" |
| | @@ -85639,20 +86886,11 @@ |
| 85639 | 86886 | |
| 85640 | 86887 | pVTab->nRef--; |
| 85641 | 86888 | if( pVTab->nRef==0 ){ |
| 85642 | 86889 | sqlite3_vtab *p = pVTab->pVtab; |
| 85643 | 86890 | 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 | | - } |
| 86891 | + p->pModule->xDisconnect(p); |
| 85654 | 86892 | } |
| 85655 | 86893 | sqlite3DbFree(db, pVTab); |
| 85656 | 86894 | } |
| 85657 | 86895 | } |
| 85658 | 86896 | |
| | @@ -85984,13 +87222,11 @@ |
| 85984 | 87222 | assert( !db->pVTab ); |
| 85985 | 87223 | assert( xConstruct ); |
| 85986 | 87224 | db->pVTab = pTab; |
| 85987 | 87225 | |
| 85988 | 87226 | /* Invoke the virtual table constructor */ |
| 85989 | | - (void)sqlite3SafetyOff(db); |
| 85990 | 87227 | rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
| 85991 | | - (void)sqlite3SafetyOn(db); |
| 85992 | 87228 | if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 85993 | 87229 | |
| 85994 | 87230 | if( SQLITE_OK!=rc ){ |
| 85995 | 87231 | if( zErr==0 ){ |
| 85996 | 87232 | *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
| | @@ -86174,11 +87410,11 @@ |
| 86174 | 87410 | sqlite3_mutex_enter(db->mutex); |
| 86175 | 87411 | pTab = db->pVTab; |
| 86176 | 87412 | if( !pTab ){ |
| 86177 | 87413 | sqlite3Error(db, SQLITE_MISUSE, 0); |
| 86178 | 87414 | sqlite3_mutex_leave(db->mutex); |
| 86179 | | - return SQLITE_MISUSE; |
| 87415 | + return SQLITE_MISUSE_BKPT; |
| 86180 | 87416 | } |
| 86181 | 87417 | assert( (pTab->tabFlags & TF_Virtual)!=0 ); |
| 86182 | 87418 | |
| 86183 | 87419 | pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
| 86184 | 87420 | if( pParse==0 ){ |
| | @@ -86233,14 +87469,12 @@ |
| 86233 | 87469 | |
| 86234 | 87470 | pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); |
| 86235 | 87471 | if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ |
| 86236 | 87472 | VTable *p = vtabDisconnectAll(db, pTab); |
| 86237 | 87473 | |
| 86238 | | - rc = sqlite3SafetyOff(db); |
| 86239 | 87474 | assert( rc==SQLITE_OK ); |
| 86240 | 87475 | rc = p->pMod->pModule->xDestroy(p->pVtab); |
| 86241 | | - (void)sqlite3SafetyOn(db); |
| 86242 | 87476 | |
| 86243 | 87477 | /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ |
| 86244 | 87478 | if( rc==SQLITE_OK ){ |
| 86245 | 87479 | assert( pTab->pVTable==p && p->pNext==0 ); |
| 86246 | 87480 | p->pVtab = 0; |
| | @@ -86288,14 +87522,12 @@ |
| 86288 | 87522 | ** sqlite3DbFree() containing an error message, if one is available. |
| 86289 | 87523 | */ |
| 86290 | 87524 | SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){ |
| 86291 | 87525 | int i; |
| 86292 | 87526 | int rc = SQLITE_OK; |
| 86293 | | - int rcsafety; |
| 86294 | 87527 | VTable **aVTrans = db->aVTrans; |
| 86295 | 87528 | |
| 86296 | | - rc = sqlite3SafetyOff(db); |
| 86297 | 87529 | db->aVTrans = 0; |
| 86298 | 87530 | for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){ |
| 86299 | 87531 | int (*x)(sqlite3_vtab *); |
| 86300 | 87532 | sqlite3_vtab *pVtab = aVTrans[i]->pVtab; |
| 86301 | 87533 | if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ |
| | @@ -86304,15 +87536,10 @@ |
| 86304 | 87536 | *pzErrmsg = pVtab->zErrMsg; |
| 86305 | 87537 | pVtab->zErrMsg = 0; |
| 86306 | 87538 | } |
| 86307 | 87539 | } |
| 86308 | 87540 | db->aVTrans = aVTrans; |
| 86309 | | - rcsafety = sqlite3SafetyOn(db); |
| 86310 | | - |
| 86311 | | - if( rc==SQLITE_OK ){ |
| 86312 | | - rc = rcsafety; |
| 86313 | | - } |
| 86314 | 87541 | return rc; |
| 86315 | 87542 | } |
| 86316 | 87543 | |
| 86317 | 87544 | /* |
| 86318 | 87545 | ** Invoke the xRollback method of all virtual tables in the |
| | @@ -87131,11 +88358,11 @@ |
| 87131 | 88358 | ** be the name of an indexed column with TEXT affinity. */ |
| 87132 | 88359 | return 0; |
| 87133 | 88360 | } |
| 87134 | 88361 | assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ |
| 87135 | 88362 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 87136 | | - assert( pColl!=0 ); /* Every non-IPK column has a collating sequence */ |
| 88363 | + if( pColl==0 ) return 0; /* Happens when LHS has an undefined collation */ |
| 87137 | 88364 | if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) && |
| 87138 | 88365 | (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){ |
| 87139 | 88366 | /* IMP: R-09003-32046 For the GLOB operator, the column must use the |
| 87140 | 88367 | ** default BINARY collating sequence. |
| 87141 | 88368 | ** IMP: R-41408-28306 For the LIKE operator, if case_sensitive_like mode |
| | @@ -87574,11 +88801,11 @@ |
| 87574 | 88801 | WhereTerm *pTerm; /* The term to be analyzed */ |
| 87575 | 88802 | WhereMaskSet *pMaskSet; /* Set of table index masks */ |
| 87576 | 88803 | Expr *pExpr; /* The expression to be analyzed */ |
| 87577 | 88804 | Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ |
| 87578 | 88805 | Bitmask prereqAll; /* Prerequesites of pExpr */ |
| 87579 | | - Bitmask extraRight = 0; /* */ |
| 88806 | + Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ |
| 87580 | 88807 | Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ |
| 87581 | 88808 | int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ |
| 87582 | 88809 | int noCase = 0; /* LIKE/GLOB distinguishes case */ |
| 87583 | 88810 | int op; /* Top-level operator. pExpr->op */ |
| 87584 | 88811 | Parse *pParse = pWC->pParse; /* Parsing context */ |
| | @@ -87646,11 +88873,12 @@ |
| 87646 | 88873 | } |
| 87647 | 88874 | exprCommute(pParse, pDup); |
| 87648 | 88875 | pLeft = pDup->pLeft; |
| 87649 | 88876 | pNew->leftCursor = pLeft->iTable; |
| 87650 | 88877 | pNew->u.leftColumn = pLeft->iColumn; |
| 87651 | | - pNew->prereqRight = prereqLeft; |
| 88878 | + testcase( (prereqLeft | extraRight) != prereqLeft ); |
| 88879 | + pNew->prereqRight = prereqLeft | extraRight; |
| 87652 | 88880 | pNew->prereqAll = prereqAll; |
| 87653 | 88881 | pNew->eOperator = operatorMask(pDup->op); |
| 87654 | 88882 | } |
| 87655 | 88883 | } |
| 87656 | 88884 | |
| | @@ -88236,16 +89464,14 @@ |
| 88236 | 89464 | static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ |
| 88237 | 89465 | sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; |
| 88238 | 89466 | int i; |
| 88239 | 89467 | int rc; |
| 88240 | 89468 | |
| 88241 | | - (void)sqlite3SafetyOff(pParse->db); |
| 88242 | 89469 | WHERETRACE(("xBestIndex for %s\n", pTab->zName)); |
| 88243 | 89470 | TRACE_IDX_INPUTS(p); |
| 88244 | 89471 | rc = pVtab->pModule->xBestIndex(pVtab, p); |
| 88245 | 89472 | TRACE_IDX_OUTPUTS(p); |
| 88246 | | - (void)sqlite3SafetyOn(pParse->db); |
| 88247 | 89473 | |
| 88248 | 89474 | if( rc!=SQLITE_OK ){ |
| 88249 | 89475 | if( rc==SQLITE_NOMEM ){ |
| 88250 | 89476 | pParse->db->mallocFailed = 1; |
| 88251 | 89477 | }else if( !pVtab->zErrMsg ){ |
| | @@ -90871,11 +92097,11 @@ |
| 90871 | 92097 | ** shifting terminals. |
| 90872 | 92098 | ** yy_reduce_ofst[] For each state, the offset into yy_action for |
| 90873 | 92099 | ** shifting non-terminals after a reduce. |
| 90874 | 92100 | ** yy_default[] Default action for each state. |
| 90875 | 92101 | */ |
| 90876 | | -#define YY_ACTTAB_COUNT (1543) |
| 92102 | +#define YY_ACTTAB_COUNT (1550) |
| 90877 | 92103 | static const YYACTIONTYPE yy_action[] = { |
| 90878 | 92104 | /* 0 */ 313, 49, 556, 46, 147, 172, 628, 598, 55, 55, |
| 90879 | 92105 | /* 10 */ 55, 55, 302, 53, 53, 53, 53, 52, 52, 51, |
| 90880 | 92106 | /* 20 */ 51, 51, 50, 238, 603, 66, 624, 623, 604, 598, |
| 90881 | 92107 | /* 30 */ 591, 585, 48, 53, 53, 53, 53, 52, 52, 51, |
| | @@ -91021,17 +92247,17 @@ |
| 91021 | 92247 | /* 1430 */ 602, 81, 411, 514, 414, 512, 131, 602, 70, 229, |
| 91022 | 92248 | /* 1440 */ 228, 227, 494, 602, 17, 411, 488, 414, 259, 346, |
| 91023 | 92249 | /* 1450 */ 249, 389, 487, 486, 314, 164, 602, 79, 310, 240, |
| 91024 | 92250 | /* 1460 */ 414, 373, 480, 163, 262, 371, 414, 162, 369, 602, |
| 91025 | 92251 | /* 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, |
| 92252 | + /* 1480 */ 141, 122, 339, 187, 119, 457, 348, 347, 117, 116, |
| 92253 | + /* 1490 */ 115, 112, 114, 448, 182, 22, 320, 433, 432, 431, |
| 92254 | + /* 1500 */ 19, 428, 610, 597, 574, 193, 572, 63, 298, 404, |
| 92255 | + /* 1510 */ 555, 552, 290, 281, 510, 460, 498, 499, 495, 447, |
| 92256 | + /* 1520 */ 356, 497, 256, 380, 306, 570, 5, 250, 345, 238, |
| 92257 | + /* 1530 */ 299, 550, 527, 490, 508, 525, 502, 401, 501, 963, |
| 92258 | + /* 1540 */ 211, 963, 483, 963, 963, 963, 963, 963, 963, 370, |
| 91033 | 92259 | }; |
| 91034 | 92260 | static const YYCODETYPE yy_lookahead[] = { |
| 91035 | 92261 | /* 0 */ 19, 222, 223, 224, 225, 24, 1, 26, 77, 78, |
| 91036 | 92262 | /* 10 */ 79, 80, 15, 82, 83, 84, 85, 86, 87, 88, |
| 91037 | 92263 | /* 20 */ 89, 90, 91, 92, 113, 22, 26, 27, 117, 26, |
| | @@ -91178,22 +92404,22 @@ |
| 91178 | 92404 | /* 1430 */ 174, 175, 150, 178, 165, 176, 22, 174, 175, 230, |
| 91179 | 92405 | /* 1440 */ 92, 230, 184, 174, 175, 150, 176, 165, 105, 106, |
| 91180 | 92406 | /* 1450 */ 107, 150, 176, 176, 111, 156, 174, 175, 179, 116, |
| 91181 | 92407 | /* 1460 */ 165, 18, 157, 156, 238, 157, 165, 156, 45, 174, |
| 91182 | 92408 | /* 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, |
| 92409 | + /* 1480 */ 68, 189, 139, 219, 22, 199, 157, 18, 192, 192, |
| 92410 | + /* 1490 */ 192, 189, 192, 199, 219, 243, 157, 40, 157, 157, |
| 92411 | + /* 1500 */ 243, 38, 153, 166, 233, 196, 233, 246, 198, 228, |
| 92412 | + /* 1510 */ 177, 177, 209, 177, 182, 199, 166, 177, 166, 199, |
| 92413 | + /* 1520 */ 242, 177, 242, 178, 148, 166, 196, 209, 209, 92, |
| 92414 | + /* 1530 */ 195, 208, 174, 186, 183, 174, 183, 191, 183, 253, |
| 92415 | + /* 1540 */ 236, 253, 186, 253, 253, 253, 253, 253, 253, 237, |
| 91190 | 92416 | }; |
| 91191 | 92417 | #define YY_SHIFT_USE_DFLT (-90) |
| 91192 | 92418 | #define YY_SHIFT_COUNT (418) |
| 91193 | 92419 | #define YY_SHIFT_MIN (-89) |
| 91194 | | -#define YY_SHIFT_MAX (1470) |
| 92420 | +#define YY_SHIFT_MAX (1469) |
| 91195 | 92421 | static const short yy_shift_ofst[] = { |
| 91196 | 92422 | /* 0 */ 993, 1114, 1343, 1114, 1213, 1213, 90, 90, 0, -19, |
| 91197 | 92423 | /* 10 */ 1213, 1213, 1213, 1213, 1213, 352, 517, 721, 1091, 1213, |
| 91198 | 92424 | /* 20 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, |
| 91199 | 92425 | /* 30 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, |
| | @@ -91204,11 +92430,11 @@ |
| 91204 | 92430 | /* 80 */ 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, |
| 91205 | 92431 | /* 90 */ 795, 795, 795, 795, 795, 795, 869, 795, 943, 1017, |
| 91206 | 92432 | /* 100 */ 1017, -69, -69, -69, -69, -1, -1, 58, 138, -44, |
| 91207 | 92433 | /* 110 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91208 | 92434 | /* 120 */ 517, 517, 517, 517, 517, 517, 202, 579, 517, 517, |
| 91209 | | - /* 130 */ 517, 517, 517, 382, 885, 1450, -90, -90, -90, 1293, |
| 92435 | + /* 130 */ 517, 517, 517, 382, 885, 1437, -90, -90, -90, 1293, |
| 91210 | 92436 | /* 140 */ 73, 272, 272, 309, 311, 297, 282, 216, 602, 538, |
| 91211 | 92437 | /* 150 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91212 | 92438 | /* 160 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91213 | 92439 | /* 170 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, |
| 91214 | 92440 | /* 180 */ 517, 517, 505, 231, 231, 231, 706, 64, 1177, 1177, |
| | @@ -91215,12 +92441,12 @@ |
| 91215 | 92441 | /* 190 */ 1177, -90, -90, -90, 136, 168, 168, 12, 496, 496, |
| 91216 | 92442 | /* 200 */ 496, 506, 423, 512, 370, 349, 335, 149, 149, 149, |
| 91217 | 92443 | /* 210 */ 149, 604, 516, 149, 149, 508, 3, 299, 677, 871, |
| 91218 | 92444 | /* 220 */ 613, 613, 879, 871, 879, 144, 382, 226, 382, 226, |
| 91219 | 92445 | /* 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, |
| 92446 | + /* 240 */ -89, 801, 1463, 1244, 1244, 1457, 1457, 1244, 1462, 1412, |
| 92447 | + /* 250 */ 1188, 1469, 1469, 1469, 1469, 1244, 1188, 1462, 1412, 1412, |
| 91222 | 92448 | /* 260 */ 1244, 1443, 1338, 1423, 1244, 1244, 1443, 1244, 1443, 1244, |
| 91223 | 92449 | /* 270 */ 1443, 1414, 1306, 1306, 1306, 1365, 1348, 1348, 1414, 1306, |
| 91224 | 92450 | /* 280 */ 1317, 1306, 1365, 1306, 1306, 1267, 1268, 1267, 1268, 1267, |
| 91225 | 92451 | /* 290 */ 1268, 1244, 1244, 1216, 1214, 1215, 1192, 1173, 1188, 1177, |
| 91226 | 92452 | /* 300 */ 1260, 1253, 1253, 1248, 1248, 1248, 1248, -90, -90, -90, |
| | @@ -91237,11 +92463,11 @@ |
| 91237 | 92463 | /* 410 */ 152, 123, 68, -20, -42, 57, 39, -3, 5, |
| 91238 | 92464 | }; |
| 91239 | 92465 | #define YY_REDUCE_USE_DFLT (-222) |
| 91240 | 92466 | #define YY_REDUCE_COUNT (312) |
| 91241 | 92467 | #define YY_REDUCE_MIN (-221) |
| 91242 | | -#define YY_REDUCE_MAX (1378) |
| 92468 | +#define YY_REDUCE_MAX (1376) |
| 91243 | 92469 | static const short yy_reduce_ofst[] = { |
| 91244 | 92470 | /* 0 */ 310, 994, 1134, 221, 169, 157, 89, 18, 83, 301, |
| 91245 | 92471 | /* 10 */ 377, 316, 312, 16, 295, 238, 249, 391, 1301, 1295, |
| 91246 | 92472 | /* 20 */ 1282, 1269, 1263, 1256, 1251, 1240, 1234, 1228, 1221, 1208, |
| 91247 | 92473 | /* 30 */ 1109, 1103, 1077, 1054, 1022, 1016, 911, 908, 890, 888, |
| | @@ -91258,17 +92484,17 @@ |
| 91258 | 92484 | /* 140 */ 823, 738, 712, 892, 1199, 1185, 1176, 1171, 673, 673, |
| 91259 | 92485 | /* 150 */ 1168, 1167, 1162, 1159, 1148, 1145, 1139, 1117, 1111, 1107, |
| 91260 | 92486 | /* 160 */ 1084, 1066, 1049, 1011, 1010, 1006, 1002, 999, 998, 973, |
| 91261 | 92487 | /* 170 */ 972, 970, 966, 964, 895, 894, 892, 833, 822, 762, |
| 91262 | 92488 | /* 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, |
| 92489 | + /* 190 */ 460, 464, 572, 584, 1356, 1361, 1358, 1347, 1355, 1353, |
| 92490 | + /* 200 */ 1351, 1323, 1335, 1346, 1335, 1335, 1335, 1335, 1335, 1335, |
| 92491 | + /* 210 */ 1335, 1312, 1304, 1335, 1335, 1323, 1359, 1330, 1376, 1320, |
| 92492 | + /* 220 */ 1319, 1318, 1280, 1316, 1278, 1345, 1352, 1344, 1350, 1340, |
| 92493 | + /* 230 */ 1332, 1336, 1303, 1334, 1333, 1281, 1273, 1271, 1337, 1310, |
| 92494 | + /* 240 */ 1309, 1349, 1261, 1342, 1341, 1257, 1252, 1339, 1275, 1302, |
| 92495 | + /* 250 */ 1294, 1300, 1298, 1297, 1296, 1329, 1286, 1264, 1292, 1289, |
| 91270 | 92496 | /* 260 */ 1322, 1321, 1235, 1226, 1315, 1314, 1311, 1308, 1307, 1305, |
| 91271 | 92497 | /* 270 */ 1299, 1279, 1277, 1276, 1270, 1258, 1211, 1209, 1250, 1259, |
| 91272 | 92498 | /* 280 */ 1255, 1242, 1243, 1241, 1201, 1200, 1184, 1186, 1182, 1178, |
| 91273 | 92499 | /* 290 */ 1165, 1206, 1204, 1113, 1135, 1095, 1124, 1105, 1102, 1096, |
| 91274 | 92500 | /* 300 */ 1112, 1140, 1136, 1121, 1116, 1115, 1089, 985, 961, 987, |
| | @@ -94758,10 +95984,11 @@ |
| 94758 | 95984 | sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc)); |
| 94759 | 95985 | } |
| 94760 | 95986 | assert( pzErrMsg!=0 ); |
| 94761 | 95987 | if( pParse->zErrMsg ){ |
| 94762 | 95988 | *pzErrMsg = pParse->zErrMsg; |
| 95989 | + sqlite3_log(pParse->rc, "%s", *pzErrMsg); |
| 94763 | 95990 | pParse->zErrMsg = 0; |
| 94764 | 95991 | nErr++; |
| 94765 | 95992 | } |
| 94766 | 95993 | if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ |
| 94767 | 95994 | sqlite3VdbeDelete(pParse->pVdbe); |
| | @@ -95436,11 +96663,11 @@ |
| 95436 | 96663 | va_list ap; |
| 95437 | 96664 | int rc = SQLITE_OK; |
| 95438 | 96665 | |
| 95439 | 96666 | /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while |
| 95440 | 96667 | ** the SQLite library is in use. */ |
| 95441 | | - if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE; |
| 96668 | + if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT; |
| 95442 | 96669 | |
| 95443 | 96670 | va_start(ap, op); |
| 95444 | 96671 | switch( op ){ |
| 95445 | 96672 | |
| 95446 | 96673 | /* Mutex configuration options are only available in a threadsafe |
| | @@ -95557,10 +96784,25 @@ |
| 95557 | 96784 | case SQLITE_CONFIG_LOOKASIDE: { |
| 95558 | 96785 | sqlite3GlobalConfig.szLookaside = va_arg(ap, int); |
| 95559 | 96786 | sqlite3GlobalConfig.nLookaside = va_arg(ap, int); |
| 95560 | 96787 | break; |
| 95561 | 96788 | } |
| 96789 | + |
| 96790 | + /* Record a pointer to the logger funcction and its first argument. |
| 96791 | + ** The default is NULL. Logging is disabled if the function pointer is |
| 96792 | + ** NULL. |
| 96793 | + */ |
| 96794 | + case SQLITE_CONFIG_LOG: { |
| 96795 | + /* MSVC is picky about pulling func ptrs from va lists. |
| 96796 | + ** http://support.microsoft.com/kb/47961 |
| 96797 | + ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*)); |
| 96798 | + */ |
| 96799 | + typedef void(*LOGFUNC_t)(void*,int,const char*); |
| 96800 | + sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t); |
| 96801 | + sqlite3GlobalConfig.pLogArg = va_arg(ap, void*); |
| 96802 | + break; |
| 96803 | + } |
| 95562 | 96804 | |
| 95563 | 96805 | default: { |
| 95564 | 96806 | rc = SQLITE_ERROR; |
| 95565 | 96807 | break; |
| 95566 | 96808 | } |
| | @@ -95770,11 +97012,11 @@ |
| 95770 | 97012 | |
| 95771 | 97013 | if( !db ){ |
| 95772 | 97014 | return SQLITE_OK; |
| 95773 | 97015 | } |
| 95774 | 97016 | if( !sqlite3SafetyCheckSickOrOk(db) ){ |
| 95775 | | - return SQLITE_MISUSE; |
| 97017 | + return SQLITE_MISUSE_BKPT; |
| 95776 | 97018 | } |
| 95777 | 97019 | sqlite3_mutex_enter(db->mutex); |
| 95778 | 97020 | |
| 95779 | 97021 | sqlite3ResetInternalSchema(db, 0); |
| 95780 | 97022 | |
| | @@ -96117,11 +97359,11 @@ |
| 96117 | 97359 | (xFunc && (xFinal || xStep)) || |
| 96118 | 97360 | (!xFunc && (xFinal && !xStep)) || |
| 96119 | 97361 | (!xFunc && (!xFinal && xStep)) || |
| 96120 | 97362 | (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || |
| 96121 | 97363 | (255<(nName = sqlite3Strlen30( zFunctionName))) ){ |
| 96122 | | - return SQLITE_MISUSE; |
| 97364 | + return SQLITE_MISUSE_BKPT; |
| 96123 | 97365 | } |
| 96124 | 97366 | |
| 96125 | 97367 | #ifndef SQLITE_OMIT_UTF16 |
| 96126 | 97368 | /* If SQLITE_UTF16 is specified as the encoding type, transform this |
| 96127 | 97369 | ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the |
| | @@ -96448,11 +97690,11 @@ |
| 96448 | 97690 | const char *z; |
| 96449 | 97691 | if( !db ){ |
| 96450 | 97692 | return sqlite3ErrStr(SQLITE_NOMEM); |
| 96451 | 97693 | } |
| 96452 | 97694 | if( !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96453 | | - return sqlite3ErrStr(SQLITE_MISUSE); |
| 97695 | + return sqlite3ErrStr(SQLITE_MISUSE_BKPT); |
| 96454 | 97696 | } |
| 96455 | 97697 | sqlite3_mutex_enter(db->mutex); |
| 96456 | 97698 | if( db->mallocFailed ){ |
| 96457 | 97699 | z = sqlite3ErrStr(SQLITE_NOMEM); |
| 96458 | 97700 | }else{ |
| | @@ -96517,20 +97759,20 @@ |
| 96517 | 97759 | ** Return the most recent error code generated by an SQLite routine. If NULL is |
| 96518 | 97760 | ** passed to this function, we assume a malloc() failed during sqlite3_open(). |
| 96519 | 97761 | */ |
| 96520 | 97762 | SQLITE_API int sqlite3_errcode(sqlite3 *db){ |
| 96521 | 97763 | if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96522 | | - return SQLITE_MISUSE; |
| 97764 | + return SQLITE_MISUSE_BKPT; |
| 96523 | 97765 | } |
| 96524 | 97766 | if( !db || db->mallocFailed ){ |
| 96525 | 97767 | return SQLITE_NOMEM; |
| 96526 | 97768 | } |
| 96527 | 97769 | return db->errCode & db->errMask; |
| 96528 | 97770 | } |
| 96529 | 97771 | SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ |
| 96530 | 97772 | if( db && !sqlite3SafetyCheckSickOrOk(db) ){ |
| 96531 | | - return SQLITE_MISUSE; |
| 97773 | + return SQLITE_MISUSE_BKPT; |
| 96532 | 97774 | } |
| 96533 | 97775 | if( !db || db->mallocFailed ){ |
| 96534 | 97776 | return SQLITE_NOMEM; |
| 96535 | 97777 | } |
| 96536 | 97778 | return db->errCode; |
| | @@ -96564,11 +97806,11 @@ |
| 96564 | 97806 | testcase( enc2==SQLITE_UTF16_ALIGNED ); |
| 96565 | 97807 | if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){ |
| 96566 | 97808 | enc2 = SQLITE_UTF16NATIVE; |
| 96567 | 97809 | } |
| 96568 | 97810 | if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){ |
| 96569 | | - return SQLITE_MISUSE; |
| 97811 | + return SQLITE_MISUSE_BKPT; |
| 96570 | 97812 | } |
| 96571 | 97813 | |
| 96572 | 97814 | /* Check if this call is removing or replacing an existing collation |
| 96573 | 97815 | ** sequence. If so, and there are active VMs, return busy. If there |
| 96574 | 97816 | ** are no active VMs, invalidate any pre-compiled statements. |
| | @@ -97108,20 +98350,38 @@ |
| 97108 | 98350 | */ |
| 97109 | 98351 | SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ |
| 97110 | 98352 | return db->autoCommit; |
| 97111 | 98353 | } |
| 97112 | 98354 | |
| 97113 | | -#ifdef SQLITE_DEBUG |
| 97114 | 98355 | /* |
| 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. |
| 98356 | +** The following routines are subtitutes for constants SQLITE_CORRUPT, |
| 98357 | +** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error |
| 98358 | +** constants. They server two purposes: |
| 98359 | +** |
| 98360 | +** 1. Serve as a convenient place to set a breakpoint in a debugger |
| 98361 | +** to detect when version error conditions occurs. |
| 98362 | +** |
| 98363 | +** 2. Invoke sqlite3_log() to provide the source code location where |
| 98364 | +** a low-level error is first detected. |
| 97118 | 98365 | */ |
| 97119 | | -SQLITE_PRIVATE int sqlite3Corrupt(void){ |
| 98366 | +SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ |
| 98367 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 98368 | + sqlite3_log(SQLITE_CORRUPT, |
| 98369 | + "database corruption found by source line %d", lineno); |
| 97120 | 98370 | return SQLITE_CORRUPT; |
| 97121 | 98371 | } |
| 97122 | | -#endif |
| 98372 | +SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ |
| 98373 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 98374 | + sqlite3_log(SQLITE_MISUSE, "misuse detected by source line %d", lineno); |
| 98375 | + return SQLITE_MISUSE; |
| 98376 | +} |
| 98377 | +SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ |
| 98378 | + testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 98379 | + sqlite3_log(SQLITE_CANTOPEN, "cannot open file at source line %d", lineno); |
| 98380 | + return SQLITE_CANTOPEN; |
| 98381 | +} |
| 98382 | + |
| 97123 | 98383 | |
| 97124 | 98384 | #ifndef SQLITE_OMIT_DEPRECATED |
| 97125 | 98385 | /* |
| 97126 | 98386 | ** This is a convenience routine that makes sure that all thread-specific |
| 97127 | 98387 | ** data for this thread has been deallocated. |
| | @@ -97161,11 +98421,10 @@ |
| 97161 | 98421 | int primarykey = 0; |
| 97162 | 98422 | int autoinc = 0; |
| 97163 | 98423 | |
| 97164 | 98424 | /* Ensure the database schema has been loaded */ |
| 97165 | 98425 | sqlite3_mutex_enter(db->mutex); |
| 97166 | | - (void)sqlite3SafetyOn(db); |
| 97167 | 98426 | sqlite3BtreeEnterAll(db); |
| 97168 | 98427 | rc = sqlite3Init(db, &zErrMsg); |
| 97169 | 98428 | if( SQLITE_OK!=rc ){ |
| 97170 | 98429 | goto error_out; |
| 97171 | 98430 | } |
| | @@ -97220,11 +98479,10 @@ |
| 97220 | 98479 | zCollSeq = "BINARY"; |
| 97221 | 98480 | } |
| 97222 | 98481 | |
| 97223 | 98482 | error_out: |
| 97224 | 98483 | sqlite3BtreeLeaveAll(db); |
| 97225 | | - (void)sqlite3SafetyOff(db); |
| 97226 | 98484 | |
| 97227 | 98485 | /* Whether the function call succeeded or failed, set the output parameters |
| 97228 | 98486 | ** to whatever their local counterparts contain. If an error did occur, |
| 97229 | 98487 | ** this has the effect of zeroing all output parameters. |
| 97230 | 98488 | */ |
| | @@ -97859,13 +99117,10 @@ |
| 97859 | 99117 | ** |
| 97860 | 99118 | ** * The FTS3 module is being built into the core of |
| 97861 | 99119 | ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). |
| 97862 | 99120 | */ |
| 97863 | 99121 | |
| 97864 | | -/* TODO(shess) Consider exporting this comment to an HTML file or the |
| 97865 | | -** wiki. |
| 97866 | | -*/ |
| 97867 | 99122 | /* The full-text index is stored in a series of b+tree (-like) |
| 97868 | 99123 | ** structures called segments which map terms to doclists. The |
| 97869 | 99124 | ** structures are like b+trees in layout, but are constructed from the |
| 97870 | 99125 | ** bottom up in optimal fashion and are not updatable. Since trees |
| 97871 | 99126 | ** are built from the bottom up, things will be described from the |
| | @@ -97884,45 +99139,68 @@ |
| 97884 | 99139 | ** 7 bits - A |
| 97885 | 99140 | ** 14 bits - BA |
| 97886 | 99141 | ** 21 bits - BBA |
| 97887 | 99142 | ** and so on. |
| 97888 | 99143 | ** |
| 97889 | | -** This is identical to how sqlite encodes varints (see util.c). |
| 99144 | +** This is similar in concept to how sqlite encodes "varints" but |
| 99145 | +** the encoding is not the same. SQLite varints are big-endian |
| 99146 | +** are are limited to 9 bytes in length whereas FTS3 varints are |
| 99147 | +** little-endian and can be upt to 10 bytes in length (in theory). |
| 99148 | +** |
| 99149 | +** Example encodings: |
| 99150 | +** |
| 99151 | +** 1: 0x01 |
| 99152 | +** 127: 0x7f |
| 99153 | +** 128: 0x81 0x00 |
| 97890 | 99154 | ** |
| 97891 | 99155 | ** |
| 97892 | 99156 | **** Document lists **** |
| 97893 | 99157 | ** A doclist (document list) holds a docid-sorted list of hits for a |
| 97894 | 99158 | ** given term. Doclists hold docids, and can optionally associate |
| 97895 | | -** token positions and offsets with docids. |
| 99159 | +** token positions and offsets with docids. A position is the index |
| 99160 | +** of a word within the document. The first word of the document has |
| 99161 | +** a position of 0. |
| 99162 | +** |
| 99163 | +** FTS3 used to optionally store character offsets using a compile-time |
| 99164 | +** option. But that functionality is no longer supported. |
| 97896 | 99165 | ** |
| 97897 | 99166 | ** A DL_POSITIONS_OFFSETS doclist is stored like this: |
| 97898 | 99167 | ** |
| 97899 | 99168 | ** array { |
| 97900 | 99169 | ** varint docid; |
| 97901 | 99170 | ** array { (position list for column 0) |
| 97902 | 99171 | ** varint position; (delta from previous position plus POS_BASE) |
| 97903 | | -** varint startOffset; (delta from previous startOffset) |
| 97904 | | -** varint endOffset; (delta from startOffset) |
| 97905 | 99172 | ** } |
| 97906 | 99173 | ** array { |
| 97907 | 99174 | ** varint POS_COLUMN; (marks start of position list for new column) |
| 97908 | 99175 | ** varint column; (index of new column) |
| 97909 | 99176 | ** array { |
| 97910 | 99177 | ** varint position; (delta from previous position plus POS_BASE) |
| 97911 | | -** varint startOffset;(delta from previous startOffset) |
| 97912 | | -** varint endOffset; (delta from startOffset) |
| 97913 | 99178 | ** } |
| 97914 | 99179 | ** } |
| 97915 | 99180 | ** varint POS_END; (marks end of positions for this document. |
| 97916 | 99181 | ** } |
| 97917 | 99182 | ** |
| 97918 | 99183 | ** Here, array { X } means zero or more occurrences of X, adjacent in |
| 97919 | 99184 | ** 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. |
| 99185 | +** generated by the tokenizer. Note that POS_END and POS_COLUMN occur |
| 99186 | +** in the same logical place as the position element, and act as sentinals |
| 99187 | +** ending a position list array. POS_END is 0. POS_COLUMN is 1. |
| 99188 | +** The positions numbers are not stored literally but rather as two more |
| 99189 | +** the difference from the prior position, or the just the position plus |
| 99190 | +** 2 for the first position. Example: |
| 99191 | +** |
| 99192 | +** label: A B C D E F G H I J K |
| 99193 | +** value: 123 5 9 1 1 14 35 0 234 72 0 |
| 99194 | +** |
| 99195 | +** The 123 value is the first docid. For column zero in this document |
| 99196 | +** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1 |
| 99197 | +** at D signals the start of a new column; the 1 at E indicates that the |
| 99198 | +** new column is column number 1. There are two positions at 12 and 45 |
| 99199 | +** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The |
| 99200 | +** 234 at I is the next docid. It has one position 72 (72-2) and then |
| 99201 | +** terminates with the 0 at K. |
| 97924 | 99202 | ** |
| 97925 | 99203 | ** A DL_POSITIONS doclist omits the startOffset and endOffset |
| 97926 | 99204 | ** information. A DL_DOCIDS doclist omits both the position and |
| 97927 | 99205 | ** offset information, becoming an array of varint-encoded docids. |
| 97928 | 99206 | ** |
| | @@ -98492,11 +99770,11 @@ |
| 98492 | 99770 | sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ |
| 98493 | 99771 | |
| 98494 | 99772 | /* Precompiled statements used by the implementation. Each of these |
| 98495 | 99773 | ** statements is run and reset within a single virtual table API call. |
| 98496 | 99774 | */ |
| 98497 | | - sqlite3_stmt *aStmt[18]; |
| 99775 | + sqlite3_stmt *aStmt[25]; |
| 98498 | 99776 | |
| 98499 | 99777 | /* Pointer to string containing the SQL: |
| 98500 | 99778 | ** |
| 98501 | 99779 | ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ? |
| 98502 | 99780 | ** ORDER BY blockid" |
| | @@ -98506,10 +99784,12 @@ |
| 98506 | 99784 | int nLeavesTotal; /* Total number of prepared leaves stmts */ |
| 98507 | 99785 | int nLeavesAlloc; /* Allocated size of aLeavesStmt */ |
| 98508 | 99786 | sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */ |
| 98509 | 99787 | |
| 98510 | 99788 | int nNodeSize; /* Soft limit for node size */ |
| 99789 | + u8 bHasContent; /* True if %_content table exists */ |
| 99790 | + u8 bHasDocsize; /* True if %_docsize table exists */ |
| 98511 | 99791 | |
| 98512 | 99792 | /* The following hash table is used to buffer pending index updates during |
| 98513 | 99793 | ** transactions. Variable nPendingData estimates the memory size of the |
| 98514 | 99794 | ** pending data, including hash table overhead, but not malloc overhead. |
| 98515 | 99795 | ** When nPendingData exceeds nMaxPendingData, the buffer is flushed |
| | @@ -98536,12 +99816,12 @@ |
| 98536 | 99816 | Fts3Expr *pExpr; /* Parsed MATCH query string */ |
| 98537 | 99817 | sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ |
| 98538 | 99818 | char *pNextId; /* Pointer into the body of aDoclist */ |
| 98539 | 99819 | char *aDoclist; /* List of docids for full-text queries */ |
| 98540 | 99820 | int nDoclist; /* Size of buffer at aDoclist */ |
| 98541 | | - int isMatchinfoOk; /* True when aMatchinfo[] matches iPrevId */ |
| 98542 | | - u32 *aMatchinfo; |
| 99821 | + int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ |
| 99822 | + u32 *aMatchinfo; /* Information about most recent match */ |
| 98543 | 99823 | }; |
| 98544 | 99824 | |
| 98545 | 99825 | /* |
| 98546 | 99826 | ** The Fts3Cursor.eSearch member is always set to one of the following. |
| 98547 | 99827 | ** Actualy, Fts3Cursor.eSearch can be greater than or equal to |
| | @@ -98643,10 +99923,12 @@ |
| 98643 | 99923 | Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *, |
| 98644 | 99924 | int (*)(Fts3Table *, void *, char *, int, char *, int), void * |
| 98645 | 99925 | ); |
| 98646 | 99926 | SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*); |
| 98647 | 99927 | SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **); |
| 99928 | +SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*); |
| 99929 | +SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*); |
| 98648 | 99930 | |
| 98649 | 99931 | /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ |
| 98650 | 99932 | #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 |
| 98651 | 99933 | #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 |
| 98652 | 99934 | #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 |
| | @@ -98667,10 +99949,11 @@ |
| 98667 | 99949 | SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); |
| 98668 | 99950 | SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); |
| 98669 | 99951 | |
| 98670 | 99952 | SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int); |
| 98671 | 99953 | SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *, Fts3Expr *); |
| 99954 | +SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int); |
| 98672 | 99955 | |
| 98673 | 99956 | /* fts3_tokenizer.c */ |
| 98674 | 99957 | SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); |
| 98675 | 99958 | SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); |
| 98676 | 99959 | SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, |
| | @@ -98677,14 +99960,11 @@ |
| 98677 | 99960 | const char *, sqlite3_tokenizer **, const char **, char ** |
| 98678 | 99961 | ); |
| 98679 | 99962 | |
| 98680 | 99963 | /* fts3_snippet.c */ |
| 98681 | 99964 | 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 *, |
| 99965 | +SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, |
| 98686 | 99966 | const char *, const char *, int, int |
| 98687 | 99967 | ); |
| 98688 | 99968 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *); |
| 98689 | 99969 | |
| 98690 | 99970 | /* fts3_expr.c */ |
| | @@ -98800,16 +100080,27 @@ |
| 98800 | 100080 | } |
| 98801 | 100081 | z[iOut] = '\0'; |
| 98802 | 100082 | } |
| 98803 | 100083 | } |
| 98804 | 100084 | |
| 100085 | +/* |
| 100086 | +** Read a single varint from the doclist at *pp and advance *pp to point |
| 100087 | +** to the next element of the varlist. Add the value of the varint |
| 100088 | +** to *pVal. |
| 100089 | +*/ |
| 98805 | 100090 | static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){ |
| 98806 | 100091 | sqlite3_int64 iVal; |
| 98807 | 100092 | *pp += sqlite3Fts3GetVarint(*pp, &iVal); |
| 98808 | 100093 | *pVal += iVal; |
| 98809 | 100094 | } |
| 98810 | 100095 | |
| 100096 | +/* |
| 100097 | +** As long as *pp has not reached its end (pEnd), then do the same |
| 100098 | +** as fts3GetDeltaVarint(): read a single varint and add it to *pVal. |
| 100099 | +** But if we have reached the end of the varint, just set *pp=0 and |
| 100100 | +** leave *pVal unchanged. |
| 100101 | +*/ |
| 98811 | 100102 | static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){ |
| 98812 | 100103 | if( *pp>=pEnd ){ |
| 98813 | 100104 | *pp = 0; |
| 98814 | 100105 | }else{ |
| 98815 | 100106 | fts3GetDeltaVarint(pp, pVal); |
| | @@ -98839,35 +100130,52 @@ |
| 98839 | 100130 | p->pTokenizer->pModule->xDestroy(p->pTokenizer); |
| 98840 | 100131 | |
| 98841 | 100132 | sqlite3_free(p); |
| 98842 | 100133 | return SQLITE_OK; |
| 98843 | 100134 | } |
| 100135 | + |
| 100136 | +/* |
| 100137 | +** Construct one or more SQL statements from the format string given |
| 100138 | +** and then evaluate those statements. The success code is writting |
| 100139 | +** into *pRc. |
| 100140 | +** |
| 100141 | +** If *pRc is initially non-zero then this routine is a no-op. |
| 100142 | +*/ |
| 100143 | +void fts3DbExec( |
| 100144 | + int *pRc, /* Success code */ |
| 100145 | + sqlite3 *db, /* Database in which to run SQL */ |
| 100146 | + const char *zFormat, /* Format string for SQL */ |
| 100147 | + ... /* Arguments to the format string */ |
| 100148 | +){ |
| 100149 | + va_list ap; |
| 100150 | + char *zSql; |
| 100151 | + if( *pRc ) return; |
| 100152 | + va_start(ap, zFormat); |
| 100153 | + zSql = sqlite3_vmprintf(zFormat, ap); |
| 100154 | + va_end(ap); |
| 100155 | + if( zSql==0 ){ |
| 100156 | + *pRc = SQLITE_NOMEM; |
| 100157 | + }else{ |
| 100158 | + *pRc = sqlite3_exec(db, zSql, 0, 0, 0); |
| 100159 | + sqlite3_free(zSql); |
| 100160 | + } |
| 100161 | +} |
| 98844 | 100162 | |
| 98845 | 100163 | /* |
| 98846 | 100164 | ** The xDestroy() virtual table method. |
| 98847 | 100165 | */ |
| 98848 | 100166 | static int fts3DestroyMethod(sqlite3_vtab *pVtab){ |
| 98849 | | - int rc; /* Return code */ |
| 100167 | + int rc = SQLITE_OK; /* Return code */ |
| 98850 | 100168 | 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 | | - } |
| 100169 | + sqlite3 *db = p->db; |
| 100170 | + |
| 100171 | + /* Drop the shadow tables */ |
| 100172 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", p->zDb, p->zName); |
| 100173 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", p->zDb,p->zName); |
| 100174 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", p->zDb, p->zName); |
| 100175 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", p->zDb, p->zName); |
| 100176 | + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", p->zDb, p->zName); |
| 98869 | 100177 | |
| 98870 | 100178 | /* If everything has worked, invoke fts3DisconnectMethod() to free the |
| 98871 | 100179 | ** memory associated with the Fts3Table structure and return SQLITE_OK. |
| 98872 | 100180 | ** Otherwise, return an SQLite error code. |
| 98873 | 100181 | */ |
| | @@ -98912,50 +100220,77 @@ |
| 98912 | 100220 | ** Create the backing store tables (%_content, %_segments and %_segdir) |
| 98913 | 100221 | ** required by the FTS3 table passed as the only argument. This is done |
| 98914 | 100222 | ** as part of the vtab xCreate() method. |
| 98915 | 100223 | */ |
| 98916 | 100224 | static int fts3CreateTables(Fts3Table *p){ |
| 98917 | | - int rc; /* Return code */ |
| 100225 | + int rc = SQLITE_OK; /* Return code */ |
| 98918 | 100226 | int i; /* Iterator variable */ |
| 98919 | 100227 | char *zContentCols; /* Columns of %_content table */ |
| 98920 | | - char *zSql; /* SQL script to create required tables */ |
| 100228 | + sqlite3 *db = p->db; /* The database connection */ |
| 98921 | 100229 | |
| 98922 | 100230 | /* 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);" |
| 100231 | + if( p->bHasContent ){ |
| 100232 | + zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); |
| 100233 | + for(i=0; zContentCols && i<p->nColumn; i++){ |
| 100234 | + char *z = p->azColumn[i]; |
| 100235 | + zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); |
| 100236 | + } |
| 100237 | + if( zContentCols==0 ) rc = SQLITE_NOMEM; |
| 100238 | + |
| 100239 | + /* Create the content table */ |
| 100240 | + fts3DbExec(&rc, db, |
| 100241 | + "CREATE TABLE %Q.'%q_content'(%s)", |
| 100242 | + p->zDb, p->zName, zContentCols |
| 100243 | + ); |
| 100244 | + sqlite3_free(zContentCols); |
| 100245 | + } |
| 100246 | + /* Create other tables */ |
| 100247 | + fts3DbExec(&rc, db, |
| 100248 | + "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);", |
| 100249 | + p->zDb, p->zName |
| 100250 | + ); |
| 100251 | + fts3DbExec(&rc, db, |
| 98933 | 100252 | "CREATE TABLE %Q.'%q_segdir'(" |
| 98934 | 100253 | "level INTEGER," |
| 98935 | 100254 | "idx INTEGER," |
| 98936 | 100255 | "start_block INTEGER," |
| 98937 | 100256 | "leaves_end_block INTEGER," |
| 98938 | 100257 | "end_block INTEGER," |
| 98939 | 100258 | "root BLOB," |
| 98940 | 100259 | "PRIMARY KEY(level, idx)" |
| 98941 | 100260 | ");", |
| 98942 | | - p->zDb, p->zName, zContentCols, p->zDb, p->zName, p->zDb, p->zName |
| 100261 | + p->zDb, p->zName |
| 98943 | 100262 | ); |
| 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; |
| 100263 | + if( p->bHasDocsize ){ |
| 100264 | + fts3DbExec(&rc, db, |
| 100265 | + "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", |
| 100266 | + p->zDb, p->zName |
| 100267 | + ); |
| 100268 | + fts3DbExec(&rc, db, |
| 100269 | + "CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);", |
| 100270 | + p->zDb, p->zName |
| 100271 | + ); |
| 100272 | + } |
| 100273 | + return rc; |
| 100274 | +} |
| 100275 | + |
| 100276 | +/* |
| 100277 | +** Determine if a table currently exists in the database. |
| 100278 | +*/ |
| 100279 | +static void fts3TableExists( |
| 100280 | + int *pRc, /* Success code */ |
| 100281 | + sqlite3 *db, /* The database connection to test */ |
| 100282 | + const char *zDb, /* ATTACHed database within the connection */ |
| 100283 | + const char *zName, /* Name of the FTS3 table */ |
| 100284 | + const char *zSuffix, /* Shadow table extension */ |
| 100285 | + u8 *pResult /* Write results here */ |
| 100286 | +){ |
| 100287 | + int rc = SQLITE_OK; |
| 100288 | + if( *pRc ) return; |
| 100289 | + fts3DbExec(&rc, db, "SELECT 1 FROM %Q.'%q%s'", zDb, zName, zSuffix); |
| 100290 | + *pResult = (rc==SQLITE_OK) ? 1 : 0; |
| 100291 | + if( rc!=SQLITE_ERROR ) *pRc = rc; |
| 98957 | 100292 | } |
| 98958 | 100293 | |
| 98959 | 100294 | /* |
| 98960 | 100295 | ** This function is the implementation of both the xConnect and xCreate |
| 98961 | 100296 | ** methods of the FTS3 virtual table. |
| | @@ -99070,13 +100405,19 @@ |
| 99070 | 100405 | |
| 99071 | 100406 | /* If this is an xCreate call, create the underlying tables in the |
| 99072 | 100407 | ** database. TODO: For xConnect(), it could verify that said tables exist. |
| 99073 | 100408 | */ |
| 99074 | 100409 | if( isCreate ){ |
| 100410 | + p->bHasContent = 1; |
| 100411 | + p->bHasDocsize = argv[0][3]=='4'; |
| 99075 | 100412 | rc = fts3CreateTables(p); |
| 99076 | | - if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 100413 | + }else{ |
| 100414 | + rc = SQLITE_OK; |
| 100415 | + fts3TableExists(&rc, db, argv[1], argv[2], "_content", &p->bHasContent); |
| 100416 | + fts3TableExists(&rc, db, argv[1], argv[2], "_docsize", &p->bHasDocsize); |
| 99077 | 100417 | } |
| 100418 | + if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 99078 | 100419 | |
| 99079 | 100420 | rc = fts3DeclareVtab(p); |
| 99080 | 100421 | if( rc!=SQLITE_OK ) goto fts3_init_out; |
| 99081 | 100422 | |
| 99082 | 100423 | *ppVTab = &p->base; |
| | @@ -99193,16 +100534,10 @@ |
| 99193 | 100534 | return SQLITE_NOMEM; |
| 99194 | 100535 | } |
| 99195 | 100536 | memset(pCsr, 0, sizeof(Fts3Cursor)); |
| 99196 | 100537 | return SQLITE_OK; |
| 99197 | 100538 | } |
| 99198 | | - |
| 99199 | | -/****************************************************************/ |
| 99200 | | -/****************************************************************/ |
| 99201 | | -/****************************************************************/ |
| 99202 | | -/****************************************************************/ |
| 99203 | | - |
| 99204 | 100539 | |
| 99205 | 100540 | /* |
| 99206 | 100541 | ** Close the cursor. For additional information see the documentation |
| 99207 | 100542 | ** on the xClose method of the virtual table interface. |
| 99208 | 100543 | */ |
| | @@ -99255,11 +100590,11 @@ |
| 99255 | 100590 | pCsr->isEof = 1; |
| 99256 | 100591 | }else{ |
| 99257 | 100592 | sqlite3_reset(pCsr->pStmt); |
| 99258 | 100593 | fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId); |
| 99259 | 100594 | pCsr->isRequireSeek = 1; |
| 99260 | | - pCsr->isMatchinfoOk = 1; |
| 100595 | + pCsr->isMatchinfoNeeded = 1; |
| 99261 | 100596 | } |
| 99262 | 100597 | return rc; |
| 99263 | 100598 | } |
| 99264 | 100599 | |
| 99265 | 100600 | |
| | @@ -100120,10 +101455,78 @@ |
| 100120 | 101455 | }else{ |
| 100121 | 101456 | sqlite3_free(pOut); |
| 100122 | 101457 | } |
| 100123 | 101458 | return rc; |
| 100124 | 101459 | } |
| 101460 | + |
| 101461 | +static int fts3NearMerge( |
| 101462 | + int mergetype, /* MERGE_POS_NEAR or MERGE_NEAR */ |
| 101463 | + int nNear, /* Parameter to NEAR operator */ |
| 101464 | + int nTokenLeft, /* Number of tokens in LHS phrase arg */ |
| 101465 | + char *aLeft, /* Doclist for LHS (incl. positions) */ |
| 101466 | + int nLeft, /* Size of LHS doclist in bytes */ |
| 101467 | + int nTokenRight, /* As nTokenLeft */ |
| 101468 | + char *aRight, /* As aLeft */ |
| 101469 | + int nRight, /* As nRight */ |
| 101470 | + char **paOut, /* OUT: Results of merge (malloced) */ |
| 101471 | + int *pnOut /* OUT: Sized of output buffer */ |
| 101472 | +){ |
| 101473 | + char *aOut; |
| 101474 | + int rc; |
| 101475 | + |
| 101476 | + assert( mergetype==MERGE_POS_NEAR || MERGE_NEAR ); |
| 101477 | + |
| 101478 | + aOut = sqlite3_malloc(nLeft+nRight+1); |
| 101479 | + if( aOut==0 ){ |
| 101480 | + rc = SQLITE_NOMEM; |
| 101481 | + }else{ |
| 101482 | + rc = fts3DoclistMerge(mergetype, nNear+nTokenRight, nNear+nTokenLeft, |
| 101483 | + aOut, pnOut, aLeft, nLeft, aRight, nRight |
| 101484 | + ); |
| 101485 | + if( rc!=SQLITE_OK ){ |
| 101486 | + sqlite3_free(aOut); |
| 101487 | + aOut = 0; |
| 101488 | + } |
| 101489 | + } |
| 101490 | + |
| 101491 | + *paOut = aOut; |
| 101492 | + return rc; |
| 101493 | +} |
| 101494 | + |
| 101495 | +SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *pLeft, Fts3Expr *pRight, int nNear){ |
| 101496 | + int rc; |
| 101497 | + if( pLeft->aDoclist==0 || pRight->aDoclist==0 ){ |
| 101498 | + sqlite3_free(pLeft->aDoclist); |
| 101499 | + sqlite3_free(pRight->aDoclist); |
| 101500 | + pRight->aDoclist = 0; |
| 101501 | + pLeft->aDoclist = 0; |
| 101502 | + rc = SQLITE_OK; |
| 101503 | + }else{ |
| 101504 | + char *aOut; |
| 101505 | + int nOut; |
| 101506 | + |
| 101507 | + rc = fts3NearMerge(MERGE_POS_NEAR, nNear, |
| 101508 | + pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist, |
| 101509 | + pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist, |
| 101510 | + &aOut, &nOut |
| 101511 | + ); |
| 101512 | + if( rc!=SQLITE_OK ) return rc; |
| 101513 | + sqlite3_free(pRight->aDoclist); |
| 101514 | + pRight->aDoclist = aOut; |
| 101515 | + pRight->nDoclist = nOut; |
| 101516 | + |
| 101517 | + rc = fts3NearMerge(MERGE_POS_NEAR, nNear, |
| 101518 | + pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist, |
| 101519 | + pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist, |
| 101520 | + &aOut, &nOut |
| 101521 | + ); |
| 101522 | + sqlite3_free(pLeft->aDoclist); |
| 101523 | + pLeft->aDoclist = aOut; |
| 101524 | + pLeft->nDoclist = nOut; |
| 101525 | + } |
| 101526 | + return rc; |
| 101527 | +} |
| 100125 | 101528 | |
| 100126 | 101529 | /* |
| 100127 | 101530 | ** Evaluate the full-text expression pExpr against fts3 table pTab. Store |
| 100128 | 101531 | ** the resulting doclist in *paOut and *pnOut. |
| 100129 | 101532 | */ |
| | @@ -100165,13 +101568,10 @@ |
| 100165 | 101568 | switch( pExpr->eType ){ |
| 100166 | 101569 | case FTSQUERY_NEAR: { |
| 100167 | 101570 | Fts3Expr *pLeft; |
| 100168 | 101571 | Fts3Expr *pRight; |
| 100169 | 101572 | int mergetype = isReqPos ? MERGE_POS_NEAR : MERGE_NEAR; |
| 100170 | | - int nParam1; |
| 100171 | | - int nParam2; |
| 100172 | | - char *aBuffer; |
| 100173 | 101573 | |
| 100174 | 101574 | if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){ |
| 100175 | 101575 | mergetype = MERGE_POS_NEAR; |
| 100176 | 101576 | } |
| 100177 | 101577 | pLeft = pExpr->pLeft; |
| | @@ -100180,21 +101580,15 @@ |
| 100180 | 101580 | } |
| 100181 | 101581 | pRight = pExpr->pRight; |
| 100182 | 101582 | assert( pRight->eType==FTSQUERY_PHRASE ); |
| 100183 | 101583 | assert( pLeft->eType==FTSQUERY_PHRASE ); |
| 100184 | 101584 | |
| 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 |
| 101585 | + rc = fts3NearMerge(mergetype, pExpr->nNear, |
| 101586 | + pLeft->pPhrase->nToken, aLeft, nLeft, |
| 101587 | + pRight->pPhrase->nToken, aRight, nRight, |
| 101588 | + paOut, pnOut |
| 100190 | 101589 | ); |
| 100191 | | - if( rc!=SQLITE_OK ){ |
| 100192 | | - sqlite3_free(aBuffer); |
| 100193 | | - }else{ |
| 100194 | | - *paOut = aBuffer; |
| 100195 | | - } |
| 100196 | 101590 | sqlite3_free(aLeft); |
| 100197 | 101591 | break; |
| 100198 | 101592 | } |
| 100199 | 101593 | |
| 100200 | 101594 | case FTSQUERY_OR: { |
| | @@ -100441,11 +101835,11 @@ |
| 100441 | 101835 | return evalFts3Expr(pTab, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1); |
| 100442 | 101836 | } |
| 100443 | 101837 | |
| 100444 | 101838 | /* |
| 100445 | 101839 | ** After ExprLoadDoclist() (see above) has been called, this function is |
| 100446 | | -** used to iterate through the position lists that make up the doclist |
| 101840 | +** used to iterate/search through the position lists that make up the doclist |
| 100447 | 101841 | ** stored in pExpr->aDoclist. |
| 100448 | 101842 | */ |
| 100449 | 101843 | SQLITE_PRIVATE char *sqlite3Fts3FindPositions( |
| 100450 | 101844 | Fts3Expr *pExpr, /* Access this expressions doclist */ |
| 100451 | 101845 | sqlite3_int64 iDocid, /* Docid associated with requested pos-list */ |
| | @@ -100476,11 +101870,11 @@ |
| 100476 | 101870 | fts3ColumnlistCopy(0, &pCsr); |
| 100477 | 101871 | if( *pCsr==0x00 ) return 0; |
| 100478 | 101872 | pCsr++; |
| 100479 | 101873 | pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis); |
| 100480 | 101874 | } |
| 100481 | | - if( iCol==iThis ) return pCsr; |
| 101875 | + if( iCol==iThis && (*pCsr&0xFE) ) return pCsr; |
| 100482 | 101876 | } |
| 100483 | 101877 | return 0; |
| 100484 | 101878 | } |
| 100485 | 101879 | } |
| 100486 | 101880 | } |
| | @@ -100528,49 +101922,12 @@ |
| 100528 | 101922 | ){ |
| 100529 | 101923 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 100530 | 101924 | const char *zStart = "<b>"; |
| 100531 | 101925 | const char *zEnd = "</b>"; |
| 100532 | 101926 | 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 | 101927 | int iCol = -1; |
| 100571 | | - int nToken = 10; |
| 101928 | + int nToken = 15; /* Default number of tokens in snippet */ |
| 100572 | 101929 | |
| 100573 | 101930 | /* There must be at least one argument passed to this function (otherwise |
| 100574 | 101931 | ** the non-overloaded version would have been called instead of this one). |
| 100575 | 101932 | */ |
| 100576 | 101933 | assert( nVal>=1 ); |
| | @@ -100590,11 +101947,11 @@ |
| 100590 | 101947 | case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); |
| 100591 | 101948 | } |
| 100592 | 101949 | if( !zEllipsis || !zEnd || !zStart ){ |
| 100593 | 101950 | sqlite3_result_error_nomem(pContext); |
| 100594 | 101951 | }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ |
| 100595 | | - sqlite3Fts3Snippet2(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); |
| 101952 | + sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); |
| 100596 | 101953 | } |
| 100597 | 101954 | } |
| 100598 | 101955 | |
| 100599 | 101956 | /* |
| 100600 | 101957 | ** Implementation of the offsets() function for FTS3 |
| | @@ -100691,11 +102048,10 @@ |
| 100691 | 102048 | struct Overloaded { |
| 100692 | 102049 | const char *zName; |
| 100693 | 102050 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**); |
| 100694 | 102051 | } aOverload[] = { |
| 100695 | 102052 | { "snippet", fts3SnippetFunc }, |
| 100696 | | - { "snippet2", fts3Snippet2Func }, |
| 100697 | 102053 | { "offsets", fts3OffsetsFunc }, |
| 100698 | 102054 | { "optimize", fts3OptimizeFunc }, |
| 100699 | 102055 | { "matchinfo", fts3MatchinfoFunc }, |
| 100700 | 102056 | }; |
| 100701 | 102057 | int i; /* Iterator variable */ |
| | @@ -100720,26 +102076,39 @@ |
| 100720 | 102076 | */ |
| 100721 | 102077 | static int fts3RenameMethod( |
| 100722 | 102078 | sqlite3_vtab *pVtab, /* Virtual table handle */ |
| 100723 | 102079 | const char *zName /* New name of table */ |
| 100724 | 102080 | ){ |
| 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 | | - } |
| 102081 | + Fts3Table *p = (Fts3Table *)pVtab; |
| 102082 | + sqlite3 *db; /* Database connection */ |
| 102083 | + int rc; /* Return Code */ |
| 102084 | + |
| 102085 | + db = p->db; |
| 102086 | + rc = SQLITE_OK; |
| 102087 | + fts3DbExec(&rc, db, |
| 102088 | + "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", |
| 102089 | + p->zDb, p->zName, zName |
| 102090 | + ); |
| 102091 | + if( rc==SQLITE_ERROR ) rc = SQLITE_OK; |
| 102092 | + if( p->bHasDocsize ){ |
| 102093 | + fts3DbExec(&rc, db, |
| 102094 | + "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';", |
| 102095 | + p->zDb, p->zName, zName |
| 102096 | + ); |
| 102097 | + fts3DbExec(&rc, db, |
| 102098 | + "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';", |
| 102099 | + p->zDb, p->zName, zName |
| 102100 | + ); |
| 102101 | + } |
| 102102 | + fts3DbExec(&rc, db, |
| 102103 | + "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';", |
| 102104 | + p->zDb, p->zName, zName |
| 102105 | + ); |
| 102106 | + fts3DbExec(&rc, db, |
| 102107 | + "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';", |
| 102108 | + p->zDb, p->zName, zName |
| 102109 | + ); |
| 100741 | 102110 | return rc; |
| 100742 | 102111 | } |
| 100743 | 102112 | |
| 100744 | 102113 | static const sqlite3_module fts3Module = { |
| 100745 | 102114 | /* iVersion */ 0, |
| | @@ -100841,18 +102210,23 @@ |
| 100841 | 102210 | ** module with sqlite. |
| 100842 | 102211 | */ |
| 100843 | 102212 | if( SQLITE_OK==rc |
| 100844 | 102213 | && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) |
| 100845 | 102214 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) |
| 100846 | | - && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet2", -1)) |
| 100847 | 102215 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) |
| 100848 | 102216 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", -1)) |
| 100849 | 102217 | && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) |
| 100850 | 102218 | ){ |
| 100851 | | - return sqlite3_create_module_v2( |
| 102219 | + rc = sqlite3_create_module_v2( |
| 100852 | 102220 | db, "fts3", &fts3Module, (void *)pHash, hashDestroy |
| 100853 | 102221 | ); |
| 102222 | + if( rc==SQLITE_OK ){ |
| 102223 | + rc = sqlite3_create_module_v2( |
| 102224 | + db, "fts4", &fts3Module, (void *)pHash, 0 |
| 102225 | + ); |
| 102226 | + } |
| 102227 | + return rc; |
| 100854 | 102228 | } |
| 100855 | 102229 | |
| 100856 | 102230 | /* An error has occurred. Delete the hash table and return the error code. */ |
| 100857 | 102231 | assert( rc!=SQLITE_OK ); |
| 100858 | 102232 | if( pHash ){ |
| | @@ -102778,13 +104152,15 @@ |
| 102778 | 104152 | } |
| 102779 | 104153 | |
| 102780 | 104154 | if( c->iOffset>iStartOffset ){ |
| 102781 | 104155 | int n = c->iOffset-iStartOffset; |
| 102782 | 104156 | if( n>c->nAllocated ){ |
| 104157 | + char *pNew; |
| 102783 | 104158 | c->nAllocated = n+20; |
| 102784 | | - c->zToken = sqlite3_realloc(c->zToken, c->nAllocated); |
| 102785 | | - if( c->zToken==NULL ) return SQLITE_NOMEM; |
| 104159 | + pNew = sqlite3_realloc(c->zToken, c->nAllocated); |
| 104160 | + if( !pNew ) return SQLITE_NOMEM; |
| 104161 | + c->zToken = pNew; |
| 102786 | 104162 | } |
| 102787 | 104163 | porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); |
| 102788 | 104164 | *pzToken = c->zToken; |
| 102789 | 104165 | *piStartOffset = iStartOffset; |
| 102790 | 104166 | *piEndOffset = c->iOffset; |
| | @@ -103491,13 +104867,15 @@ |
| 103491 | 104867 | } |
| 103492 | 104868 | |
| 103493 | 104869 | if( c->iOffset>iStartOffset ){ |
| 103494 | 104870 | int i, n = c->iOffset-iStartOffset; |
| 103495 | 104871 | if( n>c->nTokenAllocated ){ |
| 104872 | + char *pNew; |
| 103496 | 104873 | c->nTokenAllocated = n+20; |
| 103497 | | - c->pToken = sqlite3_realloc(c->pToken, c->nTokenAllocated); |
| 103498 | | - if( c->pToken==NULL ) return SQLITE_NOMEM; |
| 104874 | + pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated); |
| 104875 | + if( !pNew ) return SQLITE_NOMEM; |
| 104876 | + c->pToken = pNew; |
| 103499 | 104877 | } |
| 103500 | 104878 | for(i=0; i<n; i++){ |
| 103501 | 104879 | /* TODO(shess) This needs expansion to handle UTF-8 |
| 103502 | 104880 | ** case-insensitivity. |
| 103503 | 104881 | */ |
| | @@ -103677,23 +105055,30 @@ |
| 103677 | 105055 | #define SQL_DELETE_CONTENT 0 |
| 103678 | 105056 | #define SQL_IS_EMPTY 1 |
| 103679 | 105057 | #define SQL_DELETE_ALL_CONTENT 2 |
| 103680 | 105058 | #define SQL_DELETE_ALL_SEGMENTS 3 |
| 103681 | 105059 | #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 |
| 105060 | +#define SQL_DELETE_ALL_DOCSIZE 5 |
| 105061 | +#define SQL_DELETE_ALL_STAT 6 |
| 105062 | +#define SQL_SELECT_CONTENT_BY_ROWID 7 |
| 105063 | +#define SQL_NEXT_SEGMENT_INDEX 8 |
| 105064 | +#define SQL_INSERT_SEGMENTS 9 |
| 105065 | +#define SQL_NEXT_SEGMENTS_ID 10 |
| 105066 | +#define SQL_INSERT_SEGDIR 11 |
| 105067 | +#define SQL_SELECT_LEVEL 12 |
| 105068 | +#define SQL_SELECT_ALL_LEVEL 13 |
| 105069 | +#define SQL_SELECT_LEVEL_COUNT 14 |
| 105070 | +#define SQL_SELECT_SEGDIR_COUNT_MAX 15 |
| 105071 | +#define SQL_DELETE_SEGDIR_BY_LEVEL 16 |
| 105072 | +#define SQL_DELETE_SEGMENTS_RANGE 17 |
| 105073 | +#define SQL_CONTENT_INSERT 18 |
| 105074 | +#define SQL_GET_BLOCK 19 |
| 105075 | +#define SQL_DELETE_DOCSIZE 20 |
| 105076 | +#define SQL_REPLACE_DOCSIZE 21 |
| 105077 | +#define SQL_SELECT_DOCSIZE 22 |
| 105078 | +#define SQL_SELECT_DOCTOTAL 23 |
| 105079 | +#define SQL_REPLACE_DOCTOTAL 24 |
| 103695 | 105080 | |
| 103696 | 105081 | /* |
| 103697 | 105082 | ** This function is used to obtain an SQLite prepared statement handle |
| 103698 | 105083 | ** for the statement identified by the second argument. If successful, |
| 103699 | 105084 | ** *pp is set to the requested statement handle and SQLITE_OK returned. |
| | @@ -103714,29 +105099,36 @@ |
| 103714 | 105099 | /* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?", |
| 103715 | 105100 | /* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)", |
| 103716 | 105101 | /* 2 */ "DELETE FROM %Q.'%q_content'", |
| 103717 | 105102 | /* 3 */ "DELETE FROM %Q.'%q_segments'", |
| 103718 | 105103 | /* 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(?,?,?,?,?,?)", |
| 105104 | +/* 5 */ "DELETE FROM %Q.'%q_docsize'", |
| 105105 | +/* 6 */ "DELETE FROM %Q.'%q_stat'", |
| 105106 | +/* 7 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?", |
| 105107 | +/* 8 */ "SELECT coalesce(max(idx)+1, 0) FROM %Q.'%q_segdir' WHERE level=?", |
| 105108 | +/* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", |
| 105109 | +/* 10 */ "SELECT coalesce(max(blockid)+1, 1) FROM %Q.'%q_segments'", |
| 105110 | +/* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", |
| 103724 | 105111 | |
| 103725 | 105112 | /* Return segments in order from oldest to newest.*/ |
| 103726 | | -/* 10 */ "SELECT idx, start_block, leaves_end_block, end_block, root " |
| 105113 | +/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root " |
| 103727 | 105114 | "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC", |
| 103728 | | -/* 11 */ "SELECT idx, start_block, leaves_end_block, end_block, root " |
| 105115 | +/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root " |
| 103729 | 105116 | "FROM %Q.'%q_segdir' ORDER BY level DESC, idx ASC", |
| 103730 | 105117 | |
| 103731 | | -/* 12 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", |
| 103732 | | -/* 13 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'", |
| 105118 | +/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", |
| 105119 | +/* 15 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'", |
| 103733 | 105120 | |
| 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 = ?", |
| 105121 | +/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?", |
| 105122 | +/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?", |
| 105123 | +/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%z)", |
| 105124 | +/* 19 */ "SELECT block FROM %Q.'%q_segments' WHERE blockid = ?", |
| 105125 | +/* 20 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", |
| 105126 | +/* 21 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", |
| 105127 | +/* 22 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", |
| 105128 | +/* 23 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0", |
| 105129 | +/* 24 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)", |
| 103738 | 105130 | }; |
| 103739 | 105131 | int rc = SQLITE_OK; |
| 103740 | 105132 | sqlite3_stmt *pStmt; |
| 103741 | 105133 | |
| 103742 | 105134 | assert( SizeofArray(azSql)==SizeofArray(p->aStmt) ); |
| | @@ -103789,18 +105181,25 @@ |
| 103789 | 105181 | ** is executed. |
| 103790 | 105182 | ** |
| 103791 | 105183 | ** Returns SQLITE_OK if the statement is successfully executed, or an |
| 103792 | 105184 | ** SQLite error code otherwise. |
| 103793 | 105185 | */ |
| 103794 | | -static int fts3SqlExec(Fts3Table *p, int eStmt, sqlite3_value **apVal){ |
| 105186 | +static void fts3SqlExec( |
| 105187 | + int *pRC, /* Result code */ |
| 105188 | + Fts3Table *p, /* The FTS3 table */ |
| 105189 | + int eStmt, /* Index of statement to evaluate */ |
| 105190 | + sqlite3_value **apVal /* Parameters to bind */ |
| 105191 | +){ |
| 103795 | 105192 | sqlite3_stmt *pStmt; |
| 103796 | | - int rc = fts3SqlStmt(p, eStmt, &pStmt, apVal); |
| 105193 | + int rc; |
| 105194 | + if( *pRC ) return; |
| 105195 | + rc = fts3SqlStmt(p, eStmt, &pStmt, apVal); |
| 103797 | 105196 | if( rc==SQLITE_OK ){ |
| 103798 | 105197 | sqlite3_step(pStmt); |
| 103799 | 105198 | rc = sqlite3_reset(pStmt); |
| 103800 | 105199 | } |
| 103801 | | - return rc; |
| 105200 | + *pRC = rc; |
| 103802 | 105201 | } |
| 103803 | 105202 | |
| 103804 | 105203 | |
| 103805 | 105204 | /* |
| 103806 | 105205 | ** Read a single block from the %_segments table. If the specified block |
| | @@ -103976,15 +105375,21 @@ |
| 103976 | 105375 | ** pending-terms hash-table. The docid used is that currently stored in |
| 103977 | 105376 | ** p->iPrevDocid, and the column is specified by argument iCol. |
| 103978 | 105377 | ** |
| 103979 | 105378 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. |
| 103980 | 105379 | */ |
| 103981 | | -static int fts3PendingTermsAdd(Fts3Table *p, const char *zText, int iCol){ |
| 105380 | +static int fts3PendingTermsAdd( |
| 105381 | + Fts3Table *p, /* FTS table into which text will be inserted */ |
| 105382 | + const char *zText, /* Text of document to be inseted */ |
| 105383 | + int iCol, /* Column number into which text is inserted */ |
| 105384 | + u32 *pnWord /* OUT: Number of tokens inserted */ |
| 105385 | +){ |
| 103982 | 105386 | int rc; |
| 103983 | 105387 | int iStart; |
| 103984 | 105388 | int iEnd; |
| 103985 | 105389 | int iPos; |
| 105390 | + int nWord = 0; |
| 103986 | 105391 | |
| 103987 | 105392 | char const *zToken; |
| 103988 | 105393 | int nToken; |
| 103989 | 105394 | |
| 103990 | 105395 | sqlite3_tokenizer *pTokenizer = p->pTokenizer; |
| | @@ -104004,10 +105409,12 @@ |
| 104004 | 105409 | xNext = pModule->xNext; |
| 104005 | 105410 | while( SQLITE_OK==rc |
| 104006 | 105411 | && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) |
| 104007 | 105412 | ){ |
| 104008 | 105413 | PendingList *pList; |
| 105414 | + |
| 105415 | + if( iPos>=nWord ) nWord = iPos+1; |
| 104009 | 105416 | |
| 104010 | 105417 | /* Positions cannot be negative; we use -1 as a terminator internally. |
| 104011 | 105418 | ** Tokens must have a non-zero length. |
| 104012 | 105419 | */ |
| 104013 | 105420 | if( iPos<0 || !zToken || nToken<=0 ){ |
| | @@ -104033,10 +105440,11 @@ |
| 104033 | 105440 | p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem)); |
| 104034 | 105441 | } |
| 104035 | 105442 | } |
| 104036 | 105443 | |
| 104037 | 105444 | pModule->xClose(pCsr); |
| 105445 | + *pnWord = nWord; |
| 104038 | 105446 | return (rc==SQLITE_DONE ? SQLITE_OK : rc); |
| 104039 | 105447 | } |
| 104040 | 105448 | |
| 104041 | 105449 | /* |
| 104042 | 105450 | ** Calling this function indicates that subsequent calls to |
| | @@ -104073,16 +105481,16 @@ |
| 104073 | 105481 | ** pendingTerms hash table. |
| 104074 | 105482 | ** |
| 104075 | 105483 | ** Argument apVal is the same as the similarly named argument passed to |
| 104076 | 105484 | ** fts3InsertData(). Parameter iDocid is the docid of the new row. |
| 104077 | 105485 | */ |
| 104078 | | -static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal){ |
| 105486 | +static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){ |
| 104079 | 105487 | int i; /* Iterator variable */ |
| 104080 | 105488 | for(i=2; i<p->nColumn+2; i++){ |
| 104081 | 105489 | const char *zText = (const char *)sqlite3_value_text(apVal[i]); |
| 104082 | 105490 | if( zText ){ |
| 104083 | | - int rc = fts3PendingTermsAdd(p, zText, i-2); |
| 105491 | + int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]); |
| 104084 | 105492 | if( rc!=SQLITE_OK ){ |
| 104085 | 105493 | return rc; |
| 104086 | 105494 | } |
| 104087 | 105495 | } |
| 104088 | 105496 | } |
| | @@ -104159,53 +105567,60 @@ |
| 104159 | 105567 | /* |
| 104160 | 105568 | ** Remove all data from the FTS3 table. Clear the hash table containing |
| 104161 | 105569 | ** pending terms. |
| 104162 | 105570 | */ |
| 104163 | 105571 | static int fts3DeleteAll(Fts3Table *p){ |
| 104164 | | - int rc; /* Return code */ |
| 105572 | + int rc = SQLITE_OK; /* Return code */ |
| 104165 | 105573 | |
| 104166 | 105574 | /* Discard the contents of the pending-terms hash table. */ |
| 104167 | 105575 | sqlite3Fts3PendingTermsClear(p); |
| 104168 | 105576 | |
| 104169 | 105577 | /* 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); |
| 105578 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0); |
| 105579 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0); |
| 105580 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); |
| 105581 | + if( p->bHasDocsize ){ |
| 105582 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0); |
| 105583 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); |
| 104176 | 105584 | } |
| 104177 | 105585 | return rc; |
| 104178 | 105586 | } |
| 104179 | 105587 | |
| 104180 | 105588 | /* |
| 104181 | 105589 | ** The first element in the apVal[] array is assumed to contain the docid |
| 104182 | 105590 | ** (an integer) of a row about to be deleted. Remove all terms from the |
| 104183 | 105591 | ** full-text index. |
| 104184 | 105592 | */ |
| 104185 | | -static int fts3DeleteTerms(Fts3Table *p, sqlite3_value **apVal){ |
| 105593 | +static void fts3DeleteTerms( |
| 105594 | + int *pRC, /* Result code */ |
| 105595 | + Fts3Table *p, /* The FTS table to delete from */ |
| 105596 | + sqlite3_value **apVal, /* apVal[] contains the docid to be deleted */ |
| 105597 | + u32 *aSz /* Sizes of deleted document written here */ |
| 105598 | +){ |
| 104186 | 105599 | int rc; |
| 104187 | 105600 | sqlite3_stmt *pSelect; |
| 104188 | 105601 | |
| 105602 | + if( *pRC ) return; |
| 104189 | 105603 | rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, apVal); |
| 104190 | 105604 | if( rc==SQLITE_OK ){ |
| 104191 | 105605 | if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
| 104192 | 105606 | int i; |
| 104193 | 105607 | for(i=1; i<=p->nColumn; i++){ |
| 104194 | 105608 | const char *zText = (const char *)sqlite3_column_text(pSelect, i); |
| 104195 | | - rc = fts3PendingTermsAdd(p, zText, -1); |
| 105609 | + rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]); |
| 104196 | 105610 | if( rc!=SQLITE_OK ){ |
| 104197 | 105611 | sqlite3_reset(pSelect); |
| 104198 | | - return rc; |
| 105612 | + *pRC = rc; |
| 105613 | + return; |
| 104199 | 105614 | } |
| 104200 | 105615 | } |
| 104201 | 105616 | } |
| 104202 | 105617 | rc = sqlite3_reset(pSelect); |
| 104203 | 105618 | }else{ |
| 104204 | 105619 | sqlite3_reset(pSelect); |
| 104205 | 105620 | } |
| 104206 | | - return rc; |
| 105621 | + *pRC = rc; |
| 104207 | 105622 | } |
| 104208 | 105623 | |
| 104209 | 105624 | /* |
| 104210 | 105625 | ** Forward declaration to account for the circular dependency between |
| 104211 | 105626 | ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). |
| | @@ -105321,11 +106736,11 @@ |
| 105321 | 106736 | sqlite3_bind_int(pDelete, 1, iLevel); |
| 105322 | 106737 | sqlite3_step(pDelete); |
| 105323 | 106738 | rc = sqlite3_reset(pDelete); |
| 105324 | 106739 | } |
| 105325 | 106740 | }else{ |
| 105326 | | - rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGDIR, 0); |
| 106741 | + fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); |
| 105327 | 106742 | } |
| 105328 | 106743 | |
| 105329 | 106744 | return rc; |
| 105330 | 106745 | } |
| 105331 | 106746 | |
| | @@ -105748,10 +107163,215 @@ |
| 105748 | 107163 | if( rc==SQLITE_OK ){ |
| 105749 | 107164 | sqlite3Fts3PendingTermsClear(p); |
| 105750 | 107165 | } |
| 105751 | 107166 | return rc; |
| 105752 | 107167 | } |
| 107168 | + |
| 107169 | +/* |
| 107170 | +** Encode N integers as varints into a blob. |
| 107171 | +*/ |
| 107172 | +static void fts3EncodeIntArray( |
| 107173 | + int N, /* The number of integers to encode */ |
| 107174 | + u32 *a, /* The integer values */ |
| 107175 | + char *zBuf, /* Write the BLOB here */ |
| 107176 | + int *pNBuf /* Write number of bytes if zBuf[] used here */ |
| 107177 | +){ |
| 107178 | + int i, j; |
| 107179 | + for(i=j=0; i<N; i++){ |
| 107180 | + j += sqlite3Fts3PutVarint(&zBuf[j], (sqlite3_int64)a[i]); |
| 107181 | + } |
| 107182 | + *pNBuf = j; |
| 107183 | +} |
| 107184 | + |
| 107185 | +/* |
| 107186 | +** Decode a blob of varints into N integers |
| 107187 | +*/ |
| 107188 | +static void fts3DecodeIntArray( |
| 107189 | + int N, /* The number of integers to decode */ |
| 107190 | + u32 *a, /* Write the integer values */ |
| 107191 | + const char *zBuf, /* The BLOB containing the varints */ |
| 107192 | + int nBuf /* size of the BLOB */ |
| 107193 | +){ |
| 107194 | + int i, j; |
| 107195 | + UNUSED_PARAMETER(nBuf); |
| 107196 | + for(i=j=0; i<N; i++){ |
| 107197 | + sqlite3_int64 x; |
| 107198 | + j += sqlite3Fts3GetVarint(&zBuf[j], &x); |
| 107199 | + assert(j<=nBuf); |
| 107200 | + a[i] = (u32)(x & 0xffffffff); |
| 107201 | + } |
| 107202 | +} |
| 107203 | + |
| 107204 | +/* |
| 107205 | +** Fill in the document size auxiliary information for the matchinfo |
| 107206 | +** structure. The auxiliary information is: |
| 107207 | +** |
| 107208 | +** N Total number of documents in the full-text index |
| 107209 | +** a0 Average length of column 0 over the whole index |
| 107210 | +** n0 Length of column 0 on the matching row |
| 107211 | +** ... |
| 107212 | +** aM Average length of column M over the whole index |
| 107213 | +** nM Length of column M on the matching row |
| 107214 | +** |
| 107215 | +** The fts3MatchinfoDocsizeLocal() routine fills in the nX values. |
| 107216 | +** The fts3MatchinfoDocsizeGlobal() routine fills in N and the aX values. |
| 107217 | +*/ |
| 107218 | +SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor *pCur, u32 *a){ |
| 107219 | + const char *pBlob; /* The BLOB holding %_docsize info */ |
| 107220 | + int nBlob; /* Size of the BLOB */ |
| 107221 | + sqlite3_stmt *pStmt; /* Statement for reading and writing */ |
| 107222 | + int i, j; /* Loop counters */ |
| 107223 | + sqlite3_int64 x; /* Varint value */ |
| 107224 | + int rc; /* Result code from subfunctions */ |
| 107225 | + Fts3Table *p; /* The FTS table */ |
| 107226 | + |
| 107227 | + p = (Fts3Table*)pCur->base.pVtab; |
| 107228 | + rc = fts3SqlStmt(p, SQL_SELECT_DOCSIZE, &pStmt, 0); |
| 107229 | + if( rc ){ |
| 107230 | + return rc; |
| 107231 | + } |
| 107232 | + sqlite3_bind_int64(pStmt, 1, pCur->iPrevId); |
| 107233 | + if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 107234 | + nBlob = sqlite3_column_bytes(pStmt, 0); |
| 107235 | + pBlob = (const char*)sqlite3_column_blob(pStmt, 0); |
| 107236 | + for(i=j=0; i<p->nColumn && j<nBlob; i++){ |
| 107237 | + j = sqlite3Fts3GetVarint(&pBlob[j], &x); |
| 107238 | + a[2+i*2] = (u32)(x & 0xffffffff); |
| 107239 | + } |
| 107240 | + } |
| 107241 | + sqlite3_reset(pStmt); |
| 107242 | + return SQLITE_OK; |
| 107243 | +} |
| 107244 | +SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor *pCur, u32 *a){ |
| 107245 | + const char *pBlob; /* The BLOB holding %_stat info */ |
| 107246 | + int nBlob; /* Size of the BLOB */ |
| 107247 | + sqlite3_stmt *pStmt; /* Statement for reading and writing */ |
| 107248 | + int i, j; /* Loop counters */ |
| 107249 | + sqlite3_int64 x; /* Varint value */ |
| 107250 | + int nDoc; /* Number of documents */ |
| 107251 | + int rc; /* Result code from subfunctions */ |
| 107252 | + Fts3Table *p; /* The FTS table */ |
| 107253 | + |
| 107254 | + p = (Fts3Table*)pCur->base.pVtab; |
| 107255 | + rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0); |
| 107256 | + if( rc ){ |
| 107257 | + return rc; |
| 107258 | + } |
| 107259 | + if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 107260 | + nBlob = sqlite3_column_bytes(pStmt, 0); |
| 107261 | + pBlob = (const char*)sqlite3_column_blob(pStmt, 0); |
| 107262 | + j = sqlite3Fts3GetVarint(pBlob, &x); |
| 107263 | + a[0] = nDoc = (u32)(x & 0xffffffff); |
| 107264 | + for(i=0; i<p->nColumn && j<nBlob; i++){ |
| 107265 | + j = sqlite3Fts3GetVarint(&pBlob[j], &x); |
| 107266 | + a[1+i*2] = ((u32)(x & 0xffffffff) + nDoc/2)/nDoc; |
| 107267 | + } |
| 107268 | + } |
| 107269 | + sqlite3_reset(pStmt); |
| 107270 | + return SQLITE_OK; |
| 107271 | +} |
| 107272 | + |
| 107273 | +/* |
| 107274 | +** Insert the sizes (in tokens) for each column of the document |
| 107275 | +** with docid equal to p->iPrevDocid. The sizes are encoded as |
| 107276 | +** a blob of varints. |
| 107277 | +*/ |
| 107278 | +static void fts3InsertDocsize( |
| 107279 | + int *pRC, /* Result code */ |
| 107280 | + Fts3Table *p, /* Table into which to insert */ |
| 107281 | + u32 *aSz /* Sizes of each column */ |
| 107282 | +){ |
| 107283 | + char *pBlob; /* The BLOB encoding of the document size */ |
| 107284 | + int nBlob; /* Number of bytes in the BLOB */ |
| 107285 | + sqlite3_stmt *pStmt; /* Statement used to insert the encoding */ |
| 107286 | + int rc; /* Result code from subfunctions */ |
| 107287 | + |
| 107288 | + if( *pRC ) return; |
| 107289 | + pBlob = sqlite3_malloc( 10*p->nColumn ); |
| 107290 | + if( pBlob==0 ){ |
| 107291 | + *pRC = SQLITE_NOMEM; |
| 107292 | + return; |
| 107293 | + } |
| 107294 | + fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob); |
| 107295 | + rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0); |
| 107296 | + if( rc ){ |
| 107297 | + sqlite3_free(pBlob); |
| 107298 | + *pRC = rc; |
| 107299 | + return; |
| 107300 | + } |
| 107301 | + sqlite3_bind_int64(pStmt, 1, p->iPrevDocid); |
| 107302 | + sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free); |
| 107303 | + sqlite3_step(pStmt); |
| 107304 | + *pRC = sqlite3_reset(pStmt); |
| 107305 | +} |
| 107306 | + |
| 107307 | +/* |
| 107308 | +** Update the 0 record of the %_stat table so that it holds a blob |
| 107309 | +** which contains the document count followed by the cumulative |
| 107310 | +** document sizes for all columns. |
| 107311 | +*/ |
| 107312 | +static void fts3UpdateDocTotals( |
| 107313 | + int *pRC, /* The result code */ |
| 107314 | + Fts3Table *p, /* Table being updated */ |
| 107315 | + u32 *aSzIns, /* Size increases */ |
| 107316 | + u32 *aSzDel, /* Size decreases */ |
| 107317 | + int nChng /* Change in the number of documents */ |
| 107318 | +){ |
| 107319 | + char *pBlob; /* Storage for BLOB written into %_stat */ |
| 107320 | + int nBlob; /* Size of BLOB written into %_stat */ |
| 107321 | + u32 *a; /* Array of integers that becomes the BLOB */ |
| 107322 | + sqlite3_stmt *pStmt; /* Statement for reading and writing */ |
| 107323 | + int i; /* Loop counter */ |
| 107324 | + int rc; /* Result code from subfunctions */ |
| 107325 | + |
| 107326 | + if( *pRC ) return; |
| 107327 | + a = sqlite3_malloc( (sizeof(u32)+10)*(p->nColumn+1) ); |
| 107328 | + if( a==0 ){ |
| 107329 | + *pRC = SQLITE_NOMEM; |
| 107330 | + return; |
| 107331 | + } |
| 107332 | + pBlob = (char*)&a[p->nColumn+1]; |
| 107333 | + rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0); |
| 107334 | + if( rc ){ |
| 107335 | + sqlite3_free(a); |
| 107336 | + *pRC = rc; |
| 107337 | + return; |
| 107338 | + } |
| 107339 | + if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 107340 | + fts3DecodeIntArray(p->nColumn+1, a, |
| 107341 | + sqlite3_column_blob(pStmt, 0), |
| 107342 | + sqlite3_column_bytes(pStmt, 0)); |
| 107343 | + }else{ |
| 107344 | + memset(a, 0, sizeof(u32)*(p->nColumn+1) ); |
| 107345 | + } |
| 107346 | + sqlite3_reset(pStmt); |
| 107347 | + if( nChng<0 && a[0]<(u32)(-nChng) ){ |
| 107348 | + a[0] = 0; |
| 107349 | + }else{ |
| 107350 | + a[0] += nChng; |
| 107351 | + } |
| 107352 | + for(i=0; i<p->nColumn; i++){ |
| 107353 | + u32 x = a[i+1]; |
| 107354 | + if( x+aSzIns[i] < aSzDel[i] ){ |
| 107355 | + x = 0; |
| 107356 | + }else{ |
| 107357 | + x = x + aSzIns[i] - aSzDel[i]; |
| 107358 | + } |
| 107359 | + a[i+1] = x; |
| 107360 | + } |
| 107361 | + fts3EncodeIntArray(p->nColumn+1, a, pBlob, &nBlob); |
| 107362 | + rc = fts3SqlStmt(p, SQL_REPLACE_DOCTOTAL, &pStmt, 0); |
| 107363 | + if( rc ){ |
| 107364 | + sqlite3_free(a); |
| 107365 | + *pRC = rc; |
| 107366 | + return; |
| 107367 | + } |
| 107368 | + sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC); |
| 107369 | + sqlite3_step(pStmt); |
| 107370 | + *pRC = sqlite3_reset(pStmt); |
| 107371 | + sqlite3_free(a); |
| 107372 | +} |
| 105753 | 107373 | |
| 105754 | 107374 | /* |
| 105755 | 107375 | ** Handle a 'special' INSERT of the form: |
| 105756 | 107376 | ** |
| 105757 | 107377 | ** "INSERT INTO tbl(tbl) VALUES(<expr>)" |
| | @@ -105800,11 +107420,20 @@ |
| 105800 | 107420 | ){ |
| 105801 | 107421 | Fts3Table *p = (Fts3Table *)pVtab; |
| 105802 | 107422 | int rc = SQLITE_OK; /* Return Code */ |
| 105803 | 107423 | int isRemove = 0; /* True for an UPDATE or DELETE */ |
| 105804 | 107424 | sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */ |
| 107425 | + u32 *aSzIns; /* Sizes of inserted documents */ |
| 107426 | + u32 *aSzDel; /* Sizes of deleted documents */ |
| 107427 | + int nChng = 0; /* Net change in number of documents */ |
| 105805 | 107428 | |
| 107429 | + |
| 107430 | + /* Allocate space to hold the change in document sizes */ |
| 107431 | + aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*p->nColumn*2 ); |
| 107432 | + if( aSzIns==0 ) return SQLITE_NOMEM; |
| 107433 | + aSzDel = &aSzIns[p->nColumn]; |
| 107434 | + memset(aSzIns, 0, sizeof(aSzIns[0])*p->nColumn*2); |
| 105806 | 107435 | |
| 105807 | 107436 | /* If this is a DELETE or UPDATE operation, remove the old record. */ |
| 105808 | 107437 | if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ |
| 105809 | 107438 | int isEmpty; |
| 105810 | 107439 | rc = fts3IsEmpty(p, apVal, &isEmpty); |
| | @@ -105817,19 +107446,20 @@ |
| 105817 | 107446 | rc = fts3DeleteAll(p); |
| 105818 | 107447 | }else{ |
| 105819 | 107448 | isRemove = 1; |
| 105820 | 107449 | iRemove = sqlite3_value_int64(apVal[0]); |
| 105821 | 107450 | 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 | | - } |
| 107451 | + fts3DeleteTerms(&rc, p, apVal, aSzDel); |
| 107452 | + fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, apVal); |
| 107453 | + if( p->bHasDocsize ){ |
| 107454 | + fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, apVal); |
| 107455 | + nChng--; |
| 105827 | 107456 | } |
| 105828 | 107457 | } |
| 105829 | 107458 | } |
| 105830 | 107459 | }else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){ |
| 107460 | + sqlite3_free(aSzIns); |
| 105831 | 107461 | return fts3SpecialInsert(p, apVal[p->nColumn+2]); |
| 105832 | 107462 | } |
| 105833 | 107463 | |
| 105834 | 107464 | /* If this is an INSERT or UPDATE operation, insert the new record. */ |
| 105835 | 107465 | if( nArg>1 && rc==SQLITE_OK ){ |
| | @@ -105836,14 +107466,23 @@ |
| 105836 | 107466 | rc = fts3InsertData(p, apVal, pRowid); |
| 105837 | 107467 | if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){ |
| 105838 | 107468 | rc = fts3PendingTermsDocid(p, *pRowid); |
| 105839 | 107469 | } |
| 105840 | 107470 | if( rc==SQLITE_OK ){ |
| 105841 | | - rc = fts3InsertTerms(p, apVal); |
| 107471 | + rc = fts3InsertTerms(p, apVal, aSzIns); |
| 107472 | + } |
| 107473 | + if( p->bHasDocsize ){ |
| 107474 | + nChng++; |
| 107475 | + fts3InsertDocsize(&rc, p, aSzIns); |
| 105842 | 107476 | } |
| 105843 | 107477 | } |
| 105844 | 107478 | |
| 107479 | + if( p->bHasDocsize ){ |
| 107480 | + fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); |
| 107481 | + } |
| 107482 | + |
| 107483 | + sqlite3_free(aSzIns); |
| 105845 | 107484 | return rc; |
| 105846 | 107485 | } |
| 105847 | 107486 | |
| 105848 | 107487 | /* |
| 105849 | 107488 | ** Flush any data in the pending-terms hash table to disk. If successful, |
| | @@ -105886,736 +107525,131 @@ |
| 105886 | 107525 | */ |
| 105887 | 107526 | |
| 105888 | 107527 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 105889 | 107528 | |
| 105890 | 107529 | |
| 105891 | | -typedef struct Snippet Snippet; |
| 105892 | 107530 | |
| 105893 | 107531 | /* |
| 105894 | | -** An instance of the following structure keeps track of generated |
| 105895 | | -** matching-word offset information and snippets. |
| 107532 | +** Used as an fts3ExprIterate() context when loading phrase doclists to |
| 107533 | +** Fts3Expr.aDoclist[]/nDoclist. |
| 105896 | 107534 | */ |
| 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) */ |
| 107535 | +typedef struct LoadDoclistCtx LoadDoclistCtx; |
| 107536 | +struct LoadDoclistCtx { |
| 107537 | + Fts3Table *pTab; /* FTS3 Table */ |
| 107538 | + int nPhrase; /* Number of phrases seen so far */ |
| 107539 | + int nToken; /* Number of tokens seen so far */ |
| 107540 | +}; |
| 107541 | + |
| 107542 | +/* |
| 107543 | +** The following types are used as part of the implementation of the |
| 107544 | +** fts3BestSnippet() routine. |
| 107545 | +*/ |
| 107546 | +typedef struct SnippetIter SnippetIter; |
| 107547 | +typedef struct SnippetPhrase SnippetPhrase; |
| 107548 | +typedef struct SnippetFragment SnippetFragment; |
| 107549 | + |
| 107550 | +struct SnippetIter { |
| 107551 | + Fts3Cursor *pCsr; /* Cursor snippet is being generated from */ |
| 107552 | + int iCol; /* Extract snippet from this column */ |
| 107553 | + int nSnippet; /* Requested snippet length (in tokens) */ |
| 107554 | + int nPhrase; /* Number of phrases in query */ |
| 107555 | + SnippetPhrase *aPhrase; /* Array of size nPhrase */ |
| 107556 | + int iCurrent; /* First token of current snippet */ |
| 107557 | +}; |
| 107558 | + |
| 107559 | +struct SnippetPhrase { |
| 107560 | + int nToken; /* Number of tokens in phrase */ |
| 107561 | + char *pList; /* Pointer to start of phrase position list */ |
| 107562 | + int iHead; /* Next value in position list */ |
| 107563 | + char *pHead; /* Position list data following iHead */ |
| 107564 | + int iTail; /* Next value in trailing position list */ |
| 107565 | + char *pTail; /* Position list data following iTail */ |
| 107566 | +}; |
| 107567 | + |
| 107568 | +struct SnippetFragment { |
| 107569 | + int iCol; /* Column snippet is extracted from */ |
| 107570 | + int iPos; /* Index of first token in snippet */ |
| 107571 | + u64 covered; /* Mask of query phrases covered */ |
| 107572 | + u64 hlmask; /* Mask of snippet terms to highlight */ |
| 107573 | +}; |
| 107574 | + |
| 107575 | +/* |
| 107576 | +** This type is used as an fts3ExprIterate() context object while |
| 107577 | +** accumulating the data returned by the matchinfo() function. |
| 107578 | +*/ |
| 107579 | +typedef struct MatchInfo MatchInfo; |
| 107580 | +struct MatchInfo { |
| 107581 | + Fts3Cursor *pCursor; /* FTS3 Cursor */ |
| 107582 | + int nCol; /* Number of columns in table */ |
| 107583 | + u32 *aMatchinfo; /* Pre-allocated buffer */ |
| 107584 | +}; |
| 107585 | + |
| 107586 | + |
| 107587 | + |
| 107588 | +/* |
| 107589 | +** The snippet() and offsets() functions both return text values. An instance |
| 107590 | +** of the following structure is used to accumulate those values while the |
| 107591 | +** functions are running. See fts3StringAppend() for details. |
| 107592 | +*/ |
| 107593 | +typedef struct StrBuffer StrBuffer; |
| 107594 | +struct StrBuffer { |
| 107595 | + char *z; /* Pointer to buffer containing string */ |
| 107596 | + int n; /* Length of z in bytes (excl. nul-term) */ |
| 107597 | + int nAlloc; /* Allocated size of buffer z in bytes */ |
| 105912 | 107598 | }; |
| 105913 | 107599 | |
| 105914 | 107600 | |
| 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 | | - |
| 107601 | +/* |
| 107602 | +** This function is used to help iterate through a position-list. A position |
| 107603 | +** list is a list of unique integers, sorted from smallest to largest. Each |
| 107604 | +** element of the list is represented by an FTS3 varint that takes the value |
| 107605 | +** of the difference between the current element and the previous one plus |
| 107606 | +** two. For example, to store the position-list: |
| 107607 | +** |
| 107608 | +** 4 9 113 |
| 107609 | +** |
| 107610 | +** the three varints: |
| 107611 | +** |
| 107612 | +** 6 7 106 |
| 107613 | +** |
| 107614 | +** are encoded. |
| 107615 | +** |
| 107616 | +** When this function is called, *pp points to the start of an element of |
| 107617 | +** the list. *piPos contains the value of the previous entry in the list. |
| 107618 | +** After it returns, *piPos contains the value of the next element of the |
| 107619 | +** list and *pp is advanced to the following varint. |
| 107620 | +*/ |
| 106612 | 107621 | static void fts3GetDeltaPosition(char **pp, int *piPos){ |
| 106613 | 107622 | int iVal; |
| 106614 | 107623 | *pp += sqlite3Fts3GetVarint32(*pp, &iVal); |
| 106615 | 107624 | *piPos += (iVal-2); |
| 106616 | 107625 | } |
| 107626 | + |
| 107627 | +/* |
| 107628 | +** Helper function for fts3ExprIterate() (see below). |
| 107629 | +*/ |
| 107630 | +static int fts3ExprIterate2( |
| 107631 | + Fts3Expr *pExpr, /* Expression to iterate phrases of */ |
| 107632 | + int *piPhrase, /* Pointer to phrase counter */ |
| 107633 | + int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ |
| 107634 | + void *pCtx /* Second argument to pass to callback */ |
| 107635 | +){ |
| 107636 | + int rc; /* Return code */ |
| 107637 | + int eType = pExpr->eType; /* Type of expression node pExpr */ |
| 107638 | + |
| 107639 | + if( eType!=FTSQUERY_PHRASE ){ |
| 107640 | + assert( pExpr->pLeft && pExpr->pRight ); |
| 107641 | + rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx); |
| 107642 | + if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){ |
| 107643 | + rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx); |
| 107644 | + } |
| 107645 | + }else{ |
| 107646 | + rc = x(pExpr, *piPhrase, pCtx); |
| 107647 | + (*piPhrase)++; |
| 107648 | + } |
| 107649 | + return rc; |
| 107650 | +} |
| 106617 | 107651 | |
| 106618 | 107652 | /* |
| 106619 | 107653 | ** Iterate through all phrase nodes in an FTS3 query, except those that |
| 106620 | 107654 | ** are part of a sub-tree that is the right-hand-side of a NOT operator. |
| 106621 | 107655 | ** For each phrase node found, the supplied callback function is invoked. |
| | @@ -106625,289 +107659,391 @@ |
| 106625 | 107659 | ** Otherwise, SQLITE_OK is returned after a callback has been made for |
| 106626 | 107660 | ** all eligible phrase nodes. |
| 106627 | 107661 | */ |
| 106628 | 107662 | static int fts3ExprIterate( |
| 106629 | 107663 | Fts3Expr *pExpr, /* Expression to iterate phrases of */ |
| 106630 | | - int (*x)(Fts3Expr *, void *), /* Callback function to invoke for phrases */ |
| 107664 | + int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ |
| 106631 | 107665 | void *pCtx /* Second argument to pass to callback */ |
| 106632 | 107666 | ){ |
| 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 | | - } |
| 107667 | + int iPhrase = 0; /* Variable used as the phrase counter */ |
| 107668 | + return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); |
| 107669 | +} |
| 107670 | + |
| 107671 | +/* |
| 107672 | +** The argument to this function is always a phrase node. Its doclist |
| 107673 | +** (Fts3Expr.aDoclist[]) and the doclists associated with all phrase nodes |
| 107674 | +** to the left of this one in the query tree have already been loaded. |
| 107675 | +** |
| 107676 | +** If this phrase node is part of a series of phrase nodes joined by |
| 107677 | +** NEAR operators (and is not the left-most of said series), then elements are |
| 107678 | +** removed from the phrases doclist consistent with the NEAR restriction. If |
| 107679 | +** required, elements may be removed from the doclists of phrases to the |
| 107680 | +** left of this one that are part of the same series of NEAR operator |
| 107681 | +** connected phrases. |
| 107682 | +** |
| 107683 | +** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK. |
| 107684 | +*/ |
| 107685 | +static int fts3ExprNearTrim(Fts3Expr *pExpr){ |
| 107686 | + int rc = SQLITE_OK; |
| 107687 | + Fts3Expr *pParent = pExpr->pParent; |
| 107688 | + |
| 107689 | + assert( pExpr->eType==FTSQUERY_PHRASE ); |
| 107690 | + while( rc==SQLITE_OK |
| 107691 | + && pParent |
| 107692 | + && pParent->eType==FTSQUERY_NEAR |
| 107693 | + && pParent->pRight==pExpr |
| 107694 | + ){ |
| 107695 | + /* This expression (pExpr) is the right-hand-side of a NEAR operator. |
| 107696 | + ** Find the expression to the left of the same operator. |
| 107697 | + */ |
| 107698 | + int nNear = pParent->nNear; |
| 107699 | + Fts3Expr *pLeft = pParent->pLeft; |
| 107700 | + |
| 107701 | + if( pLeft->eType!=FTSQUERY_PHRASE ){ |
| 107702 | + assert( pLeft->eType==FTSQUERY_NEAR ); |
| 107703 | + assert( pLeft->pRight->eType==FTSQUERY_PHRASE ); |
| 107704 | + pLeft = pLeft->pRight; |
| 107705 | + } |
| 107706 | + |
| 107707 | + rc = sqlite3Fts3ExprNearTrim(pLeft, pExpr, nNear); |
| 107708 | + |
| 107709 | + pExpr = pLeft; |
| 107710 | + pParent = pExpr->pParent; |
| 107711 | + } |
| 107712 | + |
| 106646 | 107713 | return rc; |
| 106647 | 107714 | } |
| 106648 | 107715 | |
| 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){ |
| 107716 | +/* |
| 107717 | +** This is an fts3ExprIterate() callback used while loading the doclists |
| 107718 | +** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also |
| 107719 | +** fts3ExprLoadDoclists(). |
| 107720 | +*/ |
| 107721 | +static int fts3ExprLoadDoclistsCb1(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 106656 | 107722 | int rc = SQLITE_OK; |
| 106657 | 107723 | LoadDoclistCtx *p = (LoadDoclistCtx *)ctx; |
| 107724 | + |
| 107725 | + UNUSED_PARAMETER(iPhrase); |
| 107726 | + |
| 106658 | 107727 | p->nPhrase++; |
| 107728 | + p->nToken += pExpr->pPhrase->nToken; |
| 107729 | + |
| 106659 | 107730 | if( pExpr->isLoaded==0 ){ |
| 106660 | 107731 | rc = sqlite3Fts3ExprLoadDoclist(p->pTab, pExpr); |
| 106661 | 107732 | pExpr->isLoaded = 1; |
| 106662 | | - if( rc==SQLITE_OK && pExpr->aDoclist ){ |
| 106663 | | - pExpr->pCurrent = pExpr->aDoclist; |
| 106664 | | - pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent,&pExpr->iCurrent); |
| 107733 | + if( rc==SQLITE_OK ){ |
| 107734 | + rc = fts3ExprNearTrim(pExpr); |
| 106665 | 107735 | } |
| 106666 | 107736 | } |
| 107737 | + |
| 106667 | 107738 | return rc; |
| 106668 | 107739 | } |
| 106669 | 107740 | |
| 106670 | | -static int fts3ExprLoadDoclists(Fts3Cursor *pCsr, int *pnPhrase){ |
| 106671 | | - int rc; |
| 106672 | | - LoadDoclistCtx sCtx = {0, 0}; |
| 107741 | +/* |
| 107742 | +** This is an fts3ExprIterate() callback used while loading the doclists |
| 107743 | +** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also |
| 107744 | +** fts3ExprLoadDoclists(). |
| 107745 | +*/ |
| 107746 | +static int fts3ExprLoadDoclistsCb2(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 107747 | + UNUSED_PARAMETER(iPhrase); |
| 107748 | + UNUSED_PARAMETER(ctx); |
| 107749 | + if( pExpr->aDoclist ){ |
| 107750 | + pExpr->pCurrent = pExpr->aDoclist; |
| 107751 | + pExpr->iCurrent = 0; |
| 107752 | + pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent, &pExpr->iCurrent); |
| 107753 | + } |
| 107754 | + return SQLITE_OK; |
| 107755 | +} |
| 107756 | + |
| 107757 | +/* |
| 107758 | +** Load the doclists for each phrase in the query associated with FTS3 cursor |
| 107759 | +** pCsr. |
| 107760 | +** |
| 107761 | +** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable |
| 107762 | +** phrases in the expression (all phrases except those directly or |
| 107763 | +** indirectly descended from the right-hand-side of a NOT operator). If |
| 107764 | +** pnToken is not NULL, then it is set to the number of tokens in all |
| 107765 | +** matchable phrases of the expression. |
| 107766 | +*/ |
| 107767 | +static int fts3ExprLoadDoclists( |
| 107768 | + Fts3Cursor *pCsr, /* Fts3 cursor for current query */ |
| 107769 | + int *pnPhrase, /* OUT: Number of phrases in query */ |
| 107770 | + int *pnToken /* OUT: Number of tokens in query */ |
| 107771 | +){ |
| 107772 | + int rc; /* Return Code */ |
| 107773 | + LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */ |
| 106673 | 107774 | sCtx.pTab = (Fts3Table *)pCsr->base.pVtab; |
| 106674 | | - rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx); |
| 106675 | | - *pnPhrase = sCtx.nPhrase; |
| 107775 | + rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb1, (void *)&sCtx); |
| 107776 | + if( rc==SQLITE_OK ){ |
| 107777 | + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb2, 0); |
| 107778 | + } |
| 107779 | + if( pnPhrase ) *pnPhrase = sCtx.nPhrase; |
| 107780 | + if( pnToken ) *pnToken = sCtx.nToken; |
| 106676 | 107781 | return rc; |
| 106677 | 107782 | } |
| 106678 | 107783 | |
| 106679 | 107784 | /* |
| 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. |
| 107785 | +** Advance the position list iterator specified by the first two |
| 107786 | +** arguments so that it points to the first element with a value greater |
| 107787 | +** than or equal to parameter iNext. |
| 106686 | 107788 | */ |
| 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++; |
| 107789 | +static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){ |
| 107790 | + char *pIter = *ppIter; |
| 107791 | + if( pIter ){ |
| 107792 | + int iIter = *piIter; |
| 107793 | + |
| 107794 | + while( iIter<iNext ){ |
| 107795 | + if( 0==(*pIter & 0xFE) ){ |
| 107796 | + iIter = -1; |
| 107797 | + pIter = 0; |
| 106716 | 107798 | break; |
| 106717 | 107799 | } |
| 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++; |
| 107800 | + fts3GetDeltaPosition(&pIter, &iIter); |
| 107801 | + } |
| 107802 | + |
| 107803 | + *piIter = iIter; |
| 107804 | + *ppIter = pIter; |
| 107805 | + } |
| 107806 | +} |
| 107807 | + |
| 107808 | +/* |
| 107809 | +** Advance the snippet iterator to the next candidate snippet. |
| 107810 | +*/ |
| 107811 | +static int fts3SnippetNextCandidate(SnippetIter *pIter){ |
| 107812 | + int i; /* Loop counter */ |
| 107813 | + |
| 107814 | + if( pIter->iCurrent<0 ){ |
| 107815 | + /* The SnippetIter object has just been initialized. The first snippet |
| 107816 | + ** candidate always starts at offset 0 (even if this candidate has a |
| 107817 | + ** score of 0.0). |
| 107818 | + */ |
| 107819 | + pIter->iCurrent = 0; |
| 107820 | + |
| 107821 | + /* Advance the 'head' iterator of each phrase to the first offset that |
| 107822 | + ** is greater than or equal to (iNext+nSnippet). |
| 107823 | + */ |
| 107824 | + for(i=0; i<pIter->nPhrase; i++){ |
| 107825 | + SnippetPhrase *pPhrase = &pIter->aPhrase[i]; |
| 107826 | + fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet); |
| 107827 | + } |
| 107828 | + }else{ |
| 107829 | + int iStart; |
| 107830 | + int iEnd = 0x7FFFFFFF; |
| 107831 | + |
| 107832 | + for(i=0; i<pIter->nPhrase; i++){ |
| 107833 | + SnippetPhrase *pPhrase = &pIter->aPhrase[i]; |
| 107834 | + if( pPhrase->pHead && pPhrase->iHead<iEnd ){ |
| 107835 | + iEnd = pPhrase->iHead; |
| 107836 | + } |
| 107837 | + } |
| 107838 | + if( iEnd==0x7FFFFFFF ){ |
| 107839 | + return 1; |
| 107840 | + } |
| 107841 | + |
| 107842 | + pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1; |
| 107843 | + for(i=0; i<pIter->nPhrase; i++){ |
| 107844 | + SnippetPhrase *pPhrase = &pIter->aPhrase[i]; |
| 107845 | + fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1); |
| 107846 | + fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart); |
| 107847 | + } |
| 107848 | + } |
| 107849 | + |
| 107850 | + return 0; |
| 107851 | +} |
| 107852 | + |
| 107853 | +/* |
| 107854 | +** Retrieve information about the current candidate snippet of snippet |
| 107855 | +** iterator pIter. |
| 107856 | +*/ |
| 107857 | +static void fts3SnippetDetails( |
| 107858 | + SnippetIter *pIter, /* Snippet iterator */ |
| 107859 | + u64 mCovered, /* Bitmask of phrases already covered */ |
| 107860 | + int *piToken, /* OUT: First token of proposed snippet */ |
| 107861 | + int *piScore, /* OUT: "Score" for this snippet */ |
| 107862 | + u64 *pmCover, /* OUT: Bitmask of phrases covered */ |
| 107863 | + u64 *pmHighlight /* OUT: Bitmask of terms to highlight */ |
| 107864 | +){ |
| 107865 | + int iStart = pIter->iCurrent; /* First token of snippet */ |
| 107866 | + int iScore = 0; /* Score of this snippet */ |
| 107867 | + int i; /* Loop counter */ |
| 107868 | + u64 mCover = 0; /* Mask of phrases covered by this snippet */ |
| 107869 | + u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */ |
| 107870 | + |
| 107871 | + for(i=0; i<pIter->nPhrase; i++){ |
| 107872 | + SnippetPhrase *pPhrase = &pIter->aPhrase[i]; |
| 107873 | + if( pPhrase->pTail ){ |
| 107874 | + char *pCsr = pPhrase->pTail; |
| 107875 | + int iCsr = pPhrase->iTail; |
| 107876 | + |
| 107877 | + while( iCsr<(iStart+pIter->nSnippet) ){ |
| 107878 | + int j; |
| 107879 | + u64 mPhrase = (u64)1 << i; |
| 107880 | + u64 mPos = (u64)1 << (iCsr - iStart); |
| 107881 | + assert( iCsr>=iStart ); |
| 107882 | + if( (mCover|mCovered)&mPhrase ){ |
| 107883 | + iScore++; |
| 107884 | + }else{ |
| 107885 | + iScore += 1000; |
| 107886 | + } |
| 107887 | + mCover |= mPhrase; |
| 107888 | + |
| 107889 | + for(j=0; j<pPhrase->nToken; j++){ |
| 107890 | + mHighlight |= (mPos>>j); |
| 107891 | + } |
| 107892 | + |
| 107893 | + if( 0==(*pCsr & 0x0FE) ) break; |
| 107894 | + fts3GetDeltaPosition(&pCsr, &iCsr); |
| 107895 | + } |
| 107896 | + } |
| 107897 | + } |
| 107898 | + |
| 107899 | + /* Set the output variables before returning. */ |
| 107900 | + *piToken = iStart; |
| 107901 | + *piScore = iScore; |
| 107902 | + *pmCover = mCover; |
| 107903 | + *pmHighlight = mHighlight; |
| 107904 | +} |
| 107905 | + |
| 107906 | +/* |
| 107907 | +** This function is an fts3ExprIterate() callback used by fts3BestSnippet(). |
| 107908 | +** Each invocation populates an element of the SnippetIter.aPhrase[] array. |
| 107909 | +*/ |
| 107910 | +static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 107911 | + SnippetIter *p = (SnippetIter *)ctx; |
| 107912 | + SnippetPhrase *pPhrase = &p->aPhrase[iPhrase]; |
| 106741 | 107913 | char *pCsr; |
| 106742 | 107914 | |
| 106743 | | - p->anToken[iPhrase] = pExpr->pPhrase->nToken; |
| 107915 | + pPhrase->nToken = pExpr->pPhrase->nToken; |
| 107916 | + |
| 106744 | 107917 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCsr->iPrevId, p->iCol); |
| 106745 | | - |
| 106746 | 107918 | if( pCsr ){ |
| 106747 | | - int iVal; |
| 106748 | | - pCsr += sqlite3Fts3GetVarint32(pCsr, &iVal); |
| 106749 | | - p->apList[iPhrase] = pCsr; |
| 106750 | | - p->aiPrev[iPhrase] = iVal-2; |
| 107919 | + int iFirst = 0; |
| 107920 | + pPhrase->pList = pCsr; |
| 107921 | + fts3GetDeltaPosition(&pCsr, &iFirst); |
| 107922 | + pPhrase->pHead = pCsr; |
| 107923 | + pPhrase->pTail = pCsr; |
| 107924 | + pPhrase->iHead = iFirst; |
| 107925 | + pPhrase->iTail = iFirst; |
| 107926 | + }else{ |
| 107927 | + assert( pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 ); |
| 106751 | 107928 | } |
| 107929 | + |
| 106752 | 107930 | return SQLITE_OK; |
| 106753 | 107931 | } |
| 106754 | 107932 | |
| 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 | | - |
| 107933 | +/* |
| 107934 | +** Select the fragment of text consisting of nFragment contiguous tokens |
| 107935 | +** from column iCol that represent the "best" snippet. The best snippet |
| 107936 | +** is the snippet with the highest score, where scores are calculated |
| 107937 | +** by adding: |
| 107938 | +** |
| 107939 | +** (a) +1 point for each occurence of a matchable phrase in the snippet. |
| 107940 | +** |
| 107941 | +** (b) +1000 points for the first occurence of each matchable phrase in |
| 107942 | +** the snippet for which the corresponding mCovered bit is not set. |
| 107943 | +** |
| 107944 | +** The selected snippet parameters are stored in structure *pFragment before |
| 107945 | +** returning. The score of the selected snippet is stored in *piScore |
| 107946 | +** before returning. |
| 107947 | +*/ |
| 106795 | 107948 | static int fts3BestSnippet( |
| 106796 | 107949 | int nSnippet, /* Desired snippet length */ |
| 106797 | 107950 | Fts3Cursor *pCsr, /* Cursor to create snippet for */ |
| 106798 | 107951 | 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 */ |
| 107952 | + u64 mCovered, /* Mask of phrases already covered */ |
| 107953 | + u64 *pmSeen, /* IN/OUT: Mask of phrases seen */ |
| 107954 | + SnippetFragment *pFragment, /* OUT: Best snippet found */ |
| 107955 | + int *piScore /* OUT: Score of snippet pFragment */ |
| 106801 | 107956 | ){ |
| 106802 | 107957 | 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; |
| 107958 | + int nList; /* Number of phrases in expression */ |
| 107959 | + SnippetIter sIter; /* Iterates through snippet candidates */ |
| 107960 | + int nByte; /* Number of bytes of space to allocate */ |
| 107961 | + int iBestScore = -1; /* Best snippet score found so far */ |
| 107962 | + int i; /* Loop counter */ |
| 107963 | + |
| 107964 | + memset(&sIter, 0, sizeof(sIter)); |
| 106817 | 107965 | |
| 106818 | 107966 | /* Iterate through the phrases in the expression to count them. The same |
| 106819 | 107967 | ** callback makes sure the doclists are loaded for each phrase. |
| 106820 | 107968 | */ |
| 106821 | | - rc = fts3ExprLoadDoclists(pCsr, &nList); |
| 107969 | + rc = fts3ExprLoadDoclists(pCsr, &nList, 0); |
| 106822 | 107970 | if( rc!=SQLITE_OK ){ |
| 106823 | 107971 | return rc; |
| 106824 | 107972 | } |
| 106825 | 107973 | |
| 106826 | 107974 | /* Now that it is known how many phrases there are, allocate and zero |
| 106827 | | - ** the required arrays using malloc(). |
| 107975 | + ** the required space using malloc(). |
| 106828 | 107976 | */ |
| 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 ){ |
| 107977 | + nByte = sizeof(SnippetPhrase) * nList; |
| 107978 | + sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte); |
| 107979 | + if( !sIter.aPhrase ){ |
| 106836 | 107980 | return SQLITE_NOMEM; |
| 106837 | 107981 | } |
| 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++){ |
| 107982 | + memset(sIter.aPhrase, 0, nByte); |
| 107983 | + |
| 107984 | + /* Initialize the contents of the SnippetIter object. Then iterate through |
| 107985 | + ** the set of phrases in the expression to populate the aPhrase[] array. |
| 107986 | + */ |
| 107987 | + sIter.pCsr = pCsr; |
| 107988 | + sIter.iCol = iCol; |
| 107989 | + sIter.nSnippet = nSnippet; |
| 107990 | + sIter.nPhrase = nList; |
| 107991 | + sIter.iCurrent = -1; |
| 107992 | + (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter); |
| 107993 | + |
| 107994 | + /* Set the *pmSeen output variable. */ |
| 107995 | + for(i=0; i<nList; i++){ |
| 107996 | + if( sIter.aPhrase[i].pHead ){ |
| 107997 | + *pmSeen |= (u64)1 << i; |
| 107998 | + } |
| 107999 | + } |
| 108000 | + |
| 108001 | + /* Loop through all candidate snippets. Store the best snippet in |
| 108002 | + ** *pFragment. Store its associated 'score' in iBestScore. |
| 108003 | + */ |
| 108004 | + pFragment->iCol = iCol; |
| 108005 | + while( !fts3SnippetNextCandidate(&sIter) ){ |
| 108006 | + int iPos; |
| 106866 | 108007 | 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); |
| 108008 | + u64 mCover; |
| 108009 | + u64 mHighlight; |
| 108010 | + fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight); |
| 108011 | + assert( iScore>=0 ); |
| 106880 | 108012 | if( iScore>iBestScore ){ |
| 106881 | | - iBestPos = i; |
| 108013 | + pFragment->iPos = iPos; |
| 108014 | + pFragment->hlmask = mHighlight; |
| 108015 | + pFragment->covered = mCover; |
| 106882 | 108016 | iBestScore = iScore; |
| 106883 | | - besthlmask = hlmask; |
| 106884 | 108017 | } |
| 106885 | 108018 | } |
| 106886 | 108019 | |
| 106887 | | - sqlite3_free(apList); |
| 106888 | | - *piPos = iBestPos; |
| 106889 | | - *pHlmask = besthlmask; |
| 108020 | + sqlite3_free(sIter.aPhrase); |
| 108021 | + *piScore = iBestScore; |
| 106890 | 108022 | return SQLITE_OK; |
| 106891 | 108023 | } |
| 106892 | 108024 | |
| 106893 | | -typedef struct StrBuffer StrBuffer; |
| 106894 | | -struct StrBuffer { |
| 106895 | | - char *z; |
| 106896 | | - int n; |
| 106897 | | - int nAlloc; |
| 106898 | | -}; |
| 106899 | 108025 | |
| 108026 | +/* |
| 108027 | +** Append a string to the string-buffer passed as the first argument. |
| 108028 | +** |
| 108029 | +** If nAppend is negative, then the length of the string zAppend is |
| 108030 | +** determined using strlen(). |
| 108031 | +*/ |
| 106900 | 108032 | static int fts3StringAppend( |
| 106901 | | - StrBuffer *pStr, |
| 106902 | | - const char *zAppend, |
| 106903 | | - int nAppend |
| 108033 | + StrBuffer *pStr, /* Buffer to append to */ |
| 108034 | + const char *zAppend, /* Pointer to data to append to buffer */ |
| 108035 | + int nAppend /* Size of zAppend in bytes (or -1) */ |
| 106904 | 108036 | ){ |
| 106905 | 108037 | if( nAppend<0 ){ |
| 106906 | | - nAppend = strlen(zAppend); |
| 108038 | + nAppend = (int)strlen(zAppend); |
| 106907 | 108039 | } |
| 106908 | 108040 | |
| 108041 | + /* If there is insufficient space allocated at StrBuffer.z, use realloc() |
| 108042 | + ** to grow the buffer until so that it is big enough to accomadate the |
| 108043 | + ** appended data. |
| 108044 | + */ |
| 106909 | 108045 | if( pStr->n+nAppend+1>=pStr->nAlloc ){ |
| 106910 | 108046 | int nAlloc = pStr->nAlloc+nAppend+100; |
| 106911 | 108047 | char *zNew = sqlite3_realloc(pStr->z, nAlloc); |
| 106912 | 108048 | if( !zNew ){ |
| 106913 | 108049 | return SQLITE_NOMEM; |
| | @@ -106914,137 +108050,213 @@ |
| 106914 | 108050 | } |
| 106915 | 108051 | pStr->z = zNew; |
| 106916 | 108052 | pStr->nAlloc = nAlloc; |
| 106917 | 108053 | } |
| 106918 | 108054 | |
| 108055 | + /* Append the data to the string buffer. */ |
| 106919 | 108056 | memcpy(&pStr->z[pStr->n], zAppend, nAppend); |
| 106920 | 108057 | pStr->n += nAppend; |
| 106921 | 108058 | pStr->z[pStr->n] = '\0'; |
| 106922 | 108059 | |
| 106923 | 108060 | return SQLITE_OK; |
| 106924 | 108061 | } |
| 106925 | 108062 | |
| 108063 | +/* |
| 108064 | +** The fts3BestSnippet() function often selects snippets that end with a |
| 108065 | +** query term. That is, the final term of the snippet is always a term |
| 108066 | +** that requires highlighting. For example, if 'X' is a highlighted term |
| 108067 | +** and '.' is a non-highlighted term, BestSnippet() may select: |
| 108068 | +** |
| 108069 | +** ........X.....X |
| 108070 | +** |
| 108071 | +** This function "shifts" the beginning of the snippet forward in the |
| 108072 | +** document so that there are approximately the same number of |
| 108073 | +** non-highlighted terms to the right of the final highlighted term as there |
| 108074 | +** are to the left of the first highlighted term. For example, to this: |
| 108075 | +** |
| 108076 | +** ....X.....X.... |
| 108077 | +** |
| 108078 | +** This is done as part of extracting the snippet text, not when selecting |
| 108079 | +** the snippet. Snippet selection is done based on doclists only, so there |
| 108080 | +** is no way for fts3BestSnippet() to know whether or not the document |
| 108081 | +** actually contains terms that follow the final highlighted term. |
| 108082 | +*/ |
| 108083 | +int fts3SnippetShift( |
| 108084 | + Fts3Table *pTab, /* FTS3 table snippet comes from */ |
| 108085 | + int nSnippet, /* Number of tokens desired for snippet */ |
| 108086 | + const char *zDoc, /* Document text to extract snippet from */ |
| 108087 | + int nDoc, /* Size of buffer zDoc in bytes */ |
| 108088 | + int *piPos, /* IN/OUT: First token of snippet */ |
| 108089 | + u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */ |
| 108090 | +){ |
| 108091 | + u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */ |
| 108092 | + |
| 108093 | + if( hlmask ){ |
| 108094 | + int nLeft; /* Tokens to the left of first highlight */ |
| 108095 | + int nRight; /* Tokens to the right of last highlight */ |
| 108096 | + int nDesired; /* Ideal number of tokens to shift forward */ |
| 108097 | + |
| 108098 | + for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++); |
| 108099 | + for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++); |
| 108100 | + nDesired = (nLeft-nRight)/2; |
| 108101 | + |
| 108102 | + /* Ideally, the start of the snippet should be pushed forward in the |
| 108103 | + ** document nDesired tokens. This block checks if there are actually |
| 108104 | + ** nDesired tokens to the right of the snippet. If so, *piPos and |
| 108105 | + ** *pHlMask are updated to shift the snippet nDesired tokens to the |
| 108106 | + ** right. Otherwise, the snippet is shifted by the number of tokens |
| 108107 | + ** available. |
| 108108 | + */ |
| 108109 | + if( nDesired>0 ){ |
| 108110 | + int nShift; /* Number of tokens to shift snippet by */ |
| 108111 | + int iCurrent = 0; /* Token counter */ |
| 108112 | + int rc; /* Return Code */ |
| 108113 | + sqlite3_tokenizer_module *pMod; |
| 108114 | + sqlite3_tokenizer_cursor *pC; |
| 108115 | + pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 108116 | + |
| 108117 | + /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) |
| 108118 | + ** or more tokens in zDoc/nDoc. |
| 108119 | + */ |
| 108120 | + rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 108121 | + if( rc!=SQLITE_OK ){ |
| 108122 | + return rc; |
| 108123 | + } |
| 108124 | + pC->pTokenizer = pTab->pTokenizer; |
| 108125 | + while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ |
| 108126 | + const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3; |
| 108127 | + rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); |
| 108128 | + } |
| 108129 | + pMod->xClose(pC); |
| 108130 | + if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; } |
| 108131 | + |
| 108132 | + nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet; |
| 108133 | + assert( nShift<=nDesired ); |
| 108134 | + if( nShift>0 ){ |
| 108135 | + *piPos += nShift; |
| 108136 | + *pHlmask = hlmask >> nShift; |
| 108137 | + } |
| 108138 | + } |
| 108139 | + } |
| 108140 | + return SQLITE_OK; |
| 108141 | +} |
| 108142 | + |
| 108143 | +/* |
| 108144 | +** Extract the snippet text for fragment pFragment from cursor pCsr and |
| 108145 | +** append it to string buffer pOut. |
| 108146 | +*/ |
| 106926 | 108147 | static int fts3SnippetText( |
| 106927 | 108148 | Fts3Cursor *pCsr, /* FTS3 Cursor */ |
| 106928 | | - const char *zDoc, /* Document to extract snippet from */ |
| 106929 | | - int nDoc, /* Size of zDoc in bytes */ |
| 108149 | + SnippetFragment *pFragment, /* Snippet to extract */ |
| 108150 | + int iFragment, /* Fragment number */ |
| 108151 | + int isLast, /* True for final fragment in snippet */ |
| 106930 | 108152 | 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 | 108153 | const char *zOpen, /* String inserted before highlighted term */ |
| 106934 | 108154 | const char *zClose, /* String inserted after highlighted term */ |
| 106935 | | - const char *zEllipsis, |
| 106936 | | - char **pzSnippet /* OUT: Snippet text */ |
| 108155 | + const char *zEllipsis, /* String inserted between snippets */ |
| 108156 | + StrBuffer *pOut /* Write output here */ |
| 106937 | 108157 | ){ |
| 106938 | 108158 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 106939 | 108159 | int rc; /* Return code */ |
| 106940 | | - int iCurrent = 0; |
| 106941 | | - int iStart = 0; |
| 106942 | | - int iEnd; |
| 106943 | | - |
| 108160 | + const char *zDoc; /* Document text to extract snippet from */ |
| 108161 | + int nDoc; /* Size of zDoc in bytes */ |
| 108162 | + int iCurrent = 0; /* Current token number of document */ |
| 108163 | + int iEnd = 0; /* Byte offset of end of current token */ |
| 108164 | + int isShiftDone = 0; /* True after snippet is shifted */ |
| 108165 | + int iPos = pFragment->iPos; /* First token of snippet */ |
| 108166 | + u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ |
| 108167 | + int iCol = pFragment->iCol+1; /* Query column to extract text from */ |
| 106944 | 108168 | sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ |
| 106945 | 108169 | 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 | | - */ |
| 108170 | + const char *ZDUMMY; /* Dummy argument used with tokenizer */ |
| 108171 | + int DUMMY1; /* Dummy argument used with tokenizer */ |
| 108172 | + |
| 108173 | + zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); |
| 108174 | + if( zDoc==0 ){ |
| 108175 | + if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ |
| 108176 | + return SQLITE_NOMEM; |
| 108177 | + } |
| 108178 | + return SQLITE_OK; |
| 108179 | + } |
| 108180 | + nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); |
| 108181 | + |
| 108182 | + /* Open a token cursor on the document. */ |
| 106955 | 108183 | pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; |
| 106956 | 108184 | 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 | | - } |
| 108185 | + if( rc!=SQLITE_OK ){ |
| 108186 | + return rc; |
| 108187 | + } |
| 108188 | + pC->pTokenizer = pTab->pTokenizer; |
| 106965 | 108189 | |
| 106966 | 108190 | while( rc==SQLITE_OK ){ |
| 106967 | | - int iBegin; |
| 106968 | | - int iFin; |
| 108191 | + int iBegin; /* Offset in zDoc of start of token */ |
| 108192 | + int iFin; /* Offset in zDoc of end of token */ |
| 108193 | + int isHighlight; /* True for highlighted terms */ |
| 108194 | + |
| 106969 | 108195 | 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 | | - } |
| 108196 | + if( rc!=SQLITE_OK ){ |
| 108197 | + if( rc==SQLITE_DONE ){ |
| 108198 | + /* Special case - the last token of the snippet is also the last token |
| 108199 | + ** of the column. Append any punctuation that occurred between the end |
| 108200 | + ** of the previous token and the end of the document to the output. |
| 108201 | + ** Then break out of the loop. */ |
| 108202 | + rc = fts3StringAppend(pOut, &zDoc[iEnd], -1); |
| 108203 | + } |
| 108204 | + break; |
| 108205 | + } |
| 108206 | + if( iCurrent<iPos ){ continue; } |
| 108207 | + |
| 108208 | + if( !isShiftDone ){ |
| 108209 | + int n = nDoc - iBegin; |
| 108210 | + rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask); |
| 108211 | + isShiftDone = 1; |
| 108212 | + |
| 108213 | + /* Now that the shift has been done, check if the initial "..." are |
| 108214 | + ** required. They are required if (a) this is not the first fragment, |
| 108215 | + ** or (b) this fragment does not begin at position 0 of its column. |
| 108216 | + */ |
| 108217 | + if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){ |
| 108218 | + rc = fts3StringAppend(pOut, zEllipsis, -1); |
| 108219 | + } |
| 108220 | + if( rc!=SQLITE_OK || iCurrent<iPos ) continue; |
| 108221 | + } |
| 108222 | + |
| 108223 | + if( iCurrent>=(iPos+nSnippet) ){ |
| 108224 | + if( isLast ){ |
| 108225 | + rc = fts3StringAppend(pOut, zEllipsis, -1); |
| 108226 | + } |
| 108227 | + break; |
| 108228 | + } |
| 108229 | + |
| 108230 | + /* Set isHighlight to true if this term should be highlighted. */ |
| 108231 | + isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0; |
| 108232 | + |
| 108233 | + if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd); |
| 108234 | + if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1); |
| 108235 | + if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin); |
| 108236 | + if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1); |
| 108237 | + |
| 108238 | + iEnd = iFin; |
| 107000 | 108239 | } |
| 107001 | 108240 | |
| 107002 | 108241 | pMod->xClose(pC); |
| 107003 | | - if( rc!=SQLITE_OK ){ |
| 107004 | | - sqlite3_free(res.z); |
| 107005 | | - }else{ |
| 107006 | | - *pzSnippet = res.z; |
| 107007 | | - } |
| 107008 | 108242 | return rc; |
| 107009 | 108243 | } |
| 107010 | 108244 | |
| 107011 | 108245 | |
| 107012 | 108246 | /* |
| 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). |
| 108247 | +** This function is used to count the entries in a column-list (a |
| 108248 | +** delta-encoded list of term offsets within a single column of a single |
| 108249 | +** row). When this function is called, *ppCollist should point to the |
| 108250 | +** beginning of the first varint in the column-list (the varint that |
| 108251 | +** contains the position of the first matching term in the column data). |
| 108252 | +** Before returning, *ppCollist is set to point to the first byte after |
| 108253 | +** the last varint in the column-list (either the 0x00 signifying the end |
| 108254 | +** of the position-list, or the 0x01 that precedes the column number of |
| 108255 | +** the next column in the position-list). |
| 108256 | +** |
| 108257 | +** The number of elements in the column-list is returned. |
| 107046 | 108258 | */ |
| 107047 | 108259 | static int fts3ColumnlistCount(char **ppCollist){ |
| 107048 | 108260 | char *pEnd = *ppCollist; |
| 107049 | 108261 | char c = 0; |
| 107050 | 108262 | int nEntry = 0; |
| | @@ -107057,158 +108269,445 @@ |
| 107057 | 108269 | |
| 107058 | 108270 | *ppCollist = pEnd; |
| 107059 | 108271 | return nEntry; |
| 107060 | 108272 | } |
| 107061 | 108273 | |
| 107062 | | -static void fts3LoadColumnlistCounts(char **pp, u32 *aOut){ |
| 108274 | +static void fts3LoadColumnlistCounts(char **pp, u32 *aOut, int isGlobal){ |
| 107063 | 108275 | char *pCsr = *pp; |
| 107064 | 108276 | while( *pCsr ){ |
| 108277 | + int nHit; |
| 107065 | 108278 | sqlite3_int64 iCol = 0; |
| 107066 | 108279 | if( *pCsr==0x01 ){ |
| 107067 | 108280 | pCsr++; |
| 107068 | 108281 | pCsr += sqlite3Fts3GetVarint(pCsr, &iCol); |
| 107069 | 108282 | } |
| 107070 | | - aOut[iCol] += fts3ColumnlistCount(&pCsr); |
| 108283 | + nHit = fts3ColumnlistCount(&pCsr); |
| 108284 | + assert( nHit>0 ); |
| 108285 | + if( isGlobal ){ |
| 108286 | + aOut[iCol*3+1]++; |
| 108287 | + } |
| 108288 | + aOut[iCol*3] += nHit; |
| 107071 | 108289 | } |
| 107072 | 108290 | pCsr++; |
| 107073 | 108291 | *pp = pCsr; |
| 107074 | 108292 | } |
| 107075 | 108293 | |
| 107076 | 108294 | /* |
| 107077 | 108295 | ** fts3ExprIterate() callback used to collect the "global" matchinfo stats |
| 107078 | | -** for a single query. |
| 108296 | +** for a single query. The "global" stats are those elements of the matchinfo |
| 108297 | +** array that are constant for all rows returned by the current query. |
| 107079 | 108298 | */ |
| 107080 | 108299 | static int fts3ExprGlobalMatchinfoCb( |
| 107081 | 108300 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 108301 | + int iPhrase, /* Phrase number (numbered from zero) */ |
| 107082 | 108302 | void *pCtx /* Pointer to MatchInfo structure */ |
| 107083 | 108303 | ){ |
| 107084 | 108304 | MatchInfo *p = (MatchInfo *)pCtx; |
| 107085 | 108305 | char *pCsr; |
| 107086 | 108306 | char *pEnd; |
| 107087 | | - const int iStart = 2 + p->nCol*p->iPhrase; |
| 108307 | + const int iStart = 2 + (iPhrase * p->nCol * 3) + 1; |
| 107088 | 108308 | |
| 107089 | 108309 | assert( pExpr->isLoaded ); |
| 107090 | 108310 | |
| 107091 | 108311 | /* Fill in the global hit count matrix row for this phrase. */ |
| 107092 | 108312 | pCsr = pExpr->aDoclist; |
| 107093 | 108313 | pEnd = &pExpr->aDoclist[pExpr->nDoclist]; |
| 107094 | 108314 | while( pCsr<pEnd ){ |
| 107095 | | - while( *pCsr++ & 0x80 ); |
| 107096 | | - fts3LoadColumnlistCounts(&pCsr, &p->aGlobal[iStart]); |
| 108315 | + while( *pCsr++ & 0x80 ); /* Skip past docid. */ |
| 108316 | + fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 1); |
| 107097 | 108317 | } |
| 107098 | 108318 | |
| 107099 | | - p->iPhrase++; |
| 107100 | 108319 | return SQLITE_OK; |
| 107101 | 108320 | } |
| 107102 | 108321 | |
| 108322 | +/* |
| 108323 | +** fts3ExprIterate() callback used to collect the "local" matchinfo stats |
| 108324 | +** for a single query. The "local" stats are those elements of the matchinfo |
| 108325 | +** array that are different for each row returned by the query. |
| 108326 | +*/ |
| 107103 | 108327 | static int fts3ExprLocalMatchinfoCb( |
| 107104 | 108328 | Fts3Expr *pExpr, /* Phrase expression node */ |
| 108329 | + int iPhrase, /* Phrase number */ |
| 107105 | 108330 | void *pCtx /* Pointer to MatchInfo structure */ |
| 107106 | 108331 | ){ |
| 107107 | 108332 | MatchInfo *p = (MatchInfo *)pCtx; |
| 107108 | | - int iPhrase = p->iPhrase++; |
| 107109 | 108333 | |
| 107110 | 108334 | if( pExpr->aDoclist ){ |
| 107111 | 108335 | char *pCsr; |
| 107112 | | - int iOffset = 2 + p->nCol*(p->aGlobal[0]+iPhrase); |
| 108336 | + int iStart = 2 + (iPhrase * p->nCol * 3); |
| 108337 | + int i; |
| 107113 | 108338 | |
| 107114 | | - memset(&p->aGlobal[iOffset], 0, p->nCol*sizeof(u32)); |
| 108339 | + for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0; |
| 108340 | + |
| 107115 | 108341 | pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1); |
| 107116 | | - if( pCsr ) fts3LoadColumnlistCounts(&pCsr, &p->aGlobal[iOffset]); |
| 108342 | + if( pCsr ){ |
| 108343 | + fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0); |
| 108344 | + } |
| 107117 | 108345 | } |
| 107118 | 108346 | |
| 107119 | 108347 | return SQLITE_OK; |
| 107120 | 108348 | } |
| 107121 | 108349 | |
| 107122 | 108350 | /* |
| 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). |
| 108351 | +** Populate pCsr->aMatchinfo[] with data for the current row. The |
| 108352 | +** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). |
| 107125 | 108353 | */ |
| 107126 | 108354 | static int fts3GetMatchinfo(Fts3Cursor *pCsr){ |
| 107127 | | - MatchInfo g; |
| 108355 | + MatchInfo sInfo; |
| 107128 | 108356 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 108357 | + int rc = SQLITE_OK; |
| 108358 | + |
| 108359 | + sInfo.pCursor = pCsr; |
| 108360 | + sInfo.nCol = pTab->nColumn; |
| 108361 | + |
| 107129 | 108362 | 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); |
| 108363 | + /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the |
| 108364 | + ** matchinfo function has been called for this query. In this case |
| 108365 | + ** allocate the array used to accumulate the matchinfo data and |
| 108366 | + ** initialize those elements that are constant for every row. |
| 108367 | + */ |
| 108368 | + int nPhrase; /* Number of phrases */ |
| 108369 | + int nMatchinfo; /* Number of u32 elements in match-info */ |
| 108370 | + |
| 108371 | + /* Load doclists for each phrase in the query. */ |
| 108372 | + rc = fts3ExprLoadDoclists(pCsr, &nPhrase, 0); |
| 107138 | 108373 | if( rc!=SQLITE_OK ){ |
| 107139 | 108374 | return rc; |
| 107140 | 108375 | } |
| 108376 | + nMatchinfo = 2 + 3*sInfo.nCol*nPhrase; |
| 108377 | + if( pTab->bHasDocsize ){ |
| 108378 | + nMatchinfo += 1 + 2*pTab->nColumn; |
| 108379 | + } |
| 107141 | 108380 | |
| 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 ){ |
| 108381 | + sInfo.aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo); |
| 108382 | + if( !sInfo.aMatchinfo ){ |
| 107147 | 108383 | return SQLITE_NOMEM; |
| 107148 | 108384 | } |
| 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; |
| 108385 | + memset(sInfo.aMatchinfo, 0, sizeof(u32)*nMatchinfo); |
| 108386 | + |
| 108387 | + |
| 108388 | + /* First element of match-info is the number of phrases in the query */ |
| 108389 | + sInfo.aMatchinfo[0] = nPhrase; |
| 108390 | + sInfo.aMatchinfo[1] = sInfo.nCol; |
| 108391 | + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo); |
| 108392 | + if( pTab->bHasDocsize ){ |
| 108393 | + int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; |
| 108394 | + rc = sqlite3Fts3MatchinfoDocsizeGlobal(pCsr, &sInfo.aMatchinfo[ofst]); |
| 108395 | + } |
| 108396 | + pCsr->aMatchinfo = sInfo.aMatchinfo; |
| 108397 | + pCsr->isMatchinfoNeeded = 1; |
| 108398 | + } |
| 108399 | + |
| 108400 | + sInfo.aMatchinfo = pCsr->aMatchinfo; |
| 108401 | + if( rc==SQLITE_OK && pCsr->isMatchinfoNeeded ){ |
| 108402 | + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void*)&sInfo); |
| 108403 | + if( pTab->bHasDocsize ){ |
| 108404 | + int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1]; |
| 108405 | + rc = sqlite3Fts3MatchinfoDocsizeLocal(pCsr, &sInfo.aMatchinfo[ofst]); |
| 108406 | + } |
| 108407 | + pCsr->isMatchinfoNeeded = 0; |
| 107167 | 108408 | } |
| 107168 | 108409 | |
| 107169 | 108410 | return SQLITE_OK; |
| 107170 | 108411 | } |
| 107171 | 108412 | |
| 107172 | | -SQLITE_PRIVATE void sqlite3Fts3Snippet2( |
| 108413 | +/* |
| 108414 | +** Implementation of snippet() function. |
| 108415 | +*/ |
| 108416 | +SQLITE_PRIVATE void sqlite3Fts3Snippet( |
| 107173 | 108417 | sqlite3_context *pCtx, /* SQLite function call context */ |
| 107174 | 108418 | Fts3Cursor *pCsr, /* Cursor object */ |
| 107175 | 108419 | const char *zStart, /* Snippet start text - "<b>" */ |
| 107176 | 108420 | const char *zEnd, /* Snippet end text - "</b>" */ |
| 107177 | 108421 | const char *zEllipsis, /* Snippet ellipsis text - "<b>...</b>" */ |
| 107178 | 108422 | int iCol, /* Extract snippet from this column */ |
| 107179 | 108423 | int nToken /* Approximate number of tokens in snippet */ |
| 107180 | 108424 | ){ |
| 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 | | - } |
| 108425 | + Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 108426 | + int rc = SQLITE_OK; |
| 108427 | + int i; |
| 108428 | + StrBuffer res = {0, 0, 0}; |
| 108429 | + |
| 108430 | + /* The returned text includes up to four fragments of text extracted from |
| 108431 | + ** the data in the current row. The first iteration of the for(...) loop |
| 108432 | + ** below attempts to locate a single fragment of text nToken tokens in |
| 108433 | + ** size that contains at least one instance of all phrases in the query |
| 108434 | + ** expression that appear in the current row. If such a fragment of text |
| 108435 | + ** cannot be found, the second iteration of the loop attempts to locate |
| 108436 | + ** a pair of fragments, and so on. |
| 108437 | + */ |
| 108438 | + int nSnippet = 0; /* Number of fragments in this snippet */ |
| 108439 | + SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */ |
| 108440 | + int nFToken = -1; /* Number of tokens in each fragment */ |
| 108441 | + |
| 108442 | + if( !pCsr->pExpr ){ |
| 108443 | + sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); |
| 108444 | + return; |
| 108445 | + } |
| 108446 | + |
| 108447 | + for(nSnippet=1; 1; nSnippet++){ |
| 108448 | + |
| 108449 | + int iSnip; /* Loop counter 0..nSnippet-1 */ |
| 108450 | + u64 mCovered = 0; /* Bitmask of phrases covered by snippet */ |
| 108451 | + u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */ |
| 108452 | + |
| 108453 | + if( nToken>=0 ){ |
| 108454 | + nFToken = (nToken+nSnippet-1) / nSnippet; |
| 108455 | + }else{ |
| 108456 | + nFToken = -1 * nToken; |
| 108457 | + } |
| 108458 | + |
| 108459 | + for(iSnip=0; iSnip<nSnippet; iSnip++){ |
| 108460 | + int iBestScore = -1; /* Best score of columns checked so far */ |
| 108461 | + int iRead; /* Used to iterate through columns */ |
| 108462 | + SnippetFragment *pFragment = &aSnippet[iSnip]; |
| 108463 | + |
| 108464 | + memset(pFragment, 0, sizeof(*pFragment)); |
| 108465 | + |
| 108466 | + /* Loop through all columns of the table being considered for snippets. |
| 108467 | + ** If the iCol argument to this function was negative, this means all |
| 108468 | + ** columns of the FTS3 table. Otherwise, only column iCol is considered. |
| 108469 | + */ |
| 108470 | + for(iRead=0; iRead<pTab->nColumn; iRead++){ |
| 108471 | + SnippetFragment sF; |
| 108472 | + int iS; |
| 108473 | + if( iCol>=0 && iRead!=iCol ) continue; |
| 108474 | + |
| 108475 | + /* Find the best snippet of nFToken tokens in column iRead. */ |
| 108476 | + rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS); |
| 108477 | + if( rc!=SQLITE_OK ){ |
| 108478 | + goto snippet_out; |
| 108479 | + } |
| 108480 | + if( iS>iBestScore ){ |
| 108481 | + *pFragment = sF; |
| 108482 | + iBestScore = iS; |
| 108483 | + } |
| 108484 | + } |
| 108485 | + |
| 108486 | + mCovered |= pFragment->covered; |
| 108487 | + } |
| 108488 | + |
| 108489 | + /* If all query phrases seen by fts3BestSnippet() are present in at least |
| 108490 | + ** one of the nSnippet snippet fragments, break out of the loop. |
| 108491 | + */ |
| 108492 | + assert( (mCovered&mSeen)==mCovered ); |
| 108493 | + if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break; |
| 108494 | + } |
| 108495 | + |
| 108496 | + assert( nFToken>0 ); |
| 108497 | + |
| 108498 | + for(i=0; i<nSnippet && rc==SQLITE_OK; i++){ |
| 108499 | + rc = fts3SnippetText(pCsr, &aSnippet[i], |
| 108500 | + i, (i==nSnippet-1), nFToken, zStart, zEnd, zEllipsis, &res |
| 108501 | + ); |
| 108502 | + } |
| 108503 | + |
| 108504 | + snippet_out: |
| 107197 | 108505 | if( rc!=SQLITE_OK ){ |
| 107198 | 108506 | sqlite3_result_error_code(pCtx, rc); |
| 108507 | + sqlite3_free(res.z); |
| 108508 | + }else{ |
| 108509 | + sqlite3_result_text(pCtx, res.z, -1, sqlite3_free); |
| 108510 | + } |
| 108511 | +} |
| 108512 | + |
| 108513 | + |
| 108514 | +typedef struct TermOffset TermOffset; |
| 108515 | +typedef struct TermOffsetCtx TermOffsetCtx; |
| 108516 | + |
| 108517 | +struct TermOffset { |
| 108518 | + char *pList; /* Position-list */ |
| 108519 | + int iPos; /* Position just read from pList */ |
| 108520 | + int iOff; /* Offset of this term from read positions */ |
| 108521 | +}; |
| 108522 | + |
| 108523 | +struct TermOffsetCtx { |
| 108524 | + int iCol; /* Column of table to populate aTerm for */ |
| 108525 | + int iTerm; |
| 108526 | + sqlite3_int64 iDocid; |
| 108527 | + TermOffset *aTerm; |
| 108528 | +}; |
| 108529 | + |
| 108530 | +/* |
| 108531 | +** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets(). |
| 108532 | +*/ |
| 108533 | +static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 108534 | + TermOffsetCtx *p = (TermOffsetCtx *)ctx; |
| 108535 | + int nTerm; /* Number of tokens in phrase */ |
| 108536 | + int iTerm; /* For looping through nTerm phrase terms */ |
| 108537 | + char *pList; /* Pointer to position list for phrase */ |
| 108538 | + int iPos = 0; /* First position in position-list */ |
| 108539 | + |
| 108540 | + UNUSED_PARAMETER(iPhrase); |
| 108541 | + pList = sqlite3Fts3FindPositions(pExpr, p->iDocid, p->iCol); |
| 108542 | + nTerm = pExpr->pPhrase->nToken; |
| 108543 | + if( pList ){ |
| 108544 | + fts3GetDeltaPosition(&pList, &iPos); |
| 108545 | + assert( iPos>=0 ); |
| 108546 | + } |
| 108547 | + |
| 108548 | + for(iTerm=0; iTerm<nTerm; iTerm++){ |
| 108549 | + TermOffset *pT = &p->aTerm[p->iTerm++]; |
| 108550 | + pT->iOff = nTerm-iTerm-1; |
| 108551 | + pT->pList = pList; |
| 108552 | + pT->iPos = iPos; |
| 108553 | + } |
| 108554 | + |
| 108555 | + return SQLITE_OK; |
| 108556 | +} |
| 108557 | + |
| 108558 | +/* |
| 108559 | +** Implementation of offsets() function. |
| 108560 | +*/ |
| 108561 | +SQLITE_PRIVATE void sqlite3Fts3Offsets( |
| 108562 | + sqlite3_context *pCtx, /* SQLite function call context */ |
| 108563 | + Fts3Cursor *pCsr /* Cursor object */ |
| 108564 | +){ |
| 108565 | + Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 108566 | + sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; |
| 108567 | + const char *ZDUMMY; /* Dummy argument used with xNext() */ |
| 108568 | + int NDUMMY; /* Dummy argument used with xNext() */ |
| 108569 | + int rc; /* Return Code */ |
| 108570 | + int nToken; /* Number of tokens in query */ |
| 108571 | + int iCol; /* Column currently being processed */ |
| 108572 | + StrBuffer res = {0, 0, 0}; /* Result string */ |
| 108573 | + TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */ |
| 108574 | + |
| 108575 | + if( !pCsr->pExpr ){ |
| 108576 | + sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); |
| 108577 | + return; |
| 108578 | + } |
| 108579 | + |
| 108580 | + memset(&sCtx, 0, sizeof(sCtx)); |
| 108581 | + assert( pCsr->isRequireSeek==0 ); |
| 108582 | + |
| 108583 | + /* Count the number of terms in the query */ |
| 108584 | + rc = fts3ExprLoadDoclists(pCsr, 0, &nToken); |
| 108585 | + if( rc!=SQLITE_OK ) goto offsets_out; |
| 108586 | + |
| 108587 | + /* Allocate the array of TermOffset iterators. */ |
| 108588 | + sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken); |
| 108589 | + if( 0==sCtx.aTerm ){ |
| 108590 | + rc = SQLITE_NOMEM; |
| 108591 | + goto offsets_out; |
| 108592 | + } |
| 108593 | + sCtx.iDocid = pCsr->iPrevId; |
| 108594 | + |
| 108595 | + /* Loop through the table columns, appending offset information to |
| 108596 | + ** string-buffer res for each column. |
| 108597 | + */ |
| 108598 | + for(iCol=0; iCol<pTab->nColumn; iCol++){ |
| 108599 | + sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ |
| 108600 | + int iStart; |
| 108601 | + int iEnd; |
| 108602 | + int iCurrent; |
| 108603 | + const char *zDoc; |
| 108604 | + int nDoc; |
| 108605 | + |
| 108606 | + /* Initialize the contents of sCtx.aTerm[] for column iCol. There is |
| 108607 | + ** no way that this operation can fail, so the return code from |
| 108608 | + ** fts3ExprIterate() can be discarded. |
| 108609 | + */ |
| 108610 | + sCtx.iCol = iCol; |
| 108611 | + sCtx.iTerm = 0; |
| 108612 | + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx); |
| 108613 | + |
| 108614 | + /* Retreive the text stored in column iCol. If an SQL NULL is stored |
| 108615 | + ** in column iCol, jump immediately to the next iteration of the loop. |
| 108616 | + ** If an OOM occurs while retrieving the data (this can happen if SQLite |
| 108617 | + ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM |
| 108618 | + ** to the caller. |
| 108619 | + */ |
| 108620 | + zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1); |
| 108621 | + nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1); |
| 108622 | + if( zDoc==0 ){ |
| 108623 | + if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){ |
| 108624 | + continue; |
| 108625 | + } |
| 108626 | + rc = SQLITE_NOMEM; |
| 108627 | + goto offsets_out; |
| 108628 | + } |
| 108629 | + |
| 108630 | + /* Initialize a tokenizer iterator to iterate through column iCol. */ |
| 108631 | + rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); |
| 108632 | + if( rc!=SQLITE_OK ) goto offsets_out; |
| 108633 | + pC->pTokenizer = pTab->pTokenizer; |
| 108634 | + |
| 108635 | + rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); |
| 108636 | + while( rc==SQLITE_OK ){ |
| 108637 | + int i; /* Used to loop through terms */ |
| 108638 | + int iMinPos = 0x7FFFFFFF; /* Position of next token */ |
| 108639 | + TermOffset *pTerm = 0; /* TermOffset associated with next token */ |
| 108640 | + |
| 108641 | + for(i=0; i<nToken; i++){ |
| 108642 | + TermOffset *pT = &sCtx.aTerm[i]; |
| 108643 | + if( pT->pList && (pT->iPos-pT->iOff)<iMinPos ){ |
| 108644 | + iMinPos = pT->iPos-pT->iOff; |
| 108645 | + pTerm = pT; |
| 108646 | + } |
| 108647 | + } |
| 108648 | + |
| 108649 | + if( !pTerm ){ |
| 108650 | + /* All offsets for this column have been gathered. */ |
| 108651 | + break; |
| 108652 | + }else{ |
| 108653 | + assert( iCurrent<=iMinPos ); |
| 108654 | + if( 0==(0xFE&*pTerm->pList) ){ |
| 108655 | + pTerm->pList = 0; |
| 108656 | + }else{ |
| 108657 | + fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos); |
| 108658 | + } |
| 108659 | + while( rc==SQLITE_OK && iCurrent<iMinPos ){ |
| 108660 | + rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); |
| 108661 | + } |
| 108662 | + if( rc==SQLITE_OK ){ |
| 108663 | + char aBuffer[64]; |
| 108664 | + sqlite3_snprintf(sizeof(aBuffer), aBuffer, |
| 108665 | + "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart |
| 108666 | + ); |
| 108667 | + rc = fts3StringAppend(&res, aBuffer, -1); |
| 108668 | + } |
| 108669 | + } |
| 108670 | + } |
| 108671 | + if( rc==SQLITE_DONE ){ |
| 108672 | + rc = SQLITE_CORRUPT; |
| 108673 | + } |
| 108674 | + |
| 108675 | + pMod->xClose(pC); |
| 108676 | + if( rc!=SQLITE_OK ) goto offsets_out; |
| 108677 | + } |
| 108678 | + |
| 108679 | + offsets_out: |
| 108680 | + sqlite3_free(sCtx.aTerm); |
| 108681 | + assert( rc!=SQLITE_DONE ); |
| 108682 | + if( rc!=SQLITE_OK ){ |
| 108683 | + sqlite3_result_error_code(pCtx, rc); |
| 108684 | + sqlite3_free(res.z); |
| 107199 | 108685 | }else{ |
| 107200 | | - sqlite3_result_text(pCtx, z, -1, sqlite3_free); |
| 108686 | + sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free); |
| 107201 | 108687 | } |
| 108688 | + return; |
| 107202 | 108689 | } |
| 107203 | 108690 | |
| 108691 | +/* |
| 108692 | +** Implementation of matchinfo() function. |
| 108693 | +*/ |
| 107204 | 108694 | SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *pCsr){ |
| 107205 | | - int rc = fts3GetMatchinfo(pCsr); |
| 108695 | + int rc; |
| 108696 | + if( !pCsr->pExpr ){ |
| 108697 | + sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); |
| 108698 | + return; |
| 108699 | + } |
| 108700 | + rc = fts3GetMatchinfo(pCsr); |
| 107206 | 108701 | if( rc!=SQLITE_OK ){ |
| 107207 | 108702 | sqlite3_result_error_code(pContext, rc); |
| 107208 | 108703 | }else{ |
| 107209 | | - int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*2); |
| 108704 | + Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab; |
| 108705 | + int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*3); |
| 108706 | + if( pTab->bHasDocsize ){ |
| 108707 | + n += sizeof(u32)*(1 + 2*pTab->nColumn); |
| 108708 | + } |
| 107210 | 108709 | sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); |
| 107211 | 108710 | } |
| 107212 | 108711 | } |
| 107213 | 108712 | |
| 107214 | 108713 | #endif |
| | @@ -107634,10 +109133,11 @@ |
| 107634 | 109133 | |
| 107635 | 109134 | sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); |
| 107636 | 109135 | rc = sqlite3_step(pRtree->pReadNode); |
| 107637 | 109136 | if( rc==SQLITE_ROW ){ |
| 107638 | 109137 | const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); |
| 109138 | + assert( sqlite3_column_bytes(pRtree->pReadNode, 0)==pRtree->iNodeSize ); |
| 107639 | 109139 | memcpy(pNode->zData, zBlob, pRtree->iNodeSize); |
| 107640 | 109140 | nodeReference(pParent); |
| 107641 | 109141 | }else{ |
| 107642 | 109142 | sqlite3_free(pNode); |
| 107643 | 109143 | pNode = 0; |
| | @@ -109830,35 +111330,73 @@ |
| 109830 | 111330 | |
| 109831 | 111331 | return rc; |
| 109832 | 111332 | } |
| 109833 | 111333 | |
| 109834 | 111334 | /* |
| 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. |
| 111335 | +** The second argument to this function contains the text of an SQL statement |
| 111336 | +** that returns a single integer value. The statement is compiled and executed |
| 111337 | +** using database connection db. If successful, the integer value returned |
| 111338 | +** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error |
| 111339 | +** code is returned and the value of *piVal after returning is not defined. |
| 109839 | 111340 | */ |
| 109840 | | -static int getPageSize(sqlite3 *db, const char *zDb, int *piPageSize){ |
| 111341 | +static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){ |
| 109841 | 111342 | int rc = SQLITE_NOMEM; |
| 111343 | + if( zSql ){ |
| 111344 | + sqlite3_stmt *pStmt = 0; |
| 111345 | + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
| 111346 | + if( rc==SQLITE_OK ){ |
| 111347 | + if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 111348 | + *piVal = sqlite3_column_int(pStmt, 0); |
| 111349 | + } |
| 111350 | + rc = sqlite3_finalize(pStmt); |
| 111351 | + } |
| 111352 | + } |
| 111353 | + return rc; |
| 111354 | +} |
| 111355 | + |
| 111356 | +/* |
| 111357 | +** This function is called from within the xConnect() or xCreate() method to |
| 111358 | +** determine the node-size used by the rtree table being created or connected |
| 111359 | +** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned. |
| 111360 | +** Otherwise, an SQLite error code is returned. |
| 111361 | +** |
| 111362 | +** If this function is being called as part of an xConnect(), then the rtree |
| 111363 | +** table already exists. In this case the node-size is determined by inspecting |
| 111364 | +** the root node of the tree. |
| 111365 | +** |
| 111366 | +** Otherwise, for an xCreate(), use 64 bytes less than the database page-size. |
| 111367 | +** This ensures that each node is stored on a single database page. If the |
| 111368 | +** database page-size is so large that more than RTREE_MAXCELLS entries |
| 111369 | +** would fit in a single node, use a smaller node-size. |
| 111370 | +*/ |
| 111371 | +static int getNodeSize( |
| 111372 | + sqlite3 *db, /* Database handle */ |
| 111373 | + Rtree *pRtree, /* Rtree handle */ |
| 111374 | + int isCreate /* True for xCreate, false for xConnect */ |
| 111375 | +){ |
| 111376 | + int rc; |
| 109842 | 111377 | char *zSql; |
| 109843 | | - sqlite3_stmt *pStmt = 0; |
| 109844 | | - |
| 109845 | | - zSql = sqlite3_mprintf("PRAGMA %Q.page_size", zDb); |
| 109846 | | - if( !zSql ){ |
| 109847 | | - return SQLITE_NOMEM; |
| 111378 | + if( isCreate ){ |
| 111379 | + int iPageSize; |
| 111380 | + zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb); |
| 111381 | + rc = getIntFromStmt(db, zSql, &iPageSize); |
| 111382 | + if( rc==SQLITE_OK ){ |
| 111383 | + pRtree->iNodeSize = iPageSize-64; |
| 111384 | + if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ |
| 111385 | + pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; |
| 111386 | + } |
| 111387 | + } |
| 111388 | + }else{ |
| 111389 | + zSql = sqlite3_mprintf( |
| 111390 | + "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1", |
| 111391 | + pRtree->zDb, pRtree->zName |
| 111392 | + ); |
| 111393 | + rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); |
| 109848 | 111394 | } |
| 109849 | 111395 | |
| 109850 | | - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
| 109851 | 111396 | 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); |
| 111397 | + return rc; |
| 109860 | 111398 | } |
| 109861 | 111399 | |
| 109862 | 111400 | /* |
| 109863 | 111401 | ** This function is the implementation of both the xConnect and xCreate |
| 109864 | 111402 | ** methods of the r-tree virtual table. |
| | @@ -109875,11 +111413,10 @@ |
| 109875 | 111413 | sqlite3_vtab **ppVtab, /* OUT: New virtual table */ |
| 109876 | 111414 | char **pzErr, /* OUT: Error message, if any */ |
| 109877 | 111415 | int isCreate /* True for xCreate, false for xConnect */ |
| 109878 | 111416 | ){ |
| 109879 | 111417 | int rc = SQLITE_OK; |
| 109880 | | - int iPageSize = 0; |
| 109881 | 111418 | Rtree *pRtree; |
| 109882 | 111419 | int nDb; /* Length of string argv[1] */ |
| 109883 | 111420 | int nName; /* Length of string argv[2] */ |
| 109884 | 111421 | int eCoordType = (int)pAux; |
| 109885 | 111422 | |
| | @@ -109894,15 +111431,10 @@ |
| 109894 | 111431 | if( aErrMsg[iErr] ){ |
| 109895 | 111432 | *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); |
| 109896 | 111433 | return SQLITE_ERROR; |
| 109897 | 111434 | } |
| 109898 | 111435 | |
| 109899 | | - rc = getPageSize(db, argv[1], &iPageSize); |
| 109900 | | - if( rc!=SQLITE_OK ){ |
| 109901 | | - return rc; |
| 109902 | | - } |
| 109903 | | - |
| 109904 | 111436 | /* Allocate the sqlite3_vtab structure */ |
| 109905 | 111437 | nDb = strlen(argv[1]); |
| 109906 | 111438 | nName = strlen(argv[2]); |
| 109907 | 111439 | pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); |
| 109908 | 111440 | if( !pRtree ){ |
| | @@ -109917,48 +111449,41 @@ |
| 109917 | 111449 | pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; |
| 109918 | 111450 | pRtree->eCoordType = eCoordType; |
| 109919 | 111451 | memcpy(pRtree->zDb, argv[1], nDb); |
| 109920 | 111452 | memcpy(pRtree->zName, argv[2], nName); |
| 109921 | 111453 | |
| 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 | | - } |
| 111454 | + /* Figure out the node size to use. */ |
| 111455 | + rc = getNodeSize(db, pRtree, isCreate); |
| 109933 | 111456 | |
| 109934 | 111457 | /* Create/Connect to the underlying relational database schema. If |
| 109935 | 111458 | ** that is successful, call sqlite3_declare_vtab() to configure |
| 109936 | 111459 | ** the r-tree table schema. |
| 109937 | 111460 | */ |
| 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); |
| 111461 | + if( rc==SQLITE_OK ){ |
| 111462 | + if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ |
| 111463 | + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
| 111464 | + }else{ |
| 111465 | + char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); |
| 111466 | + char *zTmp; |
| 111467 | + int ii; |
| 111468 | + for(ii=4; zSql && ii<argc; ii++){ |
| 111469 | + zTmp = zSql; |
| 111470 | + zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); |
| 111471 | + sqlite3_free(zTmp); |
| 111472 | + } |
| 111473 | + if( zSql ){ |
| 111474 | + zTmp = zSql; |
| 111475 | + zSql = sqlite3_mprintf("%s);", zTmp); |
| 111476 | + sqlite3_free(zTmp); |
| 111477 | + } |
| 111478 | + if( !zSql ){ |
| 111479 | + rc = SQLITE_NOMEM; |
| 111480 | + }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ |
| 111481 | + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
| 111482 | + } |
| 111483 | + sqlite3_free(zSql); |
| 111484 | + } |
| 109960 | 111485 | } |
| 109961 | 111486 | |
| 109962 | 111487 | if( rc==SQLITE_OK ){ |
| 109963 | 111488 | *ppVtab = (sqlite3_vtab *)pRtree; |
| 109964 | 111489 | }else{ |
| 109965 | 111490 | |