Fossil SCM

Update the built-in SQLite to the latests trunk version, which includes fixes found in 3.47.2, plus other enhancements.

drh 2024-12-09 23:03 trunk
Commit 077e53a341150a1fe85818e556381ec9e186cf565ac1c06bb5573658b08697b5
3 files changed +254 -49 +807 -294 +30 -4
+254 -49
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -2367,11 +2367,11 @@
23672367
**
23682368
******************************************************************************
23692369
**
23702370
** This SQLite extension implements functions that compute SHA3 hashes
23712371
** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard.
2372
-** Two SQL functions are implemented:
2372
+** Three SQL functions are implemented:
23732373
**
23742374
** sha3(X,SIZE)
23752375
** sha3_agg(Y,SIZE)
23762376
** sha3_query(Z,SIZE)
23772377
**
@@ -14193,11 +14193,11 @@
1419314193
/* A view. Or a trigger on a view. */
1419414194
if( zSql ) rc = expertSchemaSql(p->dbv, zSql, pzErrmsg);
1419514195
}else{
1419614196
IdxTable *pTab;
1419714197
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
14198
- if( rc==SQLITE_OK ){
14198
+ if( rc==SQLITE_OK && ALWAYS(pTab!=0) ){
1419914199
int i;
1420014200
char *zInner = 0;
1420114201
char *zOuter = 0;
1420214202
pTab->pNext = p->pTable;
1420314203
p->pTable = pTab;
@@ -16261,11 +16261,31 @@
1626116261
**
1626216262
** Similar compiler commands will work on different systems. The key
1626316263
** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that
1626416264
** the shell.c source file will know to include the -vfstrace command-line
1626516265
** option and (2) you must compile and link the three source files
16266
-** shell,c, test_vfstrace.c, and sqlite3.c.
16266
+** shell,c, test_vfstrace.c, and sqlite3.c.
16267
+**
16268
+** RUNTIME CONTROL OF VFSTRACE OUTPUT
16269
+**
16270
+** The application can use the "vfstrace" pragma to control which VFS
16271
+** APIs are traced. To disable all output:
16272
+**
16273
+** PRAGMA vfstrace('-all');
16274
+**
16275
+** To enable all output (which is the default setting):
16276
+**
16277
+** PRAGMA vfstrace('+all');
16278
+**
16279
+** Individual APIs can be enabled or disabled by name, with or without
16280
+** the initial "x" character. For example, to set up for tracing lock
16281
+** primatives only:
16282
+**
16283
+** PRAGMA vfstrace('-all, +Lock,Unlock,ShmLock');
16284
+**
16285
+** The argument to the vfstrace pragma ignores capitalization and any
16286
+** characters other than alphabetics, '+', and '-'.
1626716287
*/
1626816288
#include <stdlib.h>
1626916289
#include <string.h>
1627016290
/* #include "sqlite3.h" */
1627116291
@@ -16275,10 +16295,12 @@
1627516295
*/
1627616296
typedef struct vfstrace_info vfstrace_info;
1627716297
struct vfstrace_info {
1627816298
sqlite3_vfs *pRootVfs; /* The underlying real VFS */
1627916299
int (*xOut)(const char*, void*); /* Send output here */
16300
+ unsigned int mTrace; /* Mask of interfaces to trace */
16301
+ u8 bOn; /* Tracing on/off */
1628016302
void *pOutArg; /* First argument to xOut */
1628116303
const char *zVfsName; /* Name of this trace-VFS */
1628216304
sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */
1628316305
};
1628416306
@@ -16291,10 +16313,42 @@
1629116313
vfstrace_info *pInfo; /* The trace-VFS to which this file belongs */
1629216314
const char *zFName; /* Base name of the file */
1629316315
sqlite3_file *pReal; /* The real underlying file */
1629416316
};
1629516317
16318
+/*
16319
+** Bit values for vfstrace_info.mTrace.
16320
+*/
16321
+#define VTR_CLOSE 0x00000001
16322
+#define VTR_READ 0x00000002
16323
+#define VTR_WRITE 0x00000004
16324
+#define VTR_TRUNC 0x00000008
16325
+#define VTR_SYNC 0x00000010
16326
+#define VTR_FSIZE 0x00000020
16327
+#define VTR_LOCK 0x00000040
16328
+#define VTR_UNLOCK 0x00000080
16329
+#define VTR_CRL 0x00000100
16330
+#define VTR_FCTRL 0x00000200
16331
+#define VTR_SECSZ 0x00000400
16332
+#define VTR_DEVCHAR 0x00000800
16333
+#define VTR_SHMLOCK 0x00001000
16334
+#define VTR_SHMMAP 0x00002000
16335
+#define VTR_SHMBAR 0x00004000
16336
+#define VTR_SHMUNMAP 0x00008000
16337
+#define VTR_OPEN 0x00010000
16338
+#define VTR_DELETE 0x00020000
16339
+#define VTR_ACCESS 0x00040000
16340
+#define VTR_FULLPATH 0x00080000
16341
+#define VTR_DLOPEN 0x00100000
16342
+#define VTR_DLERR 0x00200000
16343
+#define VTR_DLSYM 0x00400000
16344
+#define VTR_DLCLOSE 0x00800000
16345
+#define VTR_RAND 0x01000000
16346
+#define VTR_SLEEP 0x02000000
16347
+#define VTR_CURTIME 0x04000000
16348
+#define VTR_LASTERR 0x08000000
16349
+
1629616350
/*
1629716351
** Method declarations for vfstrace_file.
1629816352
*/
1629916353
static int vfstraceClose(sqlite3_file*);
1630016354
static int vfstraceRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
@@ -16355,15 +16409,17 @@
1635516409
const char *zFormat,
1635616410
...
1635716411
){
1635816412
va_list ap;
1635916413
char *zMsg;
16360
- va_start(ap, zFormat);
16361
- zMsg = sqlite3_vmprintf(zFormat, ap);
16362
- va_end(ap);
16363
- pInfo->xOut(zMsg, pInfo->pOutArg);
16364
- sqlite3_free(zMsg);
16414
+ if( pInfo->bOn ){
16415
+ va_start(ap, zFormat);
16416
+ zMsg = sqlite3_vmprintf(zFormat, ap);
16417
+ va_end(ap);
16418
+ pInfo->xOut(zMsg, pInfo->pOutArg);
16419
+ sqlite3_free(zMsg);
16420
+ }
1636516421
}
1636616422
1636716423
/*
1636816424
** Try to convert an error code into a symbolic name for that error code.
1636916425
*/
@@ -16457,18 +16513,26 @@
1645716513
int i = *pI;
1645816514
while( zAppend[0] ){ z[i++] = *(zAppend++); }
1645916515
z[i] = 0;
1646016516
*pI = i;
1646116517
}
16518
+
16519
+/*
16520
+** Turn tracing output on or off according to mMask.
16521
+*/
16522
+static void vfstraceOnOff(vfstrace_info *pInfo, unsigned int mMask){
16523
+ pInfo->bOn = (pInfo->mTrace & mMask)!=0;
16524
+}
1646216525
1646316526
/*
1646416527
** Close an vfstrace-file.
1646516528
*/
1646616529
static int vfstraceClose(sqlite3_file *pFile){
1646716530
vfstrace_file *p = (vfstrace_file *)pFile;
1646816531
vfstrace_info *pInfo = p->pInfo;
1646916532
int rc;
16533
+ vfstraceOnOff(pInfo, VTR_CLOSE);
1647016534
vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
1647116535
rc = p->pReal->pMethods->xClose(p->pReal);
1647216536
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
1647316537
if( rc==SQLITE_OK ){
1647416538
sqlite3_free((void*)p->base.pMethods);
@@ -16487,10 +16551,11 @@
1648716551
sqlite_int64 iOfst
1648816552
){
1648916553
vfstrace_file *p = (vfstrace_file *)pFile;
1649016554
vfstrace_info *pInfo = p->pInfo;
1649116555
int rc;
16556
+ vfstraceOnOff(pInfo, VTR_READ);
1649216557
vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
1649316558
pInfo->zVfsName, p->zFName, iAmt, iOfst);
1649416559
rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
1649516560
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
1649616561
return rc;
@@ -16506,10 +16571,11 @@
1650616571
sqlite_int64 iOfst
1650716572
){
1650816573
vfstrace_file *p = (vfstrace_file *)pFile;
1650916574
vfstrace_info *pInfo = p->pInfo;
1651016575
int rc;
16576
+ vfstraceOnOff(pInfo, VTR_WRITE);
1651116577
vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
1651216578
pInfo->zVfsName, p->zFName, iAmt, iOfst);
1651316579
rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
1651416580
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
1651516581
return rc;
@@ -16520,10 +16586,11 @@
1652016586
*/
1652116587
static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
1652216588
vfstrace_file *p = (vfstrace_file *)pFile;
1652316589
vfstrace_info *pInfo = p->pInfo;
1652416590
int rc;
16591
+ vfstraceOnOff(pInfo, VTR_TRUNC);
1652516592
vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
1652616593
size);
1652716594
rc = p->pReal->pMethods->xTruncate(p->pReal, size);
1652816595
vfstrace_printf(pInfo, " -> %d\n", rc);
1652916596
return rc;
@@ -16544,10 +16611,11 @@
1654416611
else if( flags & SQLITE_SYNC_NORMAL ) strappend(zBuf, &i, "|NORMAL");
1654516612
if( flags & SQLITE_SYNC_DATAONLY ) strappend(zBuf, &i, "|DATAONLY");
1654616613
if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
1654716614
sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
1654816615
}
16616
+ vfstraceOnOff(pInfo, VTR_SYNC);
1654916617
vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
1655016618
&zBuf[1]);
1655116619
rc = p->pReal->pMethods->xSync(p->pReal, flags);
1655216620
vfstrace_printf(pInfo, " -> %d\n", rc);
1655316621
return rc;
@@ -16558,10 +16626,11 @@
1655816626
*/
1655916627
static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
1656016628
vfstrace_file *p = (vfstrace_file *)pFile;
1656116629
vfstrace_info *pInfo = p->pInfo;
1656216630
int rc;
16631
+ vfstraceOnOff(pInfo, VTR_FSIZE);
1656316632
vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
1656416633
rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
1656516634
vfstrace_print_errcode(pInfo, " -> %s,", rc);
1656616635
vfstrace_printf(pInfo, " size=%lld\n", *pSize);
1656716636
return rc;
@@ -16586,10 +16655,11 @@
1658616655
*/
1658716656
static int vfstraceLock(sqlite3_file *pFile, int eLock){
1658816657
vfstrace_file *p = (vfstrace_file *)pFile;
1658916658
vfstrace_info *pInfo = p->pInfo;
1659016659
int rc;
16660
+ vfstraceOnOff(pInfo, VTR_LOCK);
1659116661
vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
1659216662
lockName(eLock));
1659316663
rc = p->pReal->pMethods->xLock(p->pReal, eLock);
1659416664
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
1659516665
return rc;
@@ -16600,10 +16670,11 @@
1660016670
*/
1660116671
static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
1660216672
vfstrace_file *p = (vfstrace_file *)pFile;
1660316673
vfstrace_info *pInfo = p->pInfo;
1660416674
int rc;
16675
+ vfstraceOnOff(pInfo, VTR_UNLOCK);
1660516676
vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
1660616677
lockName(eLock));
1660716678
rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
1660816679
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
1660916680
return rc;
@@ -16614,10 +16685,11 @@
1661416685
*/
1661516686
static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
1661616687
vfstrace_file *p = (vfstrace_file *)pFile;
1661716688
vfstrace_info *pInfo = p->pInfo;
1661816689
int rc;
16690
+ vfstraceOnOff(pInfo, VTR_CRL);
1661916691
vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)",
1662016692
pInfo->zVfsName, p->zFName);
1662116693
rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
1662216694
vfstrace_print_errcode(pInfo, " -> %s", rc);
1662316695
vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
@@ -16633,10 +16705,11 @@
1663316705
int rc;
1663416706
char zBuf[100];
1663516707
char zBuf2[100];
1663616708
char *zOp;
1663716709
char *zRVal = 0;
16710
+ vfstraceOnOff(pInfo, VTR_FCTRL);
1663816711
switch( op ){
1663916712
case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
1664016713
case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
1664116714
case SQLITE_SET_LOCKPROXYFILE: zOp = "SET_LOCKPROXYFILE"; break;
1664216715
case SQLITE_LAST_ERRNO: zOp = "LAST_ERRNO"; break;
@@ -16661,10 +16734,83 @@
1666116734
case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break;
1666216735
case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break;
1666316736
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
1666416737
case SQLITE_FCNTL_PRAGMA: {
1666516738
const char *const* a = (const char*const*)pArg;
16739
+ if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){
16740
+ const u8 *zArg = (const u8*)a[2];
16741
+ if( zArg[0]>='0' && zArg[0]<=9 ){
16742
+ pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0);
16743
+ }else{
16744
+ static const struct {
16745
+ const char *z;
16746
+ unsigned int m;
16747
+ } aKw[] = {
16748
+ { "all", 0xffffffff },
16749
+ { "close", VTR_CLOSE },
16750
+ { "read", VTR_READ },
16751
+ { "write", VTR_WRITE },
16752
+ { "truncate", VTR_TRUNC },
16753
+ { "sync", VTR_SYNC },
16754
+ { "filesize", VTR_FSIZE },
16755
+ { "lock", VTR_LOCK },
16756
+ { "unlock", VTR_UNLOCK },
16757
+ { "checkreservedlock", VTR_CRL },
16758
+ { "filecontrol", VTR_FCTRL },
16759
+ { "sectorsize", VTR_SECSZ },
16760
+ { "devicecharacteristics", VTR_DEVCHAR },
16761
+ { "shmlock", VTR_SHMLOCK },
16762
+ { "shmmap", VTR_SHMMAP },
16763
+ { "shmummap", VTR_SHMUNMAP },
16764
+ { "shmbarrier", VTR_SHMBAR },
16765
+ { "open", VTR_OPEN },
16766
+ { "delete", VTR_DELETE },
16767
+ { "access", VTR_ACCESS },
16768
+ { "fullpathname", VTR_FULLPATH },
16769
+ { "dlopen", VTR_DLOPEN },
16770
+ { "dlerror", VTR_DLERR },
16771
+ { "dlsym", VTR_DLSYM },
16772
+ { "dlclose", VTR_DLCLOSE },
16773
+ { "randomness", VTR_RAND },
16774
+ { "sleep", VTR_SLEEP },
16775
+ { "currenttime", VTR_CURTIME },
16776
+ { "currenttimeint64", VTR_CURTIME },
16777
+ { "getlasterror", VTR_LASTERR },
16778
+ };
16779
+ int onOff = 1;
16780
+ while( zArg[0] ){
16781
+ int jj, n;
16782
+ while( zArg[0]!=0 && zArg[0]!='-' && zArg[0]!='+'
16783
+ && !isalpha(zArg[0]) ) zArg++;
16784
+ if( zArg[0]==0 ) break;
16785
+ if( zArg[0]=='-' ){
16786
+ onOff = 0;
16787
+ zArg++;
16788
+ }else if( zArg[0]=='+' ){
16789
+ onOff = 1;
16790
+ zArg++;
16791
+ }
16792
+ while( !isalpha(zArg[0]) ){
16793
+ if( zArg[0]==0 ) break;
16794
+ zArg++;
16795
+ }
16796
+ if( zArg[0]=='x' && isalpha(zArg[1]) ) zArg++;
16797
+ for(n=0; isalpha(zArg[n]); n++){}
16798
+ for(jj=0; jj<(int)(sizeof(aKw)/sizeof(aKw[0])); jj++){
16799
+ if( sqlite3_strnicmp(aKw[jj].z,(const char*)zArg,n)==0 ){
16800
+ if( onOff ){
16801
+ pInfo->mTrace |= aKw[jj].m;
16802
+ }else{
16803
+ pInfo->mTrace &= ~aKw[jj].m;
16804
+ }
16805
+ break;
16806
+ }
16807
+ }
16808
+ zArg += n;
16809
+ }
16810
+ }
16811
+ }
1666616812
sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
1666716813
zOp = zBuf;
1666816814
break;
1666916815
}
1667016816
case SQLITE_FCNTL_BUSYHANDLER: zOp = "BUSYHANDLER"; break;
@@ -16756,10 +16902,11 @@
1675616902
*/
1675716903
static int vfstraceSectorSize(sqlite3_file *pFile){
1675816904
vfstrace_file *p = (vfstrace_file *)pFile;
1675916905
vfstrace_info *pInfo = p->pInfo;
1676016906
int rc;
16907
+ vfstraceOnOff(pInfo, VTR_SECSZ);
1676116908
vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
1676216909
rc = p->pReal->pMethods->xSectorSize(p->pReal);
1676316910
vfstrace_printf(pInfo, " -> %d\n", rc);
1676416911
return rc;
1676516912
}
@@ -16769,10 +16916,11 @@
1676916916
*/
1677016917
static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
1677116918
vfstrace_file *p = (vfstrace_file *)pFile;
1677216919
vfstrace_info *pInfo = p->pInfo;
1677316920
int rc;
16921
+ vfstraceOnOff(pInfo, VTR_DEVCHAR);
1677416922
vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
1677516923
pInfo->zVfsName, p->zFName);
1677616924
rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
1677716925
vfstrace_printf(pInfo, " -> 0x%08x\n", rc);
1677816926
return rc;
@@ -16795,19 +16943,20 @@
1679516943
vfstrace_file *p = (vfstrace_file *)pFile;
1679616944
vfstrace_info *pInfo = p->pInfo;
1679716945
int rc;
1679816946
char zLck[100];
1679916947
int i = 0;
16948
+ vfstraceOnOff(pInfo, VTR_SHMLOCK);
1680016949
memcpy(zLck, "|0", 3);
1680116950
if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK");
1680216951
if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK");
1680316952
if( flags & SQLITE_SHM_SHARED ) strappend(zLck, &i, "|SHARED");
1680416953
if( flags & SQLITE_SHM_EXCLUSIVE ) strappend(zLck, &i, "|EXCLUSIVE");
1680516954
if( flags & ~(0xf) ){
1680616955
sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
1680716956
}
16808
- if( ofst>=0 && ofst<sizeof(azLockName)/sizeof(azLockName[0]) ){
16957
+ if( ofst>=0 && ofst<(int)(sizeof(azLockName)/sizeof(azLockName[0])) ){
1680916958
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d(%s),n=%d,%s)",
1681016959
pInfo->zVfsName, p->zFName, ofst, azLockName[ofst],
1681116960
n, &zLck[1]);
1681216961
}else{
1681316962
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=5d,n=%d,%s)",
@@ -16826,26 +16975,29 @@
1682616975
void volatile **pp
1682716976
){
1682816977
vfstrace_file *p = (vfstrace_file *)pFile;
1682916978
vfstrace_info *pInfo = p->pInfo;
1683016979
int rc;
16980
+ vfstraceOnOff(pInfo, VTR_SHMMAP);
1683116981
vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
1683216982
pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
1683316983
rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
1683416984
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
1683516985
return rc;
1683616986
}
1683716987
static void vfstraceShmBarrier(sqlite3_file *pFile){
1683816988
vfstrace_file *p = (vfstrace_file *)pFile;
1683916989
vfstrace_info *pInfo = p->pInfo;
16990
+ vfstraceOnOff(pInfo, VTR_SHMBAR);
1684016991
vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
1684116992
p->pReal->pMethods->xShmBarrier(p->pReal);
1684216993
}
1684316994
static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
1684416995
vfstrace_file *p = (vfstrace_file *)pFile;
1684516996
vfstrace_info *pInfo = p->pInfo;
1684616997
int rc;
16998
+ vfstraceOnOff(pInfo, VTR_SHMUNMAP);
1684716999
vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
1684817000
pInfo->zVfsName, p->zFName, delFlag);
1684917001
rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
1685017002
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
1685117003
return rc;
@@ -16869,10 +17021,11 @@
1686917021
sqlite3_vfs *pRoot = pInfo->pRootVfs;
1687017022
p->pInfo = pInfo;
1687117023
p->zFName = zName ? fileTail(zName) : "<temp>";
1687217024
p->pReal = (sqlite3_file *)&p[1];
1687317025
rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
17026
+ vfstraceOnOff(pInfo, VTR_OPEN);
1687417027
vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
1687517028
pInfo->zVfsName, p->zFName, flags);
1687617029
if( p->pReal->pMethods ){
1687717030
sqlite3_io_methods *pNew = sqlite3_malloc( sizeof(*pNew) );
1687817031
const sqlite3_io_methods *pSub = p->pReal->pMethods;
@@ -16914,10 +17067,11 @@
1691417067
*/
1691517068
static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
1691617069
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1691717070
sqlite3_vfs *pRoot = pInfo->pRootVfs;
1691817071
int rc;
17072
+ vfstraceOnOff(pInfo, VTR_DELETE);
1691917073
vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
1692017074
pInfo->zVfsName, zPath, dirSync);
1692117075
rc = pRoot->xDelete(pRoot, zPath, dirSync);
1692217076
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
1692317077
return rc;
@@ -16934,10 +17088,11 @@
1693417088
int *pResOut
1693517089
){
1693617090
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1693717091
sqlite3_vfs *pRoot = pInfo->pRootVfs;
1693817092
int rc;
17093
+ vfstraceOnOff(pInfo, VTR_ACCESS);
1693917094
vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
1694017095
pInfo->zVfsName, zPath, flags);
1694117096
rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
1694217097
vfstrace_print_errcode(pInfo, " -> %s", rc);
1694317098
vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
@@ -16956,10 +17111,11 @@
1695617111
char *zOut
1695717112
){
1695817113
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1695917114
sqlite3_vfs *pRoot = pInfo->pRootVfs;
1696017115
int rc;
17116
+ vfstraceOnOff(pInfo, VTR_FULLPATH);
1696117117
vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
1696217118
pInfo->zVfsName, zPath);
1696317119
rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
1696417120
vfstrace_print_errcode(pInfo, " -> %s", rc);
1696517121
vfstrace_printf(pInfo, ", out=\"%.*s\"\n", nOut, zOut);
@@ -16970,10 +17126,11 @@
1697017126
** Open the dynamic library located at zPath and return a handle.
1697117127
*/
1697217128
static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
1697317129
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1697417130
sqlite3_vfs *pRoot = pInfo->pRootVfs;
17131
+ vfstraceOnOff(pInfo, VTR_DLOPEN);
1697517132
vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
1697617133
return pRoot->xDlOpen(pRoot, zPath);
1697717134
}
1697817135
1697917136
/*
@@ -16982,10 +17139,11 @@
1698217139
** with dynamic libraries.
1698317140
*/
1698417141
static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
1698517142
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1698617143
sqlite3_vfs *pRoot = pInfo->pRootVfs;
17144
+ vfstraceOnOff(pInfo, VTR_DLERR);
1698717145
vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
1698817146
pRoot->xDlError(pRoot, nByte, zErrMsg);
1698917147
vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
1699017148
}
1699117149
@@ -17003,10 +17161,11 @@
1700317161
** Close the dynamic library handle pHandle.
1700417162
*/
1700517163
static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
1700617164
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1700717165
sqlite3_vfs *pRoot = pInfo->pRootVfs;
17166
+ vfstraceOnOff(pInfo, VTR_DLCLOSE);
1700817167
vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
1700917168
pRoot->xDlClose(pRoot, pHandle);
1701017169
}
1701117170
1701217171
/*
@@ -17014,10 +17173,11 @@
1701417173
** random data.
1701517174
*/
1701617175
static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
1701717176
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1701817177
sqlite3_vfs *pRoot = pInfo->pRootVfs;
17178
+ vfstraceOnOff(pInfo, VTR_RAND);
1701917179
vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
1702017180
return pRoot->xRandomness(pRoot, nByte, zBufOut);
1702117181
}
1702217182
1702317183
/*
@@ -17025,34 +17185,52 @@
1702517185
** actually slept.
1702617186
*/
1702717187
static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
1702817188
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1702917189
sqlite3_vfs *pRoot = pInfo->pRootVfs;
17190
+ vfstraceOnOff(pInfo, VTR_SLEEP);
17191
+ vfstrace_printf(pInfo, "%s.xSleep(%d)\n", pInfo->zVfsName, nMicro);
1703017192
return pRoot->xSleep(pRoot, nMicro);
1703117193
}
1703217194
1703317195
/*
1703417196
** Return the current time as a Julian Day number in *pTimeOut.
1703517197
*/
1703617198
static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
1703717199
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1703817200
sqlite3_vfs *pRoot = pInfo->pRootVfs;
17039
- return pRoot->xCurrentTime(pRoot, pTimeOut);
17201
+ int rc;
17202
+ vfstraceOnOff(pInfo, VTR_CURTIME);
17203
+ vfstrace_printf(pInfo, "%s.xCurrentTime()", pInfo->zVfsName);
17204
+ rc = pRoot->xCurrentTime(pRoot, pTimeOut);
17205
+ vfstrace_printf(pInfo, " -> %.17g\n", *pTimeOut);
17206
+ return rc;
1704017207
}
1704117208
static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
1704217209
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1704317210
sqlite3_vfs *pRoot = pInfo->pRootVfs;
17044
- return pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
17211
+ int rc;
17212
+ vfstraceOnOff(pInfo, VTR_CURTIME);
17213
+ vfstrace_printf(pInfo, "%s.xCurrentTimeInt64()", pInfo->zVfsName);
17214
+ rc = pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
17215
+ vfstrace_printf(pInfo, " -> %lld\n", *pTimeOut);
17216
+ return rc;
1704517217
}
1704617218
1704717219
/*
17048
-** Return th3 most recent error code and message
17220
+** Return the most recent error code and message
1704917221
*/
17050
-static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){
17222
+static int vfstraceGetLastError(sqlite3_vfs *pVfs, int nErr, char *zErr){
1705117223
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
1705217224
sqlite3_vfs *pRoot = pInfo->pRootVfs;
17053
- return pRoot->xGetLastError(pRoot, iErr, zErr);
17225
+ int rc;
17226
+ vfstraceOnOff(pInfo, VTR_LASTERR);
17227
+ vfstrace_printf(pInfo, "%s.xGetLastError(%d,zBuf)", pInfo->zVfsName, nErr);
17228
+ if( nErr ) zErr[0] = 0;
17229
+ rc = pRoot->xGetLastError(pRoot, nErr, zErr);
17230
+ vfstrace_printf(pInfo, " -> zBuf[] = \"%s\", rc = %d\n", nErr?zErr:"", rc);
17231
+ return rc;
1705417232
}
1705517233
1705617234
/*
1705717235
** Override system calls.
1705817236
*/
@@ -17142,10 +17320,12 @@
1714217320
pInfo->pRootVfs = pRoot;
1714317321
pInfo->xOut = xOut;
1714417322
pInfo->pOutArg = pOutArg;
1714517323
pInfo->zVfsName = pNew->zName;
1714617324
pInfo->pTraceVfs = pNew;
17325
+ pInfo->mTrace = 0xffffffff;
17326
+ pInfo->bOn = 1;
1714717327
vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
1714817328
pInfo->zVfsName, pRoot->zName);
1714917329
return sqlite3_vfs_register(pNew, makeDefault);
1715017330
}
1715117331
@@ -26444,18 +26624,24 @@
2644426624
#endif
2644526625
2644626626
/*
2644726627
** Run an SQL command and return the single integer result.
2644826628
*/
26449
-static int db_int(sqlite3 *db, const char *zSql){
26629
+static int db_int(sqlite3 *db, const char *zSql, ...){
2645026630
sqlite3_stmt *pStmt;
2645126631
int res = 0;
26452
- sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
26632
+ char *z;
26633
+ va_list ap;
26634
+ va_start(ap, zSql);
26635
+ z = sqlite3_vmprintf(zSql, ap);
26636
+ va_end(ap);
26637
+ sqlite3_prepare_v2(db, z, -1, &pStmt, 0);
2645326638
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
2645426639
res = sqlite3_column_int(pStmt,0);
2645526640
}
2645626641
sqlite3_finalize(pStmt);
26642
+ sqlite3_free(z);
2645726643
return res;
2645826644
}
2645926645
2646026646
#if SQLITE_SHELL_HAVE_RECOVER
2646126647
/*
@@ -26554,13 +26740,11 @@
2655426740
zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
2655526741
}else{
2655626742
zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
2655726743
}
2655826744
for(i=0; i<ArraySize(aQuery); i++){
26559
- char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
26560
- int val = db_int(p->db, zSql);
26561
- sqlite3_free(zSql);
26745
+ int val = db_int(p->db, aQuery[i].zSql, zSchemaTab);
2656226746
sqlite3_fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
2656326747
}
2656426748
sqlite3_free(zSchemaTab);
2656526749
sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
2656626750
sqlite3_fprintf(p->out, "%-20s %u\n", "data version", iDataVersion);
@@ -26575,16 +26759,17 @@
2657526759
*/
2657626760
static int shell_dbtotxt_command(ShellState *p, int nArg, char **azArg){
2657726761
sqlite3_stmt *pStmt = 0;
2657826762
sqlite3_int64 nPage = 0;
2657926763
int pgSz = 0;
26580
- const char *zFilename;
2658126764
const char *zTail;
2658226765
char *zName = 0;
2658326766
int rc, i, j;
2658426767
unsigned char bShow[256]; /* Characters ok to display */
2658526768
26769
+ UNUSED_PARAMETER(nArg);
26770
+ UNUSED_PARAMETER(azArg);
2658626771
memset(bShow, '.', sizeof(bShow));
2658726772
for(i=' '; i<='~'; i++){
2658826773
if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = (unsigned char)i;
2658926774
}
2659026775
rc = sqlite3_prepare_v2(p->db, "PRAGMA page_size", -1, &pStmt, 0);
@@ -26603,21 +26788,19 @@
2660326788
sqlite3_finalize(pStmt);
2660426789
pStmt = 0;
2660526790
if( nPage<1 ) goto dbtotxt_error;
2660626791
rc = sqlite3_prepare_v2(p->db, "PRAGMA databases", -1, &pStmt, 0);
2660726792
if( rc ) goto dbtotxt_error;
26608
- rc = 0;
2660926793
if( sqlite3_step(pStmt)!=SQLITE_ROW ){
26610
- zTail = zFilename = "unk.db";
26794
+ zTail = "unk.db";
2661126795
}else{
26612
- zFilename = (const char*)sqlite3_column_text(pStmt, 2);
26796
+ const char *zFilename = (const char*)sqlite3_column_text(pStmt, 2);
2661326797
if( zFilename==0 || zFilename[0]==0 ) zFilename = "unk.db";
2661426798
zTail = strrchr(zFilename, '/');
2661526799
#if defined(_WIN32)
2661626800
if( zTail==0 ) zTail = strrchr(zFilename, '\\');
2661726801
#endif
26618
- if( zTail ) zFilename = zTail;
2661926802
}
2662026803
zName = strdup(zTail);
2662126804
shell_check_oom(zName);
2662226805
sqlite3_fprintf(p->out, "| size %lld pagesize %d filename %s\n",
2662326806
nPage*pgSz, pgSz, zName);
@@ -26624,11 +26807,10 @@
2662426807
sqlite3_finalize(pStmt);
2662526808
pStmt = 0;
2662626809
rc = sqlite3_prepare_v2(p->db,
2662726810
"SELECT pgno, data FROM sqlite_dbpage ORDER BY pgno", -1, &pStmt, 0);
2662826811
if( rc ) goto dbtotxt_error;
26629
- rc = 0;
2663026812
while( sqlite3_step(pStmt)==SQLITE_ROW ){
2663126813
sqlite3_int64 pgno = sqlite3_column_int64(pStmt, 0);
2663226814
const u8 *aData = sqlite3_column_blob(pStmt, 1);
2663326815
int seenPageLabel = 0;
2663426816
for(i=0; i<pgSz; i+=16){
@@ -28216,12 +28398,12 @@
2821628398
}else if( *pDb==0 ){
2821728399
return 0;
2821828400
}else{
2821928401
/* Formulate the columns spec, close the DB, zero *pDb. */
2822028402
char *zColsSpec = 0;
28221
- int hasDupes = db_int(*pDb, zHasDupes);
28222
- int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
28403
+ int hasDupes = db_int(*pDb, "%s", zHasDupes);
28404
+ int nDigits = (hasDupes)? db_int(*pDb, "%s", zColDigits) : 0;
2822328405
if( hasDupes ){
2822428406
#ifdef SHELL_COLUMN_RENAME_CLEAN
2822528407
rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
2822628408
rc_err_oom_die(rc);
2822728409
#endif
@@ -28232,11 +28414,11 @@
2823228414
sqlite3_bind_int(pStmt, 1, nDigits);
2823328415
rc = sqlite3_step(pStmt);
2823428416
sqlite3_finalize(pStmt);
2823528417
if( rc!=SQLITE_DONE ) rc_err_oom_die(SQLITE_NOMEM);
2823628418
}
28237
- assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
28419
+ assert(db_int(*pDb, "%s", zHasDupes)==0); /* Consider: remove this */
2823828420
rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
2823928421
rc_err_oom_die(rc);
2824028422
rc = sqlite3_step(pStmt);
2824128423
if( rc==SQLITE_ROW ){
2824228424
zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
@@ -29282,11 +29464,15 @@
2928229464
/* Below, resources must be freed before exit. */
2928329465
while( (nSkip--)>0 ){
2928429466
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
2928529467
}
2928629468
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
29287
- if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0) ){
29469
+ if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0)
29470
+ && 0==db_int(p->db, "SELECT count(*) FROM \"%w\".sqlite_schema"
29471
+ " WHERE name=%Q AND type='view'",
29472
+ zSchema ? zSchema : "main", zTable)
29473
+ ){
2928829474
/* Table does not exist. Create it. */
2928929475
sqlite3 *dbCols = 0;
2929029476
char *zRenames = 0;
2929129477
char *zColDefs;
2929229478
zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"",
@@ -30354,11 +30540,14 @@
3035430540
}
3035530541
close_db(pSrc);
3035630542
}else
3035730543
#endif /* !defined(SQLITE_SHELL_FIDDLE) */
3035830544
30359
- if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
30545
+ if( c=='s' &&
30546
+ (cli_strncmp(azArg[0], "scanstats", n)==0 ||
30547
+ cli_strncmp(azArg[0], "scanstatus", n)==0)
30548
+ ){
3036030549
if( nArg==2 ){
3036130550
if( cli_strcmp(azArg[1], "vm")==0 ){
3036230551
p->scanstatsOn = 3;
3036330552
}else
3036430553
if( cli_strcmp(azArg[1], "est")==0 ){
@@ -31409,11 +31598,13 @@
3140931598
{ 0x10000000, 1, "OrderBySubq" },
3141031599
{ 0xffffffff, 0, "All" },
3141131600
};
3141231601
unsigned int curOpt;
3141331602
unsigned int newOpt;
31603
+ unsigned int m;
3141431604
int ii;
31605
+ int nOff;
3141531606
sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, p->db, &curOpt);
3141631607
newOpt = curOpt;
3141731608
for(ii=2; ii<nArg; ii++){
3141831609
const char *z = azArg[ii];
3141931610
int useLabel = 0;
@@ -31450,28 +31641,32 @@
3145031641
}
3145131642
}
3145231643
}
3145331644
if( curOpt!=newOpt ){
3145431645
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,p->db,newOpt);
31455
- }else if( nArg<3 ){
31456
- curOpt = ~newOpt;
31646
+ }
31647
+ for(ii=nOff=0, m=1; ii<32; ii++, m <<= 1){
31648
+ if( m & newOpt ) nOff++;
3145731649
}
31458
- if( newOpt==0 ){
31459
- sqlite3_fputs("+All\n", p->out);
31460
- }else if( newOpt==0xffffffff ){
31461
- sqlite3_fputs("-All\n", p->out);
31650
+ if( nOff<12 ){
31651
+ sqlite3_fputs("+All", p->out);
31652
+ for(ii=0; ii<ArraySize(aLabel); ii++){
31653
+ if( !aLabel[ii].bDsply ) continue;
31654
+ if( (newOpt & aLabel[ii].mask)!=0 ){
31655
+ sqlite3_fprintf(p->out, " -%s", aLabel[ii].zLabel);
31656
+ }
31657
+ }
3146231658
}else{
31463
- int jj;
31464
- for(jj=0; jj<ArraySize(aLabel); jj++){
31465
- unsigned int m = aLabel[jj].mask;
31466
- if( !aLabel[jj].bDsply ) continue;
31467
- if( (curOpt&m)!=(newOpt&m) ){
31468
- sqlite3_fprintf(p->out, "%c%s\n", (newOpt & m)==0 ? '+' : '-',
31469
- aLabel[jj].zLabel);
31659
+ sqlite3_fputs("-All", p->out);
31660
+ for(ii=0; ii<ArraySize(aLabel); ii++){
31661
+ if( !aLabel[ii].bDsply ) continue;
31662
+ if( (newOpt & aLabel[ii].mask)==0 ){
31663
+ sqlite3_fprintf(p->out, " +%s", aLabel[ii].zLabel);
3147031664
}
3147131665
}
3147231666
}
31667
+ sqlite3_fputs("\n", p->out);
3147331668
rc2 = isOk = 3;
3147431669
break;
3147531670
}
3147631671
3147731672
/* sqlite3_test_control(int, db, int) */
@@ -31928,11 +32123,10 @@
3192832123
SCAN_TRACKER_REFTYPE pst){
3192932124
char cin;
3193032125
char cWait = (char)qss; /* intentional narrowing loss */
3193132126
if( cWait==0 ){
3193232127
PlainScan:
31933
- assert( cWait==0 );
3193432128
while( (cin = *zLine++)!=0 ){
3193532129
if( IsSpace(cin) )
3193632130
continue;
3193732131
switch (cin){
3193832132
case '-':
@@ -31980,11 +32174,10 @@
3198032174
switch( cWait ){
3198132175
case '*':
3198232176
if( *zLine != '/' )
3198332177
continue;
3198432178
++zLine;
31985
- cWait = 0;
3198632179
CONTINUE_PROMPT_AWAITC(pst, 0);
3198732180
qss = QSS_SETV(qss, 0);
3198832181
goto PlainScan;
3198932182
case '`': case '\'': case '"':
3199032183
if(*zLine==cWait){
@@ -31992,11 +32185,10 @@
3199232185
++zLine;
3199332186
continue;
3199432187
}
3199532188
deliberate_fall_through;
3199632189
case ']':
31997
- cWait = 0;
3199832190
CONTINUE_PROMPT_AWAITC(pst, 0);
3199932191
qss = QSS_SETV(qss, 0);
3200032192
goto PlainScan;
3200132193
default: assert(0);
3200232194
}
@@ -32180,11 +32372,14 @@
3218032372
if( doAutoDetectRestore(p, zSql) ) return 1;
3218132373
return 0;
3218232374
}
3218332375
3218432376
static void echo_group_input(ShellState *p, const char *zDo){
32185
- if( ShellHasFlag(p, SHFLG_Echo) ) sqlite3_fprintf(p->out, "%s\n", zDo);
32377
+ if( ShellHasFlag(p, SHFLG_Echo) ){
32378
+ sqlite3_fprintf(p->out, "%s\n", zDo);
32379
+ fflush(p->out);
32380
+ }
3218632381
}
3218732382
3218832383
#ifdef SQLITE_SHELL_FIDDLE
3218932384
/*
3219032385
** Alternate one_input_line() impl for wasm mode. This is not in the primary
@@ -32640,10 +32835,19 @@
3264032835
}
3264132836
3264232837
static void sayAbnormalExit(void){
3264332838
if( seenInterrupt ) eputz("Program interrupted.\n");
3264432839
}
32840
+
32841
+/* Routine to output from vfstrace
32842
+*/
32843
+static int vfstraceOut(const char *z, void *pArg){
32844
+ ShellState *p = (ShellState*)pArg;
32845
+ sqlite3_fputs(z, p->out);
32846
+ fflush(p->out);
32847
+ return 1;
32848
+}
3264532849
3264632850
#ifndef SQLITE_SHELL_IS_UTF8
3264732851
# if (defined(_WIN32) || defined(WIN32)) \
3264832852
&& (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
3264932853
# define SQLITE_SHELL_IS_UTF8 (0)
@@ -32877,12 +33081,10 @@
3287733081
case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
3287833082
case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
3287933083
default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
3288033084
}
3288133085
}else if( cli_strcmp(z,"-vfstrace")==0 ){
32882
- vfstrace_register("trace",0,(int(*)(const char*,void*))sqlite3_fputs,
32883
- stderr,1);
3288433086
bEnableVfstrace = 1;
3288533087
#ifdef SQLITE_ENABLE_MULTIPLEX
3288633088
}else if( cli_strcmp(z,"-multiplex")==0 ){
3288733089
extern int sqlite3_multiplex_initialize(const char*,int);
3288833090
sqlite3_multiplex_initialize(0, 1);
@@ -32975,10 +33177,13 @@
3297533177
"%s: Error: no database filename specified\n", Argv0);
3297633178
return 1;
3297733179
#endif
3297833180
}
3297933181
data.out = stdout;
33182
+ if( bEnableVfstrace ){
33183
+ vfstrace_register("trace",0,vfstraceOut, &data, 1);
33184
+ }
3298033185
#ifndef SQLITE_SHELL_FIDDLE
3298133186
sqlite3_appendvfs_init(0,0,0);
3298233187
#endif
3298333188
3298433189
/* Go ahead and open the database file if it already exists. If the
3298533190
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -2367,11 +2367,11 @@
2367 **
2368 ******************************************************************************
2369 **
2370 ** This SQLite extension implements functions that compute SHA3 hashes
2371 ** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard.
2372 ** Two SQL functions are implemented:
2373 **
2374 ** sha3(X,SIZE)
2375 ** sha3_agg(Y,SIZE)
2376 ** sha3_query(Z,SIZE)
2377 **
@@ -14193,11 +14193,11 @@
14193 /* A view. Or a trigger on a view. */
14194 if( zSql ) rc = expertSchemaSql(p->dbv, zSql, pzErrmsg);
14195 }else{
14196 IdxTable *pTab;
14197 rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
14198 if( rc==SQLITE_OK ){
14199 int i;
14200 char *zInner = 0;
14201 char *zOuter = 0;
14202 pTab->pNext = p->pTable;
14203 p->pTable = pTab;
@@ -16261,11 +16261,31 @@
16261 **
16262 ** Similar compiler commands will work on different systems. The key
16263 ** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that
16264 ** the shell.c source file will know to include the -vfstrace command-line
16265 ** option and (2) you must compile and link the three source files
16266 ** shell,c, test_vfstrace.c, and sqlite3.c.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16267 */
16268 #include <stdlib.h>
16269 #include <string.h>
16270 /* #include "sqlite3.h" */
16271
@@ -16275,10 +16295,12 @@
16275 */
16276 typedef struct vfstrace_info vfstrace_info;
16277 struct vfstrace_info {
16278 sqlite3_vfs *pRootVfs; /* The underlying real VFS */
16279 int (*xOut)(const char*, void*); /* Send output here */
 
 
16280 void *pOutArg; /* First argument to xOut */
16281 const char *zVfsName; /* Name of this trace-VFS */
16282 sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */
16283 };
16284
@@ -16291,10 +16313,42 @@
16291 vfstrace_info *pInfo; /* The trace-VFS to which this file belongs */
16292 const char *zFName; /* Base name of the file */
16293 sqlite3_file *pReal; /* The real underlying file */
16294 };
16295
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16296 /*
16297 ** Method declarations for vfstrace_file.
16298 */
16299 static int vfstraceClose(sqlite3_file*);
16300 static int vfstraceRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
@@ -16355,15 +16409,17 @@
16355 const char *zFormat,
16356 ...
16357 ){
16358 va_list ap;
16359 char *zMsg;
16360 va_start(ap, zFormat);
16361 zMsg = sqlite3_vmprintf(zFormat, ap);
16362 va_end(ap);
16363 pInfo->xOut(zMsg, pInfo->pOutArg);
16364 sqlite3_free(zMsg);
 
 
16365 }
16366
16367 /*
16368 ** Try to convert an error code into a symbolic name for that error code.
16369 */
@@ -16457,18 +16513,26 @@
16457 int i = *pI;
16458 while( zAppend[0] ){ z[i++] = *(zAppend++); }
16459 z[i] = 0;
16460 *pI = i;
16461 }
 
 
 
 
 
 
 
16462
16463 /*
16464 ** Close an vfstrace-file.
16465 */
16466 static int vfstraceClose(sqlite3_file *pFile){
16467 vfstrace_file *p = (vfstrace_file *)pFile;
16468 vfstrace_info *pInfo = p->pInfo;
16469 int rc;
 
16470 vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
16471 rc = p->pReal->pMethods->xClose(p->pReal);
16472 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16473 if( rc==SQLITE_OK ){
16474 sqlite3_free((void*)p->base.pMethods);
@@ -16487,10 +16551,11 @@
16487 sqlite_int64 iOfst
16488 ){
16489 vfstrace_file *p = (vfstrace_file *)pFile;
16490 vfstrace_info *pInfo = p->pInfo;
16491 int rc;
 
16492 vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
16493 pInfo->zVfsName, p->zFName, iAmt, iOfst);
16494 rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
16495 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16496 return rc;
@@ -16506,10 +16571,11 @@
16506 sqlite_int64 iOfst
16507 ){
16508 vfstrace_file *p = (vfstrace_file *)pFile;
16509 vfstrace_info *pInfo = p->pInfo;
16510 int rc;
 
16511 vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
16512 pInfo->zVfsName, p->zFName, iAmt, iOfst);
16513 rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
16514 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16515 return rc;
@@ -16520,10 +16586,11 @@
16520 */
16521 static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
16522 vfstrace_file *p = (vfstrace_file *)pFile;
16523 vfstrace_info *pInfo = p->pInfo;
16524 int rc;
 
16525 vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
16526 size);
16527 rc = p->pReal->pMethods->xTruncate(p->pReal, size);
16528 vfstrace_printf(pInfo, " -> %d\n", rc);
16529 return rc;
@@ -16544,10 +16611,11 @@
16544 else if( flags & SQLITE_SYNC_NORMAL ) strappend(zBuf, &i, "|NORMAL");
16545 if( flags & SQLITE_SYNC_DATAONLY ) strappend(zBuf, &i, "|DATAONLY");
16546 if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
16547 sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
16548 }
 
16549 vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
16550 &zBuf[1]);
16551 rc = p->pReal->pMethods->xSync(p->pReal, flags);
16552 vfstrace_printf(pInfo, " -> %d\n", rc);
16553 return rc;
@@ -16558,10 +16626,11 @@
16558 */
16559 static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
16560 vfstrace_file *p = (vfstrace_file *)pFile;
16561 vfstrace_info *pInfo = p->pInfo;
16562 int rc;
 
16563 vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
16564 rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
16565 vfstrace_print_errcode(pInfo, " -> %s,", rc);
16566 vfstrace_printf(pInfo, " size=%lld\n", *pSize);
16567 return rc;
@@ -16586,10 +16655,11 @@
16586 */
16587 static int vfstraceLock(sqlite3_file *pFile, int eLock){
16588 vfstrace_file *p = (vfstrace_file *)pFile;
16589 vfstrace_info *pInfo = p->pInfo;
16590 int rc;
 
16591 vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
16592 lockName(eLock));
16593 rc = p->pReal->pMethods->xLock(p->pReal, eLock);
16594 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16595 return rc;
@@ -16600,10 +16670,11 @@
16600 */
16601 static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
16602 vfstrace_file *p = (vfstrace_file *)pFile;
16603 vfstrace_info *pInfo = p->pInfo;
16604 int rc;
 
16605 vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
16606 lockName(eLock));
16607 rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
16608 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16609 return rc;
@@ -16614,10 +16685,11 @@
16614 */
16615 static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
16616 vfstrace_file *p = (vfstrace_file *)pFile;
16617 vfstrace_info *pInfo = p->pInfo;
16618 int rc;
 
16619 vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)",
16620 pInfo->zVfsName, p->zFName);
16621 rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
16622 vfstrace_print_errcode(pInfo, " -> %s", rc);
16623 vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
@@ -16633,10 +16705,11 @@
16633 int rc;
16634 char zBuf[100];
16635 char zBuf2[100];
16636 char *zOp;
16637 char *zRVal = 0;
 
16638 switch( op ){
16639 case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
16640 case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
16641 case SQLITE_SET_LOCKPROXYFILE: zOp = "SET_LOCKPROXYFILE"; break;
16642 case SQLITE_LAST_ERRNO: zOp = "LAST_ERRNO"; break;
@@ -16661,10 +16734,83 @@
16661 case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break;
16662 case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break;
16663 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
16664 case SQLITE_FCNTL_PRAGMA: {
16665 const char *const* a = (const char*const*)pArg;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16666 sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
16667 zOp = zBuf;
16668 break;
16669 }
16670 case SQLITE_FCNTL_BUSYHANDLER: zOp = "BUSYHANDLER"; break;
@@ -16756,10 +16902,11 @@
16756 */
16757 static int vfstraceSectorSize(sqlite3_file *pFile){
16758 vfstrace_file *p = (vfstrace_file *)pFile;
16759 vfstrace_info *pInfo = p->pInfo;
16760 int rc;
 
16761 vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
16762 rc = p->pReal->pMethods->xSectorSize(p->pReal);
16763 vfstrace_printf(pInfo, " -> %d\n", rc);
16764 return rc;
16765 }
@@ -16769,10 +16916,11 @@
16769 */
16770 static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
16771 vfstrace_file *p = (vfstrace_file *)pFile;
16772 vfstrace_info *pInfo = p->pInfo;
16773 int rc;
 
16774 vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
16775 pInfo->zVfsName, p->zFName);
16776 rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
16777 vfstrace_printf(pInfo, " -> 0x%08x\n", rc);
16778 return rc;
@@ -16795,19 +16943,20 @@
16795 vfstrace_file *p = (vfstrace_file *)pFile;
16796 vfstrace_info *pInfo = p->pInfo;
16797 int rc;
16798 char zLck[100];
16799 int i = 0;
 
16800 memcpy(zLck, "|0", 3);
16801 if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK");
16802 if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK");
16803 if( flags & SQLITE_SHM_SHARED ) strappend(zLck, &i, "|SHARED");
16804 if( flags & SQLITE_SHM_EXCLUSIVE ) strappend(zLck, &i, "|EXCLUSIVE");
16805 if( flags & ~(0xf) ){
16806 sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
16807 }
16808 if( ofst>=0 && ofst<sizeof(azLockName)/sizeof(azLockName[0]) ){
16809 vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d(%s),n=%d,%s)",
16810 pInfo->zVfsName, p->zFName, ofst, azLockName[ofst],
16811 n, &zLck[1]);
16812 }else{
16813 vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=5d,n=%d,%s)",
@@ -16826,26 +16975,29 @@
16826 void volatile **pp
16827 ){
16828 vfstrace_file *p = (vfstrace_file *)pFile;
16829 vfstrace_info *pInfo = p->pInfo;
16830 int rc;
 
16831 vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
16832 pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
16833 rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
16834 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16835 return rc;
16836 }
16837 static void vfstraceShmBarrier(sqlite3_file *pFile){
16838 vfstrace_file *p = (vfstrace_file *)pFile;
16839 vfstrace_info *pInfo = p->pInfo;
 
16840 vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
16841 p->pReal->pMethods->xShmBarrier(p->pReal);
16842 }
16843 static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
16844 vfstrace_file *p = (vfstrace_file *)pFile;
16845 vfstrace_info *pInfo = p->pInfo;
16846 int rc;
 
16847 vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
16848 pInfo->zVfsName, p->zFName, delFlag);
16849 rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
16850 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16851 return rc;
@@ -16869,10 +17021,11 @@
16869 sqlite3_vfs *pRoot = pInfo->pRootVfs;
16870 p->pInfo = pInfo;
16871 p->zFName = zName ? fileTail(zName) : "<temp>";
16872 p->pReal = (sqlite3_file *)&p[1];
16873 rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
 
16874 vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
16875 pInfo->zVfsName, p->zFName, flags);
16876 if( p->pReal->pMethods ){
16877 sqlite3_io_methods *pNew = sqlite3_malloc( sizeof(*pNew) );
16878 const sqlite3_io_methods *pSub = p->pReal->pMethods;
@@ -16914,10 +17067,11 @@
16914 */
16915 static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
16916 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
16917 sqlite3_vfs *pRoot = pInfo->pRootVfs;
16918 int rc;
 
16919 vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
16920 pInfo->zVfsName, zPath, dirSync);
16921 rc = pRoot->xDelete(pRoot, zPath, dirSync);
16922 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16923 return rc;
@@ -16934,10 +17088,11 @@
16934 int *pResOut
16935 ){
16936 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
16937 sqlite3_vfs *pRoot = pInfo->pRootVfs;
16938 int rc;
 
16939 vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
16940 pInfo->zVfsName, zPath, flags);
16941 rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
16942 vfstrace_print_errcode(pInfo, " -> %s", rc);
16943 vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
@@ -16956,10 +17111,11 @@
16956 char *zOut
16957 ){
16958 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
16959 sqlite3_vfs *pRoot = pInfo->pRootVfs;
16960 int rc;
 
16961 vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
16962 pInfo->zVfsName, zPath);
16963 rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
16964 vfstrace_print_errcode(pInfo, " -> %s", rc);
16965 vfstrace_printf(pInfo, ", out=\"%.*s\"\n", nOut, zOut);
@@ -16970,10 +17126,11 @@
16970 ** Open the dynamic library located at zPath and return a handle.
16971 */
16972 static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
16973 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
16974 sqlite3_vfs *pRoot = pInfo->pRootVfs;
 
16975 vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
16976 return pRoot->xDlOpen(pRoot, zPath);
16977 }
16978
16979 /*
@@ -16982,10 +17139,11 @@
16982 ** with dynamic libraries.
16983 */
16984 static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
16985 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
16986 sqlite3_vfs *pRoot = pInfo->pRootVfs;
 
16987 vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
16988 pRoot->xDlError(pRoot, nByte, zErrMsg);
16989 vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
16990 }
16991
@@ -17003,10 +17161,11 @@
17003 ** Close the dynamic library handle pHandle.
17004 */
17005 static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
17006 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17007 sqlite3_vfs *pRoot = pInfo->pRootVfs;
 
17008 vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
17009 pRoot->xDlClose(pRoot, pHandle);
17010 }
17011
17012 /*
@@ -17014,10 +17173,11 @@
17014 ** random data.
17015 */
17016 static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
17017 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17018 sqlite3_vfs *pRoot = pInfo->pRootVfs;
 
17019 vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
17020 return pRoot->xRandomness(pRoot, nByte, zBufOut);
17021 }
17022
17023 /*
@@ -17025,34 +17185,52 @@
17025 ** actually slept.
17026 */
17027 static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
17028 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17029 sqlite3_vfs *pRoot = pInfo->pRootVfs;
 
 
17030 return pRoot->xSleep(pRoot, nMicro);
17031 }
17032
17033 /*
17034 ** Return the current time as a Julian Day number in *pTimeOut.
17035 */
17036 static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
17037 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17038 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17039 return pRoot->xCurrentTime(pRoot, pTimeOut);
 
 
 
 
 
17040 }
17041 static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
17042 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17043 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17044 return pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
 
 
 
 
 
17045 }
17046
17047 /*
17048 ** Return th3 most recent error code and message
17049 */
17050 static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){
17051 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17052 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17053 return pRoot->xGetLastError(pRoot, iErr, zErr);
 
 
 
 
 
 
17054 }
17055
17056 /*
17057 ** Override system calls.
17058 */
@@ -17142,10 +17320,12 @@
17142 pInfo->pRootVfs = pRoot;
17143 pInfo->xOut = xOut;
17144 pInfo->pOutArg = pOutArg;
17145 pInfo->zVfsName = pNew->zName;
17146 pInfo->pTraceVfs = pNew;
 
 
17147 vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
17148 pInfo->zVfsName, pRoot->zName);
17149 return sqlite3_vfs_register(pNew, makeDefault);
17150 }
17151
@@ -26444,18 +26624,24 @@
26444 #endif
26445
26446 /*
26447 ** Run an SQL command and return the single integer result.
26448 */
26449 static int db_int(sqlite3 *db, const char *zSql){
26450 sqlite3_stmt *pStmt;
26451 int res = 0;
26452 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
 
 
 
 
 
26453 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
26454 res = sqlite3_column_int(pStmt,0);
26455 }
26456 sqlite3_finalize(pStmt);
 
26457 return res;
26458 }
26459
26460 #if SQLITE_SHELL_HAVE_RECOVER
26461 /*
@@ -26554,13 +26740,11 @@
26554 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
26555 }else{
26556 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
26557 }
26558 for(i=0; i<ArraySize(aQuery); i++){
26559 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
26560 int val = db_int(p->db, zSql);
26561 sqlite3_free(zSql);
26562 sqlite3_fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
26563 }
26564 sqlite3_free(zSchemaTab);
26565 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
26566 sqlite3_fprintf(p->out, "%-20s %u\n", "data version", iDataVersion);
@@ -26575,16 +26759,17 @@
26575 */
26576 static int shell_dbtotxt_command(ShellState *p, int nArg, char **azArg){
26577 sqlite3_stmt *pStmt = 0;
26578 sqlite3_int64 nPage = 0;
26579 int pgSz = 0;
26580 const char *zFilename;
26581 const char *zTail;
26582 char *zName = 0;
26583 int rc, i, j;
26584 unsigned char bShow[256]; /* Characters ok to display */
26585
 
 
26586 memset(bShow, '.', sizeof(bShow));
26587 for(i=' '; i<='~'; i++){
26588 if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = (unsigned char)i;
26589 }
26590 rc = sqlite3_prepare_v2(p->db, "PRAGMA page_size", -1, &pStmt, 0);
@@ -26603,21 +26788,19 @@
26603 sqlite3_finalize(pStmt);
26604 pStmt = 0;
26605 if( nPage<1 ) goto dbtotxt_error;
26606 rc = sqlite3_prepare_v2(p->db, "PRAGMA databases", -1, &pStmt, 0);
26607 if( rc ) goto dbtotxt_error;
26608 rc = 0;
26609 if( sqlite3_step(pStmt)!=SQLITE_ROW ){
26610 zTail = zFilename = "unk.db";
26611 }else{
26612 zFilename = (const char*)sqlite3_column_text(pStmt, 2);
26613 if( zFilename==0 || zFilename[0]==0 ) zFilename = "unk.db";
26614 zTail = strrchr(zFilename, '/');
26615 #if defined(_WIN32)
26616 if( zTail==0 ) zTail = strrchr(zFilename, '\\');
26617 #endif
26618 if( zTail ) zFilename = zTail;
26619 }
26620 zName = strdup(zTail);
26621 shell_check_oom(zName);
26622 sqlite3_fprintf(p->out, "| size %lld pagesize %d filename %s\n",
26623 nPage*pgSz, pgSz, zName);
@@ -26624,11 +26807,10 @@
26624 sqlite3_finalize(pStmt);
26625 pStmt = 0;
26626 rc = sqlite3_prepare_v2(p->db,
26627 "SELECT pgno, data FROM sqlite_dbpage ORDER BY pgno", -1, &pStmt, 0);
26628 if( rc ) goto dbtotxt_error;
26629 rc = 0;
26630 while( sqlite3_step(pStmt)==SQLITE_ROW ){
26631 sqlite3_int64 pgno = sqlite3_column_int64(pStmt, 0);
26632 const u8 *aData = sqlite3_column_blob(pStmt, 1);
26633 int seenPageLabel = 0;
26634 for(i=0; i<pgSz; i+=16){
@@ -28216,12 +28398,12 @@
28216 }else if( *pDb==0 ){
28217 return 0;
28218 }else{
28219 /* Formulate the columns spec, close the DB, zero *pDb. */
28220 char *zColsSpec = 0;
28221 int hasDupes = db_int(*pDb, zHasDupes);
28222 int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
28223 if( hasDupes ){
28224 #ifdef SHELL_COLUMN_RENAME_CLEAN
28225 rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
28226 rc_err_oom_die(rc);
28227 #endif
@@ -28232,11 +28414,11 @@
28232 sqlite3_bind_int(pStmt, 1, nDigits);
28233 rc = sqlite3_step(pStmt);
28234 sqlite3_finalize(pStmt);
28235 if( rc!=SQLITE_DONE ) rc_err_oom_die(SQLITE_NOMEM);
28236 }
28237 assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
28238 rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
28239 rc_err_oom_die(rc);
28240 rc = sqlite3_step(pStmt);
28241 if( rc==SQLITE_ROW ){
28242 zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
@@ -29282,11 +29464,15 @@
29282 /* Below, resources must be freed before exit. */
29283 while( (nSkip--)>0 ){
29284 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
29285 }
29286 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
29287 if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0) ){
 
 
 
 
29288 /* Table does not exist. Create it. */
29289 sqlite3 *dbCols = 0;
29290 char *zRenames = 0;
29291 char *zColDefs;
29292 zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"",
@@ -30354,11 +30540,14 @@
30354 }
30355 close_db(pSrc);
30356 }else
30357 #endif /* !defined(SQLITE_SHELL_FIDDLE) */
30358
30359 if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
 
 
 
30360 if( nArg==2 ){
30361 if( cli_strcmp(azArg[1], "vm")==0 ){
30362 p->scanstatsOn = 3;
30363 }else
30364 if( cli_strcmp(azArg[1], "est")==0 ){
@@ -31409,11 +31598,13 @@
31409 { 0x10000000, 1, "OrderBySubq" },
31410 { 0xffffffff, 0, "All" },
31411 };
31412 unsigned int curOpt;
31413 unsigned int newOpt;
 
31414 int ii;
 
31415 sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, p->db, &curOpt);
31416 newOpt = curOpt;
31417 for(ii=2; ii<nArg; ii++){
31418 const char *z = azArg[ii];
31419 int useLabel = 0;
@@ -31450,28 +31641,32 @@
31450 }
31451 }
31452 }
31453 if( curOpt!=newOpt ){
31454 sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,p->db,newOpt);
31455 }else if( nArg<3 ){
31456 curOpt = ~newOpt;
 
31457 }
31458 if( newOpt==0 ){
31459 sqlite3_fputs("+All\n", p->out);
31460 }else if( newOpt==0xffffffff ){
31461 sqlite3_fputs("-All\n", p->out);
 
 
 
 
31462 }else{
31463 int jj;
31464 for(jj=0; jj<ArraySize(aLabel); jj++){
31465 unsigned int m = aLabel[jj].mask;
31466 if( !aLabel[jj].bDsply ) continue;
31467 if( (curOpt&m)!=(newOpt&m) ){
31468 sqlite3_fprintf(p->out, "%c%s\n", (newOpt & m)==0 ? '+' : '-',
31469 aLabel[jj].zLabel);
31470 }
31471 }
31472 }
 
31473 rc2 = isOk = 3;
31474 break;
31475 }
31476
31477 /* sqlite3_test_control(int, db, int) */
@@ -31928,11 +32123,10 @@
31928 SCAN_TRACKER_REFTYPE pst){
31929 char cin;
31930 char cWait = (char)qss; /* intentional narrowing loss */
31931 if( cWait==0 ){
31932 PlainScan:
31933 assert( cWait==0 );
31934 while( (cin = *zLine++)!=0 ){
31935 if( IsSpace(cin) )
31936 continue;
31937 switch (cin){
31938 case '-':
@@ -31980,11 +32174,10 @@
31980 switch( cWait ){
31981 case '*':
31982 if( *zLine != '/' )
31983 continue;
31984 ++zLine;
31985 cWait = 0;
31986 CONTINUE_PROMPT_AWAITC(pst, 0);
31987 qss = QSS_SETV(qss, 0);
31988 goto PlainScan;
31989 case '`': case '\'': case '"':
31990 if(*zLine==cWait){
@@ -31992,11 +32185,10 @@
31992 ++zLine;
31993 continue;
31994 }
31995 deliberate_fall_through;
31996 case ']':
31997 cWait = 0;
31998 CONTINUE_PROMPT_AWAITC(pst, 0);
31999 qss = QSS_SETV(qss, 0);
32000 goto PlainScan;
32001 default: assert(0);
32002 }
@@ -32180,11 +32372,14 @@
32180 if( doAutoDetectRestore(p, zSql) ) return 1;
32181 return 0;
32182 }
32183
32184 static void echo_group_input(ShellState *p, const char *zDo){
32185 if( ShellHasFlag(p, SHFLG_Echo) ) sqlite3_fprintf(p->out, "%s\n", zDo);
 
 
 
32186 }
32187
32188 #ifdef SQLITE_SHELL_FIDDLE
32189 /*
32190 ** Alternate one_input_line() impl for wasm mode. This is not in the primary
@@ -32640,10 +32835,19 @@
32640 }
32641
32642 static void sayAbnormalExit(void){
32643 if( seenInterrupt ) eputz("Program interrupted.\n");
32644 }
 
 
 
 
 
 
 
 
 
32645
32646 #ifndef SQLITE_SHELL_IS_UTF8
32647 # if (defined(_WIN32) || defined(WIN32)) \
32648 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
32649 # define SQLITE_SHELL_IS_UTF8 (0)
@@ -32877,12 +33081,10 @@
32877 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
32878 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
32879 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
32880 }
32881 }else if( cli_strcmp(z,"-vfstrace")==0 ){
32882 vfstrace_register("trace",0,(int(*)(const char*,void*))sqlite3_fputs,
32883 stderr,1);
32884 bEnableVfstrace = 1;
32885 #ifdef SQLITE_ENABLE_MULTIPLEX
32886 }else if( cli_strcmp(z,"-multiplex")==0 ){
32887 extern int sqlite3_multiplex_initialize(const char*,int);
32888 sqlite3_multiplex_initialize(0, 1);
@@ -32975,10 +33177,13 @@
32975 "%s: Error: no database filename specified\n", Argv0);
32976 return 1;
32977 #endif
32978 }
32979 data.out = stdout;
 
 
 
32980 #ifndef SQLITE_SHELL_FIDDLE
32981 sqlite3_appendvfs_init(0,0,0);
32982 #endif
32983
32984 /* Go ahead and open the database file if it already exists. If the
32985
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -2367,11 +2367,11 @@
2367 **
2368 ******************************************************************************
2369 **
2370 ** This SQLite extension implements functions that compute SHA3 hashes
2371 ** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard.
2372 ** Three SQL functions are implemented:
2373 **
2374 ** sha3(X,SIZE)
2375 ** sha3_agg(Y,SIZE)
2376 ** sha3_query(Z,SIZE)
2377 **
@@ -14193,11 +14193,11 @@
14193 /* A view. Or a trigger on a view. */
14194 if( zSql ) rc = expertSchemaSql(p->dbv, zSql, pzErrmsg);
14195 }else{
14196 IdxTable *pTab;
14197 rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
14198 if( rc==SQLITE_OK && ALWAYS(pTab!=0) ){
14199 int i;
14200 char *zInner = 0;
14201 char *zOuter = 0;
14202 pTab->pNext = p->pTable;
14203 p->pTable = pTab;
@@ -16261,11 +16261,31 @@
16261 **
16262 ** Similar compiler commands will work on different systems. The key
16263 ** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that
16264 ** the shell.c source file will know to include the -vfstrace command-line
16265 ** option and (2) you must compile and link the three source files
16266 ** shell,c, test_vfstrace.c, and sqlite3.c.
16267 **
16268 ** RUNTIME CONTROL OF VFSTRACE OUTPUT
16269 **
16270 ** The application can use the "vfstrace" pragma to control which VFS
16271 ** APIs are traced. To disable all output:
16272 **
16273 ** PRAGMA vfstrace('-all');
16274 **
16275 ** To enable all output (which is the default setting):
16276 **
16277 ** PRAGMA vfstrace('+all');
16278 **
16279 ** Individual APIs can be enabled or disabled by name, with or without
16280 ** the initial "x" character. For example, to set up for tracing lock
16281 ** primatives only:
16282 **
16283 ** PRAGMA vfstrace('-all, +Lock,Unlock,ShmLock');
16284 **
16285 ** The argument to the vfstrace pragma ignores capitalization and any
16286 ** characters other than alphabetics, '+', and '-'.
16287 */
16288 #include <stdlib.h>
16289 #include <string.h>
16290 /* #include "sqlite3.h" */
16291
@@ -16275,10 +16295,12 @@
16295 */
16296 typedef struct vfstrace_info vfstrace_info;
16297 struct vfstrace_info {
16298 sqlite3_vfs *pRootVfs; /* The underlying real VFS */
16299 int (*xOut)(const char*, void*); /* Send output here */
16300 unsigned int mTrace; /* Mask of interfaces to trace */
16301 u8 bOn; /* Tracing on/off */
16302 void *pOutArg; /* First argument to xOut */
16303 const char *zVfsName; /* Name of this trace-VFS */
16304 sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */
16305 };
16306
@@ -16291,10 +16313,42 @@
16313 vfstrace_info *pInfo; /* The trace-VFS to which this file belongs */
16314 const char *zFName; /* Base name of the file */
16315 sqlite3_file *pReal; /* The real underlying file */
16316 };
16317
16318 /*
16319 ** Bit values for vfstrace_info.mTrace.
16320 */
16321 #define VTR_CLOSE 0x00000001
16322 #define VTR_READ 0x00000002
16323 #define VTR_WRITE 0x00000004
16324 #define VTR_TRUNC 0x00000008
16325 #define VTR_SYNC 0x00000010
16326 #define VTR_FSIZE 0x00000020
16327 #define VTR_LOCK 0x00000040
16328 #define VTR_UNLOCK 0x00000080
16329 #define VTR_CRL 0x00000100
16330 #define VTR_FCTRL 0x00000200
16331 #define VTR_SECSZ 0x00000400
16332 #define VTR_DEVCHAR 0x00000800
16333 #define VTR_SHMLOCK 0x00001000
16334 #define VTR_SHMMAP 0x00002000
16335 #define VTR_SHMBAR 0x00004000
16336 #define VTR_SHMUNMAP 0x00008000
16337 #define VTR_OPEN 0x00010000
16338 #define VTR_DELETE 0x00020000
16339 #define VTR_ACCESS 0x00040000
16340 #define VTR_FULLPATH 0x00080000
16341 #define VTR_DLOPEN 0x00100000
16342 #define VTR_DLERR 0x00200000
16343 #define VTR_DLSYM 0x00400000
16344 #define VTR_DLCLOSE 0x00800000
16345 #define VTR_RAND 0x01000000
16346 #define VTR_SLEEP 0x02000000
16347 #define VTR_CURTIME 0x04000000
16348 #define VTR_LASTERR 0x08000000
16349
16350 /*
16351 ** Method declarations for vfstrace_file.
16352 */
16353 static int vfstraceClose(sqlite3_file*);
16354 static int vfstraceRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
@@ -16355,15 +16409,17 @@
16409 const char *zFormat,
16410 ...
16411 ){
16412 va_list ap;
16413 char *zMsg;
16414 if( pInfo->bOn ){
16415 va_start(ap, zFormat);
16416 zMsg = sqlite3_vmprintf(zFormat, ap);
16417 va_end(ap);
16418 pInfo->xOut(zMsg, pInfo->pOutArg);
16419 sqlite3_free(zMsg);
16420 }
16421 }
16422
16423 /*
16424 ** Try to convert an error code into a symbolic name for that error code.
16425 */
@@ -16457,18 +16513,26 @@
16513 int i = *pI;
16514 while( zAppend[0] ){ z[i++] = *(zAppend++); }
16515 z[i] = 0;
16516 *pI = i;
16517 }
16518
16519 /*
16520 ** Turn tracing output on or off according to mMask.
16521 */
16522 static void vfstraceOnOff(vfstrace_info *pInfo, unsigned int mMask){
16523 pInfo->bOn = (pInfo->mTrace & mMask)!=0;
16524 }
16525
16526 /*
16527 ** Close an vfstrace-file.
16528 */
16529 static int vfstraceClose(sqlite3_file *pFile){
16530 vfstrace_file *p = (vfstrace_file *)pFile;
16531 vfstrace_info *pInfo = p->pInfo;
16532 int rc;
16533 vfstraceOnOff(pInfo, VTR_CLOSE);
16534 vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
16535 rc = p->pReal->pMethods->xClose(p->pReal);
16536 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16537 if( rc==SQLITE_OK ){
16538 sqlite3_free((void*)p->base.pMethods);
@@ -16487,10 +16551,11 @@
16551 sqlite_int64 iOfst
16552 ){
16553 vfstrace_file *p = (vfstrace_file *)pFile;
16554 vfstrace_info *pInfo = p->pInfo;
16555 int rc;
16556 vfstraceOnOff(pInfo, VTR_READ);
16557 vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
16558 pInfo->zVfsName, p->zFName, iAmt, iOfst);
16559 rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
16560 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16561 return rc;
@@ -16506,10 +16571,11 @@
16571 sqlite_int64 iOfst
16572 ){
16573 vfstrace_file *p = (vfstrace_file *)pFile;
16574 vfstrace_info *pInfo = p->pInfo;
16575 int rc;
16576 vfstraceOnOff(pInfo, VTR_WRITE);
16577 vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
16578 pInfo->zVfsName, p->zFName, iAmt, iOfst);
16579 rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
16580 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16581 return rc;
@@ -16520,10 +16586,11 @@
16586 */
16587 static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
16588 vfstrace_file *p = (vfstrace_file *)pFile;
16589 vfstrace_info *pInfo = p->pInfo;
16590 int rc;
16591 vfstraceOnOff(pInfo, VTR_TRUNC);
16592 vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
16593 size);
16594 rc = p->pReal->pMethods->xTruncate(p->pReal, size);
16595 vfstrace_printf(pInfo, " -> %d\n", rc);
16596 return rc;
@@ -16544,10 +16611,11 @@
16611 else if( flags & SQLITE_SYNC_NORMAL ) strappend(zBuf, &i, "|NORMAL");
16612 if( flags & SQLITE_SYNC_DATAONLY ) strappend(zBuf, &i, "|DATAONLY");
16613 if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
16614 sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
16615 }
16616 vfstraceOnOff(pInfo, VTR_SYNC);
16617 vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
16618 &zBuf[1]);
16619 rc = p->pReal->pMethods->xSync(p->pReal, flags);
16620 vfstrace_printf(pInfo, " -> %d\n", rc);
16621 return rc;
@@ -16558,10 +16626,11 @@
16626 */
16627 static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
16628 vfstrace_file *p = (vfstrace_file *)pFile;
16629 vfstrace_info *pInfo = p->pInfo;
16630 int rc;
16631 vfstraceOnOff(pInfo, VTR_FSIZE);
16632 vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
16633 rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
16634 vfstrace_print_errcode(pInfo, " -> %s,", rc);
16635 vfstrace_printf(pInfo, " size=%lld\n", *pSize);
16636 return rc;
@@ -16586,10 +16655,11 @@
16655 */
16656 static int vfstraceLock(sqlite3_file *pFile, int eLock){
16657 vfstrace_file *p = (vfstrace_file *)pFile;
16658 vfstrace_info *pInfo = p->pInfo;
16659 int rc;
16660 vfstraceOnOff(pInfo, VTR_LOCK);
16661 vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
16662 lockName(eLock));
16663 rc = p->pReal->pMethods->xLock(p->pReal, eLock);
16664 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16665 return rc;
@@ -16600,10 +16670,11 @@
16670 */
16671 static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
16672 vfstrace_file *p = (vfstrace_file *)pFile;
16673 vfstrace_info *pInfo = p->pInfo;
16674 int rc;
16675 vfstraceOnOff(pInfo, VTR_UNLOCK);
16676 vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
16677 lockName(eLock));
16678 rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
16679 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16680 return rc;
@@ -16614,10 +16685,11 @@
16685 */
16686 static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
16687 vfstrace_file *p = (vfstrace_file *)pFile;
16688 vfstrace_info *pInfo = p->pInfo;
16689 int rc;
16690 vfstraceOnOff(pInfo, VTR_CRL);
16691 vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)",
16692 pInfo->zVfsName, p->zFName);
16693 rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
16694 vfstrace_print_errcode(pInfo, " -> %s", rc);
16695 vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
@@ -16633,10 +16705,11 @@
16705 int rc;
16706 char zBuf[100];
16707 char zBuf2[100];
16708 char *zOp;
16709 char *zRVal = 0;
16710 vfstraceOnOff(pInfo, VTR_FCTRL);
16711 switch( op ){
16712 case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
16713 case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
16714 case SQLITE_SET_LOCKPROXYFILE: zOp = "SET_LOCKPROXYFILE"; break;
16715 case SQLITE_LAST_ERRNO: zOp = "LAST_ERRNO"; break;
@@ -16661,10 +16734,83 @@
16734 case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break;
16735 case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break;
16736 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
16737 case SQLITE_FCNTL_PRAGMA: {
16738 const char *const* a = (const char*const*)pArg;
16739 if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){
16740 const u8 *zArg = (const u8*)a[2];
16741 if( zArg[0]>='0' && zArg[0]<=9 ){
16742 pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0);
16743 }else{
16744 static const struct {
16745 const char *z;
16746 unsigned int m;
16747 } aKw[] = {
16748 { "all", 0xffffffff },
16749 { "close", VTR_CLOSE },
16750 { "read", VTR_READ },
16751 { "write", VTR_WRITE },
16752 { "truncate", VTR_TRUNC },
16753 { "sync", VTR_SYNC },
16754 { "filesize", VTR_FSIZE },
16755 { "lock", VTR_LOCK },
16756 { "unlock", VTR_UNLOCK },
16757 { "checkreservedlock", VTR_CRL },
16758 { "filecontrol", VTR_FCTRL },
16759 { "sectorsize", VTR_SECSZ },
16760 { "devicecharacteristics", VTR_DEVCHAR },
16761 { "shmlock", VTR_SHMLOCK },
16762 { "shmmap", VTR_SHMMAP },
16763 { "shmummap", VTR_SHMUNMAP },
16764 { "shmbarrier", VTR_SHMBAR },
16765 { "open", VTR_OPEN },
16766 { "delete", VTR_DELETE },
16767 { "access", VTR_ACCESS },
16768 { "fullpathname", VTR_FULLPATH },
16769 { "dlopen", VTR_DLOPEN },
16770 { "dlerror", VTR_DLERR },
16771 { "dlsym", VTR_DLSYM },
16772 { "dlclose", VTR_DLCLOSE },
16773 { "randomness", VTR_RAND },
16774 { "sleep", VTR_SLEEP },
16775 { "currenttime", VTR_CURTIME },
16776 { "currenttimeint64", VTR_CURTIME },
16777 { "getlasterror", VTR_LASTERR },
16778 };
16779 int onOff = 1;
16780 while( zArg[0] ){
16781 int jj, n;
16782 while( zArg[0]!=0 && zArg[0]!='-' && zArg[0]!='+'
16783 && !isalpha(zArg[0]) ) zArg++;
16784 if( zArg[0]==0 ) break;
16785 if( zArg[0]=='-' ){
16786 onOff = 0;
16787 zArg++;
16788 }else if( zArg[0]=='+' ){
16789 onOff = 1;
16790 zArg++;
16791 }
16792 while( !isalpha(zArg[0]) ){
16793 if( zArg[0]==0 ) break;
16794 zArg++;
16795 }
16796 if( zArg[0]=='x' && isalpha(zArg[1]) ) zArg++;
16797 for(n=0; isalpha(zArg[n]); n++){}
16798 for(jj=0; jj<(int)(sizeof(aKw)/sizeof(aKw[0])); jj++){
16799 if( sqlite3_strnicmp(aKw[jj].z,(const char*)zArg,n)==0 ){
16800 if( onOff ){
16801 pInfo->mTrace |= aKw[jj].m;
16802 }else{
16803 pInfo->mTrace &= ~aKw[jj].m;
16804 }
16805 break;
16806 }
16807 }
16808 zArg += n;
16809 }
16810 }
16811 }
16812 sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
16813 zOp = zBuf;
16814 break;
16815 }
16816 case SQLITE_FCNTL_BUSYHANDLER: zOp = "BUSYHANDLER"; break;
@@ -16756,10 +16902,11 @@
16902 */
16903 static int vfstraceSectorSize(sqlite3_file *pFile){
16904 vfstrace_file *p = (vfstrace_file *)pFile;
16905 vfstrace_info *pInfo = p->pInfo;
16906 int rc;
16907 vfstraceOnOff(pInfo, VTR_SECSZ);
16908 vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
16909 rc = p->pReal->pMethods->xSectorSize(p->pReal);
16910 vfstrace_printf(pInfo, " -> %d\n", rc);
16911 return rc;
16912 }
@@ -16769,10 +16916,11 @@
16916 */
16917 static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
16918 vfstrace_file *p = (vfstrace_file *)pFile;
16919 vfstrace_info *pInfo = p->pInfo;
16920 int rc;
16921 vfstraceOnOff(pInfo, VTR_DEVCHAR);
16922 vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
16923 pInfo->zVfsName, p->zFName);
16924 rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
16925 vfstrace_printf(pInfo, " -> 0x%08x\n", rc);
16926 return rc;
@@ -16795,19 +16943,20 @@
16943 vfstrace_file *p = (vfstrace_file *)pFile;
16944 vfstrace_info *pInfo = p->pInfo;
16945 int rc;
16946 char zLck[100];
16947 int i = 0;
16948 vfstraceOnOff(pInfo, VTR_SHMLOCK);
16949 memcpy(zLck, "|0", 3);
16950 if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK");
16951 if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK");
16952 if( flags & SQLITE_SHM_SHARED ) strappend(zLck, &i, "|SHARED");
16953 if( flags & SQLITE_SHM_EXCLUSIVE ) strappend(zLck, &i, "|EXCLUSIVE");
16954 if( flags & ~(0xf) ){
16955 sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
16956 }
16957 if( ofst>=0 && ofst<(int)(sizeof(azLockName)/sizeof(azLockName[0])) ){
16958 vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d(%s),n=%d,%s)",
16959 pInfo->zVfsName, p->zFName, ofst, azLockName[ofst],
16960 n, &zLck[1]);
16961 }else{
16962 vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=5d,n=%d,%s)",
@@ -16826,26 +16975,29 @@
16975 void volatile **pp
16976 ){
16977 vfstrace_file *p = (vfstrace_file *)pFile;
16978 vfstrace_info *pInfo = p->pInfo;
16979 int rc;
16980 vfstraceOnOff(pInfo, VTR_SHMMAP);
16981 vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
16982 pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
16983 rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
16984 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
16985 return rc;
16986 }
16987 static void vfstraceShmBarrier(sqlite3_file *pFile){
16988 vfstrace_file *p = (vfstrace_file *)pFile;
16989 vfstrace_info *pInfo = p->pInfo;
16990 vfstraceOnOff(pInfo, VTR_SHMBAR);
16991 vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
16992 p->pReal->pMethods->xShmBarrier(p->pReal);
16993 }
16994 static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
16995 vfstrace_file *p = (vfstrace_file *)pFile;
16996 vfstrace_info *pInfo = p->pInfo;
16997 int rc;
16998 vfstraceOnOff(pInfo, VTR_SHMUNMAP);
16999 vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
17000 pInfo->zVfsName, p->zFName, delFlag);
17001 rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
17002 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
17003 return rc;
@@ -16869,10 +17021,11 @@
17021 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17022 p->pInfo = pInfo;
17023 p->zFName = zName ? fileTail(zName) : "<temp>";
17024 p->pReal = (sqlite3_file *)&p[1];
17025 rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
17026 vfstraceOnOff(pInfo, VTR_OPEN);
17027 vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
17028 pInfo->zVfsName, p->zFName, flags);
17029 if( p->pReal->pMethods ){
17030 sqlite3_io_methods *pNew = sqlite3_malloc( sizeof(*pNew) );
17031 const sqlite3_io_methods *pSub = p->pReal->pMethods;
@@ -16914,10 +17067,11 @@
17067 */
17068 static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
17069 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17070 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17071 int rc;
17072 vfstraceOnOff(pInfo, VTR_DELETE);
17073 vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
17074 pInfo->zVfsName, zPath, dirSync);
17075 rc = pRoot->xDelete(pRoot, zPath, dirSync);
17076 vfstrace_print_errcode(pInfo, " -> %s\n", rc);
17077 return rc;
@@ -16934,10 +17088,11 @@
17088 int *pResOut
17089 ){
17090 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17091 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17092 int rc;
17093 vfstraceOnOff(pInfo, VTR_ACCESS);
17094 vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
17095 pInfo->zVfsName, zPath, flags);
17096 rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
17097 vfstrace_print_errcode(pInfo, " -> %s", rc);
17098 vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
@@ -16956,10 +17111,11 @@
17111 char *zOut
17112 ){
17113 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17114 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17115 int rc;
17116 vfstraceOnOff(pInfo, VTR_FULLPATH);
17117 vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
17118 pInfo->zVfsName, zPath);
17119 rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
17120 vfstrace_print_errcode(pInfo, " -> %s", rc);
17121 vfstrace_printf(pInfo, ", out=\"%.*s\"\n", nOut, zOut);
@@ -16970,10 +17126,11 @@
17126 ** Open the dynamic library located at zPath and return a handle.
17127 */
17128 static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
17129 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17130 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17131 vfstraceOnOff(pInfo, VTR_DLOPEN);
17132 vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
17133 return pRoot->xDlOpen(pRoot, zPath);
17134 }
17135
17136 /*
@@ -16982,10 +17139,11 @@
17139 ** with dynamic libraries.
17140 */
17141 static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
17142 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17143 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17144 vfstraceOnOff(pInfo, VTR_DLERR);
17145 vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
17146 pRoot->xDlError(pRoot, nByte, zErrMsg);
17147 vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
17148 }
17149
@@ -17003,10 +17161,11 @@
17161 ** Close the dynamic library handle pHandle.
17162 */
17163 static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
17164 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17165 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17166 vfstraceOnOff(pInfo, VTR_DLCLOSE);
17167 vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
17168 pRoot->xDlClose(pRoot, pHandle);
17169 }
17170
17171 /*
@@ -17014,10 +17173,11 @@
17173 ** random data.
17174 */
17175 static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
17176 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17177 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17178 vfstraceOnOff(pInfo, VTR_RAND);
17179 vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
17180 return pRoot->xRandomness(pRoot, nByte, zBufOut);
17181 }
17182
17183 /*
@@ -17025,34 +17185,52 @@
17185 ** actually slept.
17186 */
17187 static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
17188 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17189 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17190 vfstraceOnOff(pInfo, VTR_SLEEP);
17191 vfstrace_printf(pInfo, "%s.xSleep(%d)\n", pInfo->zVfsName, nMicro);
17192 return pRoot->xSleep(pRoot, nMicro);
17193 }
17194
17195 /*
17196 ** Return the current time as a Julian Day number in *pTimeOut.
17197 */
17198 static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
17199 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17200 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17201 int rc;
17202 vfstraceOnOff(pInfo, VTR_CURTIME);
17203 vfstrace_printf(pInfo, "%s.xCurrentTime()", pInfo->zVfsName);
17204 rc = pRoot->xCurrentTime(pRoot, pTimeOut);
17205 vfstrace_printf(pInfo, " -> %.17g\n", *pTimeOut);
17206 return rc;
17207 }
17208 static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
17209 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17210 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17211 int rc;
17212 vfstraceOnOff(pInfo, VTR_CURTIME);
17213 vfstrace_printf(pInfo, "%s.xCurrentTimeInt64()", pInfo->zVfsName);
17214 rc = pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
17215 vfstrace_printf(pInfo, " -> %lld\n", *pTimeOut);
17216 return rc;
17217 }
17218
17219 /*
17220 ** Return the most recent error code and message
17221 */
17222 static int vfstraceGetLastError(sqlite3_vfs *pVfs, int nErr, char *zErr){
17223 vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
17224 sqlite3_vfs *pRoot = pInfo->pRootVfs;
17225 int rc;
17226 vfstraceOnOff(pInfo, VTR_LASTERR);
17227 vfstrace_printf(pInfo, "%s.xGetLastError(%d,zBuf)", pInfo->zVfsName, nErr);
17228 if( nErr ) zErr[0] = 0;
17229 rc = pRoot->xGetLastError(pRoot, nErr, zErr);
17230 vfstrace_printf(pInfo, " -> zBuf[] = \"%s\", rc = %d\n", nErr?zErr:"", rc);
17231 return rc;
17232 }
17233
17234 /*
17235 ** Override system calls.
17236 */
@@ -17142,10 +17320,12 @@
17320 pInfo->pRootVfs = pRoot;
17321 pInfo->xOut = xOut;
17322 pInfo->pOutArg = pOutArg;
17323 pInfo->zVfsName = pNew->zName;
17324 pInfo->pTraceVfs = pNew;
17325 pInfo->mTrace = 0xffffffff;
17326 pInfo->bOn = 1;
17327 vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
17328 pInfo->zVfsName, pRoot->zName);
17329 return sqlite3_vfs_register(pNew, makeDefault);
17330 }
17331
@@ -26444,18 +26624,24 @@
26624 #endif
26625
26626 /*
26627 ** Run an SQL command and return the single integer result.
26628 */
26629 static int db_int(sqlite3 *db, const char *zSql, ...){
26630 sqlite3_stmt *pStmt;
26631 int res = 0;
26632 char *z;
26633 va_list ap;
26634 va_start(ap, zSql);
26635 z = sqlite3_vmprintf(zSql, ap);
26636 va_end(ap);
26637 sqlite3_prepare_v2(db, z, -1, &pStmt, 0);
26638 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
26639 res = sqlite3_column_int(pStmt,0);
26640 }
26641 sqlite3_finalize(pStmt);
26642 sqlite3_free(z);
26643 return res;
26644 }
26645
26646 #if SQLITE_SHELL_HAVE_RECOVER
26647 /*
@@ -26554,13 +26740,11 @@
26740 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
26741 }else{
26742 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
26743 }
26744 for(i=0; i<ArraySize(aQuery); i++){
26745 int val = db_int(p->db, aQuery[i].zSql, zSchemaTab);
 
 
26746 sqlite3_fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
26747 }
26748 sqlite3_free(zSchemaTab);
26749 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
26750 sqlite3_fprintf(p->out, "%-20s %u\n", "data version", iDataVersion);
@@ -26575,16 +26759,17 @@
26759 */
26760 static int shell_dbtotxt_command(ShellState *p, int nArg, char **azArg){
26761 sqlite3_stmt *pStmt = 0;
26762 sqlite3_int64 nPage = 0;
26763 int pgSz = 0;
 
26764 const char *zTail;
26765 char *zName = 0;
26766 int rc, i, j;
26767 unsigned char bShow[256]; /* Characters ok to display */
26768
26769 UNUSED_PARAMETER(nArg);
26770 UNUSED_PARAMETER(azArg);
26771 memset(bShow, '.', sizeof(bShow));
26772 for(i=' '; i<='~'; i++){
26773 if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = (unsigned char)i;
26774 }
26775 rc = sqlite3_prepare_v2(p->db, "PRAGMA page_size", -1, &pStmt, 0);
@@ -26603,21 +26788,19 @@
26788 sqlite3_finalize(pStmt);
26789 pStmt = 0;
26790 if( nPage<1 ) goto dbtotxt_error;
26791 rc = sqlite3_prepare_v2(p->db, "PRAGMA databases", -1, &pStmt, 0);
26792 if( rc ) goto dbtotxt_error;
 
26793 if( sqlite3_step(pStmt)!=SQLITE_ROW ){
26794 zTail = "unk.db";
26795 }else{
26796 const char *zFilename = (const char*)sqlite3_column_text(pStmt, 2);
26797 if( zFilename==0 || zFilename[0]==0 ) zFilename = "unk.db";
26798 zTail = strrchr(zFilename, '/');
26799 #if defined(_WIN32)
26800 if( zTail==0 ) zTail = strrchr(zFilename, '\\');
26801 #endif
 
26802 }
26803 zName = strdup(zTail);
26804 shell_check_oom(zName);
26805 sqlite3_fprintf(p->out, "| size %lld pagesize %d filename %s\n",
26806 nPage*pgSz, pgSz, zName);
@@ -26624,11 +26807,10 @@
26807 sqlite3_finalize(pStmt);
26808 pStmt = 0;
26809 rc = sqlite3_prepare_v2(p->db,
26810 "SELECT pgno, data FROM sqlite_dbpage ORDER BY pgno", -1, &pStmt, 0);
26811 if( rc ) goto dbtotxt_error;
 
26812 while( sqlite3_step(pStmt)==SQLITE_ROW ){
26813 sqlite3_int64 pgno = sqlite3_column_int64(pStmt, 0);
26814 const u8 *aData = sqlite3_column_blob(pStmt, 1);
26815 int seenPageLabel = 0;
26816 for(i=0; i<pgSz; i+=16){
@@ -28216,12 +28398,12 @@
28398 }else if( *pDb==0 ){
28399 return 0;
28400 }else{
28401 /* Formulate the columns spec, close the DB, zero *pDb. */
28402 char *zColsSpec = 0;
28403 int hasDupes = db_int(*pDb, "%s", zHasDupes);
28404 int nDigits = (hasDupes)? db_int(*pDb, "%s", zColDigits) : 0;
28405 if( hasDupes ){
28406 #ifdef SHELL_COLUMN_RENAME_CLEAN
28407 rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
28408 rc_err_oom_die(rc);
28409 #endif
@@ -28232,11 +28414,11 @@
28414 sqlite3_bind_int(pStmt, 1, nDigits);
28415 rc = sqlite3_step(pStmt);
28416 sqlite3_finalize(pStmt);
28417 if( rc!=SQLITE_DONE ) rc_err_oom_die(SQLITE_NOMEM);
28418 }
28419 assert(db_int(*pDb, "%s", zHasDupes)==0); /* Consider: remove this */
28420 rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
28421 rc_err_oom_die(rc);
28422 rc = sqlite3_step(pStmt);
28423 if( rc==SQLITE_ROW ){
28424 zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
@@ -29282,11 +29464,15 @@
29464 /* Below, resources must be freed before exit. */
29465 while( (nSkip--)>0 ){
29466 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
29467 }
29468 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
29469 if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0)
29470 && 0==db_int(p->db, "SELECT count(*) FROM \"%w\".sqlite_schema"
29471 " WHERE name=%Q AND type='view'",
29472 zSchema ? zSchema : "main", zTable)
29473 ){
29474 /* Table does not exist. Create it. */
29475 sqlite3 *dbCols = 0;
29476 char *zRenames = 0;
29477 char *zColDefs;
29478 zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"",
@@ -30354,11 +30540,14 @@
30540 }
30541 close_db(pSrc);
30542 }else
30543 #endif /* !defined(SQLITE_SHELL_FIDDLE) */
30544
30545 if( c=='s' &&
30546 (cli_strncmp(azArg[0], "scanstats", n)==0 ||
30547 cli_strncmp(azArg[0], "scanstatus", n)==0)
30548 ){
30549 if( nArg==2 ){
30550 if( cli_strcmp(azArg[1], "vm")==0 ){
30551 p->scanstatsOn = 3;
30552 }else
30553 if( cli_strcmp(azArg[1], "est")==0 ){
@@ -31409,11 +31598,13 @@
31598 { 0x10000000, 1, "OrderBySubq" },
31599 { 0xffffffff, 0, "All" },
31600 };
31601 unsigned int curOpt;
31602 unsigned int newOpt;
31603 unsigned int m;
31604 int ii;
31605 int nOff;
31606 sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, p->db, &curOpt);
31607 newOpt = curOpt;
31608 for(ii=2; ii<nArg; ii++){
31609 const char *z = azArg[ii];
31610 int useLabel = 0;
@@ -31450,28 +31641,32 @@
31641 }
31642 }
31643 }
31644 if( curOpt!=newOpt ){
31645 sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,p->db,newOpt);
31646 }
31647 for(ii=nOff=0, m=1; ii<32; ii++, m <<= 1){
31648 if( m & newOpt ) nOff++;
31649 }
31650 if( nOff<12 ){
31651 sqlite3_fputs("+All", p->out);
31652 for(ii=0; ii<ArraySize(aLabel); ii++){
31653 if( !aLabel[ii].bDsply ) continue;
31654 if( (newOpt & aLabel[ii].mask)!=0 ){
31655 sqlite3_fprintf(p->out, " -%s", aLabel[ii].zLabel);
31656 }
31657 }
31658 }else{
31659 sqlite3_fputs("-All", p->out);
31660 for(ii=0; ii<ArraySize(aLabel); ii++){
31661 if( !aLabel[ii].bDsply ) continue;
31662 if( (newOpt & aLabel[ii].mask)==0 ){
31663 sqlite3_fprintf(p->out, " +%s", aLabel[ii].zLabel);
 
 
31664 }
31665 }
31666 }
31667 sqlite3_fputs("\n", p->out);
31668 rc2 = isOk = 3;
31669 break;
31670 }
31671
31672 /* sqlite3_test_control(int, db, int) */
@@ -31928,11 +32123,10 @@
32123 SCAN_TRACKER_REFTYPE pst){
32124 char cin;
32125 char cWait = (char)qss; /* intentional narrowing loss */
32126 if( cWait==0 ){
32127 PlainScan:
 
32128 while( (cin = *zLine++)!=0 ){
32129 if( IsSpace(cin) )
32130 continue;
32131 switch (cin){
32132 case '-':
@@ -31980,11 +32174,10 @@
32174 switch( cWait ){
32175 case '*':
32176 if( *zLine != '/' )
32177 continue;
32178 ++zLine;
 
32179 CONTINUE_PROMPT_AWAITC(pst, 0);
32180 qss = QSS_SETV(qss, 0);
32181 goto PlainScan;
32182 case '`': case '\'': case '"':
32183 if(*zLine==cWait){
@@ -31992,11 +32185,10 @@
32185 ++zLine;
32186 continue;
32187 }
32188 deliberate_fall_through;
32189 case ']':
 
32190 CONTINUE_PROMPT_AWAITC(pst, 0);
32191 qss = QSS_SETV(qss, 0);
32192 goto PlainScan;
32193 default: assert(0);
32194 }
@@ -32180,11 +32372,14 @@
32372 if( doAutoDetectRestore(p, zSql) ) return 1;
32373 return 0;
32374 }
32375
32376 static void echo_group_input(ShellState *p, const char *zDo){
32377 if( ShellHasFlag(p, SHFLG_Echo) ){
32378 sqlite3_fprintf(p->out, "%s\n", zDo);
32379 fflush(p->out);
32380 }
32381 }
32382
32383 #ifdef SQLITE_SHELL_FIDDLE
32384 /*
32385 ** Alternate one_input_line() impl for wasm mode. This is not in the primary
@@ -32640,10 +32835,19 @@
32835 }
32836
32837 static void sayAbnormalExit(void){
32838 if( seenInterrupt ) eputz("Program interrupted.\n");
32839 }
32840
32841 /* Routine to output from vfstrace
32842 */
32843 static int vfstraceOut(const char *z, void *pArg){
32844 ShellState *p = (ShellState*)pArg;
32845 sqlite3_fputs(z, p->out);
32846 fflush(p->out);
32847 return 1;
32848 }
32849
32850 #ifndef SQLITE_SHELL_IS_UTF8
32851 # if (defined(_WIN32) || defined(WIN32)) \
32852 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
32853 # define SQLITE_SHELL_IS_UTF8 (0)
@@ -32877,12 +33081,10 @@
33081 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
33082 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
33083 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
33084 }
33085 }else if( cli_strcmp(z,"-vfstrace")==0 ){
 
 
33086 bEnableVfstrace = 1;
33087 #ifdef SQLITE_ENABLE_MULTIPLEX
33088 }else if( cli_strcmp(z,"-multiplex")==0 ){
33089 extern int sqlite3_multiplex_initialize(const char*,int);
33090 sqlite3_multiplex_initialize(0, 1);
@@ -32975,10 +33177,13 @@
33177 "%s: Error: no database filename specified\n", Argv0);
33178 return 1;
33179 #endif
33180 }
33181 data.out = stdout;
33182 if( bEnableVfstrace ){
33183 vfstrace_register("trace",0,vfstraceOut, &data, 1);
33184 }
33185 #ifndef SQLITE_SHELL_FIDDLE
33186 sqlite3_appendvfs_init(0,0,0);
33187 #endif
33188
33189 /* Go ahead and open the database file if it already exists. If the
33190
+807 -294
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
1616
** if you want a wrapper to interface SQLite with your choice of programming
1717
** language. The code for the "sqlite3" command-line shell is also in a
1818
** separate file. This file contains only code for the core SQLite library.
1919
**
2020
** The content in this amalgamation comes from Fossil check-in
21
-** 81202d2ab5963fdcf20555b6d0b31cc955ac with changes in files:
21
+** e2bae4143afd07de1ae55a6d2606a3b541a5 with changes in files:
2222
**
2323
**
2424
*/
2525
#ifndef SQLITE_AMALGAMATION
2626
#define SQLITE_CORE 1
@@ -465,11 +465,11 @@
465465
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
466466
** [sqlite_version()] and [sqlite_source_id()].
467467
*/
468468
#define SQLITE_VERSION "3.48.0"
469469
#define SQLITE_VERSION_NUMBER 3048000
470
-#define SQLITE_SOURCE_ID "2024-11-14 19:34:28 81202d2ab5963fdcf20555b6d0b31cc955ac27f1cd87656faea5c0611c9a2ee8"
470
+#define SQLITE_SOURCE_ID "2024-12-09 20:46:36 e2bae4143afd07de1ae55a6d2606a3b541a5b94568aa41f6a96e5d1245471653"
471471
472472
/*
473473
** CAPI3REF: Run-Time Library Version Numbers
474474
** KEYWORDS: sqlite3_version sqlite3_sourceid
475475
**
@@ -4521,15 +4521,26 @@
45214521
**
45224522
** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
45234523
** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
45244524
** to return an error (error code SQLITE_ERROR) if the statement uses
45254525
** any virtual tables.
4526
+**
4527
+** [[SQLITE_PREPARE_DONT_LOG]] <dt>SQLITE_PREPARE_DONT_LOG</dt>
4528
+** <dd>The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler
4529
+** errors from being sent to the error log defined by
4530
+** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test
4531
+** compiles to see if some SQL syntax is well-formed, without generating
4532
+** messages on the global error log when it is not. If the test compile
4533
+** fails, the sqlite3_prepare_v3() call returns the same error indications
4534
+** with or without this flag; it just omits the call to [sqlite3_log()] that
4535
+** logs the error.
45264536
** </dl>
45274537
*/
45284538
#define SQLITE_PREPARE_PERSISTENT 0x01
45294539
#define SQLITE_PREPARE_NORMALIZE 0x02
45304540
#define SQLITE_PREPARE_NO_VTAB 0x04
4541
+#define SQLITE_PREPARE_DONT_LOG 0x10
45314542
45324543
/*
45334544
** CAPI3REF: Compiling An SQL Statement
45344545
** KEYWORDS: {SQL statement compiler}
45354546
** METHOD: sqlite3
@@ -13467,17 +13478,32 @@
1346713478
** This is used to access token iToken of phrase hit iIdx within the
1346813479
** current row. If iIdx is less than zero or greater than or equal to the
1346913480
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
1347013481
** output variable (*ppToken) is set to point to a buffer containing the
1347113482
** matching document token, and (*pnToken) to the size of that buffer in
13472
-** bytes. This API is not available if the specified token matches a
13473
-** prefix query term. In that case both output variables are always set
13474
-** to 0.
13483
+** bytes.
1347513484
**
1347613485
** The output text is not a copy of the document text that was tokenized.
1347713486
** It is the output of the tokenizer module. For tokendata=1 tables, this
1347813487
** includes any embedded 0x00 and trailing data.
13488
+**
13489
+** This API may be slow in some cases if the token identified by parameters
13490
+** iIdx and iToken matched a prefix token in the query. In most cases, the
13491
+** first call to this API for each prefix token in the query is forced
13492
+** to scan the portion of the full-text index that matches the prefix
13493
+** token to collect the extra data required by this API. If the prefix
13494
+** token matches a large number of token instances in the document set,
13495
+** this may be a performance problem.
13496
+**
13497
+** If the user knows in advance that a query may use this API for a
13498
+** prefix token, FTS5 may be configured to collect all required data as part
13499
+** of the initial querying of the full-text index, avoiding the second scan
13500
+** entirely. This also causes prefix queries that do not use this API to
13501
+** run more slowly and use more memory. FTS5 may be configured in this way
13502
+** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
13503
+** option, or on a per-query basis using the
13504
+** [fts5_insttoken | fts5_insttoken()] user function.
1347913505
**
1348013506
** This API can be quite slow if used with an FTS5 table created with the
1348113507
** "detail=none" or "detail=column" option.
1348213508
**
1348313509
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
@@ -17049,11 +17075,11 @@
1704917075
1705017076
/*
1705117077
** Additional non-public SQLITE_PREPARE_* flags
1705217078
*/
1705317079
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
17054
-#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
17080
+#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
1705517081
1705617082
/*
1705717083
** Prototypes for the VDBE interface. See comments on the implementation
1705817084
** for a description of what each of these routines does.
1705917085
*/
@@ -32279,10 +32305,11 @@
3227932305
&& (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
3228032306
){
3228132307
pExpr = pExpr->pLeft;
3228232308
}
3228332309
if( pExpr==0 ) return;
32310
+ if( ExprHasProperty(pExpr, EP_FromDDL) ) return;
3228432311
db->errByteOffset = pExpr->w.iOfst;
3228532312
}
3228632313
3228732314
/*
3228832315
** Enlarge the memory allocation on a StrAccum object so that it is
@@ -33008,11 +33035,11 @@
3300833035
}
3300933036
if( pItem->fg.isCte ){
3301033037
sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
3301133038
}
3301233039
if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
33013
- sqlite3_str_appendf(&x, " ON");
33040
+ sqlite3_str_appendf(&x, " isOn");
3301433041
}
3301533042
if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
3301633043
if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
3301733044
if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
3301833045
if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
@@ -34092,10 +34119,14 @@
3409234119
**
3409334120
** This routines are given external linkage so that they will always be
3409434121
** accessible to the debugging, and to avoid warnings about unused
3409534122
** functions. But these routines only exist in debugging builds, so they
3409634123
** do not contaminate the interface.
34124
+**
34125
+** See Also:
34126
+**
34127
+** sqlite3ShowWhereTerm() in where.c
3409734128
*/
3409834129
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
3409934130
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
3410034131
SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
3410134132
SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
@@ -35668,12 +35699,12 @@
3566835699
int esign = 1; /* sign of exponent */
3566935700
int e = 0; /* exponent */
3567035701
int eValid = 1; /* True exponent is either not used or is well-formed */
3567135702
int nDigit = 0; /* Number of digits processed */
3567235703
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
35704
+ u64 s2; /* round-tripped significand */
3567335705
double rr[2];
35674
- u64 s2;
3567535706
3567635707
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
3567735708
*pResult = 0.0; /* Default return value, in case of an error */
3567835709
if( length==0 ) return 0;
3567935710
@@ -35772,25 +35803,36 @@
3577235803
3577335804
/* adjust exponent by d, and update sign */
3577435805
e = (e*esign) + d;
3577535806
3577635807
/* Try to adjust the exponent to make it smaller */
35777
- while( e>0 && s<(LARGEST_UINT64/10) ){
35808
+ while( e>0 && s<((LARGEST_UINT64-0x7ff)/10) ){
3577835809
s *= 10;
3577935810
e--;
3578035811
}
3578135812
while( e<0 && (s%10)==0 ){
3578235813
s /= 10;
3578335814
e++;
3578435815
}
3578535816
3578635817
rr[0] = (double)s;
35787
- s2 = (u64)rr[0];
35788
-#if defined(_MSC_VER) && _MSC_VER<1700
35789
- if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
35818
+ assert( sizeof(s2)==sizeof(rr[0]) );
35819
+#ifdef SQLITE_DEBUG
35820
+ rr[1] = 18446744073709549568.0;
35821
+ memcpy(&s2, &rr[1], sizeof(s2));
35822
+ assert( s2==0x43efffffffffffffLL );
3579035823
#endif
35791
- rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
35824
+ /* Largest double that can be safely converted to u64
35825
+ ** vvvvvvvvvvvvvvvvvvvvvv */
35826
+ if( rr[0]<=18446744073709549568.0 ){
35827
+ s2 = (u64)rr[0];
35828
+ rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
35829
+ }else{
35830
+ rr[1] = 0.0;
35831
+ }
35832
+ assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */
35833
+
3579235834
if( e>0 ){
3579335835
while( e>=100 ){
3579435836
e -= 100;
3579535837
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
3579635838
}
@@ -51771,11 +51813,11 @@
5177151813
*/
5177251814
char *zTmpname = 0; /* For temporary filename, if necessary. */
5177351815
5177451816
int rc = SQLITE_OK; /* Function Return Code */
5177551817
#if !defined(NDEBUG) || SQLITE_OS_WINCE
51776
- int eType = flags&0xFFFFFF00; /* Type of file to open */
51818
+ int eType = flags&0x0FFF00; /* Type of file to open */
5177751819
#endif
5177851820
5177951821
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
5178051822
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
5178151823
int isCreate = (flags & SQLITE_OPEN_CREATE);
@@ -112021,11 +112063,11 @@
112021112063
**
112022112064
** (4) If pSrc is the right operand of a LEFT JOIN, then...
112023112065
** (4a) pExpr must come from an ON clause..
112024112066
** (4b) and specifically the ON clause associated with the LEFT JOIN.
112025112067
**
112026
-** (5) If pSrc is not the right operand of a LEFT JOIN or the left
112068
+** (5) If pSrc is the right operand of a LEFT JOIN or the left
112027112069
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
112028112070
** clause, not an ON clause.
112029112071
**
112030112072
** (6) Either:
112031112073
**
@@ -115555,35 +115597,41 @@
115555115597
**
115556115598
** Additionally, if pExpr is a simple SQL value and the value is the
115557115599
** same as that currently bound to variable pVar, non-zero is returned.
115558115600
** Otherwise, if the values are not the same or if pExpr is not a simple
115559115601
** SQL value, zero is returned.
115602
+**
115603
+** If the SQLITE_EnableQPSG flag is set on the database connection, then
115604
+** this routine always returns false.
115560115605
*/
115561
-static int exprCompareVariable(
115606
+static SQLITE_NOINLINE int exprCompareVariable(
115562115607
const Parse *pParse,
115563115608
const Expr *pVar,
115564115609
const Expr *pExpr
115565115610
){
115566
- int res = 0;
115611
+ int res = 2;
115567115612
int iVar;
115568115613
sqlite3_value *pL, *pR = 0;
115569115614
115615
+ if( pExpr->op==TK_VARIABLE && pVar->iColumn==pExpr->iColumn ){
115616
+ return 0;
115617
+ }
115618
+ if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) return 2;
115570115619
sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
115571115620
if( pR ){
115572115621
iVar = pVar->iColumn;
115573115622
sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
115574115623
pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
115575115624
if( pL ){
115576115625
if( sqlite3_value_type(pL)==SQLITE_TEXT ){
115577115626
sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
115578115627
}
115579
- res = 0==sqlite3MemCompare(pL, pR, 0);
115628
+ res = sqlite3MemCompare(pL, pR, 0) ? 2 : 0;
115580115629
}
115581115630
sqlite3ValueFree(pR);
115582115631
sqlite3ValueFree(pL);
115583115632
}
115584
-
115585115633
return res;
115586115634
}
115587115635
115588115636
/*
115589115637
** Do a deep comparison of two expression trees. Return 0 if the two
@@ -115605,16 +115653,14 @@
115605115653
** can be sure the expressions are the same. In the places where
115606115654
** this routine is used, it does not hurt to get an extra 2 - that
115607115655
** just might result in some slightly slower code. But returning
115608115656
** an incorrect 0 or 1 could lead to a malfunction.
115609115657
**
115610
-** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
115611
-** pParse->pReprepare can be matched against literals in pB. The
115612
-** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
115613
-** If pParse is NULL (the normal case) then any TK_VARIABLE term in
115614
-** Argument pParse should normally be NULL. If it is not NULL and pA or
115615
-** pB causes a return value of 2.
115658
+** If pParse is not NULL and SQLITE_EnableQPSG is off then TK_VARIABLE
115659
+** terms in pA with bindings in pParse->pReprepare can be matched against
115660
+** literals in pB. The pParse->pVdbe->expmask bitmask is updated for
115661
+** each variable referenced.
115616115662
*/
115617115663
SQLITE_PRIVATE int sqlite3ExprCompare(
115618115664
const Parse *pParse,
115619115665
const Expr *pA,
115620115666
const Expr *pB,
@@ -115622,12 +115668,12 @@
115622115668
){
115623115669
u32 combinedFlags;
115624115670
if( pA==0 || pB==0 ){
115625115671
return pB==pA ? 0 : 2;
115626115672
}
115627
- if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
115628
- return 0;
115673
+ if( pParse && pA->op==TK_VARIABLE ){
115674
+ return exprCompareVariable(pParse, pA, pB);
115629115675
}
115630115676
combinedFlags = pA->flags | pB->flags;
115631115677
if( combinedFlags & EP_IntValue ){
115632115678
if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
115633115679
return 0;
@@ -115817,23 +115863,75 @@
115817115863
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
115818115864
}
115819115865
}
115820115866
return 0;
115821115867
}
115868
+
115869
+/*
115870
+** Return true if the boolean value of the expression is always either
115871
+** FALSE or NULL.
115872
+*/
115873
+static int sqlite3ExprIsNotTrue(Expr *pExpr){
115874
+ int v;
115875
+ if( pExpr->op==TK_NULL ) return 1;
115876
+ if( pExpr->op==TK_TRUEFALSE && sqlite3ExprTruthValue(pExpr)==0 ) return 1;
115877
+ v = 1;
115878
+ if( sqlite3ExprIsInteger(pExpr, &v, 0) && v==0 ) return 1;
115879
+ return 0;
115880
+}
115881
+
115882
+/*
115883
+** Return true if the expression is one of the following:
115884
+**
115885
+** CASE WHEN x THEN y END
115886
+** CASE WHEN x THEN y ELSE NULL END
115887
+** CASE WHEN x THEN y ELSE false END
115888
+** iif(x,y)
115889
+** iif(x,y,NULL)
115890
+** iif(x,y,false)
115891
+*/
115892
+static int sqlite3ExprIsIIF(sqlite3 *db, const Expr *pExpr){
115893
+ ExprList *pList;
115894
+ if( pExpr->op==TK_FUNCTION ){
115895
+ const char *z = pExpr->u.zToken;
115896
+ FuncDef *pDef;
115897
+ if( (z[0]!='i' && z[0]!='I') ) return 0;
115898
+ if( pExpr->x.pList==0 ) return 0;
115899
+ pDef = sqlite3FindFunction(db, z, pExpr->x.pList->nExpr, ENC(db), 0);
115900
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
115901
+ if( pDef==0 ) return 0;
115902
+#else
115903
+ if( NEVER(pDef==0) ) return 0;
115904
+#endif
115905
+ if( (pDef->funcFlags & SQLITE_FUNC_INLINE)==0 ) return 0;
115906
+ if( SQLITE_PTR_TO_INT(pDef->pUserData)!=INLINEFUNC_iif ) return 0;
115907
+ }else if( pExpr->op==TK_CASE ){
115908
+ if( pExpr->pLeft!=0 ) return 0;
115909
+ }else{
115910
+ return 0;
115911
+ }
115912
+ pList = pExpr->x.pList;
115913
+ assert( pList!=0 );
115914
+ if( pList->nExpr==2 ) return 1;
115915
+ if( pList->nExpr==3 && sqlite3ExprIsNotTrue(pList->a[2].pExpr) ) return 1;
115916
+ return 0;
115917
+}
115822115918
115823115919
/*
115824115920
** Return true if we can prove the pE2 will always be true if pE1 is
115825115921
** true. Return false if we cannot complete the proof or if pE2 might
115826115922
** be false. Examples:
115827115923
**
115828
-** pE1: x==5 pE2: x==5 Result: true
115829
-** pE1: x>0 pE2: x==5 Result: false
115830
-** pE1: x=21 pE2: x=21 OR y=43 Result: true
115831
-** pE1: x!=123 pE2: x IS NOT NULL Result: true
115832
-** pE1: x!=?1 pE2: x IS NOT NULL Result: true
115833
-** pE1: x IS NULL pE2: x IS NOT NULL Result: false
115834
-** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
115924
+** pE1: x==5 pE2: x==5 Result: true
115925
+** pE1: x>0 pE2: x==5 Result: false
115926
+** pE1: x=21 pE2: x=21 OR y=43 Result: true
115927
+** pE1: x!=123 pE2: x IS NOT NULL Result: true
115928
+** pE1: x!=?1 pE2: x IS NOT NULL Result: true
115929
+** pE1: x IS NULL pE2: x IS NOT NULL Result: false
115930
+** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
115931
+** pE1: iif(x,y) pE2: x Result: true
115932
+** PE1: iif(x,y,0) pE2: x Result: true
115835115933
**
115836115934
** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
115837115935
** Expr.iTable<0 then assume a table number given by iTab.
115838115936
**
115839115937
** If pParse is not NULL, then the values of bound variables in pE1 are
@@ -115863,10 +115961,13 @@
115863115961
if( pE2->op==TK_NOTNULL
115864115962
&& exprImpliesNotNull(pParse, pE1, pE2->pLeft, iTab, 0)
115865115963
){
115866115964
return 1;
115867115965
}
115966
+ if( sqlite3ExprIsIIF(pParse->db, pE1) ){
115967
+ return sqlite3ExprImpliesExpr(pParse,pE1->x.pList->a[0].pExpr,pE2,iTab);
115968
+ }
115868115969
return 0;
115869115970
}
115870115971
115871115972
/* This is a helper function to impliesNotNullRow(). In this routine,
115872115973
** set pWalker->eCode to one only if *both* of the input expressions
@@ -132082,11 +132183,14 @@
132082132183
MFUNCTION(degrees, 1, radToDeg, math1Func ),
132083132184
MFUNCTION(pi, 0, 0, piFunc ),
132084132185
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
132085132186
FUNCTION(sign, 1, 0, 0, signFunc ),
132086132187
INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
132188
+ INLINE_FUNC(iif, 2, INLINEFUNC_iif, 0 ),
132087132189
INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
132190
+ INLINE_FUNC(if, 2, INLINEFUNC_iif, 0 ),
132191
+ INLINE_FUNC(if, 3, INLINEFUNC_iif, 0 ),
132088132192
};
132089132193
#ifndef SQLITE_OMIT_ALTERTABLE
132090132194
sqlite3AlterFunctions();
132091132195
#endif
132092132196
sqlite3WindowFunctions();
@@ -140730,11 +140834,12 @@
140730140834
pTab = sqliteHashData(k);
140731140835
if( pTab->nCol==0 ){
140732140836
char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
140733140837
if( zSql ){
140734140838
sqlite3_stmt *pDummy = 0;
140735
- (void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
140839
+ (void)sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_DONT_LOG,
140840
+ &pDummy, 0);
140736140841
(void)sqlite3_finalize(pDummy);
140737140842
sqlite3DbFree(db, zSql);
140738140843
}
140739140844
if( db->mallocFailed ){
140740140845
sqlite3ErrorMsg(db->pParse, "out of memory");
@@ -147529,36 +147634,36 @@
147529147634
return pExpr;
147530147635
}
147531147636
if( pSubst->isOuterJoin ){
147532147637
ExprSetProperty(pNew, EP_CanBeNull);
147533147638
}
147639
+ if( pNew->op==TK_TRUEFALSE ){
147640
+ pNew->u.iValue = sqlite3ExprTruthValue(pNew);
147641
+ pNew->op = TK_INTEGER;
147642
+ ExprSetProperty(pNew, EP_IntValue);
147643
+ }
147644
+
147645
+ /* Ensure that the expression now has an implicit collation sequence,
147646
+ ** just as it did when it was a column of a view or sub-query. */
147647
+ {
147648
+ CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pNew);
147649
+ CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
147650
+ pSubst->pCList->a[iColumn].pExpr
147651
+ );
147652
+ if( pNat!=pColl || (pNew->op!=TK_COLUMN && pNew->op!=TK_COLLATE) ){
147653
+ pNew = sqlite3ExprAddCollateString(pSubst->pParse, pNew,
147654
+ (pColl ? pColl->zName : "BINARY")
147655
+ );
147656
+ }
147657
+ }
147658
+ ExprClearProperty(pNew, EP_Collate);
147534147659
if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
147535147660
sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
147536147661
pExpr->flags & (EP_OuterON|EP_InnerON));
147537147662
}
147538147663
sqlite3ExprDelete(db, pExpr);
147539147664
pExpr = pNew;
147540
- if( pExpr->op==TK_TRUEFALSE ){
147541
- pExpr->u.iValue = sqlite3ExprTruthValue(pExpr);
147542
- pExpr->op = TK_INTEGER;
147543
- ExprSetProperty(pExpr, EP_IntValue);
147544
- }
147545
-
147546
- /* Ensure that the expression now has an implicit collation sequence,
147547
- ** just as it did when it was a column of a view or sub-query. */
147548
- {
147549
- CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
147550
- CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
147551
- pSubst->pCList->a[iColumn].pExpr
147552
- );
147553
- if( pNat!=pColl || (pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE) ){
147554
- pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
147555
- (pColl ? pColl->zName : "BINARY")
147556
- );
147557
- }
147558
- }
147559
- ExprClearProperty(pExpr, EP_Collate);
147560147665
}
147561147666
}
147562147667
}else{
147563147668
if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
147564147669
pExpr->iTable = pSubst->iNewTable;
@@ -148291,20 +148396,20 @@
148291148396
}
148292148397
148293148398
/* Transfer the FROM clause terms from the subquery into the
148294148399
** outer query.
148295148400
*/
148401
+ iNewParent = pSubSrc->a[0].iCursor;
148296148402
for(i=0; i<nSubSrc; i++){
148297148403
SrcItem *pItem = &pSrc->a[i+iFrom];
148298148404
assert( pItem->fg.isTabFunc==0 );
148299148405
assert( pItem->fg.isSubquery
148300148406
|| pItem->fg.fixedSchema
148301148407
|| pItem->u4.zDatabase==0 );
148302148408
if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
148303148409
*pItem = pSubSrc->a[i];
148304148410
pItem->fg.jointype |= ltorj;
148305
- iNewParent = pSubSrc->a[i].iCursor;
148306148411
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
148307148412
}
148308148413
pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
148309148414
pSrc->a[iFrom].fg.jointype |= jointype | ltorj;
148310148415
@@ -148340,10 +148445,11 @@
148340148445
pSub->pOrderBy = 0;
148341148446
}
148342148447
pWhere = pSub->pWhere;
148343148448
pSub->pWhere = 0;
148344148449
if( isOuterJoin>0 ){
148450
+ assert( pSubSrc->nSrc==1 );
148345148451
sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
148346148452
}
148347148453
if( pWhere ){
148348148454
if( pParent->pWhere ){
148349148455
pParent->pWhere = sqlite3PExpr(pParse, TK_AND, pWhere, pParent->pWhere);
@@ -151439,11 +151545,11 @@
151439151545
sqlite3TreeViewSelect(0, p, 0);
151440151546
}
151441151547
#endif
151442151548
assert( pSubq->pSelect && (pSub->selFlags & SF_PushDown)!=0 );
151443151549
}else{
151444
- TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
151550
+ TREETRACE(0x4000,pParse,p,("WHERE-clause push-down not possible\n"));
151445151551
}
151446151552
151447151553
/* Convert unused result columns of the subquery into simple NULL
151448151554
** expressions, to avoid unneeded searching and computation.
151449151555
** tag-select-0440
@@ -158930,10 +159036,11 @@
158930159036
if( pOrigLhs ){
158931159037
sqlite3ExprListDelete(db, pOrigLhs);
158932159038
pNew->pLeft->x.pList = pLhs;
158933159039
}
158934159040
pSelect->pEList = pRhs;
159041
+ pSelect->selId = ++pParse->nSelect; /* Req'd for SubrtnSig validity */
158935159042
if( pLhs && pLhs->nExpr==1 ){
158936159043
/* Take care here not to generate a TK_VECTOR containing only a
158937159044
** single value. Since the parser never creates such a vector, some
158938159045
** of the subroutines do not handle this case. */
158939159046
Expr *p = pLhs->a[0].pExpr;
@@ -164002,11 +164109,11 @@
164002164109
|| pTerm->pExpr->w.iJoin != pSrc->iCursor
164003164110
){
164004164111
return 0;
164005164112
}
164006164113
if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0
164007
- && ExprHasProperty(pTerm->pExpr, EP_InnerON)
164114
+ && NEVER(ExprHasProperty(pTerm->pExpr, EP_InnerON))
164008164115
){
164009164116
return 0;
164010164117
}
164011164118
return 1;
164012164119
}
@@ -165495,11 +165602,11 @@
165495165602
return rc;
165496165603
}
165497165604
#endif /* SQLITE_ENABLE_STAT4 */
165498165605
165499165606
165500
-#ifdef WHERETRACE_ENABLED
165607
+#if defined(WHERETRACE_ENABLED) || defined(SQLITE_DEBUG)
165501165608
/*
165502165609
** Print the content of a WhereTerm object
165503165610
*/
165504165611
SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
165505165612
if( pTerm==0 ){
@@ -165538,10 +165645,13 @@
165538165645
sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
165539165646
}
165540165647
sqlite3DebugPrintf("\n");
165541165648
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
165542165649
}
165650
+}
165651
+SQLITE_PRIVATE void sqlite3ShowWhereTerm(WhereTerm *pTerm){
165652
+ sqlite3WhereTermPrint(pTerm, 0);
165543165653
}
165544165654
#endif
165545165655
165546165656
#ifdef WHERETRACE_ENABLED
165547165657
/*
@@ -166724,11 +166834,10 @@
166724166834
pParse = pWC->pWInfo->pParse;
166725166835
while( pWhere->op==TK_AND ){
166726166836
if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
166727166837
pWhere = pWhere->pRight;
166728166838
}
166729
- if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
166730166839
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
166731166840
Expr *pExpr;
166732166841
pExpr = pTerm->pExpr;
166733166842
if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
166734166843
&& ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
@@ -169385,11 +169494,11 @@
169385169494
break;
169386169495
}
169387169496
}
169388169497
if( hasRightJoin
169389169498
&& ExprHasProperty(pTerm->pExpr, EP_InnerON)
169390
- && pTerm->pExpr->w.iJoin==pItem->iCursor
169499
+ && NEVER(pTerm->pExpr->w.iJoin==pItem->iCursor)
169391169500
){
169392169501
break; /* restriction (5) */
169393169502
}
169394169503
}
169395169504
if( pTerm<pEnd ) continue;
@@ -173846,10 +173955,17 @@
173846173955
** Then the "b" IdList records the list "a,b,c".
173847173956
*/
173848173957
struct TrigEvent { int a; IdList * b; };
173849173958
173850173959
struct FrameBound { int eType; Expr *pExpr; };
173960
+
173961
+/*
173962
+** Generate a syntax error
173963
+*/
173964
+static void parserSyntaxError(Parse *pParse, Token *p){
173965
+ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", p);
173966
+}
173851173967
173852173968
/*
173853173969
** Disable lookaside memory allocation for objects that might be
173854173970
** shared across database connections.
173855173971
*/
@@ -178214,11 +178330,11 @@
178214178330
** that look like this: #1 #2 ... These terms refer to registers
178215178331
** in the virtual machine. #N is the N-th register. */
178216178332
Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/
178217178333
assert( t.n>=2 );
178218178334
if( pParse->nested==0 ){
178219
- sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
178335
+ parserSyntaxError(pParse, &t);
178220178336
yymsp[0].minor.yy454 = 0;
178221178337
}else{
178222178338
yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
178223178339
if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable);
178224178340
}
@@ -179062,11 +179178,11 @@
179062179178
#define TOKEN yyminor
179063179179
/************ Begin %syntax_error code ****************************************/
179064179180
179065179181
UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */
179066179182
if( TOKEN.z[0] ){
179067
- sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
179183
+ parserSyntaxError(pParse, &TOKEN);
179068179184
}else{
179069179185
sqlite3ErrorMsg(pParse, "incomplete input");
179070179186
}
179071179187
/************ End %syntax_error code ******************************************/
179072179188
sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */
@@ -180553,11 +180669,13 @@
180553180669
}
180554180670
if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){
180555180671
if( pParse->zErrMsg==0 ){
180556180672
pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
180557180673
}
180558
- sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
180674
+ if( (pParse->prepFlags & SQLITE_PREPARE_DONT_LOG)==0 ){
180675
+ sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
180676
+ }
180559180677
nErr++;
180560180678
}
180561180679
pParse->zTail = zSql;
180562180680
#ifndef SQLITE_OMIT_VIRTUALTABLE
180563180681
sqlite3_free(pParse->apVtabLock);
@@ -185391,10 +185509,11 @@
185391185509
#ifndef SQLITE_OMIT_WINDOWFUNC
185392185510
sqlite3ShowWindow(0);
185393185511
sqlite3ShowWinFunc(0);
185394185512
#endif
185395185513
sqlite3ShowSelect(0);
185514
+ sqlite3ShowWhereTerm(0);
185396185515
}
185397185516
#endif
185398185517
break;
185399185518
}
185400185519
@@ -194537,14 +194656,15 @@
194537194656
rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
194538194657
if( rc==SQLITE_OK ){
194539194658
Fts3PhraseToken *pToken;
194540194659
194541194660
p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
194542
- if( !p ) goto no_mem;
194543
-
194544194661
zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
194545
- if( !zTemp ) goto no_mem;
194662
+ if( !zTemp || !p ){
194663
+ rc = SQLITE_NOMEM;
194664
+ goto getnextstring_out;
194665
+ }
194546194666
194547194667
assert( nToken==ii );
194548194668
pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
194549194669
memset(pToken, 0, sizeof(Fts3PhraseToken));
194550194670
@@ -194555,53 +194675,51 @@
194555194675
pToken->isPrefix = (iEnd<nInput && zInput[iEnd]=='*');
194556194676
pToken->bFirst = (iBegin>0 && zInput[iBegin-1]=='^');
194557194677
nToken = ii+1;
194558194678
}
194559194679
}
194560
-
194561
- pModule->xClose(pCursor);
194562
- pCursor = 0;
194563194680
}
194564194681
194565194682
if( rc==SQLITE_DONE ){
194566194683
int jj;
194567194684
char *zBuf = 0;
194568194685
194569194686
p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
194570
- if( !p ) goto no_mem;
194687
+ if( !p ){
194688
+ rc = SQLITE_NOMEM;
194689
+ goto getnextstring_out;
194690
+ }
194571194691
memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
194572194692
p->eType = FTSQUERY_PHRASE;
194573194693
p->pPhrase = (Fts3Phrase *)&p[1];
194574194694
p->pPhrase->iColumn = pParse->iDefaultCol;
194575194695
p->pPhrase->nToken = nToken;
194576194696
194577194697
zBuf = (char *)&p->pPhrase->aToken[nToken];
194698
+ assert( nTemp==0 || zTemp );
194578194699
if( zTemp ){
194579194700
memcpy(zBuf, zTemp, nTemp);
194580
- sqlite3_free(zTemp);
194581
- }else{
194582
- assert( nTemp==0 );
194583194701
}
194584194702
194585194703
for(jj=0; jj<p->pPhrase->nToken; jj++){
194586194704
p->pPhrase->aToken[jj].z = zBuf;
194587194705
zBuf += p->pPhrase->aToken[jj].n;
194588194706
}
194589194707
rc = SQLITE_OK;
194590194708
}
194591194709
194592
- *ppExpr = p;
194593
- return rc;
194594
-no_mem:
194595
-
194710
+ getnextstring_out:
194596194711
if( pCursor ){
194597194712
pModule->xClose(pCursor);
194598194713
}
194599194714
sqlite3_free(zTemp);
194600
- sqlite3_free(p);
194601
- *ppExpr = 0;
194602
- return SQLITE_NOMEM;
194715
+ if( rc!=SQLITE_OK ){
194716
+ sqlite3_free(p);
194717
+ p = 0;
194718
+ }
194719
+ *ppExpr = p;
194720
+ return rc;
194603194721
}
194604194722
194605194723
/*
194606194724
** The output variable *ppExpr is populated with an allocated Fts3Expr
194607194725
** structure, or set to 0 if the end of the input buffer is reached.
@@ -226191,10 +226309,12 @@
226191226309
if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
226192226310
unsigned char *aPage = sqlite3PagerGetData(pDbPage);
226193226311
memcpy(aPage, pData, szPage);
226194226312
pTab->pgnoTrunc = 0;
226195226313
}
226314
+ }else{
226315
+ pTab->pgnoTrunc = 0;
226196226316
}
226197226317
sqlite3PagerUnref(pDbPage);
226198226318
return rc;
226199226319
226200226320
update_fail:
@@ -233154,17 +233274,32 @@
233154233274
** This is used to access token iToken of phrase hit iIdx within the
233155233275
** current row. If iIdx is less than zero or greater than or equal to the
233156233276
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
233157233277
** output variable (*ppToken) is set to point to a buffer containing the
233158233278
** matching document token, and (*pnToken) to the size of that buffer in
233159
-** bytes. This API is not available if the specified token matches a
233160
-** prefix query term. In that case both output variables are always set
233161
-** to 0.
233279
+** bytes.
233162233280
**
233163233281
** The output text is not a copy of the document text that was tokenized.
233164233282
** It is the output of the tokenizer module. For tokendata=1 tables, this
233165233283
** includes any embedded 0x00 and trailing data.
233284
+**
233285
+** This API may be slow in some cases if the token identified by parameters
233286
+** iIdx and iToken matched a prefix token in the query. In most cases, the
233287
+** first call to this API for each prefix token in the query is forced
233288
+** to scan the portion of the full-text index that matches the prefix
233289
+** token to collect the extra data required by this API. If the prefix
233290
+** token matches a large number of token instances in the document set,
233291
+** this may be a performance problem.
233292
+**
233293
+** If the user knows in advance that a query may use this API for a
233294
+** prefix token, FTS5 may be configured to collect all required data as part
233295
+** of the initial querying of the full-text index, avoiding the second scan
233296
+** entirely. This also causes prefix queries that do not use this API to
233297
+** run more slowly and use more memory. FTS5 may be configured in this way
233298
+** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
233299
+** option, or on a per-query basis using the
233300
+** [fts5_insttoken | fts5_insttoken()] user function.
233166233301
**
233167233302
** This API can be quite slow if used with an FTS5 table created with the
233168233303
** "detail=none" or "detail=column" option.
233169233304
**
233170233305
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
@@ -233843,11 +233978,12 @@
233843233978
int nUsermerge; /* 'usermerge' setting */
233844233979
int nHashSize; /* Bytes of memory for in-memory hash */
233845233980
char *zRank; /* Name of rank function */
233846233981
char *zRankArgs; /* Arguments to rank function */
233847233982
int bSecureDelete; /* 'secure-delete' */
233848
- int nDeleteMerge; /* 'deletemerge' */
233983
+ int nDeleteMerge; /* 'deletemerge' */
233984
+ int bPrefixInsttoken; /* 'prefix-insttoken' */
233849233985
233850233986
/* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
233851233987
char **pzErrmsg;
233852233988
233853233989
#ifdef SQLITE_DEBUG
@@ -234100,11 +234236,18 @@
234100234236
static int sqlite3Fts5StructureTest(Fts5Index*, void*);
234101234237
234102234238
/*
234103234239
** Used by xInstToken():
234104234240
*/
234105
-static int sqlite3Fts5IterToken(Fts5IndexIter*, i64, int, int, const char**, int*);
234241
+static int sqlite3Fts5IterToken(
234242
+ Fts5IndexIter *pIndexIter,
234243
+ const char *pToken, int nToken,
234244
+ i64 iRowid,
234245
+ int iCol,
234246
+ int iOff,
234247
+ const char **ppOut, int *pnOut
234248
+);
234106234249
234107234250
/*
234108234251
** Insert or remove data to or from the index. Each time a document is
234109234252
** added to or removed from the index, this function is called one or more
234110234253
** times.
@@ -238314,10 +238457,23 @@
238314238457
if( bVal<0 ){
238315238458
*pbBadkey = 1;
238316238459
}else{
238317238460
pConfig->bSecureDelete = (bVal ? 1 : 0);
238318238461
}
238462
+ }
238463
+
238464
+ else if( 0==sqlite3_stricmp(zKey, "insttoken") ){
238465
+ int bVal = -1;
238466
+ if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
238467
+ bVal = sqlite3_value_int(pVal);
238468
+ }
238469
+ if( bVal<0 ){
238470
+ *pbBadkey = 1;
238471
+ }else{
238472
+ pConfig->bPrefixInsttoken = (bVal ? 1 : 0);
238473
+ }
238474
+
238319238475
}else{
238320238476
*pbBadkey = 1;
238321238477
}
238322238478
return rc;
238323238479
}
@@ -241449,11 +241605,11 @@
241449241605
&& memcmp(pT->pTerm, pToken, pT->nQueryTerm)==0
241450241606
){
241451241607
int rc = sqlite3Fts5PoslistWriterAppend(
241452241608
&pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
241453241609
);
241454
- if( rc==SQLITE_OK && pExpr->pConfig->bTokendata && !pT->bPrefix ){
241610
+ if( rc==SQLITE_OK && (pExpr->pConfig->bTokendata || pT->bPrefix) ){
241455241611
int iCol = p->iOff>>32;
241456241612
int iTokOff = p->iOff & 0x7FFFFFFF;
241457241613
rc = sqlite3Fts5IndexIterWriteTokendata(
241458241614
pT->pIter, pToken, nToken, iRowid, iCol, iTokOff
241459241615
);
@@ -241642,19 +241798,18 @@
241642241798
pPhrase = pExpr->apExprPhrase[iPhrase];
241643241799
if( iToken<0 || iToken>=pPhrase->nTerm ){
241644241800
return SQLITE_RANGE;
241645241801
}
241646241802
pTerm = &pPhrase->aTerm[iToken];
241647
- if( pTerm->bPrefix==0 ){
241648
- if( pExpr->pConfig->bTokendata ){
241649
- rc = sqlite3Fts5IterToken(
241650
- pTerm->pIter, iRowid, iCol, iOff+iToken, ppOut, pnOut
241651
- );
241652
- }else{
241653
- *ppOut = pTerm->pTerm;
241654
- *pnOut = pTerm->nFullTerm;
241655
- }
241803
+ if( pExpr->pConfig->bTokendata || pTerm->bPrefix ){
241804
+ rc = sqlite3Fts5IterToken(
241805
+ pTerm->pIter, pTerm->pTerm, pTerm->nQueryTerm,
241806
+ iRowid, iCol, iOff+iToken, ppOut, pnOut
241807
+ );
241808
+ }else{
241809
+ *ppOut = pTerm->pTerm;
241810
+ *pnOut = pTerm->nFullTerm;
241656241811
}
241657241812
return rc;
241658241813
}
241659241814
241660241815
/*
@@ -248465,10 +248620,387 @@
248465248620
fts5BufferFree(&tmp);
248466248621
memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
248467248622
*p1 = out;
248468248623
}
248469248624
248625
+
248626
+/*
248627
+** Iterate through a range of entries in the FTS index, invoking the xVisit
248628
+** callback for each of them.
248629
+**
248630
+** Parameter pToken points to an nToken buffer containing an FTS index term
248631
+** (i.e. a document term with the preceding 1 byte index identifier -
248632
+** FTS5_MAIN_PREFIX or similar). If bPrefix is true, then the call visits
248633
+** all entries for terms that have pToken/nToken as a prefix. If bPrefix
248634
+** is false, then only entries with pToken/nToken as the entire key are
248635
+** visited.
248636
+**
248637
+** If the current table is a tokendata=1 table, then if bPrefix is true then
248638
+** each index term is treated separately. However, if bPrefix is false, then
248639
+** all index terms corresponding to pToken/nToken are collapsed into a single
248640
+** term before the callback is invoked.
248641
+**
248642
+** The callback invoked for each entry visited is specified by paramter xVisit.
248643
+** Each time it is invoked, it is passed a pointer to the Fts5Index object,
248644
+** a copy of the 7th paramter to this function (pCtx) and a pointer to the
248645
+** iterator that indicates the current entry. If the current entry is the
248646
+** first with a new term (i.e. different from that of the previous entry,
248647
+** including the very first term), then the final two parameters are passed
248648
+** a pointer to the term and its size in bytes, respectively. If the current
248649
+** entry is not the first associated with its term, these two parameters
248650
+** are passed 0.
248651
+**
248652
+** If parameter pColset is not NULL, then it is used to filter entries before
248653
+** the callback is invoked.
248654
+*/
248655
+static int fts5VisitEntries(
248656
+ Fts5Index *p, /* Fts5 index object */
248657
+ Fts5Colset *pColset, /* Columns filter to apply, or NULL */
248658
+ u8 *pToken, /* Buffer containing token */
248659
+ int nToken, /* Size of buffer pToken in bytes */
248660
+ int bPrefix, /* True for a prefix scan */
248661
+ void (*xVisit)(Fts5Index*, void *pCtx, Fts5Iter *pIter, const u8*, int),
248662
+ void *pCtx /* Passed as second argument to xVisit() */
248663
+){
248664
+ const int flags = (bPrefix ? FTS5INDEX_QUERY_SCAN : 0)
248665
+ | FTS5INDEX_QUERY_SKIPEMPTY
248666
+ | FTS5INDEX_QUERY_NOOUTPUT;
248667
+ Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
248668
+ int bNewTerm = 1;
248669
+ Fts5Structure *pStruct = fts5StructureRead(p);
248670
+
248671
+ fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
248672
+ fts5IterSetOutputCb(&p->rc, p1);
248673
+ for( /* no-op */ ;
248674
+ fts5MultiIterEof(p, p1)==0;
248675
+ fts5MultiIterNext2(p, p1, &bNewTerm)
248676
+ ){
248677
+ Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
248678
+ int nNew = 0;
248679
+ const u8 *pNew = 0;
248680
+
248681
+ p1->xSetOutputs(p1, pSeg);
248682
+ if( p->rc ) break;
248683
+
248684
+ if( bNewTerm ){
248685
+ nNew = pSeg->term.n;
248686
+ pNew = pSeg->term.p;
248687
+ if( nNew<nToken || memcmp(pToken, pNew, nToken) ) break;
248688
+ }
248689
+
248690
+ xVisit(p, pCtx, p1, pNew, nNew);
248691
+ }
248692
+ fts5MultiIterFree(p1);
248693
+
248694
+ fts5StructureRelease(pStruct);
248695
+ return p->rc;
248696
+}
248697
+
248698
+
248699
+/*
248700
+** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
248701
+** array of these for each row it visits (so all iRowid fields are the same).
248702
+** Or, for an iterator used by an "ORDER BY rank" query, it accumulates an
248703
+** array of these for the entire query (in which case iRowid fields may take
248704
+** a variety of values).
248705
+**
248706
+** Each instance in the array indicates the iterator (and therefore term)
248707
+** associated with position iPos of rowid iRowid. This is used by the
248708
+** xInstToken() API.
248709
+**
248710
+** iRowid:
248711
+** Rowid for the current entry.
248712
+**
248713
+** iPos:
248714
+** Position of current entry within row. In the usual ((iCol<<32)+iOff)
248715
+** format (e.g. see macros FTS5_POS2COLUMN() and FTS5_POS2OFFSET()).
248716
+**
248717
+** iIter:
248718
+** If the Fts5TokenDataIter iterator that the entry is part of is
248719
+** actually an iterator (i.e. with nIter>0, not just a container for
248720
+** Fts5TokenDataMap structures), then this variable is an index into
248721
+** the apIter[] array. The corresponding term is that which the iterator
248722
+** at apIter[iIter] currently points to.
248723
+**
248724
+** Or, if the Fts5TokenDataIter iterator is just a container object
248725
+** (nIter==0), then iIter is an index into the term.p[] buffer where
248726
+** the term is stored.
248727
+**
248728
+** nByte:
248729
+** In the case where iIter is an index into term.p[], this variable
248730
+** is the size of the term in bytes. If iIter is an index into apIter[],
248731
+** this variable is unused.
248732
+*/
248733
+struct Fts5TokenDataMap {
248734
+ i64 iRowid; /* Row this token is located in */
248735
+ i64 iPos; /* Position of token */
248736
+ int iIter; /* Iterator token was read from */
248737
+ int nByte; /* Length of token in bytes (or 0) */
248738
+};
248739
+
248740
+/*
248741
+** An object used to supplement Fts5Iter for tokendata=1 iterators.
248742
+**
248743
+** This object serves two purposes. The first is as a container for an array
248744
+** of Fts5TokenDataMap structures, which are used to find the token required
248745
+** when the xInstToken() API is used. This is done by the nMapAlloc, nMap and
248746
+** aMap[] variables.
248747
+*/
248748
+struct Fts5TokenDataIter {
248749
+ int nMapAlloc; /* Allocated size of aMap[] in entries */
248750
+ int nMap; /* Number of valid entries in aMap[] */
248751
+ Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */
248752
+
248753
+ /* The following are used for prefix-queries only. */
248754
+ Fts5Buffer terms;
248755
+
248756
+ /* The following are used for other full-token tokendata queries only. */
248757
+ int nIter;
248758
+ int nIterAlloc;
248759
+ Fts5PoslistReader *aPoslistReader;
248760
+ int *aPoslistToIter;
248761
+ Fts5Iter *apIter[1];
248762
+};
248763
+
248764
+/*
248765
+** The two input arrays - a1[] and a2[] - are in sorted order. This function
248766
+** merges the two arrays together and writes the result to output array
248767
+** aOut[]. aOut[] is guaranteed to be large enough to hold the result.
248768
+**
248769
+** Duplicate entries are copied into the output. So the size of the output
248770
+** array is always (n1+n2) entries.
248771
+*/
248772
+static void fts5TokendataMerge(
248773
+ Fts5TokenDataMap *a1, int n1, /* Input array 1 */
248774
+ Fts5TokenDataMap *a2, int n2, /* Input array 2 */
248775
+ Fts5TokenDataMap *aOut /* Output array */
248776
+){
248777
+ int i1 = 0;
248778
+ int i2 = 0;
248779
+
248780
+ assert( n1>=0 && n2>=0 );
248781
+ while( i1<n1 || i2<n2 ){
248782
+ Fts5TokenDataMap *pOut = &aOut[i1+i2];
248783
+ if( i2>=n2 || (i1<n1 && (
248784
+ a1[i1].iRowid<a2[i2].iRowid
248785
+ || (a1[i1].iRowid==a2[i2].iRowid && a1[i1].iPos<=a2[i2].iPos)
248786
+ ))){
248787
+ memcpy(pOut, &a1[i1], sizeof(Fts5TokenDataMap));
248788
+ i1++;
248789
+ }else{
248790
+ memcpy(pOut, &a2[i2], sizeof(Fts5TokenDataMap));
248791
+ i2++;
248792
+ }
248793
+ }
248794
+}
248795
+
248796
+
248797
+/*
248798
+** Append a mapping to the token-map belonging to object pT.
248799
+*/
248800
+static void fts5TokendataIterAppendMap(
248801
+ Fts5Index *p,
248802
+ Fts5TokenDataIter *pT,
248803
+ int iIter,
248804
+ int nByte,
248805
+ i64 iRowid,
248806
+ i64 iPos
248807
+){
248808
+ if( p->rc==SQLITE_OK ){
248809
+ if( pT->nMap==pT->nMapAlloc ){
248810
+ int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
248811
+ int nAlloc = nNew * sizeof(Fts5TokenDataMap);
248812
+ Fts5TokenDataMap *aNew;
248813
+
248814
+ aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc);
248815
+ if( aNew==0 ){
248816
+ p->rc = SQLITE_NOMEM;
248817
+ return;
248818
+ }
248819
+
248820
+ pT->aMap = aNew;
248821
+ pT->nMapAlloc = nNew;
248822
+ }
248823
+
248824
+ pT->aMap[pT->nMap].iRowid = iRowid;
248825
+ pT->aMap[pT->nMap].iPos = iPos;
248826
+ pT->aMap[pT->nMap].iIter = iIter;
248827
+ pT->aMap[pT->nMap].nByte = nByte;
248828
+ pT->nMap++;
248829
+ }
248830
+}
248831
+
248832
+/*
248833
+** Sort the contents of the pT->aMap[] array.
248834
+**
248835
+** The sorting algorithm requries a malloc(). If this fails, an error code
248836
+** is left in Fts5Index.rc before returning.
248837
+*/
248838
+static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
248839
+ Fts5TokenDataMap *aTmp = 0;
248840
+ int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
248841
+
248842
+ aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte);
248843
+ if( aTmp ){
248844
+ Fts5TokenDataMap *a1 = pT->aMap;
248845
+ Fts5TokenDataMap *a2 = aTmp;
248846
+ i64 nHalf;
248847
+
248848
+ for(nHalf=1; nHalf<pT->nMap; nHalf=nHalf*2){
248849
+ int i1;
248850
+ for(i1=0; i1<pT->nMap; i1+=(nHalf*2)){
248851
+ int n1 = MIN(nHalf, pT->nMap-i1);
248852
+ int n2 = MIN(nHalf, pT->nMap-i1-n1);
248853
+ fts5TokendataMerge(&a1[i1], n1, &a1[i1+n1], n2, &a2[i1]);
248854
+ }
248855
+ SWAPVAL(Fts5TokenDataMap*, a1, a2);
248856
+ }
248857
+
248858
+ if( a1!=pT->aMap ){
248859
+ memcpy(pT->aMap, a1, pT->nMap*sizeof(Fts5TokenDataMap));
248860
+ }
248861
+ sqlite3_free(aTmp);
248862
+
248863
+#ifdef SQLITE_DEBUG
248864
+ {
248865
+ int ii;
248866
+ for(ii=1; ii<pT->nMap; ii++){
248867
+ Fts5TokenDataMap *p1 = &pT->aMap[ii-1];
248868
+ Fts5TokenDataMap *p2 = &pT->aMap[ii];
248869
+ assert( p1->iRowid<p2->iRowid
248870
+ || (p1->iRowid==p2->iRowid && p1->iPos<=p2->iPos)
248871
+ );
248872
+ }
248873
+ }
248874
+#endif
248875
+ }
248876
+}
248877
+
248878
+/*
248879
+** Delete an Fts5TokenDataIter structure and its contents.
248880
+*/
248881
+static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
248882
+ if( pSet ){
248883
+ int ii;
248884
+ for(ii=0; ii<pSet->nIter; ii++){
248885
+ fts5MultiIterFree(pSet->apIter[ii]);
248886
+ }
248887
+ fts5BufferFree(&pSet->terms);
248888
+ sqlite3_free(pSet->aPoslistReader);
248889
+ sqlite3_free(pSet->aMap);
248890
+ sqlite3_free(pSet);
248891
+ }
248892
+}
248893
+
248894
+
248895
+/*
248896
+** fts5VisitEntries() context object used by fts5SetupPrefixIterTokendata()
248897
+** to pass data to prefixIterSetupTokendataCb().
248898
+*/
248899
+typedef struct TokendataSetupCtx TokendataSetupCtx;
248900
+struct TokendataSetupCtx {
248901
+ Fts5TokenDataIter *pT; /* Object being populated with mappings */
248902
+ int iTermOff; /* Offset of current term in terms.p[] */
248903
+ int nTermByte; /* Size of current term in bytes */
248904
+};
248905
+
248906
+/*
248907
+** fts5VisitEntries() callback used by fts5SetupPrefixIterTokendata(). This
248908
+** callback adds an entry to the Fts5TokenDataIter.aMap[] array for each
248909
+** position in the current position-list. It doesn't matter that some of
248910
+** these may be out of order - they will be sorted later.
248911
+*/
248912
+static void prefixIterSetupTokendataCb(
248913
+ Fts5Index *p,
248914
+ void *pCtx,
248915
+ Fts5Iter *p1,
248916
+ const u8 *pNew,
248917
+ int nNew
248918
+){
248919
+ TokendataSetupCtx *pSetup = (TokendataSetupCtx*)pCtx;
248920
+ int iPosOff = 0;
248921
+ i64 iPos = 0;
248922
+
248923
+ if( pNew ){
248924
+ pSetup->nTermByte = nNew-1;
248925
+ pSetup->iTermOff = pSetup->pT->terms.n;
248926
+ fts5BufferAppendBlob(&p->rc, &pSetup->pT->terms, nNew-1, pNew+1);
248927
+ }
248928
+
248929
+ while( 0==sqlite3Fts5PoslistNext64(
248930
+ p1->base.pData, p1->base.nData, &iPosOff, &iPos
248931
+ ) ){
248932
+ fts5TokendataIterAppendMap(p,
248933
+ pSetup->pT, pSetup->iTermOff, pSetup->nTermByte, p1->base.iRowid, iPos
248934
+ );
248935
+ }
248936
+}
248937
+
248938
+
248939
+/*
248940
+** Context object passed by fts5SetupPrefixIter() to fts5VisitEntries().
248941
+*/
248942
+typedef struct PrefixSetupCtx PrefixSetupCtx;
248943
+struct PrefixSetupCtx {
248944
+ void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
248945
+ void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
248946
+ i64 iLastRowid;
248947
+ int nMerge;
248948
+ Fts5Buffer *aBuf;
248949
+ int nBuf;
248950
+ Fts5Buffer doclist;
248951
+ TokendataSetupCtx *pTokendata;
248952
+};
248953
+
248954
+/*
248955
+** fts5VisitEntries() callback used by fts5SetupPrefixIter()
248956
+*/
248957
+static void prefixIterSetupCb(
248958
+ Fts5Index *p,
248959
+ void *pCtx,
248960
+ Fts5Iter *p1,
248961
+ const u8 *pNew,
248962
+ int nNew
248963
+){
248964
+ PrefixSetupCtx *pSetup = (PrefixSetupCtx*)pCtx;
248965
+ const int nMerge = pSetup->nMerge;
248966
+
248967
+ if( p1->base.nData>0 ){
248968
+ if( p1->base.iRowid<=pSetup->iLastRowid && pSetup->doclist.n>0 ){
248969
+ int i;
248970
+ for(i=0; p->rc==SQLITE_OK && pSetup->doclist.n; i++){
248971
+ int i1 = i*nMerge;
248972
+ int iStore;
248973
+ assert( i1+nMerge<=pSetup->nBuf );
248974
+ for(iStore=i1; iStore<i1+nMerge; iStore++){
248975
+ if( pSetup->aBuf[iStore].n==0 ){
248976
+ fts5BufferSwap(&pSetup->doclist, &pSetup->aBuf[iStore]);
248977
+ fts5BufferZero(&pSetup->doclist);
248978
+ break;
248979
+ }
248980
+ }
248981
+ if( iStore==i1+nMerge ){
248982
+ pSetup->xMerge(p, &pSetup->doclist, nMerge, &pSetup->aBuf[i1]);
248983
+ for(iStore=i1; iStore<i1+nMerge; iStore++){
248984
+ fts5BufferZero(&pSetup->aBuf[iStore]);
248985
+ }
248986
+ }
248987
+ }
248988
+ pSetup->iLastRowid = 0;
248989
+ }
248990
+
248991
+ pSetup->xAppend(
248992
+ p, (u64)p1->base.iRowid-(u64)pSetup->iLastRowid, p1, &pSetup->doclist
248993
+ );
248994
+ pSetup->iLastRowid = p1->base.iRowid;
248995
+ }
248996
+
248997
+ if( pSetup->pTokendata ){
248998
+ prefixIterSetupTokendataCb(p, (void*)pSetup->pTokendata, p1, pNew, nNew);
248999
+ }
249000
+}
249001
+
248470249002
static void fts5SetupPrefixIter(
248471249003
Fts5Index *p, /* Index to read from */
248472249004
int bDesc, /* True for "ORDER BY rowid DESC" */
248473249005
int iIdx, /* Index to scan for data */
248474249006
u8 *pToken, /* Buffer containing prefix to match */
@@ -248475,137 +249007,89 @@
248475249007
int nToken, /* Size of buffer pToken in bytes */
248476249008
Fts5Colset *pColset, /* Restrict matches to these columns */
248477249009
Fts5Iter **ppIter /* OUT: New iterator */
248478249010
){
248479249011
Fts5Structure *pStruct;
248480
- Fts5Buffer *aBuf;
248481
- int nBuf = 32;
248482
- int nMerge = 1;
249012
+ PrefixSetupCtx s;
249013
+ TokendataSetupCtx s2;
248483249014
248484
- void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
248485
- void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
249015
+ memset(&s, 0, sizeof(s));
249016
+ memset(&s2, 0, sizeof(s2));
249017
+
249018
+ s.nMerge = 1;
249019
+ s.iLastRowid = 0;
249020
+ s.nBuf = 32;
249021
+ if( iIdx==0
249022
+ && p->pConfig->eDetail==FTS5_DETAIL_FULL
249023
+ && p->pConfig->bPrefixInsttoken
249024
+ ){
249025
+ s.pTokendata = &s2;
249026
+ s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT));
249027
+ }
249028
+
248486249029
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
248487
- xMerge = fts5MergeRowidLists;
248488
- xAppend = fts5AppendRowid;
249030
+ s.xMerge = fts5MergeRowidLists;
249031
+ s.xAppend = fts5AppendRowid;
248489249032
}else{
248490
- nMerge = FTS5_MERGE_NLIST-1;
248491
- nBuf = nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
248492
- xMerge = fts5MergePrefixLists;
248493
- xAppend = fts5AppendPoslist;
249033
+ s.nMerge = FTS5_MERGE_NLIST-1;
249034
+ s.nBuf = s.nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
249035
+ s.xMerge = fts5MergePrefixLists;
249036
+ s.xAppend = fts5AppendPoslist;
248494249037
}
248495249038
248496
- aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
249039
+ s.aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*s.nBuf);
248497249040
pStruct = fts5StructureRead(p);
248498
- assert( p->rc!=SQLITE_OK || (aBuf && pStruct) );
249041
+ assert( p->rc!=SQLITE_OK || (s.aBuf && pStruct) );
248499249042
248500249043
if( p->rc==SQLITE_OK ){
248501
- const int flags = FTS5INDEX_QUERY_SCAN
248502
- | FTS5INDEX_QUERY_SKIPEMPTY
248503
- | FTS5INDEX_QUERY_NOOUTPUT;
249044
+ void *pCtx = (void*)&s;
248504249045
int i;
248505
- i64 iLastRowid = 0;
248506
- Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
248507249046
Fts5Data *pData;
248508
- Fts5Buffer doclist;
248509
- int bNewTerm = 1;
248510
-
248511
- memset(&doclist, 0, sizeof(doclist));
248512249047
248513249048
/* If iIdx is non-zero, then it is the number of a prefix-index for
248514249049
** prefixes 1 character longer than the prefix being queried for. That
248515249050
** index contains all the doclists required, except for the one
248516249051
** corresponding to the prefix itself. That one is extracted from the
248517249052
** main term index here. */
248518249053
if( iIdx!=0 ){
248519
- int dummy = 0;
248520
- const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
248521249054
pToken[0] = FTS5_MAIN_PREFIX;
248522
- fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
248523
- fts5IterSetOutputCb(&p->rc, p1);
248524
- for(;
248525
- fts5MultiIterEof(p, p1)==0;
248526
- fts5MultiIterNext2(p, p1, &dummy)
248527
- ){
248528
- Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
248529
- p1->xSetOutputs(p1, pSeg);
248530
- if( p1->base.nData ){
248531
- xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
248532
- iLastRowid = p1->base.iRowid;
248533
- }
248534
- }
248535
- fts5MultiIterFree(p1);
249055
+ fts5VisitEntries(p, pColset, pToken, nToken, 0, prefixIterSetupCb, pCtx);
248536249056
}
248537249057
248538249058
pToken[0] = FTS5_MAIN_PREFIX + iIdx;
248539
- fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
248540
- fts5IterSetOutputCb(&p->rc, p1);
248541
-
248542
- for( /* no-op */ ;
248543
- fts5MultiIterEof(p, p1)==0;
248544
- fts5MultiIterNext2(p, p1, &bNewTerm)
248545
- ){
248546
- Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
248547
- int nTerm = pSeg->term.n;
248548
- const u8 *pTerm = pSeg->term.p;
248549
- p1->xSetOutputs(p1, pSeg);
248550
-
248551
- assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
248552
- if( bNewTerm ){
248553
- if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
248554
- }
248555
-
248556
- if( p1->base.nData==0 ) continue;
248557
- if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
248558
- for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
248559
- int i1 = i*nMerge;
248560
- int iStore;
248561
- assert( i1+nMerge<=nBuf );
248562
- for(iStore=i1; iStore<i1+nMerge; iStore++){
248563
- if( aBuf[iStore].n==0 ){
248564
- fts5BufferSwap(&doclist, &aBuf[iStore]);
248565
- fts5BufferZero(&doclist);
248566
- break;
248567
- }
248568
- }
248569
- if( iStore==i1+nMerge ){
248570
- xMerge(p, &doclist, nMerge, &aBuf[i1]);
248571
- for(iStore=i1; iStore<i1+nMerge; iStore++){
248572
- fts5BufferZero(&aBuf[iStore]);
248573
- }
248574
- }
248575
- }
248576
- iLastRowid = 0;
248577
- }
248578
-
248579
- xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
248580
- iLastRowid = p1->base.iRowid;
248581
- }
248582
-
248583
- assert( (nBuf%nMerge)==0 );
248584
- for(i=0; i<nBuf; i+=nMerge){
249059
+ fts5VisitEntries(p, pColset, pToken, nToken, 1, prefixIterSetupCb, pCtx);
249060
+
249061
+ assert( (s.nBuf%s.nMerge)==0 );
249062
+ for(i=0; i<s.nBuf; i+=s.nMerge){
248585249063
int iFree;
248586249064
if( p->rc==SQLITE_OK ){
248587
- xMerge(p, &doclist, nMerge, &aBuf[i]);
249065
+ s.xMerge(p, &s.doclist, s.nMerge, &s.aBuf[i]);
248588249066
}
248589
- for(iFree=i; iFree<i+nMerge; iFree++){
248590
- fts5BufferFree(&aBuf[iFree]);
249067
+ for(iFree=i; iFree<i+s.nMerge; iFree++){
249068
+ fts5BufferFree(&s.aBuf[iFree]);
248591249069
}
248592249070
}
248593
- fts5MultiIterFree(p1);
248594249071
248595
- pData = fts5IdxMalloc(p, sizeof(*pData)+doclist.n+FTS5_DATA_ZERO_PADDING);
249072
+ pData = fts5IdxMalloc(p, sizeof(*pData)+s.doclist.n+FTS5_DATA_ZERO_PADDING);
248596249073
if( pData ){
248597249074
pData->p = (u8*)&pData[1];
248598
- pData->nn = pData->szLeaf = doclist.n;
248599
- if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
249075
+ pData->nn = pData->szLeaf = s.doclist.n;
249076
+ if( s.doclist.n ) memcpy(pData->p, s.doclist.p, s.doclist.n);
248600249077
fts5MultiIterNew2(p, pData, bDesc, ppIter);
248601249078
}
248602
- fts5BufferFree(&doclist);
249079
+
249080
+ if( p->rc==SQLITE_OK && s.pTokendata ){
249081
+ fts5TokendataIterSortMap(p, s2.pT);
249082
+ (*ppIter)->pTokenDataIter = s2.pT;
249083
+ s2.pT = 0;
249084
+ }
248603249085
}
248604249086
249087
+ fts5TokendataIterDelete(s2.pT);
249088
+ fts5BufferFree(&s.doclist);
248605249089
fts5StructureRelease(pStruct);
248606
- sqlite3_free(aBuf);
249090
+ sqlite3_free(s.aBuf);
248607249091
}
248608249092
248609249093
248610249094
/*
248611249095
** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
@@ -248855,42 +249339,10 @@
248855249339
static void fts5SegIterSetEOF(Fts5SegIter *pSeg){
248856249340
fts5DataRelease(pSeg->pLeaf);
248857249341
pSeg->pLeaf = 0;
248858249342
}
248859249343
248860
-/*
248861
-** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
248862
-** array of these for each row it visits. Or, for an iterator used by an
248863
-** "ORDER BY rank" query, it accumulates an array of these for the entire
248864
-** query.
248865
-**
248866
-** Each instance in the array indicates the iterator (and therefore term)
248867
-** associated with position iPos of rowid iRowid. This is used by the
248868
-** xInstToken() API.
248869
-*/
248870
-struct Fts5TokenDataMap {
248871
- i64 iRowid; /* Row this token is located in */
248872
- i64 iPos; /* Position of token */
248873
- int iIter; /* Iterator token was read from */
248874
-};
248875
-
248876
-/*
248877
-** An object used to supplement Fts5Iter for tokendata=1 iterators.
248878
-*/
248879
-struct Fts5TokenDataIter {
248880
- int nIter;
248881
- int nIterAlloc;
248882
-
248883
- int nMap;
248884
- int nMapAlloc;
248885
- Fts5TokenDataMap *aMap;
248886
-
248887
- Fts5PoslistReader *aPoslistReader;
248888
- int *aPoslistToIter;
248889
- Fts5Iter *apIter[1];
248890
-};
248891
-
248892249344
/*
248893249345
** This function appends iterator pAppend to Fts5TokenDataIter pIn and
248894249346
** returns the result.
248895249347
*/
248896249348
static Fts5TokenDataIter *fts5AppendTokendataIter(
@@ -248923,58 +249375,10 @@
248923249375
assert( pRet==0 || pRet->nIter<=pRet->nIterAlloc );
248924249376
248925249377
return pRet;
248926249378
}
248927249379
248928
-/*
248929
-** Delete an Fts5TokenDataIter structure and its contents.
248930
-*/
248931
-static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
248932
- if( pSet ){
248933
- int ii;
248934
- for(ii=0; ii<pSet->nIter; ii++){
248935
- fts5MultiIterFree(pSet->apIter[ii]);
248936
- }
248937
- sqlite3_free(pSet->aPoslistReader);
248938
- sqlite3_free(pSet->aMap);
248939
- sqlite3_free(pSet);
248940
- }
248941
-}
248942
-
248943
-/*
248944
-** Append a mapping to the token-map belonging to object pT.
248945
-*/
248946
-static void fts5TokendataIterAppendMap(
248947
- Fts5Index *p,
248948
- Fts5TokenDataIter *pT,
248949
- int iIter,
248950
- i64 iRowid,
248951
- i64 iPos
248952
-){
248953
- if( p->rc==SQLITE_OK ){
248954
- if( pT->nMap==pT->nMapAlloc ){
248955
- int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
248956
- int nByte = nNew * sizeof(Fts5TokenDataMap);
248957
- Fts5TokenDataMap *aNew;
248958
-
248959
- aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nByte);
248960
- if( aNew==0 ){
248961
- p->rc = SQLITE_NOMEM;
248962
- return;
248963
- }
248964
-
248965
- pT->aMap = aNew;
248966
- pT->nMapAlloc = nNew;
248967
- }
248968
-
248969
- pT->aMap[pT->nMap].iRowid = iRowid;
248970
- pT->aMap[pT->nMap].iPos = iPos;
248971
- pT->aMap[pT->nMap].iIter = iIter;
248972
- pT->nMap++;
248973
- }
248974
-}
248975
-
248976249380
/*
248977249381
** The iterator passed as the only argument must be a tokendata=1 iterator
248978249382
** (pIter->pTokenDataIter!=0). This function sets the iterator output
248979249383
** variables (pIter->base.*) according to the contents of the current
248980249384
** row.
@@ -249011,11 +249415,11 @@
249011249415
int eDetail = pIter->pIndex->pConfig->eDetail;
249012249416
pIter->base.bEof = 0;
249013249417
pIter->base.iRowid = iRowid;
249014249418
249015249419
if( nHit==1 && eDetail==FTS5_DETAIL_FULL ){
249016
- fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, iRowid, -1);
249420
+ fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, 0, iRowid, -1);
249017249421
}else
249018249422
if( nHit>1 && eDetail!=FTS5_DETAIL_NONE ){
249019249423
int nReader = 0;
249020249424
int nByte = 0;
249021249425
i64 iPrev = 0;
@@ -249264,10 +249668,11 @@
249264249668
249265249669
if( p->rc==SQLITE_OK ){
249266249670
pRet = fts5MultiIterAlloc(p, 0);
249267249671
}
249268249672
if( pRet ){
249673
+ pRet->nSeg = 0;
249269249674
pRet->pTokenDataIter = pSet;
249270249675
if( pSet ){
249271249676
fts5IterSetOutputsTokendata(pRet);
249272249677
}else{
249273249678
pRet->base.bEof = 1;
@@ -249278,11 +249683,10 @@
249278249683
249279249684
fts5StructureRelease(pStruct);
249280249685
fts5BufferFree(&bSeek);
249281249686
return pRet;
249282249687
}
249283
-
249284249688
249285249689
/*
249286249690
** Open a new iterator to iterate though all rowid that match the
249287249691
** specified token or token prefix.
249288249692
*/
@@ -249304,10 +249708,15 @@
249304249708
int iIdx = 0; /* Index to search */
249305249709
int iPrefixIdx = 0; /* +1 prefix index */
249306249710
int bTokendata = pConfig->bTokendata;
249307249711
if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
249308249712
249713
+ /* The NOTOKENDATA flag is set when each token in a tokendata=1 table
249714
+ ** should be treated individually, instead of merging all those with
249715
+ ** a common prefix into a single entry. This is used, for example, by
249716
+ ** queries performed as part of an integrity-check, or by the fts5vocab
249717
+ ** module. */
249309249718
if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){
249310249719
bTokendata = 0;
249311249720
}
249312249721
249313249722
/* Figure out which index to search and set iIdx accordingly. If this
@@ -249334,11 +249743,11 @@
249334249743
if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
249335249744
}
249336249745
}
249337249746
249338249747
if( bTokendata && iIdx==0 ){
249339
- buf.p[0] = '0';
249748
+ buf.p[0] = FTS5_MAIN_PREFIX;
249340249749
pRet = fts5SetupTokendataIter(p, buf.p, nToken+1, pColset);
249341249750
}else if( iIdx<=pConfig->nPrefix ){
249342249751
/* Straight index lookup */
249343249752
Fts5Structure *pStruct = fts5StructureRead(p);
249344249753
buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
@@ -249347,11 +249756,11 @@
249347249756
pColset, buf.p, nToken+1, -1, 0, &pRet
249348249757
);
249349249758
fts5StructureRelease(pStruct);
249350249759
}
249351249760
}else{
249352
- /* Scan multiple terms in the main index */
249761
+ /* Scan multiple terms in the main index for a prefix query. */
249353249762
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
249354249763
fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
249355249764
if( pRet==0 ){
249356249765
assert( p->rc!=SQLITE_OK );
249357249766
}else{
@@ -249383,11 +249792,12 @@
249383249792
** Move to the next matching rowid.
249384249793
*/
249385249794
static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
249386249795
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249387249796
assert( pIter->pIndex->rc==SQLITE_OK );
249388
- if( pIter->pTokenDataIter ){
249797
+ if( pIter->nSeg==0 ){
249798
+ assert( pIter->pTokenDataIter );
249389249799
fts5TokendataIterNext(pIter, 0, 0);
249390249800
}else{
249391249801
fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
249392249802
}
249393249803
return fts5IndexReturn(pIter->pIndex);
@@ -249420,11 +249830,12 @@
249420249830
** definition of "at or after" depends on whether this iterator iterates
249421249831
** in ascending or descending rowid order.
249422249832
*/
249423249833
static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
249424249834
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249425
- if( pIter->pTokenDataIter ){
249835
+ if( pIter->nSeg==0 ){
249836
+ assert( pIter->pTokenDataIter );
249426249837
fts5TokendataIterNext(pIter, 1, iMatch);
249427249838
}else{
249428249839
fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
249429249840
}
249430249841
return fts5IndexReturn(pIter->pIndex);
@@ -249438,32 +249849,87 @@
249438249849
const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
249439249850
assert_nc( z || n<=1 );
249440249851
*pn = n-1;
249441249852
return (z ? &z[1] : 0);
249442249853
}
249854
+
249855
+/*
249856
+** pIter is a prefix query. This function populates pIter->pTokenDataIter
249857
+** with an Fts5TokenDataIter object containing mappings for all rows
249858
+** matched by the query.
249859
+*/
249860
+static int fts5SetupPrefixIterTokendata(
249861
+ Fts5Iter *pIter,
249862
+ const char *pToken, /* Token prefix to search for */
249863
+ int nToken /* Size of pToken in bytes */
249864
+){
249865
+ Fts5Index *p = pIter->pIndex;
249866
+ Fts5Buffer token = {0, 0, 0};
249867
+ TokendataSetupCtx ctx;
249868
+
249869
+ memset(&ctx, 0, sizeof(ctx));
249870
+
249871
+ fts5BufferGrow(&p->rc, &token, nToken+1);
249872
+ ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT));
249873
+
249874
+ if( p->rc==SQLITE_OK ){
249875
+
249876
+ /* Fill in the token prefix to search for */
249877
+ token.p[0] = FTS5_MAIN_PREFIX;
249878
+ memcpy(&token.p[1], pToken, nToken);
249879
+ token.n = nToken+1;
249880
+
249881
+ fts5VisitEntries(
249882
+ p, 0, token.p, token.n, 1, prefixIterSetupTokendataCb, (void*)&ctx
249883
+ );
249884
+
249885
+ fts5TokendataIterSortMap(p, ctx.pT);
249886
+ }
249887
+
249888
+ if( p->rc==SQLITE_OK ){
249889
+ pIter->pTokenDataIter = ctx.pT;
249890
+ }else{
249891
+ fts5TokendataIterDelete(ctx.pT);
249892
+ }
249893
+ fts5BufferFree(&token);
249894
+
249895
+ return fts5IndexReturn(p);
249896
+}
249443249897
249444249898
/*
249445249899
** This is used by xInstToken() to access the token at offset iOff, column
249446249900
** iCol of row iRowid. The token is returned via output variables *ppOut
249447249901
** and *pnOut. The iterator passed as the first argument must be a tokendata=1
249448249902
** iterator (pIter->pTokenDataIter!=0).
249903
+**
249904
+** pToken/nToken:
249449249905
*/
249450249906
static int sqlite3Fts5IterToken(
249451249907
Fts5IndexIter *pIndexIter,
249908
+ const char *pToken, int nToken,
249452249909
i64 iRowid,
249453249910
int iCol,
249454249911
int iOff,
249455249912
const char **ppOut, int *pnOut
249456249913
){
249457249914
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249458249915
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
249459
- Fts5TokenDataMap *aMap = pT->aMap;
249460249916
i64 iPos = (((i64)iCol)<<32) + iOff;
249461
-
249917
+ Fts5TokenDataMap *aMap = 0;
249462249918
int i1 = 0;
249463
- int i2 = pT->nMap;
249919
+ int i2 = 0;
249464249920
int iTest = 0;
249921
+
249922
+ assert( pT || (pToken && pIter->nSeg>0) );
249923
+ if( pT==0 ){
249924
+ int rc = fts5SetupPrefixIterTokendata(pIter, pToken, nToken);
249925
+ if( rc!=SQLITE_OK ) return rc;
249926
+ pT = pIter->pTokenDataIter;
249927
+ }
249928
+
249929
+ i2 = pT->nMap;
249930
+ aMap = pT->aMap;
249465249931
249466249932
while( i2>i1 ){
249467249933
iTest = (i1 + i2) / 2;
249468249934
249469249935
if( aMap[iTest].iRowid<iRowid ){
@@ -249483,13 +249949,19 @@
249483249949
}
249484249950
}
249485249951
}
249486249952
249487249953
if( i2>i1 ){
249488
- Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
249489
- *ppOut = (const char*)pMap->aSeg[0].term.p+1;
249490
- *pnOut = pMap->aSeg[0].term.n-1;
249954
+ if( pIter->nSeg==0 ){
249955
+ Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
249956
+ *ppOut = (const char*)pMap->aSeg[0].term.p+1;
249957
+ *pnOut = pMap->aSeg[0].term.n-1;
249958
+ }else{
249959
+ Fts5TokenDataMap *p = &aMap[iTest];
249960
+ *ppOut = (const char*)&pT->terms.p[p->iIter];
249961
+ *pnOut = aMap[iTest].nByte;
249962
+ }
249491249963
}
249492249964
249493249965
return SQLITE_OK;
249494249966
}
249495249967
@@ -249497,11 +249969,13 @@
249497249969
** Clear any existing entries from the token-map associated with the
249498249970
** iterator passed as the only argument.
249499249971
*/
249500249972
static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){
249501249973
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249502
- if( pIter && pIter->pTokenDataIter ){
249974
+ if( pIter && pIter->pTokenDataIter
249975
+ && (pIter->nSeg==0 || pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_FULL)
249976
+ ){
249503249977
pIter->pTokenDataIter->nMap = 0;
249504249978
}
249505249979
}
249506249980
249507249981
/*
@@ -249517,21 +249991,33 @@
249517249991
i64 iRowid, int iCol, int iOff
249518249992
){
249519249993
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249520249994
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
249521249995
Fts5Index *p = pIter->pIndex;
249522
- int ii;
249996
+ i64 iPos = (((i64)iCol)<<32) + iOff;
249523249997
249524249998
assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
249525
- assert( pIter->pTokenDataIter );
249526
-
249527
- for(ii=0; ii<pT->nIter; ii++){
249528
- Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
249529
- if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
249530
- }
249531
- if( ii<pT->nIter ){
249532
- fts5TokendataIterAppendMap(p, pT, ii, iRowid, (((i64)iCol)<<32) + iOff);
249999
+ assert( pIter->pTokenDataIter || pIter->nSeg>0 );
250000
+ if( pIter->nSeg>0 ){
250001
+ /* This is a prefix term iterator. */
250002
+ if( pT==0 ){
250003
+ pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT));
250004
+ pIter->pTokenDataIter = pT;
250005
+ }
250006
+ if( pT ){
250007
+ fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos);
250008
+ fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken);
250009
+ }
250010
+ }else{
250011
+ int ii;
250012
+ for(ii=0; ii<pT->nIter; ii++){
250013
+ Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
250014
+ if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
250015
+ }
250016
+ if( ii<pT->nIter ){
250017
+ fts5TokendataIterAppendMap(p, pT, ii, 0, iRowid, iPos);
250018
+ }
249533250019
}
249534250020
return fts5IndexReturn(p);
249535250021
}
249536250022
249537250023
/*
@@ -251432,10 +251918,11 @@
251432251918
** containing a copy of the header from an Fts5Config pointer.
251433251919
*/
251434251920
#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
251435251921
#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
251436251922
251923
+#define FTS5_INSTTOKEN_SUBTYPE 73
251437251924
251438251925
/*
251439251926
** Each auxiliary function registered with the FTS5 module is represented
251440251927
** by an object of the following type. All such objects are stored as part
251441251928
** of the Fts5Global.pAux list.
@@ -252757,10 +253244,11 @@
252757253244
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
252758253245
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
252759253246
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
252760253247
int iCol; /* Column on LHS of MATCH operator */
252761253248
char **pzErrmsg = pConfig->pzErrmsg;
253249
+ int bPrefixInsttoken = pConfig->bPrefixInsttoken;
252762253250
int i;
252763253251
int iIdxStr = 0;
252764253252
Fts5Expr *pExpr = 0;
252765253253
252766253254
assert( pConfig->bLock==0 );
@@ -252792,10 +253280,13 @@
252792253280
int bInternal = 0;
252793253281
252794253282
rc = fts5ExtractExprText(pConfig, apVal[i], &zText, &bFreeAndReset);
252795253283
if( rc!=SQLITE_OK ) goto filter_out;
252796253284
if( zText==0 ) zText = "";
253285
+ if( sqlite3_value_subtype(apVal[i])==FTS5_INSTTOKEN_SUBTYPE ){
253286
+ pConfig->bPrefixInsttoken = 1;
253287
+ }
252797253288
252798253289
iCol = 0;
252799253290
do{
252800253291
iCol = iCol*10 + (idxStr[iIdxStr]-'0');
252801253292
iIdxStr++;
@@ -252932,10 +253423,11 @@
252932253423
}
252933253424
252934253425
filter_out:
252935253426
sqlite3Fts5ExprFree(pExpr);
252936253427
pConfig->pzErrmsg = pzErrmsg;
253428
+ pConfig->bPrefixInsttoken = bPrefixInsttoken;
252937253429
return rc;
252938253430
}
252939253431
252940253432
/*
252941253433
** This is the xEof method of the virtual table. SQLite calls this
@@ -254927,11 +255419,11 @@
254927255419
int nArg, /* Number of args */
254928255420
sqlite3_value **apUnused /* Function arguments */
254929255421
){
254930255422
assert( nArg==0 );
254931255423
UNUSED_PARAM2(nArg, apUnused);
254932
- sqlite3_result_text(pCtx, "fts5: 2024-11-14 19:34:28 81202d2ab5963fdcf20555b6d0b31cc955ac27f1cd87656faea5c0611c9a2ee8", -1, SQLITE_TRANSIENT);
255424
+ sqlite3_result_text(pCtx, "fts5: 2024-12-09 20:46:36 e2bae4143afd07de1ae55a6d2606a3b541a5b94568aa41f6a96e5d1245471653", -1, SQLITE_TRANSIENT);
254933255425
}
254934255426
254935255427
/*
254936255428
** Implementation of fts5_locale(LOCALE, TEXT) function.
254937255429
**
@@ -254990,10 +255482,24 @@
254990255482
assert( &pCsr[nText]==&pBlob[nBlob] );
254991255483
254992255484
sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);
254993255485
}
254994255486
}
255487
+
255488
+/*
255489
+** Implementation of fts5_insttoken() function.
255490
+*/
255491
+static void fts5InsttokenFunc(
255492
+ sqlite3_context *pCtx, /* Function call context */
255493
+ int nArg, /* Number of args */
255494
+ sqlite3_value **apArg /* Function arguments */
255495
+){
255496
+ assert( nArg==1 );
255497
+ (void)nArg;
255498
+ sqlite3_result_value(pCtx, apArg[0]);
255499
+ sqlite3_result_subtype(pCtx, FTS5_INSTTOKEN_SUBTYPE);
255500
+}
254995255501
254996255502
/*
254997255503
** Return true if zName is the extension on one of the shadow tables used
254998255504
** by this module.
254999255505
*/
@@ -255120,13 +255626,20 @@
255120255626
);
255121255627
}
255122255628
if( rc==SQLITE_OK ){
255123255629
rc = sqlite3_create_function(
255124255630
db, "fts5_locale", 2,
255125
- SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
255631
+ SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE|SQLITE_SUBTYPE,
255126255632
p, fts5LocaleFunc, 0, 0
255127255633
);
255634
+ }
255635
+ if( rc==SQLITE_OK ){
255636
+ rc = sqlite3_create_function(
255637
+ db, "fts5_insttoken", 1,
255638
+ SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
255639
+ p, fts5InsttokenFunc, 0, 0
255640
+ );
255128255641
}
255129255642
}
255130255643
255131255644
/* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
255132255645
** fts5_test_mi.c is compiled and linked into the executable. And call
@@ -258048,11 +258561,11 @@
258048258561
int rc = SQLITE_OK;
258049258562
char aBuf[32];
258050258563
char *zOut = aBuf;
258051258564
int ii;
258052258565
const unsigned char *zIn = (const unsigned char*)pText;
258053
- const unsigned char *zEof = &zIn[nText];
258566
+ const unsigned char *zEof = (zIn ? &zIn[nText] : 0);
258054258567
u32 iCode = 0;
258055258568
int aStart[3]; /* Input offset of each character in aBuf[] */
258056258569
258057258570
UNUSED_PARAM(unusedFlags);
258058258571
258059258572
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** 81202d2ab5963fdcf20555b6d0b31cc955ac with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -465,11 +465,11 @@
465 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
466 ** [sqlite_version()] and [sqlite_source_id()].
467 */
468 #define SQLITE_VERSION "3.48.0"
469 #define SQLITE_VERSION_NUMBER 3048000
470 #define SQLITE_SOURCE_ID "2024-11-14 19:34:28 81202d2ab5963fdcf20555b6d0b31cc955ac27f1cd87656faea5c0611c9a2ee8"
471
472 /*
473 ** CAPI3REF: Run-Time Library Version Numbers
474 ** KEYWORDS: sqlite3_version sqlite3_sourceid
475 **
@@ -4521,15 +4521,26 @@
4521 **
4522 ** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
4523 ** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
4524 ** to return an error (error code SQLITE_ERROR) if the statement uses
4525 ** any virtual tables.
 
 
 
 
 
 
 
 
 
 
4526 ** </dl>
4527 */
4528 #define SQLITE_PREPARE_PERSISTENT 0x01
4529 #define SQLITE_PREPARE_NORMALIZE 0x02
4530 #define SQLITE_PREPARE_NO_VTAB 0x04
 
4531
4532 /*
4533 ** CAPI3REF: Compiling An SQL Statement
4534 ** KEYWORDS: {SQL statement compiler}
4535 ** METHOD: sqlite3
@@ -13467,17 +13478,32 @@
13467 ** This is used to access token iToken of phrase hit iIdx within the
13468 ** current row. If iIdx is less than zero or greater than or equal to the
13469 ** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
13470 ** output variable (*ppToken) is set to point to a buffer containing the
13471 ** matching document token, and (*pnToken) to the size of that buffer in
13472 ** bytes. This API is not available if the specified token matches a
13473 ** prefix query term. In that case both output variables are always set
13474 ** to 0.
13475 **
13476 ** The output text is not a copy of the document text that was tokenized.
13477 ** It is the output of the tokenizer module. For tokendata=1 tables, this
13478 ** includes any embedded 0x00 and trailing data.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13479 **
13480 ** This API can be quite slow if used with an FTS5 table created with the
13481 ** "detail=none" or "detail=column" option.
13482 **
13483 ** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
@@ -17049,11 +17075,11 @@
17049
17050 /*
17051 ** Additional non-public SQLITE_PREPARE_* flags
17052 */
17053 #define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
17054 #define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
17055
17056 /*
17057 ** Prototypes for the VDBE interface. See comments on the implementation
17058 ** for a description of what each of these routines does.
17059 */
@@ -32279,10 +32305,11 @@
32279 && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
32280 ){
32281 pExpr = pExpr->pLeft;
32282 }
32283 if( pExpr==0 ) return;
 
32284 db->errByteOffset = pExpr->w.iOfst;
32285 }
32286
32287 /*
32288 ** Enlarge the memory allocation on a StrAccum object so that it is
@@ -33008,11 +33035,11 @@
33008 }
33009 if( pItem->fg.isCte ){
33010 sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
33011 }
33012 if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
33013 sqlite3_str_appendf(&x, " ON");
33014 }
33015 if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
33016 if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
33017 if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
33018 if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
@@ -34092,10 +34119,14 @@
34092 **
34093 ** This routines are given external linkage so that they will always be
34094 ** accessible to the debugging, and to avoid warnings about unused
34095 ** functions. But these routines only exist in debugging builds, so they
34096 ** do not contaminate the interface.
 
 
 
 
34097 */
34098 SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
34099 SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
34100 SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
34101 SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
@@ -35668,12 +35699,12 @@
35668 int esign = 1; /* sign of exponent */
35669 int e = 0; /* exponent */
35670 int eValid = 1; /* True exponent is either not used or is well-formed */
35671 int nDigit = 0; /* Number of digits processed */
35672 int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
 
35673 double rr[2];
35674 u64 s2;
35675
35676 assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
35677 *pResult = 0.0; /* Default return value, in case of an error */
35678 if( length==0 ) return 0;
35679
@@ -35772,25 +35803,36 @@
35772
35773 /* adjust exponent by d, and update sign */
35774 e = (e*esign) + d;
35775
35776 /* Try to adjust the exponent to make it smaller */
35777 while( e>0 && s<(LARGEST_UINT64/10) ){
35778 s *= 10;
35779 e--;
35780 }
35781 while( e<0 && (s%10)==0 ){
35782 s /= 10;
35783 e++;
35784 }
35785
35786 rr[0] = (double)s;
35787 s2 = (u64)rr[0];
35788 #if defined(_MSC_VER) && _MSC_VER<1700
35789 if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
 
 
35790 #endif
35791 rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
 
 
 
 
 
 
 
 
 
35792 if( e>0 ){
35793 while( e>=100 ){
35794 e -= 100;
35795 dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
35796 }
@@ -51771,11 +51813,11 @@
51771 */
51772 char *zTmpname = 0; /* For temporary filename, if necessary. */
51773
51774 int rc = SQLITE_OK; /* Function Return Code */
51775 #if !defined(NDEBUG) || SQLITE_OS_WINCE
51776 int eType = flags&0xFFFFFF00; /* Type of file to open */
51777 #endif
51778
51779 int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
51780 int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
51781 int isCreate = (flags & SQLITE_OPEN_CREATE);
@@ -112021,11 +112063,11 @@
112021 **
112022 ** (4) If pSrc is the right operand of a LEFT JOIN, then...
112023 ** (4a) pExpr must come from an ON clause..
112024 ** (4b) and specifically the ON clause associated with the LEFT JOIN.
112025 **
112026 ** (5) If pSrc is not the right operand of a LEFT JOIN or the left
112027 ** operand of a RIGHT JOIN, then pExpr must be from the WHERE
112028 ** clause, not an ON clause.
112029 **
112030 ** (6) Either:
112031 **
@@ -115555,35 +115597,41 @@
115555 **
115556 ** Additionally, if pExpr is a simple SQL value and the value is the
115557 ** same as that currently bound to variable pVar, non-zero is returned.
115558 ** Otherwise, if the values are not the same or if pExpr is not a simple
115559 ** SQL value, zero is returned.
 
 
 
115560 */
115561 static int exprCompareVariable(
115562 const Parse *pParse,
115563 const Expr *pVar,
115564 const Expr *pExpr
115565 ){
115566 int res = 0;
115567 int iVar;
115568 sqlite3_value *pL, *pR = 0;
115569
 
 
 
 
115570 sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
115571 if( pR ){
115572 iVar = pVar->iColumn;
115573 sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
115574 pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
115575 if( pL ){
115576 if( sqlite3_value_type(pL)==SQLITE_TEXT ){
115577 sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
115578 }
115579 res = 0==sqlite3MemCompare(pL, pR, 0);
115580 }
115581 sqlite3ValueFree(pR);
115582 sqlite3ValueFree(pL);
115583 }
115584
115585 return res;
115586 }
115587
115588 /*
115589 ** Do a deep comparison of two expression trees. Return 0 if the two
@@ -115605,16 +115653,14 @@
115605 ** can be sure the expressions are the same. In the places where
115606 ** this routine is used, it does not hurt to get an extra 2 - that
115607 ** just might result in some slightly slower code. But returning
115608 ** an incorrect 0 or 1 could lead to a malfunction.
115609 **
115610 ** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
115611 ** pParse->pReprepare can be matched against literals in pB. The
115612 ** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
115613 ** If pParse is NULL (the normal case) then any TK_VARIABLE term in
115614 ** Argument pParse should normally be NULL. If it is not NULL and pA or
115615 ** pB causes a return value of 2.
115616 */
115617 SQLITE_PRIVATE int sqlite3ExprCompare(
115618 const Parse *pParse,
115619 const Expr *pA,
115620 const Expr *pB,
@@ -115622,12 +115668,12 @@
115622 ){
115623 u32 combinedFlags;
115624 if( pA==0 || pB==0 ){
115625 return pB==pA ? 0 : 2;
115626 }
115627 if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
115628 return 0;
115629 }
115630 combinedFlags = pA->flags | pB->flags;
115631 if( combinedFlags & EP_IntValue ){
115632 if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
115633 return 0;
@@ -115817,23 +115863,75 @@
115817 return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
115818 }
115819 }
115820 return 0;
115821 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115822
115823 /*
115824 ** Return true if we can prove the pE2 will always be true if pE1 is
115825 ** true. Return false if we cannot complete the proof or if pE2 might
115826 ** be false. Examples:
115827 **
115828 ** pE1: x==5 pE2: x==5 Result: true
115829 ** pE1: x>0 pE2: x==5 Result: false
115830 ** pE1: x=21 pE2: x=21 OR y=43 Result: true
115831 ** pE1: x!=123 pE2: x IS NOT NULL Result: true
115832 ** pE1: x!=?1 pE2: x IS NOT NULL Result: true
115833 ** pE1: x IS NULL pE2: x IS NOT NULL Result: false
115834 ** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
 
 
115835 **
115836 ** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
115837 ** Expr.iTable<0 then assume a table number given by iTab.
115838 **
115839 ** If pParse is not NULL, then the values of bound variables in pE1 are
@@ -115863,10 +115961,13 @@
115863 if( pE2->op==TK_NOTNULL
115864 && exprImpliesNotNull(pParse, pE1, pE2->pLeft, iTab, 0)
115865 ){
115866 return 1;
115867 }
 
 
 
115868 return 0;
115869 }
115870
115871 /* This is a helper function to impliesNotNullRow(). In this routine,
115872 ** set pWalker->eCode to one only if *both* of the input expressions
@@ -132082,11 +132183,14 @@
132082 MFUNCTION(degrees, 1, radToDeg, math1Func ),
132083 MFUNCTION(pi, 0, 0, piFunc ),
132084 #endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
132085 FUNCTION(sign, 1, 0, 0, signFunc ),
132086 INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
 
132087 INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
 
 
132088 };
132089 #ifndef SQLITE_OMIT_ALTERTABLE
132090 sqlite3AlterFunctions();
132091 #endif
132092 sqlite3WindowFunctions();
@@ -140730,11 +140834,12 @@
140730 pTab = sqliteHashData(k);
140731 if( pTab->nCol==0 ){
140732 char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
140733 if( zSql ){
140734 sqlite3_stmt *pDummy = 0;
140735 (void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
 
140736 (void)sqlite3_finalize(pDummy);
140737 sqlite3DbFree(db, zSql);
140738 }
140739 if( db->mallocFailed ){
140740 sqlite3ErrorMsg(db->pParse, "out of memory");
@@ -147529,36 +147634,36 @@
147529 return pExpr;
147530 }
147531 if( pSubst->isOuterJoin ){
147532 ExprSetProperty(pNew, EP_CanBeNull);
147533 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147534 if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
147535 sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
147536 pExpr->flags & (EP_OuterON|EP_InnerON));
147537 }
147538 sqlite3ExprDelete(db, pExpr);
147539 pExpr = pNew;
147540 if( pExpr->op==TK_TRUEFALSE ){
147541 pExpr->u.iValue = sqlite3ExprTruthValue(pExpr);
147542 pExpr->op = TK_INTEGER;
147543 ExprSetProperty(pExpr, EP_IntValue);
147544 }
147545
147546 /* Ensure that the expression now has an implicit collation sequence,
147547 ** just as it did when it was a column of a view or sub-query. */
147548 {
147549 CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
147550 CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
147551 pSubst->pCList->a[iColumn].pExpr
147552 );
147553 if( pNat!=pColl || (pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE) ){
147554 pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
147555 (pColl ? pColl->zName : "BINARY")
147556 );
147557 }
147558 }
147559 ExprClearProperty(pExpr, EP_Collate);
147560 }
147561 }
147562 }else{
147563 if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
147564 pExpr->iTable = pSubst->iNewTable;
@@ -148291,20 +148396,20 @@
148291 }
148292
148293 /* Transfer the FROM clause terms from the subquery into the
148294 ** outer query.
148295 */
 
148296 for(i=0; i<nSubSrc; i++){
148297 SrcItem *pItem = &pSrc->a[i+iFrom];
148298 assert( pItem->fg.isTabFunc==0 );
148299 assert( pItem->fg.isSubquery
148300 || pItem->fg.fixedSchema
148301 || pItem->u4.zDatabase==0 );
148302 if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
148303 *pItem = pSubSrc->a[i];
148304 pItem->fg.jointype |= ltorj;
148305 iNewParent = pSubSrc->a[i].iCursor;
148306 memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
148307 }
148308 pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
148309 pSrc->a[iFrom].fg.jointype |= jointype | ltorj;
148310
@@ -148340,10 +148445,11 @@
148340 pSub->pOrderBy = 0;
148341 }
148342 pWhere = pSub->pWhere;
148343 pSub->pWhere = 0;
148344 if( isOuterJoin>0 ){
 
148345 sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
148346 }
148347 if( pWhere ){
148348 if( pParent->pWhere ){
148349 pParent->pWhere = sqlite3PExpr(pParse, TK_AND, pWhere, pParent->pWhere);
@@ -151439,11 +151545,11 @@
151439 sqlite3TreeViewSelect(0, p, 0);
151440 }
151441 #endif
151442 assert( pSubq->pSelect && (pSub->selFlags & SF_PushDown)!=0 );
151443 }else{
151444 TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
151445 }
151446
151447 /* Convert unused result columns of the subquery into simple NULL
151448 ** expressions, to avoid unneeded searching and computation.
151449 ** tag-select-0440
@@ -158930,10 +159036,11 @@
158930 if( pOrigLhs ){
158931 sqlite3ExprListDelete(db, pOrigLhs);
158932 pNew->pLeft->x.pList = pLhs;
158933 }
158934 pSelect->pEList = pRhs;
 
158935 if( pLhs && pLhs->nExpr==1 ){
158936 /* Take care here not to generate a TK_VECTOR containing only a
158937 ** single value. Since the parser never creates such a vector, some
158938 ** of the subroutines do not handle this case. */
158939 Expr *p = pLhs->a[0].pExpr;
@@ -164002,11 +164109,11 @@
164002 || pTerm->pExpr->w.iJoin != pSrc->iCursor
164003 ){
164004 return 0;
164005 }
164006 if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0
164007 && ExprHasProperty(pTerm->pExpr, EP_InnerON)
164008 ){
164009 return 0;
164010 }
164011 return 1;
164012 }
@@ -165495,11 +165602,11 @@
165495 return rc;
165496 }
165497 #endif /* SQLITE_ENABLE_STAT4 */
165498
165499
165500 #ifdef WHERETRACE_ENABLED
165501 /*
165502 ** Print the content of a WhereTerm object
165503 */
165504 SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
165505 if( pTerm==0 ){
@@ -165538,10 +165645,13 @@
165538 sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
165539 }
165540 sqlite3DebugPrintf("\n");
165541 sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
165542 }
 
 
 
165543 }
165544 #endif
165545
165546 #ifdef WHERETRACE_ENABLED
165547 /*
@@ -166724,11 +166834,10 @@
166724 pParse = pWC->pWInfo->pParse;
166725 while( pWhere->op==TK_AND ){
166726 if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
166727 pWhere = pWhere->pRight;
166728 }
166729 if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
166730 for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
166731 Expr *pExpr;
166732 pExpr = pTerm->pExpr;
166733 if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
166734 && ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
@@ -169385,11 +169494,11 @@
169385 break;
169386 }
169387 }
169388 if( hasRightJoin
169389 && ExprHasProperty(pTerm->pExpr, EP_InnerON)
169390 && pTerm->pExpr->w.iJoin==pItem->iCursor
169391 ){
169392 break; /* restriction (5) */
169393 }
169394 }
169395 if( pTerm<pEnd ) continue;
@@ -173846,10 +173955,17 @@
173846 ** Then the "b" IdList records the list "a,b,c".
173847 */
173848 struct TrigEvent { int a; IdList * b; };
173849
173850 struct FrameBound { int eType; Expr *pExpr; };
 
 
 
 
 
 
 
173851
173852 /*
173853 ** Disable lookaside memory allocation for objects that might be
173854 ** shared across database connections.
173855 */
@@ -178214,11 +178330,11 @@
178214 ** that look like this: #1 #2 ... These terms refer to registers
178215 ** in the virtual machine. #N is the N-th register. */
178216 Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/
178217 assert( t.n>=2 );
178218 if( pParse->nested==0 ){
178219 sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
178220 yymsp[0].minor.yy454 = 0;
178221 }else{
178222 yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
178223 if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable);
178224 }
@@ -179062,11 +179178,11 @@
179062 #define TOKEN yyminor
179063 /************ Begin %syntax_error code ****************************************/
179064
179065 UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */
179066 if( TOKEN.z[0] ){
179067 sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
179068 }else{
179069 sqlite3ErrorMsg(pParse, "incomplete input");
179070 }
179071 /************ End %syntax_error code ******************************************/
179072 sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */
@@ -180553,11 +180669,13 @@
180553 }
180554 if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){
180555 if( pParse->zErrMsg==0 ){
180556 pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
180557 }
180558 sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
 
 
180559 nErr++;
180560 }
180561 pParse->zTail = zSql;
180562 #ifndef SQLITE_OMIT_VIRTUALTABLE
180563 sqlite3_free(pParse->apVtabLock);
@@ -185391,10 +185509,11 @@
185391 #ifndef SQLITE_OMIT_WINDOWFUNC
185392 sqlite3ShowWindow(0);
185393 sqlite3ShowWinFunc(0);
185394 #endif
185395 sqlite3ShowSelect(0);
 
185396 }
185397 #endif
185398 break;
185399 }
185400
@@ -194537,14 +194656,15 @@
194537 rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
194538 if( rc==SQLITE_OK ){
194539 Fts3PhraseToken *pToken;
194540
194541 p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
194542 if( !p ) goto no_mem;
194543
194544 zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
194545 if( !zTemp ) goto no_mem;
 
 
 
194546
194547 assert( nToken==ii );
194548 pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
194549 memset(pToken, 0, sizeof(Fts3PhraseToken));
194550
@@ -194555,53 +194675,51 @@
194555 pToken->isPrefix = (iEnd<nInput && zInput[iEnd]=='*');
194556 pToken->bFirst = (iBegin>0 && zInput[iBegin-1]=='^');
194557 nToken = ii+1;
194558 }
194559 }
194560
194561 pModule->xClose(pCursor);
194562 pCursor = 0;
194563 }
194564
194565 if( rc==SQLITE_DONE ){
194566 int jj;
194567 char *zBuf = 0;
194568
194569 p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
194570 if( !p ) goto no_mem;
 
 
 
194571 memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
194572 p->eType = FTSQUERY_PHRASE;
194573 p->pPhrase = (Fts3Phrase *)&p[1];
194574 p->pPhrase->iColumn = pParse->iDefaultCol;
194575 p->pPhrase->nToken = nToken;
194576
194577 zBuf = (char *)&p->pPhrase->aToken[nToken];
 
194578 if( zTemp ){
194579 memcpy(zBuf, zTemp, nTemp);
194580 sqlite3_free(zTemp);
194581 }else{
194582 assert( nTemp==0 );
194583 }
194584
194585 for(jj=0; jj<p->pPhrase->nToken; jj++){
194586 p->pPhrase->aToken[jj].z = zBuf;
194587 zBuf += p->pPhrase->aToken[jj].n;
194588 }
194589 rc = SQLITE_OK;
194590 }
194591
194592 *ppExpr = p;
194593 return rc;
194594 no_mem:
194595
194596 if( pCursor ){
194597 pModule->xClose(pCursor);
194598 }
194599 sqlite3_free(zTemp);
194600 sqlite3_free(p);
194601 *ppExpr = 0;
194602 return SQLITE_NOMEM;
 
 
 
194603 }
194604
194605 /*
194606 ** The output variable *ppExpr is populated with an allocated Fts3Expr
194607 ** structure, or set to 0 if the end of the input buffer is reached.
@@ -226191,10 +226309,12 @@
226191 if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
226192 unsigned char *aPage = sqlite3PagerGetData(pDbPage);
226193 memcpy(aPage, pData, szPage);
226194 pTab->pgnoTrunc = 0;
226195 }
 
 
226196 }
226197 sqlite3PagerUnref(pDbPage);
226198 return rc;
226199
226200 update_fail:
@@ -233154,17 +233274,32 @@
233154 ** This is used to access token iToken of phrase hit iIdx within the
233155 ** current row. If iIdx is less than zero or greater than or equal to the
233156 ** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
233157 ** output variable (*ppToken) is set to point to a buffer containing the
233158 ** matching document token, and (*pnToken) to the size of that buffer in
233159 ** bytes. This API is not available if the specified token matches a
233160 ** prefix query term. In that case both output variables are always set
233161 ** to 0.
233162 **
233163 ** The output text is not a copy of the document text that was tokenized.
233164 ** It is the output of the tokenizer module. For tokendata=1 tables, this
233165 ** includes any embedded 0x00 and trailing data.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233166 **
233167 ** This API can be quite slow if used with an FTS5 table created with the
233168 ** "detail=none" or "detail=column" option.
233169 **
233170 ** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
@@ -233843,11 +233978,12 @@
233843 int nUsermerge; /* 'usermerge' setting */
233844 int nHashSize; /* Bytes of memory for in-memory hash */
233845 char *zRank; /* Name of rank function */
233846 char *zRankArgs; /* Arguments to rank function */
233847 int bSecureDelete; /* 'secure-delete' */
233848 int nDeleteMerge; /* 'deletemerge' */
 
233849
233850 /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
233851 char **pzErrmsg;
233852
233853 #ifdef SQLITE_DEBUG
@@ -234100,11 +234236,18 @@
234100 static int sqlite3Fts5StructureTest(Fts5Index*, void*);
234101
234102 /*
234103 ** Used by xInstToken():
234104 */
234105 static int sqlite3Fts5IterToken(Fts5IndexIter*, i64, int, int, const char**, int*);
 
 
 
 
 
 
 
234106
234107 /*
234108 ** Insert or remove data to or from the index. Each time a document is
234109 ** added to or removed from the index, this function is called one or more
234110 ** times.
@@ -238314,10 +238457,23 @@
238314 if( bVal<0 ){
238315 *pbBadkey = 1;
238316 }else{
238317 pConfig->bSecureDelete = (bVal ? 1 : 0);
238318 }
 
 
 
 
 
 
 
 
 
 
 
 
 
238319 }else{
238320 *pbBadkey = 1;
238321 }
238322 return rc;
238323 }
@@ -241449,11 +241605,11 @@
241449 && memcmp(pT->pTerm, pToken, pT->nQueryTerm)==0
241450 ){
241451 int rc = sqlite3Fts5PoslistWriterAppend(
241452 &pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
241453 );
241454 if( rc==SQLITE_OK && pExpr->pConfig->bTokendata && !pT->bPrefix ){
241455 int iCol = p->iOff>>32;
241456 int iTokOff = p->iOff & 0x7FFFFFFF;
241457 rc = sqlite3Fts5IndexIterWriteTokendata(
241458 pT->pIter, pToken, nToken, iRowid, iCol, iTokOff
241459 );
@@ -241642,19 +241798,18 @@
241642 pPhrase = pExpr->apExprPhrase[iPhrase];
241643 if( iToken<0 || iToken>=pPhrase->nTerm ){
241644 return SQLITE_RANGE;
241645 }
241646 pTerm = &pPhrase->aTerm[iToken];
241647 if( pTerm->bPrefix==0 ){
241648 if( pExpr->pConfig->bTokendata ){
241649 rc = sqlite3Fts5IterToken(
241650 pTerm->pIter, iRowid, iCol, iOff+iToken, ppOut, pnOut
241651 );
241652 }else{
241653 *ppOut = pTerm->pTerm;
241654 *pnOut = pTerm->nFullTerm;
241655 }
241656 }
241657 return rc;
241658 }
241659
241660 /*
@@ -248465,10 +248620,387 @@
248465 fts5BufferFree(&tmp);
248466 memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
248467 *p1 = out;
248468 }
248469
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248470 static void fts5SetupPrefixIter(
248471 Fts5Index *p, /* Index to read from */
248472 int bDesc, /* True for "ORDER BY rowid DESC" */
248473 int iIdx, /* Index to scan for data */
248474 u8 *pToken, /* Buffer containing prefix to match */
@@ -248475,137 +249007,89 @@
248475 int nToken, /* Size of buffer pToken in bytes */
248476 Fts5Colset *pColset, /* Restrict matches to these columns */
248477 Fts5Iter **ppIter /* OUT: New iterator */
248478 ){
248479 Fts5Structure *pStruct;
248480 Fts5Buffer *aBuf;
248481 int nBuf = 32;
248482 int nMerge = 1;
248483
248484 void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
248485 void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
 
 
 
 
 
 
 
 
 
 
 
 
248486 if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
248487 xMerge = fts5MergeRowidLists;
248488 xAppend = fts5AppendRowid;
248489 }else{
248490 nMerge = FTS5_MERGE_NLIST-1;
248491 nBuf = nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
248492 xMerge = fts5MergePrefixLists;
248493 xAppend = fts5AppendPoslist;
248494 }
248495
248496 aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
248497 pStruct = fts5StructureRead(p);
248498 assert( p->rc!=SQLITE_OK || (aBuf && pStruct) );
248499
248500 if( p->rc==SQLITE_OK ){
248501 const int flags = FTS5INDEX_QUERY_SCAN
248502 | FTS5INDEX_QUERY_SKIPEMPTY
248503 | FTS5INDEX_QUERY_NOOUTPUT;
248504 int i;
248505 i64 iLastRowid = 0;
248506 Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
248507 Fts5Data *pData;
248508 Fts5Buffer doclist;
248509 int bNewTerm = 1;
248510
248511 memset(&doclist, 0, sizeof(doclist));
248512
248513 /* If iIdx is non-zero, then it is the number of a prefix-index for
248514 ** prefixes 1 character longer than the prefix being queried for. That
248515 ** index contains all the doclists required, except for the one
248516 ** corresponding to the prefix itself. That one is extracted from the
248517 ** main term index here. */
248518 if( iIdx!=0 ){
248519 int dummy = 0;
248520 const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
248521 pToken[0] = FTS5_MAIN_PREFIX;
248522 fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
248523 fts5IterSetOutputCb(&p->rc, p1);
248524 for(;
248525 fts5MultiIterEof(p, p1)==0;
248526 fts5MultiIterNext2(p, p1, &dummy)
248527 ){
248528 Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
248529 p1->xSetOutputs(p1, pSeg);
248530 if( p1->base.nData ){
248531 xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
248532 iLastRowid = p1->base.iRowid;
248533 }
248534 }
248535 fts5MultiIterFree(p1);
248536 }
248537
248538 pToken[0] = FTS5_MAIN_PREFIX + iIdx;
248539 fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
248540 fts5IterSetOutputCb(&p->rc, p1);
248541
248542 for( /* no-op */ ;
248543 fts5MultiIterEof(p, p1)==0;
248544 fts5MultiIterNext2(p, p1, &bNewTerm)
248545 ){
248546 Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
248547 int nTerm = pSeg->term.n;
248548 const u8 *pTerm = pSeg->term.p;
248549 p1->xSetOutputs(p1, pSeg);
248550
248551 assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
248552 if( bNewTerm ){
248553 if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
248554 }
248555
248556 if( p1->base.nData==0 ) continue;
248557 if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
248558 for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
248559 int i1 = i*nMerge;
248560 int iStore;
248561 assert( i1+nMerge<=nBuf );
248562 for(iStore=i1; iStore<i1+nMerge; iStore++){
248563 if( aBuf[iStore].n==0 ){
248564 fts5BufferSwap(&doclist, &aBuf[iStore]);
248565 fts5BufferZero(&doclist);
248566 break;
248567 }
248568 }
248569 if( iStore==i1+nMerge ){
248570 xMerge(p, &doclist, nMerge, &aBuf[i1]);
248571 for(iStore=i1; iStore<i1+nMerge; iStore++){
248572 fts5BufferZero(&aBuf[iStore]);
248573 }
248574 }
248575 }
248576 iLastRowid = 0;
248577 }
248578
248579 xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
248580 iLastRowid = p1->base.iRowid;
248581 }
248582
248583 assert( (nBuf%nMerge)==0 );
248584 for(i=0; i<nBuf; i+=nMerge){
248585 int iFree;
248586 if( p->rc==SQLITE_OK ){
248587 xMerge(p, &doclist, nMerge, &aBuf[i]);
248588 }
248589 for(iFree=i; iFree<i+nMerge; iFree++){
248590 fts5BufferFree(&aBuf[iFree]);
248591 }
248592 }
248593 fts5MultiIterFree(p1);
248594
248595 pData = fts5IdxMalloc(p, sizeof(*pData)+doclist.n+FTS5_DATA_ZERO_PADDING);
248596 if( pData ){
248597 pData->p = (u8*)&pData[1];
248598 pData->nn = pData->szLeaf = doclist.n;
248599 if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
248600 fts5MultiIterNew2(p, pData, bDesc, ppIter);
248601 }
248602 fts5BufferFree(&doclist);
 
 
 
 
 
248603 }
248604
 
 
248605 fts5StructureRelease(pStruct);
248606 sqlite3_free(aBuf);
248607 }
248608
248609
248610 /*
248611 ** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
@@ -248855,42 +249339,10 @@
248855 static void fts5SegIterSetEOF(Fts5SegIter *pSeg){
248856 fts5DataRelease(pSeg->pLeaf);
248857 pSeg->pLeaf = 0;
248858 }
248859
248860 /*
248861 ** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
248862 ** array of these for each row it visits. Or, for an iterator used by an
248863 ** "ORDER BY rank" query, it accumulates an array of these for the entire
248864 ** query.
248865 **
248866 ** Each instance in the array indicates the iterator (and therefore term)
248867 ** associated with position iPos of rowid iRowid. This is used by the
248868 ** xInstToken() API.
248869 */
248870 struct Fts5TokenDataMap {
248871 i64 iRowid; /* Row this token is located in */
248872 i64 iPos; /* Position of token */
248873 int iIter; /* Iterator token was read from */
248874 };
248875
248876 /*
248877 ** An object used to supplement Fts5Iter for tokendata=1 iterators.
248878 */
248879 struct Fts5TokenDataIter {
248880 int nIter;
248881 int nIterAlloc;
248882
248883 int nMap;
248884 int nMapAlloc;
248885 Fts5TokenDataMap *aMap;
248886
248887 Fts5PoslistReader *aPoslistReader;
248888 int *aPoslistToIter;
248889 Fts5Iter *apIter[1];
248890 };
248891
248892 /*
248893 ** This function appends iterator pAppend to Fts5TokenDataIter pIn and
248894 ** returns the result.
248895 */
248896 static Fts5TokenDataIter *fts5AppendTokendataIter(
@@ -248923,58 +249375,10 @@
248923 assert( pRet==0 || pRet->nIter<=pRet->nIterAlloc );
248924
248925 return pRet;
248926 }
248927
248928 /*
248929 ** Delete an Fts5TokenDataIter structure and its contents.
248930 */
248931 static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
248932 if( pSet ){
248933 int ii;
248934 for(ii=0; ii<pSet->nIter; ii++){
248935 fts5MultiIterFree(pSet->apIter[ii]);
248936 }
248937 sqlite3_free(pSet->aPoslistReader);
248938 sqlite3_free(pSet->aMap);
248939 sqlite3_free(pSet);
248940 }
248941 }
248942
248943 /*
248944 ** Append a mapping to the token-map belonging to object pT.
248945 */
248946 static void fts5TokendataIterAppendMap(
248947 Fts5Index *p,
248948 Fts5TokenDataIter *pT,
248949 int iIter,
248950 i64 iRowid,
248951 i64 iPos
248952 ){
248953 if( p->rc==SQLITE_OK ){
248954 if( pT->nMap==pT->nMapAlloc ){
248955 int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
248956 int nByte = nNew * sizeof(Fts5TokenDataMap);
248957 Fts5TokenDataMap *aNew;
248958
248959 aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nByte);
248960 if( aNew==0 ){
248961 p->rc = SQLITE_NOMEM;
248962 return;
248963 }
248964
248965 pT->aMap = aNew;
248966 pT->nMapAlloc = nNew;
248967 }
248968
248969 pT->aMap[pT->nMap].iRowid = iRowid;
248970 pT->aMap[pT->nMap].iPos = iPos;
248971 pT->aMap[pT->nMap].iIter = iIter;
248972 pT->nMap++;
248973 }
248974 }
248975
248976 /*
248977 ** The iterator passed as the only argument must be a tokendata=1 iterator
248978 ** (pIter->pTokenDataIter!=0). This function sets the iterator output
248979 ** variables (pIter->base.*) according to the contents of the current
248980 ** row.
@@ -249011,11 +249415,11 @@
249011 int eDetail = pIter->pIndex->pConfig->eDetail;
249012 pIter->base.bEof = 0;
249013 pIter->base.iRowid = iRowid;
249014
249015 if( nHit==1 && eDetail==FTS5_DETAIL_FULL ){
249016 fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, iRowid, -1);
249017 }else
249018 if( nHit>1 && eDetail!=FTS5_DETAIL_NONE ){
249019 int nReader = 0;
249020 int nByte = 0;
249021 i64 iPrev = 0;
@@ -249264,10 +249668,11 @@
249264
249265 if( p->rc==SQLITE_OK ){
249266 pRet = fts5MultiIterAlloc(p, 0);
249267 }
249268 if( pRet ){
 
249269 pRet->pTokenDataIter = pSet;
249270 if( pSet ){
249271 fts5IterSetOutputsTokendata(pRet);
249272 }else{
249273 pRet->base.bEof = 1;
@@ -249278,11 +249683,10 @@
249278
249279 fts5StructureRelease(pStruct);
249280 fts5BufferFree(&bSeek);
249281 return pRet;
249282 }
249283
249284
249285 /*
249286 ** Open a new iterator to iterate though all rowid that match the
249287 ** specified token or token prefix.
249288 */
@@ -249304,10 +249708,15 @@
249304 int iIdx = 0; /* Index to search */
249305 int iPrefixIdx = 0; /* +1 prefix index */
249306 int bTokendata = pConfig->bTokendata;
249307 if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
249308
 
 
 
 
 
249309 if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){
249310 bTokendata = 0;
249311 }
249312
249313 /* Figure out which index to search and set iIdx accordingly. If this
@@ -249334,11 +249743,11 @@
249334 if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
249335 }
249336 }
249337
249338 if( bTokendata && iIdx==0 ){
249339 buf.p[0] = '0';
249340 pRet = fts5SetupTokendataIter(p, buf.p, nToken+1, pColset);
249341 }else if( iIdx<=pConfig->nPrefix ){
249342 /* Straight index lookup */
249343 Fts5Structure *pStruct = fts5StructureRead(p);
249344 buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
@@ -249347,11 +249756,11 @@
249347 pColset, buf.p, nToken+1, -1, 0, &pRet
249348 );
249349 fts5StructureRelease(pStruct);
249350 }
249351 }else{
249352 /* Scan multiple terms in the main index */
249353 int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
249354 fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
249355 if( pRet==0 ){
249356 assert( p->rc!=SQLITE_OK );
249357 }else{
@@ -249383,11 +249792,12 @@
249383 ** Move to the next matching rowid.
249384 */
249385 static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
249386 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249387 assert( pIter->pIndex->rc==SQLITE_OK );
249388 if( pIter->pTokenDataIter ){
 
249389 fts5TokendataIterNext(pIter, 0, 0);
249390 }else{
249391 fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
249392 }
249393 return fts5IndexReturn(pIter->pIndex);
@@ -249420,11 +249830,12 @@
249420 ** definition of "at or after" depends on whether this iterator iterates
249421 ** in ascending or descending rowid order.
249422 */
249423 static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
249424 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249425 if( pIter->pTokenDataIter ){
 
249426 fts5TokendataIterNext(pIter, 1, iMatch);
249427 }else{
249428 fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
249429 }
249430 return fts5IndexReturn(pIter->pIndex);
@@ -249438,32 +249849,87 @@
249438 const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
249439 assert_nc( z || n<=1 );
249440 *pn = n-1;
249441 return (z ? &z[1] : 0);
249442 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249443
249444 /*
249445 ** This is used by xInstToken() to access the token at offset iOff, column
249446 ** iCol of row iRowid. The token is returned via output variables *ppOut
249447 ** and *pnOut. The iterator passed as the first argument must be a tokendata=1
249448 ** iterator (pIter->pTokenDataIter!=0).
 
 
249449 */
249450 static int sqlite3Fts5IterToken(
249451 Fts5IndexIter *pIndexIter,
 
249452 i64 iRowid,
249453 int iCol,
249454 int iOff,
249455 const char **ppOut, int *pnOut
249456 ){
249457 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249458 Fts5TokenDataIter *pT = pIter->pTokenDataIter;
249459 Fts5TokenDataMap *aMap = pT->aMap;
249460 i64 iPos = (((i64)iCol)<<32) + iOff;
249461
249462 int i1 = 0;
249463 int i2 = pT->nMap;
249464 int iTest = 0;
 
 
 
 
 
 
 
 
 
 
249465
249466 while( i2>i1 ){
249467 iTest = (i1 + i2) / 2;
249468
249469 if( aMap[iTest].iRowid<iRowid ){
@@ -249483,13 +249949,19 @@
249483 }
249484 }
249485 }
249486
249487 if( i2>i1 ){
249488 Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
249489 *ppOut = (const char*)pMap->aSeg[0].term.p+1;
249490 *pnOut = pMap->aSeg[0].term.n-1;
 
 
 
 
 
 
249491 }
249492
249493 return SQLITE_OK;
249494 }
249495
@@ -249497,11 +249969,13 @@
249497 ** Clear any existing entries from the token-map associated with the
249498 ** iterator passed as the only argument.
249499 */
249500 static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){
249501 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249502 if( pIter && pIter->pTokenDataIter ){
 
 
249503 pIter->pTokenDataIter->nMap = 0;
249504 }
249505 }
249506
249507 /*
@@ -249517,21 +249991,33 @@
249517 i64 iRowid, int iCol, int iOff
249518 ){
249519 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249520 Fts5TokenDataIter *pT = pIter->pTokenDataIter;
249521 Fts5Index *p = pIter->pIndex;
249522 int ii;
249523
249524 assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
249525 assert( pIter->pTokenDataIter );
249526
249527 for(ii=0; ii<pT->nIter; ii++){
249528 Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
249529 if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
249530 }
249531 if( ii<pT->nIter ){
249532 fts5TokendataIterAppendMap(p, pT, ii, iRowid, (((i64)iCol)<<32) + iOff);
 
 
 
 
 
 
 
 
 
 
 
 
249533 }
249534 return fts5IndexReturn(p);
249535 }
249536
249537 /*
@@ -251432,10 +251918,11 @@
251432 ** containing a copy of the header from an Fts5Config pointer.
251433 */
251434 #define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
251435 #define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
251436
 
251437
251438 /*
251439 ** Each auxiliary function registered with the FTS5 module is represented
251440 ** by an object of the following type. All such objects are stored as part
251441 ** of the Fts5Global.pAux list.
@@ -252757,10 +253244,11 @@
252757 sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
252758 sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
252759 sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
252760 int iCol; /* Column on LHS of MATCH operator */
252761 char **pzErrmsg = pConfig->pzErrmsg;
 
252762 int i;
252763 int iIdxStr = 0;
252764 Fts5Expr *pExpr = 0;
252765
252766 assert( pConfig->bLock==0 );
@@ -252792,10 +253280,13 @@
252792 int bInternal = 0;
252793
252794 rc = fts5ExtractExprText(pConfig, apVal[i], &zText, &bFreeAndReset);
252795 if( rc!=SQLITE_OK ) goto filter_out;
252796 if( zText==0 ) zText = "";
 
 
 
252797
252798 iCol = 0;
252799 do{
252800 iCol = iCol*10 + (idxStr[iIdxStr]-'0');
252801 iIdxStr++;
@@ -252932,10 +253423,11 @@
252932 }
252933
252934 filter_out:
252935 sqlite3Fts5ExprFree(pExpr);
252936 pConfig->pzErrmsg = pzErrmsg;
 
252937 return rc;
252938 }
252939
252940 /*
252941 ** This is the xEof method of the virtual table. SQLite calls this
@@ -254927,11 +255419,11 @@
254927 int nArg, /* Number of args */
254928 sqlite3_value **apUnused /* Function arguments */
254929 ){
254930 assert( nArg==0 );
254931 UNUSED_PARAM2(nArg, apUnused);
254932 sqlite3_result_text(pCtx, "fts5: 2024-11-14 19:34:28 81202d2ab5963fdcf20555b6d0b31cc955ac27f1cd87656faea5c0611c9a2ee8", -1, SQLITE_TRANSIENT);
254933 }
254934
254935 /*
254936 ** Implementation of fts5_locale(LOCALE, TEXT) function.
254937 **
@@ -254990,10 +255482,24 @@
254990 assert( &pCsr[nText]==&pBlob[nBlob] );
254991
254992 sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);
254993 }
254994 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254995
254996 /*
254997 ** Return true if zName is the extension on one of the shadow tables used
254998 ** by this module.
254999 */
@@ -255120,13 +255626,20 @@
255120 );
255121 }
255122 if( rc==SQLITE_OK ){
255123 rc = sqlite3_create_function(
255124 db, "fts5_locale", 2,
255125 SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
255126 p, fts5LocaleFunc, 0, 0
255127 );
 
 
 
 
 
 
 
255128 }
255129 }
255130
255131 /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
255132 ** fts5_test_mi.c is compiled and linked into the executable. And call
@@ -258048,11 +258561,11 @@
258048 int rc = SQLITE_OK;
258049 char aBuf[32];
258050 char *zOut = aBuf;
258051 int ii;
258052 const unsigned char *zIn = (const unsigned char*)pText;
258053 const unsigned char *zEof = &zIn[nText];
258054 u32 iCode = 0;
258055 int aStart[3]; /* Input offset of each character in aBuf[] */
258056
258057 UNUSED_PARAM(unusedFlags);
258058
258059
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** e2bae4143afd07de1ae55a6d2606a3b541a5 with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -465,11 +465,11 @@
465 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
466 ** [sqlite_version()] and [sqlite_source_id()].
467 */
468 #define SQLITE_VERSION "3.48.0"
469 #define SQLITE_VERSION_NUMBER 3048000
470 #define SQLITE_SOURCE_ID "2024-12-09 20:46:36 e2bae4143afd07de1ae55a6d2606a3b541a5b94568aa41f6a96e5d1245471653"
471
472 /*
473 ** CAPI3REF: Run-Time Library Version Numbers
474 ** KEYWORDS: sqlite3_version sqlite3_sourceid
475 **
@@ -4521,15 +4521,26 @@
4521 **
4522 ** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
4523 ** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
4524 ** to return an error (error code SQLITE_ERROR) if the statement uses
4525 ** any virtual tables.
4526 **
4527 ** [[SQLITE_PREPARE_DONT_LOG]] <dt>SQLITE_PREPARE_DONT_LOG</dt>
4528 ** <dd>The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler
4529 ** errors from being sent to the error log defined by
4530 ** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test
4531 ** compiles to see if some SQL syntax is well-formed, without generating
4532 ** messages on the global error log when it is not. If the test compile
4533 ** fails, the sqlite3_prepare_v3() call returns the same error indications
4534 ** with or without this flag; it just omits the call to [sqlite3_log()] that
4535 ** logs the error.
4536 ** </dl>
4537 */
4538 #define SQLITE_PREPARE_PERSISTENT 0x01
4539 #define SQLITE_PREPARE_NORMALIZE 0x02
4540 #define SQLITE_PREPARE_NO_VTAB 0x04
4541 #define SQLITE_PREPARE_DONT_LOG 0x10
4542
4543 /*
4544 ** CAPI3REF: Compiling An SQL Statement
4545 ** KEYWORDS: {SQL statement compiler}
4546 ** METHOD: sqlite3
@@ -13467,17 +13478,32 @@
13478 ** This is used to access token iToken of phrase hit iIdx within the
13479 ** current row. If iIdx is less than zero or greater than or equal to the
13480 ** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
13481 ** output variable (*ppToken) is set to point to a buffer containing the
13482 ** matching document token, and (*pnToken) to the size of that buffer in
13483 ** bytes.
 
 
13484 **
13485 ** The output text is not a copy of the document text that was tokenized.
13486 ** It is the output of the tokenizer module. For tokendata=1 tables, this
13487 ** includes any embedded 0x00 and trailing data.
13488 **
13489 ** This API may be slow in some cases if the token identified by parameters
13490 ** iIdx and iToken matched a prefix token in the query. In most cases, the
13491 ** first call to this API for each prefix token in the query is forced
13492 ** to scan the portion of the full-text index that matches the prefix
13493 ** token to collect the extra data required by this API. If the prefix
13494 ** token matches a large number of token instances in the document set,
13495 ** this may be a performance problem.
13496 **
13497 ** If the user knows in advance that a query may use this API for a
13498 ** prefix token, FTS5 may be configured to collect all required data as part
13499 ** of the initial querying of the full-text index, avoiding the second scan
13500 ** entirely. This also causes prefix queries that do not use this API to
13501 ** run more slowly and use more memory. FTS5 may be configured in this way
13502 ** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
13503 ** option, or on a per-query basis using the
13504 ** [fts5_insttoken | fts5_insttoken()] user function.
13505 **
13506 ** This API can be quite slow if used with an FTS5 table created with the
13507 ** "detail=none" or "detail=column" option.
13508 **
13509 ** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
@@ -17049,11 +17075,11 @@
17075
17076 /*
17077 ** Additional non-public SQLITE_PREPARE_* flags
17078 */
17079 #define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
17080 #define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
17081
17082 /*
17083 ** Prototypes for the VDBE interface. See comments on the implementation
17084 ** for a description of what each of these routines does.
17085 */
@@ -32279,10 +32305,11 @@
32305 && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
32306 ){
32307 pExpr = pExpr->pLeft;
32308 }
32309 if( pExpr==0 ) return;
32310 if( ExprHasProperty(pExpr, EP_FromDDL) ) return;
32311 db->errByteOffset = pExpr->w.iOfst;
32312 }
32313
32314 /*
32315 ** Enlarge the memory allocation on a StrAccum object so that it is
@@ -33008,11 +33035,11 @@
33035 }
33036 if( pItem->fg.isCte ){
33037 sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
33038 }
33039 if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
33040 sqlite3_str_appendf(&x, " isOn");
33041 }
33042 if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
33043 if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
33044 if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
33045 if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
@@ -34092,10 +34119,14 @@
34119 **
34120 ** This routines are given external linkage so that they will always be
34121 ** accessible to the debugging, and to avoid warnings about unused
34122 ** functions. But these routines only exist in debugging builds, so they
34123 ** do not contaminate the interface.
34124 **
34125 ** See Also:
34126 **
34127 ** sqlite3ShowWhereTerm() in where.c
34128 */
34129 SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
34130 SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
34131 SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
34132 SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
@@ -35668,12 +35699,12 @@
35699 int esign = 1; /* sign of exponent */
35700 int e = 0; /* exponent */
35701 int eValid = 1; /* True exponent is either not used or is well-formed */
35702 int nDigit = 0; /* Number of digits processed */
35703 int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
35704 u64 s2; /* round-tripped significand */
35705 double rr[2];
 
35706
35707 assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
35708 *pResult = 0.0; /* Default return value, in case of an error */
35709 if( length==0 ) return 0;
35710
@@ -35772,25 +35803,36 @@
35803
35804 /* adjust exponent by d, and update sign */
35805 e = (e*esign) + d;
35806
35807 /* Try to adjust the exponent to make it smaller */
35808 while( e>0 && s<((LARGEST_UINT64-0x7ff)/10) ){
35809 s *= 10;
35810 e--;
35811 }
35812 while( e<0 && (s%10)==0 ){
35813 s /= 10;
35814 e++;
35815 }
35816
35817 rr[0] = (double)s;
35818 assert( sizeof(s2)==sizeof(rr[0]) );
35819 #ifdef SQLITE_DEBUG
35820 rr[1] = 18446744073709549568.0;
35821 memcpy(&s2, &rr[1], sizeof(s2));
35822 assert( s2==0x43efffffffffffffLL );
35823 #endif
35824 /* Largest double that can be safely converted to u64
35825 ** vvvvvvvvvvvvvvvvvvvvvv */
35826 if( rr[0]<=18446744073709549568.0 ){
35827 s2 = (u64)rr[0];
35828 rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
35829 }else{
35830 rr[1] = 0.0;
35831 }
35832 assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */
35833
35834 if( e>0 ){
35835 while( e>=100 ){
35836 e -= 100;
35837 dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
35838 }
@@ -51771,11 +51813,11 @@
51813 */
51814 char *zTmpname = 0; /* For temporary filename, if necessary. */
51815
51816 int rc = SQLITE_OK; /* Function Return Code */
51817 #if !defined(NDEBUG) || SQLITE_OS_WINCE
51818 int eType = flags&0x0FFF00; /* Type of file to open */
51819 #endif
51820
51821 int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
51822 int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
51823 int isCreate = (flags & SQLITE_OPEN_CREATE);
@@ -112021,11 +112063,11 @@
112063 **
112064 ** (4) If pSrc is the right operand of a LEFT JOIN, then...
112065 ** (4a) pExpr must come from an ON clause..
112066 ** (4b) and specifically the ON clause associated with the LEFT JOIN.
112067 **
112068 ** (5) If pSrc is the right operand of a LEFT JOIN or the left
112069 ** operand of a RIGHT JOIN, then pExpr must be from the WHERE
112070 ** clause, not an ON clause.
112071 **
112072 ** (6) Either:
112073 **
@@ -115555,35 +115597,41 @@
115597 **
115598 ** Additionally, if pExpr is a simple SQL value and the value is the
115599 ** same as that currently bound to variable pVar, non-zero is returned.
115600 ** Otherwise, if the values are not the same or if pExpr is not a simple
115601 ** SQL value, zero is returned.
115602 **
115603 ** If the SQLITE_EnableQPSG flag is set on the database connection, then
115604 ** this routine always returns false.
115605 */
115606 static SQLITE_NOINLINE int exprCompareVariable(
115607 const Parse *pParse,
115608 const Expr *pVar,
115609 const Expr *pExpr
115610 ){
115611 int res = 2;
115612 int iVar;
115613 sqlite3_value *pL, *pR = 0;
115614
115615 if( pExpr->op==TK_VARIABLE && pVar->iColumn==pExpr->iColumn ){
115616 return 0;
115617 }
115618 if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) return 2;
115619 sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
115620 if( pR ){
115621 iVar = pVar->iColumn;
115622 sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
115623 pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
115624 if( pL ){
115625 if( sqlite3_value_type(pL)==SQLITE_TEXT ){
115626 sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
115627 }
115628 res = sqlite3MemCompare(pL, pR, 0) ? 2 : 0;
115629 }
115630 sqlite3ValueFree(pR);
115631 sqlite3ValueFree(pL);
115632 }
 
115633 return res;
115634 }
115635
115636 /*
115637 ** Do a deep comparison of two expression trees. Return 0 if the two
@@ -115605,16 +115653,14 @@
115653 ** can be sure the expressions are the same. In the places where
115654 ** this routine is used, it does not hurt to get an extra 2 - that
115655 ** just might result in some slightly slower code. But returning
115656 ** an incorrect 0 or 1 could lead to a malfunction.
115657 **
115658 ** If pParse is not NULL and SQLITE_EnableQPSG is off then TK_VARIABLE
115659 ** terms in pA with bindings in pParse->pReprepare can be matched against
115660 ** literals in pB. The pParse->pVdbe->expmask bitmask is updated for
115661 ** each variable referenced.
 
 
115662 */
115663 SQLITE_PRIVATE int sqlite3ExprCompare(
115664 const Parse *pParse,
115665 const Expr *pA,
115666 const Expr *pB,
@@ -115622,12 +115668,12 @@
115668 ){
115669 u32 combinedFlags;
115670 if( pA==0 || pB==0 ){
115671 return pB==pA ? 0 : 2;
115672 }
115673 if( pParse && pA->op==TK_VARIABLE ){
115674 return exprCompareVariable(pParse, pA, pB);
115675 }
115676 combinedFlags = pA->flags | pB->flags;
115677 if( combinedFlags & EP_IntValue ){
115678 if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
115679 return 0;
@@ -115817,23 +115863,75 @@
115863 return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
115864 }
115865 }
115866 return 0;
115867 }
115868
115869 /*
115870 ** Return true if the boolean value of the expression is always either
115871 ** FALSE or NULL.
115872 */
115873 static int sqlite3ExprIsNotTrue(Expr *pExpr){
115874 int v;
115875 if( pExpr->op==TK_NULL ) return 1;
115876 if( pExpr->op==TK_TRUEFALSE && sqlite3ExprTruthValue(pExpr)==0 ) return 1;
115877 v = 1;
115878 if( sqlite3ExprIsInteger(pExpr, &v, 0) && v==0 ) return 1;
115879 return 0;
115880 }
115881
115882 /*
115883 ** Return true if the expression is one of the following:
115884 **
115885 ** CASE WHEN x THEN y END
115886 ** CASE WHEN x THEN y ELSE NULL END
115887 ** CASE WHEN x THEN y ELSE false END
115888 ** iif(x,y)
115889 ** iif(x,y,NULL)
115890 ** iif(x,y,false)
115891 */
115892 static int sqlite3ExprIsIIF(sqlite3 *db, const Expr *pExpr){
115893 ExprList *pList;
115894 if( pExpr->op==TK_FUNCTION ){
115895 const char *z = pExpr->u.zToken;
115896 FuncDef *pDef;
115897 if( (z[0]!='i' && z[0]!='I') ) return 0;
115898 if( pExpr->x.pList==0 ) return 0;
115899 pDef = sqlite3FindFunction(db, z, pExpr->x.pList->nExpr, ENC(db), 0);
115900 #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
115901 if( pDef==0 ) return 0;
115902 #else
115903 if( NEVER(pDef==0) ) return 0;
115904 #endif
115905 if( (pDef->funcFlags & SQLITE_FUNC_INLINE)==0 ) return 0;
115906 if( SQLITE_PTR_TO_INT(pDef->pUserData)!=INLINEFUNC_iif ) return 0;
115907 }else if( pExpr->op==TK_CASE ){
115908 if( pExpr->pLeft!=0 ) return 0;
115909 }else{
115910 return 0;
115911 }
115912 pList = pExpr->x.pList;
115913 assert( pList!=0 );
115914 if( pList->nExpr==2 ) return 1;
115915 if( pList->nExpr==3 && sqlite3ExprIsNotTrue(pList->a[2].pExpr) ) return 1;
115916 return 0;
115917 }
115918
115919 /*
115920 ** Return true if we can prove the pE2 will always be true if pE1 is
115921 ** true. Return false if we cannot complete the proof or if pE2 might
115922 ** be false. Examples:
115923 **
115924 ** pE1: x==5 pE2: x==5 Result: true
115925 ** pE1: x>0 pE2: x==5 Result: false
115926 ** pE1: x=21 pE2: x=21 OR y=43 Result: true
115927 ** pE1: x!=123 pE2: x IS NOT NULL Result: true
115928 ** pE1: x!=?1 pE2: x IS NOT NULL Result: true
115929 ** pE1: x IS NULL pE2: x IS NOT NULL Result: false
115930 ** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
115931 ** pE1: iif(x,y) pE2: x Result: true
115932 ** PE1: iif(x,y,0) pE2: x Result: true
115933 **
115934 ** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
115935 ** Expr.iTable<0 then assume a table number given by iTab.
115936 **
115937 ** If pParse is not NULL, then the values of bound variables in pE1 are
@@ -115863,10 +115961,13 @@
115961 if( pE2->op==TK_NOTNULL
115962 && exprImpliesNotNull(pParse, pE1, pE2->pLeft, iTab, 0)
115963 ){
115964 return 1;
115965 }
115966 if( sqlite3ExprIsIIF(pParse->db, pE1) ){
115967 return sqlite3ExprImpliesExpr(pParse,pE1->x.pList->a[0].pExpr,pE2,iTab);
115968 }
115969 return 0;
115970 }
115971
115972 /* This is a helper function to impliesNotNullRow(). In this routine,
115973 ** set pWalker->eCode to one only if *both* of the input expressions
@@ -132082,11 +132183,14 @@
132183 MFUNCTION(degrees, 1, radToDeg, math1Func ),
132184 MFUNCTION(pi, 0, 0, piFunc ),
132185 #endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
132186 FUNCTION(sign, 1, 0, 0, signFunc ),
132187 INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
132188 INLINE_FUNC(iif, 2, INLINEFUNC_iif, 0 ),
132189 INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
132190 INLINE_FUNC(if, 2, INLINEFUNC_iif, 0 ),
132191 INLINE_FUNC(if, 3, INLINEFUNC_iif, 0 ),
132192 };
132193 #ifndef SQLITE_OMIT_ALTERTABLE
132194 sqlite3AlterFunctions();
132195 #endif
132196 sqlite3WindowFunctions();
@@ -140730,11 +140834,12 @@
140834 pTab = sqliteHashData(k);
140835 if( pTab->nCol==0 ){
140836 char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
140837 if( zSql ){
140838 sqlite3_stmt *pDummy = 0;
140839 (void)sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_DONT_LOG,
140840 &pDummy, 0);
140841 (void)sqlite3_finalize(pDummy);
140842 sqlite3DbFree(db, zSql);
140843 }
140844 if( db->mallocFailed ){
140845 sqlite3ErrorMsg(db->pParse, "out of memory");
@@ -147529,36 +147634,36 @@
147634 return pExpr;
147635 }
147636 if( pSubst->isOuterJoin ){
147637 ExprSetProperty(pNew, EP_CanBeNull);
147638 }
147639 if( pNew->op==TK_TRUEFALSE ){
147640 pNew->u.iValue = sqlite3ExprTruthValue(pNew);
147641 pNew->op = TK_INTEGER;
147642 ExprSetProperty(pNew, EP_IntValue);
147643 }
147644
147645 /* Ensure that the expression now has an implicit collation sequence,
147646 ** just as it did when it was a column of a view or sub-query. */
147647 {
147648 CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pNew);
147649 CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
147650 pSubst->pCList->a[iColumn].pExpr
147651 );
147652 if( pNat!=pColl || (pNew->op!=TK_COLUMN && pNew->op!=TK_COLLATE) ){
147653 pNew = sqlite3ExprAddCollateString(pSubst->pParse, pNew,
147654 (pColl ? pColl->zName : "BINARY")
147655 );
147656 }
147657 }
147658 ExprClearProperty(pNew, EP_Collate);
147659 if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
147660 sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
147661 pExpr->flags & (EP_OuterON|EP_InnerON));
147662 }
147663 sqlite3ExprDelete(db, pExpr);
147664 pExpr = pNew;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147665 }
147666 }
147667 }else{
147668 if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
147669 pExpr->iTable = pSubst->iNewTable;
@@ -148291,20 +148396,20 @@
148396 }
148397
148398 /* Transfer the FROM clause terms from the subquery into the
148399 ** outer query.
148400 */
148401 iNewParent = pSubSrc->a[0].iCursor;
148402 for(i=0; i<nSubSrc; i++){
148403 SrcItem *pItem = &pSrc->a[i+iFrom];
148404 assert( pItem->fg.isTabFunc==0 );
148405 assert( pItem->fg.isSubquery
148406 || pItem->fg.fixedSchema
148407 || pItem->u4.zDatabase==0 );
148408 if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
148409 *pItem = pSubSrc->a[i];
148410 pItem->fg.jointype |= ltorj;
 
148411 memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
148412 }
148413 pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
148414 pSrc->a[iFrom].fg.jointype |= jointype | ltorj;
148415
@@ -148340,10 +148445,11 @@
148445 pSub->pOrderBy = 0;
148446 }
148447 pWhere = pSub->pWhere;
148448 pSub->pWhere = 0;
148449 if( isOuterJoin>0 ){
148450 assert( pSubSrc->nSrc==1 );
148451 sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
148452 }
148453 if( pWhere ){
148454 if( pParent->pWhere ){
148455 pParent->pWhere = sqlite3PExpr(pParse, TK_AND, pWhere, pParent->pWhere);
@@ -151439,11 +151545,11 @@
151545 sqlite3TreeViewSelect(0, p, 0);
151546 }
151547 #endif
151548 assert( pSubq->pSelect && (pSub->selFlags & SF_PushDown)!=0 );
151549 }else{
151550 TREETRACE(0x4000,pParse,p,("WHERE-clause push-down not possible\n"));
151551 }
151552
151553 /* Convert unused result columns of the subquery into simple NULL
151554 ** expressions, to avoid unneeded searching and computation.
151555 ** tag-select-0440
@@ -158930,10 +159036,11 @@
159036 if( pOrigLhs ){
159037 sqlite3ExprListDelete(db, pOrigLhs);
159038 pNew->pLeft->x.pList = pLhs;
159039 }
159040 pSelect->pEList = pRhs;
159041 pSelect->selId = ++pParse->nSelect; /* Req'd for SubrtnSig validity */
159042 if( pLhs && pLhs->nExpr==1 ){
159043 /* Take care here not to generate a TK_VECTOR containing only a
159044 ** single value. Since the parser never creates such a vector, some
159045 ** of the subroutines do not handle this case. */
159046 Expr *p = pLhs->a[0].pExpr;
@@ -164002,11 +164109,11 @@
164109 || pTerm->pExpr->w.iJoin != pSrc->iCursor
164110 ){
164111 return 0;
164112 }
164113 if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0
164114 && NEVER(ExprHasProperty(pTerm->pExpr, EP_InnerON))
164115 ){
164116 return 0;
164117 }
164118 return 1;
164119 }
@@ -165495,11 +165602,11 @@
165602 return rc;
165603 }
165604 #endif /* SQLITE_ENABLE_STAT4 */
165605
165606
165607 #if defined(WHERETRACE_ENABLED) || defined(SQLITE_DEBUG)
165608 /*
165609 ** Print the content of a WhereTerm object
165610 */
165611 SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
165612 if( pTerm==0 ){
@@ -165538,10 +165645,13 @@
165645 sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
165646 }
165647 sqlite3DebugPrintf("\n");
165648 sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
165649 }
165650 }
165651 SQLITE_PRIVATE void sqlite3ShowWhereTerm(WhereTerm *pTerm){
165652 sqlite3WhereTermPrint(pTerm, 0);
165653 }
165654 #endif
165655
165656 #ifdef WHERETRACE_ENABLED
165657 /*
@@ -166724,11 +166834,10 @@
166834 pParse = pWC->pWInfo->pParse;
166835 while( pWhere->op==TK_AND ){
166836 if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
166837 pWhere = pWhere->pRight;
166838 }
 
166839 for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
166840 Expr *pExpr;
166841 pExpr = pTerm->pExpr;
166842 if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
166843 && ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
@@ -169385,11 +169494,11 @@
169494 break;
169495 }
169496 }
169497 if( hasRightJoin
169498 && ExprHasProperty(pTerm->pExpr, EP_InnerON)
169499 && NEVER(pTerm->pExpr->w.iJoin==pItem->iCursor)
169500 ){
169501 break; /* restriction (5) */
169502 }
169503 }
169504 if( pTerm<pEnd ) continue;
@@ -173846,10 +173955,17 @@
173955 ** Then the "b" IdList records the list "a,b,c".
173956 */
173957 struct TrigEvent { int a; IdList * b; };
173958
173959 struct FrameBound { int eType; Expr *pExpr; };
173960
173961 /*
173962 ** Generate a syntax error
173963 */
173964 static void parserSyntaxError(Parse *pParse, Token *p){
173965 sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", p);
173966 }
173967
173968 /*
173969 ** Disable lookaside memory allocation for objects that might be
173970 ** shared across database connections.
173971 */
@@ -178214,11 +178330,11 @@
178330 ** that look like this: #1 #2 ... These terms refer to registers
178331 ** in the virtual machine. #N is the N-th register. */
178332 Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/
178333 assert( t.n>=2 );
178334 if( pParse->nested==0 ){
178335 parserSyntaxError(pParse, &t);
178336 yymsp[0].minor.yy454 = 0;
178337 }else{
178338 yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
178339 if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable);
178340 }
@@ -179062,11 +179178,11 @@
179178 #define TOKEN yyminor
179179 /************ Begin %syntax_error code ****************************************/
179180
179181 UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */
179182 if( TOKEN.z[0] ){
179183 parserSyntaxError(pParse, &TOKEN);
179184 }else{
179185 sqlite3ErrorMsg(pParse, "incomplete input");
179186 }
179187 /************ End %syntax_error code ******************************************/
179188 sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */
@@ -180553,11 +180669,13 @@
180669 }
180670 if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){
180671 if( pParse->zErrMsg==0 ){
180672 pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
180673 }
180674 if( (pParse->prepFlags & SQLITE_PREPARE_DONT_LOG)==0 ){
180675 sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
180676 }
180677 nErr++;
180678 }
180679 pParse->zTail = zSql;
180680 #ifndef SQLITE_OMIT_VIRTUALTABLE
180681 sqlite3_free(pParse->apVtabLock);
@@ -185391,10 +185509,11 @@
185509 #ifndef SQLITE_OMIT_WINDOWFUNC
185510 sqlite3ShowWindow(0);
185511 sqlite3ShowWinFunc(0);
185512 #endif
185513 sqlite3ShowSelect(0);
185514 sqlite3ShowWhereTerm(0);
185515 }
185516 #endif
185517 break;
185518 }
185519
@@ -194537,14 +194656,15 @@
194656 rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
194657 if( rc==SQLITE_OK ){
194658 Fts3PhraseToken *pToken;
194659
194660 p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
 
 
194661 zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
194662 if( !zTemp || !p ){
194663 rc = SQLITE_NOMEM;
194664 goto getnextstring_out;
194665 }
194666
194667 assert( nToken==ii );
194668 pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
194669 memset(pToken, 0, sizeof(Fts3PhraseToken));
194670
@@ -194555,53 +194675,51 @@
194675 pToken->isPrefix = (iEnd<nInput && zInput[iEnd]=='*');
194676 pToken->bFirst = (iBegin>0 && zInput[iBegin-1]=='^');
194677 nToken = ii+1;
194678 }
194679 }
 
 
 
194680 }
194681
194682 if( rc==SQLITE_DONE ){
194683 int jj;
194684 char *zBuf = 0;
194685
194686 p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
194687 if( !p ){
194688 rc = SQLITE_NOMEM;
194689 goto getnextstring_out;
194690 }
194691 memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
194692 p->eType = FTSQUERY_PHRASE;
194693 p->pPhrase = (Fts3Phrase *)&p[1];
194694 p->pPhrase->iColumn = pParse->iDefaultCol;
194695 p->pPhrase->nToken = nToken;
194696
194697 zBuf = (char *)&p->pPhrase->aToken[nToken];
194698 assert( nTemp==0 || zTemp );
194699 if( zTemp ){
194700 memcpy(zBuf, zTemp, nTemp);
 
 
 
194701 }
194702
194703 for(jj=0; jj<p->pPhrase->nToken; jj++){
194704 p->pPhrase->aToken[jj].z = zBuf;
194705 zBuf += p->pPhrase->aToken[jj].n;
194706 }
194707 rc = SQLITE_OK;
194708 }
194709
194710 getnextstring_out:
 
 
 
194711 if( pCursor ){
194712 pModule->xClose(pCursor);
194713 }
194714 sqlite3_free(zTemp);
194715 if( rc!=SQLITE_OK ){
194716 sqlite3_free(p);
194717 p = 0;
194718 }
194719 *ppExpr = p;
194720 return rc;
194721 }
194722
194723 /*
194724 ** The output variable *ppExpr is populated with an allocated Fts3Expr
194725 ** structure, or set to 0 if the end of the input buffer is reached.
@@ -226191,10 +226309,12 @@
226309 if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
226310 unsigned char *aPage = sqlite3PagerGetData(pDbPage);
226311 memcpy(aPage, pData, szPage);
226312 pTab->pgnoTrunc = 0;
226313 }
226314 }else{
226315 pTab->pgnoTrunc = 0;
226316 }
226317 sqlite3PagerUnref(pDbPage);
226318 return rc;
226319
226320 update_fail:
@@ -233154,17 +233274,32 @@
233274 ** This is used to access token iToken of phrase hit iIdx within the
233275 ** current row. If iIdx is less than zero or greater than or equal to the
233276 ** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
233277 ** output variable (*ppToken) is set to point to a buffer containing the
233278 ** matching document token, and (*pnToken) to the size of that buffer in
233279 ** bytes.
 
 
233280 **
233281 ** The output text is not a copy of the document text that was tokenized.
233282 ** It is the output of the tokenizer module. For tokendata=1 tables, this
233283 ** includes any embedded 0x00 and trailing data.
233284 **
233285 ** This API may be slow in some cases if the token identified by parameters
233286 ** iIdx and iToken matched a prefix token in the query. In most cases, the
233287 ** first call to this API for each prefix token in the query is forced
233288 ** to scan the portion of the full-text index that matches the prefix
233289 ** token to collect the extra data required by this API. If the prefix
233290 ** token matches a large number of token instances in the document set,
233291 ** this may be a performance problem.
233292 **
233293 ** If the user knows in advance that a query may use this API for a
233294 ** prefix token, FTS5 may be configured to collect all required data as part
233295 ** of the initial querying of the full-text index, avoiding the second scan
233296 ** entirely. This also causes prefix queries that do not use this API to
233297 ** run more slowly and use more memory. FTS5 may be configured in this way
233298 ** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
233299 ** option, or on a per-query basis using the
233300 ** [fts5_insttoken | fts5_insttoken()] user function.
233301 **
233302 ** This API can be quite slow if used with an FTS5 table created with the
233303 ** "detail=none" or "detail=column" option.
233304 **
233305 ** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
@@ -233843,11 +233978,12 @@
233978 int nUsermerge; /* 'usermerge' setting */
233979 int nHashSize; /* Bytes of memory for in-memory hash */
233980 char *zRank; /* Name of rank function */
233981 char *zRankArgs; /* Arguments to rank function */
233982 int bSecureDelete; /* 'secure-delete' */
233983 int nDeleteMerge; /* 'deletemerge' */
233984 int bPrefixInsttoken; /* 'prefix-insttoken' */
233985
233986 /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
233987 char **pzErrmsg;
233988
233989 #ifdef SQLITE_DEBUG
@@ -234100,11 +234236,18 @@
234236 static int sqlite3Fts5StructureTest(Fts5Index*, void*);
234237
234238 /*
234239 ** Used by xInstToken():
234240 */
234241 static int sqlite3Fts5IterToken(
234242 Fts5IndexIter *pIndexIter,
234243 const char *pToken, int nToken,
234244 i64 iRowid,
234245 int iCol,
234246 int iOff,
234247 const char **ppOut, int *pnOut
234248 );
234249
234250 /*
234251 ** Insert or remove data to or from the index. Each time a document is
234252 ** added to or removed from the index, this function is called one or more
234253 ** times.
@@ -238314,10 +238457,23 @@
238457 if( bVal<0 ){
238458 *pbBadkey = 1;
238459 }else{
238460 pConfig->bSecureDelete = (bVal ? 1 : 0);
238461 }
238462 }
238463
238464 else if( 0==sqlite3_stricmp(zKey, "insttoken") ){
238465 int bVal = -1;
238466 if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
238467 bVal = sqlite3_value_int(pVal);
238468 }
238469 if( bVal<0 ){
238470 *pbBadkey = 1;
238471 }else{
238472 pConfig->bPrefixInsttoken = (bVal ? 1 : 0);
238473 }
238474
238475 }else{
238476 *pbBadkey = 1;
238477 }
238478 return rc;
238479 }
@@ -241449,11 +241605,11 @@
241605 && memcmp(pT->pTerm, pToken, pT->nQueryTerm)==0
241606 ){
241607 int rc = sqlite3Fts5PoslistWriterAppend(
241608 &pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
241609 );
241610 if( rc==SQLITE_OK && (pExpr->pConfig->bTokendata || pT->bPrefix) ){
241611 int iCol = p->iOff>>32;
241612 int iTokOff = p->iOff & 0x7FFFFFFF;
241613 rc = sqlite3Fts5IndexIterWriteTokendata(
241614 pT->pIter, pToken, nToken, iRowid, iCol, iTokOff
241615 );
@@ -241642,19 +241798,18 @@
241798 pPhrase = pExpr->apExprPhrase[iPhrase];
241799 if( iToken<0 || iToken>=pPhrase->nTerm ){
241800 return SQLITE_RANGE;
241801 }
241802 pTerm = &pPhrase->aTerm[iToken];
241803 if( pExpr->pConfig->bTokendata || pTerm->bPrefix ){
241804 rc = sqlite3Fts5IterToken(
241805 pTerm->pIter, pTerm->pTerm, pTerm->nQueryTerm,
241806 iRowid, iCol, iOff+iToken, ppOut, pnOut
241807 );
241808 }else{
241809 *ppOut = pTerm->pTerm;
241810 *pnOut = pTerm->nFullTerm;
 
241811 }
241812 return rc;
241813 }
241814
241815 /*
@@ -248465,10 +248620,387 @@
248620 fts5BufferFree(&tmp);
248621 memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
248622 *p1 = out;
248623 }
248624
248625
248626 /*
248627 ** Iterate through a range of entries in the FTS index, invoking the xVisit
248628 ** callback for each of them.
248629 **
248630 ** Parameter pToken points to an nToken buffer containing an FTS index term
248631 ** (i.e. a document term with the preceding 1 byte index identifier -
248632 ** FTS5_MAIN_PREFIX or similar). If bPrefix is true, then the call visits
248633 ** all entries for terms that have pToken/nToken as a prefix. If bPrefix
248634 ** is false, then only entries with pToken/nToken as the entire key are
248635 ** visited.
248636 **
248637 ** If the current table is a tokendata=1 table, then if bPrefix is true then
248638 ** each index term is treated separately. However, if bPrefix is false, then
248639 ** all index terms corresponding to pToken/nToken are collapsed into a single
248640 ** term before the callback is invoked.
248641 **
248642 ** The callback invoked for each entry visited is specified by paramter xVisit.
248643 ** Each time it is invoked, it is passed a pointer to the Fts5Index object,
248644 ** a copy of the 7th paramter to this function (pCtx) and a pointer to the
248645 ** iterator that indicates the current entry. If the current entry is the
248646 ** first with a new term (i.e. different from that of the previous entry,
248647 ** including the very first term), then the final two parameters are passed
248648 ** a pointer to the term and its size in bytes, respectively. If the current
248649 ** entry is not the first associated with its term, these two parameters
248650 ** are passed 0.
248651 **
248652 ** If parameter pColset is not NULL, then it is used to filter entries before
248653 ** the callback is invoked.
248654 */
248655 static int fts5VisitEntries(
248656 Fts5Index *p, /* Fts5 index object */
248657 Fts5Colset *pColset, /* Columns filter to apply, or NULL */
248658 u8 *pToken, /* Buffer containing token */
248659 int nToken, /* Size of buffer pToken in bytes */
248660 int bPrefix, /* True for a prefix scan */
248661 void (*xVisit)(Fts5Index*, void *pCtx, Fts5Iter *pIter, const u8*, int),
248662 void *pCtx /* Passed as second argument to xVisit() */
248663 ){
248664 const int flags = (bPrefix ? FTS5INDEX_QUERY_SCAN : 0)
248665 | FTS5INDEX_QUERY_SKIPEMPTY
248666 | FTS5INDEX_QUERY_NOOUTPUT;
248667 Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
248668 int bNewTerm = 1;
248669 Fts5Structure *pStruct = fts5StructureRead(p);
248670
248671 fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
248672 fts5IterSetOutputCb(&p->rc, p1);
248673 for( /* no-op */ ;
248674 fts5MultiIterEof(p, p1)==0;
248675 fts5MultiIterNext2(p, p1, &bNewTerm)
248676 ){
248677 Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
248678 int nNew = 0;
248679 const u8 *pNew = 0;
248680
248681 p1->xSetOutputs(p1, pSeg);
248682 if( p->rc ) break;
248683
248684 if( bNewTerm ){
248685 nNew = pSeg->term.n;
248686 pNew = pSeg->term.p;
248687 if( nNew<nToken || memcmp(pToken, pNew, nToken) ) break;
248688 }
248689
248690 xVisit(p, pCtx, p1, pNew, nNew);
248691 }
248692 fts5MultiIterFree(p1);
248693
248694 fts5StructureRelease(pStruct);
248695 return p->rc;
248696 }
248697
248698
248699 /*
248700 ** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
248701 ** array of these for each row it visits (so all iRowid fields are the same).
248702 ** Or, for an iterator used by an "ORDER BY rank" query, it accumulates an
248703 ** array of these for the entire query (in which case iRowid fields may take
248704 ** a variety of values).
248705 **
248706 ** Each instance in the array indicates the iterator (and therefore term)
248707 ** associated with position iPos of rowid iRowid. This is used by the
248708 ** xInstToken() API.
248709 **
248710 ** iRowid:
248711 ** Rowid for the current entry.
248712 **
248713 ** iPos:
248714 ** Position of current entry within row. In the usual ((iCol<<32)+iOff)
248715 ** format (e.g. see macros FTS5_POS2COLUMN() and FTS5_POS2OFFSET()).
248716 **
248717 ** iIter:
248718 ** If the Fts5TokenDataIter iterator that the entry is part of is
248719 ** actually an iterator (i.e. with nIter>0, not just a container for
248720 ** Fts5TokenDataMap structures), then this variable is an index into
248721 ** the apIter[] array. The corresponding term is that which the iterator
248722 ** at apIter[iIter] currently points to.
248723 **
248724 ** Or, if the Fts5TokenDataIter iterator is just a container object
248725 ** (nIter==0), then iIter is an index into the term.p[] buffer where
248726 ** the term is stored.
248727 **
248728 ** nByte:
248729 ** In the case where iIter is an index into term.p[], this variable
248730 ** is the size of the term in bytes. If iIter is an index into apIter[],
248731 ** this variable is unused.
248732 */
248733 struct Fts5TokenDataMap {
248734 i64 iRowid; /* Row this token is located in */
248735 i64 iPos; /* Position of token */
248736 int iIter; /* Iterator token was read from */
248737 int nByte; /* Length of token in bytes (or 0) */
248738 };
248739
248740 /*
248741 ** An object used to supplement Fts5Iter for tokendata=1 iterators.
248742 **
248743 ** This object serves two purposes. The first is as a container for an array
248744 ** of Fts5TokenDataMap structures, which are used to find the token required
248745 ** when the xInstToken() API is used. This is done by the nMapAlloc, nMap and
248746 ** aMap[] variables.
248747 */
248748 struct Fts5TokenDataIter {
248749 int nMapAlloc; /* Allocated size of aMap[] in entries */
248750 int nMap; /* Number of valid entries in aMap[] */
248751 Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */
248752
248753 /* The following are used for prefix-queries only. */
248754 Fts5Buffer terms;
248755
248756 /* The following are used for other full-token tokendata queries only. */
248757 int nIter;
248758 int nIterAlloc;
248759 Fts5PoslistReader *aPoslistReader;
248760 int *aPoslistToIter;
248761 Fts5Iter *apIter[1];
248762 };
248763
248764 /*
248765 ** The two input arrays - a1[] and a2[] - are in sorted order. This function
248766 ** merges the two arrays together and writes the result to output array
248767 ** aOut[]. aOut[] is guaranteed to be large enough to hold the result.
248768 **
248769 ** Duplicate entries are copied into the output. So the size of the output
248770 ** array is always (n1+n2) entries.
248771 */
248772 static void fts5TokendataMerge(
248773 Fts5TokenDataMap *a1, int n1, /* Input array 1 */
248774 Fts5TokenDataMap *a2, int n2, /* Input array 2 */
248775 Fts5TokenDataMap *aOut /* Output array */
248776 ){
248777 int i1 = 0;
248778 int i2 = 0;
248779
248780 assert( n1>=0 && n2>=0 );
248781 while( i1<n1 || i2<n2 ){
248782 Fts5TokenDataMap *pOut = &aOut[i1+i2];
248783 if( i2>=n2 || (i1<n1 && (
248784 a1[i1].iRowid<a2[i2].iRowid
248785 || (a1[i1].iRowid==a2[i2].iRowid && a1[i1].iPos<=a2[i2].iPos)
248786 ))){
248787 memcpy(pOut, &a1[i1], sizeof(Fts5TokenDataMap));
248788 i1++;
248789 }else{
248790 memcpy(pOut, &a2[i2], sizeof(Fts5TokenDataMap));
248791 i2++;
248792 }
248793 }
248794 }
248795
248796
248797 /*
248798 ** Append a mapping to the token-map belonging to object pT.
248799 */
248800 static void fts5TokendataIterAppendMap(
248801 Fts5Index *p,
248802 Fts5TokenDataIter *pT,
248803 int iIter,
248804 int nByte,
248805 i64 iRowid,
248806 i64 iPos
248807 ){
248808 if( p->rc==SQLITE_OK ){
248809 if( pT->nMap==pT->nMapAlloc ){
248810 int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
248811 int nAlloc = nNew * sizeof(Fts5TokenDataMap);
248812 Fts5TokenDataMap *aNew;
248813
248814 aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc);
248815 if( aNew==0 ){
248816 p->rc = SQLITE_NOMEM;
248817 return;
248818 }
248819
248820 pT->aMap = aNew;
248821 pT->nMapAlloc = nNew;
248822 }
248823
248824 pT->aMap[pT->nMap].iRowid = iRowid;
248825 pT->aMap[pT->nMap].iPos = iPos;
248826 pT->aMap[pT->nMap].iIter = iIter;
248827 pT->aMap[pT->nMap].nByte = nByte;
248828 pT->nMap++;
248829 }
248830 }
248831
248832 /*
248833 ** Sort the contents of the pT->aMap[] array.
248834 **
248835 ** The sorting algorithm requries a malloc(). If this fails, an error code
248836 ** is left in Fts5Index.rc before returning.
248837 */
248838 static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
248839 Fts5TokenDataMap *aTmp = 0;
248840 int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
248841
248842 aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte);
248843 if( aTmp ){
248844 Fts5TokenDataMap *a1 = pT->aMap;
248845 Fts5TokenDataMap *a2 = aTmp;
248846 i64 nHalf;
248847
248848 for(nHalf=1; nHalf<pT->nMap; nHalf=nHalf*2){
248849 int i1;
248850 for(i1=0; i1<pT->nMap; i1+=(nHalf*2)){
248851 int n1 = MIN(nHalf, pT->nMap-i1);
248852 int n2 = MIN(nHalf, pT->nMap-i1-n1);
248853 fts5TokendataMerge(&a1[i1], n1, &a1[i1+n1], n2, &a2[i1]);
248854 }
248855 SWAPVAL(Fts5TokenDataMap*, a1, a2);
248856 }
248857
248858 if( a1!=pT->aMap ){
248859 memcpy(pT->aMap, a1, pT->nMap*sizeof(Fts5TokenDataMap));
248860 }
248861 sqlite3_free(aTmp);
248862
248863 #ifdef SQLITE_DEBUG
248864 {
248865 int ii;
248866 for(ii=1; ii<pT->nMap; ii++){
248867 Fts5TokenDataMap *p1 = &pT->aMap[ii-1];
248868 Fts5TokenDataMap *p2 = &pT->aMap[ii];
248869 assert( p1->iRowid<p2->iRowid
248870 || (p1->iRowid==p2->iRowid && p1->iPos<=p2->iPos)
248871 );
248872 }
248873 }
248874 #endif
248875 }
248876 }
248877
248878 /*
248879 ** Delete an Fts5TokenDataIter structure and its contents.
248880 */
248881 static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
248882 if( pSet ){
248883 int ii;
248884 for(ii=0; ii<pSet->nIter; ii++){
248885 fts5MultiIterFree(pSet->apIter[ii]);
248886 }
248887 fts5BufferFree(&pSet->terms);
248888 sqlite3_free(pSet->aPoslistReader);
248889 sqlite3_free(pSet->aMap);
248890 sqlite3_free(pSet);
248891 }
248892 }
248893
248894
248895 /*
248896 ** fts5VisitEntries() context object used by fts5SetupPrefixIterTokendata()
248897 ** to pass data to prefixIterSetupTokendataCb().
248898 */
248899 typedef struct TokendataSetupCtx TokendataSetupCtx;
248900 struct TokendataSetupCtx {
248901 Fts5TokenDataIter *pT; /* Object being populated with mappings */
248902 int iTermOff; /* Offset of current term in terms.p[] */
248903 int nTermByte; /* Size of current term in bytes */
248904 };
248905
248906 /*
248907 ** fts5VisitEntries() callback used by fts5SetupPrefixIterTokendata(). This
248908 ** callback adds an entry to the Fts5TokenDataIter.aMap[] array for each
248909 ** position in the current position-list. It doesn't matter that some of
248910 ** these may be out of order - they will be sorted later.
248911 */
248912 static void prefixIterSetupTokendataCb(
248913 Fts5Index *p,
248914 void *pCtx,
248915 Fts5Iter *p1,
248916 const u8 *pNew,
248917 int nNew
248918 ){
248919 TokendataSetupCtx *pSetup = (TokendataSetupCtx*)pCtx;
248920 int iPosOff = 0;
248921 i64 iPos = 0;
248922
248923 if( pNew ){
248924 pSetup->nTermByte = nNew-1;
248925 pSetup->iTermOff = pSetup->pT->terms.n;
248926 fts5BufferAppendBlob(&p->rc, &pSetup->pT->terms, nNew-1, pNew+1);
248927 }
248928
248929 while( 0==sqlite3Fts5PoslistNext64(
248930 p1->base.pData, p1->base.nData, &iPosOff, &iPos
248931 ) ){
248932 fts5TokendataIterAppendMap(p,
248933 pSetup->pT, pSetup->iTermOff, pSetup->nTermByte, p1->base.iRowid, iPos
248934 );
248935 }
248936 }
248937
248938
248939 /*
248940 ** Context object passed by fts5SetupPrefixIter() to fts5VisitEntries().
248941 */
248942 typedef struct PrefixSetupCtx PrefixSetupCtx;
248943 struct PrefixSetupCtx {
248944 void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
248945 void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
248946 i64 iLastRowid;
248947 int nMerge;
248948 Fts5Buffer *aBuf;
248949 int nBuf;
248950 Fts5Buffer doclist;
248951 TokendataSetupCtx *pTokendata;
248952 };
248953
248954 /*
248955 ** fts5VisitEntries() callback used by fts5SetupPrefixIter()
248956 */
248957 static void prefixIterSetupCb(
248958 Fts5Index *p,
248959 void *pCtx,
248960 Fts5Iter *p1,
248961 const u8 *pNew,
248962 int nNew
248963 ){
248964 PrefixSetupCtx *pSetup = (PrefixSetupCtx*)pCtx;
248965 const int nMerge = pSetup->nMerge;
248966
248967 if( p1->base.nData>0 ){
248968 if( p1->base.iRowid<=pSetup->iLastRowid && pSetup->doclist.n>0 ){
248969 int i;
248970 for(i=0; p->rc==SQLITE_OK && pSetup->doclist.n; i++){
248971 int i1 = i*nMerge;
248972 int iStore;
248973 assert( i1+nMerge<=pSetup->nBuf );
248974 for(iStore=i1; iStore<i1+nMerge; iStore++){
248975 if( pSetup->aBuf[iStore].n==0 ){
248976 fts5BufferSwap(&pSetup->doclist, &pSetup->aBuf[iStore]);
248977 fts5BufferZero(&pSetup->doclist);
248978 break;
248979 }
248980 }
248981 if( iStore==i1+nMerge ){
248982 pSetup->xMerge(p, &pSetup->doclist, nMerge, &pSetup->aBuf[i1]);
248983 for(iStore=i1; iStore<i1+nMerge; iStore++){
248984 fts5BufferZero(&pSetup->aBuf[iStore]);
248985 }
248986 }
248987 }
248988 pSetup->iLastRowid = 0;
248989 }
248990
248991 pSetup->xAppend(
248992 p, (u64)p1->base.iRowid-(u64)pSetup->iLastRowid, p1, &pSetup->doclist
248993 );
248994 pSetup->iLastRowid = p1->base.iRowid;
248995 }
248996
248997 if( pSetup->pTokendata ){
248998 prefixIterSetupTokendataCb(p, (void*)pSetup->pTokendata, p1, pNew, nNew);
248999 }
249000 }
249001
249002 static void fts5SetupPrefixIter(
249003 Fts5Index *p, /* Index to read from */
249004 int bDesc, /* True for "ORDER BY rowid DESC" */
249005 int iIdx, /* Index to scan for data */
249006 u8 *pToken, /* Buffer containing prefix to match */
@@ -248475,137 +249007,89 @@
249007 int nToken, /* Size of buffer pToken in bytes */
249008 Fts5Colset *pColset, /* Restrict matches to these columns */
249009 Fts5Iter **ppIter /* OUT: New iterator */
249010 ){
249011 Fts5Structure *pStruct;
249012 PrefixSetupCtx s;
249013 TokendataSetupCtx s2;
 
249014
249015 memset(&s, 0, sizeof(s));
249016 memset(&s2, 0, sizeof(s2));
249017
249018 s.nMerge = 1;
249019 s.iLastRowid = 0;
249020 s.nBuf = 32;
249021 if( iIdx==0
249022 && p->pConfig->eDetail==FTS5_DETAIL_FULL
249023 && p->pConfig->bPrefixInsttoken
249024 ){
249025 s.pTokendata = &s2;
249026 s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT));
249027 }
249028
249029 if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
249030 s.xMerge = fts5MergeRowidLists;
249031 s.xAppend = fts5AppendRowid;
249032 }else{
249033 s.nMerge = FTS5_MERGE_NLIST-1;
249034 s.nBuf = s.nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
249035 s.xMerge = fts5MergePrefixLists;
249036 s.xAppend = fts5AppendPoslist;
249037 }
249038
249039 s.aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*s.nBuf);
249040 pStruct = fts5StructureRead(p);
249041 assert( p->rc!=SQLITE_OK || (s.aBuf && pStruct) );
249042
249043 if( p->rc==SQLITE_OK ){
249044 void *pCtx = (void*)&s;
 
 
249045 int i;
 
 
249046 Fts5Data *pData;
 
 
 
 
249047
249048 /* If iIdx is non-zero, then it is the number of a prefix-index for
249049 ** prefixes 1 character longer than the prefix being queried for. That
249050 ** index contains all the doclists required, except for the one
249051 ** corresponding to the prefix itself. That one is extracted from the
249052 ** main term index here. */
249053 if( iIdx!=0 ){
 
 
249054 pToken[0] = FTS5_MAIN_PREFIX;
249055 fts5VisitEntries(p, pColset, pToken, nToken, 0, prefixIterSetupCb, pCtx);
 
 
 
 
 
 
 
 
 
 
 
 
 
249056 }
249057
249058 pToken[0] = FTS5_MAIN_PREFIX + iIdx;
249059 fts5VisitEntries(p, pColset, pToken, nToken, 1, prefixIterSetupCb, pCtx);
249060
249061 assert( (s.nBuf%s.nMerge)==0 );
249062 for(i=0; i<s.nBuf; i+=s.nMerge){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249063 int iFree;
249064 if( p->rc==SQLITE_OK ){
249065 s.xMerge(p, &s.doclist, s.nMerge, &s.aBuf[i]);
249066 }
249067 for(iFree=i; iFree<i+s.nMerge; iFree++){
249068 fts5BufferFree(&s.aBuf[iFree]);
249069 }
249070 }
 
249071
249072 pData = fts5IdxMalloc(p, sizeof(*pData)+s.doclist.n+FTS5_DATA_ZERO_PADDING);
249073 if( pData ){
249074 pData->p = (u8*)&pData[1];
249075 pData->nn = pData->szLeaf = s.doclist.n;
249076 if( s.doclist.n ) memcpy(pData->p, s.doclist.p, s.doclist.n);
249077 fts5MultiIterNew2(p, pData, bDesc, ppIter);
249078 }
249079
249080 if( p->rc==SQLITE_OK && s.pTokendata ){
249081 fts5TokendataIterSortMap(p, s2.pT);
249082 (*ppIter)->pTokenDataIter = s2.pT;
249083 s2.pT = 0;
249084 }
249085 }
249086
249087 fts5TokendataIterDelete(s2.pT);
249088 fts5BufferFree(&s.doclist);
249089 fts5StructureRelease(pStruct);
249090 sqlite3_free(s.aBuf);
249091 }
249092
249093
249094 /*
249095 ** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
@@ -248855,42 +249339,10 @@
249339 static void fts5SegIterSetEOF(Fts5SegIter *pSeg){
249340 fts5DataRelease(pSeg->pLeaf);
249341 pSeg->pLeaf = 0;
249342 }
249343
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249344 /*
249345 ** This function appends iterator pAppend to Fts5TokenDataIter pIn and
249346 ** returns the result.
249347 */
249348 static Fts5TokenDataIter *fts5AppendTokendataIter(
@@ -248923,58 +249375,10 @@
249375 assert( pRet==0 || pRet->nIter<=pRet->nIterAlloc );
249376
249377 return pRet;
249378 }
249379
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249380 /*
249381 ** The iterator passed as the only argument must be a tokendata=1 iterator
249382 ** (pIter->pTokenDataIter!=0). This function sets the iterator output
249383 ** variables (pIter->base.*) according to the contents of the current
249384 ** row.
@@ -249011,11 +249415,11 @@
249415 int eDetail = pIter->pIndex->pConfig->eDetail;
249416 pIter->base.bEof = 0;
249417 pIter->base.iRowid = iRowid;
249418
249419 if( nHit==1 && eDetail==FTS5_DETAIL_FULL ){
249420 fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, 0, iRowid, -1);
249421 }else
249422 if( nHit>1 && eDetail!=FTS5_DETAIL_NONE ){
249423 int nReader = 0;
249424 int nByte = 0;
249425 i64 iPrev = 0;
@@ -249264,10 +249668,11 @@
249668
249669 if( p->rc==SQLITE_OK ){
249670 pRet = fts5MultiIterAlloc(p, 0);
249671 }
249672 if( pRet ){
249673 pRet->nSeg = 0;
249674 pRet->pTokenDataIter = pSet;
249675 if( pSet ){
249676 fts5IterSetOutputsTokendata(pRet);
249677 }else{
249678 pRet->base.bEof = 1;
@@ -249278,11 +249683,10 @@
249683
249684 fts5StructureRelease(pStruct);
249685 fts5BufferFree(&bSeek);
249686 return pRet;
249687 }
 
249688
249689 /*
249690 ** Open a new iterator to iterate though all rowid that match the
249691 ** specified token or token prefix.
249692 */
@@ -249304,10 +249708,15 @@
249708 int iIdx = 0; /* Index to search */
249709 int iPrefixIdx = 0; /* +1 prefix index */
249710 int bTokendata = pConfig->bTokendata;
249711 if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
249712
249713 /* The NOTOKENDATA flag is set when each token in a tokendata=1 table
249714 ** should be treated individually, instead of merging all those with
249715 ** a common prefix into a single entry. This is used, for example, by
249716 ** queries performed as part of an integrity-check, or by the fts5vocab
249717 ** module. */
249718 if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){
249719 bTokendata = 0;
249720 }
249721
249722 /* Figure out which index to search and set iIdx accordingly. If this
@@ -249334,11 +249743,11 @@
249743 if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
249744 }
249745 }
249746
249747 if( bTokendata && iIdx==0 ){
249748 buf.p[0] = FTS5_MAIN_PREFIX;
249749 pRet = fts5SetupTokendataIter(p, buf.p, nToken+1, pColset);
249750 }else if( iIdx<=pConfig->nPrefix ){
249751 /* Straight index lookup */
249752 Fts5Structure *pStruct = fts5StructureRead(p);
249753 buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
@@ -249347,11 +249756,11 @@
249756 pColset, buf.p, nToken+1, -1, 0, &pRet
249757 );
249758 fts5StructureRelease(pStruct);
249759 }
249760 }else{
249761 /* Scan multiple terms in the main index for a prefix query. */
249762 int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
249763 fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
249764 if( pRet==0 ){
249765 assert( p->rc!=SQLITE_OK );
249766 }else{
@@ -249383,11 +249792,12 @@
249792 ** Move to the next matching rowid.
249793 */
249794 static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
249795 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249796 assert( pIter->pIndex->rc==SQLITE_OK );
249797 if( pIter->nSeg==0 ){
249798 assert( pIter->pTokenDataIter );
249799 fts5TokendataIterNext(pIter, 0, 0);
249800 }else{
249801 fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
249802 }
249803 return fts5IndexReturn(pIter->pIndex);
@@ -249420,11 +249830,12 @@
249830 ** definition of "at or after" depends on whether this iterator iterates
249831 ** in ascending or descending rowid order.
249832 */
249833 static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
249834 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249835 if( pIter->nSeg==0 ){
249836 assert( pIter->pTokenDataIter );
249837 fts5TokendataIterNext(pIter, 1, iMatch);
249838 }else{
249839 fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
249840 }
249841 return fts5IndexReturn(pIter->pIndex);
@@ -249438,32 +249849,87 @@
249849 const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
249850 assert_nc( z || n<=1 );
249851 *pn = n-1;
249852 return (z ? &z[1] : 0);
249853 }
249854
249855 /*
249856 ** pIter is a prefix query. This function populates pIter->pTokenDataIter
249857 ** with an Fts5TokenDataIter object containing mappings for all rows
249858 ** matched by the query.
249859 */
249860 static int fts5SetupPrefixIterTokendata(
249861 Fts5Iter *pIter,
249862 const char *pToken, /* Token prefix to search for */
249863 int nToken /* Size of pToken in bytes */
249864 ){
249865 Fts5Index *p = pIter->pIndex;
249866 Fts5Buffer token = {0, 0, 0};
249867 TokendataSetupCtx ctx;
249868
249869 memset(&ctx, 0, sizeof(ctx));
249870
249871 fts5BufferGrow(&p->rc, &token, nToken+1);
249872 ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT));
249873
249874 if( p->rc==SQLITE_OK ){
249875
249876 /* Fill in the token prefix to search for */
249877 token.p[0] = FTS5_MAIN_PREFIX;
249878 memcpy(&token.p[1], pToken, nToken);
249879 token.n = nToken+1;
249880
249881 fts5VisitEntries(
249882 p, 0, token.p, token.n, 1, prefixIterSetupTokendataCb, (void*)&ctx
249883 );
249884
249885 fts5TokendataIterSortMap(p, ctx.pT);
249886 }
249887
249888 if( p->rc==SQLITE_OK ){
249889 pIter->pTokenDataIter = ctx.pT;
249890 }else{
249891 fts5TokendataIterDelete(ctx.pT);
249892 }
249893 fts5BufferFree(&token);
249894
249895 return fts5IndexReturn(p);
249896 }
249897
249898 /*
249899 ** This is used by xInstToken() to access the token at offset iOff, column
249900 ** iCol of row iRowid. The token is returned via output variables *ppOut
249901 ** and *pnOut. The iterator passed as the first argument must be a tokendata=1
249902 ** iterator (pIter->pTokenDataIter!=0).
249903 **
249904 ** pToken/nToken:
249905 */
249906 static int sqlite3Fts5IterToken(
249907 Fts5IndexIter *pIndexIter,
249908 const char *pToken, int nToken,
249909 i64 iRowid,
249910 int iCol,
249911 int iOff,
249912 const char **ppOut, int *pnOut
249913 ){
249914 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249915 Fts5TokenDataIter *pT = pIter->pTokenDataIter;
 
249916 i64 iPos = (((i64)iCol)<<32) + iOff;
249917 Fts5TokenDataMap *aMap = 0;
249918 int i1 = 0;
249919 int i2 = 0;
249920 int iTest = 0;
249921
249922 assert( pT || (pToken && pIter->nSeg>0) );
249923 if( pT==0 ){
249924 int rc = fts5SetupPrefixIterTokendata(pIter, pToken, nToken);
249925 if( rc!=SQLITE_OK ) return rc;
249926 pT = pIter->pTokenDataIter;
249927 }
249928
249929 i2 = pT->nMap;
249930 aMap = pT->aMap;
249931
249932 while( i2>i1 ){
249933 iTest = (i1 + i2) / 2;
249934
249935 if( aMap[iTest].iRowid<iRowid ){
@@ -249483,13 +249949,19 @@
249949 }
249950 }
249951 }
249952
249953 if( i2>i1 ){
249954 if( pIter->nSeg==0 ){
249955 Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
249956 *ppOut = (const char*)pMap->aSeg[0].term.p+1;
249957 *pnOut = pMap->aSeg[0].term.n-1;
249958 }else{
249959 Fts5TokenDataMap *p = &aMap[iTest];
249960 *ppOut = (const char*)&pT->terms.p[p->iIter];
249961 *pnOut = aMap[iTest].nByte;
249962 }
249963 }
249964
249965 return SQLITE_OK;
249966 }
249967
@@ -249497,11 +249969,13 @@
249969 ** Clear any existing entries from the token-map associated with the
249970 ** iterator passed as the only argument.
249971 */
249972 static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){
249973 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249974 if( pIter && pIter->pTokenDataIter
249975 && (pIter->nSeg==0 || pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_FULL)
249976 ){
249977 pIter->pTokenDataIter->nMap = 0;
249978 }
249979 }
249980
249981 /*
@@ -249517,21 +249991,33 @@
249991 i64 iRowid, int iCol, int iOff
249992 ){
249993 Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
249994 Fts5TokenDataIter *pT = pIter->pTokenDataIter;
249995 Fts5Index *p = pIter->pIndex;
249996 i64 iPos = (((i64)iCol)<<32) + iOff;
249997
249998 assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
249999 assert( pIter->pTokenDataIter || pIter->nSeg>0 );
250000 if( pIter->nSeg>0 ){
250001 /* This is a prefix term iterator. */
250002 if( pT==0 ){
250003 pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT));
250004 pIter->pTokenDataIter = pT;
250005 }
250006 if( pT ){
250007 fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos);
250008 fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken);
250009 }
250010 }else{
250011 int ii;
250012 for(ii=0; ii<pT->nIter; ii++){
250013 Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
250014 if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
250015 }
250016 if( ii<pT->nIter ){
250017 fts5TokendataIterAppendMap(p, pT, ii, 0, iRowid, iPos);
250018 }
250019 }
250020 return fts5IndexReturn(p);
250021 }
250022
250023 /*
@@ -251432,10 +251918,11 @@
251918 ** containing a copy of the header from an Fts5Config pointer.
251919 */
251920 #define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
251921 #define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
251922
251923 #define FTS5_INSTTOKEN_SUBTYPE 73
251924
251925 /*
251926 ** Each auxiliary function registered with the FTS5 module is represented
251927 ** by an object of the following type. All such objects are stored as part
251928 ** of the Fts5Global.pAux list.
@@ -252757,10 +253244,11 @@
253244 sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
253245 sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
253246 sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
253247 int iCol; /* Column on LHS of MATCH operator */
253248 char **pzErrmsg = pConfig->pzErrmsg;
253249 int bPrefixInsttoken = pConfig->bPrefixInsttoken;
253250 int i;
253251 int iIdxStr = 0;
253252 Fts5Expr *pExpr = 0;
253253
253254 assert( pConfig->bLock==0 );
@@ -252792,10 +253280,13 @@
253280 int bInternal = 0;
253281
253282 rc = fts5ExtractExprText(pConfig, apVal[i], &zText, &bFreeAndReset);
253283 if( rc!=SQLITE_OK ) goto filter_out;
253284 if( zText==0 ) zText = "";
253285 if( sqlite3_value_subtype(apVal[i])==FTS5_INSTTOKEN_SUBTYPE ){
253286 pConfig->bPrefixInsttoken = 1;
253287 }
253288
253289 iCol = 0;
253290 do{
253291 iCol = iCol*10 + (idxStr[iIdxStr]-'0');
253292 iIdxStr++;
@@ -252932,10 +253423,11 @@
253423 }
253424
253425 filter_out:
253426 sqlite3Fts5ExprFree(pExpr);
253427 pConfig->pzErrmsg = pzErrmsg;
253428 pConfig->bPrefixInsttoken = bPrefixInsttoken;
253429 return rc;
253430 }
253431
253432 /*
253433 ** This is the xEof method of the virtual table. SQLite calls this
@@ -254927,11 +255419,11 @@
255419 int nArg, /* Number of args */
255420 sqlite3_value **apUnused /* Function arguments */
255421 ){
255422 assert( nArg==0 );
255423 UNUSED_PARAM2(nArg, apUnused);
255424 sqlite3_result_text(pCtx, "fts5: 2024-12-09 20:46:36 e2bae4143afd07de1ae55a6d2606a3b541a5b94568aa41f6a96e5d1245471653", -1, SQLITE_TRANSIENT);
255425 }
255426
255427 /*
255428 ** Implementation of fts5_locale(LOCALE, TEXT) function.
255429 **
@@ -254990,10 +255482,24 @@
255482 assert( &pCsr[nText]==&pBlob[nBlob] );
255483
255484 sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);
255485 }
255486 }
255487
255488 /*
255489 ** Implementation of fts5_insttoken() function.
255490 */
255491 static void fts5InsttokenFunc(
255492 sqlite3_context *pCtx, /* Function call context */
255493 int nArg, /* Number of args */
255494 sqlite3_value **apArg /* Function arguments */
255495 ){
255496 assert( nArg==1 );
255497 (void)nArg;
255498 sqlite3_result_value(pCtx, apArg[0]);
255499 sqlite3_result_subtype(pCtx, FTS5_INSTTOKEN_SUBTYPE);
255500 }
255501
255502 /*
255503 ** Return true if zName is the extension on one of the shadow tables used
255504 ** by this module.
255505 */
@@ -255120,13 +255626,20 @@
255626 );
255627 }
255628 if( rc==SQLITE_OK ){
255629 rc = sqlite3_create_function(
255630 db, "fts5_locale", 2,
255631 SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE|SQLITE_SUBTYPE,
255632 p, fts5LocaleFunc, 0, 0
255633 );
255634 }
255635 if( rc==SQLITE_OK ){
255636 rc = sqlite3_create_function(
255637 db, "fts5_insttoken", 1,
255638 SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
255639 p, fts5InsttokenFunc, 0, 0
255640 );
255641 }
255642 }
255643
255644 /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
255645 ** fts5_test_mi.c is compiled and linked into the executable. And call
@@ -258048,11 +258561,11 @@
258561 int rc = SQLITE_OK;
258562 char aBuf[32];
258563 char *zOut = aBuf;
258564 int ii;
258565 const unsigned char *zIn = (const unsigned char*)pText;
258566 const unsigned char *zEof = (zIn ? &zIn[nText] : 0);
258567 u32 iCode = 0;
258568 int aStart[3]; /* Input offset of each character in aBuf[] */
258569
258570 UNUSED_PARAM(unusedFlags);
258571
258572
+30 -4
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,11 +146,11 @@
146146
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147147
** [sqlite_version()] and [sqlite_source_id()].
148148
*/
149149
#define SQLITE_VERSION "3.48.0"
150150
#define SQLITE_VERSION_NUMBER 3048000
151
-#define SQLITE_SOURCE_ID "2024-11-14 19:34:28 81202d2ab5963fdcf20555b6d0b31cc955ac27f1cd87656faea5c0611c9a2ee8"
151
+#define SQLITE_SOURCE_ID "2024-12-09 20:46:36 e2bae4143afd07de1ae55a6d2606a3b541a5b94568aa41f6a96e5d1245471653"
152152
153153
/*
154154
** CAPI3REF: Run-Time Library Version Numbers
155155
** KEYWORDS: sqlite3_version sqlite3_sourceid
156156
**
@@ -4202,15 +4202,26 @@
42024202
**
42034203
** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
42044204
** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
42054205
** to return an error (error code SQLITE_ERROR) if the statement uses
42064206
** any virtual tables.
4207
+**
4208
+** [[SQLITE_PREPARE_DONT_LOG]] <dt>SQLITE_PREPARE_DONT_LOG</dt>
4209
+** <dd>The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler
4210
+** errors from being sent to the error log defined by
4211
+** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test
4212
+** compiles to see if some SQL syntax is well-formed, without generating
4213
+** messages on the global error log when it is not. If the test compile
4214
+** fails, the sqlite3_prepare_v3() call returns the same error indications
4215
+** with or without this flag; it just omits the call to [sqlite3_log()] that
4216
+** logs the error.
42074217
** </dl>
42084218
*/
42094219
#define SQLITE_PREPARE_PERSISTENT 0x01
42104220
#define SQLITE_PREPARE_NORMALIZE 0x02
42114221
#define SQLITE_PREPARE_NO_VTAB 0x04
4222
+#define SQLITE_PREPARE_DONT_LOG 0x10
42124223
42134224
/*
42144225
** CAPI3REF: Compiling An SQL Statement
42154226
** KEYWORDS: {SQL statement compiler}
42164227
** METHOD: sqlite3
@@ -13148,17 +13159,32 @@
1314813159
** This is used to access token iToken of phrase hit iIdx within the
1314913160
** current row. If iIdx is less than zero or greater than or equal to the
1315013161
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
1315113162
** output variable (*ppToken) is set to point to a buffer containing the
1315213163
** matching document token, and (*pnToken) to the size of that buffer in
13153
-** bytes. This API is not available if the specified token matches a
13154
-** prefix query term. In that case both output variables are always set
13155
-** to 0.
13164
+** bytes.
1315613165
**
1315713166
** The output text is not a copy of the document text that was tokenized.
1315813167
** It is the output of the tokenizer module. For tokendata=1 tables, this
1315913168
** includes any embedded 0x00 and trailing data.
13169
+**
13170
+** This API may be slow in some cases if the token identified by parameters
13171
+** iIdx and iToken matched a prefix token in the query. In most cases, the
13172
+** first call to this API for each prefix token in the query is forced
13173
+** to scan the portion of the full-text index that matches the prefix
13174
+** token to collect the extra data required by this API. If the prefix
13175
+** token matches a large number of token instances in the document set,
13176
+** this may be a performance problem.
13177
+**
13178
+** If the user knows in advance that a query may use this API for a
13179
+** prefix token, FTS5 may be configured to collect all required data as part
13180
+** of the initial querying of the full-text index, avoiding the second scan
13181
+** entirely. This also causes prefix queries that do not use this API to
13182
+** run more slowly and use more memory. FTS5 may be configured in this way
13183
+** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
13184
+** option, or on a per-query basis using the
13185
+** [fts5_insttoken | fts5_insttoken()] user function.
1316013186
**
1316113187
** This API can be quite slow if used with an FTS5 table created with the
1316213188
** "detail=none" or "detail=column" option.
1316313189
**
1316413190
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
1316513191
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,11 +146,11 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.48.0"
150 #define SQLITE_VERSION_NUMBER 3048000
151 #define SQLITE_SOURCE_ID "2024-11-14 19:34:28 81202d2ab5963fdcf20555b6d0b31cc955ac27f1cd87656faea5c0611c9a2ee8"
152
153 /*
154 ** CAPI3REF: Run-Time Library Version Numbers
155 ** KEYWORDS: sqlite3_version sqlite3_sourceid
156 **
@@ -4202,15 +4202,26 @@
4202 **
4203 ** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
4204 ** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
4205 ** to return an error (error code SQLITE_ERROR) if the statement uses
4206 ** any virtual tables.
 
 
 
 
 
 
 
 
 
 
4207 ** </dl>
4208 */
4209 #define SQLITE_PREPARE_PERSISTENT 0x01
4210 #define SQLITE_PREPARE_NORMALIZE 0x02
4211 #define SQLITE_PREPARE_NO_VTAB 0x04
 
4212
4213 /*
4214 ** CAPI3REF: Compiling An SQL Statement
4215 ** KEYWORDS: {SQL statement compiler}
4216 ** METHOD: sqlite3
@@ -13148,17 +13159,32 @@
13148 ** This is used to access token iToken of phrase hit iIdx within the
13149 ** current row. If iIdx is less than zero or greater than or equal to the
13150 ** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
13151 ** output variable (*ppToken) is set to point to a buffer containing the
13152 ** matching document token, and (*pnToken) to the size of that buffer in
13153 ** bytes. This API is not available if the specified token matches a
13154 ** prefix query term. In that case both output variables are always set
13155 ** to 0.
13156 **
13157 ** The output text is not a copy of the document text that was tokenized.
13158 ** It is the output of the tokenizer module. For tokendata=1 tables, this
13159 ** includes any embedded 0x00 and trailing data.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13160 **
13161 ** This API can be quite slow if used with an FTS5 table created with the
13162 ** "detail=none" or "detail=column" option.
13163 **
13164 ** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
13165
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,11 +146,11 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.48.0"
150 #define SQLITE_VERSION_NUMBER 3048000
151 #define SQLITE_SOURCE_ID "2024-12-09 20:46:36 e2bae4143afd07de1ae55a6d2606a3b541a5b94568aa41f6a96e5d1245471653"
152
153 /*
154 ** CAPI3REF: Run-Time Library Version Numbers
155 ** KEYWORDS: sqlite3_version sqlite3_sourceid
156 **
@@ -4202,15 +4202,26 @@
4202 **
4203 ** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
4204 ** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
4205 ** to return an error (error code SQLITE_ERROR) if the statement uses
4206 ** any virtual tables.
4207 **
4208 ** [[SQLITE_PREPARE_DONT_LOG]] <dt>SQLITE_PREPARE_DONT_LOG</dt>
4209 ** <dd>The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler
4210 ** errors from being sent to the error log defined by
4211 ** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test
4212 ** compiles to see if some SQL syntax is well-formed, without generating
4213 ** messages on the global error log when it is not. If the test compile
4214 ** fails, the sqlite3_prepare_v3() call returns the same error indications
4215 ** with or without this flag; it just omits the call to [sqlite3_log()] that
4216 ** logs the error.
4217 ** </dl>
4218 */
4219 #define SQLITE_PREPARE_PERSISTENT 0x01
4220 #define SQLITE_PREPARE_NORMALIZE 0x02
4221 #define SQLITE_PREPARE_NO_VTAB 0x04
4222 #define SQLITE_PREPARE_DONT_LOG 0x10
4223
4224 /*
4225 ** CAPI3REF: Compiling An SQL Statement
4226 ** KEYWORDS: {SQL statement compiler}
4227 ** METHOD: sqlite3
@@ -13148,17 +13159,32 @@
13159 ** This is used to access token iToken of phrase hit iIdx within the
13160 ** current row. If iIdx is less than zero or greater than or equal to the
13161 ** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
13162 ** output variable (*ppToken) is set to point to a buffer containing the
13163 ** matching document token, and (*pnToken) to the size of that buffer in
13164 ** bytes.
 
 
13165 **
13166 ** The output text is not a copy of the document text that was tokenized.
13167 ** It is the output of the tokenizer module. For tokendata=1 tables, this
13168 ** includes any embedded 0x00 and trailing data.
13169 **
13170 ** This API may be slow in some cases if the token identified by parameters
13171 ** iIdx and iToken matched a prefix token in the query. In most cases, the
13172 ** first call to this API for each prefix token in the query is forced
13173 ** to scan the portion of the full-text index that matches the prefix
13174 ** token to collect the extra data required by this API. If the prefix
13175 ** token matches a large number of token instances in the document set,
13176 ** this may be a performance problem.
13177 **
13178 ** If the user knows in advance that a query may use this API for a
13179 ** prefix token, FTS5 may be configured to collect all required data as part
13180 ** of the initial querying of the full-text index, avoiding the second scan
13181 ** entirely. This also causes prefix queries that do not use this API to
13182 ** run more slowly and use more memory. FTS5 may be configured in this way
13183 ** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
13184 ** option, or on a per-query basis using the
13185 ** [fts5_insttoken | fts5_insttoken()] user function.
13186 **
13187 ** This API can be quite slow if used with an FTS5 table created with the
13188 ** "detail=none" or "detail=column" option.
13189 **
13190 ** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
13191

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button