| | @@ -16,11 +16,11 @@ |
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | | -** f97f9944b829a49da12786f934da0a5ad515. |
| 21 | +** 011fab70cb3d194b27742ebb236b05be5822. |
| 22 | 22 | */ |
| 23 | 23 | #define SQLITE_CORE 1 |
| 24 | 24 | #define SQLITE_AMALGAMATION 1 |
| 25 | 25 | #ifndef SQLITE_PRIVATE |
| 26 | 26 | # define SQLITE_PRIVATE static |
| | @@ -462,11 +462,11 @@ |
| 462 | 462 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 463 | 463 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 464 | 464 | */ |
| 465 | 465 | #define SQLITE_VERSION "3.47.0" |
| 466 | 466 | #define SQLITE_VERSION_NUMBER 3047000 |
| 467 | | -#define SQLITE_SOURCE_ID "2024-09-26 19:38:34 f97f9944b829a49da12786f934da0a5ad51591afd6d8a19a4a0835f51bbdbff2" |
| 467 | +#define SQLITE_SOURCE_ID "2024-10-07 12:48:21 011fab70cb3d194b27742ebb236b05be582230567cf78e3e6cac6911de86922f" |
| 468 | 468 | |
| 469 | 469 | /* |
| 470 | 470 | ** CAPI3REF: Run-Time Library Version Numbers |
| 471 | 471 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 472 | 472 | ** |
| | @@ -5917,11 +5917,11 @@ |
| 5917 | 5917 | ** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call |
| 5918 | 5918 | ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. |
| 5919 | 5919 | ** This flag instructs SQLite to omit some corner-case optimizations that |
| 5920 | 5920 | ** might disrupt the operation of the [sqlite3_value_subtype()] function, |
| 5921 | 5921 | ** causing it to return zero rather than the correct subtype(). |
| 5922 | | -** SQL functions that invokes [sqlite3_value_subtype()] should have this |
| 5922 | +** All SQL functions that invoke [sqlite3_value_subtype()] should have this |
| 5923 | 5923 | ** property. If the SQLITE_SUBTYPE property is omitted, then the return |
| 5924 | 5924 | ** value from [sqlite3_value_subtype()] might sometimes be zero even though |
| 5925 | 5925 | ** a non-zero subtype was specified by the function argument expression. |
| 5926 | 5926 | ** |
| 5927 | 5927 | ** [[SQLITE_RESULT_SUBTYPE]] <dt>SQLITE_RESULT_SUBTYPE</dt><dd> |
| | @@ -8682,11 +8682,11 @@ |
| 8682 | 8682 | #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 |
| 8683 | 8683 | #define SQLITE_TESTCTRL_SEEK_COUNT 30 |
| 8684 | 8684 | #define SQLITE_TESTCTRL_TRACEFLAGS 31 |
| 8685 | 8685 | #define SQLITE_TESTCTRL_TUNE 32 |
| 8686 | 8686 | #define SQLITE_TESTCTRL_LOGEST 33 |
| 8687 | | -#define SQLITE_TESTCTRL_USELONGDOUBLE 34 |
| 8687 | +#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */ |
| 8688 | 8688 | #define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ |
| 8689 | 8689 | |
| 8690 | 8690 | /* |
| 8691 | 8691 | ** CAPI3REF: SQL Keyword Checking |
| 8692 | 8692 | ** |
| | @@ -10856,10 +10856,18 @@ |
| 10856 | 10856 | ** schema S in database connection D. ^On success, the |
| 10857 | 10857 | ** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly |
| 10858 | 10858 | ** created [sqlite3_snapshot] object into *P and returns SQLITE_OK. |
| 10859 | 10859 | ** If there is not already a read-transaction open on schema S when |
| 10860 | 10860 | ** this function is called, one is opened automatically. |
| 10861 | +** |
| 10862 | +** If a read-transaction is opened by this function, then it is guaranteed |
| 10863 | +** that the returned snapshot object may not be invalidated by a database |
| 10864 | +** writer or checkpointer until after the read-transaction is closed. This |
| 10865 | +** is not guaranteed if a read-transaction is already open when this |
| 10866 | +** function is called. In that case, any subsequent write or checkpoint |
| 10867 | +** operation on the database may invalidate the returned snapshot handle, |
| 10868 | +** even while the read-transaction remains open. |
| 10861 | 10869 | ** |
| 10862 | 10870 | ** The following must be true for this function to succeed. If any of |
| 10863 | 10871 | ** the following statements are false when sqlite3_snapshot_get() is |
| 10864 | 10872 | ** called, SQLITE_ERROR is returned. The final value of *P is undefined |
| 10865 | 10873 | ** in this case. |
| | @@ -14813,10 +14821,11 @@ |
| 14813 | 14821 | #include <stdio.h> |
| 14814 | 14822 | #include <stdlib.h> |
| 14815 | 14823 | #include <string.h> |
| 14816 | 14824 | #include <assert.h> |
| 14817 | 14825 | #include <stddef.h> |
| 14826 | +#include <ctype.h> |
| 14818 | 14827 | |
| 14819 | 14828 | /* |
| 14820 | 14829 | ** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY. |
| 14821 | 14830 | ** This allows better measurements of where memcpy() is used when running |
| 14822 | 14831 | ** cachegrind. But this macro version of memcpy() is very slow so it |
| | @@ -14835,11 +14844,10 @@ |
| 14835 | 14844 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 14836 | 14845 | # define double sqlite_int64 |
| 14837 | 14846 | # define float sqlite_int64 |
| 14838 | 14847 | # define fabs(X) ((X)<0?-(X):(X)) |
| 14839 | 14848 | # define sqlite3IsOverflow(X) 0 |
| 14840 | | -# define LONGDOUBLE_TYPE sqlite_int64 |
| 14841 | 14849 | # ifndef SQLITE_BIG_DBL |
| 14842 | 14850 | # define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) |
| 14843 | 14851 | # endif |
| 14844 | 14852 | # define SQLITE_OMIT_DATETIME_FUNCS 1 |
| 14845 | 14853 | # define SQLITE_OMIT_TRACE 1 |
| | @@ -15010,13 +15018,10 @@ |
| 15010 | 15018 | # define INT8_TYPE int8_t |
| 15011 | 15019 | # else |
| 15012 | 15020 | # define INT8_TYPE signed char |
| 15013 | 15021 | # endif |
| 15014 | 15022 | #endif |
| 15015 | | -#ifndef LONGDOUBLE_TYPE |
| 15016 | | -# define LONGDOUBLE_TYPE long double |
| 15017 | | -#endif |
| 15018 | 15023 | typedef sqlite_int64 i64; /* 8-byte signed integer */ |
| 15019 | 15024 | typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ |
| 15020 | 15025 | typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ |
| 15021 | 15026 | typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ |
| 15022 | 15027 | typedef INT16_TYPE i16; /* 2-byte signed integer */ |
| | @@ -20380,11 +20385,10 @@ |
| 20380 | 20385 | u8 bFullMutex; /* True to enable full mutexing */ |
| 20381 | 20386 | u8 bOpenUri; /* True to interpret filenames as URIs */ |
| 20382 | 20387 | u8 bUseCis; /* Use covering indices for full-scans */ |
| 20383 | 20388 | u8 bSmallMalloc; /* Avoid large memory allocations if true */ |
| 20384 | 20389 | u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ |
| 20385 | | - u8 bUseLongDouble; /* Make use of long double */ |
| 20386 | 20390 | #ifdef SQLITE_DEBUG |
| 20387 | 20391 | u8 bJsonSelfcheck; /* Double-check JSON parsing */ |
| 20388 | 20392 | #endif |
| 20389 | 20393 | int mxStrlen; /* Maximum string length */ |
| 20390 | 20394 | int neverCorrupt; /* Database is always well-formed */ |
| | @@ -20755,19 +20759,10 @@ |
| 20755 | 20759 | */ |
| 20756 | 20760 | #if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) |
| 20757 | 20761 | # define SQLITE_ENABLE_FTS3 1 |
| 20758 | 20762 | #endif |
| 20759 | 20763 | |
| 20760 | | -/* |
| 20761 | | -** The ctype.h header is needed for non-ASCII systems. It is also |
| 20762 | | -** needed by FTS3 when FTS3 is included in the amalgamation. |
| 20763 | | -*/ |
| 20764 | | -#if !defined(SQLITE_ASCII) || \ |
| 20765 | | - (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION)) |
| 20766 | | -# include <ctype.h> |
| 20767 | | -#endif |
| 20768 | | - |
| 20769 | 20764 | /* |
| 20770 | 20765 | ** The following macros mimic the standard library functions toupper(), |
| 20771 | 20766 | ** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The |
| 20772 | 20767 | ** sqlite versions only work for ASCII characters, regardless of locale. |
| 20773 | 20768 | */ |
| | @@ -23121,11 +23116,10 @@ |
| 23121 | 23116 | SQLITE_THREADSAFE==1, /* bFullMutex */ |
| 23122 | 23117 | SQLITE_USE_URI, /* bOpenUri */ |
| 23123 | 23118 | SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ |
| 23124 | 23119 | 0, /* bSmallMalloc */ |
| 23125 | 23120 | 1, /* bExtraSchemaChecks */ |
| 23126 | | - sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */ |
| 23127 | 23121 | #ifdef SQLITE_DEBUG |
| 23128 | 23122 | 0, /* bJsonSelfcheck */ |
| 23129 | 23123 | #endif |
| 23130 | 23124 | 0x7ffffffe, /* mxStrlen */ |
| 23131 | 23125 | 0, /* neverCorrupt */ |
| | @@ -35679,10 +35673,12 @@ |
| 35679 | 35673 | int esign = 1; /* sign of exponent */ |
| 35680 | 35674 | int e = 0; /* exponent */ |
| 35681 | 35675 | int eValid = 1; /* True exponent is either not used or is well-formed */ |
| 35682 | 35676 | int nDigit = 0; /* Number of digits processed */ |
| 35683 | 35677 | int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ |
| 35678 | + double rr[2]; |
| 35679 | + u64 s2; |
| 35684 | 35680 | |
| 35685 | 35681 | assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); |
| 35686 | 35682 | *pResult = 0.0; /* Default return value, in case of an error */ |
| 35687 | 35683 | if( length==0 ) return 0; |
| 35688 | 35684 | |
| | @@ -35790,72 +35786,45 @@ |
| 35790 | 35786 | while( e<0 && (s%10)==0 ){ |
| 35791 | 35787 | s /= 10; |
| 35792 | 35788 | e++; |
| 35793 | 35789 | } |
| 35794 | 35790 | |
| 35795 | | - if( e==0 ){ |
| 35796 | | - *pResult = s; |
| 35797 | | - }else if( sqlite3Config.bUseLongDouble ){ |
| 35798 | | - LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s; |
| 35799 | | - if( e>0 ){ |
| 35800 | | - while( e>=100 ){ e-=100; r *= 1.0e+100L; } |
| 35801 | | - while( e>=10 ){ e-=10; r *= 1.0e+10L; } |
| 35802 | | - while( e>=1 ){ e-=1; r *= 1.0e+01L; } |
| 35803 | | - }else{ |
| 35804 | | - while( e<=-100 ){ e+=100; r *= 1.0e-100L; } |
| 35805 | | - while( e<=-10 ){ e+=10; r *= 1.0e-10L; } |
| 35806 | | - while( e<=-1 ){ e+=1; r *= 1.0e-01L; } |
| 35807 | | - } |
| 35808 | | - assert( r>=0.0 ); |
| 35809 | | - if( r>+1.7976931348623157081452742373e+308L ){ |
| 35810 | | -#ifdef INFINITY |
| 35811 | | - *pResult = +INFINITY; |
| 35812 | | -#else |
| 35813 | | - *pResult = 1.0e308*10.0; |
| 35814 | | -#endif |
| 35815 | | - }else{ |
| 35816 | | - *pResult = (double)r; |
| 35817 | | - } |
| 35818 | | - }else{ |
| 35819 | | - double rr[2]; |
| 35820 | | - u64 s2; |
| 35821 | | - rr[0] = (double)s; |
| 35822 | | - s2 = (u64)rr[0]; |
| 35791 | + rr[0] = (double)s; |
| 35792 | + s2 = (u64)rr[0]; |
| 35823 | 35793 | #if defined(_MSC_VER) && _MSC_VER<1700 |
| 35824 | | - if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); } |
| 35794 | + if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); } |
| 35825 | 35795 | #endif |
| 35826 | | - rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); |
| 35827 | | - if( e>0 ){ |
| 35828 | | - while( e>=100 ){ |
| 35829 | | - e -= 100; |
| 35830 | | - dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); |
| 35831 | | - } |
| 35832 | | - while( e>=10 ){ |
| 35833 | | - e -= 10; |
| 35834 | | - dekkerMul2(rr, 1.0e+10, 0.0); |
| 35835 | | - } |
| 35836 | | - while( e>=1 ){ |
| 35837 | | - e -= 1; |
| 35838 | | - dekkerMul2(rr, 1.0e+01, 0.0); |
| 35839 | | - } |
| 35840 | | - }else{ |
| 35841 | | - while( e<=-100 ){ |
| 35842 | | - e += 100; |
| 35843 | | - dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); |
| 35844 | | - } |
| 35845 | | - while( e<=-10 ){ |
| 35846 | | - e += 10; |
| 35847 | | - dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); |
| 35848 | | - } |
| 35849 | | - while( e<=-1 ){ |
| 35850 | | - e += 1; |
| 35851 | | - dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); |
| 35852 | | - } |
| 35853 | | - } |
| 35854 | | - *pResult = rr[0]+rr[1]; |
| 35855 | | - if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300; |
| 35856 | | - } |
| 35796 | + rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); |
| 35797 | + if( e>0 ){ |
| 35798 | + while( e>=100 ){ |
| 35799 | + e -= 100; |
| 35800 | + dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); |
| 35801 | + } |
| 35802 | + while( e>=10 ){ |
| 35803 | + e -= 10; |
| 35804 | + dekkerMul2(rr, 1.0e+10, 0.0); |
| 35805 | + } |
| 35806 | + while( e>=1 ){ |
| 35807 | + e -= 1; |
| 35808 | + dekkerMul2(rr, 1.0e+01, 0.0); |
| 35809 | + } |
| 35810 | + }else{ |
| 35811 | + while( e<=-100 ){ |
| 35812 | + e += 100; |
| 35813 | + dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); |
| 35814 | + } |
| 35815 | + while( e<=-10 ){ |
| 35816 | + e += 10; |
| 35817 | + dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); |
| 35818 | + } |
| 35819 | + while( e<=-1 ){ |
| 35820 | + e += 1; |
| 35821 | + dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); |
| 35822 | + } |
| 35823 | + } |
| 35824 | + *pResult = rr[0]+rr[1]; |
| 35825 | + if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300; |
| 35857 | 35826 | if( sign<0 ) *pResult = -*pResult; |
| 35858 | 35827 | assert( !sqlite3IsNaN(*pResult) ); |
| 35859 | 35828 | |
| 35860 | 35829 | atof_return: |
| 35861 | 35830 | /* return true if number and no extra non-whitespace characters after */ |
| | @@ -36172,13 +36141,14 @@ |
| 36172 | 36141 | */ |
| 36173 | 36142 | SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ |
| 36174 | 36143 | int i; |
| 36175 | 36144 | u64 v; |
| 36176 | 36145 | int e, exp = 0; |
| 36146 | + double rr[2]; |
| 36147 | + |
| 36177 | 36148 | p->isSpecial = 0; |
| 36178 | 36149 | p->z = p->zBuf; |
| 36179 | | - |
| 36180 | 36150 | assert( mxRound>0 ); |
| 36181 | 36151 | |
| 36182 | 36152 | /* Convert negative numbers to positive. Deal with Infinity, 0.0, and |
| 36183 | 36153 | ** NaN. */ |
| 36184 | 36154 | if( r<0.0 ){ |
| | @@ -36202,66 +36172,49 @@ |
| 36202 | 36172 | return; |
| 36203 | 36173 | } |
| 36204 | 36174 | |
| 36205 | 36175 | /* Multiply r by powers of ten until it lands somewhere in between |
| 36206 | 36176 | ** 1.0e+19 and 1.0e+17. |
| 36207 | | - */ |
| 36208 | | - if( sqlite3Config.bUseLongDouble ){ |
| 36209 | | - LONGDOUBLE_TYPE rr = r; |
| 36210 | | - if( rr>=1.0e+19 ){ |
| 36211 | | - while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; } |
| 36212 | | - while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; } |
| 36213 | | - while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; } |
| 36214 | | - }else{ |
| 36215 | | - while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; } |
| 36216 | | - while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; } |
| 36217 | | - while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; } |
| 36218 | | - } |
| 36219 | | - v = (u64)rr; |
| 36220 | | - }else{ |
| 36221 | | - /* If high-precision floating point is not available using "long double", |
| 36222 | | - ** then use Dekker-style double-double computation to increase the |
| 36223 | | - ** precision. |
| 36224 | | - ** |
| 36225 | | - ** The error terms on constants like 1.0e+100 computed using the |
| 36226 | | - ** decimal extension, for example as follows: |
| 36227 | | - ** |
| 36228 | | - ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100))); |
| 36229 | | - */ |
| 36230 | | - double rr[2]; |
| 36231 | | - rr[0] = r; |
| 36232 | | - rr[1] = 0.0; |
| 36233 | | - if( rr[0]>9.223372036854774784e+18 ){ |
| 36234 | | - while( rr[0]>9.223372036854774784e+118 ){ |
| 36235 | | - exp += 100; |
| 36236 | | - dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); |
| 36237 | | - } |
| 36238 | | - while( rr[0]>9.223372036854774784e+28 ){ |
| 36239 | | - exp += 10; |
| 36240 | | - dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); |
| 36241 | | - } |
| 36242 | | - while( rr[0]>9.223372036854774784e+18 ){ |
| 36243 | | - exp += 1; |
| 36244 | | - dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); |
| 36245 | | - } |
| 36246 | | - }else{ |
| 36247 | | - while( rr[0]<9.223372036854774784e-83 ){ |
| 36248 | | - exp -= 100; |
| 36249 | | - dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); |
| 36250 | | - } |
| 36251 | | - while( rr[0]<9.223372036854774784e+07 ){ |
| 36252 | | - exp -= 10; |
| 36253 | | - dekkerMul2(rr, 1.0e+10, 0.0); |
| 36254 | | - } |
| 36255 | | - while( rr[0]<9.22337203685477478e+17 ){ |
| 36256 | | - exp -= 1; |
| 36257 | | - dekkerMul2(rr, 1.0e+01, 0.0); |
| 36258 | | - } |
| 36259 | | - } |
| 36260 | | - v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1]; |
| 36261 | | - } |
| 36262 | | - |
| 36177 | + ** |
| 36178 | + ** Use Dekker-style double-double computation to increase the |
| 36179 | + ** precision. |
| 36180 | + ** |
| 36181 | + ** The error terms on constants like 1.0e+100 computed using the |
| 36182 | + ** decimal extension, for example as follows: |
| 36183 | + ** |
| 36184 | + ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100))); |
| 36185 | + */ |
| 36186 | + rr[0] = r; |
| 36187 | + rr[1] = 0.0; |
| 36188 | + if( rr[0]>9.223372036854774784e+18 ){ |
| 36189 | + while( rr[0]>9.223372036854774784e+118 ){ |
| 36190 | + exp += 100; |
| 36191 | + dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); |
| 36192 | + } |
| 36193 | + while( rr[0]>9.223372036854774784e+28 ){ |
| 36194 | + exp += 10; |
| 36195 | + dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); |
| 36196 | + } |
| 36197 | + while( rr[0]>9.223372036854774784e+18 ){ |
| 36198 | + exp += 1; |
| 36199 | + dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); |
| 36200 | + } |
| 36201 | + }else{ |
| 36202 | + while( rr[0]<9.223372036854774784e-83 ){ |
| 36203 | + exp -= 100; |
| 36204 | + dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); |
| 36205 | + } |
| 36206 | + while( rr[0]<9.223372036854774784e+07 ){ |
| 36207 | + exp -= 10; |
| 36208 | + dekkerMul2(rr, 1.0e+10, 0.0); |
| 36209 | + } |
| 36210 | + while( rr[0]<9.22337203685477478e+17 ){ |
| 36211 | + exp -= 1; |
| 36212 | + dekkerMul2(rr, 1.0e+01, 0.0); |
| 36213 | + } |
| 36214 | + } |
| 36215 | + v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1]; |
| 36263 | 36216 | |
| 36264 | 36217 | /* Extract significant digits. */ |
| 36265 | 36218 | i = sizeof(p->zBuf)-1; |
| 36266 | 36219 | assert( v>0 ); |
| 36267 | 36220 | while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; } |
| | @@ -65688,10 +65641,11 @@ |
| 65688 | 65641 | int nSehTry; /* Number of nested SEH_TRY{} blocks */ |
| 65689 | 65642 | u8 lockError; /* True if a locking error has occurred */ |
| 65690 | 65643 | #endif |
| 65691 | 65644 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 65692 | 65645 | WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ |
| 65646 | + int bGetSnapshot; /* Transaction opened for sqlite3_get_snapshot() */ |
| 65693 | 65647 | #endif |
| 65694 | 65648 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 65695 | 65649 | sqlite3 *db; |
| 65696 | 65650 | #endif |
| 65697 | 65651 | }; |
| | @@ -68244,11 +68198,11 @@ |
| 68244 | 68198 | assert( pWal->apWiData[0]!=0 ); |
| 68245 | 68199 | pInfo = walCkptInfo(pWal); |
| 68246 | 68200 | SEH_INJECT_FAULT; |
| 68247 | 68201 | if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame |
| 68248 | 68202 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 68249 | | - && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) |
| 68203 | + && ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0) |
| 68250 | 68204 | #endif |
| 68251 | 68205 | ){ |
| 68252 | 68206 | /* The WAL has been completely backfilled (or it is empty). |
| 68253 | 68207 | ** and can be safely ignored. |
| 68254 | 68208 | */ |
| | @@ -69644,11 +69598,24 @@ |
| 69644 | 69598 | */ |
| 69645 | 69599 | SQLITE_PRIVATE void sqlite3WalSnapshotOpen( |
| 69646 | 69600 | Wal *pWal, |
| 69647 | 69601 | sqlite3_snapshot *pSnapshot |
| 69648 | 69602 | ){ |
| 69649 | | - pWal->pSnapshot = (WalIndexHdr*)pSnapshot; |
| 69603 | + if( pSnapshot && ((WalIndexHdr*)pSnapshot)->iVersion==0 ){ |
| 69604 | + /* iVersion==0 means that this is a call to sqlite3_snapshot_get(). In |
| 69605 | + ** this case set the bGetSnapshot flag so that if the call to |
| 69606 | + ** sqlite3_snapshot_get() is about to read transaction on this wal |
| 69607 | + ** file, it does not take read-lock 0 if the wal file has been completely |
| 69608 | + ** checkpointed. Taking read-lock 0 would work, but then it would be |
| 69609 | + ** possible for a subsequent writer to destroy the snapshot even while |
| 69610 | + ** this connection is holding its read-transaction open. This is contrary |
| 69611 | + ** to user expectations, so we avoid it by not taking read-lock 0. */ |
| 69612 | + pWal->bGetSnapshot = 1; |
| 69613 | + }else{ |
| 69614 | + pWal->pSnapshot = (WalIndexHdr*)pSnapshot; |
| 69615 | + pWal->bGetSnapshot = 0; |
| 69616 | + } |
| 69650 | 69617 | } |
| 69651 | 69618 | |
| 69652 | 69619 | /* |
| 69653 | 69620 | ** Return a +ve value if snapshot p1 is newer than p2. A -ve value if |
| 69654 | 69621 | ** p1 is older than p2 and zero if p1 and p2 are the same snapshot. |
| | @@ -89592,11 +89559,11 @@ |
| 89592 | 89559 | /* The following two functions are used only within testcase() to prove |
| 89593 | 89560 | ** test coverage. These functions do no exist for production builds. |
| 89594 | 89561 | ** We must use separate SQLITE_NOINLINE functions here, since otherwise |
| 89595 | 89562 | ** optimizer code movement causes gcov to become very confused. |
| 89596 | 89563 | */ |
| 89597 | | -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) |
| 89564 | +#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) |
| 89598 | 89565 | static int SQLITE_NOINLINE doubleLt(double a, double b){ return a<b; } |
| 89599 | 89566 | static int SQLITE_NOINLINE doubleEq(double a, double b){ return a==b; } |
| 89600 | 89567 | #endif |
| 89601 | 89568 | |
| 89602 | 89569 | /* |
| | @@ -89607,17 +89574,10 @@ |
| 89607 | 89574 | SQLITE_PRIVATE int sqlite3IntFloatCompare(i64 i, double r){ |
| 89608 | 89575 | if( sqlite3IsNaN(r) ){ |
| 89609 | 89576 | /* SQLite considers NaN to be a NULL. And all integer values are greater |
| 89610 | 89577 | ** than NULL */ |
| 89611 | 89578 | return 1; |
| 89612 | | - } |
| 89613 | | - if( sqlite3Config.bUseLongDouble ){ |
| 89614 | | - LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; |
| 89615 | | - testcase( x<r ); |
| 89616 | | - testcase( x>r ); |
| 89617 | | - testcase( x==r ); |
| 89618 | | - return (x<r) ? -1 : (x>r); |
| 89619 | 89579 | }else{ |
| 89620 | 89580 | i64 y; |
| 89621 | 89581 | if( r<-9223372036854775808.0 ) return +1; |
| 89622 | 89582 | if( r>=9223372036854775808.0 ) return -1; |
| 89623 | 89583 | y = (i64)r; |
| | @@ -131787,11 +131747,17 @@ |
| 131787 | 131747 | #ifdef SQLITE_DEBUG |
| 131788 | 131748 | /* |
| 131789 | 131749 | ** Implementation of fpdecode(x,y,z) function. |
| 131790 | 131750 | ** |
| 131791 | 131751 | ** x is a real number that is to be decoded. y is the precision. |
| 131792 | | -** z is the maximum real precision. |
| 131752 | +** z is the maximum real precision. Return a string that shows the |
| 131753 | +** results of the sqlite3FpDecode() function. |
| 131754 | +** |
| 131755 | +** Used for testing and debugging only, specifically testing and debugging |
| 131756 | +** of the sqlite3FpDecode() function. This SQL function does not appear |
| 131757 | +** in production builds. This function is not an API and is subject to |
| 131758 | +** modification or removal in future versions of SQLite. |
| 131793 | 131759 | */ |
| 131794 | 131760 | static void fpdecodeFunc( |
| 131795 | 131761 | sqlite3_context *context, |
| 131796 | 131762 | int argc, |
| 131797 | 131763 | sqlite3_value **argv |
| | @@ -131811,10 +131777,86 @@ |
| 131811 | 131777 | sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN"); |
| 131812 | 131778 | }else{ |
| 131813 | 131779 | sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP); |
| 131814 | 131780 | } |
| 131815 | 131781 | sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); |
| 131782 | +} |
| 131783 | +#endif /* SQLITE_DEBUG */ |
| 131784 | + |
| 131785 | +#ifdef SQLITE_DEBUG |
| 131786 | +/* |
| 131787 | +** Implementation of parseuri(uri,flags) function. |
| 131788 | +** |
| 131789 | +** Required Arguments: |
| 131790 | +** "uri" The URI to parse. |
| 131791 | +** "flags" Bitmask of flags, as if to sqlite3_open_v2(). |
| 131792 | +** |
| 131793 | +** Additional arguments beyond the first two make calls to |
| 131794 | +** sqlite3_uri_key() for integers and sqlite3_uri_parameter for |
| 131795 | +** anything else. |
| 131796 | +** |
| 131797 | +** The result is a string showing the results of calling sqlite3ParseUri(). |
| 131798 | +** |
| 131799 | +** Used for testing and debugging only, specifically testing and debugging |
| 131800 | +** of the sqlite3ParseUri() function. This SQL function does not appear |
| 131801 | +** in production builds. This function is not an API and is subject to |
| 131802 | +** modification or removal in future versions of SQLite. |
| 131803 | +*/ |
| 131804 | +static void parseuriFunc( |
| 131805 | + sqlite3_context *ctx, |
| 131806 | + int argc, |
| 131807 | + sqlite3_value **argv |
| 131808 | +){ |
| 131809 | + sqlite3_str *pResult; |
| 131810 | + const char *zVfs; |
| 131811 | + const char *zUri; |
| 131812 | + unsigned int flgs; |
| 131813 | + int rc; |
| 131814 | + sqlite3_vfs *pVfs = 0; |
| 131815 | + char *zFile = 0; |
| 131816 | + char *zErr = 0; |
| 131817 | + |
| 131818 | + if( argc<2 ) return; |
| 131819 | + pVfs = sqlite3_vfs_find(0); |
| 131820 | + assert( pVfs ); |
| 131821 | + zVfs = pVfs->zName; |
| 131822 | + zUri = (const char*)sqlite3_value_text(argv[0]); |
| 131823 | + if( zUri==0 ) return; |
| 131824 | + flgs = (unsigned int)sqlite3_value_int(argv[1]); |
| 131825 | + rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr); |
| 131826 | + pResult = sqlite3_str_new(0); |
| 131827 | + if( pResult ){ |
| 131828 | + int i; |
| 131829 | + sqlite3_str_appendf(pResult, "rc=%d", rc); |
| 131830 | + sqlite3_str_appendf(pResult, ", flags=0x%x", flgs); |
| 131831 | + sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0); |
| 131832 | + sqlite3_str_appendf(pResult, ", err=%Q", zErr); |
| 131833 | + sqlite3_str_appendf(pResult, ", file=%Q", zFile); |
| 131834 | + if( zFile ){ |
| 131835 | + const char *z = zFile; |
| 131836 | + z += sqlite3Strlen30(z)+1; |
| 131837 | + while( z[0] ){ |
| 131838 | + sqlite3_str_appendf(pResult, ", %Q", z); |
| 131839 | + z += sqlite3Strlen30(z)+1; |
| 131840 | + } |
| 131841 | + for(i=2; i<argc; i++){ |
| 131842 | + const char *zArg; |
| 131843 | + if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){ |
| 131844 | + int k = sqlite3_value_int(argv[i]); |
| 131845 | + sqlite3_str_appendf(pResult, ", '%d:%q'",k,sqlite3_uri_key(zFile, k)); |
| 131846 | + }else if( (zArg = (const char*)sqlite3_value_text(argv[i]))!=0 ){ |
| 131847 | + sqlite3_str_appendf(pResult, ", '%q:%q'", |
| 131848 | + zArg, sqlite3_uri_parameter(zFile,zArg)); |
| 131849 | + }else{ |
| 131850 | + sqlite3_str_appendf(pResult, ", NULL"); |
| 131851 | + } |
| 131852 | + } |
| 131853 | + } |
| 131854 | + sqlite3_result_text(ctx, sqlite3_str_finish(pResult), -1, sqlite3_free); |
| 131855 | + } |
| 131856 | + sqlite3_free_filename(zFile); |
| 131857 | + sqlite3_free(zErr); |
| 131816 | 131858 | } |
| 131817 | 131859 | #endif /* SQLITE_DEBUG */ |
| 131818 | 131860 | |
| 131819 | 131861 | /* |
| 131820 | 131862 | ** All of the FuncDef structures in the aBuiltinFunc[] array above |
| | @@ -131887,10 +131929,11 @@ |
| 131887 | 131929 | FUNCTION(unicode, 1, 0, 0, unicodeFunc ), |
| 131888 | 131930 | FUNCTION(char, -1, 0, 0, charFunc ), |
| 131889 | 131931 | FUNCTION(abs, 1, 0, 0, absFunc ), |
| 131890 | 131932 | #ifdef SQLITE_DEBUG |
| 131891 | 131933 | FUNCTION(fpdecode, 3, 0, 0, fpdecodeFunc ), |
| 131934 | + FUNCTION(parseuri, -1, 0, 0, parseuriFunc ), |
| 131892 | 131935 | #endif |
| 131893 | 131936 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 131894 | 131937 | FUNCTION(round, 1, 0, 0, roundFunc ), |
| 131895 | 131938 | FUNCTION(round, 2, 0, 0, roundFunc ), |
| 131896 | 131939 | #endif |
| | @@ -141115,10 +141158,11 @@ |
| 141115 | 141158 | } |
| 141116 | 141159 | aRoot[0] = cnt; |
| 141117 | 141160 | |
| 141118 | 141161 | /* Make sure sufficient number of registers have been allocated */ |
| 141119 | 141162 | sqlite3TouchRegister(pParse, 8+cnt); |
| 141163 | + sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt); |
| 141120 | 141164 | sqlite3ClearTempRegCache(pParse); |
| 141121 | 141165 | |
| 141122 | 141166 | /* Do the b-tree integrity checks */ |
| 141123 | 141167 | sqlite3VdbeAddOp4(v, OP_IntegrityCk, 1, cnt, 8, (char*)aRoot,P4_INTARRAY); |
| 141124 | 141168 | sqlite3VdbeChangeP5(v, (u8)i); |
| | @@ -161344,24 +161388,29 @@ |
| 161344 | 161388 | }else if( op==TK_STRING ){ |
| 161345 | 161389 | assert( !ExprHasProperty(pRight, EP_IntValue) ); |
| 161346 | 161390 | z = (u8*)pRight->u.zToken; |
| 161347 | 161391 | } |
| 161348 | 161392 | if( z ){ |
| 161349 | | - |
| 161350 | | - /* Count the number of prefix characters prior to the first wildcard. |
| 161351 | | - ** If the underlying database has a UTF16LE encoding, then only consider |
| 161352 | | - ** ASCII characters. Note that the encoding of z[] is UTF8 - we are |
| 161353 | | - ** dealing with only UTF8 here in this code, but the database engine |
| 161354 | | - ** itself might be processing content using a different encoding. */ |
| 161393 | + /* Count the number of prefix bytes prior to the first wildcard. |
| 161394 | + ** or U+fffd character. If the underlying database has a UTF16LE |
| 161395 | + ** encoding, then only consider ASCII characters. Note that the |
| 161396 | + ** encoding of z[] is UTF8 - we are dealing with only UTF8 here in |
| 161397 | + ** this code, but the database engine itself might be processing |
| 161398 | + ** content using a different encoding. */ |
| 161355 | 161399 | cnt = 0; |
| 161356 | 161400 | while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ |
| 161357 | 161401 | cnt++; |
| 161358 | 161402 | if( c==wc[3] && z[cnt]!=0 ){ |
| 161359 | 161403 | cnt++; |
| 161360 | | - }else if( c>=0x80 && ENC(db)==SQLITE_UTF16LE ){ |
| 161361 | | - cnt--; |
| 161362 | | - break; |
| 161404 | + }else if( c>=0x80 ){ |
| 161405 | + const u8 *z2 = z+cnt-1; |
| 161406 | + if( sqlite3Utf8Read(&z2)==0xfffd || ENC(db)==SQLITE_UTF16LE ){ |
| 161407 | + cnt--; |
| 161408 | + break; |
| 161409 | + }else{ |
| 161410 | + cnt = (int)(z2-z); |
| 161411 | + } |
| 161363 | 161412 | } |
| 161364 | 161413 | } |
| 161365 | 161414 | |
| 161366 | 161415 | /* The optimization is possible only if (1) the pattern does not begin |
| 161367 | 161416 | ** with a wildcard and if (2) the non-wildcard prefix does not end with |
| | @@ -161369,11 +161418,11 @@ |
| 161369 | 161418 | ** a single escape character. The second condition is necessary so |
| 161370 | 161419 | ** that we can increment the prefix key to find an upper bound for the |
| 161371 | 161420 | ** range search. The third is because the caller assumes that the pattern |
| 161372 | 161421 | ** consists of at least one character after all escapes have been |
| 161373 | 161422 | ** removed. */ |
| 161374 | | - if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && 255!=(u8)z[cnt-1] ){ |
| 161423 | + if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && ALWAYS(255!=(u8)z[cnt-1]) ){ |
| 161375 | 161424 | Expr *pPrefix; |
| 161376 | 161425 | |
| 161377 | 161426 | /* A "complete" match if the pattern ends with "*" or "%" */ |
| 161378 | 161427 | *pisComplete = c==wc[0] && z[cnt+1]==0 && ENC(db)!=SQLITE_UTF16LE; |
| 161379 | 161428 | |
| | @@ -181161,36 +181210,10 @@ |
| 181161 | 181210 | ** all database files specified with a relative pathname. |
| 181162 | 181211 | ** |
| 181163 | 181212 | ** See also the "PRAGMA data_store_directory" SQL command. |
| 181164 | 181213 | */ |
| 181165 | 181214 | SQLITE_API char *sqlite3_data_directory = 0; |
| 181166 | | - |
| 181167 | | -/* |
| 181168 | | -** Determine whether or not high-precision (long double) floating point |
| 181169 | | -** math works correctly on CPU currently running. |
| 181170 | | -*/ |
| 181171 | | -static SQLITE_NOINLINE int hasHighPrecisionDouble(int rc){ |
| 181172 | | - if( sizeof(LONGDOUBLE_TYPE)<=8 ){ |
| 181173 | | - /* If the size of "long double" is not more than 8, then |
| 181174 | | - ** high-precision math is not possible. */ |
| 181175 | | - return 0; |
| 181176 | | - }else{ |
| 181177 | | - /* Just because sizeof(long double)>8 does not mean that the underlying |
| 181178 | | - ** hardware actually supports high-precision floating point. For example, |
| 181179 | | - ** clearing the 0x100 bit in the floating-point control word on Intel |
| 181180 | | - ** processors will make long double work like double, even though long |
| 181181 | | - ** double takes up more space. The only way to determine if long double |
| 181182 | | - ** actually works is to run an experiment. */ |
| 181183 | | - LONGDOUBLE_TYPE a, b, c; |
| 181184 | | - rc++; |
| 181185 | | - a = 1.0+rc*0.1; |
| 181186 | | - b = 1.0e+18+rc*25.0; |
| 181187 | | - c = a+b; |
| 181188 | | - return b!=c; |
| 181189 | | - } |
| 181190 | | -} |
| 181191 | | - |
| 181192 | 181215 | |
| 181193 | 181216 | /* |
| 181194 | 181217 | ** Initialize SQLite. |
| 181195 | 181218 | ** |
| 181196 | 181219 | ** This routine must be called to initialize the memory allocation, |
| | @@ -181382,17 +181405,10 @@ |
| 181382 | 181405 | if( bRunExtraInit ){ |
| 181383 | 181406 | int SQLITE_EXTRA_INIT(const char*); |
| 181384 | 181407 | rc = SQLITE_EXTRA_INIT(0); |
| 181385 | 181408 | } |
| 181386 | 181409 | #endif |
| 181387 | | - |
| 181388 | | - /* Experimentally determine if high-precision floating point is |
| 181389 | | - ** available. */ |
| 181390 | | -#ifndef SQLITE_OMIT_WSD |
| 181391 | | - sqlite3Config.bUseLongDouble = hasHighPrecisionDouble(rc); |
| 181392 | | -#endif |
| 181393 | | - |
| 181394 | 181410 | return rc; |
| 181395 | 181411 | } |
| 181396 | 181412 | |
| 181397 | 181413 | /* |
| 181398 | 181414 | ** Undo the effects of sqlite3_initialize(). Must not be called while |
| | @@ -185640,28 +185656,10 @@ |
| 185640 | 185656 | *pI1 = rLogEst; |
| 185641 | 185657 | *pU64 = sqlite3LogEstToInt(rLogEst); |
| 185642 | 185658 | *pI2 = sqlite3LogEst(*pU64); |
| 185643 | 185659 | break; |
| 185644 | 185660 | } |
| 185645 | | - |
| 185646 | | -#if !defined(SQLITE_OMIT_WSD) |
| 185647 | | - /* sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, int X); |
| 185648 | | - ** |
| 185649 | | - ** X<0 Make no changes to the bUseLongDouble. Just report value. |
| 185650 | | - ** X==0 Disable bUseLongDouble |
| 185651 | | - ** X==1 Enable bUseLongDouble |
| 185652 | | - ** X>=2 Set bUseLongDouble to its default value for this platform |
| 185653 | | - */ |
| 185654 | | - case SQLITE_TESTCTRL_USELONGDOUBLE: { |
| 185655 | | - int b = va_arg(ap, int); |
| 185656 | | - if( b>=2 ) b = hasHighPrecisionDouble(b); |
| 185657 | | - if( b>=0 ) sqlite3Config.bUseLongDouble = b>0; |
| 185658 | | - rc = sqlite3Config.bUseLongDouble!=0; |
| 185659 | | - break; |
| 185660 | | - } |
| 185661 | | -#endif |
| 185662 | | - |
| 185663 | 185661 | |
| 185664 | 185662 | #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) |
| 185665 | 185663 | /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue) |
| 185666 | 185664 | ** |
| 185667 | 185665 | ** If "id" is an integer between 1 and SQLITE_NTUNE then set the value |
| | @@ -185966,11 +185964,15 @@ |
| 185966 | 185964 | if( db->autoCommit==0 ){ |
| 185967 | 185965 | int iDb = sqlite3FindDbName(db, zDb); |
| 185968 | 185966 | if( iDb==0 || iDb>1 ){ |
| 185969 | 185967 | Btree *pBt = db->aDb[iDb].pBt; |
| 185970 | 185968 | if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){ |
| 185969 | + Pager *pPager = sqlite3BtreePager(pBt); |
| 185970 | + i64 dummy = 0; |
| 185971 | + sqlite3PagerSnapshotOpen(pPager, (sqlite3_snapshot*)&dummy); |
| 185971 | 185972 | rc = sqlite3BtreeBeginTrans(pBt, 0, 0); |
| 185973 | + sqlite3PagerSnapshotOpen(pPager, 0); |
| 185972 | 185974 | if( rc==SQLITE_OK ){ |
| 185973 | 185975 | rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); |
| 185974 | 185976 | } |
| 185975 | 185977 | } |
| 185976 | 185978 | } |
| | @@ -225801,12 +225803,12 @@ |
| 225801 | 225803 | }; |
| 225802 | 225804 | |
| 225803 | 225805 | struct DbpageTable { |
| 225804 | 225806 | sqlite3_vtab base; /* Base class. Must be first */ |
| 225805 | 225807 | sqlite3 *db; /* The database */ |
| 225806 | | - int nTrunc; /* Entries in aTrunc[] */ |
| 225807 | | - Pgno *aTrunc; /* Truncation size for each database */ |
| 225808 | + int iDbTrunc; /* Database to truncate */ |
| 225809 | + Pgno pgnoTrunc; /* Size to truncate to */ |
| 225808 | 225810 | }; |
| 225809 | 225811 | |
| 225810 | 225812 | /* Columns */ |
| 225811 | 225813 | #define DBPAGE_COLUMN_PGNO 0 |
| 225812 | 225814 | #define DBPAGE_COLUMN_DATA 1 |
| | @@ -225851,12 +225853,10 @@ |
| 225851 | 225853 | |
| 225852 | 225854 | /* |
| 225853 | 225855 | ** Disconnect from or destroy a dbpagevfs virtual table. |
| 225854 | 225856 | */ |
| 225855 | 225857 | static int dbpageDisconnect(sqlite3_vtab *pVtab){ |
| 225856 | | - DbpageTable *pTab = (DbpageTable *)pVtab; |
| 225857 | | - sqlite3_free(pTab->aTrunc); |
| 225858 | 225858 | sqlite3_free(pVtab); |
| 225859 | 225859 | return SQLITE_OK; |
| 225860 | 225860 | } |
| 225861 | 225861 | |
| 225862 | 225862 | /* |
| | @@ -226119,23 +226119,16 @@ |
| 226119 | 226119 | } |
| 226120 | 226120 | szPage = sqlite3BtreeGetPageSize(pBt); |
| 226121 | 226121 | if( sqlite3_value_type(argv[3])!=SQLITE_BLOB |
| 226122 | 226122 | || sqlite3_value_bytes(argv[3])!=szPage |
| 226123 | 226123 | ){ |
| 226124 | | - if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert ){ |
| 226125 | | - if( iDb>=pTab->nTrunc ){ |
| 226126 | | - testcase( pTab->aTrunc!=0 ); |
| 226127 | | - pTab->aTrunc = sqlite3_realloc(pTab->aTrunc, (iDb+1)*sizeof(Pgno)); |
| 226128 | | - if( pTab->aTrunc ){ |
| 226129 | | - int j; |
| 226130 | | - for(j=pTab->nTrunc; j<iDb; j++) pTab->aTrunc[j] = 0; |
| 226131 | | - pTab->nTrunc = iDb+1; |
| 226132 | | - }else{ |
| 226133 | | - return SQLITE_NOMEM; |
| 226134 | | - } |
| 226135 | | - } |
| 226136 | | - pTab->aTrunc[iDb] = pgno; |
| 226124 | + if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert && pgno>1 ){ |
| 226125 | + /* "INSERT INTO dbpage($PGNO,NULL)" causes page number $PGNO and |
| 226126 | + ** all subsequent pages to be deleted. */ |
| 226127 | + pTab->iDbTrunc = iDb; |
| 226128 | + pgno--; |
| 226129 | + pTab->pgnoTrunc = pgno; |
| 226137 | 226130 | }else{ |
| 226138 | 226131 | zErr = "bad page value"; |
| 226139 | 226132 | goto update_fail; |
| 226140 | 226133 | } |
| 226141 | 226134 | } |
| | @@ -226144,10 +226137,11 @@ |
| 226144 | 226137 | if( rc==SQLITE_OK ){ |
| 226145 | 226138 | const void *pData = sqlite3_value_blob(argv[3]); |
| 226146 | 226139 | if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){ |
| 226147 | 226140 | unsigned char *aPage = sqlite3PagerGetData(pDbPage); |
| 226148 | 226141 | memcpy(aPage, pData, szPage); |
| 226142 | + pTab->pgnoTrunc = 0; |
| 226149 | 226143 | } |
| 226150 | 226144 | } |
| 226151 | 226145 | sqlite3PagerUnref(pDbPage); |
| 226152 | 226146 | return rc; |
| 226153 | 226147 | |
| | @@ -226167,33 +226161,35 @@ |
| 226167 | 226161 | int i; |
| 226168 | 226162 | for(i=0; i<db->nDb; i++){ |
| 226169 | 226163 | Btree *pBt = db->aDb[i].pBt; |
| 226170 | 226164 | if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0); |
| 226171 | 226165 | } |
| 226172 | | - if( pTab->nTrunc>0 ){ |
| 226173 | | - memset(pTab->aTrunc, 0, sizeof(pTab->aTrunc[0])*pTab->nTrunc); |
| 226174 | | - } |
| 226166 | + pTab->pgnoTrunc = 0; |
| 226175 | 226167 | return SQLITE_OK; |
| 226176 | 226168 | } |
| 226177 | 226169 | |
| 226178 | 226170 | /* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT |
| 226179 | 226171 | */ |
| 226180 | 226172 | static int dbpageSync(sqlite3_vtab *pVtab){ |
| 226181 | | - int iDb; |
| 226173 | + DbpageTable *pTab = (DbpageTable *)pVtab; |
| 226174 | + if( pTab->pgnoTrunc>0 ){ |
| 226175 | + Btree *pBt = pTab->db->aDb[pTab->iDbTrunc].pBt; |
| 226176 | + Pager *pPager = sqlite3BtreePager(pBt); |
| 226177 | + sqlite3PagerTruncateImage(pPager, pTab->pgnoTrunc); |
| 226178 | + } |
| 226179 | + pTab->pgnoTrunc = 0; |
| 226180 | + return SQLITE_OK; |
| 226181 | +} |
| 226182 | + |
| 226183 | +/* Cancel any pending truncate. |
| 226184 | +*/ |
| 226185 | +static int dbpageRollbackTo(sqlite3_vtab *pVtab, int notUsed1){ |
| 226182 | 226186 | DbpageTable *pTab = (DbpageTable *)pVtab; |
| 226183 | | - |
| 226184 | | - for(iDb=0; iDb<pTab->nTrunc; iDb++){ |
| 226185 | | - if( pTab->aTrunc[iDb]>0 ){ |
| 226186 | | - Btree *pBt = pTab->db->aDb[iDb].pBt; |
| 226187 | | - Pager *pPager = sqlite3BtreePager(pBt); |
| 226188 | | - sqlite3PagerTruncateImage(pPager, pTab->aTrunc[iDb]); |
| 226189 | | - pTab->aTrunc[iDb] = 0; |
| 226190 | | - } |
| 226191 | | - } |
| 226187 | + pTab->pgnoTrunc = 0; |
| 226188 | + (void)notUsed1; |
| 226192 | 226189 | return SQLITE_OK; |
| 226193 | 226190 | } |
| 226194 | | - |
| 226195 | 226191 | |
| 226196 | 226192 | /* |
| 226197 | 226193 | ** Invoke this routine to register the "dbpage" virtual table module |
| 226198 | 226194 | */ |
| 226199 | 226195 | SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ |
| | @@ -226218,11 +226214,11 @@ |
| 226218 | 226214 | 0, /* xRollback */ |
| 226219 | 226215 | 0, /* xFindMethod */ |
| 226220 | 226216 | 0, /* xRename */ |
| 226221 | 226217 | 0, /* xSavepoint */ |
| 226222 | 226218 | 0, /* xRelease */ |
| 226223 | | - 0, /* xRollbackTo */ |
| 226219 | + dbpageRollbackTo, /* xRollbackTo */ |
| 226224 | 226220 | 0, /* xShadowName */ |
| 226225 | 226221 | 0 /* xIntegrity */ |
| 226226 | 226222 | }; |
| 226227 | 226223 | return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); |
| 226228 | 226224 | } |
| | @@ -233747,10 +233743,11 @@ |
| 233747 | 233743 | u8 *abUnindexed; /* True for unindexed columns */ |
| 233748 | 233744 | int nPrefix; /* Number of prefix indexes */ |
| 233749 | 233745 | int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */ |
| 233750 | 233746 | int eContent; /* An FTS5_CONTENT value */ |
| 233751 | 233747 | int bContentlessDelete; /* "contentless_delete=" option (dflt==0) */ |
| 233748 | + int bContentlessUnindexed; /* "contentless_unindexed=" option (dflt=0) */ |
| 233752 | 233749 | char *zContent; /* content table */ |
| 233753 | 233750 | char *zContentRowid; /* "content_rowid=" option value */ |
| 233754 | 233751 | int bColumnsize; /* "columnsize=" option value (dflt==1) */ |
| 233755 | 233752 | int bTokendata; /* "tokendata=" option value (dflt==0) */ |
| 233756 | 233753 | int bLocale; /* "locale=" option value (dflt==0) */ |
| | @@ -233785,13 +233782,14 @@ |
| 233785 | 233782 | ** the expected version if the 'secure-delete' option has ever been |
| 233786 | 233783 | ** set on the table. */ |
| 233787 | 233784 | #define FTS5_CURRENT_VERSION 4 |
| 233788 | 233785 | #define FTS5_CURRENT_VERSION_SECUREDELETE 5 |
| 233789 | 233786 | |
| 233790 | | -#define FTS5_CONTENT_NORMAL 0 |
| 233791 | | -#define FTS5_CONTENT_NONE 1 |
| 233792 | | -#define FTS5_CONTENT_EXTERNAL 2 |
| 233787 | +#define FTS5_CONTENT_NORMAL 0 |
| 233788 | +#define FTS5_CONTENT_NONE 1 |
| 233789 | +#define FTS5_CONTENT_EXTERNAL 2 |
| 233790 | +#define FTS5_CONTENT_UNINDEXED 3 |
| 233793 | 233791 | |
| 233794 | 233792 | #define FTS5_DETAIL_FULL 0 |
| 233795 | 233793 | #define FTS5_DETAIL_NONE 1 |
| 233796 | 233794 | #define FTS5_DETAIL_COLUMNS 2 |
| 233797 | 233795 | |
| | @@ -234247,11 +234245,11 @@ |
| 234247 | 234245 | |
| 234248 | 234246 | static int sqlite3Fts5DropAll(Fts5Config*); |
| 234249 | 234247 | static int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **); |
| 234250 | 234248 | |
| 234251 | 234249 | static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**, int); |
| 234252 | | -static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*); |
| 234250 | +static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, int, sqlite3_value**, i64*); |
| 234253 | 234251 | static int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64); |
| 234254 | 234252 | |
| 234255 | 234253 | static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg); |
| 234256 | 234254 | |
| 234257 | 234255 | static int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**); |
| | @@ -237454,10 +237452,11 @@ |
| 237454 | 237452 | const char *zArg, /* Argument to parse */ |
| 237455 | 237453 | char **pzErr /* OUT: Error message */ |
| 237456 | 237454 | ){ |
| 237457 | 237455 | int rc = SQLITE_OK; |
| 237458 | 237456 | int nCmd = (int)strlen(zCmd); |
| 237457 | + |
| 237459 | 237458 | if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){ |
| 237460 | 237459 | const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES; |
| 237461 | 237460 | const char *p; |
| 237462 | 237461 | int bFirst = 1; |
| 237463 | 237462 | if( pConfig->aPrefix==0 ){ |
| | @@ -237572,10 +237571,20 @@ |
| 237572 | 237571 | }else{ |
| 237573 | 237572 | pConfig->bContentlessDelete = (zArg[0]=='1'); |
| 237574 | 237573 | } |
| 237575 | 237574 | return rc; |
| 237576 | 237575 | } |
| 237576 | + |
| 237577 | + if( sqlite3_strnicmp("contentless_unindexed", zCmd, nCmd)==0 ){ |
| 237578 | + if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){ |
| 237579 | + *pzErr = sqlite3_mprintf("malformed contentless_delete=... directive"); |
| 237580 | + rc = SQLITE_ERROR; |
| 237581 | + }else{ |
| 237582 | + pConfig->bContentlessUnindexed = (zArg[0]=='1'); |
| 237583 | + } |
| 237584 | + return rc; |
| 237585 | + } |
| 237577 | 237586 | |
| 237578 | 237587 | if( sqlite3_strnicmp("content_rowid", zCmd, nCmd)==0 ){ |
| 237579 | 237588 | if( pConfig->zContentRowid ){ |
| 237580 | 237589 | *pzErr = sqlite3_mprintf("multiple content_rowid=... directives"); |
| 237581 | 237590 | rc = SQLITE_ERROR; |
| | @@ -237690,11 +237699,12 @@ |
| 237690 | 237699 | |
| 237691 | 237700 | static int fts5ConfigParseColumn( |
| 237692 | 237701 | Fts5Config *p, |
| 237693 | 237702 | char *zCol, |
| 237694 | 237703 | char *zArg, |
| 237695 | | - char **pzErr |
| 237704 | + char **pzErr, |
| 237705 | + int *pbUnindexed |
| 237696 | 237706 | ){ |
| 237697 | 237707 | int rc = SQLITE_OK; |
| 237698 | 237708 | if( 0==sqlite3_stricmp(zCol, FTS5_RANK_NAME) |
| 237699 | 237709 | || 0==sqlite3_stricmp(zCol, FTS5_ROWID_NAME) |
| 237700 | 237710 | ){ |
| | @@ -237701,10 +237711,11 @@ |
| 237701 | 237711 | *pzErr = sqlite3_mprintf("reserved fts5 column name: %s", zCol); |
| 237702 | 237712 | rc = SQLITE_ERROR; |
| 237703 | 237713 | }else if( zArg ){ |
| 237704 | 237714 | if( 0==sqlite3_stricmp(zArg, "unindexed") ){ |
| 237705 | 237715 | p->abUnindexed[p->nCol] = 1; |
| 237716 | + *pbUnindexed = 1; |
| 237706 | 237717 | }else{ |
| 237707 | 237718 | *pzErr = sqlite3_mprintf("unrecognized column option: %s", zArg); |
| 237708 | 237719 | rc = SQLITE_ERROR; |
| 237709 | 237720 | } |
| 237710 | 237721 | } |
| | @@ -237721,15 +237732,21 @@ |
| 237721 | 237732 | int rc = SQLITE_OK; |
| 237722 | 237733 | Fts5Buffer buf = {0, 0, 0}; |
| 237723 | 237734 | |
| 237724 | 237735 | sqlite3Fts5BufferAppendPrintf(&rc, &buf, "T.%Q", p->zContentRowid); |
| 237725 | 237736 | if( p->eContent!=FTS5_CONTENT_NONE ){ |
| 237737 | + assert( p->eContent==FTS5_CONTENT_EXTERNAL |
| 237738 | + || p->eContent==FTS5_CONTENT_NORMAL |
| 237739 | + || p->eContent==FTS5_CONTENT_UNINDEXED |
| 237740 | + ); |
| 237726 | 237741 | for(i=0; i<p->nCol; i++){ |
| 237727 | 237742 | if( p->eContent==FTS5_CONTENT_EXTERNAL ){ |
| 237728 | 237743 | sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.%Q", p->azCol[i]); |
| 237729 | | - }else{ |
| 237744 | + }else if( p->eContent==FTS5_CONTENT_NORMAL || p->abUnindexed[i] ){ |
| 237730 | 237745 | sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i); |
| 237746 | + }else{ |
| 237747 | + sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL"); |
| 237731 | 237748 | } |
| 237732 | 237749 | } |
| 237733 | 237750 | } |
| 237734 | 237751 | if( p->eContent==FTS5_CONTENT_NORMAL && p->bLocale ){ |
| 237735 | 237752 | for(i=0; i<p->nCol; i++){ |
| | @@ -237768,10 +237785,11 @@ |
| 237768 | 237785 | ){ |
| 237769 | 237786 | int rc = SQLITE_OK; /* Return code */ |
| 237770 | 237787 | Fts5Config *pRet; /* New object to return */ |
| 237771 | 237788 | int i; |
| 237772 | 237789 | sqlite3_int64 nByte; |
| 237790 | + int bUnindexed = 0; /* True if there are one or more UNINDEXED */ |
| 237773 | 237791 | |
| 237774 | 237792 | *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config)); |
| 237775 | 237793 | if( pRet==0 ) return SQLITE_NOMEM; |
| 237776 | 237794 | memset(pRet, 0, sizeof(Fts5Config)); |
| 237777 | 237795 | pRet->pGlobal = pGlobal; |
| | @@ -237827,11 +237845,11 @@ |
| 237827 | 237845 | ALWAYS(zOne)?zOne:"", |
| 237828 | 237846 | zTwo?zTwo:"", |
| 237829 | 237847 | pzErr |
| 237830 | 237848 | ); |
| 237831 | 237849 | }else{ |
| 237832 | | - rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr); |
| 237850 | + rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr, &bUnindexed); |
| 237833 | 237851 | zOne = 0; |
| 237834 | 237852 | } |
| 237835 | 237853 | } |
| 237836 | 237854 | } |
| 237837 | 237855 | |
| | @@ -237858,18 +237876,34 @@ |
| 237858 | 237876 | *pzErr = sqlite3_mprintf( |
| 237859 | 237877 | "contentless_delete=1 is incompatible with columnsize=0" |
| 237860 | 237878 | ); |
| 237861 | 237879 | rc = SQLITE_ERROR; |
| 237862 | 237880 | } |
| 237881 | + |
| 237882 | + /* We only allow contentless_unindexed=1 if the table is actually a |
| 237883 | + ** contentless one. |
| 237884 | + */ |
| 237885 | + if( rc==SQLITE_OK |
| 237886 | + && pRet->bContentlessUnindexed |
| 237887 | + && pRet->eContent!=FTS5_CONTENT_NONE |
| 237888 | + ){ |
| 237889 | + *pzErr = sqlite3_mprintf( |
| 237890 | + "contentless_unindexed=1 requires a contentless table" |
| 237891 | + ); |
| 237892 | + rc = SQLITE_ERROR; |
| 237893 | + } |
| 237863 | 237894 | |
| 237864 | 237895 | /* If no zContent option was specified, fill in the default values. */ |
| 237865 | 237896 | if( rc==SQLITE_OK && pRet->zContent==0 ){ |
| 237866 | 237897 | const char *zTail = 0; |
| 237867 | 237898 | assert( pRet->eContent==FTS5_CONTENT_NORMAL |
| 237868 | 237899 | || pRet->eContent==FTS5_CONTENT_NONE |
| 237869 | 237900 | ); |
| 237870 | 237901 | if( pRet->eContent==FTS5_CONTENT_NORMAL ){ |
| 237902 | + zTail = "content"; |
| 237903 | + }else if( bUnindexed && pRet->bContentlessUnindexed ){ |
| 237904 | + pRet->eContent = FTS5_CONTENT_UNINDEXED; |
| 237871 | 237905 | zTail = "content"; |
| 237872 | 237906 | }else if( pRet->bColumnsize ){ |
| 237873 | 237907 | zTail = "docsize"; |
| 237874 | 237908 | } |
| 237875 | 237909 | |
| | @@ -247040,10 +247074,15 @@ |
| 247040 | 247074 | if( nPercent>=pConfig->nDeleteMerge && nPercent>nBest ){ |
| 247041 | 247075 | iRet = ii; |
| 247042 | 247076 | nBest = nPercent; |
| 247043 | 247077 | } |
| 247044 | 247078 | } |
| 247079 | + |
| 247080 | + /* If pLvl is already the input level to an ongoing merge, look no |
| 247081 | + ** further for a merge candidate. The caller should be allowed to |
| 247082 | + ** continue merging from pLvl first. */ |
| 247083 | + if( pLvl->nMerge ) break; |
| 247045 | 247084 | } |
| 247046 | 247085 | } |
| 247047 | 247086 | return iRet; |
| 247048 | 247087 | } |
| 247049 | 247088 | |
| | @@ -250964,11 +251003,11 @@ |
| 250964 | 251003 | return rc; |
| 250965 | 251004 | } |
| 250966 | 251005 | |
| 250967 | 251006 | /* |
| 250968 | 251007 | ** We must have a single struct=? constraint that will be passed through |
| 250969 | | -** into the xFilter method. If there is no valid stmt=? constraint, |
| 251008 | +** into the xFilter method. If there is no valid struct=? constraint, |
| 250970 | 251009 | ** then return an SQLITE_CONSTRAINT error. |
| 250971 | 251010 | */ |
| 250972 | 251011 | static int fts5structBestIndexMethod( |
| 250973 | 251012 | sqlite3_vtab *tab, |
| 250974 | 251013 | sqlite3_index_info *pIdxInfo |
| | @@ -251555,14 +251594,20 @@ |
| 251555 | 251594 | #else |
| 251556 | 251595 | # define fts5CheckTransactionState(x,y,z) |
| 251557 | 251596 | #endif |
| 251558 | 251597 | |
| 251559 | 251598 | /* |
| 251560 | | -** Return true if pTab is a contentless table. |
| 251599 | +** Return true if pTab is a contentless table. If parameter bIncludeUnindexed |
| 251600 | +** is true, this includes contentless tables that store UNINDEXED columns |
| 251601 | +** only. |
| 251561 | 251602 | */ |
| 251562 | | -static int fts5IsContentless(Fts5FullTable *pTab){ |
| 251563 | | - return pTab->p.pConfig->eContent==FTS5_CONTENT_NONE; |
| 251603 | +static int fts5IsContentless(Fts5FullTable *pTab, int bIncludeUnindexed){ |
| 251604 | + int eContent = pTab->p.pConfig->eContent; |
| 251605 | + return ( |
| 251606 | + eContent==FTS5_CONTENT_NONE |
| 251607 | + || (bIncludeUnindexed && eContent==FTS5_CONTENT_UNINDEXED) |
| 251608 | + ); |
| 251564 | 251609 | } |
| 251565 | 251610 | |
| 251566 | 251611 | /* |
| 251567 | 251612 | ** Delete a virtual table handle allocated by fts5InitVtab(). |
| 251568 | 251613 | */ |
| | @@ -252949,11 +252994,11 @@ |
| 252949 | 252994 | }else{ |
| 252950 | 252995 | rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage); |
| 252951 | 252996 | } |
| 252952 | 252997 | bLoadConfig = 1; |
| 252953 | 252998 | }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){ |
| 252954 | | - if( pConfig->eContent==FTS5_CONTENT_NONE ){ |
| 252999 | + if( fts5IsContentless(pTab, 1) ){ |
| 252955 | 253000 | fts5SetVtabError(pTab, |
| 252956 | 253001 | "'rebuild' may not be used with a contentless fts5 table" |
| 252957 | 253002 | ); |
| 252958 | 253003 | rc = SQLITE_ERROR; |
| 252959 | 253004 | }else{ |
| | @@ -253018,17 +253063,78 @@ |
| 253018 | 253063 | sqlite3_value **apVal, |
| 253019 | 253064 | i64 *piRowid |
| 253020 | 253065 | ){ |
| 253021 | 253066 | int rc = *pRc; |
| 253022 | 253067 | if( rc==SQLITE_OK ){ |
| 253023 | | - rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid); |
| 253068 | + rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, 0, apVal, piRowid); |
| 253024 | 253069 | } |
| 253025 | 253070 | if( rc==SQLITE_OK ){ |
| 253026 | 253071 | rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid); |
| 253027 | 253072 | } |
| 253028 | 253073 | *pRc = rc; |
| 253029 | 253074 | } |
| 253075 | + |
| 253076 | +/* |
| 253077 | +** |
| 253078 | +** This function is called when the user attempts an UPDATE on a contentless |
| 253079 | +** table. Parameter bRowidModified is true if the UPDATE statement modifies |
| 253080 | +** the rowid value. Parameter apVal[] contains the new values for each user |
| 253081 | +** defined column of the fts5 table. pConfig is the configuration object of the |
| 253082 | +** table being updated (guaranteed to be contentless). The contentless_delete=1 |
| 253083 | +** and contentless_unindexed=1 options may or may not be set. |
| 253084 | +** |
| 253085 | +** This function returns SQLITE_OK if the UPDATE can go ahead, or an SQLite |
| 253086 | +** error code if it cannot. In this case an error message is also loaded into |
| 253087 | +** pConfig. Output parameter (*pbContent) is set to true if the caller should |
| 253088 | +** update the %_content table only - not the FTS index or any other shadow |
| 253089 | +** table. This occurs when an UPDATE modifies only UNINDEXED columns of the |
| 253090 | +** table. |
| 253091 | +** |
| 253092 | +** An UPDATE may proceed if: |
| 253093 | +** |
| 253094 | +** * The only columns modified are UNINDEXED columns, or |
| 253095 | +** |
| 253096 | +** * The contentless_delete=1 option was specified and all of the indexed |
| 253097 | +** columns (not a subset) have been modified. |
| 253098 | +*/ |
| 253099 | +static int fts5ContentlessUpdate( |
| 253100 | + Fts5Config *pConfig, |
| 253101 | + sqlite3_value **apVal, |
| 253102 | + int bRowidModified, |
| 253103 | + int *pbContent |
| 253104 | +){ |
| 253105 | + int ii; |
| 253106 | + int bSeenIndex = 0; /* Have seen modified indexed column */ |
| 253107 | + int bSeenIndexNC = 0; /* Have seen unmodified indexed column */ |
| 253108 | + int rc = SQLITE_OK; |
| 253109 | + |
| 253110 | + for(ii=0; ii<pConfig->nCol; ii++){ |
| 253111 | + if( pConfig->abUnindexed[ii]==0 ){ |
| 253112 | + if( sqlite3_value_nochange(apVal[ii]) ){ |
| 253113 | + bSeenIndexNC++; |
| 253114 | + }else{ |
| 253115 | + bSeenIndex++; |
| 253116 | + } |
| 253117 | + } |
| 253118 | + } |
| 253119 | + |
| 253120 | + if( bSeenIndex==0 && bRowidModified==0 ){ |
| 253121 | + *pbContent = 1; |
| 253122 | + }else{ |
| 253123 | + if( bSeenIndexNC || pConfig->bContentlessDelete==0 ){ |
| 253124 | + rc = SQLITE_ERROR; |
| 253125 | + sqlite3Fts5ConfigErrmsg(pConfig, |
| 253126 | + (pConfig->bContentlessDelete ? |
| 253127 | + "%s a subset of columns on fts5 contentless-delete table: %s" : |
| 253128 | + "%s contentless fts5 table: %s") |
| 253129 | + , "cannot UPDATE", pConfig->zName |
| 253130 | + ); |
| 253131 | + } |
| 253132 | + } |
| 253133 | + |
| 253134 | + return rc; |
| 253135 | +} |
| 253030 | 253136 | |
| 253031 | 253137 | /* |
| 253032 | 253138 | ** This function is the implementation of the xUpdate callback used by |
| 253033 | 253139 | ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be |
| 253034 | 253140 | ** inserted, updated or deleted. |
| | @@ -253112,29 +253218,24 @@ |
| 253112 | 253218 | } |
| 253113 | 253219 | |
| 253114 | 253220 | assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL ); |
| 253115 | 253221 | assert( nArg!=1 || eType0==SQLITE_INTEGER ); |
| 253116 | 253222 | |
| 253117 | | - /* Filter out attempts to run UPDATE or DELETE on contentless tables. |
| 253118 | | - ** This is not suported. Except - they are both supported if the CREATE |
| 253119 | | - ** VIRTUAL TABLE statement contained "contentless_delete=1". */ |
| 253120 | | - if( eType0==SQLITE_INTEGER |
| 253121 | | - && pConfig->eContent==FTS5_CONTENT_NONE |
| 253122 | | - && pConfig->bContentlessDelete==0 |
| 253123 | | - ){ |
| 253124 | | - pTab->p.base.zErrMsg = sqlite3_mprintf( |
| 253125 | | - "cannot %s contentless fts5 table: %s", |
| 253126 | | - (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName |
| 253127 | | - ); |
| 253128 | | - rc = SQLITE_ERROR; |
| 253129 | | - } |
| 253130 | | - |
| 253131 | 253223 | /* DELETE */ |
| 253132 | | - else if( nArg==1 ){ |
| 253133 | | - i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ |
| 253134 | | - rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0); |
| 253135 | | - bUpdateOrDelete = 1; |
| 253224 | + if( nArg==1 ){ |
| 253225 | + /* It is only possible to DELETE from a contentless table if the |
| 253226 | + ** contentless_delete=1 flag is set. */ |
| 253227 | + if( fts5IsContentless(pTab, 1) && pConfig->bContentlessDelete==0 ){ |
| 253228 | + fts5SetVtabError(pTab, |
| 253229 | + "cannot DELETE from contentless fts5 table: %s", pConfig->zName |
| 253230 | + ); |
| 253231 | + rc = SQLITE_ERROR; |
| 253232 | + }else{ |
| 253233 | + i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ |
| 253234 | + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0); |
| 253235 | + bUpdateOrDelete = 1; |
| 253236 | + } |
| 253136 | 253237 | } |
| 253137 | 253238 | |
| 253138 | 253239 | /* INSERT or UPDATE */ |
| 253139 | 253240 | else{ |
| 253140 | 253241 | int eType1 = sqlite3_value_numeric_type(apVal[1]); |
| | @@ -253164,39 +253265,59 @@ |
| 253164 | 253265 | fts5StorageInsert(&rc, pTab, apVal, pRowid); |
| 253165 | 253266 | } |
| 253166 | 253267 | |
| 253167 | 253268 | /* UPDATE */ |
| 253168 | 253269 | else{ |
| 253169 | | - i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */ |
| 253170 | | - i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */ |
| 253171 | | - if( eType1!=SQLITE_INTEGER ){ |
| 253172 | | - rc = SQLITE_MISMATCH; |
| 253173 | | - }else if( iOld!=iNew ){ |
| 253174 | | - if( eConflict==SQLITE_REPLACE ){ |
| 253175 | | - rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0, 1); |
| 253176 | | - if( rc==SQLITE_OK ){ |
| 253177 | | - rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0); |
| 253178 | | - } |
| 253179 | | - fts5StorageInsert(&rc, pTab, apVal, pRowid); |
| 253180 | | - }else{ |
| 253181 | | - rc = sqlite3Fts5StorageFindDeleteRow(pTab->pStorage, iOld); |
| 253182 | | - if( rc==SQLITE_OK ){ |
| 253183 | | - rc = sqlite3Fts5StorageContentInsert(pTab->pStorage,apVal,pRowid); |
| 253184 | | - } |
| 253185 | | - if( rc==SQLITE_OK ){ |
| 253186 | | - rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0, 1); |
| 253187 | | - } |
| 253188 | | - if( rc==SQLITE_OK ){ |
| 253189 | | - rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid); |
| 253190 | | - } |
| 253191 | | - } |
| 253192 | | - }else{ |
| 253193 | | - rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0, 1); |
| 253194 | | - fts5StorageInsert(&rc, pTab, apVal, pRowid); |
| 253195 | | - } |
| 253196 | | - bUpdateOrDelete = 1; |
| 253197 | | - sqlite3Fts5StorageReleaseDeleteRow(pTab->pStorage); |
| 253270 | + Fts5Storage *pStorage = pTab->pStorage; |
| 253271 | + i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */ |
| 253272 | + i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */ |
| 253273 | + int bContent = 0; /* Content only update */ |
| 253274 | + |
| 253275 | + /* If this is a contentless table (including contentless_unindexed=1 |
| 253276 | + ** tables), check if the UPDATE may proceed. */ |
| 253277 | + if( fts5IsContentless(pTab, 1) ){ |
| 253278 | + rc = fts5ContentlessUpdate(pConfig, &apVal[2], iOld!=iNew, &bContent); |
| 253279 | + if( rc!=SQLITE_OK ) goto update_out; |
| 253280 | + } |
| 253281 | + |
| 253282 | + if( eType1!=SQLITE_INTEGER ){ |
| 253283 | + rc = SQLITE_MISMATCH; |
| 253284 | + }else if( iOld!=iNew ){ |
| 253285 | + assert( bContent==0 ); |
| 253286 | + if( eConflict==SQLITE_REPLACE ){ |
| 253287 | + rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1); |
| 253288 | + if( rc==SQLITE_OK ){ |
| 253289 | + rc = sqlite3Fts5StorageDelete(pStorage, iNew, 0, 0); |
| 253290 | + } |
| 253291 | + fts5StorageInsert(&rc, pTab, apVal, pRowid); |
| 253292 | + }else{ |
| 253293 | + rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld); |
| 253294 | + if( rc==SQLITE_OK ){ |
| 253295 | + rc = sqlite3Fts5StorageContentInsert(pStorage, 0, apVal, pRowid); |
| 253296 | + } |
| 253297 | + if( rc==SQLITE_OK ){ |
| 253298 | + rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 0); |
| 253299 | + } |
| 253300 | + if( rc==SQLITE_OK ){ |
| 253301 | + rc = sqlite3Fts5StorageIndexInsert(pStorage, apVal, *pRowid); |
| 253302 | + } |
| 253303 | + } |
| 253304 | + }else if( bContent ){ |
| 253305 | + /* This occurs when an UPDATE on a contentless table affects *only* |
| 253306 | + ** UNINDEXED columns. This is a no-op for contentless_unindexed=0 |
| 253307 | + ** tables, or a write to the %_content table only for =1 tables. */ |
| 253308 | + assert( fts5IsContentless(pTab, 1) ); |
| 253309 | + rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld); |
| 253310 | + if( rc==SQLITE_OK ){ |
| 253311 | + rc = sqlite3Fts5StorageContentInsert(pStorage, 1, apVal, pRowid); |
| 253312 | + } |
| 253313 | + }else{ |
| 253314 | + rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1); |
| 253315 | + fts5StorageInsert(&rc, pTab, apVal, pRowid); |
| 253316 | + } |
| 253317 | + bUpdateOrDelete = 1; |
| 253318 | + sqlite3Fts5StorageReleaseDeleteRow(pStorage); |
| 253198 | 253319 | } |
| 253199 | 253320 | |
| 253200 | 253321 | } |
| 253201 | 253322 | } |
| 253202 | 253323 | |
| | @@ -253393,11 +253514,11 @@ |
| 253393 | 253514 | Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); |
| 253394 | 253515 | |
| 253395 | 253516 | assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL ); |
| 253396 | 253517 | if( iCol<0 || iCol>=pTab->pConfig->nCol ){ |
| 253397 | 253518 | rc = SQLITE_RANGE; |
| 253398 | | - }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab)) ){ |
| 253519 | + }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab), 0) ){ |
| 253399 | 253520 | *pz = 0; |
| 253400 | 253521 | *pn = 0; |
| 253401 | 253522 | }else{ |
| 253402 | 253523 | rc = fts5SeekCursor(pCsr, 0); |
| 253403 | 253524 | if( rc==SQLITE_OK ){ |
| | @@ -253426,11 +253547,11 @@ |
| 253426 | 253547 | int bLive = (pCsr->pSorter==0); |
| 253427 | 253548 | |
| 253428 | 253549 | if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){ |
| 253429 | 253550 | rc = SQLITE_RANGE; |
| 253430 | 253551 | }else if( pConfig->eDetail!=FTS5_DETAIL_FULL |
| 253431 | | - && pConfig->eContent==FTS5_CONTENT_NONE |
| 253552 | + && fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1) |
| 253432 | 253553 | ){ |
| 253433 | 253554 | *pa = 0; |
| 253434 | 253555 | *pn = 0; |
| 253435 | 253556 | return SQLITE_OK; |
| 253436 | 253557 | }else if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){ |
| | @@ -253622,11 +253743,11 @@ |
| 253622 | 253743 | |
| 253623 | 253744 | if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){ |
| 253624 | 253745 | if( pConfig->bColumnsize ){ |
| 253625 | 253746 | i64 iRowid = fts5CursorRowid(pCsr); |
| 253626 | 253747 | rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize); |
| 253627 | | - }else if( pConfig->zContent==0 ){ |
| 253748 | + }else if( !pConfig->zContent || pConfig->eContent==FTS5_CONTENT_UNINDEXED ){ |
| 253628 | 253749 | int i; |
| 253629 | 253750 | for(i=0; i<pConfig->nCol; i++){ |
| 253630 | 253751 | if( pConfig->abUnindexed[i]==0 ){ |
| 253631 | 253752 | pCsr->aColumnSize[i] = -1; |
| 253632 | 253753 | } |
| | @@ -253910,11 +254031,11 @@ |
| 253910 | 254031 | assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL ); |
| 253911 | 254032 | if( iCol<0 || iCol>=pConfig->nCol ){ |
| 253912 | 254033 | rc = SQLITE_RANGE; |
| 253913 | 254034 | }else if( |
| 253914 | 254035 | pConfig->abUnindexed[iCol]==0 |
| 253915 | | - && pConfig->eContent!=FTS5_CONTENT_NONE |
| 254036 | + && 0==fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1) |
| 253916 | 254037 | && pConfig->bLocale |
| 253917 | 254038 | ){ |
| 253918 | 254039 | rc = fts5SeekCursor(pCsr, 0); |
| 253919 | 254040 | if( rc==SQLITE_OK ){ |
| 253920 | 254041 | const char *zDummy = 0; |
| | @@ -254185,20 +254306,11 @@ |
| 254185 | 254306 | if( pCsr->pRank || SQLITE_OK==(rc = fts5FindRankFunction(pCsr)) ){ |
| 254186 | 254307 | fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg); |
| 254187 | 254308 | } |
| 254188 | 254309 | } |
| 254189 | 254310 | }else{ |
| 254190 | | - /* A column created by the user containing values. */ |
| 254191 | | - int bNochange = sqlite3_vtab_nochange(pCtx); |
| 254192 | | - |
| 254193 | | - if( fts5IsContentless(pTab) ){ |
| 254194 | | - if( bNochange && pConfig->bContentlessDelete ){ |
| 254195 | | - fts5ResultError(pCtx, "cannot UPDATE a subset of " |
| 254196 | | - "columns on fts5 contentless-delete table: %s", pConfig->zName |
| 254197 | | - ); |
| 254198 | | - } |
| 254199 | | - }else if( bNochange==0 || pConfig->eContent!=FTS5_CONTENT_NORMAL ){ |
| 254311 | + if( !sqlite3_vtab_nochange(pCtx) && pConfig->eContent!=FTS5_CONTENT_NONE ){ |
| 254200 | 254312 | pConfig->pzErrmsg = &pTab->p.base.zErrMsg; |
| 254201 | 254313 | rc = fts5SeekCursor(pCsr, 1); |
| 254202 | 254314 | if( rc==SQLITE_OK ){ |
| 254203 | 254315 | sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1); |
| 254204 | 254316 | if( pConfig->bLocale |
| | @@ -254737,11 +254849,11 @@ |
| 254737 | 254849 | int nArg, /* Number of args */ |
| 254738 | 254850 | sqlite3_value **apUnused /* Function arguments */ |
| 254739 | 254851 | ){ |
| 254740 | 254852 | assert( nArg==0 ); |
| 254741 | 254853 | UNUSED_PARAM2(nArg, apUnused); |
| 254742 | | - sqlite3_result_text(pCtx, "fts5: 2024-09-25 16:11:27 660ca5ce6600d897cc2b00b9d39e5d993c1c0e71ec0d5dc706246c053a163281", -1, SQLITE_TRANSIENT); |
| 254854 | + sqlite3_result_text(pCtx, "fts5: 2024-10-07 12:48:21 011fab70cb3d194b27742ebb236b05be582230567cf78e3e6cac6911de86922f", -1, SQLITE_TRANSIENT); |
| 254743 | 254855 | } |
| 254744 | 254856 | |
| 254745 | 254857 | /* |
| 254746 | 254858 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 254747 | 254859 | ** |
| | @@ -255065,34 +255177,10 @@ |
| 255065 | 255177 | #define FTS5_STMT_DELETE_DOCSIZE 8 |
| 255066 | 255178 | #define FTS5_STMT_LOOKUP_DOCSIZE 9 |
| 255067 | 255179 | #define FTS5_STMT_REPLACE_CONFIG 10 |
| 255068 | 255180 | #define FTS5_STMT_SCAN 11 |
| 255069 | 255181 | |
| 255070 | | -/* |
| 255071 | | -** Return a pointer to a buffer obtained from sqlite3_malloc() that contains |
| 255072 | | -** nBind comma-separated question marks. e.g. if nBind is passed 5, this |
| 255073 | | -** function returns "?,?,?,?,?". |
| 255074 | | -** |
| 255075 | | -** If *pRc is not SQLITE_OK when this function is called, it is a no-op and |
| 255076 | | -** NULL is returned immediately. Or, if the attempt to malloc a buffer |
| 255077 | | -** fails, then *pRc is set to SQLITE_NOMEM and NULL is returned. Otherwise, |
| 255078 | | -** if it is SQLITE_OK when this function is called and the malloc() succeeds, |
| 255079 | | -** *pRc is left unchanged. |
| 255080 | | -*/ |
| 255081 | | -static char *fts5BindingsList(int *pRc, int nBind){ |
| 255082 | | - char *zBind = sqlite3Fts5MallocZero(pRc, 1 + nBind*2); |
| 255083 | | - if( zBind ){ |
| 255084 | | - int ii; |
| 255085 | | - for(ii=0; ii<nBind; ii++){ |
| 255086 | | - zBind[ii*2] = '?'; |
| 255087 | | - zBind[ii*2 + 1] = ','; |
| 255088 | | - } |
| 255089 | | - zBind[ii*2-1] = '\0'; |
| 255090 | | - } |
| 255091 | | - return zBind; |
| 255092 | | -} |
| 255093 | | - |
| 255094 | 255182 | /* |
| 255095 | 255183 | ** Prepare the two insert statements - Fts5Storage.pInsertContent and |
| 255096 | 255184 | ** Fts5Storage.pInsertDocsize - if they have not already been prepared. |
| 255097 | 255185 | ** Return SQLITE_OK if successful, or an SQLite error code if an error |
| 255098 | 255186 | ** occurs. |
| | @@ -255157,27 +255245,41 @@ |
| 255157 | 255245 | zSql = sqlite3_mprintf(azStmt[eStmt], |
| 255158 | 255246 | pC->zContentExprlist, pC->zContent, pC->zContentRowid |
| 255159 | 255247 | ); |
| 255160 | 255248 | break; |
| 255161 | 255249 | |
| 255162 | | - case FTS5_STMT_INSERT_CONTENT: { |
| 255163 | | - int nCol = 0; |
| 255164 | | - char *zBind; |
| 255250 | + case FTS5_STMT_INSERT_CONTENT: |
| 255251 | + case FTS5_STMT_REPLACE_CONTENT: { |
| 255252 | + char *zBind = 0; |
| 255165 | 255253 | int i; |
| 255166 | 255254 | |
| 255167 | | - nCol = 1 + pC->nCol; |
| 255168 | | - if( pC->bLocale ){ |
| 255169 | | - for(i=0; i<pC->nCol; i++){ |
| 255170 | | - if( pC->abUnindexed[i]==0 ) nCol++; |
| 255255 | + assert( pC->eContent==FTS5_CONTENT_NORMAL |
| 255256 | + || pC->eContent==FTS5_CONTENT_UNINDEXED |
| 255257 | + ); |
| 255258 | + |
| 255259 | + /* Add bindings for the "c*" columns - those that store the actual |
| 255260 | + ** table content. If eContent==NORMAL, then there is one binding |
| 255261 | + ** for each column. Or, if eContent==UNINDEXED, then there are only |
| 255262 | + ** bindings for the UNINDEXED columns. */ |
| 255263 | + for(i=0; rc==SQLITE_OK && i<(pC->nCol+1); i++){ |
| 255264 | + if( !i || pC->eContent==FTS5_CONTENT_NORMAL || pC->abUnindexed[i-1] ){ |
| 255265 | + zBind = sqlite3Fts5Mprintf(&rc, "%z%s?%d", zBind, zBind?",":"",i+1); |
| 255266 | + } |
| 255267 | + } |
| 255268 | + |
| 255269 | + /* Add bindings for any "l*" columns. Only non-UNINDEXED columns |
| 255270 | + ** require these. */ |
| 255271 | + if( pC->bLocale && pC->eContent==FTS5_CONTENT_NORMAL ){ |
| 255272 | + for(i=0; rc==SQLITE_OK && i<pC->nCol; i++){ |
| 255273 | + if( pC->abUnindexed[i]==0 ){ |
| 255274 | + zBind = sqlite3Fts5Mprintf(&rc, "%z,?%d", zBind, pC->nCol+i+2); |
| 255275 | + } |
| 255171 | 255276 | } |
| 255172 | 255277 | } |
| 255173 | 255278 | |
| 255174 | | - zBind = fts5BindingsList(&rc, nCol); |
| 255175 | | - if( zBind ){ |
| 255176 | | - zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind); |
| 255177 | | - sqlite3_free(zBind); |
| 255178 | | - } |
| 255279 | + zSql = sqlite3Fts5Mprintf(&rc, azStmt[eStmt], pC->zDb, pC->zName,zBind); |
| 255280 | + sqlite3_free(zBind); |
| 255179 | 255281 | break; |
| 255180 | 255282 | } |
| 255181 | 255283 | |
| 255182 | 255284 | case FTS5_STMT_REPLACE_DOCSIZE: |
| 255183 | 255285 | zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, |
| | @@ -255359,11 +255461,13 @@ |
| 255359 | 255461 | p->aTotalSize = (i64*)&p[1]; |
| 255360 | 255462 | p->pConfig = pConfig; |
| 255361 | 255463 | p->pIndex = pIndex; |
| 255362 | 255464 | |
| 255363 | 255465 | if( bCreate ){ |
| 255364 | | - if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ |
| 255466 | + if( pConfig->eContent==FTS5_CONTENT_NORMAL |
| 255467 | + || pConfig->eContent==FTS5_CONTENT_UNINDEXED |
| 255468 | + ){ |
| 255365 | 255469 | int nDefn = 32 + pConfig->nCol*10; |
| 255366 | 255470 | char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20); |
| 255367 | 255471 | if( zDefn==0 ){ |
| 255368 | 255472 | rc = SQLITE_NOMEM; |
| 255369 | 255473 | }else{ |
| | @@ -255370,12 +255474,16 @@ |
| 255370 | 255474 | int i; |
| 255371 | 255475 | int iOff; |
| 255372 | 255476 | sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY"); |
| 255373 | 255477 | iOff = (int)strlen(zDefn); |
| 255374 | 255478 | for(i=0; i<pConfig->nCol; i++){ |
| 255375 | | - sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i); |
| 255376 | | - iOff += (int)strlen(&zDefn[iOff]); |
| 255479 | + if( pConfig->eContent==FTS5_CONTENT_NORMAL |
| 255480 | + || pConfig->abUnindexed[i] |
| 255481 | + ){ |
| 255482 | + sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i); |
| 255483 | + iOff += (int)strlen(&zDefn[iOff]); |
| 255484 | + } |
| 255377 | 255485 | } |
| 255378 | 255486 | if( pConfig->bLocale ){ |
| 255379 | 255487 | for(i=0; i<pConfig->nCol; i++){ |
| 255380 | 255488 | if( pConfig->abUnindexed[i]==0 ){ |
| 255381 | 255489 | sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i); |
| | @@ -255609,11 +255717,13 @@ |
| 255609 | 255717 | i64 iOrigin = 0; |
| 255610 | 255718 | sqlite3_stmt *pLookup = 0; |
| 255611 | 255719 | int rc = SQLITE_OK; |
| 255612 | 255720 | |
| 255613 | 255721 | assert( p->pConfig->bContentlessDelete ); |
| 255614 | | - assert( p->pConfig->eContent==FTS5_CONTENT_NONE ); |
| 255722 | + assert( p->pConfig->eContent==FTS5_CONTENT_NONE |
| 255723 | + || p->pConfig->eContent==FTS5_CONTENT_UNINDEXED |
| 255724 | + ); |
| 255615 | 255725 | |
| 255616 | 255726 | /* Look up the origin of the document in the %_docsize table. Store |
| 255617 | 255727 | ** this in stack variable iOrigin. */ |
| 255618 | 255728 | rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0); |
| 255619 | 255729 | if( rc==SQLITE_OK ){ |
| | @@ -255733,10 +255843,16 @@ |
| 255733 | 255843 | } |
| 255734 | 255844 | |
| 255735 | 255845 | if( rc==SQLITE_OK ){ |
| 255736 | 255846 | if( p->pConfig->bContentlessDelete ){ |
| 255737 | 255847 | rc = fts5StorageContentlessDelete(p, iDel); |
| 255848 | + if( rc==SQLITE_OK |
| 255849 | + && bSaveRow |
| 255850 | + && p->pConfig->eContent==FTS5_CONTENT_UNINDEXED |
| 255851 | + ){ |
| 255852 | + rc = sqlite3Fts5StorageFindDeleteRow(p, iDel); |
| 255853 | + } |
| 255738 | 255854 | }else{ |
| 255739 | 255855 | rc = fts5StorageDeleteFromIndex(p, iDel, apVal, bSaveRow); |
| 255740 | 255856 | } |
| 255741 | 255857 | } |
| 255742 | 255858 | |
| | @@ -255749,11 +255865,13 @@ |
| 255749 | 255865 | rc = sqlite3_reset(pDel); |
| 255750 | 255866 | } |
| 255751 | 255867 | } |
| 255752 | 255868 | |
| 255753 | 255869 | /* Delete the %_content record */ |
| 255754 | | - if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ |
| 255870 | + if( pConfig->eContent==FTS5_CONTENT_NORMAL |
| 255871 | + || pConfig->eContent==FTS5_CONTENT_UNINDEXED |
| 255872 | + ){ |
| 255755 | 255873 | if( rc==SQLITE_OK ){ |
| 255756 | 255874 | rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0); |
| 255757 | 255875 | } |
| 255758 | 255876 | if( rc==SQLITE_OK ){ |
| 255759 | 255877 | sqlite3_bind_int64(pDel, 1, iDel); |
| | @@ -255781,12 +255899,17 @@ |
| 255781 | 255899 | pConfig->zDb, pConfig->zName, |
| 255782 | 255900 | pConfig->zDb, pConfig->zName |
| 255783 | 255901 | ); |
| 255784 | 255902 | if( rc==SQLITE_OK && pConfig->bColumnsize ){ |
| 255785 | 255903 | rc = fts5ExecPrintf(pConfig->db, 0, |
| 255786 | | - "DELETE FROM %Q.'%q_docsize';", |
| 255787 | | - pConfig->zDb, pConfig->zName |
| 255904 | + "DELETE FROM %Q.'%q_docsize';", pConfig->zDb, pConfig->zName |
| 255905 | + ); |
| 255906 | + } |
| 255907 | + |
| 255908 | + if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_UNINDEXED ){ |
| 255909 | + rc = fts5ExecPrintf(pConfig->db, 0, |
| 255910 | + "DELETE FROM %Q.'%q_content';", pConfig->zDb, pConfig->zName |
| 255788 | 255911 | ); |
| 255789 | 255912 | } |
| 255790 | 255913 | |
| 255791 | 255914 | /* Reinitialize the %_data table. This call creates the initial structure |
| 255792 | 255915 | ** and averages records. */ |
| | @@ -255918,69 +256041,75 @@ |
| 255918 | 256041 | /* |
| 255919 | 256042 | ** Insert a new row into the FTS content table. |
| 255920 | 256043 | */ |
| 255921 | 256044 | static int sqlite3Fts5StorageContentInsert( |
| 255922 | 256045 | Fts5Storage *p, |
| 256046 | + int bReplace, /* True to use REPLACE instead of INSERT */ |
| 255923 | 256047 | sqlite3_value **apVal, |
| 255924 | 256048 | i64 *piRowid |
| 255925 | 256049 | ){ |
| 255926 | 256050 | Fts5Config *pConfig = p->pConfig; |
| 255927 | 256051 | int rc = SQLITE_OK; |
| 255928 | 256052 | |
| 255929 | 256053 | /* Insert the new row into the %_content table. */ |
| 255930 | | - if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){ |
| 256054 | + if( pConfig->eContent!=FTS5_CONTENT_NORMAL |
| 256055 | + && pConfig->eContent!=FTS5_CONTENT_UNINDEXED |
| 256056 | + ){ |
| 255931 | 256057 | if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){ |
| 255932 | 256058 | *piRowid = sqlite3_value_int64(apVal[1]); |
| 255933 | 256059 | }else{ |
| 255934 | 256060 | rc = fts5StorageNewRowid(p, piRowid); |
| 255935 | 256061 | } |
| 255936 | 256062 | }else{ |
| 255937 | 256063 | sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */ |
| 255938 | 256064 | int i; /* Counter variable */ |
| 255939 | | - int nIndexed = 0; /* Number indexed columns seen */ |
| 255940 | | - rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0); |
| 256065 | + |
| 256066 | + assert( FTS5_STMT_INSERT_CONTENT+1==FTS5_STMT_REPLACE_CONTENT ); |
| 256067 | + assert( bReplace==0 || bReplace==1 ); |
| 256068 | + rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT+bReplace, &pInsert, 0); |
| 255941 | 256069 | if( pInsert ) sqlite3_clear_bindings(pInsert); |
| 255942 | 256070 | |
| 255943 | 256071 | /* Bind the rowid value */ |
| 255944 | 256072 | sqlite3_bind_value(pInsert, 1, apVal[1]); |
| 255945 | 256073 | |
| 255946 | 256074 | /* Loop through values for user-defined columns. i=2 is the leftmost |
| 255947 | 256075 | ** user-defined column. As is column 1 of pSavedRow. */ |
| 255948 | 256076 | for(i=2; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){ |
| 255949 | 256077 | int bUnindexed = pConfig->abUnindexed[i-2]; |
| 255950 | | - sqlite3_value *pVal = apVal[i]; |
| 255951 | | - |
| 255952 | | - nIndexed += !bUnindexed; |
| 255953 | | - if( sqlite3_value_nochange(pVal) && p->pSavedRow ){ |
| 255954 | | - /* This is an UPDATE statement, and column (i-2) was not modified. |
| 255955 | | - ** Retrieve the value from Fts5Storage.pSavedRow instead. */ |
| 255956 | | - pVal = sqlite3_column_value(p->pSavedRow, i-1); |
| 255957 | | - if( pConfig->bLocale && bUnindexed==0 ){ |
| 255958 | | - sqlite3_bind_value(pInsert, pConfig->nCol + 1 + nIndexed, |
| 255959 | | - sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1) |
| 255960 | | - ); |
| 255961 | | - } |
| 255962 | | - }else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ |
| 255963 | | - const char *pText = 0; |
| 255964 | | - const char *pLoc = 0; |
| 255965 | | - int nText = 0; |
| 255966 | | - int nLoc = 0; |
| 255967 | | - assert( pConfig->bLocale ); |
| 255968 | | - |
| 255969 | | - rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc); |
| 255970 | | - if( rc==SQLITE_OK ){ |
| 255971 | | - sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT); |
| 255972 | | - if( bUnindexed==0 ){ |
| 255973 | | - int iLoc = pConfig->nCol + 1 + nIndexed; |
| 255974 | | - sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT); |
| 255975 | | - } |
| 255976 | | - } |
| 255977 | | - |
| 255978 | | - continue; |
| 255979 | | - } |
| 255980 | | - |
| 255981 | | - rc = sqlite3_bind_value(pInsert, i, pVal); |
| 256078 | + if( pConfig->eContent==FTS5_CONTENT_NORMAL || bUnindexed ){ |
| 256079 | + sqlite3_value *pVal = apVal[i]; |
| 256080 | + |
| 256081 | + if( sqlite3_value_nochange(pVal) && p->pSavedRow ){ |
| 256082 | + /* This is an UPDATE statement, and user-defined column (i-2) was not |
| 256083 | + ** modified. Retrieve the value from Fts5Storage.pSavedRow. */ |
| 256084 | + pVal = sqlite3_column_value(p->pSavedRow, i-1); |
| 256085 | + if( pConfig->bLocale && bUnindexed==0 ){ |
| 256086 | + sqlite3_bind_value(pInsert, pConfig->nCol + i, |
| 256087 | + sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1) |
| 256088 | + ); |
| 256089 | + } |
| 256090 | + }else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ |
| 256091 | + const char *pText = 0; |
| 256092 | + const char *pLoc = 0; |
| 256093 | + int nText = 0; |
| 256094 | + int nLoc = 0; |
| 256095 | + assert( pConfig->bLocale ); |
| 256096 | + |
| 256097 | + rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc); |
| 256098 | + if( rc==SQLITE_OK ){ |
| 256099 | + sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT); |
| 256100 | + if( bUnindexed==0 ){ |
| 256101 | + int iLoc = pConfig->nCol + i; |
| 256102 | + sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT); |
| 256103 | + } |
| 256104 | + } |
| 256105 | + |
| 256106 | + continue; |
| 256107 | + } |
| 256108 | + |
| 256109 | + rc = sqlite3_bind_value(pInsert, i, pVal); |
| 256110 | + } |
| 255982 | 256111 | } |
| 255983 | 256112 | if( rc==SQLITE_OK ){ |
| 255984 | 256113 | sqlite3_step(pInsert); |
| 255985 | 256114 | rc = sqlite3_reset(pInsert); |
| 255986 | 256115 | } |
| 255987 | 256116 | |