@rocicorp/zero-sqlite3 1.0.15 → 1.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +1 -1
- package/deps/defines.gypi +1 -2
- package/deps/download.sh +2 -3
- package/deps/sqlite3/shell.c +1205 -1337
- package/deps/sqlite3/sqlite3.c +4540 -1435
- package/deps/sqlite3/sqlite3.h +389 -194
- package/deps/sqlite3/sqlite3ext.h +7 -0
- package/lib/database.js +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/methods/wrappers.js +5 -0
- package/package.json +3 -3
- package/src/better_sqlite3.cpp +6 -1
- package/src/objects/database.cpp +28 -3
- package/src/objects/database.hpp +1 -0
- package/src/objects/statement.cpp +2 -2
- package/src/util/binder.cpp +2 -2
- package/src/util/data.cpp +1 -1
- package/src/util/macros.cpp +20 -0
- package/src/util/row-builder.cpp +1 -1
- package/deps/patches/1208.patch +0 -15
package/deps/sqlite3/shell.c
CHANGED
|
@@ -124,6 +124,9 @@ typedef sqlite3_uint64 u64;
|
|
|
124
124
|
typedef unsigned char u8;
|
|
125
125
|
#include <ctype.h>
|
|
126
126
|
#include <stdarg.h>
|
|
127
|
+
#ifndef _WIN32
|
|
128
|
+
# include <sys/time.h>
|
|
129
|
+
#endif
|
|
127
130
|
|
|
128
131
|
#if !defined(_WIN32) && !defined(WIN32)
|
|
129
132
|
# include <signal.h>
|
|
@@ -648,8 +651,19 @@ static int cli_strncmp(const char *a, const char *b, size_t n){
|
|
|
648
651
|
return strncmp(a,b,n);
|
|
649
652
|
}
|
|
650
653
|
|
|
651
|
-
/* Return the current wall-clock time
|
|
654
|
+
/* Return the current wall-clock time in microseconds since the
|
|
655
|
+
** Unix epoch (1970-01-01T00:00:00Z)
|
|
656
|
+
*/
|
|
652
657
|
static sqlite3_int64 timeOfDay(void){
|
|
658
|
+
#if defined(_WIN64)
|
|
659
|
+
sqlite3_uint64 t;
|
|
660
|
+
FILETIME tm;
|
|
661
|
+
GetSystemTimePreciseAsFileTime(&tm);
|
|
662
|
+
t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
|
|
663
|
+
t += 116444736000000000LL;
|
|
664
|
+
t /= 10;
|
|
665
|
+
return t;
|
|
666
|
+
#elif defined(_WIN32)
|
|
653
667
|
static sqlite3_vfs *clockVfs = 0;
|
|
654
668
|
sqlite3_int64 t;
|
|
655
669
|
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
|
|
@@ -661,7 +675,12 @@ static sqlite3_int64 timeOfDay(void){
|
|
|
661
675
|
clockVfs->xCurrentTime(clockVfs, &r);
|
|
662
676
|
t = (sqlite3_int64)(r*86400000.0);
|
|
663
677
|
}
|
|
664
|
-
return t;
|
|
678
|
+
return t*1000;
|
|
679
|
+
#else
|
|
680
|
+
struct timeval sNow;
|
|
681
|
+
(void)gettimeofday(&sNow,0);
|
|
682
|
+
return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec;
|
|
683
|
+
#endif
|
|
665
684
|
}
|
|
666
685
|
|
|
667
686
|
#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
|
|
@@ -706,8 +725,8 @@ static void endTimer(FILE *out){
|
|
|
706
725
|
sqlite3_int64 iEnd = timeOfDay();
|
|
707
726
|
struct rusage sEnd;
|
|
708
727
|
getrusage(RUSAGE_SELF, &sEnd);
|
|
709
|
-
sqlite3_fprintf(out, "Run Time: real %.
|
|
710
|
-
(iEnd - iBegin)*0.
|
|
728
|
+
sqlite3_fprintf(out, "Run Time: real %.6f user %.6f sys %.6f\n",
|
|
729
|
+
(iEnd - iBegin)*0.000001,
|
|
711
730
|
timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
|
|
712
731
|
timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
|
|
713
732
|
}
|
|
@@ -785,10 +804,19 @@ static void endTimer(FILE *out){
|
|
|
785
804
|
FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
|
|
786
805
|
sqlite3_int64 ftWallEnd = timeOfDay();
|
|
787
806
|
getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
|
|
788
|
-
|
|
789
|
-
|
|
807
|
+
#ifdef _WIN64
|
|
808
|
+
/* microsecond precision on 64-bit windows */
|
|
809
|
+
sqlite3_fprintf(out, "Run Time: real %.6f user %f sys %f\n",
|
|
810
|
+
(ftWallEnd - ftWallBegin)*0.000001,
|
|
790
811
|
timeDiff(&ftUserBegin, &ftUserEnd),
|
|
791
812
|
timeDiff(&ftKernelBegin, &ftKernelEnd));
|
|
813
|
+
#else
|
|
814
|
+
/* millisecond precisino on 32-bit windows */
|
|
815
|
+
sqlite3_fprintf(out, "Run Time: real %.3f user %.3f sys %.3f\n",
|
|
816
|
+
(ftWallEnd - ftWallBegin)*0.000001,
|
|
817
|
+
timeDiff(&ftUserBegin, &ftUserEnd),
|
|
818
|
+
timeDiff(&ftKernelBegin, &ftKernelEnd));
|
|
819
|
+
#endif
|
|
792
820
|
}
|
|
793
821
|
}
|
|
794
822
|
|
|
@@ -1128,7 +1156,7 @@ static int decodeUtf8(const unsigned char *z, int *pU){
|
|
|
1128
1156
|
&& (z[3] & 0xc0)==0x80
|
|
1129
1157
|
){
|
|
1130
1158
|
*pU = ((z[0] & 0x0f)<<18) | ((z[1] & 0x3f)<<12) | ((z[2] & 0x3f))<<6
|
|
1131
|
-
| (z[
|
|
1159
|
+
| (z[3] & 0x3f);
|
|
1132
1160
|
return 4;
|
|
1133
1161
|
}
|
|
1134
1162
|
*pU = 0;
|
|
@@ -1191,14 +1219,24 @@ static int isVt100(const unsigned char *z){
|
|
|
1191
1219
|
** Take into account zero-width and double-width Unicode characters.
|
|
1192
1220
|
** In other words, a zero-width character does not count toward the
|
|
1193
1221
|
** the w limit. A double-width character counts as two.
|
|
1222
|
+
**
|
|
1223
|
+
** w should normally be a small number. A couple hundred at most. This
|
|
1224
|
+
** routine caps w at 100 million to avoid integer overflow issues.
|
|
1194
1225
|
*/
|
|
1195
1226
|
static void utf8_width_print(FILE *out, int w, const char *zUtf){
|
|
1196
1227
|
const unsigned char *a = (const unsigned char*)zUtf;
|
|
1228
|
+
static const int mxW = 10000000;
|
|
1197
1229
|
unsigned char c;
|
|
1198
1230
|
int i = 0;
|
|
1199
1231
|
int n = 0;
|
|
1200
1232
|
int k;
|
|
1201
|
-
int aw
|
|
1233
|
+
int aw;
|
|
1234
|
+
if( w<-mxW ){
|
|
1235
|
+
w = -mxW;
|
|
1236
|
+
}else if( w>mxW ){
|
|
1237
|
+
w= mxW;
|
|
1238
|
+
}
|
|
1239
|
+
aw = w<0 ? -w : w;
|
|
1202
1240
|
if( zUtf==0 ) zUtf = "";
|
|
1203
1241
|
while( (c = a[i])!=0 ){
|
|
1204
1242
|
if( (c&0xc0)==0xc0 ){
|
|
@@ -1268,12 +1306,21 @@ static int strlen30(const char *z){
|
|
|
1268
1306
|
|
|
1269
1307
|
/*
|
|
1270
1308
|
** Return the length of a string in characters. Multibyte UTF8 characters
|
|
1271
|
-
** count as a single character
|
|
1309
|
+
** count as a single character for single-width characters, or as two
|
|
1310
|
+
** characters for double-width characters.
|
|
1272
1311
|
*/
|
|
1273
1312
|
static int strlenChar(const char *z){
|
|
1274
1313
|
int n = 0;
|
|
1275
1314
|
while( *z ){
|
|
1276
|
-
if( (
|
|
1315
|
+
if( (0x80&z[0])==0 ){
|
|
1316
|
+
n++;
|
|
1317
|
+
z++;
|
|
1318
|
+
}else{
|
|
1319
|
+
int u = 0;
|
|
1320
|
+
int len = decodeUtf8((const u8*)z, &u);
|
|
1321
|
+
z += len;
|
|
1322
|
+
n += cli_wcwidth(u);
|
|
1323
|
+
}
|
|
1277
1324
|
}
|
|
1278
1325
|
return n;
|
|
1279
1326
|
}
|
|
@@ -1316,7 +1363,7 @@ static FILE * openChrSource(const char *zFile){
|
|
|
1316
1363
|
** This routine reads a line of text from FILE in, stores
|
|
1317
1364
|
** the text in memory obtained from malloc() and returns a pointer
|
|
1318
1365
|
** to the text. NULL is returned at end of file, or if malloc()
|
|
1319
|
-
** fails.
|
|
1366
|
+
** fails, or if the length of the line is longer than about a gigabyte.
|
|
1320
1367
|
**
|
|
1321
1368
|
** If zLine is not NULL then it is a malloced buffer returned from
|
|
1322
1369
|
** a previous call to this routine that may be reused.
|
|
@@ -1327,6 +1374,10 @@ static char *local_getline(char *zLine, FILE *in){
|
|
|
1327
1374
|
|
|
1328
1375
|
while( 1 ){
|
|
1329
1376
|
if( n+100>nLine ){
|
|
1377
|
+
if( nLine>=1073741773 ){
|
|
1378
|
+
free(zLine);
|
|
1379
|
+
return 0;
|
|
1380
|
+
}
|
|
1330
1381
|
nLine = nLine*2 + 100;
|
|
1331
1382
|
zLine = realloc(zLine, nLine);
|
|
1332
1383
|
shell_check_oom(zLine);
|
|
@@ -1410,10 +1461,14 @@ static int hexDigitValue(char c){
|
|
|
1410
1461
|
|
|
1411
1462
|
/*
|
|
1412
1463
|
** Interpret zArg as an integer value, possibly with suffixes.
|
|
1464
|
+
**
|
|
1465
|
+
** If the value specified by zArg is outside the range of values that
|
|
1466
|
+
** can be represented using a 64-bit twos-complement integer, then return
|
|
1467
|
+
** the nearest representable value.
|
|
1413
1468
|
*/
|
|
1414
1469
|
static sqlite3_int64 integerValue(const char *zArg){
|
|
1415
|
-
|
|
1416
|
-
static const struct { char *zSuffix; int iMult; } aMult[] = {
|
|
1470
|
+
sqlite3_uint64 v = 0;
|
|
1471
|
+
static const struct { char *zSuffix; unsigned int iMult; } aMult[] = {
|
|
1417
1472
|
{ "KiB", 1024 },
|
|
1418
1473
|
{ "MiB", 1024*1024 },
|
|
1419
1474
|
{ "GiB", 1024*1024*1024 },
|
|
@@ -1436,22 +1491,30 @@ static sqlite3_int64 integerValue(const char *zArg){
|
|
|
1436
1491
|
int x;
|
|
1437
1492
|
zArg += 2;
|
|
1438
1493
|
while( (x = hexDigitValue(zArg[0]))>=0 ){
|
|
1494
|
+
if( v > 0x0fffffffffffffffULL ) goto integer_overflow;
|
|
1439
1495
|
v = (v<<4) + x;
|
|
1440
1496
|
zArg++;
|
|
1441
1497
|
}
|
|
1442
1498
|
}else{
|
|
1443
1499
|
while( IsDigit(zArg[0]) ){
|
|
1444
|
-
|
|
1500
|
+
if( v>=922337203685477580LL ){
|
|
1501
|
+
if( v>922337203685477580LL || zArg[0]>='8' ) goto integer_overflow;
|
|
1502
|
+
}
|
|
1503
|
+
v = v*10 + (zArg[0] - '0');
|
|
1445
1504
|
zArg++;
|
|
1446
1505
|
}
|
|
1447
1506
|
}
|
|
1448
1507
|
for(i=0; i<ArraySize(aMult); i++){
|
|
1449
1508
|
if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
|
|
1509
|
+
if( 0x7fffffffffffffffULL/aMult[i].iMult < v ) goto integer_overflow;
|
|
1450
1510
|
v *= aMult[i].iMult;
|
|
1451
1511
|
break;
|
|
1452
1512
|
}
|
|
1453
1513
|
}
|
|
1454
|
-
|
|
1514
|
+
if( isNeg && v>0x7fffffffffffffffULL ) goto integer_overflow;
|
|
1515
|
+
return isNeg? -(sqlite3_int64)v : (sqlite3_int64)v;
|
|
1516
|
+
integer_overflow:
|
|
1517
|
+
return isNeg ? (i64)0x8000000000000000LL : 0x7fffffffffffffffLL;
|
|
1455
1518
|
}
|
|
1456
1519
|
|
|
1457
1520
|
/*
|
|
@@ -1459,9 +1522,9 @@ static sqlite3_int64 integerValue(const char *zArg){
|
|
|
1459
1522
|
*/
|
|
1460
1523
|
typedef struct ShellText ShellText;
|
|
1461
1524
|
struct ShellText {
|
|
1462
|
-
char *
|
|
1463
|
-
|
|
1464
|
-
|
|
1525
|
+
char *zTxt; /* The text */
|
|
1526
|
+
i64 n; /* Number of bytes of zTxt[] actually used */
|
|
1527
|
+
i64 nAlloc; /* Number of bytes allocated for zTxt[] */
|
|
1465
1528
|
};
|
|
1466
1529
|
|
|
1467
1530
|
/*
|
|
@@ -1471,7 +1534,7 @@ static void initText(ShellText *p){
|
|
|
1471
1534
|
memset(p, 0, sizeof(*p));
|
|
1472
1535
|
}
|
|
1473
1536
|
static void freeText(ShellText *p){
|
|
1474
|
-
|
|
1537
|
+
sqlite3_free(p->zTxt);
|
|
1475
1538
|
initText(p);
|
|
1476
1539
|
}
|
|
1477
1540
|
|
|
@@ -1496,26 +1559,26 @@ static void appendText(ShellText *p, const char *zAppend, char quote){
|
|
|
1496
1559
|
}
|
|
1497
1560
|
}
|
|
1498
1561
|
|
|
1499
|
-
if( p->
|
|
1562
|
+
if( p->zTxt==0 || p->n+len>=p->nAlloc ){
|
|
1500
1563
|
p->nAlloc = p->nAlloc*2 + len + 20;
|
|
1501
|
-
p->
|
|
1502
|
-
shell_check_oom(p->
|
|
1564
|
+
p->zTxt = sqlite3_realloc64(p->zTxt, p->nAlloc);
|
|
1565
|
+
shell_check_oom(p->zTxt);
|
|
1503
1566
|
}
|
|
1504
1567
|
|
|
1505
1568
|
if( quote ){
|
|
1506
|
-
char *zCsr = p->
|
|
1569
|
+
char *zCsr = p->zTxt+p->n;
|
|
1507
1570
|
*zCsr++ = quote;
|
|
1508
1571
|
for(i=0; i<nAppend; i++){
|
|
1509
1572
|
*zCsr++ = zAppend[i];
|
|
1510
1573
|
if( zAppend[i]==quote ) *zCsr++ = quote;
|
|
1511
1574
|
}
|
|
1512
1575
|
*zCsr++ = quote;
|
|
1513
|
-
p->n = (
|
|
1576
|
+
p->n = (i64)(zCsr - p->zTxt);
|
|
1514
1577
|
*zCsr = '\0';
|
|
1515
1578
|
}else{
|
|
1516
|
-
memcpy(p->
|
|
1579
|
+
memcpy(p->zTxt+p->n, zAppend, nAppend);
|
|
1517
1580
|
p->n += nAppend;
|
|
1518
|
-
p->
|
|
1581
|
+
p->zTxt[p->n] = '\0';
|
|
1519
1582
|
}
|
|
1520
1583
|
}
|
|
1521
1584
|
|
|
@@ -1540,6 +1603,9 @@ static char quoteChar(const char *zName){
|
|
|
1540
1603
|
/*
|
|
1541
1604
|
** Construct a fake object name and column list to describe the structure
|
|
1542
1605
|
** of the view, virtual table, or table valued function zSchema.zName.
|
|
1606
|
+
**
|
|
1607
|
+
** The returned string comes from sqlite3_mprintf() and should be freed
|
|
1608
|
+
** by the caller using sqlite3_free().
|
|
1543
1609
|
*/
|
|
1544
1610
|
static char *shellFakeSchema(
|
|
1545
1611
|
sqlite3 *db, /* The database connection containing the vtab */
|
|
@@ -1580,9 +1646,9 @@ static char *shellFakeSchema(
|
|
|
1580
1646
|
sqlite3_finalize(pStmt);
|
|
1581
1647
|
if( nRow==0 ){
|
|
1582
1648
|
freeText(&s);
|
|
1583
|
-
s.
|
|
1649
|
+
s.zTxt = 0;
|
|
1584
1650
|
}
|
|
1585
|
-
return s.
|
|
1651
|
+
return s.zTxt;
|
|
1586
1652
|
}
|
|
1587
1653
|
|
|
1588
1654
|
/*
|
|
@@ -1685,7 +1751,7 @@ static void shellAddSchemaName(
|
|
|
1685
1751
|
}else{
|
|
1686
1752
|
z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
|
|
1687
1753
|
}
|
|
1688
|
-
|
|
1754
|
+
sqlite3_free(zFake);
|
|
1689
1755
|
}
|
|
1690
1756
|
if( z ){
|
|
1691
1757
|
sqlite3_result_text(pCtx, z, -1, sqlite3_free);
|
|
@@ -1706,10 +1772,9 @@ static void shellAddSchemaName(
|
|
|
1706
1772
|
#define SQLITE_EXTENSION_INIT1
|
|
1707
1773
|
#define SQLITE_EXTENSION_INIT2(X) (void)(X)
|
|
1708
1774
|
|
|
1709
|
-
|
|
1710
|
-
/************************* Begin test_windirent.h ******************/
|
|
1775
|
+
/************************* Begin ../ext/misc/windirent.h ******************/
|
|
1711
1776
|
/*
|
|
1712
|
-
**
|
|
1777
|
+
** 2025-06-05
|
|
1713
1778
|
**
|
|
1714
1779
|
** The author disclaims copyright to this source code. In place of
|
|
1715
1780
|
** a legal notice, here is a blessing:
|
|
@@ -1719,322 +1784,160 @@ static void shellAddSchemaName(
|
|
|
1719
1784
|
** May you share freely, never taking more than you give.
|
|
1720
1785
|
**
|
|
1721
1786
|
*************************************************************************
|
|
1722
|
-
**
|
|
1723
|
-
**
|
|
1787
|
+
**
|
|
1788
|
+
** An implementation of opendir(), readdir(), and closedir() for Windows,
|
|
1789
|
+
** based on the FindFirstFile(), FindNextFile(), and FindClose() APIs
|
|
1790
|
+
** of Win32.
|
|
1791
|
+
**
|
|
1792
|
+
** #include this file inside any C-code module that needs to use
|
|
1793
|
+
** opendir()/readdir()/closedir(). This file is a no-op on non-Windows
|
|
1794
|
+
** machines. On Windows, static functions are defined that implement
|
|
1795
|
+
** those standard interfaces.
|
|
1724
1796
|
*/
|
|
1725
|
-
|
|
1726
1797
|
#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
|
|
1727
1798
|
#define SQLITE_WINDIRENT_H
|
|
1728
1799
|
|
|
1729
|
-
/*
|
|
1730
|
-
** We need several data types from the Windows SDK header.
|
|
1731
|
-
*/
|
|
1732
|
-
|
|
1733
1800
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
1734
1801
|
#define WIN32_LEAN_AND_MEAN
|
|
1735
1802
|
#endif
|
|
1736
|
-
|
|
1737
|
-
#include
|
|
1738
|
-
|
|
1739
|
-
/*
|
|
1740
|
-
** We need several support functions from the SQLite core.
|
|
1741
|
-
*/
|
|
1742
|
-
|
|
1743
|
-
/* #include "sqlite3.h" */
|
|
1744
|
-
|
|
1745
|
-
/*
|
|
1746
|
-
** We need several things from the ANSI and MSVCRT headers.
|
|
1747
|
-
*/
|
|
1748
|
-
|
|
1803
|
+
#include <windows.h>
|
|
1804
|
+
#include <io.h>
|
|
1749
1805
|
#include <stdio.h>
|
|
1750
1806
|
#include <stdlib.h>
|
|
1751
1807
|
#include <errno.h>
|
|
1752
|
-
#include <io.h>
|
|
1753
1808
|
#include <limits.h>
|
|
1754
1809
|
#include <sys/types.h>
|
|
1755
1810
|
#include <sys/stat.h>
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1811
|
+
#include <string.h>
|
|
1812
|
+
#ifndef FILENAME_MAX
|
|
1813
|
+
# define FILENAME_MAX (260)
|
|
1814
|
+
#endif
|
|
1761
1815
|
#ifndef S_ISREG
|
|
1762
|
-
#define S_ISREG(
|
|
1816
|
+
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
|
1763
1817
|
#endif
|
|
1764
|
-
|
|
1765
1818
|
#ifndef S_ISDIR
|
|
1766
|
-
#define S_ISDIR(
|
|
1819
|
+
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
|
1767
1820
|
#endif
|
|
1768
|
-
|
|
1769
1821
|
#ifndef S_ISLNK
|
|
1770
|
-
#define S_ISLNK(
|
|
1771
|
-
#endif
|
|
1772
|
-
|
|
1773
|
-
/*
|
|
1774
|
-
** We may need to provide the "mode_t" type.
|
|
1775
|
-
*/
|
|
1776
|
-
|
|
1777
|
-
#ifndef MODE_T_DEFINED
|
|
1778
|
-
#define MODE_T_DEFINED
|
|
1779
|
-
typedef unsigned short mode_t;
|
|
1780
|
-
#endif
|
|
1781
|
-
|
|
1782
|
-
/*
|
|
1783
|
-
** We may need to provide the "ino_t" type.
|
|
1784
|
-
*/
|
|
1785
|
-
|
|
1786
|
-
#ifndef INO_T_DEFINED
|
|
1787
|
-
#define INO_T_DEFINED
|
|
1788
|
-
typedef unsigned short ino_t;
|
|
1822
|
+
#define S_ISLNK(m) (0)
|
|
1789
1823
|
#endif
|
|
1824
|
+
typedef unsigned short mode_t;
|
|
1790
1825
|
|
|
1791
|
-
/*
|
|
1792
|
-
**
|
|
1826
|
+
/* The dirent object for Windows is abbreviated. The only field really
|
|
1827
|
+
** usable by applications is d_name[].
|
|
1793
1828
|
*/
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
# else
|
|
1799
|
-
# define NAME_MAX (260)
|
|
1800
|
-
# endif
|
|
1801
|
-
# define DIRENT_NAME_MAX (NAME_MAX)
|
|
1802
|
-
#endif
|
|
1803
|
-
|
|
1804
|
-
/*
|
|
1805
|
-
** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
|
|
1806
|
-
*/
|
|
1807
|
-
|
|
1808
|
-
#ifndef NULL_INTPTR_T
|
|
1809
|
-
# define NULL_INTPTR_T ((intptr_t)(0))
|
|
1810
|
-
#endif
|
|
1811
|
-
|
|
1812
|
-
#ifndef BAD_INTPTR_T
|
|
1813
|
-
# define BAD_INTPTR_T ((intptr_t)(-1))
|
|
1814
|
-
#endif
|
|
1815
|
-
|
|
1816
|
-
/*
|
|
1817
|
-
** We need to provide the necessary structures and related types.
|
|
1818
|
-
*/
|
|
1819
|
-
|
|
1820
|
-
#ifndef DIRENT_DEFINED
|
|
1821
|
-
#define DIRENT_DEFINED
|
|
1822
|
-
typedef struct DIRENT DIRENT;
|
|
1823
|
-
typedef DIRENT *LPDIRENT;
|
|
1824
|
-
struct DIRENT {
|
|
1825
|
-
ino_t d_ino; /* Sequence number, do not use. */
|
|
1826
|
-
unsigned d_attributes; /* Win32 file attributes. */
|
|
1827
|
-
char d_name[NAME_MAX + 1]; /* Name within the directory. */
|
|
1829
|
+
struct dirent {
|
|
1830
|
+
int d_ino; /* Inode number (synthesized) */
|
|
1831
|
+
unsigned d_attributes; /* File attributes */
|
|
1832
|
+
char d_name[FILENAME_MAX]; /* Null-terminated filename */
|
|
1828
1833
|
};
|
|
1829
|
-
#endif
|
|
1830
1834
|
|
|
1831
|
-
|
|
1832
|
-
|
|
1835
|
+
/* The internals of DIR are opaque according to standards. So it
|
|
1836
|
+
** does not matter what we put here. */
|
|
1833
1837
|
typedef struct DIR DIR;
|
|
1834
|
-
typedef DIR *LPDIR;
|
|
1835
1838
|
struct DIR {
|
|
1836
|
-
intptr_t d_handle;
|
|
1837
|
-
|
|
1838
|
-
DIRENT d_next; /* DIRENT constructed based on "_findnext". */
|
|
1839
|
+
intptr_t d_handle; /* Handle for findfirst()/findnext() */
|
|
1840
|
+
struct dirent cur; /* Current entry */
|
|
1839
1841
|
};
|
|
1840
|
-
#endif
|
|
1841
|
-
|
|
1842
|
-
/*
|
|
1843
|
-
** Provide a macro, for use by the implementation, to determine if a
|
|
1844
|
-
** particular directory entry should be skipped over when searching for
|
|
1845
|
-
** the next directory entry that should be returned by the readdir().
|
|
1846
|
-
*/
|
|
1847
1842
|
|
|
1848
|
-
|
|
1849
|
-
#
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
/*
|
|
1853
|
-
** Provide the function prototype for the POSIX compatible getenv()
|
|
1854
|
-
** function. This function is not thread-safe.
|
|
1855
|
-
*/
|
|
1856
|
-
|
|
1857
|
-
extern const char *windirent_getenv(const char *name);
|
|
1858
|
-
|
|
1859
|
-
/*
|
|
1860
|
-
** Finally, we can provide the function prototypes for the opendir(),
|
|
1861
|
-
** readdir(), and closedir() POSIX functions.
|
|
1862
|
-
*/
|
|
1863
|
-
|
|
1864
|
-
extern LPDIR opendir(const char *dirname);
|
|
1865
|
-
extern LPDIRENT readdir(LPDIR dirp);
|
|
1866
|
-
extern INT closedir(LPDIR dirp);
|
|
1867
|
-
|
|
1868
|
-
#endif /* defined(WIN32) && defined(_MSC_VER) */
|
|
1869
|
-
|
|
1870
|
-
/************************* End test_windirent.h ********************/
|
|
1871
|
-
/************************* Begin test_windirent.c ******************/
|
|
1872
|
-
/*
|
|
1873
|
-
** 2015 November 30
|
|
1874
|
-
**
|
|
1875
|
-
** The author disclaims copyright to this source code. In place of
|
|
1876
|
-
** a legal notice, here is a blessing:
|
|
1877
|
-
**
|
|
1878
|
-
** May you do good and not evil.
|
|
1879
|
-
** May you find forgiveness for yourself and forgive others.
|
|
1880
|
-
** May you share freely, never taking more than you give.
|
|
1881
|
-
**
|
|
1882
|
-
*************************************************************************
|
|
1883
|
-
** This file contains code to implement most of the opendir() family of
|
|
1884
|
-
** POSIX functions on Win32 using the MSVCRT.
|
|
1885
|
-
*/
|
|
1886
|
-
|
|
1887
|
-
#if defined(_WIN32) && defined(_MSC_VER)
|
|
1888
|
-
/* #include "test_windirent.h" */
|
|
1843
|
+
/* Ignore hidden and system files */
|
|
1844
|
+
#define WindowsFileToIgnore(a) \
|
|
1845
|
+
((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
|
|
1889
1846
|
|
|
1890
1847
|
/*
|
|
1891
|
-
**
|
|
1892
|
-
** This function is not thread-safe.
|
|
1848
|
+
** Close a previously opened directory
|
|
1893
1849
|
*/
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
){
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
memset(value, 0, sizeof(value));
|
|
1902
|
-
dwRet = GetEnvironmentVariableA(name, value, dwSize);
|
|
1903
|
-
if( dwRet==0 || dwRet>dwSize ){
|
|
1904
|
-
/*
|
|
1905
|
-
** The function call to GetEnvironmentVariableA() failed -OR-
|
|
1906
|
-
** the buffer is not large enough. Either way, return NULL.
|
|
1907
|
-
*/
|
|
1908
|
-
return 0;
|
|
1909
|
-
}else{
|
|
1910
|
-
/*
|
|
1911
|
-
** The function call to GetEnvironmentVariableA() succeeded
|
|
1912
|
-
** -AND- the buffer contains the entire value.
|
|
1913
|
-
*/
|
|
1914
|
-
return value;
|
|
1850
|
+
static int closedir(DIR *pDir){
|
|
1851
|
+
int rc = 0;
|
|
1852
|
+
if( pDir==0 ){
|
|
1853
|
+
return EINVAL;
|
|
1854
|
+
}
|
|
1855
|
+
if( pDir->d_handle!=0 && pDir->d_handle!=(-1) ){
|
|
1856
|
+
rc = _findclose(pDir->d_handle);
|
|
1915
1857
|
}
|
|
1858
|
+
sqlite3_free(pDir);
|
|
1859
|
+
return rc;
|
|
1916
1860
|
}
|
|
1917
1861
|
|
|
1918
1862
|
/*
|
|
1919
|
-
**
|
|
1863
|
+
** Open a new directory. The directory name should be UTF-8 encoded.
|
|
1864
|
+
** appropriate translations happen automatically.
|
|
1920
1865
|
*/
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
){
|
|
1924
|
-
struct _wfinddata_t data;
|
|
1925
|
-
LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
|
|
1926
|
-
SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
|
|
1866
|
+
static DIR *opendir(const char *zDirName){
|
|
1867
|
+
DIR *pDir;
|
|
1927
1868
|
wchar_t *b1;
|
|
1928
1869
|
sqlite3_int64 sz;
|
|
1870
|
+
struct _wfinddata_t data;
|
|
1929
1871
|
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
/* TODO: Remove this if Unix-style root paths are not used. */
|
|
1934
|
-
if( sqlite3_stricmp(dirname, "/")==0 ){
|
|
1935
|
-
dirname = windirent_getenv("SystemDrive");
|
|
1936
|
-
}
|
|
1937
|
-
|
|
1872
|
+
pDir = sqlite3_malloc64( sizeof(DIR) );
|
|
1873
|
+
if( pDir==0 ) return 0;
|
|
1874
|
+
memset(pDir, 0, sizeof(DIR));
|
|
1938
1875
|
memset(&data, 0, sizeof(data));
|
|
1939
|
-
sz = strlen(
|
|
1876
|
+
sz = strlen(zDirName);
|
|
1940
1877
|
b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
|
|
1941
1878
|
if( b1==0 ){
|
|
1942
|
-
closedir(
|
|
1879
|
+
closedir(pDir);
|
|
1943
1880
|
return NULL;
|
|
1944
1881
|
}
|
|
1945
|
-
sz = MultiByteToWideChar(CP_UTF8, 0,
|
|
1882
|
+
sz = MultiByteToWideChar(CP_UTF8, 0, zDirName, sz, b1, sz);
|
|
1946
1883
|
b1[sz++] = '\\';
|
|
1947
1884
|
b1[sz++] = '*';
|
|
1948
1885
|
b1[sz] = 0;
|
|
1949
|
-
if( sz+1>(
|
|
1950
|
-
closedir(
|
|
1886
|
+
if( sz+1>sizeof(data.name)/sizeof(data.name[0]) ){
|
|
1887
|
+
closedir(pDir);
|
|
1951
1888
|
sqlite3_free(b1);
|
|
1952
1889
|
return NULL;
|
|
1953
1890
|
}
|
|
1954
1891
|
memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
|
|
1955
1892
|
sqlite3_free(b1);
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
closedir(dirp);
|
|
1893
|
+
pDir->d_handle = _wfindfirst(data.name, &data);
|
|
1894
|
+
if( pDir->d_handle<0 ){
|
|
1895
|
+
closedir(pDir);
|
|
1960
1896
|
return NULL;
|
|
1961
1897
|
}
|
|
1962
|
-
|
|
1963
|
-
/* TODO: Remove this block to allow hidden and/or system files. */
|
|
1964
|
-
if( is_filtered(data) ){
|
|
1965
|
-
next:
|
|
1966
|
-
|
|
1898
|
+
while( WindowsFileToIgnore(data) ){
|
|
1967
1899
|
memset(&data, 0, sizeof(data));
|
|
1968
|
-
if( _wfindnext(
|
|
1969
|
-
closedir(
|
|
1900
|
+
if( _wfindnext(pDir->d_handle, &data)==-1 ){
|
|
1901
|
+
closedir(pDir);
|
|
1970
1902
|
return NULL;
|
|
1971
1903
|
}
|
|
1972
|
-
|
|
1973
|
-
/* TODO: Remove this block to allow hidden and/or system files. */
|
|
1974
|
-
if( is_filtered(data) ) goto next;
|
|
1975
1904
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
1905
|
+
pDir->cur.d_ino = 0;
|
|
1906
|
+
pDir->cur.d_attributes = data.attrib;
|
|
1978
1907
|
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
|
|
1979
|
-
|
|
1980
|
-
return
|
|
1908
|
+
pDir->cur.d_name, FILENAME_MAX, 0, 0);
|
|
1909
|
+
return pDir;
|
|
1981
1910
|
}
|
|
1982
1911
|
|
|
1983
1912
|
/*
|
|
1984
|
-
**
|
|
1913
|
+
** Read the next entry from a directory.
|
|
1914
|
+
**
|
|
1915
|
+
** The returned struct-dirent object is managed by DIR. It is only
|
|
1916
|
+
** valid until the next readdir() or closedir() call. Only the
|
|
1917
|
+
** d_name[] field is meaningful. The d_name[] value has been
|
|
1918
|
+
** translated into UTF8.
|
|
1985
1919
|
*/
|
|
1986
|
-
|
|
1987
|
-
LPDIR dirp
|
|
1988
|
-
){
|
|
1920
|
+
static struct dirent *readdir(DIR *pDir){
|
|
1989
1921
|
struct _wfinddata_t data;
|
|
1990
|
-
|
|
1991
|
-
if(
|
|
1992
|
-
|
|
1993
|
-
if( dirp->d_first.d_ino==0 ){
|
|
1994
|
-
dirp->d_first.d_ino++;
|
|
1995
|
-
dirp->d_next.d_ino++;
|
|
1996
|
-
|
|
1997
|
-
return &dirp->d_first;
|
|
1922
|
+
if( pDir==0 ) return 0;
|
|
1923
|
+
if( (pDir->cur.d_ino++)==0 ){
|
|
1924
|
+
return &pDir->cur;
|
|
1998
1925
|
}
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
if( is_filtered(data) ) goto next;
|
|
2007
|
-
|
|
2008
|
-
dirp->d_next.d_ino++;
|
|
2009
|
-
dirp->d_next.d_attributes = data.attrib;
|
|
1926
|
+
do{
|
|
1927
|
+
memset(&data, 0, sizeof(data));
|
|
1928
|
+
if( _wfindnext(pDir->d_handle, &data)==-1 ){
|
|
1929
|
+
return NULL;
|
|
1930
|
+
}
|
|
1931
|
+
}while( WindowsFileToIgnore(data) );
|
|
1932
|
+
pDir->cur.d_attributes = data.attrib;
|
|
2010
1933
|
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
|
|
2011
|
-
|
|
2012
|
-
return &
|
|
2013
|
-
}
|
|
2014
|
-
|
|
2015
|
-
/*
|
|
2016
|
-
** Implementation of the POSIX closedir() function using the MSVCRT.
|
|
2017
|
-
*/
|
|
2018
|
-
INT closedir(
|
|
2019
|
-
LPDIR dirp
|
|
2020
|
-
){
|
|
2021
|
-
INT result = 0;
|
|
2022
|
-
|
|
2023
|
-
if( dirp==NULL ) return EINVAL;
|
|
2024
|
-
|
|
2025
|
-
if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
|
|
2026
|
-
result = _findclose(dirp->d_handle);
|
|
2027
|
-
}
|
|
2028
|
-
|
|
2029
|
-
sqlite3_free(dirp);
|
|
2030
|
-
return result;
|
|
1934
|
+
pDir->cur.d_name, FILENAME_MAX, 0, 0);
|
|
1935
|
+
return &pDir->cur;
|
|
2031
1936
|
}
|
|
2032
1937
|
|
|
2033
|
-
#endif /* defined(
|
|
1938
|
+
#endif /* defined(_WIN32) && defined(_MSC_VER) */
|
|
2034
1939
|
|
|
2035
|
-
/************************* End
|
|
2036
|
-
#define dirent DIRENT
|
|
2037
|
-
#endif
|
|
1940
|
+
/************************* End ../ext/misc/windirent.h ********************/
|
|
2038
1941
|
/************************* Begin ../ext/misc/memtrace.c ******************/
|
|
2039
1942
|
/*
|
|
2040
1943
|
** 2019-01-21
|
|
@@ -3823,7 +3726,8 @@ static Decimal *decimalNewFromText(const char *zIn, int n){
|
|
|
3823
3726
|
}
|
|
3824
3727
|
}
|
|
3825
3728
|
if( iExp>0 ){
|
|
3826
|
-
p->a = sqlite3_realloc64(p->a, p->nDigit
|
|
3729
|
+
p->a = sqlite3_realloc64(p->a, (sqlite3_int64)p->nDigit
|
|
3730
|
+
+ (sqlite3_int64)iExp + 1 );
|
|
3827
3731
|
if( p->a==0 ) goto new_from_text_failed;
|
|
3828
3732
|
memset(p->a+p->nDigit, 0, iExp);
|
|
3829
3733
|
p->nDigit += iExp;
|
|
@@ -3842,7 +3746,8 @@ static Decimal *decimalNewFromText(const char *zIn, int n){
|
|
|
3842
3746
|
}
|
|
3843
3747
|
}
|
|
3844
3748
|
if( iExp>0 ){
|
|
3845
|
-
p->a = sqlite3_realloc64(p->a, p->nDigit
|
|
3749
|
+
p->a = sqlite3_realloc64(p->a, (sqlite3_int64)p->nDigit
|
|
3750
|
+
+ (sqlite3_int64)iExp + 1 );
|
|
3846
3751
|
if( p->a==0 ) goto new_from_text_failed;
|
|
3847
3752
|
memmove(p->a+iExp, p->a, p->nDigit);
|
|
3848
3753
|
memset(p->a, 0, iExp);
|
|
@@ -3850,6 +3755,10 @@ static Decimal *decimalNewFromText(const char *zIn, int n){
|
|
|
3850
3755
|
p->nFrac += iExp;
|
|
3851
3756
|
}
|
|
3852
3757
|
}
|
|
3758
|
+
if( p->sign ){
|
|
3759
|
+
for(i=0; i<p->nDigit && p->a[i]==0; i++){}
|
|
3760
|
+
if( i>=p->nDigit ) p->sign = 0;
|
|
3761
|
+
}
|
|
3853
3762
|
return p;
|
|
3854
3763
|
|
|
3855
3764
|
new_from_text_failed:
|
|
@@ -3942,7 +3851,7 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
|
|
|
3942
3851
|
sqlite3_result_null(pCtx);
|
|
3943
3852
|
return;
|
|
3944
3853
|
}
|
|
3945
|
-
z =
|
|
3854
|
+
z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+4 );
|
|
3946
3855
|
if( z==0 ){
|
|
3947
3856
|
sqlite3_result_error_nomem(pCtx);
|
|
3948
3857
|
return;
|
|
@@ -4007,7 +3916,7 @@ static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
|
|
|
4007
3916
|
for(nZero=0; nZero<nDigit && p->a[nZero]==0; nZero++){}
|
|
4008
3917
|
nFrac = p->nFrac + (nDigit - p->nDigit);
|
|
4009
3918
|
nDigit -= nZero;
|
|
4010
|
-
z =
|
|
3919
|
+
z = sqlite3_malloc64( (sqlite3_int64)nDigit+20 );
|
|
4011
3920
|
if( z==0 ){
|
|
4012
3921
|
sqlite3_result_error_nomem(pCtx);
|
|
4013
3922
|
return;
|
|
@@ -4052,13 +3961,21 @@ static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
|
|
|
4052
3961
|
** pB!=0
|
|
4053
3962
|
** pB->isNull==0
|
|
4054
3963
|
*/
|
|
4055
|
-
static int decimal_cmp(
|
|
3964
|
+
static int decimal_cmp(Decimal *pA, Decimal *pB){
|
|
4056
3965
|
int nASig, nBSig, rc, n;
|
|
3966
|
+
while( pA->nFrac>0 && pA->a[pA->nDigit-1]==0 ){
|
|
3967
|
+
pA->nDigit--;
|
|
3968
|
+
pA->nFrac--;
|
|
3969
|
+
}
|
|
3970
|
+
while( pB->nFrac>0 && pB->a[pB->nDigit-1]==0 ){
|
|
3971
|
+
pB->nDigit--;
|
|
3972
|
+
pB->nFrac--;
|
|
3973
|
+
}
|
|
4057
3974
|
if( pA->sign!=pB->sign ){
|
|
4058
3975
|
return pA->sign ? -1 : +1;
|
|
4059
3976
|
}
|
|
4060
3977
|
if( pA->sign ){
|
|
4061
|
-
|
|
3978
|
+
Decimal *pTemp = pA;
|
|
4062
3979
|
pA = pB;
|
|
4063
3980
|
pB = pTemp;
|
|
4064
3981
|
}
|
|
@@ -4220,7 +4137,8 @@ static void decimalMul(Decimal *pA, Decimal *pB){
|
|
|
4220
4137
|
){
|
|
4221
4138
|
goto mul_end;
|
|
4222
4139
|
}
|
|
4223
|
-
acc = sqlite3_malloc64( pA->nDigit +
|
|
4140
|
+
acc = sqlite3_malloc64( (sqlite3_int64)pA->nDigit +
|
|
4141
|
+
(sqlite3_int64)pB->nDigit + 2 );
|
|
4224
4142
|
if( acc==0 ){
|
|
4225
4143
|
pA->oom = 1;
|
|
4226
4144
|
goto mul_end;
|
|
@@ -4307,7 +4225,7 @@ static Decimal *decimalFromDouble(double r){
|
|
|
4307
4225
|
isNeg = 0;
|
|
4308
4226
|
}
|
|
4309
4227
|
memcpy(&a,&r,sizeof(a));
|
|
4310
|
-
if( a==0 ){
|
|
4228
|
+
if( a==0 || a==(sqlite3_int64)0x8000000000000000LL){
|
|
4311
4229
|
e = 0;
|
|
4312
4230
|
m = 0;
|
|
4313
4231
|
}else{
|
|
@@ -4582,512 +4500,6 @@ int sqlite3_decimal_init(
|
|
|
4582
4500
|
}
|
|
4583
4501
|
|
|
4584
4502
|
/************************* End ../ext/misc/decimal.c ********************/
|
|
4585
|
-
/************************* Begin ../ext/misc/percentile.c ******************/
|
|
4586
|
-
/*
|
|
4587
|
-
** 2013-05-28
|
|
4588
|
-
**
|
|
4589
|
-
** The author disclaims copyright to this source code. In place of
|
|
4590
|
-
** a legal notice, here is a blessing:
|
|
4591
|
-
**
|
|
4592
|
-
** May you do good and not evil.
|
|
4593
|
-
** May you find forgiveness for yourself and forgive others.
|
|
4594
|
-
** May you share freely, never taking more than you give.
|
|
4595
|
-
**
|
|
4596
|
-
******************************************************************************
|
|
4597
|
-
**
|
|
4598
|
-
** This file contains code to implement the percentile(Y,P) SQL function
|
|
4599
|
-
** and similar as described below:
|
|
4600
|
-
**
|
|
4601
|
-
** (1) The percentile(Y,P) function is an aggregate function taking
|
|
4602
|
-
** exactly two arguments.
|
|
4603
|
-
**
|
|
4604
|
-
** (2) If the P argument to percentile(Y,P) is not the same for every
|
|
4605
|
-
** row in the aggregate then an error is thrown. The word "same"
|
|
4606
|
-
** in the previous sentence means that the value differ by less
|
|
4607
|
-
** than 0.001.
|
|
4608
|
-
**
|
|
4609
|
-
** (3) If the P argument to percentile(Y,P) evaluates to anything other
|
|
4610
|
-
** than a number in the range of 0.0 to 100.0 inclusive then an
|
|
4611
|
-
** error is thrown.
|
|
4612
|
-
**
|
|
4613
|
-
** (4) If any Y argument to percentile(Y,P) evaluates to a value that
|
|
4614
|
-
** is not NULL and is not numeric then an error is thrown.
|
|
4615
|
-
**
|
|
4616
|
-
** (5) If any Y argument to percentile(Y,P) evaluates to plus or minus
|
|
4617
|
-
** infinity then an error is thrown. (SQLite always interprets NaN
|
|
4618
|
-
** values as NULL.)
|
|
4619
|
-
**
|
|
4620
|
-
** (6) Both Y and P in percentile(Y,P) can be arbitrary expressions,
|
|
4621
|
-
** including CASE WHEN expressions.
|
|
4622
|
-
**
|
|
4623
|
-
** (7) The percentile(Y,P) aggregate is able to handle inputs of at least
|
|
4624
|
-
** one million (1,000,000) rows.
|
|
4625
|
-
**
|
|
4626
|
-
** (8) If there are no non-NULL values for Y, then percentile(Y,P)
|
|
4627
|
-
** returns NULL.
|
|
4628
|
-
**
|
|
4629
|
-
** (9) If there is exactly one non-NULL value for Y, the percentile(Y,P)
|
|
4630
|
-
** returns the one Y value.
|
|
4631
|
-
**
|
|
4632
|
-
** (10) If there N non-NULL values of Y where N is two or more and
|
|
4633
|
-
** the Y values are ordered from least to greatest and a graph is
|
|
4634
|
-
** drawn from 0 to N-1 such that the height of the graph at J is
|
|
4635
|
-
** the J-th Y value and such that straight lines are drawn between
|
|
4636
|
-
** adjacent Y values, then the percentile(Y,P) function returns
|
|
4637
|
-
** the height of the graph at P*(N-1)/100.
|
|
4638
|
-
**
|
|
4639
|
-
** (11) The percentile(Y,P) function always returns either a floating
|
|
4640
|
-
** point number or NULL.
|
|
4641
|
-
**
|
|
4642
|
-
** (12) The percentile(Y,P) is implemented as a single C99 source-code
|
|
4643
|
-
** file that compiles into a shared-library or DLL that can be loaded
|
|
4644
|
-
** into SQLite using the sqlite3_load_extension() interface.
|
|
4645
|
-
**
|
|
4646
|
-
** (13) A separate median(Y) function is the equivalent percentile(Y,50).
|
|
4647
|
-
**
|
|
4648
|
-
** (14) A separate percentile_cont(Y,P) function is equivalent to
|
|
4649
|
-
** percentile(Y,P/100.0). In other words, the fraction value in
|
|
4650
|
-
** the second argument is in the range of 0 to 1 instead of 0 to 100.
|
|
4651
|
-
**
|
|
4652
|
-
** (15) A separate percentile_disc(Y,P) function is like
|
|
4653
|
-
** percentile_cont(Y,P) except that instead of returning the weighted
|
|
4654
|
-
** average of the nearest two input values, it returns the next lower
|
|
4655
|
-
** value. So the percentile_disc(Y,P) will always return a value
|
|
4656
|
-
** that was one of the inputs.
|
|
4657
|
-
**
|
|
4658
|
-
** (16) All of median(), percentile(Y,P), percentile_cont(Y,P) and
|
|
4659
|
-
** percentile_disc(Y,P) can be used as window functions.
|
|
4660
|
-
**
|
|
4661
|
-
** Differences from standard SQL:
|
|
4662
|
-
**
|
|
4663
|
-
** * The percentile_cont(X,P) function is equivalent to the following in
|
|
4664
|
-
** standard SQL:
|
|
4665
|
-
**
|
|
4666
|
-
** (percentile_cont(P) WITHIN GROUP (ORDER BY X))
|
|
4667
|
-
**
|
|
4668
|
-
** The SQLite syntax is much more compact. The standard SQL syntax
|
|
4669
|
-
** is also supported if SQLite is compiled with the
|
|
4670
|
-
** -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES option.
|
|
4671
|
-
**
|
|
4672
|
-
** * No median(X) function exists in the SQL standard. App developers
|
|
4673
|
-
** are expected to write "percentile_cont(0.5)WITHIN GROUP(ORDER BY X)".
|
|
4674
|
-
**
|
|
4675
|
-
** * No percentile(Y,P) function exists in the SQL standard. Instead of
|
|
4676
|
-
** percential(Y,P), developers must write this:
|
|
4677
|
-
** "percentile_cont(P/100.0) WITHIN GROUP (ORDER BY Y)". Note that
|
|
4678
|
-
** the fraction parameter to percentile() goes from 0 to 100 whereas
|
|
4679
|
-
** the fraction parameter in SQL standard percentile_cont() goes from
|
|
4680
|
-
** 0 to 1.
|
|
4681
|
-
**
|
|
4682
|
-
** Implementation notes as of 2024-08-31:
|
|
4683
|
-
**
|
|
4684
|
-
** * The regular aggregate-function versions of these routines work
|
|
4685
|
-
** by accumulating all values in an array of doubles, then sorting
|
|
4686
|
-
** that array using quicksort before computing the answer. Thus
|
|
4687
|
-
** the runtime is O(NlogN) where N is the number of rows of input.
|
|
4688
|
-
**
|
|
4689
|
-
** * For the window-function versions of these routines, the array of
|
|
4690
|
-
** inputs is sorted as soon as the first value is computed. Thereafter,
|
|
4691
|
-
** the array is kept in sorted order using an insert-sort. This
|
|
4692
|
-
** results in O(N*K) performance where K is the size of the window.
|
|
4693
|
-
** One can imagine alternative implementations that give O(N*logN*logK)
|
|
4694
|
-
** performance, but they require more complex logic and data structures.
|
|
4695
|
-
** The developers have elected to keep the asymptotically slower
|
|
4696
|
-
** algorithm for now, for simplicity, under the theory that window
|
|
4697
|
-
** functions are seldom used and when they are, the window size K is
|
|
4698
|
-
** often small. The developers might revisit that decision later,
|
|
4699
|
-
** should the need arise.
|
|
4700
|
-
*/
|
|
4701
|
-
#if defined(SQLITE3_H)
|
|
4702
|
-
/* no-op */
|
|
4703
|
-
#elif defined(SQLITE_STATIC_PERCENTILE)
|
|
4704
|
-
/* # include "sqlite3.h" */
|
|
4705
|
-
#else
|
|
4706
|
-
/* # include "sqlite3ext.h" */
|
|
4707
|
-
SQLITE_EXTENSION_INIT1
|
|
4708
|
-
#endif
|
|
4709
|
-
#include <assert.h>
|
|
4710
|
-
#include <string.h>
|
|
4711
|
-
#include <stdlib.h>
|
|
4712
|
-
|
|
4713
|
-
/* The following object is the group context for a single percentile()
|
|
4714
|
-
** aggregate. Remember all input Y values until the very end.
|
|
4715
|
-
** Those values are accumulated in the Percentile.a[] array.
|
|
4716
|
-
*/
|
|
4717
|
-
typedef struct Percentile Percentile;
|
|
4718
|
-
struct Percentile {
|
|
4719
|
-
unsigned nAlloc; /* Number of slots allocated for a[] */
|
|
4720
|
-
unsigned nUsed; /* Number of slots actually used in a[] */
|
|
4721
|
-
char bSorted; /* True if a[] is already in sorted order */
|
|
4722
|
-
char bKeepSorted; /* True if advantageous to keep a[] sorted */
|
|
4723
|
-
char bPctValid; /* True if rPct is valid */
|
|
4724
|
-
double rPct; /* Fraction. 0.0 to 1.0 */
|
|
4725
|
-
double *a; /* Array of Y values */
|
|
4726
|
-
};
|
|
4727
|
-
|
|
4728
|
-
/* Details of each function in the percentile family */
|
|
4729
|
-
typedef struct PercentileFunc PercentileFunc;
|
|
4730
|
-
struct PercentileFunc {
|
|
4731
|
-
const char *zName; /* Function name */
|
|
4732
|
-
char nArg; /* Number of arguments */
|
|
4733
|
-
char mxFrac; /* Maximum value of the "fraction" input */
|
|
4734
|
-
char bDiscrete; /* True for percentile_disc() */
|
|
4735
|
-
};
|
|
4736
|
-
static const PercentileFunc aPercentFunc[] = {
|
|
4737
|
-
{ "median", 1, 1, 0 },
|
|
4738
|
-
{ "percentile", 2, 100, 0 },
|
|
4739
|
-
{ "percentile_cont", 2, 1, 0 },
|
|
4740
|
-
{ "percentile_disc", 2, 1, 1 },
|
|
4741
|
-
};
|
|
4742
|
-
|
|
4743
|
-
/*
|
|
4744
|
-
** Return TRUE if the input floating-point number is an infinity.
|
|
4745
|
-
*/
|
|
4746
|
-
static int percentIsInfinity(double r){
|
|
4747
|
-
sqlite3_uint64 u;
|
|
4748
|
-
assert( sizeof(u)==sizeof(r) );
|
|
4749
|
-
memcpy(&u, &r, sizeof(u));
|
|
4750
|
-
return ((u>>52)&0x7ff)==0x7ff;
|
|
4751
|
-
}
|
|
4752
|
-
|
|
4753
|
-
/*
|
|
4754
|
-
** Return TRUE if two doubles differ by 0.001 or less.
|
|
4755
|
-
*/
|
|
4756
|
-
static int percentSameValue(double a, double b){
|
|
4757
|
-
a -= b;
|
|
4758
|
-
return a>=-0.001 && a<=0.001;
|
|
4759
|
-
}
|
|
4760
|
-
|
|
4761
|
-
/*
|
|
4762
|
-
** Search p (which must have p->bSorted) looking for an entry with
|
|
4763
|
-
** value y. Return the index of that entry.
|
|
4764
|
-
**
|
|
4765
|
-
** If bExact is true, return -1 if the entry is not found.
|
|
4766
|
-
**
|
|
4767
|
-
** If bExact is false, return the index at which a new entry with
|
|
4768
|
-
** value y should be insert in order to keep the values in sorted
|
|
4769
|
-
** order. The smallest return value in this case will be 0, and
|
|
4770
|
-
** the largest return value will be p->nUsed.
|
|
4771
|
-
*/
|
|
4772
|
-
static int percentBinarySearch(Percentile *p, double y, int bExact){
|
|
4773
|
-
int iFirst = 0; /* First element of search range */
|
|
4774
|
-
int iLast = p->nUsed - 1; /* Last element of search range */
|
|
4775
|
-
while( iLast>=iFirst ){
|
|
4776
|
-
int iMid = (iFirst+iLast)/2;
|
|
4777
|
-
double x = p->a[iMid];
|
|
4778
|
-
if( x<y ){
|
|
4779
|
-
iFirst = iMid + 1;
|
|
4780
|
-
}else if( x>y ){
|
|
4781
|
-
iLast = iMid - 1;
|
|
4782
|
-
}else{
|
|
4783
|
-
return iMid;
|
|
4784
|
-
}
|
|
4785
|
-
}
|
|
4786
|
-
if( bExact ) return -1;
|
|
4787
|
-
return iFirst;
|
|
4788
|
-
}
|
|
4789
|
-
|
|
4790
|
-
/*
|
|
4791
|
-
** Generate an error for a percentile function.
|
|
4792
|
-
**
|
|
4793
|
-
** The error format string must have exactly one occurrence of "%%s()"
|
|
4794
|
-
** (with two '%' characters). That substring will be replaced by the name
|
|
4795
|
-
** of the function.
|
|
4796
|
-
*/
|
|
4797
|
-
static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){
|
|
4798
|
-
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
|
|
4799
|
-
char *zMsg1;
|
|
4800
|
-
char *zMsg2;
|
|
4801
|
-
va_list ap;
|
|
4802
|
-
|
|
4803
|
-
va_start(ap, zFormat);
|
|
4804
|
-
zMsg1 = sqlite3_vmprintf(zFormat, ap);
|
|
4805
|
-
va_end(ap);
|
|
4806
|
-
zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, pFunc->zName) : 0;
|
|
4807
|
-
sqlite3_result_error(pCtx, zMsg2, -1);
|
|
4808
|
-
sqlite3_free(zMsg1);
|
|
4809
|
-
sqlite3_free(zMsg2);
|
|
4810
|
-
}
|
|
4811
|
-
|
|
4812
|
-
/*
|
|
4813
|
-
** The "step" function for percentile(Y,P) is called once for each
|
|
4814
|
-
** input row.
|
|
4815
|
-
*/
|
|
4816
|
-
static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
|
|
4817
|
-
Percentile *p;
|
|
4818
|
-
double rPct;
|
|
4819
|
-
int eType;
|
|
4820
|
-
double y;
|
|
4821
|
-
assert( argc==2 || argc==1 );
|
|
4822
|
-
|
|
4823
|
-
if( argc==1 ){
|
|
4824
|
-
/* Requirement 13: median(Y) is the same as percentile(Y,50). */
|
|
4825
|
-
rPct = 0.5;
|
|
4826
|
-
}else{
|
|
4827
|
-
/* Requirement 3: P must be a number between 0 and 100 */
|
|
4828
|
-
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
|
|
4829
|
-
eType = sqlite3_value_numeric_type(argv[1]);
|
|
4830
|
-
rPct = sqlite3_value_double(argv[1])/(double)pFunc->mxFrac;
|
|
4831
|
-
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
|
|
4832
|
-
|| rPct<0.0 || rPct>1.0
|
|
4833
|
-
){
|
|
4834
|
-
percentError(pCtx, "the fraction argument to %%s()"
|
|
4835
|
-
" is not between 0.0 and %.1f",
|
|
4836
|
-
(double)pFunc->mxFrac);
|
|
4837
|
-
return;
|
|
4838
|
-
}
|
|
4839
|
-
}
|
|
4840
|
-
|
|
4841
|
-
/* Allocate the session context. */
|
|
4842
|
-
p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
|
|
4843
|
-
if( p==0 ) return;
|
|
4844
|
-
|
|
4845
|
-
/* Remember the P value. Throw an error if the P value is different
|
|
4846
|
-
** from any prior row, per Requirement (2). */
|
|
4847
|
-
if( !p->bPctValid ){
|
|
4848
|
-
p->rPct = rPct;
|
|
4849
|
-
p->bPctValid = 1;
|
|
4850
|
-
}else if( !percentSameValue(p->rPct,rPct) ){
|
|
4851
|
-
percentError(pCtx, "the fraction argument to %%s()"
|
|
4852
|
-
" is not the same for all input rows");
|
|
4853
|
-
return;
|
|
4854
|
-
}
|
|
4855
|
-
|
|
4856
|
-
/* Ignore rows for which Y is NULL */
|
|
4857
|
-
eType = sqlite3_value_type(argv[0]);
|
|
4858
|
-
if( eType==SQLITE_NULL ) return;
|
|
4859
|
-
|
|
4860
|
-
/* If not NULL, then Y must be numeric. Otherwise throw an error.
|
|
4861
|
-
** Requirement 4 */
|
|
4862
|
-
if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
|
|
4863
|
-
percentError(pCtx, "input to %%s() is not numeric");
|
|
4864
|
-
return;
|
|
4865
|
-
}
|
|
4866
|
-
|
|
4867
|
-
/* Throw an error if the Y value is infinity or NaN */
|
|
4868
|
-
y = sqlite3_value_double(argv[0]);
|
|
4869
|
-
if( percentIsInfinity(y) ){
|
|
4870
|
-
percentError(pCtx, "Inf input to %%s()");
|
|
4871
|
-
return;
|
|
4872
|
-
}
|
|
4873
|
-
|
|
4874
|
-
/* Allocate and store the Y */
|
|
4875
|
-
if( p->nUsed>=p->nAlloc ){
|
|
4876
|
-
unsigned n = p->nAlloc*2 + 250;
|
|
4877
|
-
double *a = sqlite3_realloc64(p->a, sizeof(double)*n);
|
|
4878
|
-
if( a==0 ){
|
|
4879
|
-
sqlite3_free(p->a);
|
|
4880
|
-
memset(p, 0, sizeof(*p));
|
|
4881
|
-
sqlite3_result_error_nomem(pCtx);
|
|
4882
|
-
return;
|
|
4883
|
-
}
|
|
4884
|
-
p->nAlloc = n;
|
|
4885
|
-
p->a = a;
|
|
4886
|
-
}
|
|
4887
|
-
if( p->nUsed==0 ){
|
|
4888
|
-
p->a[p->nUsed++] = y;
|
|
4889
|
-
p->bSorted = 1;
|
|
4890
|
-
}else if( !p->bSorted || y>=p->a[p->nUsed-1] ){
|
|
4891
|
-
p->a[p->nUsed++] = y;
|
|
4892
|
-
}else if( p->bKeepSorted ){
|
|
4893
|
-
int i;
|
|
4894
|
-
i = percentBinarySearch(p, y, 0);
|
|
4895
|
-
if( i<(int)p->nUsed ){
|
|
4896
|
-
memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0]));
|
|
4897
|
-
}
|
|
4898
|
-
p->a[i] = y;
|
|
4899
|
-
p->nUsed++;
|
|
4900
|
-
}else{
|
|
4901
|
-
p->a[p->nUsed++] = y;
|
|
4902
|
-
p->bSorted = 0;
|
|
4903
|
-
}
|
|
4904
|
-
}
|
|
4905
|
-
|
|
4906
|
-
/*
|
|
4907
|
-
** Interchange two doubles.
|
|
4908
|
-
*/
|
|
4909
|
-
#define SWAP_DOUBLE(X,Y) {double ttt=(X);(X)=(Y);(Y)=ttt;}
|
|
4910
|
-
|
|
4911
|
-
/*
|
|
4912
|
-
** Sort an array of doubles.
|
|
4913
|
-
**
|
|
4914
|
-
** Algorithm: quicksort
|
|
4915
|
-
**
|
|
4916
|
-
** This is implemented separately rather than using the qsort() routine
|
|
4917
|
-
** from the standard library because:
|
|
4918
|
-
**
|
|
4919
|
-
** (1) To avoid a dependency on qsort()
|
|
4920
|
-
** (2) To avoid the function call to the comparison routine for each
|
|
4921
|
-
** comparison.
|
|
4922
|
-
*/
|
|
4923
|
-
static void percentSort(double *a, unsigned int n){
|
|
4924
|
-
int iLt; /* Entries before a[iLt] are less than rPivot */
|
|
4925
|
-
int iGt; /* Entries at or after a[iGt] are greater than rPivot */
|
|
4926
|
-
int i; /* Loop counter */
|
|
4927
|
-
double rPivot; /* The pivot value */
|
|
4928
|
-
|
|
4929
|
-
assert( n>=2 );
|
|
4930
|
-
if( a[0]>a[n-1] ){
|
|
4931
|
-
SWAP_DOUBLE(a[0],a[n-1])
|
|
4932
|
-
}
|
|
4933
|
-
if( n==2 ) return;
|
|
4934
|
-
iGt = n-1;
|
|
4935
|
-
i = n/2;
|
|
4936
|
-
if( a[0]>a[i] ){
|
|
4937
|
-
SWAP_DOUBLE(a[0],a[i])
|
|
4938
|
-
}else if( a[i]>a[iGt] ){
|
|
4939
|
-
SWAP_DOUBLE(a[i],a[iGt])
|
|
4940
|
-
}
|
|
4941
|
-
if( n==3 ) return;
|
|
4942
|
-
rPivot = a[i];
|
|
4943
|
-
iLt = i = 1;
|
|
4944
|
-
do{
|
|
4945
|
-
if( a[i]<rPivot ){
|
|
4946
|
-
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
|
|
4947
|
-
iLt++;
|
|
4948
|
-
i++;
|
|
4949
|
-
}else if( a[i]>rPivot ){
|
|
4950
|
-
do{
|
|
4951
|
-
iGt--;
|
|
4952
|
-
}while( iGt>i && a[iGt]>rPivot );
|
|
4953
|
-
SWAP_DOUBLE(a[i],a[iGt])
|
|
4954
|
-
}else{
|
|
4955
|
-
i++;
|
|
4956
|
-
}
|
|
4957
|
-
}while( i<iGt );
|
|
4958
|
-
if( iLt>=2 ) percentSort(a, iLt);
|
|
4959
|
-
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
|
|
4960
|
-
|
|
4961
|
-
/* Uncomment for testing */
|
|
4962
|
-
#if 0
|
|
4963
|
-
for(i=0; i<n-1; i++){
|
|
4964
|
-
assert( a[i]<=a[i+1] );
|
|
4965
|
-
}
|
|
4966
|
-
#endif
|
|
4967
|
-
}
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
/*
|
|
4971
|
-
** The "inverse" function for percentile(Y,P) is called to remove a
|
|
4972
|
-
** row that was previously inserted by "step".
|
|
4973
|
-
*/
|
|
4974
|
-
static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
|
|
4975
|
-
Percentile *p;
|
|
4976
|
-
int eType;
|
|
4977
|
-
double y;
|
|
4978
|
-
int i;
|
|
4979
|
-
assert( argc==2 || argc==1 );
|
|
4980
|
-
|
|
4981
|
-
/* Allocate the session context. */
|
|
4982
|
-
p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
|
|
4983
|
-
assert( p!=0 );
|
|
4984
|
-
|
|
4985
|
-
/* Ignore rows for which Y is NULL */
|
|
4986
|
-
eType = sqlite3_value_type(argv[0]);
|
|
4987
|
-
if( eType==SQLITE_NULL ) return;
|
|
4988
|
-
|
|
4989
|
-
/* If not NULL, then Y must be numeric. Otherwise throw an error.
|
|
4990
|
-
** Requirement 4 */
|
|
4991
|
-
if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
|
|
4992
|
-
return;
|
|
4993
|
-
}
|
|
4994
|
-
|
|
4995
|
-
/* Ignore the Y value if it is infinity or NaN */
|
|
4996
|
-
y = sqlite3_value_double(argv[0]);
|
|
4997
|
-
if( percentIsInfinity(y) ){
|
|
4998
|
-
return;
|
|
4999
|
-
}
|
|
5000
|
-
if( p->bSorted==0 ){
|
|
5001
|
-
assert( p->nUsed>1 );
|
|
5002
|
-
percentSort(p->a, p->nUsed);
|
|
5003
|
-
p->bSorted = 1;
|
|
5004
|
-
}
|
|
5005
|
-
p->bKeepSorted = 1;
|
|
5006
|
-
|
|
5007
|
-
/* Find and remove the row */
|
|
5008
|
-
i = percentBinarySearch(p, y, 1);
|
|
5009
|
-
if( i>=0 ){
|
|
5010
|
-
p->nUsed--;
|
|
5011
|
-
if( i<(int)p->nUsed ){
|
|
5012
|
-
memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0]));
|
|
5013
|
-
}
|
|
5014
|
-
}
|
|
5015
|
-
}
|
|
5016
|
-
|
|
5017
|
-
/*
|
|
5018
|
-
** Compute the final output of percentile(). Clean up all allocated
|
|
5019
|
-
** memory if and only if bIsFinal is true.
|
|
5020
|
-
*/
|
|
5021
|
-
static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
|
|
5022
|
-
Percentile *p;
|
|
5023
|
-
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
|
|
5024
|
-
unsigned i1, i2;
|
|
5025
|
-
double v1, v2;
|
|
5026
|
-
double ix, vx;
|
|
5027
|
-
p = (Percentile*)sqlite3_aggregate_context(pCtx, 0);
|
|
5028
|
-
if( p==0 ) return;
|
|
5029
|
-
if( p->a==0 ) return;
|
|
5030
|
-
if( p->nUsed ){
|
|
5031
|
-
if( p->bSorted==0 ){
|
|
5032
|
-
assert( p->nUsed>1 );
|
|
5033
|
-
percentSort(p->a, p->nUsed);
|
|
5034
|
-
p->bSorted = 1;
|
|
5035
|
-
}
|
|
5036
|
-
ix = p->rPct*(p->nUsed-1);
|
|
5037
|
-
i1 = (unsigned)ix;
|
|
5038
|
-
if( pFunc->bDiscrete ){
|
|
5039
|
-
vx = p->a[i1];
|
|
5040
|
-
}else{
|
|
5041
|
-
i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
|
|
5042
|
-
v1 = p->a[i1];
|
|
5043
|
-
v2 = p->a[i2];
|
|
5044
|
-
vx = v1 + (v2-v1)*(ix-i1);
|
|
5045
|
-
}
|
|
5046
|
-
sqlite3_result_double(pCtx, vx);
|
|
5047
|
-
}
|
|
5048
|
-
if( bIsFinal ){
|
|
5049
|
-
sqlite3_free(p->a);
|
|
5050
|
-
memset(p, 0, sizeof(*p));
|
|
5051
|
-
}else{
|
|
5052
|
-
p->bKeepSorted = 1;
|
|
5053
|
-
}
|
|
5054
|
-
}
|
|
5055
|
-
static void percentFinal(sqlite3_context *pCtx){
|
|
5056
|
-
percentCompute(pCtx, 1);
|
|
5057
|
-
}
|
|
5058
|
-
static void percentValue(sqlite3_context *pCtx){
|
|
5059
|
-
percentCompute(pCtx, 0);
|
|
5060
|
-
}
|
|
5061
|
-
|
|
5062
|
-
#if defined(_WIN32) && !defined(SQLITE3_H) && !defined(SQLITE_STATIC_PERCENTILE)
|
|
5063
|
-
|
|
5064
|
-
#endif
|
|
5065
|
-
int sqlite3_percentile_init(
|
|
5066
|
-
sqlite3 *db,
|
|
5067
|
-
char **pzErrMsg,
|
|
5068
|
-
const sqlite3_api_routines *pApi
|
|
5069
|
-
){
|
|
5070
|
-
int rc = SQLITE_OK;
|
|
5071
|
-
unsigned int i;
|
|
5072
|
-
#ifdef SQLITE3EXT_H
|
|
5073
|
-
SQLITE_EXTENSION_INIT2(pApi);
|
|
5074
|
-
#else
|
|
5075
|
-
(void)pApi; /* Unused parameter */
|
|
5076
|
-
#endif
|
|
5077
|
-
(void)pzErrMsg; /* Unused parameter */
|
|
5078
|
-
for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
|
|
5079
|
-
rc = sqlite3_create_window_function(db,
|
|
5080
|
-
aPercentFunc[i].zName,
|
|
5081
|
-
aPercentFunc[i].nArg,
|
|
5082
|
-
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_SELFORDER1,
|
|
5083
|
-
(void*)&aPercentFunc[i],
|
|
5084
|
-
percentStep, percentFinal, percentValue, percentInverse, 0);
|
|
5085
|
-
if( rc ) break;
|
|
5086
|
-
}
|
|
5087
|
-
return rc;
|
|
5088
|
-
}
|
|
5089
|
-
|
|
5090
|
-
/************************* End ../ext/misc/percentile.c ********************/
|
|
5091
4503
|
#undef sqlite3_base_init
|
|
5092
4504
|
#define sqlite3_base_init sqlite3_base64_init
|
|
5093
4505
|
/************************* Begin ../ext/misc/base64.c ******************/
|
|
@@ -5300,7 +4712,9 @@ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
|
|
|
5300
4712
|
|
|
5301
4713
|
/* This function does the work for the SQLite base64(x) UDF. */
|
|
5302
4714
|
static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
|
|
5303
|
-
|
|
4715
|
+
sqlite3_int64 nb;
|
|
4716
|
+
sqlite3_int64 nv = sqlite3_value_bytes(av[0]);
|
|
4717
|
+
sqlite3_int64 nc;
|
|
5304
4718
|
int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
|
|
5305
4719
|
SQLITE_LIMIT_LENGTH, -1);
|
|
5306
4720
|
char *cBuf;
|
|
@@ -5309,7 +4723,7 @@ static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
|
|
|
5309
4723
|
switch( sqlite3_value_type(av[0]) ){
|
|
5310
4724
|
case SQLITE_BLOB:
|
|
5311
4725
|
nb = nv;
|
|
5312
|
-
nc = 4*(nv+2/3); /* quads needed */
|
|
4726
|
+
nc = 4*((nv+2)/3); /* quads needed */
|
|
5313
4727
|
nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */
|
|
5314
4728
|
if( nvMax < nc ){
|
|
5315
4729
|
sqlite3_result_error(context, "blob expanded to base64 too big", -1);
|
|
@@ -5680,7 +5094,7 @@ static void is_base85(sqlite3_context *context, int na, sqlite3_value *av[]){
|
|
|
5680
5094
|
|
|
5681
5095
|
/* This function does the work for the SQLite base85(x) UDF. */
|
|
5682
5096
|
static void base85(sqlite3_context *context, int na, sqlite3_value *av[]){
|
|
5683
|
-
|
|
5097
|
+
sqlite3_int64 nb, nc, nv = sqlite3_value_bytes(av[0]);
|
|
5684
5098
|
int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
|
|
5685
5099
|
SQLITE_LIMIT_LENGTH, -1);
|
|
5686
5100
|
char *cBuf;
|
|
@@ -5985,6 +5399,9 @@ static void ieee754func(
|
|
|
5985
5399
|
if( a==0 ){
|
|
5986
5400
|
e = 0;
|
|
5987
5401
|
m = 0;
|
|
5402
|
+
}else if( a==(sqlite3_int64)0x8000000000000000LL ){
|
|
5403
|
+
e = -1996;
|
|
5404
|
+
m = -1;
|
|
5988
5405
|
}else{
|
|
5989
5406
|
e = a>>52;
|
|
5990
5407
|
m = a & ((((sqlite3_int64)1)<<52)-1);
|
|
@@ -6208,19 +5625,20 @@ int sqlite3_ieee_init(
|
|
|
6208
5625
|
** SELECT * FROM generate_series(0,100,5);
|
|
6209
5626
|
**
|
|
6210
5627
|
** The query above returns integers from 0 through 100 counting by steps
|
|
6211
|
-
** of 5.
|
|
5628
|
+
** of 5. In other words, 0, 5, 10, 15, ..., 90, 95, 100. There are a total
|
|
5629
|
+
** of 21 rows.
|
|
6212
5630
|
**
|
|
6213
5631
|
** SELECT * FROM generate_series(0,100);
|
|
6214
5632
|
**
|
|
6215
|
-
** Integers from 0 through 100 with a step size of 1.
|
|
5633
|
+
** Integers from 0 through 100 with a step size of 1. 101 rows.
|
|
6216
5634
|
**
|
|
6217
5635
|
** SELECT * FROM generate_series(20) LIMIT 10;
|
|
6218
5636
|
**
|
|
6219
|
-
** Integers 20 through 29.
|
|
5637
|
+
** Integers 20 through 29. 10 rows.
|
|
6220
5638
|
**
|
|
6221
5639
|
** SELECT * FROM generate_series(0,-100,-5);
|
|
6222
5640
|
**
|
|
6223
|
-
** Integers 0 -5 -10 ... -100.
|
|
5641
|
+
** Integers 0 -5 -10 ... -100. 21 rows.
|
|
6224
5642
|
**
|
|
6225
5643
|
** SELECT * FROM generate_series(0,-1);
|
|
6226
5644
|
**
|
|
@@ -6296,140 +5714,89 @@ SQLITE_EXTENSION_INIT1
|
|
|
6296
5714
|
#include <math.h>
|
|
6297
5715
|
|
|
6298
5716
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
6299
|
-
/*
|
|
6300
|
-
** Return that member of a generate_series(...) sequence whose 0-based
|
|
6301
|
-
** index is ix. The 0th member is given by smBase. The sequence members
|
|
6302
|
-
** progress per ix increment by smStep.
|
|
6303
|
-
*/
|
|
6304
|
-
static sqlite3_int64 genSeqMember(
|
|
6305
|
-
sqlite3_int64 smBase,
|
|
6306
|
-
sqlite3_int64 smStep,
|
|
6307
|
-
sqlite3_uint64 ix
|
|
6308
|
-
){
|
|
6309
|
-
static const sqlite3_uint64 mxI64 =
|
|
6310
|
-
((sqlite3_uint64)0x7fffffff)<<32 | 0xffffffff;
|
|
6311
|
-
if( ix>=mxI64 ){
|
|
6312
|
-
/* Get ix into signed i64 range. */
|
|
6313
|
-
ix -= mxI64;
|
|
6314
|
-
/* With 2's complement ALU, this next can be 1 step, but is split into
|
|
6315
|
-
* 2 for UBSAN's satisfaction (and hypothetical 1's complement ALUs.) */
|
|
6316
|
-
smBase += (mxI64/2) * smStep;
|
|
6317
|
-
smBase += (mxI64 - mxI64/2) * smStep;
|
|
6318
|
-
}
|
|
6319
|
-
/* Under UBSAN (or on 1's complement machines), must do this last term
|
|
6320
|
-
* in steps to avoid the dreaded (and harmless) signed multiply overflow. */
|
|
6321
|
-
if( ix>=2 ){
|
|
6322
|
-
sqlite3_int64 ix2 = (sqlite3_int64)ix/2;
|
|
6323
|
-
smBase += ix2*smStep;
|
|
6324
|
-
ix -= ix2;
|
|
6325
|
-
}
|
|
6326
|
-
return smBase + ((sqlite3_int64)ix)*smStep;
|
|
6327
|
-
}
|
|
6328
|
-
|
|
6329
|
-
/* typedef unsigned char u8; */
|
|
6330
|
-
|
|
6331
|
-
typedef struct SequenceSpec {
|
|
6332
|
-
sqlite3_int64 iOBase; /* Original starting value ("start") */
|
|
6333
|
-
sqlite3_int64 iOTerm; /* Original terminal value ("stop") */
|
|
6334
|
-
sqlite3_int64 iBase; /* Starting value to actually use */
|
|
6335
|
-
sqlite3_int64 iTerm; /* Terminal value to actually use */
|
|
6336
|
-
sqlite3_int64 iStep; /* Increment ("step") */
|
|
6337
|
-
sqlite3_uint64 uSeqIndexMax; /* maximum sequence index (aka "n") */
|
|
6338
|
-
sqlite3_uint64 uSeqIndexNow; /* Current index during generation */
|
|
6339
|
-
sqlite3_int64 iValueNow; /* Current value during generation */
|
|
6340
|
-
u8 isNotEOF; /* Sequence generation not exhausted */
|
|
6341
|
-
u8 isReversing; /* Sequence is being reverse generated */
|
|
6342
|
-
} SequenceSpec;
|
|
6343
|
-
|
|
6344
|
-
/*
|
|
6345
|
-
** Prepare a SequenceSpec for use in generating an integer series
|
|
6346
|
-
** given initialized iBase, iTerm and iStep values. Sequence is
|
|
6347
|
-
** initialized per given isReversing. Other members are computed.
|
|
6348
|
-
*/
|
|
6349
|
-
static void setupSequence( SequenceSpec *pss ){
|
|
6350
|
-
int bSameSigns;
|
|
6351
|
-
pss->uSeqIndexMax = 0;
|
|
6352
|
-
pss->isNotEOF = 0;
|
|
6353
|
-
bSameSigns = (pss->iBase < 0)==(pss->iTerm < 0);
|
|
6354
|
-
if( pss->iTerm < pss->iBase ){
|
|
6355
|
-
sqlite3_uint64 nuspan = 0;
|
|
6356
|
-
if( bSameSigns ){
|
|
6357
|
-
nuspan = (sqlite3_uint64)(pss->iBase - pss->iTerm);
|
|
6358
|
-
}else{
|
|
6359
|
-
/* Under UBSAN (or on 1's complement machines), must do this in steps.
|
|
6360
|
-
* In this clause, iBase>=0 and iTerm<0 . */
|
|
6361
|
-
nuspan = 1;
|
|
6362
|
-
nuspan += pss->iBase;
|
|
6363
|
-
nuspan += -(pss->iTerm+1);
|
|
6364
|
-
}
|
|
6365
|
-
if( pss->iStep<0 ){
|
|
6366
|
-
pss->isNotEOF = 1;
|
|
6367
|
-
if( nuspan==ULONG_MAX ){
|
|
6368
|
-
pss->uSeqIndexMax = ( pss->iStep>LLONG_MIN )? nuspan/-pss->iStep : 1;
|
|
6369
|
-
}else if( pss->iStep>LLONG_MIN ){
|
|
6370
|
-
pss->uSeqIndexMax = nuspan/-pss->iStep;
|
|
6371
|
-
}
|
|
6372
|
-
}
|
|
6373
|
-
}else if( pss->iTerm > pss->iBase ){
|
|
6374
|
-
sqlite3_uint64 puspan = 0;
|
|
6375
|
-
if( bSameSigns ){
|
|
6376
|
-
puspan = (sqlite3_uint64)(pss->iTerm - pss->iBase);
|
|
6377
|
-
}else{
|
|
6378
|
-
/* Under UBSAN (or on 1's complement machines), must do this in steps.
|
|
6379
|
-
* In this clause, iTerm>=0 and iBase<0 . */
|
|
6380
|
-
puspan = 1;
|
|
6381
|
-
puspan += pss->iTerm;
|
|
6382
|
-
puspan += -(pss->iBase+1);
|
|
6383
|
-
}
|
|
6384
|
-
if( pss->iStep>0 ){
|
|
6385
|
-
pss->isNotEOF = 1;
|
|
6386
|
-
pss->uSeqIndexMax = puspan/pss->iStep;
|
|
6387
|
-
}
|
|
6388
|
-
}else if( pss->iTerm == pss->iBase ){
|
|
6389
|
-
pss->isNotEOF = 1;
|
|
6390
|
-
pss->uSeqIndexMax = 0;
|
|
6391
|
-
}
|
|
6392
|
-
pss->uSeqIndexNow = (pss->isReversing)? pss->uSeqIndexMax : 0;
|
|
6393
|
-
pss->iValueNow = (pss->isReversing)
|
|
6394
|
-
? genSeqMember(pss->iBase, pss->iStep, pss->uSeqIndexMax)
|
|
6395
|
-
: pss->iBase;
|
|
6396
|
-
}
|
|
6397
|
-
|
|
6398
|
-
/*
|
|
6399
|
-
** Progress sequence generator to yield next value, if any.
|
|
6400
|
-
** Leave its state to either yield next value or be at EOF.
|
|
6401
|
-
** Return whether there is a next value, or 0 at EOF.
|
|
6402
|
-
*/
|
|
6403
|
-
static int progressSequence( SequenceSpec *pss ){
|
|
6404
|
-
if( !pss->isNotEOF ) return 0;
|
|
6405
|
-
if( pss->isReversing ){
|
|
6406
|
-
if( pss->uSeqIndexNow > 0 ){
|
|
6407
|
-
pss->uSeqIndexNow--;
|
|
6408
|
-
pss->iValueNow -= pss->iStep;
|
|
6409
|
-
}else{
|
|
6410
|
-
pss->isNotEOF = 0;
|
|
6411
|
-
}
|
|
6412
|
-
}else{
|
|
6413
|
-
if( pss->uSeqIndexNow < pss->uSeqIndexMax ){
|
|
6414
|
-
pss->uSeqIndexNow++;
|
|
6415
|
-
pss->iValueNow += pss->iStep;
|
|
6416
|
-
}else{
|
|
6417
|
-
pss->isNotEOF = 0;
|
|
6418
|
-
}
|
|
6419
|
-
}
|
|
6420
|
-
return pss->isNotEOF;
|
|
6421
|
-
}
|
|
6422
5717
|
|
|
6423
5718
|
/* series_cursor is a subclass of sqlite3_vtab_cursor which will
|
|
6424
5719
|
** serve as the underlying representation of a cursor that scans
|
|
6425
|
-
** over rows of the result
|
|
5720
|
+
** over rows of the result.
|
|
5721
|
+
**
|
|
5722
|
+
** iOBase, iOTerm, and iOStep are the original values of the
|
|
5723
|
+
** start=, stop=, and step= constraints on the query. These are
|
|
5724
|
+
** the values reported by the start, stop, and step columns of the
|
|
5725
|
+
** virtual table.
|
|
5726
|
+
**
|
|
5727
|
+
** iBase, iTerm, iStep, and bDescp are the actual values used to generate
|
|
5728
|
+
** the sequence. These might be different from the iOxxxx values.
|
|
5729
|
+
** For example in
|
|
5730
|
+
**
|
|
5731
|
+
** SELECT value FROM generate_series(1,11,2)
|
|
5732
|
+
** WHERE value BETWEEN 4 AND 8;
|
|
5733
|
+
**
|
|
5734
|
+
** The iOBase is 1, but the iBase is 5. iOTerm is 11 but iTerm is 7.
|
|
5735
|
+
** Another example:
|
|
5736
|
+
**
|
|
5737
|
+
** SELECT value FROM generate_series(1,15,3) ORDER BY value DESC;
|
|
5738
|
+
**
|
|
5739
|
+
** The cursor initialization for the above query is:
|
|
5740
|
+
**
|
|
5741
|
+
** iOBase = 1 iBase = 13
|
|
5742
|
+
** iOTerm = 15 iTerm = 1
|
|
5743
|
+
** iOStep = 3 iStep = 3 bDesc = 1
|
|
5744
|
+
**
|
|
5745
|
+
** The actual step size is unsigned so that can have a value of
|
|
5746
|
+
** +9223372036854775808 which is needed for querys like this:
|
|
5747
|
+
**
|
|
5748
|
+
** SELECT value
|
|
5749
|
+
** FROM generate_series(9223372036854775807,
|
|
5750
|
+
** -9223372036854775808,
|
|
5751
|
+
** -9223372036854775808)
|
|
5752
|
+
** ORDER BY value ASC;
|
|
5753
|
+
**
|
|
5754
|
+
** The setup for the previous query will be:
|
|
5755
|
+
**
|
|
5756
|
+
** iOBase = 9223372036854775807 iBase = -1
|
|
5757
|
+
** iOTerm = -9223372036854775808 iTerm = 9223372036854775807
|
|
5758
|
+
** iOStep = -9223372036854775808 iStep = 9223372036854775808 bDesc = 0
|
|
6426
5759
|
*/
|
|
5760
|
+
/* typedef unsigned char u8; */
|
|
6427
5761
|
typedef struct series_cursor series_cursor;
|
|
6428
5762
|
struct series_cursor {
|
|
6429
5763
|
sqlite3_vtab_cursor base; /* Base class - must be first */
|
|
6430
|
-
|
|
5764
|
+
sqlite3_int64 iOBase; /* Original starting value ("start") */
|
|
5765
|
+
sqlite3_int64 iOTerm; /* Original terminal value ("stop") */
|
|
5766
|
+
sqlite3_int64 iOStep; /* Original step value */
|
|
5767
|
+
sqlite3_int64 iBase; /* Starting value to actually use */
|
|
5768
|
+
sqlite3_int64 iTerm; /* Terminal value to actually use */
|
|
5769
|
+
sqlite3_uint64 iStep; /* The step size */
|
|
5770
|
+
sqlite3_int64 iValue; /* Current value */
|
|
5771
|
+
u8 bDesc; /* iStep is really negative */
|
|
5772
|
+
u8 bDone; /* True if stepped past last element */
|
|
6431
5773
|
};
|
|
6432
5774
|
|
|
5775
|
+
/*
|
|
5776
|
+
** Computed the difference between two 64-bit signed integers using a
|
|
5777
|
+
** convoluted computation designed to work around the silly restriction
|
|
5778
|
+
** against signed integer overflow in C.
|
|
5779
|
+
*/
|
|
5780
|
+
static sqlite3_uint64 span64(sqlite3_int64 a, sqlite3_int64 b){
|
|
5781
|
+
assert( a>=b );
|
|
5782
|
+
return (*(sqlite3_uint64*)&a) - (*(sqlite3_uint64*)&b);
|
|
5783
|
+
}
|
|
5784
|
+
|
|
5785
|
+
/*
|
|
5786
|
+
** Add or substract an unsigned 64-bit integer from a signed 64-bit integer
|
|
5787
|
+
** and return the new signed 64-bit integer.
|
|
5788
|
+
*/
|
|
5789
|
+
static sqlite3_int64 add64(sqlite3_int64 a, sqlite3_uint64 b){
|
|
5790
|
+
sqlite3_uint64 x = *(sqlite3_uint64*)&a;
|
|
5791
|
+
x += b;
|
|
5792
|
+
return *(sqlite3_int64*)&x;
|
|
5793
|
+
}
|
|
5794
|
+
static sqlite3_int64 sub64(sqlite3_int64 a, sqlite3_uint64 b){
|
|
5795
|
+
sqlite3_uint64 x = *(sqlite3_uint64*)&a;
|
|
5796
|
+
x -= b;
|
|
5797
|
+
return *(sqlite3_int64*)&x;
|
|
5798
|
+
}
|
|
5799
|
+
|
|
6433
5800
|
/*
|
|
6434
5801
|
** The seriesConnect() method is invoked to create a new
|
|
6435
5802
|
** series_vtab that describes the generate_series virtual table.
|
|
@@ -6510,7 +5877,15 @@ static int seriesClose(sqlite3_vtab_cursor *cur){
|
|
|
6510
5877
|
*/
|
|
6511
5878
|
static int seriesNext(sqlite3_vtab_cursor *cur){
|
|
6512
5879
|
series_cursor *pCur = (series_cursor*)cur;
|
|
6513
|
-
|
|
5880
|
+
if( pCur->iValue==pCur->iTerm ){
|
|
5881
|
+
pCur->bDone = 1;
|
|
5882
|
+
}else if( pCur->bDesc ){
|
|
5883
|
+
pCur->iValue = sub64(pCur->iValue, pCur->iStep);
|
|
5884
|
+
assert( pCur->iValue>=pCur->iTerm );
|
|
5885
|
+
}else{
|
|
5886
|
+
pCur->iValue = add64(pCur->iValue, pCur->iStep);
|
|
5887
|
+
assert( pCur->iValue<=pCur->iTerm );
|
|
5888
|
+
}
|
|
6514
5889
|
return SQLITE_OK;
|
|
6515
5890
|
}
|
|
6516
5891
|
|
|
@@ -6526,19 +5901,19 @@ static int seriesColumn(
|
|
|
6526
5901
|
series_cursor *pCur = (series_cursor*)cur;
|
|
6527
5902
|
sqlite3_int64 x = 0;
|
|
6528
5903
|
switch( i ){
|
|
6529
|
-
case SERIES_COLUMN_START: x = pCur->
|
|
6530
|
-
case SERIES_COLUMN_STOP: x = pCur->
|
|
6531
|
-
case SERIES_COLUMN_STEP: x = pCur->
|
|
6532
|
-
default: x = pCur->
|
|
5904
|
+
case SERIES_COLUMN_START: x = pCur->iOBase; break;
|
|
5905
|
+
case SERIES_COLUMN_STOP: x = pCur->iOTerm; break;
|
|
5906
|
+
case SERIES_COLUMN_STEP: x = pCur->iOStep; break;
|
|
5907
|
+
default: x = pCur->iValue; break;
|
|
6533
5908
|
}
|
|
6534
5909
|
sqlite3_result_int64(ctx, x);
|
|
6535
5910
|
return SQLITE_OK;
|
|
6536
5911
|
}
|
|
6537
5912
|
|
|
6538
5913
|
#ifndef LARGEST_UINT64
|
|
6539
|
-
#define LARGEST_INT64 (
|
|
6540
|
-
#define LARGEST_UINT64 (
|
|
6541
|
-
#define SMALLEST_INT64 ((
|
|
5914
|
+
#define LARGEST_INT64 ((sqlite3_int64)0x7fffffffffffffffLL)
|
|
5915
|
+
#define LARGEST_UINT64 ((sqlite3_uint64)0xffffffffffffffffULL)
|
|
5916
|
+
#define SMALLEST_INT64 ((sqlite3_int64)0x8000000000000000LL)
|
|
6542
5917
|
#endif
|
|
6543
5918
|
|
|
6544
5919
|
/*
|
|
@@ -6546,7 +5921,7 @@ static int seriesColumn(
|
|
|
6546
5921
|
*/
|
|
6547
5922
|
static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
|
6548
5923
|
series_cursor *pCur = (series_cursor*)cur;
|
|
6549
|
-
*pRowid = pCur->
|
|
5924
|
+
*pRowid = pCur->iValue;
|
|
6550
5925
|
return SQLITE_OK;
|
|
6551
5926
|
}
|
|
6552
5927
|
|
|
@@ -6556,7 +5931,7 @@ static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
|
|
6556
5931
|
*/
|
|
6557
5932
|
static int seriesEof(sqlite3_vtab_cursor *cur){
|
|
6558
5933
|
series_cursor *pCur = (series_cursor*)cur;
|
|
6559
|
-
return
|
|
5934
|
+
return pCur->bDone;
|
|
6560
5935
|
}
|
|
6561
5936
|
|
|
6562
5937
|
/* True to cause run-time checking of the start=, stop=, and/or step=
|
|
@@ -6567,6 +5942,59 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
|
|
|
6567
5942
|
# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
|
|
6568
5943
|
#endif
|
|
6569
5944
|
|
|
5945
|
+
/*
|
|
5946
|
+
** Return the number of steps between pCur->iBase and pCur->iTerm if
|
|
5947
|
+
** the step width is pCur->iStep.
|
|
5948
|
+
*/
|
|
5949
|
+
static sqlite3_uint64 seriesSteps(series_cursor *pCur){
|
|
5950
|
+
if( pCur->bDesc ){
|
|
5951
|
+
assert( pCur->iBase >= pCur->iTerm );
|
|
5952
|
+
return span64(pCur->iBase, pCur->iTerm)/pCur->iStep;
|
|
5953
|
+
}else{
|
|
5954
|
+
assert( pCur->iBase <= pCur->iTerm );
|
|
5955
|
+
return span64(pCur->iTerm, pCur->iBase)/pCur->iStep;
|
|
5956
|
+
}
|
|
5957
|
+
}
|
|
5958
|
+
|
|
5959
|
+
#if defined(SQLITE_ENABLE_MATH_FUNCTIONS) || defined(_WIN32)
|
|
5960
|
+
/*
|
|
5961
|
+
** Case 1 (the most common case):
|
|
5962
|
+
** The standard math library is available so use ceil() and floor() from there.
|
|
5963
|
+
*/
|
|
5964
|
+
static double seriesCeil(double r){ return ceil(r); }
|
|
5965
|
+
static double seriesFloor(double r){ return floor(r); }
|
|
5966
|
+
#elif defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
|
|
5967
|
+
/*
|
|
5968
|
+
** Case 2 (2nd most common): Use GCC/Clang builtins
|
|
5969
|
+
*/
|
|
5970
|
+
static double seriesCeil(double r){ return __builtin_ceil(r); }
|
|
5971
|
+
static double seriesFloor(double r){ return __builtin_floor(r); }
|
|
5972
|
+
#else
|
|
5973
|
+
/*
|
|
5974
|
+
** Case 3 (rarely happens): Use home-grown ceil() and floor() routines.
|
|
5975
|
+
*/
|
|
5976
|
+
static double seriesCeil(double r){
|
|
5977
|
+
sqlite3_int64 x;
|
|
5978
|
+
if( r!=r ) return r;
|
|
5979
|
+
if( r<=(-4503599627370496.0) ) return r;
|
|
5980
|
+
if( r>=(+4503599627370496.0) ) return r;
|
|
5981
|
+
x = (sqlite3_int64)r;
|
|
5982
|
+
if( r==(double)x ) return r;
|
|
5983
|
+
if( r>(double)x ) x++;
|
|
5984
|
+
return (double)x;
|
|
5985
|
+
}
|
|
5986
|
+
static double seriesFloor(double r){
|
|
5987
|
+
sqlite3_int64 x;
|
|
5988
|
+
if( r!=r ) return r;
|
|
5989
|
+
if( r<=(-4503599627370496.0) ) return r;
|
|
5990
|
+
if( r>=(+4503599627370496.0) ) return r;
|
|
5991
|
+
x = (sqlite3_int64)r;
|
|
5992
|
+
if( r==(double)x ) return r;
|
|
5993
|
+
if( r<(double)x ) x--;
|
|
5994
|
+
return (double)x;
|
|
5995
|
+
}
|
|
5996
|
+
#endif
|
|
5997
|
+
|
|
6570
5998
|
/*
|
|
6571
5999
|
** This method is called to "rewind" the series_cursor object back
|
|
6572
6000
|
** to the first row of output. This method is always called at least
|
|
@@ -6600,33 +6028,42 @@ static int seriesFilter(
|
|
|
6600
6028
|
int argc, sqlite3_value **argv
|
|
6601
6029
|
){
|
|
6602
6030
|
series_cursor *pCur = (series_cursor *)pVtabCursor;
|
|
6603
|
-
int
|
|
6604
|
-
int
|
|
6605
|
-
sqlite3_int64 iMin = SMALLEST_INT64;
|
|
6606
|
-
sqlite3_int64 iMax = LARGEST_INT64;
|
|
6607
|
-
sqlite3_int64 iLimit = 0;
|
|
6608
|
-
sqlite3_int64 iOffset = 0;
|
|
6031
|
+
int iArg = 0; /* Arguments used so far */
|
|
6032
|
+
int i; /* Loop counter */
|
|
6033
|
+
sqlite3_int64 iMin = SMALLEST_INT64; /* Smallest allowed output value */
|
|
6034
|
+
sqlite3_int64 iMax = LARGEST_INT64; /* Largest allowed output value */
|
|
6035
|
+
sqlite3_int64 iLimit = 0; /* if >0, the value of the LIMIT */
|
|
6036
|
+
sqlite3_int64 iOffset = 0; /* if >0, the value of the OFFSET */
|
|
6609
6037
|
|
|
6610
6038
|
(void)idxStrUnused;
|
|
6039
|
+
|
|
6040
|
+
/* If any constraints have a NULL value, then return no rows.
|
|
6041
|
+
** See ticket https://sqlite.org/src/info/fac496b61722daf2
|
|
6042
|
+
*/
|
|
6043
|
+
for(i=0; i<argc; i++){
|
|
6044
|
+
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
|
|
6045
|
+
goto series_no_rows;
|
|
6046
|
+
}
|
|
6047
|
+
}
|
|
6048
|
+
|
|
6049
|
+
/* Capture the three HIDDEN parameters to the virtual table and insert
|
|
6050
|
+
** default values for any parameters that are omitted.
|
|
6051
|
+
*/
|
|
6611
6052
|
if( idxNum & 0x01 ){
|
|
6612
|
-
pCur->
|
|
6053
|
+
pCur->iOBase = sqlite3_value_int64(argv[iArg++]);
|
|
6613
6054
|
}else{
|
|
6614
|
-
pCur->
|
|
6055
|
+
pCur->iOBase = 0;
|
|
6615
6056
|
}
|
|
6616
6057
|
if( idxNum & 0x02 ){
|
|
6617
|
-
pCur->
|
|
6058
|
+
pCur->iOTerm = sqlite3_value_int64(argv[iArg++]);
|
|
6618
6059
|
}else{
|
|
6619
|
-
pCur->
|
|
6060
|
+
pCur->iOTerm = 0xffffffff;
|
|
6620
6061
|
}
|
|
6621
6062
|
if( idxNum & 0x04 ){
|
|
6622
|
-
pCur->
|
|
6623
|
-
if( pCur->
|
|
6624
|
-
pCur->ss.iStep = 1;
|
|
6625
|
-
}else if( pCur->ss.iStep<0 ){
|
|
6626
|
-
if( (idxNum & 0x10)==0 ) idxNum |= 0x08;
|
|
6627
|
-
}
|
|
6063
|
+
pCur->iOStep = sqlite3_value_int64(argv[iArg++]);
|
|
6064
|
+
if( pCur->iOStep==0 ) pCur->iOStep = 1;
|
|
6628
6065
|
}else{
|
|
6629
|
-
pCur->
|
|
6066
|
+
pCur->iOStep = 1;
|
|
6630
6067
|
}
|
|
6631
6068
|
|
|
6632
6069
|
/* If there are constraints on the value column but there are
|
|
@@ -6636,72 +6073,94 @@ static int seriesFilter(
|
|
|
6636
6073
|
** further below.
|
|
6637
6074
|
*/
|
|
6638
6075
|
if( (idxNum & 0x05)==0 && (idxNum & 0x0380)!=0 ){
|
|
6639
|
-
pCur->
|
|
6076
|
+
pCur->iOBase = SMALLEST_INT64;
|
|
6640
6077
|
}
|
|
6641
6078
|
if( (idxNum & 0x06)==0 && (idxNum & 0x3080)!=0 ){
|
|
6642
|
-
pCur->
|
|
6079
|
+
pCur->iOTerm = LARGEST_INT64;
|
|
6080
|
+
}
|
|
6081
|
+
pCur->iBase = pCur->iOBase;
|
|
6082
|
+
pCur->iTerm = pCur->iOTerm;
|
|
6083
|
+
if( pCur->iOStep>0 ){
|
|
6084
|
+
pCur->iStep = pCur->iOStep;
|
|
6085
|
+
}else if( pCur->iOStep>SMALLEST_INT64 ){
|
|
6086
|
+
pCur->iStep = -pCur->iOStep;
|
|
6087
|
+
}else{
|
|
6088
|
+
pCur->iStep = LARGEST_INT64;
|
|
6089
|
+
pCur->iStep++;
|
|
6090
|
+
}
|
|
6091
|
+
pCur->bDesc = pCur->iOStep<0;
|
|
6092
|
+
if( pCur->bDesc==0 && pCur->iBase>pCur->iTerm ){
|
|
6093
|
+
goto series_no_rows;
|
|
6094
|
+
}
|
|
6095
|
+
if( pCur->bDesc!=0 && pCur->iBase<pCur->iTerm ){
|
|
6096
|
+
goto series_no_rows;
|
|
6643
6097
|
}
|
|
6644
|
-
pCur->ss.iOBase = pCur->ss.iBase;
|
|
6645
|
-
pCur->ss.iOTerm = pCur->ss.iTerm;
|
|
6646
6098
|
|
|
6647
6099
|
/* Extract the LIMIT and OFFSET values, but do not apply them yet.
|
|
6648
6100
|
** The range must first be constrained by the limits on value.
|
|
6649
6101
|
*/
|
|
6650
6102
|
if( idxNum & 0x20 ){
|
|
6651
|
-
iLimit = sqlite3_value_int64(argv[
|
|
6103
|
+
iLimit = sqlite3_value_int64(argv[iArg++]);
|
|
6652
6104
|
if( idxNum & 0x40 ){
|
|
6653
|
-
iOffset = sqlite3_value_int64(argv[
|
|
6105
|
+
iOffset = sqlite3_value_int64(argv[iArg++]);
|
|
6654
6106
|
}
|
|
6655
6107
|
}
|
|
6656
6108
|
|
|
6109
|
+
/* Narrow the range of iMin and iMax (the minimum and maximum outputs)
|
|
6110
|
+
** based on equality and inequality constraints on the "value" column.
|
|
6111
|
+
*/
|
|
6657
6112
|
if( idxNum & 0x3380 ){
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6113
|
+
if( idxNum & 0x0080 ){ /* value=X */
|
|
6114
|
+
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
|
|
6115
|
+
double r = sqlite3_value_double(argv[iArg++]);
|
|
6116
|
+
if( r==seriesCeil(r)
|
|
6117
|
+
&& r>=(double)SMALLEST_INT64
|
|
6118
|
+
&& r<=(double)LARGEST_INT64
|
|
6119
|
+
){
|
|
6665
6120
|
iMin = iMax = (sqlite3_int64)r;
|
|
6666
6121
|
}else{
|
|
6667
|
-
|
|
6122
|
+
goto series_no_rows;
|
|
6668
6123
|
}
|
|
6669
6124
|
}else{
|
|
6670
|
-
iMin = iMax = sqlite3_value_int64(argv[
|
|
6125
|
+
iMin = iMax = sqlite3_value_int64(argv[iArg++]);
|
|
6671
6126
|
}
|
|
6672
6127
|
}else{
|
|
6673
|
-
if( idxNum & 0x0300 ){
|
|
6674
|
-
if( sqlite3_value_numeric_type(argv[
|
|
6675
|
-
double r = sqlite3_value_double(argv[
|
|
6676
|
-
if(
|
|
6677
|
-
iMin =
|
|
6128
|
+
if( idxNum & 0x0300 ){ /* value>X or value>=X */
|
|
6129
|
+
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
|
|
6130
|
+
double r = sqlite3_value_double(argv[iArg++]);
|
|
6131
|
+
if( r<(double)SMALLEST_INT64 ){
|
|
6132
|
+
iMin = SMALLEST_INT64;
|
|
6133
|
+
}else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
|
|
6134
|
+
iMin = (sqlite3_int64)seriesCeil(r+1.0);
|
|
6678
6135
|
}else{
|
|
6679
|
-
iMin = (sqlite3_int64)
|
|
6136
|
+
iMin = (sqlite3_int64)seriesCeil(r);
|
|
6680
6137
|
}
|
|
6681
6138
|
}else{
|
|
6682
|
-
iMin = sqlite3_value_int64(argv[
|
|
6683
|
-
if( idxNum & 0x0200 ){
|
|
6139
|
+
iMin = sqlite3_value_int64(argv[iArg++]);
|
|
6140
|
+
if( (idxNum & 0x0200)!=0 ){
|
|
6684
6141
|
if( iMin==LARGEST_INT64 ){
|
|
6685
|
-
|
|
6142
|
+
goto series_no_rows;
|
|
6686
6143
|
}else{
|
|
6687
6144
|
iMin++;
|
|
6688
6145
|
}
|
|
6689
6146
|
}
|
|
6690
6147
|
}
|
|
6691
6148
|
}
|
|
6692
|
-
if( idxNum & 0x3000 ){
|
|
6693
|
-
if( sqlite3_value_numeric_type(argv[
|
|
6694
|
-
double r = sqlite3_value_double(argv[
|
|
6695
|
-
if(
|
|
6149
|
+
if( idxNum & 0x3000 ){ /* value<X or value<=X */
|
|
6150
|
+
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
|
|
6151
|
+
double r = sqlite3_value_double(argv[iArg++]);
|
|
6152
|
+
if( r>(double)LARGEST_INT64 ){
|
|
6153
|
+
iMax = LARGEST_INT64;
|
|
6154
|
+
}else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
|
|
6696
6155
|
iMax = (sqlite3_int64)(r-1.0);
|
|
6697
6156
|
}else{
|
|
6698
|
-
iMax = (sqlite3_int64)
|
|
6157
|
+
iMax = (sqlite3_int64)seriesFloor(r);
|
|
6699
6158
|
}
|
|
6700
6159
|
}else{
|
|
6701
|
-
iMax = sqlite3_value_int64(argv[
|
|
6160
|
+
iMax = sqlite3_value_int64(argv[iArg++]);
|
|
6702
6161
|
if( idxNum & 0x2000 ){
|
|
6703
6162
|
if( iMax==SMALLEST_INT64 ){
|
|
6704
|
-
|
|
6163
|
+
goto series_no_rows;
|
|
6705
6164
|
}else{
|
|
6706
6165
|
iMax--;
|
|
6707
6166
|
}
|
|
@@ -6709,72 +6168,99 @@ static int seriesFilter(
|
|
|
6709
6168
|
}
|
|
6710
6169
|
}
|
|
6711
6170
|
if( iMin>iMax ){
|
|
6712
|
-
|
|
6171
|
+
goto series_no_rows;
|
|
6713
6172
|
}
|
|
6714
6173
|
}
|
|
6715
6174
|
|
|
6716
6175
|
/* Try to reduce the range of values to be generated based on
|
|
6717
6176
|
** constraints on the "value" column.
|
|
6718
6177
|
*/
|
|
6719
|
-
if( pCur->
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
pCur->
|
|
6178
|
+
if( pCur->bDesc==0 ){
|
|
6179
|
+
if( pCur->iBase<iMin ){
|
|
6180
|
+
sqlite3_uint64 span = span64(iMin,pCur->iBase);
|
|
6181
|
+
pCur->iBase = add64(pCur->iBase, (span/pCur->iStep)*pCur->iStep);
|
|
6182
|
+
if( pCur->iBase<iMin ){
|
|
6183
|
+
if( pCur->iBase > sub64(LARGEST_INT64, pCur->iStep) ){
|
|
6184
|
+
goto series_no_rows;
|
|
6185
|
+
}
|
|
6186
|
+
pCur->iBase = add64(pCur->iBase, pCur->iStep);
|
|
6187
|
+
}
|
|
6724
6188
|
}
|
|
6725
|
-
if( pCur->
|
|
6726
|
-
pCur->
|
|
6189
|
+
if( pCur->iTerm>iMax ){
|
|
6190
|
+
pCur->iTerm = iMax;
|
|
6727
6191
|
}
|
|
6728
6192
|
}else{
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6193
|
+
if( pCur->iBase>iMax ){
|
|
6194
|
+
sqlite3_uint64 span = span64(pCur->iBase,iMax);
|
|
6195
|
+
pCur->iBase = sub64(pCur->iBase, (span/pCur->iStep)*pCur->iStep);
|
|
6196
|
+
if( pCur->iBase>iMax ){
|
|
6197
|
+
if( pCur->iBase < add64(SMALLEST_INT64, pCur->iStep) ){
|
|
6198
|
+
goto series_no_rows;
|
|
6199
|
+
}
|
|
6200
|
+
pCur->iBase = sub64(pCur->iBase, pCur->iStep);
|
|
6201
|
+
}
|
|
6734
6202
|
}
|
|
6735
|
-
if( pCur->
|
|
6736
|
-
pCur->
|
|
6203
|
+
if( pCur->iTerm<iMin ){
|
|
6204
|
+
pCur->iTerm = iMin;
|
|
6737
6205
|
}
|
|
6738
6206
|
}
|
|
6739
6207
|
}
|
|
6740
6208
|
|
|
6209
|
+
/* Adjust iTerm so that it is exactly the last value of the series.
|
|
6210
|
+
*/
|
|
6211
|
+
if( pCur->bDesc==0 ){
|
|
6212
|
+
if( pCur->iBase>pCur->iTerm ){
|
|
6213
|
+
goto series_no_rows;
|
|
6214
|
+
}
|
|
6215
|
+
pCur->iTerm = sub64(pCur->iTerm,
|
|
6216
|
+
span64(pCur->iTerm,pCur->iBase) % pCur->iStep);
|
|
6217
|
+
}else{
|
|
6218
|
+
if( pCur->iBase<pCur->iTerm ){
|
|
6219
|
+
goto series_no_rows;
|
|
6220
|
+
}
|
|
6221
|
+
pCur->iTerm = add64(pCur->iTerm,
|
|
6222
|
+
span64(pCur->iBase,pCur->iTerm) % pCur->iStep);
|
|
6223
|
+
}
|
|
6224
|
+
|
|
6225
|
+
/* Transform the series generator to output values in the requested
|
|
6226
|
+
** order.
|
|
6227
|
+
*/
|
|
6228
|
+
if( ((idxNum & 0x0008)!=0 && pCur->bDesc==0)
|
|
6229
|
+
|| ((idxNum & 0x0010)!=0 && pCur->bDesc!=0)
|
|
6230
|
+
){
|
|
6231
|
+
sqlite3_int64 tmp = pCur->iBase;
|
|
6232
|
+
pCur->iBase = pCur->iTerm;
|
|
6233
|
+
pCur->iTerm = tmp;
|
|
6234
|
+
pCur->bDesc = !pCur->bDesc;
|
|
6235
|
+
}
|
|
6236
|
+
|
|
6741
6237
|
/* Apply LIMIT and OFFSET constraints, if any */
|
|
6238
|
+
assert( pCur->iStep!=0 );
|
|
6742
6239
|
if( idxNum & 0x20 ){
|
|
6743
6240
|
if( iOffset>0 ){
|
|
6744
|
-
pCur
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
|
|
6749
|
-
if( pCur->ss.iStep<0 ){
|
|
6750
|
-
if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
|
|
6241
|
+
if( seriesSteps(pCur) < (sqlite3_uint64)iOffset ){
|
|
6242
|
+
goto series_no_rows;
|
|
6243
|
+
}else if( pCur->bDesc ){
|
|
6244
|
+
pCur->iBase = sub64(pCur->iBase, pCur->iStep*iOffset);
|
|
6751
6245
|
}else{
|
|
6752
|
-
|
|
6246
|
+
pCur->iBase = add64(pCur->iBase, pCur->iStep*iOffset);
|
|
6753
6247
|
}
|
|
6754
6248
|
}
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
for(i=0; i<argc; i++){
|
|
6759
|
-
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
|
|
6760
|
-
/* If any of the constraints have a NULL value, then return no rows.
|
|
6761
|
-
** See ticket https://sqlite.org/src/info/fac496b61722daf2 */
|
|
6762
|
-
returnNoRows = 1;
|
|
6763
|
-
break;
|
|
6249
|
+
if( iLimit>=0 && seriesSteps(pCur) > (sqlite3_uint64)iLimit ){
|
|
6250
|
+
pCur->iTerm = add64(pCur->iBase, (iLimit - 1)*pCur->iStep);
|
|
6764
6251
|
}
|
|
6765
6252
|
}
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
pCur->ss.iTerm = 0;
|
|
6769
|
-
pCur->ss.iStep = 1;
|
|
6770
|
-
}
|
|
6771
|
-
if( idxNum & 0x08 ){
|
|
6772
|
-
pCur->ss.isReversing = pCur->ss.iStep > 0;
|
|
6773
|
-
}else{
|
|
6774
|
-
pCur->ss.isReversing = pCur->ss.iStep < 0;
|
|
6775
|
-
}
|
|
6776
|
-
setupSequence( &pCur->ss );
|
|
6253
|
+
pCur->iValue = pCur->iBase;
|
|
6254
|
+
pCur->bDone = 0;
|
|
6777
6255
|
return SQLITE_OK;
|
|
6256
|
+
|
|
6257
|
+
series_no_rows:
|
|
6258
|
+
pCur->iBase = 0;
|
|
6259
|
+
pCur->iTerm = 0;
|
|
6260
|
+
pCur->iStep = 1;
|
|
6261
|
+
pCur->bDesc = 0;
|
|
6262
|
+
pCur->bDone = 1;
|
|
6263
|
+
return SQLITE_OK;
|
|
6778
6264
|
}
|
|
6779
6265
|
|
|
6780
6266
|
/*
|
|
@@ -7104,6 +6590,8 @@ int sqlite3_series_init(
|
|
|
7104
6590
|
** to p copies of X following by q-p copies of X? and that the size of the
|
|
7105
6591
|
** regular expression in the O(N*M) performance bound is computed after
|
|
7106
6592
|
** this expansion.
|
|
6593
|
+
**
|
|
6594
|
+
** To help prevent DoS attacks, the maximum size of the NFA is restricted.
|
|
7107
6595
|
*/
|
|
7108
6596
|
#include <string.h>
|
|
7109
6597
|
#include <stdlib.h>
|
|
@@ -7145,32 +6633,6 @@ SQLITE_EXTENSION_INIT1
|
|
|
7145
6633
|
#define RE_OP_BOUNDARY 17 /* Boundary between word and non-word */
|
|
7146
6634
|
#define RE_OP_ATSTART 18 /* Currently at the start of the string */
|
|
7147
6635
|
|
|
7148
|
-
#if defined(SQLITE_DEBUG)
|
|
7149
|
-
/* Opcode names used for symbolic debugging */
|
|
7150
|
-
static const char *ReOpName[] = {
|
|
7151
|
-
"EOF",
|
|
7152
|
-
"MATCH",
|
|
7153
|
-
"ANY",
|
|
7154
|
-
"ANYSTAR",
|
|
7155
|
-
"FORK",
|
|
7156
|
-
"GOTO",
|
|
7157
|
-
"ACCEPT",
|
|
7158
|
-
"CC_INC",
|
|
7159
|
-
"CC_EXC",
|
|
7160
|
-
"CC_VALUE",
|
|
7161
|
-
"CC_RANGE",
|
|
7162
|
-
"WORD",
|
|
7163
|
-
"NOTWORD",
|
|
7164
|
-
"DIGIT",
|
|
7165
|
-
"NOTDIGIT",
|
|
7166
|
-
"SPACE",
|
|
7167
|
-
"NOTSPACE",
|
|
7168
|
-
"BOUNDARY",
|
|
7169
|
-
"ATSTART",
|
|
7170
|
-
};
|
|
7171
|
-
#endif /* SQLITE_DEBUG */
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
6636
|
/* Each opcode is a "state" in the NFA */
|
|
7175
6637
|
typedef unsigned short ReStateNumber;
|
|
7176
6638
|
|
|
@@ -7207,6 +6669,7 @@ struct ReCompiled {
|
|
|
7207
6669
|
int nInit; /* Number of bytes in zInit */
|
|
7208
6670
|
unsigned nState; /* Number of entries in aOp[] and aArg[] */
|
|
7209
6671
|
unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
|
|
6672
|
+
unsigned mxAlloc; /* Complexity limit */
|
|
7210
6673
|
};
|
|
7211
6674
|
|
|
7212
6675
|
/* Add a state to the given state set if it is not already there */
|
|
@@ -7421,14 +6884,15 @@ re_match_end:
|
|
|
7421
6884
|
|
|
7422
6885
|
/* Resize the opcode and argument arrays for an RE under construction.
|
|
7423
6886
|
*/
|
|
7424
|
-
static int re_resize(ReCompiled *p, int N){
|
|
6887
|
+
static int re_resize(ReCompiled *p, unsigned int N){
|
|
7425
6888
|
char *aOp;
|
|
7426
6889
|
int *aArg;
|
|
6890
|
+
if( N>p->mxAlloc ){ p->zErr = "REGEXP pattern too big"; return 1; }
|
|
7427
6891
|
aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0]));
|
|
7428
|
-
if( aOp==0 ) return 1;
|
|
6892
|
+
if( aOp==0 ){ p->zErr = "out of memory"; return 1; }
|
|
7429
6893
|
p->aOp = aOp;
|
|
7430
6894
|
aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0]));
|
|
7431
|
-
if( aArg==0 ) return 1;
|
|
6895
|
+
if( aArg==0 ){ p->zErr = "out of memory"; return 1; }
|
|
7432
6896
|
p->aArg = aArg;
|
|
7433
6897
|
p->nAlloc = N;
|
|
7434
6898
|
return 0;
|
|
@@ -7459,7 +6923,7 @@ static int re_append(ReCompiled *p, int op, int arg){
|
|
|
7459
6923
|
/* Make a copy of N opcodes starting at iStart onto the end of the RE
|
|
7460
6924
|
** under construction.
|
|
7461
6925
|
*/
|
|
7462
|
-
static void re_copy(ReCompiled *p, int iStart, int N){
|
|
6926
|
+
static void re_copy(ReCompiled *p, int iStart, unsigned int N){
|
|
7463
6927
|
if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return;
|
|
7464
6928
|
memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0]));
|
|
7465
6929
|
memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0]));
|
|
@@ -7612,18 +7076,26 @@ static const char *re_subcompile_string(ReCompiled *p){
|
|
|
7612
7076
|
break;
|
|
7613
7077
|
}
|
|
7614
7078
|
case '{': {
|
|
7615
|
-
int m = 0, n = 0;
|
|
7616
|
-
int sz, j;
|
|
7079
|
+
unsigned int m = 0, n = 0;
|
|
7080
|
+
unsigned int sz, j;
|
|
7617
7081
|
if( iPrev<0 ) return "'{m,n}' without operand";
|
|
7618
|
-
while( (c=rePeek(p))>='0' && c<='9' ){
|
|
7082
|
+
while( (c=rePeek(p))>='0' && c<='9' ){
|
|
7083
|
+
m = m*10 + c - '0';
|
|
7084
|
+
if( m*2>p->mxAlloc ) return "REGEXP pattern too big";
|
|
7085
|
+
p->sIn.i++;
|
|
7086
|
+
}
|
|
7619
7087
|
n = m;
|
|
7620
7088
|
if( c==',' ){
|
|
7621
7089
|
p->sIn.i++;
|
|
7622
7090
|
n = 0;
|
|
7623
|
-
while( (c=rePeek(p))>='0' && c<='9' ){
|
|
7091
|
+
while( (c=rePeek(p))>='0' && c<='9' ){
|
|
7092
|
+
n = n*10 + c-'0';
|
|
7093
|
+
if( n*2>p->mxAlloc ) return "REGEXP pattern too big";
|
|
7094
|
+
p->sIn.i++;
|
|
7095
|
+
}
|
|
7624
7096
|
}
|
|
7625
7097
|
if( c!='}' ) return "unmatched '{'";
|
|
7626
|
-
if( n
|
|
7098
|
+
if( n<m ) return "n less than m in '{m,n}'";
|
|
7627
7099
|
p->sIn.i++;
|
|
7628
7100
|
sz = p->nState - iPrev;
|
|
7629
7101
|
if( m==0 ){
|
|
@@ -7639,7 +7111,7 @@ static const char *re_subcompile_string(ReCompiled *p){
|
|
|
7639
7111
|
re_copy(p, iPrev, sz);
|
|
7640
7112
|
}
|
|
7641
7113
|
if( n==0 && m>0 ){
|
|
7642
|
-
re_append(p, RE_OP_FORK, -sz);
|
|
7114
|
+
re_append(p, RE_OP_FORK, -(int)sz);
|
|
7643
7115
|
}
|
|
7644
7116
|
break;
|
|
7645
7117
|
}
|
|
@@ -7705,8 +7177,7 @@ static const char *re_subcompile_string(ReCompiled *p){
|
|
|
7705
7177
|
** regular expression. Applications should invoke this routine once
|
|
7706
7178
|
** for every call to re_compile() to avoid memory leaks.
|
|
7707
7179
|
*/
|
|
7708
|
-
static void re_free(
|
|
7709
|
-
ReCompiled *pRe = (ReCompiled*)p;
|
|
7180
|
+
static void re_free(ReCompiled *pRe){
|
|
7710
7181
|
if( pRe ){
|
|
7711
7182
|
sqlite3_free(pRe->aOp);
|
|
7712
7183
|
sqlite3_free(pRe->aArg);
|
|
@@ -7714,13 +7185,27 @@ static void re_free(void *p){
|
|
|
7714
7185
|
}
|
|
7715
7186
|
}
|
|
7716
7187
|
|
|
7188
|
+
/*
|
|
7189
|
+
** Version of re_free() that accepts a pointer of type (void*). Required
|
|
7190
|
+
** to satisfy sanitizers when the re_free() function is called via a
|
|
7191
|
+
** function pointer.
|
|
7192
|
+
*/
|
|
7193
|
+
static void re_free_voidptr(void *p){
|
|
7194
|
+
re_free((ReCompiled*)p);
|
|
7195
|
+
}
|
|
7196
|
+
|
|
7717
7197
|
/*
|
|
7718
7198
|
** Compile a textual regular expression in zIn[] into a compiled regular
|
|
7719
7199
|
** expression suitable for us by re_match() and return a pointer to the
|
|
7720
7200
|
** compiled regular expression in *ppRe. Return NULL on success or an
|
|
7721
7201
|
** error message if something goes wrong.
|
|
7722
7202
|
*/
|
|
7723
|
-
static const char *re_compile(
|
|
7203
|
+
static const char *re_compile(
|
|
7204
|
+
ReCompiled **ppRe, /* OUT: write compiled NFA here */
|
|
7205
|
+
const char *zIn, /* Input regular expression */
|
|
7206
|
+
int mxRe, /* Complexity limit */
|
|
7207
|
+
int noCase /* True for caseless comparisons */
|
|
7208
|
+
){
|
|
7724
7209
|
ReCompiled *pRe;
|
|
7725
7210
|
const char *zErr;
|
|
7726
7211
|
int i, j;
|
|
@@ -7732,9 +7217,11 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
|
|
|
7732
7217
|
}
|
|
7733
7218
|
memset(pRe, 0, sizeof(*pRe));
|
|
7734
7219
|
pRe->xNextChar = noCase ? re_next_char_nocase : re_next_char;
|
|
7220
|
+
pRe->mxAlloc = mxRe;
|
|
7735
7221
|
if( re_resize(pRe, 30) ){
|
|
7222
|
+
zErr = pRe->zErr;
|
|
7736
7223
|
re_free(pRe);
|
|
7737
|
-
return
|
|
7224
|
+
return zErr;
|
|
7738
7225
|
}
|
|
7739
7226
|
if( zIn[0]=='^' ){
|
|
7740
7227
|
zIn++;
|
|
@@ -7787,6 +7274,14 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
|
|
|
7787
7274
|
return pRe->zErr;
|
|
7788
7275
|
}
|
|
7789
7276
|
|
|
7277
|
+
/*
|
|
7278
|
+
** Compute a reasonable limit on the length of the REGEXP NFA.
|
|
7279
|
+
*/
|
|
7280
|
+
static int re_maxlen(sqlite3_context *context){
|
|
7281
|
+
sqlite3 *db = sqlite3_context_db_handle(context);
|
|
7282
|
+
return 75 + sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1)/2;
|
|
7283
|
+
}
|
|
7284
|
+
|
|
7790
7285
|
/*
|
|
7791
7286
|
** Implementation of the regexp() SQL function. This function implements
|
|
7792
7287
|
** the build-in REGEXP operator. The first argument to the function is the
|
|
@@ -7812,7 +7307,8 @@ static void re_sql_func(
|
|
|
7812
7307
|
if( pRe==0 ){
|
|
7813
7308
|
zPattern = (const char*)sqlite3_value_text(argv[0]);
|
|
7814
7309
|
if( zPattern==0 ) return;
|
|
7815
|
-
zErr = re_compile(&pRe, zPattern,
|
|
7310
|
+
zErr = re_compile(&pRe, zPattern, re_maxlen(context),
|
|
7311
|
+
sqlite3_user_data(context)!=0);
|
|
7816
7312
|
if( zErr ){
|
|
7817
7313
|
re_free(pRe);
|
|
7818
7314
|
sqlite3_result_error(context, zErr, -1);
|
|
@@ -7829,7 +7325,7 @@ static void re_sql_func(
|
|
|
7829
7325
|
sqlite3_result_int(context, re_match(pRe, zStr, -1));
|
|
7830
7326
|
}
|
|
7831
7327
|
if( setAux ){
|
|
7832
|
-
sqlite3_set_auxdata(context, 0, pRe,
|
|
7328
|
+
sqlite3_set_auxdata(context, 0, pRe, re_free_voidptr);
|
|
7833
7329
|
}
|
|
7834
7330
|
}
|
|
7835
7331
|
|
|
@@ -7854,10 +7350,32 @@ static void re_bytecode_func(
|
|
|
7854
7350
|
int n;
|
|
7855
7351
|
char *z;
|
|
7856
7352
|
(void)argc;
|
|
7353
|
+
static const char *ReOpName[] = {
|
|
7354
|
+
"EOF",
|
|
7355
|
+
"MATCH",
|
|
7356
|
+
"ANY",
|
|
7357
|
+
"ANYSTAR",
|
|
7358
|
+
"FORK",
|
|
7359
|
+
"GOTO",
|
|
7360
|
+
"ACCEPT",
|
|
7361
|
+
"CC_INC",
|
|
7362
|
+
"CC_EXC",
|
|
7363
|
+
"CC_VALUE",
|
|
7364
|
+
"CC_RANGE",
|
|
7365
|
+
"WORD",
|
|
7366
|
+
"NOTWORD",
|
|
7367
|
+
"DIGIT",
|
|
7368
|
+
"NOTDIGIT",
|
|
7369
|
+
"SPACE",
|
|
7370
|
+
"NOTSPACE",
|
|
7371
|
+
"BOUNDARY",
|
|
7372
|
+
"ATSTART",
|
|
7373
|
+
};
|
|
7857
7374
|
|
|
7858
7375
|
zPattern = (const char*)sqlite3_value_text(argv[0]);
|
|
7859
7376
|
if( zPattern==0 ) return;
|
|
7860
|
-
zErr = re_compile(&pRe, zPattern,
|
|
7377
|
+
zErr = re_compile(&pRe, zPattern, re_maxlen(context),
|
|
7378
|
+
sqlite3_user_data(context)!=0);
|
|
7861
7379
|
if( zErr ){
|
|
7862
7380
|
re_free(pRe);
|
|
7863
7381
|
sqlite3_result_error(context, zErr, -1);
|
|
@@ -8002,6 +7520,7 @@ int sqlite3_regexp_init(
|
|
|
8002
7520
|
** data: For a regular file, a blob containing the file data. For a
|
|
8003
7521
|
** symlink, a text value containing the text of the link. For a
|
|
8004
7522
|
** directory, NULL.
|
|
7523
|
+
** level: Directory hierarchy level. Topmost is 1.
|
|
8005
7524
|
**
|
|
8006
7525
|
** If a non-NULL value is specified for the optional $dir parameter and
|
|
8007
7526
|
** $path is a relative path, then $path is interpreted relative to $dir.
|
|
@@ -8027,13 +7546,11 @@ SQLITE_EXTENSION_INIT1
|
|
|
8027
7546
|
# include <dirent.h>
|
|
8028
7547
|
# include <utime.h>
|
|
8029
7548
|
# include <sys/time.h>
|
|
7549
|
+
# define STRUCT_STAT struct stat
|
|
8030
7550
|
#else
|
|
8031
|
-
# include "
|
|
8032
|
-
# include <io.h>
|
|
7551
|
+
/* # include "windirent.h" */
|
|
8033
7552
|
# include <direct.h>
|
|
8034
|
-
|
|
8035
|
-
# define dirent DIRENT
|
|
8036
|
-
# define stat _stat
|
|
7553
|
+
# define STRUCT_STAT struct _stat
|
|
8037
7554
|
# define chmod(path,mode) fileio_chmod(path,mode)
|
|
8038
7555
|
# define mkdir(path,mode) fileio_mkdir(path)
|
|
8039
7556
|
#endif
|
|
@@ -8051,14 +7568,16 @@ SQLITE_EXTENSION_INIT1
|
|
|
8051
7568
|
/*
|
|
8052
7569
|
** Structure of the fsdir() table-valued function
|
|
8053
7570
|
*/
|
|
8054
|
-
/* 0 1 2 3 4
|
|
8055
|
-
#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
|
|
7571
|
+
/* 0 1 2 3 4 5 6 */
|
|
7572
|
+
#define FSDIR_SCHEMA "(name,mode,mtime,data,level,path HIDDEN,dir HIDDEN)"
|
|
7573
|
+
|
|
8056
7574
|
#define FSDIR_COLUMN_NAME 0 /* Name of the file */
|
|
8057
7575
|
#define FSDIR_COLUMN_MODE 1 /* Access mode */
|
|
8058
7576
|
#define FSDIR_COLUMN_MTIME 2 /* Last modification time */
|
|
8059
7577
|
#define FSDIR_COLUMN_DATA 3 /* File content */
|
|
8060
|
-
#define
|
|
8061
|
-
#define
|
|
7578
|
+
#define FSDIR_COLUMN_LEVEL 4 /* Level. Topmost is 1 */
|
|
7579
|
+
#define FSDIR_COLUMN_PATH 5 /* Path to top of search */
|
|
7580
|
+
#define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */
|
|
8062
7581
|
|
|
8063
7582
|
/*
|
|
8064
7583
|
** UTF8 chmod() function for Windows
|
|
@@ -8224,7 +7743,7 @@ LPWSTR utf8_to_utf16(const char *z){
|
|
|
8224
7743
|
*/
|
|
8225
7744
|
static void statTimesToUtc(
|
|
8226
7745
|
const char *zPath,
|
|
8227
|
-
|
|
7746
|
+
STRUCT_STAT *pStatBuf
|
|
8228
7747
|
){
|
|
8229
7748
|
HANDLE hFindFile;
|
|
8230
7749
|
WIN32_FIND_DATAW fd;
|
|
@@ -8252,7 +7771,7 @@ static void statTimesToUtc(
|
|
|
8252
7771
|
*/
|
|
8253
7772
|
static int fileStat(
|
|
8254
7773
|
const char *zPath,
|
|
8255
|
-
|
|
7774
|
+
STRUCT_STAT *pStatBuf
|
|
8256
7775
|
){
|
|
8257
7776
|
#if defined(_WIN32)
|
|
8258
7777
|
sqlite3_int64 sz = strlen(zPath);
|
|
@@ -8276,7 +7795,7 @@ static int fileStat(
|
|
|
8276
7795
|
*/
|
|
8277
7796
|
static int fileLinkStat(
|
|
8278
7797
|
const char *zPath,
|
|
8279
|
-
|
|
7798
|
+
STRUCT_STAT *pStatBuf
|
|
8280
7799
|
){
|
|
8281
7800
|
#if defined(_WIN32)
|
|
8282
7801
|
return fileStat(zPath, pStatBuf);
|
|
@@ -8309,7 +7828,7 @@ static int makeDirectory(
|
|
|
8309
7828
|
int i = 1;
|
|
8310
7829
|
|
|
8311
7830
|
while( rc==SQLITE_OK ){
|
|
8312
|
-
|
|
7831
|
+
STRUCT_STAT sStat;
|
|
8313
7832
|
int rc2;
|
|
8314
7833
|
|
|
8315
7834
|
for(; zCopy[i]!='/' && i<nCopy; i++);
|
|
@@ -8359,7 +7878,7 @@ static int writeFile(
|
|
|
8359
7878
|
** be an error though - if there is already a directory at the same
|
|
8360
7879
|
** path and either the permissions already match or can be changed
|
|
8361
7880
|
** to do so using chmod(), it is not an error. */
|
|
8362
|
-
|
|
7881
|
+
STRUCT_STAT sStat;
|
|
8363
7882
|
if( errno!=EEXIST
|
|
8364
7883
|
|| 0!=fileStat(zFile, &sStat)
|
|
8365
7884
|
|| !S_ISDIR(sStat.st_mode)
|
|
@@ -8555,13 +8074,14 @@ struct fsdir_cursor {
|
|
|
8555
8074
|
sqlite3_vtab_cursor base; /* Base class - must be first */
|
|
8556
8075
|
|
|
8557
8076
|
int nLvl; /* Number of entries in aLvl[] array */
|
|
8077
|
+
int mxLvl; /* Maximum level */
|
|
8558
8078
|
int iLvl; /* Index of current entry */
|
|
8559
8079
|
FsdirLevel *aLvl; /* Hierarchy of directories being traversed */
|
|
8560
8080
|
|
|
8561
8081
|
const char *zBase;
|
|
8562
8082
|
int nBase;
|
|
8563
8083
|
|
|
8564
|
-
|
|
8084
|
+
STRUCT_STAT sStat; /* Current lstat() results */
|
|
8565
8085
|
char *zPath; /* Path to current entry */
|
|
8566
8086
|
sqlite3_int64 iRowid; /* Current rowid */
|
|
8567
8087
|
};
|
|
@@ -8673,7 +8193,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
|
|
|
8673
8193
|
mode_t m = pCur->sStat.st_mode;
|
|
8674
8194
|
|
|
8675
8195
|
pCur->iRowid++;
|
|
8676
|
-
if( S_ISDIR(m) ){
|
|
8196
|
+
if( S_ISDIR(m) && pCur->iLvl+3<pCur->mxLvl ){
|
|
8677
8197
|
/* Descend into this directory */
|
|
8678
8198
|
int iNew = pCur->iLvl + 1;
|
|
8679
8199
|
FsdirLevel *pLvl;
|
|
@@ -8693,7 +8213,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
|
|
|
8693
8213
|
pCur->zPath = 0;
|
|
8694
8214
|
pLvl->pDir = opendir(pLvl->zDir);
|
|
8695
8215
|
if( pLvl->pDir==0 ){
|
|
8696
|
-
fsdirSetErrmsg(pCur, "cannot read directory: %s",
|
|
8216
|
+
fsdirSetErrmsg(pCur, "cannot read directory: %s", pLvl->zDir);
|
|
8697
8217
|
return SQLITE_ERROR;
|
|
8698
8218
|
}
|
|
8699
8219
|
}
|
|
@@ -8781,7 +8301,11 @@ static int fsdirColumn(
|
|
|
8781
8301
|
}else{
|
|
8782
8302
|
readFileContents(ctx, pCur->zPath);
|
|
8783
8303
|
}
|
|
8304
|
+
break;
|
|
8784
8305
|
}
|
|
8306
|
+
case FSDIR_COLUMN_LEVEL:
|
|
8307
|
+
sqlite3_result_int(ctx, pCur->iLvl+2);
|
|
8308
|
+
break;
|
|
8785
8309
|
case FSDIR_COLUMN_PATH:
|
|
8786
8310
|
default: {
|
|
8787
8311
|
/* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
|
|
@@ -8815,8 +8339,11 @@ static int fsdirEof(sqlite3_vtab_cursor *cur){
|
|
|
8815
8339
|
/*
|
|
8816
8340
|
** xFilter callback.
|
|
8817
8341
|
**
|
|
8818
|
-
** idxNum
|
|
8819
|
-
**
|
|
8342
|
+
** idxNum bit Meaning
|
|
8343
|
+
** 0x01 PATH=N
|
|
8344
|
+
** 0x02 DIR=N
|
|
8345
|
+
** 0x04 LEVEL<N
|
|
8346
|
+
** 0x08 LEVEL<=N
|
|
8820
8347
|
*/
|
|
8821
8348
|
static int fsdirFilter(
|
|
8822
8349
|
sqlite3_vtab_cursor *cur,
|
|
@@ -8825,6 +8352,7 @@ static int fsdirFilter(
|
|
|
8825
8352
|
){
|
|
8826
8353
|
const char *zDir = 0;
|
|
8827
8354
|
fsdir_cursor *pCur = (fsdir_cursor*)cur;
|
|
8355
|
+
int i;
|
|
8828
8356
|
(void)idxStr;
|
|
8829
8357
|
fsdirResetCursor(pCur);
|
|
8830
8358
|
|
|
@@ -8833,14 +8361,24 @@ static int fsdirFilter(
|
|
|
8833
8361
|
return SQLITE_ERROR;
|
|
8834
8362
|
}
|
|
8835
8363
|
|
|
8836
|
-
assert(
|
|
8364
|
+
assert( (idxNum & 0x01)!=0 && argc>0 );
|
|
8837
8365
|
zDir = (const char*)sqlite3_value_text(argv[0]);
|
|
8838
8366
|
if( zDir==0 ){
|
|
8839
8367
|
fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
|
|
8840
8368
|
return SQLITE_ERROR;
|
|
8841
8369
|
}
|
|
8842
|
-
|
|
8843
|
-
|
|
8370
|
+
i = 1;
|
|
8371
|
+
if( (idxNum & 0x02)!=0 ){
|
|
8372
|
+
assert( argc>i );
|
|
8373
|
+
pCur->zBase = (const char*)sqlite3_value_text(argv[i++]);
|
|
8374
|
+
}
|
|
8375
|
+
if( (idxNum & 0x0c)!=0 ){
|
|
8376
|
+
assert( argc>i );
|
|
8377
|
+
pCur->mxLvl = sqlite3_value_int(argv[i++]);
|
|
8378
|
+
if( idxNum & 0x08 ) pCur->mxLvl++;
|
|
8379
|
+
if( pCur->mxLvl<=0 ) pCur->mxLvl = 1000000000;
|
|
8380
|
+
}else{
|
|
8381
|
+
pCur->mxLvl = 1000000000;
|
|
8844
8382
|
}
|
|
8845
8383
|
if( pCur->zBase ){
|
|
8846
8384
|
pCur->nBase = (int)strlen(pCur->zBase)+1;
|
|
@@ -8869,10 +8407,11 @@ static int fsdirFilter(
|
|
|
8869
8407
|
** In this implementation idxNum is used to represent the
|
|
8870
8408
|
** query plan. idxStr is unused.
|
|
8871
8409
|
**
|
|
8872
|
-
** The query plan is represented by
|
|
8410
|
+
** The query plan is represented by bits in idxNum:
|
|
8873
8411
|
**
|
|
8874
|
-
**
|
|
8875
|
-
**
|
|
8412
|
+
** 0x01 The path value is supplied by argv[0]
|
|
8413
|
+
** 0x02 dir is in argv[1]
|
|
8414
|
+
** 0x04 maxdepth is in argv[1] or [2]
|
|
8876
8415
|
*/
|
|
8877
8416
|
static int fsdirBestIndex(
|
|
8878
8417
|
sqlite3_vtab *tab,
|
|
@@ -8881,6 +8420,9 @@ static int fsdirBestIndex(
|
|
|
8881
8420
|
int i; /* Loop over constraints */
|
|
8882
8421
|
int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
|
|
8883
8422
|
int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
|
|
8423
|
+
int idxLevel = -1; /* Index in pIdxInfo->aConstraint of LEVEL< or <= */
|
|
8424
|
+
int idxLevelEQ = 0; /* 0x08 for LEVEL<= or LEVEL=. 0x04 for LEVEL< */
|
|
8425
|
+
int omitLevel = 0; /* omit the LEVEL constraint */
|
|
8884
8426
|
int seenPath = 0; /* True if an unusable PATH= constraint is seen */
|
|
8885
8427
|
int seenDir = 0; /* True if an unusable DIR= constraint is seen */
|
|
8886
8428
|
const struct sqlite3_index_constraint *pConstraint;
|
|
@@ -8888,25 +8430,48 @@ static int fsdirBestIndex(
|
|
|
8888
8430
|
(void)tab;
|
|
8889
8431
|
pConstraint = pIdxInfo->aConstraint;
|
|
8890
8432
|
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
|
8891
|
-
if( pConstraint->op
|
|
8892
|
-
|
|
8893
|
-
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8433
|
+
if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
|
8434
|
+
switch( pConstraint->iColumn ){
|
|
8435
|
+
case FSDIR_COLUMN_PATH: {
|
|
8436
|
+
if( pConstraint->usable ){
|
|
8437
|
+
idxPath = i;
|
|
8438
|
+
seenPath = 0;
|
|
8439
|
+
}else if( idxPath<0 ){
|
|
8440
|
+
seenPath = 1;
|
|
8441
|
+
}
|
|
8442
|
+
break;
|
|
8899
8443
|
}
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
|
|
8904
|
-
idxDir
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8444
|
+
case FSDIR_COLUMN_DIR: {
|
|
8445
|
+
if( pConstraint->usable ){
|
|
8446
|
+
idxDir = i;
|
|
8447
|
+
seenDir = 0;
|
|
8448
|
+
}else if( idxDir<0 ){
|
|
8449
|
+
seenDir = 1;
|
|
8450
|
+
}
|
|
8451
|
+
break;
|
|
8908
8452
|
}
|
|
8909
|
-
|
|
8453
|
+
case FSDIR_COLUMN_LEVEL: {
|
|
8454
|
+
if( pConstraint->usable && idxLevel<0 ){
|
|
8455
|
+
idxLevel = i;
|
|
8456
|
+
idxLevelEQ = 0x08;
|
|
8457
|
+
omitLevel = 0;
|
|
8458
|
+
}
|
|
8459
|
+
break;
|
|
8460
|
+
}
|
|
8461
|
+
}
|
|
8462
|
+
}else
|
|
8463
|
+
if( pConstraint->iColumn==FSDIR_COLUMN_LEVEL
|
|
8464
|
+
&& pConstraint->usable
|
|
8465
|
+
&& idxLevel<0
|
|
8466
|
+
){
|
|
8467
|
+
if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){
|
|
8468
|
+
idxLevel = i;
|
|
8469
|
+
idxLevelEQ = 0x08;
|
|
8470
|
+
omitLevel = 1;
|
|
8471
|
+
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){
|
|
8472
|
+
idxLevel = i;
|
|
8473
|
+
idxLevelEQ = 0x04;
|
|
8474
|
+
omitLevel = 1;
|
|
8910
8475
|
}
|
|
8911
8476
|
}
|
|
8912
8477
|
}
|
|
@@ -8923,14 +8488,20 @@ static int fsdirBestIndex(
|
|
|
8923
8488
|
}else{
|
|
8924
8489
|
pIdxInfo->aConstraintUsage[idxPath].omit = 1;
|
|
8925
8490
|
pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
|
|
8491
|
+
pIdxInfo->idxNum = 0x01;
|
|
8492
|
+
pIdxInfo->estimatedCost = 1.0e9;
|
|
8493
|
+
i = 2;
|
|
8926
8494
|
if( idxDir>=0 ){
|
|
8927
8495
|
pIdxInfo->aConstraintUsage[idxDir].omit = 1;
|
|
8928
|
-
pIdxInfo->aConstraintUsage[idxDir].argvIndex =
|
|
8929
|
-
pIdxInfo->idxNum
|
|
8930
|
-
pIdxInfo->estimatedCost
|
|
8931
|
-
}
|
|
8932
|
-
|
|
8933
|
-
pIdxInfo->
|
|
8496
|
+
pIdxInfo->aConstraintUsage[idxDir].argvIndex = i++;
|
|
8497
|
+
pIdxInfo->idxNum |= 0x02;
|
|
8498
|
+
pIdxInfo->estimatedCost /= 1.0e4;
|
|
8499
|
+
}
|
|
8500
|
+
if( idxLevel>=0 ){
|
|
8501
|
+
pIdxInfo->aConstraintUsage[idxLevel].omit = omitLevel;
|
|
8502
|
+
pIdxInfo->aConstraintUsage[idxLevel].argvIndex = i++;
|
|
8503
|
+
pIdxInfo->idxNum |= idxLevelEQ;
|
|
8504
|
+
pIdxInfo->estimatedCost /= 1.0e4;
|
|
8934
8505
|
}
|
|
8935
8506
|
}
|
|
8936
8507
|
|
|
@@ -9387,6 +8958,7 @@ static int completionFilter(
|
|
|
9387
8958
|
if( pCur->nPrefix>0 ){
|
|
9388
8959
|
pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
|
|
9389
8960
|
if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
|
|
8961
|
+
pCur->nPrefix = (int)strlen(pCur->zPrefix);
|
|
9390
8962
|
}
|
|
9391
8963
|
iArg = 1;
|
|
9392
8964
|
}
|
|
@@ -9395,6 +8967,7 @@ static int completionFilter(
|
|
|
9395
8967
|
if( pCur->nLine>0 ){
|
|
9396
8968
|
pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
|
|
9397
8969
|
if( pCur->zLine==0 ) return SQLITE_NOMEM;
|
|
8970
|
+
pCur->nLine = (int)strlen(pCur->zLine);
|
|
9398
8971
|
}
|
|
9399
8972
|
}
|
|
9400
8973
|
if( pCur->zLine!=0 && pCur->zPrefix==0 ){
|
|
@@ -9406,6 +8979,7 @@ static int completionFilter(
|
|
|
9406
8979
|
if( pCur->nPrefix>0 ){
|
|
9407
8980
|
pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
|
|
9408
8981
|
if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
|
|
8982
|
+
pCur->nPrefix = (int)strlen(pCur->zPrefix);
|
|
9409
8983
|
}
|
|
9410
8984
|
}
|
|
9411
8985
|
pCur->iRowid = 0;
|
|
@@ -10319,7 +9893,13 @@ static const char ZIPFILE_SCHEMA[] =
|
|
|
10319
9893
|
") WITHOUT ROWID;";
|
|
10320
9894
|
|
|
10321
9895
|
#define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */
|
|
10322
|
-
#define
|
|
9896
|
+
#define ZIPFILE_MX_NAME (250) /* Windows limitation on filename size */
|
|
9897
|
+
|
|
9898
|
+
/*
|
|
9899
|
+
** The buffer should be large enough to contain 3 65536 byte strings - the
|
|
9900
|
+
** filename, the extra field and the file comment.
|
|
9901
|
+
*/
|
|
9902
|
+
#define ZIPFILE_BUFFER_SIZE (200*1024)
|
|
10323
9903
|
|
|
10324
9904
|
|
|
10325
9905
|
/*
|
|
@@ -10876,6 +10456,7 @@ static int zipfileReadLFH(
|
|
|
10876
10456
|
pLFH->szUncompressed = zipfileRead32(aRead);
|
|
10877
10457
|
pLFH->nFile = zipfileRead16(aRead);
|
|
10878
10458
|
pLFH->nExtra = zipfileRead16(aRead);
|
|
10459
|
+
if( pLFH->nFile>ZIPFILE_MX_NAME ) rc = SQLITE_ERROR;
|
|
10879
10460
|
}
|
|
10880
10461
|
return rc;
|
|
10881
10462
|
}
|
|
@@ -11002,6 +10583,15 @@ static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
|
|
|
11002
10583
|
);
|
|
11003
10584
|
}
|
|
11004
10585
|
|
|
10586
|
+
/*
|
|
10587
|
+
** Set (*pzErr) to point to a buffer from sqlite3_malloc() containing a
|
|
10588
|
+
** generic corruption message and return SQLITE_CORRUPT;
|
|
10589
|
+
*/
|
|
10590
|
+
static int zipfileCorrupt(char **pzErr){
|
|
10591
|
+
*pzErr = sqlite3_mprintf("zip archive is corrupt");
|
|
10592
|
+
return SQLITE_CORRUPT;
|
|
10593
|
+
}
|
|
10594
|
+
|
|
11005
10595
|
/*
|
|
11006
10596
|
** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
|
|
11007
10597
|
** size) containing an entire zip archive image. Or, if aBlob is NULL,
|
|
@@ -11024,12 +10614,15 @@ static int zipfileGetEntry(
|
|
|
11024
10614
|
u8 *aRead;
|
|
11025
10615
|
char **pzErr = &pTab->base.zErrMsg;
|
|
11026
10616
|
int rc = SQLITE_OK;
|
|
11027
|
-
(void)nBlob;
|
|
11028
10617
|
|
|
11029
10618
|
if( aBlob==0 ){
|
|
11030
10619
|
aRead = pTab->aBuffer;
|
|
11031
10620
|
rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
|
|
11032
10621
|
}else{
|
|
10622
|
+
if( (iOff+ZIPFILE_CDS_FIXED_SZ)>nBlob ){
|
|
10623
|
+
/* Not enough data for the CDS structure. Corruption. */
|
|
10624
|
+
return zipfileCorrupt(pzErr);
|
|
10625
|
+
}
|
|
11033
10626
|
aRead = (u8*)&aBlob[iOff];
|
|
11034
10627
|
}
|
|
11035
10628
|
|
|
@@ -11060,6 +10653,9 @@ static int zipfileGetEntry(
|
|
|
11060
10653
|
);
|
|
11061
10654
|
}else{
|
|
11062
10655
|
aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
|
|
10656
|
+
if( (iOff + ZIPFILE_LFH_FIXED_SZ + nFile + nExtra)>nBlob ){
|
|
10657
|
+
rc = zipfileCorrupt(pzErr);
|
|
10658
|
+
}
|
|
11063
10659
|
}
|
|
11064
10660
|
}
|
|
11065
10661
|
|
|
@@ -11082,6 +10678,9 @@ static int zipfileGetEntry(
|
|
|
11082
10678
|
rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
|
|
11083
10679
|
}else{
|
|
11084
10680
|
aRead = (u8*)&aBlob[pNew->cds.iOffset];
|
|
10681
|
+
if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){
|
|
10682
|
+
rc = zipfileCorrupt(pzErr);
|
|
10683
|
+
}
|
|
11085
10684
|
}
|
|
11086
10685
|
|
|
11087
10686
|
if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
|
|
@@ -11089,8 +10688,12 @@ static int zipfileGetEntry(
|
|
|
11089
10688
|
pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
|
|
11090
10689
|
pNew->iDataOff += lfh.nFile + lfh.nExtra;
|
|
11091
10690
|
if( aBlob && pNew->cds.szCompressed ){
|
|
11092
|
-
pNew->
|
|
11093
|
-
|
|
10691
|
+
if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){
|
|
10692
|
+
rc = zipfileCorrupt(pzErr);
|
|
10693
|
+
}else{
|
|
10694
|
+
pNew->aData = &pNew->aExtra[nExtra];
|
|
10695
|
+
memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
|
|
10696
|
+
}
|
|
11094
10697
|
}
|
|
11095
10698
|
}else{
|
|
11096
10699
|
*pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
|
|
@@ -11877,6 +11480,11 @@ static int zipfileUpdate(
|
|
|
11877
11480
|
zPath = (const char*)sqlite3_value_text(apVal[2]);
|
|
11878
11481
|
if( zPath==0 ) zPath = "";
|
|
11879
11482
|
nPath = (int)strlen(zPath);
|
|
11483
|
+
if( nPath>ZIPFILE_MX_NAME ){
|
|
11484
|
+
zipfileTableErr(pTab, "filename too long; max: %d bytes",
|
|
11485
|
+
ZIPFILE_MX_NAME);
|
|
11486
|
+
rc = SQLITE_CONSTRAINT;
|
|
11487
|
+
}
|
|
11880
11488
|
mTime = zipfileGetTime(apVal[4]);
|
|
11881
11489
|
}
|
|
11882
11490
|
|
|
@@ -12238,6 +11846,13 @@ static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
|
|
|
12238
11846
|
rc = SQLITE_ERROR;
|
|
12239
11847
|
goto zipfile_step_out;
|
|
12240
11848
|
}
|
|
11849
|
+
if( nName>ZIPFILE_MX_NAME ){
|
|
11850
|
+
zErr = sqlite3_mprintf(
|
|
11851
|
+
"filename argument to zipfile() too big; max: %d bytes",
|
|
11852
|
+
ZIPFILE_MX_NAME);
|
|
11853
|
+
rc = SQLITE_ERROR;
|
|
11854
|
+
goto zipfile_step_out;
|
|
11855
|
+
}
|
|
12241
11856
|
|
|
12242
11857
|
/* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
|
|
12243
11858
|
** deflate compression) or NULL (choose automatically). */
|
|
@@ -12580,6 +12195,7 @@ int sqlite3_sqlar_init(
|
|
|
12580
12195
|
|
|
12581
12196
|
/************************* End ../ext/misc/sqlar.c ********************/
|
|
12582
12197
|
#endif
|
|
12198
|
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
|
|
12583
12199
|
/************************* Begin ../ext/expert/sqlite3expert.h ******************/
|
|
12584
12200
|
/*
|
|
12585
12201
|
** 2017 April 07
|
|
@@ -12926,11 +12542,11 @@ struct sqlite3expert {
|
|
|
12926
12542
|
** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc().
|
|
12927
12543
|
** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
|
|
12928
12544
|
*/
|
|
12929
|
-
static void *idxMalloc(int *pRc,
|
|
12545
|
+
static void *idxMalloc(int *pRc, i64 nByte){
|
|
12930
12546
|
void *pRet;
|
|
12931
12547
|
assert( *pRc==SQLITE_OK );
|
|
12932
12548
|
assert( nByte>0 );
|
|
12933
|
-
pRet =
|
|
12549
|
+
pRet = sqlite3_malloc64(nByte);
|
|
12934
12550
|
if( pRet ){
|
|
12935
12551
|
memset(pRet, 0, nByte);
|
|
12936
12552
|
}else{
|
|
@@ -12997,7 +12613,7 @@ static int idxHashAdd(
|
|
|
12997
12613
|
return 1;
|
|
12998
12614
|
}
|
|
12999
12615
|
}
|
|
13000
|
-
pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1);
|
|
12616
|
+
pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + (i64)nKey+1 + (i64)nVal+1);
|
|
13001
12617
|
if( pEntry ){
|
|
13002
12618
|
pEntry->zKey = (char*)&pEntry[1];
|
|
13003
12619
|
memcpy(pEntry->zKey, zKey, nKey);
|
|
@@ -13132,15 +12748,15 @@ struct ExpertCsr {
|
|
|
13132
12748
|
};
|
|
13133
12749
|
|
|
13134
12750
|
static char *expertDequote(const char *zIn){
|
|
13135
|
-
|
|
13136
|
-
char *zRet =
|
|
12751
|
+
i64 n = STRLEN(zIn);
|
|
12752
|
+
char *zRet = sqlite3_malloc64(n);
|
|
13137
12753
|
|
|
13138
12754
|
assert( zIn[0]=='\'' );
|
|
13139
12755
|
assert( zIn[n-1]=='\'' );
|
|
13140
12756
|
|
|
13141
12757
|
if( zRet ){
|
|
13142
|
-
|
|
13143
|
-
|
|
12758
|
+
i64 iOut = 0;
|
|
12759
|
+
i64 iIn = 0;
|
|
13144
12760
|
for(iIn=1; iIn<(n-1); iIn++){
|
|
13145
12761
|
if( zIn[iIn]=='\'' ){
|
|
13146
12762
|
assert( zIn[iIn+1]=='\'' );
|
|
@@ -13453,7 +13069,7 @@ static int idxGetTableInfo(
|
|
|
13453
13069
|
sqlite3_stmt *p1 = 0;
|
|
13454
13070
|
int nCol = 0;
|
|
13455
13071
|
int nTab;
|
|
13456
|
-
|
|
13072
|
+
i64 nByte;
|
|
13457
13073
|
IdxTable *pNew = 0;
|
|
13458
13074
|
int rc, rc2;
|
|
13459
13075
|
char *pCsr = 0;
|
|
@@ -13545,14 +13161,14 @@ static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
|
|
|
13545
13161
|
va_list ap;
|
|
13546
13162
|
char *zAppend = 0;
|
|
13547
13163
|
char *zRet = 0;
|
|
13548
|
-
|
|
13549
|
-
|
|
13164
|
+
i64 nIn = zIn ? STRLEN(zIn) : 0;
|
|
13165
|
+
i64 nAppend = 0;
|
|
13550
13166
|
va_start(ap, zFmt);
|
|
13551
13167
|
if( *pRc==SQLITE_OK ){
|
|
13552
13168
|
zAppend = sqlite3_vmprintf(zFmt, ap);
|
|
13553
13169
|
if( zAppend ){
|
|
13554
13170
|
nAppend = STRLEN(zAppend);
|
|
13555
|
-
zRet = (char*)
|
|
13171
|
+
zRet = (char*)sqlite3_malloc64(nIn + nAppend + 1);
|
|
13556
13172
|
}
|
|
13557
13173
|
if( zAppend && zRet ){
|
|
13558
13174
|
if( nIn ) memcpy(zRet, zIn, nIn);
|
|
@@ -14316,8 +13932,8 @@ struct IdxRemCtx {
|
|
|
14316
13932
|
int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
|
|
14317
13933
|
i64 iVal; /* SQLITE_INTEGER value */
|
|
14318
13934
|
double rVal; /* SQLITE_FLOAT value */
|
|
14319
|
-
|
|
14320
|
-
|
|
13935
|
+
i64 nByte; /* Bytes of space allocated at z */
|
|
13936
|
+
i64 n; /* Size of buffer z */
|
|
14321
13937
|
char *z; /* SQLITE_TEXT/BLOB value */
|
|
14322
13938
|
} aSlot[1];
|
|
14323
13939
|
};
|
|
@@ -14353,11 +13969,13 @@ static void idxRemFunc(
|
|
|
14353
13969
|
break;
|
|
14354
13970
|
|
|
14355
13971
|
case SQLITE_BLOB:
|
|
14356
|
-
|
|
13972
|
+
assert( pSlot->n <= 0x7fffffff );
|
|
13973
|
+
sqlite3_result_blob(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT);
|
|
14357
13974
|
break;
|
|
14358
13975
|
|
|
14359
13976
|
case SQLITE_TEXT:
|
|
14360
|
-
|
|
13977
|
+
assert( pSlot->n <= 0x7fffffff );
|
|
13978
|
+
sqlite3_result_text(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT);
|
|
14361
13979
|
break;
|
|
14362
13980
|
}
|
|
14363
13981
|
|
|
@@ -14377,10 +13995,10 @@ static void idxRemFunc(
|
|
|
14377
13995
|
|
|
14378
13996
|
case SQLITE_BLOB:
|
|
14379
13997
|
case SQLITE_TEXT: {
|
|
14380
|
-
|
|
13998
|
+
i64 nByte = sqlite3_value_bytes(argv[1]);
|
|
14381
13999
|
const void *pData = 0;
|
|
14382
14000
|
if( nByte>pSlot->nByte ){
|
|
14383
|
-
char *zNew = (char*)
|
|
14001
|
+
char *zNew = (char*)sqlite3_realloc64(pSlot->z, nByte*2);
|
|
14384
14002
|
if( zNew==0 ){
|
|
14385
14003
|
sqlite3_result_error_nomem(pCtx);
|
|
14386
14004
|
return;
|
|
@@ -14435,7 +14053,7 @@ static int idxPopulateOneStat1(
|
|
|
14435
14053
|
int nCol = 0;
|
|
14436
14054
|
int i;
|
|
14437
14055
|
sqlite3_stmt *pQuery = 0;
|
|
14438
|
-
|
|
14056
|
+
i64 *aStat = 0;
|
|
14439
14057
|
int rc = SQLITE_OK;
|
|
14440
14058
|
|
|
14441
14059
|
assert( p->iSample>0 );
|
|
@@ -14481,7 +14099,7 @@ static int idxPopulateOneStat1(
|
|
|
14481
14099
|
sqlite3_free(zQuery);
|
|
14482
14100
|
|
|
14483
14101
|
if( rc==SQLITE_OK ){
|
|
14484
|
-
aStat = (
|
|
14102
|
+
aStat = (i64*)idxMalloc(&rc, sizeof(i64)*(nCol+1));
|
|
14485
14103
|
}
|
|
14486
14104
|
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
|
|
14487
14105
|
IdxHashEntry *pEntry;
|
|
@@ -14498,11 +14116,11 @@ static int idxPopulateOneStat1(
|
|
|
14498
14116
|
}
|
|
14499
14117
|
|
|
14500
14118
|
if( rc==SQLITE_OK ){
|
|
14501
|
-
|
|
14502
|
-
zStat = sqlite3_mprintf("%
|
|
14119
|
+
i64 s0 = aStat[0];
|
|
14120
|
+
zStat = sqlite3_mprintf("%lld", s0);
|
|
14503
14121
|
if( zStat==0 ) rc = SQLITE_NOMEM;
|
|
14504
14122
|
for(i=1; rc==SQLITE_OK && i<=nCol; i++){
|
|
14505
|
-
zStat = idxAppendText(&rc, zStat, " %
|
|
14123
|
+
zStat = idxAppendText(&rc, zStat, " %lld", (s0+aStat[i]/2) / aStat[i]);
|
|
14506
14124
|
}
|
|
14507
14125
|
}
|
|
14508
14126
|
|
|
@@ -14581,7 +14199,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
|
|
14581
14199
|
rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);
|
|
14582
14200
|
|
|
14583
14201
|
if( rc==SQLITE_OK ){
|
|
14584
|
-
|
|
14202
|
+
i64 nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
|
|
14585
14203
|
pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
|
|
14586
14204
|
}
|
|
14587
14205
|
|
|
@@ -14598,7 +14216,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
|
|
14598
14216
|
}
|
|
14599
14217
|
|
|
14600
14218
|
if( rc==SQLITE_OK ){
|
|
14601
|
-
pCtx->nSlot = nMax+1;
|
|
14219
|
+
pCtx->nSlot = (i64)nMax+1;
|
|
14602
14220
|
rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
|
|
14603
14221
|
}
|
|
14604
14222
|
if( rc==SQLITE_OK ){
|
|
@@ -14865,7 +14483,7 @@ int sqlite3_expert_sql(
|
|
|
14865
14483
|
if( pStmt ){
|
|
14866
14484
|
IdxStatement *pNew;
|
|
14867
14485
|
const char *z = sqlite3_sql(pStmt);
|
|
14868
|
-
|
|
14486
|
+
i64 n = STRLEN(z);
|
|
14869
14487
|
pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
|
|
14870
14488
|
if( rc==SQLITE_OK ){
|
|
14871
14489
|
pNew->zSql = (char*)&pNew[1];
|
|
@@ -14988,6 +14606,7 @@ void sqlite3_expert_destroy(sqlite3expert *p){
|
|
|
14988
14606
|
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
|
|
14989
14607
|
|
|
14990
14608
|
/************************* End ../ext/expert/sqlite3expert.c ********************/
|
|
14609
|
+
#endif
|
|
14991
14610
|
/************************* Begin ../ext/intck/sqlite3intck.h ******************/
|
|
14992
14611
|
/*
|
|
14993
14612
|
** 2024-02-08
|
|
@@ -21628,11 +21247,13 @@ struct OpenSession {
|
|
|
21628
21247
|
};
|
|
21629
21248
|
#endif
|
|
21630
21249
|
|
|
21250
|
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
|
|
21631
21251
|
typedef struct ExpertInfo ExpertInfo;
|
|
21632
21252
|
struct ExpertInfo {
|
|
21633
21253
|
sqlite3expert *pExpert;
|
|
21634
21254
|
int bVerbose;
|
|
21635
21255
|
};
|
|
21256
|
+
#endif
|
|
21636
21257
|
|
|
21637
21258
|
/* A single line in the EQP output */
|
|
21638
21259
|
typedef struct EQPGraphRow EQPGraphRow;
|
|
@@ -21687,7 +21308,7 @@ struct ShellState {
|
|
|
21687
21308
|
int inputNesting; /* Track nesting level of .read and other redirects */
|
|
21688
21309
|
int outCount; /* Revert to stdout when reaching zero */
|
|
21689
21310
|
int cnt; /* Number of records displayed so far */
|
|
21690
|
-
|
|
21311
|
+
i64 lineno; /* Line number of last line read from in */
|
|
21691
21312
|
int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
|
|
21692
21313
|
FILE *in; /* Read commands from this stream */
|
|
21693
21314
|
FILE *out; /* Write results here */
|
|
@@ -21736,7 +21357,9 @@ struct ShellState {
|
|
|
21736
21357
|
int iIndent; /* Index of current op in aiIndent[] */
|
|
21737
21358
|
char *zNonce; /* Nonce for temporary safe-mode escapes */
|
|
21738
21359
|
EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
|
|
21360
|
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
|
|
21739
21361
|
ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
|
|
21362
|
+
#endif
|
|
21740
21363
|
#ifdef SQLITE_SHELL_FIDDLE
|
|
21741
21364
|
struct {
|
|
21742
21365
|
const char * zInput; /* Input string from wasm/JS proxy */
|
|
@@ -21764,9 +21387,8 @@ static ShellState shellState;
|
|
|
21764
21387
|
#define SHELL_OPEN_NORMAL 1 /* Normal database file */
|
|
21765
21388
|
#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
|
|
21766
21389
|
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
|
|
21767
|
-
#define
|
|
21768
|
-
#define
|
|
21769
|
-
#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
|
|
21390
|
+
#define SHELL_OPEN_DESERIALIZE 4 /* Open using sqlite3_deserialize() */
|
|
21391
|
+
#define SHELL_OPEN_HEXDB 5 /* Use "dbtotxt" output as data source */
|
|
21770
21392
|
|
|
21771
21393
|
/* Allowed values for ShellState.eTraceType
|
|
21772
21394
|
*/
|
|
@@ -21922,7 +21544,7 @@ static void failIfSafeMode(
|
|
|
21922
21544
|
va_start(ap, zErrMsg);
|
|
21923
21545
|
zMsg = sqlite3_vmprintf(zErrMsg, ap);
|
|
21924
21546
|
va_end(ap);
|
|
21925
|
-
sqlite3_fprintf(stderr, "line %
|
|
21547
|
+
sqlite3_fprintf(stderr, "line %lld: %s\n", p->lineno, zMsg);
|
|
21926
21548
|
exit(1);
|
|
21927
21549
|
}
|
|
21928
21550
|
}
|
|
@@ -22109,7 +21731,7 @@ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
|
|
|
22109
21731
|
int i;
|
|
22110
21732
|
unsigned char *aBlob = (unsigned char*)pBlob;
|
|
22111
21733
|
|
|
22112
|
-
char *zStr =
|
|
21734
|
+
char *zStr = sqlite3_malloc64((i64)nBlob*2 + 1);
|
|
22113
21735
|
shell_check_oom(zStr);
|
|
22114
21736
|
|
|
22115
21737
|
for(i=0; i<nBlob; i++){
|
|
@@ -22130,7 +21752,7 @@ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
|
|
|
22130
21752
|
** Output the given string as a quoted string using SQL quoting conventions:
|
|
22131
21753
|
**
|
|
22132
21754
|
** (1) Single quotes (') within the string are doubled
|
|
22133
|
-
** (2) The
|
|
21755
|
+
** (2) The while string is enclosed in '...'
|
|
22134
21756
|
** (3) Control characters other than \n, \t, and \r\n are escaped
|
|
22135
21757
|
** using \u00XX notation and if such substitutions occur,
|
|
22136
21758
|
** the whole string is enclosed in unistr('...') instead of '...'.
|
|
@@ -22376,7 +21998,7 @@ static void output_json_string(FILE *out, const char *z, i64 n){
|
|
|
22376
21998
|
** other than \t, \n, and \r\n
|
|
22377
21999
|
**
|
|
22378
22000
|
** If no escaping is needed (the common case) then set *ppFree to NULL
|
|
22379
|
-
** and return the original string. If
|
|
22001
|
+
** and return the original string. If escaping is needed, write the
|
|
22380
22002
|
** escaped string into memory obtained from sqlite3_malloc64() or the
|
|
22381
22003
|
** equivalent, and return the new string and set *ppFree to the new string
|
|
22382
22004
|
** as well.
|
|
@@ -23381,28 +23003,17 @@ static void createSelftestTable(ShellState *p){
|
|
|
23381
23003
|
** table name.
|
|
23382
23004
|
*/
|
|
23383
23005
|
static void set_table_name(ShellState *p, const char *zName){
|
|
23384
|
-
int i, n;
|
|
23385
|
-
char cQuote;
|
|
23386
|
-
char *z;
|
|
23387
|
-
|
|
23388
23006
|
if( p->zDestTable ){
|
|
23389
|
-
|
|
23007
|
+
sqlite3_free(p->zDestTable);
|
|
23390
23008
|
p->zDestTable = 0;
|
|
23391
23009
|
}
|
|
23392
23010
|
if( zName==0 ) return;
|
|
23393
|
-
|
|
23394
|
-
|
|
23395
|
-
|
|
23396
|
-
|
|
23397
|
-
shell_check_oom(z);
|
|
23398
|
-
n = 0;
|
|
23399
|
-
if( cQuote ) z[n++] = cQuote;
|
|
23400
|
-
for(i=0; zName[i]; i++){
|
|
23401
|
-
z[n++] = zName[i];
|
|
23402
|
-
if( zName[i]==cQuote ) z[n++] = cQuote;
|
|
23011
|
+
if( quoteChar(zName) ){
|
|
23012
|
+
p->zDestTable = sqlite3_mprintf("\"%w\"", zName);
|
|
23013
|
+
}else{
|
|
23014
|
+
p->zDestTable = sqlite3_mprintf("%s", zName);
|
|
23403
23015
|
}
|
|
23404
|
-
|
|
23405
|
-
z[n] = 0;
|
|
23016
|
+
shell_check_oom(p->zDestTable);
|
|
23406
23017
|
}
|
|
23407
23018
|
|
|
23408
23019
|
/*
|
|
@@ -23599,8 +23210,8 @@ static int display_stats(
|
|
|
23599
23210
|
ShellState *pArg, /* Pointer to ShellState */
|
|
23600
23211
|
int bReset /* True to reset the stats */
|
|
23601
23212
|
){
|
|
23602
|
-
int iCur;
|
|
23603
|
-
|
|
23213
|
+
int iCur, iHiwtr;
|
|
23214
|
+
sqlite3_int64 iCur64, iHiwtr64;
|
|
23604
23215
|
FILE *out;
|
|
23605
23216
|
if( pArg==0 || pArg->out==0 ) return 0;
|
|
23606
23217
|
out = pArg->out;
|
|
@@ -23689,6 +23300,9 @@ static int display_stats(
|
|
|
23689
23300
|
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
|
|
23690
23301
|
sqlite3_fprintf(out,
|
|
23691
23302
|
"Page cache misses: %d\n", iCur);
|
|
23303
|
+
iHiwtr64 = iCur64 = -1;
|
|
23304
|
+
sqlite3_db_status64(db, SQLITE_DBSTATUS_TEMPBUF_SPILL, &iCur64, &iHiwtr64,
|
|
23305
|
+
0);
|
|
23692
23306
|
iHiwtr = iCur = -1;
|
|
23693
23307
|
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
|
|
23694
23308
|
sqlite3_fprintf(out,
|
|
@@ -23697,6 +23311,10 @@ static int display_stats(
|
|
|
23697
23311
|
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
|
|
23698
23312
|
sqlite3_fprintf(out,
|
|
23699
23313
|
"Page cache spills: %d\n", iCur);
|
|
23314
|
+
sqlite3_fprintf(out,
|
|
23315
|
+
"Temporary data spilled to disk: %lld\n", iCur64);
|
|
23316
|
+
sqlite3_db_status64(db, SQLITE_DBSTATUS_TEMPBUF_SPILL, &iCur64, &iHiwtr64,
|
|
23317
|
+
1);
|
|
23700
23318
|
iHiwtr = iCur = -1;
|
|
23701
23319
|
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
|
|
23702
23320
|
sqlite3_fprintf(out,
|
|
@@ -24102,6 +23720,36 @@ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
|
|
|
24102
23720
|
memcpy(zBuf, &zVar[6], szVar-5);
|
|
24103
23721
|
sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
|
|
24104
23722
|
}
|
|
23723
|
+
#ifdef SQLITE_ENABLE_CARRAY
|
|
23724
|
+
}else if( strncmp(zVar, "$carray_", 8)==0 ){
|
|
23725
|
+
static char *azColorNames[] = {
|
|
23726
|
+
"azure", "black", "blue", "brown", "cyan", "fuchsia", "gold",
|
|
23727
|
+
"gray", "green", "indigo", "khaki", "lime", "magenta", "maroon",
|
|
23728
|
+
"navy", "olive", "orange", "pink", "purple", "red", "silver",
|
|
23729
|
+
"tan", "teal", "violet", "white", "yellow"
|
|
23730
|
+
};
|
|
23731
|
+
static int aPrimes[] = {
|
|
23732
|
+
1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
|
|
23733
|
+
53, 59, 61, 67, 71, 73, 79, 83, 89, 97
|
|
23734
|
+
};
|
|
23735
|
+
/* Special bindings: carray($carray_clr), carray($carray_primes)
|
|
23736
|
+
** with --unsafe-testing: carray($carray_clr_p,26,'char*'),
|
|
23737
|
+
** carray($carray_primes_p,26,'int32')
|
|
23738
|
+
*/
|
|
23739
|
+
if( strcmp(zVar+8,"clr")==0 ){
|
|
23740
|
+
sqlite3_carray_bind(pStmt,i,azColorNames,26,SQLITE_CARRAY_TEXT,0);
|
|
23741
|
+
}else if( strcmp(zVar+8,"primes")==0 ){
|
|
23742
|
+
sqlite3_carray_bind(pStmt,i,aPrimes,26,SQLITE_CARRAY_INT32,0);
|
|
23743
|
+
}else if( strcmp(zVar+8,"clr_p")==0
|
|
23744
|
+
&& ShellHasFlag(pArg,SHFLG_TestingMode) ){
|
|
23745
|
+
sqlite3_bind_pointer(pStmt,i,azColorNames,"carray",0);
|
|
23746
|
+
}else if( strcmp(zVar+8,"primes_p")==0
|
|
23747
|
+
&& ShellHasFlag(pArg,SHFLG_TestingMode) ){
|
|
23748
|
+
sqlite3_bind_pointer(pStmt,i,aPrimes,"carray",0);
|
|
23749
|
+
}else{
|
|
23750
|
+
sqlite3_bind_null(pStmt, i);
|
|
23751
|
+
}
|
|
23752
|
+
#endif
|
|
24105
23753
|
}else{
|
|
24106
23754
|
sqlite3_bind_null(pStmt, i);
|
|
24107
23755
|
}
|
|
@@ -24684,7 +24332,7 @@ static void exec_prepared_stmt(
|
|
|
24684
24332
|
}
|
|
24685
24333
|
}
|
|
24686
24334
|
|
|
24687
|
-
#
|
|
24335
|
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
|
|
24688
24336
|
/*
|
|
24689
24337
|
** This function is called to process SQL if the previous shell command
|
|
24690
24338
|
** was ".expert". It passes the SQL in the second argument directly to
|
|
@@ -24816,7 +24464,7 @@ static int expertDotCommand(
|
|
|
24816
24464
|
|
|
24817
24465
|
return rc;
|
|
24818
24466
|
}
|
|
24819
|
-
#endif /*
|
|
24467
|
+
#endif /* !SQLITE_OMIT_VIRTUALTABLE && !SQLITE_OMIT_AUTHORIZATION */
|
|
24820
24468
|
|
|
24821
24469
|
/*
|
|
24822
24470
|
** Execute a statement or set of statements. Print
|
|
@@ -24842,7 +24490,7 @@ static int shell_exec(
|
|
|
24842
24490
|
*pzErrMsg = NULL;
|
|
24843
24491
|
}
|
|
24844
24492
|
|
|
24845
|
-
#
|
|
24493
|
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
|
|
24846
24494
|
if( pArg->expert.pExpert ){
|
|
24847
24495
|
rc = expertHandleSQL(pArg, zSql, pzErrMsg);
|
|
24848
24496
|
return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
|
|
@@ -25004,7 +24652,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){
|
|
|
25004
24652
|
sqlite3_stmt *pStmt;
|
|
25005
24653
|
char *zSql;
|
|
25006
24654
|
int nCol = 0;
|
|
25007
|
-
|
|
24655
|
+
i64 nAlloc = 0;
|
|
25008
24656
|
int nPK = 0; /* Number of PRIMARY KEY columns seen */
|
|
25009
24657
|
int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
|
|
25010
24658
|
int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
|
|
@@ -25018,7 +24666,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){
|
|
|
25018
24666
|
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
|
25019
24667
|
if( nCol>=nAlloc-2 ){
|
|
25020
24668
|
nAlloc = nAlloc*2 + nCol + 10;
|
|
25021
|
-
azCol =
|
|
24669
|
+
azCol = sqlite3_realloc64(azCol, nAlloc*sizeof(azCol[0]));
|
|
25022
24670
|
shell_check_oom(azCol);
|
|
25023
24671
|
}
|
|
25024
24672
|
azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
|
|
@@ -25107,6 +24755,9 @@ static void toggleSelectOrder(sqlite3 *db){
|
|
|
25107
24755
|
sqlite3_exec(db, zStmt, 0, 0, 0);
|
|
25108
24756
|
}
|
|
25109
24757
|
|
|
24758
|
+
/* Forward reference */
|
|
24759
|
+
static int db_int(sqlite3 *db, const char *zSql, ...);
|
|
24760
|
+
|
|
25110
24761
|
/*
|
|
25111
24762
|
** This is a different callback routine used for dumping the database.
|
|
25112
24763
|
** Each row received by this callback consists of a table name,
|
|
@@ -25133,7 +24784,21 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
|
|
|
25133
24784
|
noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
|
|
25134
24785
|
|
|
25135
24786
|
if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
|
|
25136
|
-
/*
|
|
24787
|
+
/* The sqlite_sequence table is repopulated last. Delete content
|
|
24788
|
+
** in the sqlite_sequence table added by prior repopulations prior to
|
|
24789
|
+
** repopulating sqlite_sequence itself. But only do this if the
|
|
24790
|
+
** table is non-empty, because if it is empty the table might not
|
|
24791
|
+
** have been recreated by prior repopulations. See forum posts:
|
|
24792
|
+
** 2024-10-13T17:10:01z and 2025-10-29T19:38:43z
|
|
24793
|
+
*/
|
|
24794
|
+
if( db_int(p->db, "SELECT count(*) FROM sqlite_sequence")>0 ){
|
|
24795
|
+
if( !p->writableSchema ){
|
|
24796
|
+
sqlite3_fputs("PRAGMA writable_schema=ON;\n", p->out);
|
|
24797
|
+
p->writableSchema = 1;
|
|
24798
|
+
}
|
|
24799
|
+
sqlite3_fputs("CREATE TABLE IF NOT EXISTS sqlite_sequence(name,seq);\n"
|
|
24800
|
+
"DELETE FROM sqlite_sequence;\n", p->out);
|
|
24801
|
+
}
|
|
25137
24802
|
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
|
|
25138
24803
|
if( !dataOnly ) sqlite3_fputs("ANALYZE sqlite_schema;\n", p->out);
|
|
25139
24804
|
}else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
|
|
@@ -25209,13 +24874,13 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
|
|
|
25209
24874
|
|
|
25210
24875
|
savedDestTable = p->zDestTable;
|
|
25211
24876
|
savedMode = p->mode;
|
|
25212
|
-
p->zDestTable = sTable.
|
|
24877
|
+
p->zDestTable = sTable.zTxt;
|
|
25213
24878
|
p->mode = p->cMode = MODE_Insert;
|
|
25214
|
-
rc = shell_exec(p, sSelect.
|
|
24879
|
+
rc = shell_exec(p, sSelect.zTxt, 0);
|
|
25215
24880
|
if( (rc&0xff)==SQLITE_CORRUPT ){
|
|
25216
24881
|
sqlite3_fputs("/****** CORRUPTION ERROR *******/\n", p->out);
|
|
25217
24882
|
toggleSelectOrder(p->db);
|
|
25218
|
-
shell_exec(p, sSelect.
|
|
24883
|
+
shell_exec(p, sSelect.zTxt, 0);
|
|
25219
24884
|
toggleSelectOrder(p->db);
|
|
25220
24885
|
}
|
|
25221
24886
|
p->zDestTable = savedDestTable;
|
|
@@ -25348,7 +25013,9 @@ static const char *(azHelp[]) = {
|
|
|
25348
25013
|
#ifndef SQLITE_SHELL_FIDDLE
|
|
25349
25014
|
".exit ?CODE? Exit this program with return-code CODE",
|
|
25350
25015
|
#endif
|
|
25016
|
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
|
|
25351
25017
|
".expert EXPERIMENTAL. Suggest indexes for queries",
|
|
25018
|
+
#endif
|
|
25352
25019
|
".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
|
|
25353
25020
|
".filectrl CMD ... Run various sqlite3_file_control() operations",
|
|
25354
25021
|
" --schema SCHEMA Use SCHEMA instead of \"main\"",
|
|
@@ -25373,7 +25040,7 @@ static const char *(azHelp[]) = {
|
|
|
25373
25040
|
" input text.",
|
|
25374
25041
|
#endif
|
|
25375
25042
|
#ifndef SQLITE_OMIT_TEST_CONTROL
|
|
25376
|
-
"
|
|
25043
|
+
".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
|
|
25377
25044
|
#endif
|
|
25378
25045
|
".indexes ?TABLE? Show names of indexes",
|
|
25379
25046
|
" If TABLE is specified, only show indexes for",
|
|
@@ -25440,10 +25107,17 @@ static const char *(azHelp[]) = {
|
|
|
25440
25107
|
#endif
|
|
25441
25108
|
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
25442
25109
|
" --deserialize Load into memory using sqlite3_deserialize()",
|
|
25110
|
+
#endif
|
|
25111
|
+
/*" --exclusive Set the SQLITE_OPEN_EXCLUSIVE flag", UNDOCUMENTED */
|
|
25112
|
+
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
25443
25113
|
" --hexdb Load the output of \"dbtotxt\" as an in-memory db",
|
|
25114
|
+
#endif
|
|
25115
|
+
" --ifexist Only open if FILE already exists",
|
|
25116
|
+
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
25444
25117
|
" --maxsize N Maximum size for --hexdb or --deserialized database",
|
|
25445
25118
|
#endif
|
|
25446
25119
|
" --new Initialize FILE to an empty database",
|
|
25120
|
+
" --normal FILE is an ordinary SQLite database",
|
|
25447
25121
|
" --nofollow Do not follow symbolic links",
|
|
25448
25122
|
" --readonly Open FILE readonly",
|
|
25449
25123
|
" --zip FILE is a ZIP archive",
|
|
@@ -25678,7 +25352,7 @@ static int showHelp(FILE *out, const char *zPattern){
|
|
|
25678
25352
|
}
|
|
25679
25353
|
|
|
25680
25354
|
/* Forward reference */
|
|
25681
|
-
static int process_input(ShellState *p);
|
|
25355
|
+
static int process_input(ShellState *p, const char*);
|
|
25682
25356
|
|
|
25683
25357
|
/*
|
|
25684
25358
|
** Read the content of file zName into memory obtained from sqlite3_malloc64()
|
|
@@ -25785,18 +25459,26 @@ static int session_filter(void *pCtx, const char *zTab){
|
|
|
25785
25459
|
** Otherwise, assume an ordinary database regardless of the filename if
|
|
25786
25460
|
** the type cannot be determined from content.
|
|
25787
25461
|
*/
|
|
25788
|
-
int deduceDatabaseType(const char *zName, int dfltZip){
|
|
25789
|
-
FILE *f
|
|
25462
|
+
int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
|
|
25463
|
+
FILE *f;
|
|
25790
25464
|
size_t n;
|
|
25465
|
+
sqlite3 *db = 0;
|
|
25466
|
+
sqlite3_stmt *pStmt = 0;
|
|
25791
25467
|
int rc = SHELL_OPEN_UNSPEC;
|
|
25792
25468
|
char zBuf[100];
|
|
25793
|
-
if(
|
|
25794
|
-
|
|
25795
|
-
|
|
25796
|
-
|
|
25797
|
-
|
|
25798
|
-
|
|
25469
|
+
if( access(zName,0)!=0 ) goto database_type_by_name;
|
|
25470
|
+
if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK
|
|
25471
|
+
&& sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
|
|
25472
|
+
==SQLITE_OK
|
|
25473
|
+
&& sqlite3_step(pStmt)==SQLITE_ROW
|
|
25474
|
+
){
|
|
25475
|
+
rc = SHELL_OPEN_NORMAL;
|
|
25799
25476
|
}
|
|
25477
|
+
sqlite3_finalize(pStmt);
|
|
25478
|
+
sqlite3_close(db);
|
|
25479
|
+
if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
|
|
25480
|
+
f = sqlite3_fopen(zName, "rb");
|
|
25481
|
+
if( f==0 ) goto database_type_by_name;
|
|
25800
25482
|
n = fread(zBuf, 16, 1, f);
|
|
25801
25483
|
if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
|
|
25802
25484
|
fclose(f);
|
|
@@ -25818,6 +25500,14 @@ int deduceDatabaseType(const char *zName, int dfltZip){
|
|
|
25818
25500
|
}
|
|
25819
25501
|
fclose(f);
|
|
25820
25502
|
return rc;
|
|
25503
|
+
|
|
25504
|
+
database_type_by_name:
|
|
25505
|
+
if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
|
|
25506
|
+
rc = SHELL_OPEN_ZIPFILE;
|
|
25507
|
+
}else{
|
|
25508
|
+
rc = SHELL_OPEN_NORMAL;
|
|
25509
|
+
}
|
|
25510
|
+
return rc;
|
|
25821
25511
|
}
|
|
25822
25512
|
|
|
25823
25513
|
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
@@ -25828,11 +25518,11 @@ int deduceDatabaseType(const char *zName, int dfltZip){
|
|
|
25828
25518
|
*/
|
|
25829
25519
|
static unsigned char *readHexDb(ShellState *p, int *pnData){
|
|
25830
25520
|
unsigned char *a = 0;
|
|
25831
|
-
|
|
25832
|
-
int n = 0;
|
|
25521
|
+
i64 nLine;
|
|
25522
|
+
int n = 0; /* Size of db per first line of hex dump */
|
|
25523
|
+
i64 sz = 0; /* n rounded up to nearest page boundary */
|
|
25833
25524
|
int pgsz = 0;
|
|
25834
|
-
|
|
25835
|
-
int j, k;
|
|
25525
|
+
i64 iOffset = 0;
|
|
25836
25526
|
int rc;
|
|
25837
25527
|
FILE *in;
|
|
25838
25528
|
const char *zDbFilename = p->pAuxDb->zDbFilename;
|
|
@@ -25856,16 +25546,21 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
|
|
|
25856
25546
|
rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
|
|
25857
25547
|
if( rc!=2 ) goto readHexDb_error;
|
|
25858
25548
|
if( n<0 ) goto readHexDb_error;
|
|
25859
|
-
if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
|
|
25860
|
-
n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
|
|
25861
|
-
a = sqlite3_malloc( n ? n : 1 );
|
|
25862
|
-
shell_check_oom(a);
|
|
25863
|
-
memset(a, 0, n);
|
|
25864
25549
|
if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
|
|
25865
25550
|
sqlite3_fputs("invalid pagesize\n", stderr);
|
|
25866
25551
|
goto readHexDb_error;
|
|
25867
25552
|
}
|
|
25553
|
+
sz = ((i64)n+pgsz-1)&~(pgsz-1); /* Round up to nearest multiple of pgsz */
|
|
25554
|
+
a = sqlite3_malloc64( sz ? sz : 1 );
|
|
25555
|
+
shell_check_oom(a);
|
|
25556
|
+
memset(a, 0, sz);
|
|
25868
25557
|
for(nLine++; sqlite3_fgets(zLine, sizeof(zLine), in)!=0; nLine++){
|
|
25558
|
+
int j = 0; /* Page number from "| page" line */
|
|
25559
|
+
int k = 0; /* Offset from "| page" line */
|
|
25560
|
+
if( nLine>=2000000000 ){
|
|
25561
|
+
sqlite3_fprintf(stderr, "input too big\n");
|
|
25562
|
+
goto readHexDb_error;
|
|
25563
|
+
}
|
|
25869
25564
|
rc = sscanf(zLine, "| page %d offset %d", &j, &k);
|
|
25870
25565
|
if( rc==2 ){
|
|
25871
25566
|
iOffset = k;
|
|
@@ -25878,14 +25573,14 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
|
|
|
25878
25573
|
&j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
|
|
25879
25574
|
&x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
|
|
25880
25575
|
if( rc==17 ){
|
|
25881
|
-
|
|
25882
|
-
if(
|
|
25576
|
+
i64 iOff = iOffset+j;
|
|
25577
|
+
if( iOff+16<=sz && iOff>=0 ){
|
|
25883
25578
|
int ii;
|
|
25884
|
-
for(ii=0; ii<16; ii++) a[
|
|
25579
|
+
for(ii=0; ii<16; ii++) a[iOff+ii] = x[ii]&0xff;
|
|
25885
25580
|
}
|
|
25886
25581
|
}
|
|
25887
25582
|
}
|
|
25888
|
-
*pnData =
|
|
25583
|
+
*pnData = sz;
|
|
25889
25584
|
if( in!=p->in ){
|
|
25890
25585
|
fclose(in);
|
|
25891
25586
|
}else{
|
|
@@ -25904,7 +25599,7 @@ readHexDb_error:
|
|
|
25904
25599
|
p->lineno = nLine;
|
|
25905
25600
|
}
|
|
25906
25601
|
sqlite3_free(a);
|
|
25907
|
-
sqlite3_fprintf(stderr,"Error on line %
|
|
25602
|
+
sqlite3_fprintf(stderr,"Error on line %lld of --hexdb input\n", nLine);
|
|
25908
25603
|
return 0;
|
|
25909
25604
|
}
|
|
25910
25605
|
#endif /* SQLITE_OMIT_DESERIALIZE */
|
|
@@ -25952,7 +25647,7 @@ static void shellModuleSchema(
|
|
|
25952
25647
|
if( zFake ){
|
|
25953
25648
|
sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
|
|
25954
25649
|
-1, sqlite3_free);
|
|
25955
|
-
|
|
25650
|
+
sqlite3_free(zFake);
|
|
25956
25651
|
}
|
|
25957
25652
|
}
|
|
25958
25653
|
|
|
@@ -25981,13 +25676,16 @@ static void open_db(ShellState *p, int openFlags){
|
|
|
25981
25676
|
p->openMode = SHELL_OPEN_NORMAL;
|
|
25982
25677
|
}else{
|
|
25983
25678
|
p->openMode = (u8)deduceDatabaseType(zDbFilename,
|
|
25984
|
-
(openFlags & OPEN_DB_ZIPFILE)!=0);
|
|
25679
|
+
(openFlags & OPEN_DB_ZIPFILE)!=0, p->openFlags);
|
|
25985
25680
|
}
|
|
25986
25681
|
}
|
|
25682
|
+
if( (p->openFlags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE))==0 ){
|
|
25683
|
+
if( p->openFlags==0 ) p->openFlags = SQLITE_OPEN_CREATE;
|
|
25684
|
+
p->openFlags |= SQLITE_OPEN_READWRITE;
|
|
25685
|
+
}
|
|
25987
25686
|
switch( p->openMode ){
|
|
25988
25687
|
case SHELL_OPEN_APPENDVFS: {
|
|
25989
|
-
sqlite3_open_v2(zDbFilename, &p->db,
|
|
25990
|
-
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
|
|
25688
|
+
sqlite3_open_v2(zDbFilename, &p->db, p->openFlags, "apndvfs");
|
|
25991
25689
|
break;
|
|
25992
25690
|
}
|
|
25993
25691
|
case SHELL_OPEN_HEXDB:
|
|
@@ -25999,15 +25697,9 @@ static void open_db(ShellState *p, int openFlags){
|
|
|
25999
25697
|
sqlite3_open(":memory:", &p->db);
|
|
26000
25698
|
break;
|
|
26001
25699
|
}
|
|
26002
|
-
case SHELL_OPEN_READONLY: {
|
|
26003
|
-
sqlite3_open_v2(zDbFilename, &p->db,
|
|
26004
|
-
SQLITE_OPEN_READONLY|p->openFlags, 0);
|
|
26005
|
-
break;
|
|
26006
|
-
}
|
|
26007
25700
|
case SHELL_OPEN_UNSPEC:
|
|
26008
25701
|
case SHELL_OPEN_NORMAL: {
|
|
26009
|
-
sqlite3_open_v2(zDbFilename, &p->db,
|
|
26010
|
-
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
|
|
25702
|
+
sqlite3_open_v2(zDbFilename, &p->db, p->openFlags, 0);
|
|
26011
25703
|
break;
|
|
26012
25704
|
}
|
|
26013
25705
|
}
|
|
@@ -26047,7 +25739,6 @@ static void open_db(ShellState *p, int openFlags){
|
|
|
26047
25739
|
sqlite3_uint_init(p->db, 0, 0);
|
|
26048
25740
|
sqlite3_stmtrand_init(p->db, 0, 0);
|
|
26049
25741
|
sqlite3_decimal_init(p->db, 0, 0);
|
|
26050
|
-
sqlite3_percentile_init(p->db, 0, 0);
|
|
26051
25742
|
sqlite3_base64_init(p->db, 0, 0);
|
|
26052
25743
|
sqlite3_base85_init(p->db, 0, 0);
|
|
26053
25744
|
sqlite3_regexp_init(p->db, 0, 0);
|
|
@@ -26146,9 +25837,11 @@ static void open_db(ShellState *p, int openFlags){
|
|
|
26146
25837
|
#endif
|
|
26147
25838
|
}
|
|
26148
25839
|
if( p->db!=0 ){
|
|
25840
|
+
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
26149
25841
|
if( p->bSafeModePersist ){
|
|
26150
25842
|
sqlite3_set_authorizer(p->db, safeModeAuth, p);
|
|
26151
25843
|
}
|
|
25844
|
+
#endif
|
|
26152
25845
|
sqlite3_db_config(
|
|
26153
25846
|
p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->scanstatsOn, (int*)0
|
|
26154
25847
|
);
|
|
@@ -26461,8 +26154,8 @@ struct ImportCtx {
|
|
|
26461
26154
|
FILE *in; /* Read the CSV text from this input stream */
|
|
26462
26155
|
int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
|
|
26463
26156
|
char *z; /* Accumulated text for a field */
|
|
26464
|
-
|
|
26465
|
-
|
|
26157
|
+
i64 n; /* Number of bytes in z */
|
|
26158
|
+
i64 nAlloc; /* Space allocated for z[] */
|
|
26466
26159
|
int nLine; /* Current line number */
|
|
26467
26160
|
int nRow; /* Number of rows imported */
|
|
26468
26161
|
int nErr; /* Number of errors encountered */
|
|
@@ -26932,10 +26625,13 @@ static int db_int(sqlite3 *db, const char *zSql, ...){
|
|
|
26932
26625
|
** Convert a 2-byte or 4-byte big-endian integer into a native integer
|
|
26933
26626
|
*/
|
|
26934
26627
|
static unsigned int get2byteInt(unsigned char *a){
|
|
26935
|
-
return (a[0]<<8) + a[1];
|
|
26628
|
+
return ((unsigned int)a[0]<<8) + (unsigned int)a[1];
|
|
26936
26629
|
}
|
|
26937
26630
|
static unsigned int get4byteInt(unsigned char *a){
|
|
26938
|
-
return (a[0]<<24)
|
|
26631
|
+
return ((unsigned int)a[0]<<24)
|
|
26632
|
+
+ ((unsigned int)a[1]<<16)
|
|
26633
|
+
+ ((unsigned int)a[2]<<8)
|
|
26634
|
+
+ (unsigned int)a[3];
|
|
26939
26635
|
}
|
|
26940
26636
|
|
|
26941
26637
|
/*
|
|
@@ -27072,7 +26768,7 @@ static int shell_dbtotxt_command(ShellState *p, int nArg, char **azArg){
|
|
|
27072
26768
|
sqlite3_finalize(pStmt);
|
|
27073
26769
|
pStmt = 0;
|
|
27074
26770
|
if( nPage<1 ) goto dbtotxt_error;
|
|
27075
|
-
rc = sqlite3_prepare_v2(p->db, "PRAGMA
|
|
26771
|
+
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
|
|
27076
26772
|
if( rc ) goto dbtotxt_error;
|
|
27077
26773
|
if( sqlite3_step(pStmt)!=SQLITE_ROW ){
|
|
27078
26774
|
zTail = "unk.db";
|
|
@@ -27083,6 +26779,11 @@ static int shell_dbtotxt_command(ShellState *p, int nArg, char **azArg){
|
|
|
27083
26779
|
#if defined(_WIN32)
|
|
27084
26780
|
if( zTail==0 ) zTail = strrchr(zFilename, '\\');
|
|
27085
26781
|
#endif
|
|
26782
|
+
if( zTail==0 ){
|
|
26783
|
+
zTail = zFilename;
|
|
26784
|
+
}else if( zTail[1]!=0 ){
|
|
26785
|
+
zTail++;
|
|
26786
|
+
}
|
|
27086
26787
|
}
|
|
27087
26788
|
zName = strdup(zTail);
|
|
27088
26789
|
shell_check_oom(zName);
|
|
@@ -27252,6 +26953,43 @@ static int optionMatch(const char *zStr, const char *zOpt){
|
|
|
27252
26953
|
return cli_strcmp(zStr, zOpt)==0;
|
|
27253
26954
|
}
|
|
27254
26955
|
|
|
26956
|
+
/*
|
|
26957
|
+
** The input zFN is guaranteed to start with "file:" and is thus a URI
|
|
26958
|
+
** filename. Extract the actual filename and return a pointer to that
|
|
26959
|
+
** filename in spaced obtained from sqlite3_malloc().
|
|
26960
|
+
**
|
|
26961
|
+
** The caller is responsible for freeing space using sqlite3_free() when
|
|
26962
|
+
** it has finished with the filename.
|
|
26963
|
+
*/
|
|
26964
|
+
static char *shellFilenameFromUri(const char *zFN){
|
|
26965
|
+
char *zOut;
|
|
26966
|
+
int i, j, d1, d2;
|
|
26967
|
+
|
|
26968
|
+
assert( cli_strncmp(zFN,"file:",5)==0 );
|
|
26969
|
+
zOut = sqlite3_mprintf("%s", zFN+5);
|
|
26970
|
+
shell_check_oom(zOut);
|
|
26971
|
+
for(i=j=0; zOut[i]!=0 && zOut[i]!='?'; i++){
|
|
26972
|
+
if( zOut[i]!='%' ){
|
|
26973
|
+
zOut[j++] = zOut[i];
|
|
26974
|
+
continue;
|
|
26975
|
+
}
|
|
26976
|
+
d1 = hexDigitValue(zOut[i+1]);
|
|
26977
|
+
if( d1<0 ){
|
|
26978
|
+
zOut[j] = 0;
|
|
26979
|
+
break;
|
|
26980
|
+
}
|
|
26981
|
+
d2 = hexDigitValue(zOut[i+2]);
|
|
26982
|
+
if( d2<0 ){
|
|
26983
|
+
zOut[j] = 0;
|
|
26984
|
+
break;
|
|
26985
|
+
}
|
|
26986
|
+
zOut[j++] = d1*16 + d2;
|
|
26987
|
+
i += 2;
|
|
26988
|
+
}
|
|
26989
|
+
zOut[j] = 0;
|
|
26990
|
+
return zOut;
|
|
26991
|
+
}
|
|
26992
|
+
|
|
27255
26993
|
/*
|
|
27256
26994
|
** Delete a file.
|
|
27257
26995
|
*/
|
|
@@ -27965,25 +27703,41 @@ static void arWhereClause(
|
|
|
27965
27703
|
char **pzWhere /* OUT: New WHERE clause */
|
|
27966
27704
|
){
|
|
27967
27705
|
char *zWhere = 0;
|
|
27968
|
-
const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
|
|
27969
27706
|
if( *pRc==SQLITE_OK ){
|
|
27970
27707
|
if( pAr->nArg==0 ){
|
|
27971
27708
|
zWhere = sqlite3_mprintf("1");
|
|
27972
27709
|
}else{
|
|
27710
|
+
char *z1 = sqlite3_mprintf(pAr->bGlob ? "" : "name IN(");
|
|
27711
|
+
char *z2 = sqlite3_mprintf("");
|
|
27712
|
+
const char *zSep1 = "";
|
|
27713
|
+
const char *zSep2 = "";
|
|
27714
|
+
|
|
27973
27715
|
int i;
|
|
27974
|
-
|
|
27975
|
-
for(i=0; i<pAr->nArg; i++){
|
|
27716
|
+
for(i=0; i<pAr->nArg && z1 && z2; i++){
|
|
27976
27717
|
const char *z = pAr->azArg[i];
|
|
27977
|
-
|
|
27978
|
-
|
|
27979
|
-
|
|
27980
|
-
|
|
27981
|
-
|
|
27982
|
-
|
|
27983
|
-
|
|
27718
|
+
int n = strlen30(z);
|
|
27719
|
+
|
|
27720
|
+
if( pAr->bGlob ){
|
|
27721
|
+
z1 = sqlite3_mprintf("%z%sname GLOB '%q'", z1, zSep2, z);
|
|
27722
|
+
z2 = sqlite3_mprintf(
|
|
27723
|
+
"%z%ssubstr(name,1,%d) GLOB '%q/'", z2, zSep2, n+1,z
|
|
27724
|
+
);
|
|
27725
|
+
}else{
|
|
27726
|
+
z1 = sqlite3_mprintf("%z%s'%q'", z1, zSep1, z);
|
|
27727
|
+
z2 = sqlite3_mprintf("%z%ssubstr(name,1,%d) = '%q/'",z2,zSep2,n+1,z);
|
|
27984
27728
|
}
|
|
27985
|
-
|
|
27729
|
+
zSep1 = ", ";
|
|
27730
|
+
zSep2 = " OR ";
|
|
27731
|
+
}
|
|
27732
|
+
if( z1==0 || z2==0 ){
|
|
27733
|
+
*pRc = SQLITE_NOMEM;
|
|
27734
|
+
}else{
|
|
27735
|
+
zWhere = sqlite3_mprintf("(%s%s OR (name GLOB '*/*' AND (%s))) ",
|
|
27736
|
+
z1, pAr->bGlob==0 ? ")" : "", z2
|
|
27737
|
+
);
|
|
27986
27738
|
}
|
|
27739
|
+
sqlite3_free(z1);
|
|
27740
|
+
sqlite3_free(z2);
|
|
27987
27741
|
}
|
|
27988
27742
|
}
|
|
27989
27743
|
*pzWhere = zWhere;
|
|
@@ -28303,7 +28057,7 @@ static int arDotCommand(
|
|
|
28303
28057
|
cmd.out = pState->out;
|
|
28304
28058
|
cmd.db = pState->db;
|
|
28305
28059
|
if( cmd.zFile ){
|
|
28306
|
-
eDbType = deduceDatabaseType(cmd.zFile, 1);
|
|
28060
|
+
eDbType = deduceDatabaseType(cmd.zFile, 1, 0);
|
|
28307
28061
|
}else{
|
|
28308
28062
|
eDbType = pState->openMode;
|
|
28309
28063
|
}
|
|
@@ -28807,7 +28561,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
28807
28561
|
int rc = 0;
|
|
28808
28562
|
char *azArg[52];
|
|
28809
28563
|
|
|
28810
|
-
#
|
|
28564
|
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
|
|
28811
28565
|
if( p->expert.pExpert ){
|
|
28812
28566
|
expertFinish(p, 1, 0);
|
|
28813
28567
|
}
|
|
@@ -29108,7 +28862,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29108
28862
|
const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
|
|
29109
28863
|
const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
|
|
29110
28864
|
if( zSchema==0 || zFile==0 ) continue;
|
|
29111
|
-
azName =
|
|
28865
|
+
azName = sqlite3_realloc64(azName, (nName+1)*2*sizeof(char*));
|
|
29112
28866
|
shell_check_oom(azName);
|
|
29113
28867
|
azName[nName*2] = strdup(zSchema);
|
|
29114
28868
|
azName[nName*2+1] = strdup(zFile);
|
|
@@ -29311,6 +29065,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29311
29065
|
}else
|
|
29312
29066
|
|
|
29313
29067
|
if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
|
|
29068
|
+
open_db(p, 0);
|
|
29314
29069
|
rc = shell_dbtotxt_command(p, nArg, azArg);
|
|
29315
29070
|
}else
|
|
29316
29071
|
|
|
@@ -29376,7 +29131,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29376
29131
|
}
|
|
29377
29132
|
}else
|
|
29378
29133
|
|
|
29379
|
-
#
|
|
29134
|
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
|
|
29380
29135
|
if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){
|
|
29381
29136
|
if( p->bSafeMode ){
|
|
29382
29137
|
sqlite3_fprintf(stderr,
|
|
@@ -29559,7 +29314,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29559
29314
|
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
|
|
29560
29315
|
" FROM sqlite_schema UNION ALL"
|
|
29561
29316
|
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
|
|
29562
|
-
"WHERE type!='meta' AND sql NOTNULL
|
|
29317
|
+
"WHERE type!='meta' AND sql NOTNULL"
|
|
29318
|
+
" AND name NOT LIKE 'sqlite__%' ESCAPE '_' "
|
|
29563
29319
|
"ORDER BY x",
|
|
29564
29320
|
callback, &data, 0
|
|
29565
29321
|
);
|
|
@@ -29623,7 +29379,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29623
29379
|
ImportCtx sCtx; /* Reader context */
|
|
29624
29380
|
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
|
|
29625
29381
|
int eVerbose = 0; /* Larger for more console output */
|
|
29626
|
-
|
|
29382
|
+
i64 nSkip = 0; /* Initial lines to skip */
|
|
29627
29383
|
int useOutputMode = 1; /* Use output mode to determine separators */
|
|
29628
29384
|
char *zCreate = 0; /* CREATE TABLE statement text */
|
|
29629
29385
|
|
|
@@ -29750,7 +29506,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29750
29506
|
shell_out_of_memory();
|
|
29751
29507
|
}
|
|
29752
29508
|
/* Below, resources must be freed before exit. */
|
|
29753
|
-
while(
|
|
29509
|
+
while( nSkip>0 ){
|
|
29510
|
+
nSkip--;
|
|
29754
29511
|
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
|
|
29755
29512
|
}
|
|
29756
29513
|
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
|
|
@@ -29942,12 +29699,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29942
29699
|
int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
|
|
29943
29700
|
int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
|
|
29944
29701
|
int i;
|
|
29945
|
-
if( !ShellHasFlag(p,SHFLG_TestingMode) ){
|
|
29946
|
-
sqlite3_fprintf(stderr,".%s unavailable without --unsafe-testing\n",
|
|
29947
|
-
"imposter");
|
|
29948
|
-
rc = 1;
|
|
29949
|
-
goto meta_command_exit;
|
|
29950
|
-
}
|
|
29951
29702
|
if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
|
|
29952
29703
|
eputz("Usage: .imposter INDEX IMPOSTER\n"
|
|
29953
29704
|
" .imposter off\n");
|
|
@@ -30019,7 +29770,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30019
29770
|
"CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
|
|
30020
29771
|
azArg[2], zCollist, lenPK, zCollist);
|
|
30021
29772
|
sqlite3_free(zCollist);
|
|
30022
|
-
rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main",
|
|
29773
|
+
rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 2, tnum);
|
|
30023
29774
|
if( rc==SQLITE_OK ){
|
|
30024
29775
|
rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
|
|
30025
29776
|
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
|
|
@@ -30028,9 +29779,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30028
29779
|
"Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
|
|
30029
29780
|
}else{
|
|
30030
29781
|
sqlite3_fprintf(stdout, "%s;\n", zSql);
|
|
30031
|
-
sqlite3_fprintf(stdout,
|
|
30032
|
-
"WARNING: writing to an imposter table will corrupt"
|
|
30033
|
-
" the \"%s\" %s!\n", azArg[1], isWO ? "table" : "index");
|
|
30034
29782
|
}
|
|
30035
29783
|
}else{
|
|
30036
29784
|
sqlite3_fprintf(stderr,"SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
|
|
@@ -30357,7 +30105,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30357
30105
|
eputz("Usage: .nonce NONCE\n");
|
|
30358
30106
|
rc = 1;
|
|
30359
30107
|
}else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
|
|
30360
|
-
sqlite3_fprintf(stderr,"line %
|
|
30108
|
+
sqlite3_fprintf(stderr,"line %lld: incorrect nonce: \"%s\"\n",
|
|
30361
30109
|
p->lineno, azArg[1]);
|
|
30362
30110
|
exit(1);
|
|
30363
30111
|
}else{
|
|
@@ -30384,6 +30132,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30384
30132
|
int iName = 1; /* Index in azArg[] of the filename */
|
|
30385
30133
|
int newFlag = 0; /* True to delete file before opening */
|
|
30386
30134
|
int openMode = SHELL_OPEN_UNSPEC;
|
|
30135
|
+
int openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
|
|
30387
30136
|
|
|
30388
30137
|
/* Check for command-line arguments */
|
|
30389
30138
|
for(iName=1; iName<nArg; iName++){
|
|
@@ -30398,14 +30147,21 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30398
30147
|
}else if( optionMatch(z, "append") ){
|
|
30399
30148
|
openMode = SHELL_OPEN_APPENDVFS;
|
|
30400
30149
|
}else if( optionMatch(z, "readonly") ){
|
|
30401
|
-
|
|
30150
|
+
openFlags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
|
30151
|
+
openFlags |= SQLITE_OPEN_READONLY;
|
|
30152
|
+
}else if( optionMatch(z, "exclusive") ){
|
|
30153
|
+
openFlags |= SQLITE_OPEN_EXCLUSIVE;
|
|
30154
|
+
}else if( optionMatch(z, "ifexists") ){
|
|
30155
|
+
openFlags &= ~(SQLITE_OPEN_CREATE);
|
|
30402
30156
|
}else if( optionMatch(z, "nofollow") ){
|
|
30403
|
-
|
|
30157
|
+
openFlags |= SQLITE_OPEN_NOFOLLOW;
|
|
30404
30158
|
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
30405
30159
|
}else if( optionMatch(z, "deserialize") ){
|
|
30406
30160
|
openMode = SHELL_OPEN_DESERIALIZE;
|
|
30407
30161
|
}else if( optionMatch(z, "hexdb") ){
|
|
30408
30162
|
openMode = SHELL_OPEN_HEXDB;
|
|
30163
|
+
}else if( optionMatch(z, "normal") ){
|
|
30164
|
+
openMode = SHELL_OPEN_NORMAL;
|
|
30409
30165
|
}else if( optionMatch(z, "maxsize") && iName+1<nArg ){
|
|
30410
30166
|
p->szMax = integerValue(azArg[++iName]);
|
|
30411
30167
|
#endif /* SQLITE_OMIT_DESERIALIZE */
|
|
@@ -30432,12 +30188,21 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30432
30188
|
sqlite3_free(p->pAuxDb->zFreeOnClose);
|
|
30433
30189
|
p->pAuxDb->zFreeOnClose = 0;
|
|
30434
30190
|
p->openMode = openMode;
|
|
30435
|
-
p->openFlags =
|
|
30191
|
+
p->openFlags = openFlags;
|
|
30436
30192
|
p->szMax = 0;
|
|
30437
30193
|
|
|
30438
30194
|
/* If a filename is specified, try to open it first */
|
|
30439
30195
|
if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
|
|
30440
|
-
if( newFlag && zFN && !p->bSafeMode )
|
|
30196
|
+
if( newFlag && zFN && !p->bSafeMode ){
|
|
30197
|
+
if( cli_strncmp(zFN,"file:",5)==0 ){
|
|
30198
|
+
char *zDel = shellFilenameFromUri(zFN);
|
|
30199
|
+
shell_check_oom(zDel);
|
|
30200
|
+
shellDeleteFile(zDel);
|
|
30201
|
+
sqlite3_free(zDel);
|
|
30202
|
+
}else{
|
|
30203
|
+
shellDeleteFile(zFN);
|
|
30204
|
+
}
|
|
30205
|
+
}
|
|
30441
30206
|
#ifndef SQLITE_SHELL_FIDDLE
|
|
30442
30207
|
if( p->bSafeMode
|
|
30443
30208
|
&& p->openMode!=SHELL_OPEN_HEXDB
|
|
@@ -30515,6 +30280,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30515
30280
|
"ERROR: unknown option: \"%s\". Usage:\n", azArg[i]);
|
|
30516
30281
|
showHelp(p->out, azArg[0]);
|
|
30517
30282
|
rc = 1;
|
|
30283
|
+
sqlite3_free(zFile);
|
|
30518
30284
|
goto meta_command_exit;
|
|
30519
30285
|
}
|
|
30520
30286
|
}else if( zFile==0 && eMode==0 ){
|
|
@@ -30798,7 +30564,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30798
30564
|
#ifndef SQLITE_SHELL_FIDDLE
|
|
30799
30565
|
if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){
|
|
30800
30566
|
FILE *inSaved = p->in;
|
|
30801
|
-
|
|
30567
|
+
i64 savedLineno = p->lineno;
|
|
30802
30568
|
failIfSafeMode(p, "cannot run .read in safe mode");
|
|
30803
30569
|
if( nArg!=2 ){
|
|
30804
30570
|
eputz("Usage: .read FILE\n");
|
|
@@ -30815,7 +30581,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30815
30581
|
sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
|
|
30816
30582
|
rc = 1;
|
|
30817
30583
|
}else{
|
|
30818
|
-
rc = process_input(p);
|
|
30584
|
+
rc = process_input(p, "<pipe>");
|
|
30819
30585
|
pclose(p->in);
|
|
30820
30586
|
}
|
|
30821
30587
|
#endif
|
|
@@ -30823,7 +30589,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30823
30589
|
sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
|
|
30824
30590
|
rc = 1;
|
|
30825
30591
|
}else{
|
|
30826
|
-
rc = process_input(p);
|
|
30592
|
+
rc = process_input(p, azArg[1]);
|
|
30827
30593
|
fclose(p->in);
|
|
30828
30594
|
}
|
|
30829
30595
|
p->in = inSaved;
|
|
@@ -31035,14 +30801,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31035
30801
|
sqlite3_free(zQarg);
|
|
31036
30802
|
}
|
|
31037
30803
|
if( bNoSystemTabs ){
|
|
31038
|
-
appendText(&sSelect, "name NOT LIKE '
|
|
30804
|
+
appendText(&sSelect, "name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ", 0);
|
|
31039
30805
|
}
|
|
31040
30806
|
appendText(&sSelect, "sql IS NOT NULL"
|
|
31041
30807
|
" ORDER BY snum, rowid", 0);
|
|
31042
30808
|
if( bDebug ){
|
|
31043
|
-
sqlite3_fprintf(p->out, "SQL: %s;\n", sSelect.
|
|
30809
|
+
sqlite3_fprintf(p->out, "SQL: %s;\n", sSelect.zTxt);
|
|
31044
30810
|
}else{
|
|
31045
|
-
rc = sqlite3_exec(p->db, sSelect.
|
|
30811
|
+
rc = sqlite3_exec(p->db, sSelect.zTxt, callback, &data, &zErrMsg);
|
|
31046
30812
|
}
|
|
31047
30813
|
freeText(&sSelect);
|
|
31048
30814
|
}
|
|
@@ -31174,7 +30940,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31174
30940
|
** Set a list of GLOB patterns of table names to be excluded.
|
|
31175
30941
|
*/
|
|
31176
30942
|
if( cli_strcmp(azCmd[0], "filter")==0 ){
|
|
31177
|
-
int ii
|
|
30943
|
+
int ii;
|
|
30944
|
+
i64 nByte;
|
|
31178
30945
|
if( nCmd<2 ) goto session_syntax_error;
|
|
31179
30946
|
if( pAuxDb->nSession ){
|
|
31180
30947
|
for(ii=0; ii<pSession->nFilter; ii++){
|
|
@@ -31182,7 +30949,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31182
30949
|
}
|
|
31183
30950
|
sqlite3_free(pSession->azFilter);
|
|
31184
30951
|
nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
|
|
31185
|
-
pSession->azFilter =
|
|
30952
|
+
pSession->azFilter = sqlite3_malloc64( nByte );
|
|
31186
30953
|
shell_check_oom( pSession->azFilter );
|
|
31187
30954
|
for(ii=1; ii<nCmd; ii++){
|
|
31188
30955
|
char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
|
|
@@ -31366,22 +31133,22 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31366
31133
|
if( cli_strcmp(zOp,"run")==0 ){
|
|
31367
31134
|
char *zErrMsg = 0;
|
|
31368
31135
|
str.n = 0;
|
|
31369
|
-
str.
|
|
31136
|
+
str.zTxt[0] = 0;
|
|
31370
31137
|
rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
|
|
31371
31138
|
nTest++;
|
|
31372
31139
|
if( bVerbose ){
|
|
31373
|
-
sqlite3_fprintf(p->out, "Result: %s\n", str.
|
|
31140
|
+
sqlite3_fprintf(p->out, "Result: %s\n", str.zTxt);
|
|
31374
31141
|
}
|
|
31375
31142
|
if( rc || zErrMsg ){
|
|
31376
31143
|
nErr++;
|
|
31377
31144
|
rc = 1;
|
|
31378
31145
|
sqlite3_fprintf(p->out, "%d: error-code-%d: %s\n", tno, rc,zErrMsg);
|
|
31379
31146
|
sqlite3_free(zErrMsg);
|
|
31380
|
-
}else if( cli_strcmp(zAns,str.
|
|
31147
|
+
}else if( cli_strcmp(zAns,str.zTxt)!=0 ){
|
|
31381
31148
|
nErr++;
|
|
31382
31149
|
rc = 1;
|
|
31383
31150
|
sqlite3_fprintf(p->out, "%d: Expected: [%s]\n", tno, zAns);
|
|
31384
|
-
sqlite3_fprintf(p->out, "%d: Got: [%s]\n", tno, str.
|
|
31151
|
+
sqlite3_fprintf(p->out, "%d: Got: [%s]\n", tno, str.zTxt);
|
|
31385
31152
|
}
|
|
31386
31153
|
}
|
|
31387
31154
|
else{
|
|
@@ -31466,7 +31233,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31466
31233
|
}else{
|
|
31467
31234
|
zSql = "SELECT lower(name) as tname FROM sqlite_schema"
|
|
31468
31235
|
" WHERE type='table' AND coalesce(rootpage,0)>1"
|
|
31469
|
-
" AND name NOT LIKE '
|
|
31236
|
+
" AND name NOT LIKE 'sqlite__%' ESCAPE '_'"
|
|
31470
31237
|
" ORDER BY 1 collate nocase";
|
|
31471
31238
|
}
|
|
31472
31239
|
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
|
@@ -31497,7 +31264,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31497
31264
|
appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
|
|
31498
31265
|
}
|
|
31499
31266
|
appendText(&sSql, zSep, 0);
|
|
31500
|
-
appendText(&sSql, sQuery.
|
|
31267
|
+
appendText(&sSql, sQuery.zTxt, '\'');
|
|
31501
31268
|
sQuery.n = 0;
|
|
31502
31269
|
appendText(&sSql, ",", 0);
|
|
31503
31270
|
appendText(&sSql, zTab, '\'');
|
|
@@ -31509,13 +31276,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31509
31276
|
"%s))"
|
|
31510
31277
|
" SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
|
|
31511
31278
|
" FROM [sha3sum$query]",
|
|
31512
|
-
sSql.
|
|
31279
|
+
sSql.zTxt, iSize);
|
|
31513
31280
|
}else{
|
|
31514
31281
|
zSql = sqlite3_mprintf(
|
|
31515
31282
|
"%s))"
|
|
31516
31283
|
" SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
|
|
31517
31284
|
" FROM [sha3sum$query]",
|
|
31518
|
-
sSql.
|
|
31285
|
+
sSql.zTxt, iSize);
|
|
31519
31286
|
}
|
|
31520
31287
|
shell_check_oom(zSql);
|
|
31521
31288
|
freeText(&sQuery);
|
|
@@ -31531,7 +31298,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31531
31298
|
char *zRevText = /* Query for reversible to-blob-to-text check */
|
|
31532
31299
|
"SELECT lower(name) as tname FROM sqlite_schema\n"
|
|
31533
31300
|
"WHERE type='table' AND coalesce(rootpage,0)>1\n"
|
|
31534
|
-
"AND name NOT LIKE '
|
|
31301
|
+
"AND name NOT LIKE 'sqlite__%%' ESCAPE '_'%s\n"
|
|
31535
31302
|
"ORDER BY 1 collate nocase";
|
|
31536
31303
|
zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : "");
|
|
31537
31304
|
zRevText = sqlite3_mprintf(
|
|
@@ -31715,7 +31482,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31715
31482
|
for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
|
|
31716
31483
|
const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
|
|
31717
31484
|
if( zDbName==0 ) continue;
|
|
31718
|
-
if( s.
|
|
31485
|
+
if( s.zTxt && s.zTxt[0] ) appendText(&s, " UNION ALL ", 0);
|
|
31719
31486
|
if( sqlite3_stricmp(zDbName, "main")==0 ){
|
|
31720
31487
|
appendText(&s, "SELECT name FROM ", 0);
|
|
31721
31488
|
}else{
|
|
@@ -31727,7 +31494,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31727
31494
|
appendText(&s, ".sqlite_schema ", 0);
|
|
31728
31495
|
if( c=='t' ){
|
|
31729
31496
|
appendText(&s," WHERE type IN ('table','view')"
|
|
31730
|
-
" AND name NOT LIKE '
|
|
31497
|
+
" AND name NOT LIKE 'sqlite__%' ESCAPE '_'"
|
|
31731
31498
|
" AND name LIKE ?1", 0);
|
|
31732
31499
|
}else{
|
|
31733
31500
|
appendText(&s," WHERE type='index'"
|
|
@@ -31737,7 +31504,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31737
31504
|
rc = sqlite3_finalize(pStmt);
|
|
31738
31505
|
if( rc==SQLITE_OK ){
|
|
31739
31506
|
appendText(&s, " ORDER BY 1", 0);
|
|
31740
|
-
rc = sqlite3_prepare_v2(p->db, s.
|
|
31507
|
+
rc = sqlite3_prepare_v2(p->db, s.zTxt, -1, &pStmt, 0);
|
|
31741
31508
|
}
|
|
31742
31509
|
freeText(&s);
|
|
31743
31510
|
if( rc ) return shellDatabaseError(p->db);
|
|
@@ -31754,10 +31521,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31754
31521
|
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
|
31755
31522
|
if( nRow>=nAlloc ){
|
|
31756
31523
|
char **azNew;
|
|
31757
|
-
|
|
31524
|
+
sqlite3_int64 n2 = 2*(sqlite3_int64)nAlloc + 10;
|
|
31758
31525
|
azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
|
|
31759
31526
|
shell_check_oom(azNew);
|
|
31760
|
-
nAlloc = n2;
|
|
31527
|
+
nAlloc = (int)n2;
|
|
31761
31528
|
azResult = azNew;
|
|
31762
31529
|
}
|
|
31763
31530
|
azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
|
|
@@ -31821,7 +31588,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31821
31588
|
{"always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
|
|
31822
31589
|
{"assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
|
|
31823
31590
|
/*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
|
|
31824
|
-
|
|
31591
|
+
{"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "SIZE INT-ARRAY"},
|
|
31825
31592
|
{"byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
|
|
31826
31593
|
{"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
|
|
31827
31594
|
{"fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"args..." },
|
|
@@ -31920,7 +31687,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31920
31687
|
{ 0x00000080, 1, "Transitive" },
|
|
31921
31688
|
{ 0x00000100, 1, "OmitNoopJoin" },
|
|
31922
31689
|
{ 0x00000200, 1, "CountOfView" },
|
|
31923
|
-
{ 0x00000400, 1, "
|
|
31690
|
+
{ 0x00000400, 1, "CursorHints" },
|
|
31924
31691
|
{ 0x00000800, 1, "Stat4" },
|
|
31925
31692
|
{ 0x00001000, 1, "PushDown" },
|
|
31926
31693
|
{ 0x00002000, 1, "SimplifyJoin" },
|
|
@@ -31940,6 +31707,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31940
31707
|
{ 0x08000000, 1, "OnePass" },
|
|
31941
31708
|
{ 0x10000000, 1, "OrderBySubq" },
|
|
31942
31709
|
{ 0x20000000, 1, "StarQuery" },
|
|
31710
|
+
{ 0x40000000, 1, "ExistsToJoin" },
|
|
31943
31711
|
{ 0xffffffff, 0, "All" },
|
|
31944
31712
|
};
|
|
31945
31713
|
unsigned int curOpt;
|
|
@@ -32159,6 +31927,49 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
32159
31927
|
}
|
|
32160
31928
|
sqlite3_test_control(testctrl, &rc2);
|
|
32161
31929
|
break;
|
|
31930
|
+
case SQLITE_TESTCTRL_BITVEC_TEST: {
|
|
31931
|
+
/* Examples:
|
|
31932
|
+
** .testctrl bitvec_test 100 6,1 -- Show BITVEC constants
|
|
31933
|
+
** .testctrl bitvec_test 1000 1,12,7,3 -- Simple test
|
|
31934
|
+
** ---- --------
|
|
31935
|
+
** size of Bitvec -----^ ^--- aOp array. 0 added at end.
|
|
31936
|
+
**
|
|
31937
|
+
** See comments on sqlite3BitvecBuiltinTest() for more information
|
|
31938
|
+
** about the aOp[] array.
|
|
31939
|
+
*/
|
|
31940
|
+
int iSize;
|
|
31941
|
+
const char *zTestArg;
|
|
31942
|
+
int nOp;
|
|
31943
|
+
int ii, jj, x;
|
|
31944
|
+
int *aOp;
|
|
31945
|
+
if( nArg!=4 ){
|
|
31946
|
+
sqlite3_fprintf(stderr,
|
|
31947
|
+
"ERROR - should be: \".testctrl bitvec_test SIZE INT-ARRAY\"\n"
|
|
31948
|
+
);
|
|
31949
|
+
rc = 1;
|
|
31950
|
+
goto meta_command_exit;
|
|
31951
|
+
}
|
|
31952
|
+
isOk = 3;
|
|
31953
|
+
iSize = (int)integerValue(azArg[2]);
|
|
31954
|
+
zTestArg = azArg[3];
|
|
31955
|
+
nOp = (int)strlen(zTestArg)+1;
|
|
31956
|
+
aOp = malloc( sizeof(int)*(nOp+1) );
|
|
31957
|
+
shell_check_oom(aOp);
|
|
31958
|
+
memset(aOp, 0, sizeof(int)*(nOp+1) );
|
|
31959
|
+
for(ii = jj = x = 0; zTestArg[ii]!=0; ii++){
|
|
31960
|
+
if( IsDigit(zTestArg[ii]) ){
|
|
31961
|
+
x = x*10 + zTestArg[ii] - '0';
|
|
31962
|
+
}else{
|
|
31963
|
+
aOp[jj++] = x;
|
|
31964
|
+
x = 0;
|
|
31965
|
+
}
|
|
31966
|
+
}
|
|
31967
|
+
aOp[jj] = x;
|
|
31968
|
+
x = sqlite3_test_control(testctrl, iSize, aOp);
|
|
31969
|
+
sqlite3_fprintf(p->out, "result: %d\n", x);
|
|
31970
|
+
free(aOp);
|
|
31971
|
+
break;
|
|
31972
|
+
}
|
|
32162
31973
|
case SQLITE_TESTCTRL_FAULT_INSTALL: {
|
|
32163
31974
|
int kk;
|
|
32164
31975
|
int bShowHelp = nArg<=2;
|
|
@@ -32423,7 +32234,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
32423
32234
|
if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
|
|
32424
32235
|
if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
|
|
32425
32236
|
for(j=1; j<nArg; j++){
|
|
32426
|
-
|
|
32237
|
+
i64 w = integerValue(azArg[j]);
|
|
32238
|
+
if( w < -30000 ) w = -30000;
|
|
32239
|
+
if( w > +30000 ) w = +30000;
|
|
32240
|
+
p->colWidth[j-1] = (int)w;
|
|
32427
32241
|
}
|
|
32428
32242
|
}else
|
|
32429
32243
|
|
|
@@ -32766,7 +32580,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
|
|
|
32766
32580
|
**
|
|
32767
32581
|
** Return the number of errors.
|
|
32768
32582
|
*/
|
|
32769
|
-
static int process_input(ShellState *p){
|
|
32583
|
+
static int process_input(ShellState *p, const char *zSrc){
|
|
32770
32584
|
char *zLine = 0; /* A single input line */
|
|
32771
32585
|
char *zSql = 0; /* Accumulated SQL text */
|
|
32772
32586
|
i64 nLine; /* Length of current line */
|
|
@@ -32779,8 +32593,8 @@ static int process_input(ShellState *p){
|
|
|
32779
32593
|
|
|
32780
32594
|
if( p->inputNesting==MAX_INPUT_NESTING ){
|
|
32781
32595
|
/* This will be more informative in a later version. */
|
|
32782
|
-
sqlite3_fprintf(stderr,"Input nesting limit (%d) reached at line %
|
|
32783
|
-
" Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
|
|
32596
|
+
sqlite3_fprintf(stderr,"%s: Input nesting limit (%d) reached at line %lld."
|
|
32597
|
+
" Check recursion.\n", zSrc, MAX_INPUT_NESTING, p->lineno);
|
|
32784
32598
|
return 1;
|
|
32785
32599
|
}
|
|
32786
32600
|
++p->inputNesting;
|
|
@@ -32845,7 +32659,15 @@ static int process_input(ShellState *p){
|
|
|
32845
32659
|
memcpy(zSql+nSql, zLine, nLine+1);
|
|
32846
32660
|
nSql += nLine;
|
|
32847
32661
|
}
|
|
32848
|
-
if( nSql
|
|
32662
|
+
if( nSql>0x7fff0000 ){
|
|
32663
|
+
char zSize[100];
|
|
32664
|
+
sqlite3_snprintf(sizeof(zSize),zSize,"%,lld",nSql);
|
|
32665
|
+
sqlite3_fprintf(stderr, "%s:%lld: Input SQL is too big: %s bytes\n",
|
|
32666
|
+
zSrc, startline, zSize);
|
|
32667
|
+
nSql = 0;
|
|
32668
|
+
errCnt++;
|
|
32669
|
+
break;
|
|
32670
|
+
}else if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
|
|
32849
32671
|
echo_group_input(p, zSql);
|
|
32850
32672
|
errCnt += runOneSqlLine(p, zSql, p->in, startline);
|
|
32851
32673
|
CONTINUE_PROMPT_RESET;
|
|
@@ -32946,59 +32768,79 @@ static char *find_home_dir(int clearFlag){
|
|
|
32946
32768
|
}
|
|
32947
32769
|
|
|
32948
32770
|
/*
|
|
32949
|
-
** On non-Windows platforms, look for
|
|
32950
|
-
**
|
|
32951
|
-
**
|
|
32952
|
-
**
|
|
32953
|
-
**
|
|
32771
|
+
** On non-Windows platforms, look for:
|
|
32772
|
+
**
|
|
32773
|
+
** - ${zEnvVar}/${zBaseName}
|
|
32774
|
+
** - ${HOME}/${zSubdir}/${zBaseName}
|
|
32775
|
+
**
|
|
32776
|
+
** $zEnvVar is intended to be the name of an XDG_... environment
|
|
32777
|
+
** variable, e.g. XDG_CONFIG_HOME or XDG_STATE_HOME. If zEnvVar is
|
|
32778
|
+
** NULL or getenv(zEnvVar) is NULL then fall back to the second
|
|
32779
|
+
** option. If the selected option is not found in the filesystem,
|
|
32780
|
+
** return 0.
|
|
32781
|
+
**
|
|
32782
|
+
** zSubdir may be NULL or empty, in which case ${HOME}/${zBaseName}
|
|
32783
|
+
** becomes the fallback.
|
|
32784
|
+
**
|
|
32785
|
+
** Both zSubdir and zBaseName may contain subdirectory parts. zSubdir
|
|
32786
|
+
** will conventionally be ".config" or ".local/state", which, not
|
|
32787
|
+
** coincidentally, is the typical subdir of the corresponding XDG_...
|
|
32788
|
+
** var with the XDG var's $HOME prefix.
|
|
32954
32789
|
**
|
|
32955
|
-
** The string
|
|
32956
|
-
**
|
|
32790
|
+
** The returned string is obtained from sqlite3_malloc() and should be
|
|
32791
|
+
** sqlite3_free()'d by the caller.
|
|
32957
32792
|
*/
|
|
32958
|
-
static char *
|
|
32793
|
+
static char *find_xdg_file(const char *zEnvVar, const char *zSubdir,
|
|
32794
|
+
const char *zBaseName){
|
|
32959
32795
|
#if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) \
|
|
32960
32796
|
|| defined(__RTP__) || defined(_WRS_KERNEL)
|
|
32961
32797
|
return 0;
|
|
32962
32798
|
#else
|
|
32963
|
-
char *
|
|
32964
|
-
const char *
|
|
32799
|
+
char *zConfigFile = 0;
|
|
32800
|
+
const char *zXdgDir;
|
|
32965
32801
|
|
|
32966
|
-
|
|
32967
|
-
if(
|
|
32968
|
-
|
|
32969
|
-
if( zHome==0 ) return 0;
|
|
32970
|
-
zConfig = sqlite3_mprintf("%s/.config/sqlite3/sqliterc", zHome);
|
|
32802
|
+
zXdgDir = zEnvVar ? getenv(zEnvVar) : 0;
|
|
32803
|
+
if( zXdgDir ){
|
|
32804
|
+
zConfigFile = sqlite3_mprintf("%s/%s", zXdgDir, zBaseName);
|
|
32971
32805
|
}else{
|
|
32972
|
-
|
|
32806
|
+
const char * zHome = find_home_dir(0);
|
|
32807
|
+
if( zHome==0 ) return 0;
|
|
32808
|
+
zConfigFile = (zSubdir && *zSubdir)
|
|
32809
|
+
? sqlite3_mprintf("%s/%s/%s", zHome, zSubdir, zBaseName)
|
|
32810
|
+
: sqlite3_mprintf("%s/%s", zHome, zBaseName);
|
|
32973
32811
|
}
|
|
32974
|
-
shell_check_oom(
|
|
32975
|
-
if( access(
|
|
32976
|
-
sqlite3_free(
|
|
32977
|
-
|
|
32812
|
+
shell_check_oom(zConfigFile);
|
|
32813
|
+
if( access(zConfigFile,0)!=0 ){
|
|
32814
|
+
sqlite3_free(zConfigFile);
|
|
32815
|
+
zConfigFile = 0;
|
|
32978
32816
|
}
|
|
32979
|
-
return
|
|
32817
|
+
return zConfigFile;
|
|
32980
32818
|
#endif
|
|
32981
32819
|
}
|
|
32982
32820
|
|
|
32983
32821
|
/*
|
|
32984
|
-
** Read input from the file
|
|
32985
|
-
**
|
|
32986
|
-
**
|
|
32822
|
+
** Read input from the file sqliterc_override. If that parameter is
|
|
32823
|
+
** NULL, take it from find_xdg_file(), if found, or fall back to
|
|
32824
|
+
** ~/.sqliterc.
|
|
32987
32825
|
**
|
|
32988
|
-
**
|
|
32826
|
+
** Failure to read the config is only considered a failure if
|
|
32827
|
+
** sqliterc_override is not NULL, in which case this function may emit
|
|
32828
|
+
** a warning or, if ::bail_on_error is true, fail fatally if the file
|
|
32829
|
+
** named by sqliterc_override is not found.
|
|
32989
32830
|
*/
|
|
32990
32831
|
static void process_sqliterc(
|
|
32991
32832
|
ShellState *p, /* Configuration data */
|
|
32992
32833
|
const char *sqliterc_override /* Name of config file. NULL to use default */
|
|
32993
32834
|
){
|
|
32994
32835
|
char *home_dir = NULL;
|
|
32995
|
-
|
|
32996
|
-
char *zBuf = 0;
|
|
32836
|
+
char *sqliterc = (char*)sqliterc_override;
|
|
32997
32837
|
FILE *inSaved = p->in;
|
|
32998
|
-
|
|
32838
|
+
i64 savedLineno = p->lineno;
|
|
32999
32839
|
|
|
33000
32840
|
if( sqliterc == NULL ){
|
|
33001
|
-
sqliterc =
|
|
32841
|
+
sqliterc = find_xdg_file("XDG_CONFIG_HOME",
|
|
32842
|
+
".config",
|
|
32843
|
+
"sqlite3/sqliterc");
|
|
33002
32844
|
}
|
|
33003
32845
|
if( sqliterc == NULL ){
|
|
33004
32846
|
home_dir = find_home_dir(0);
|
|
@@ -33007,16 +32849,15 @@ static void process_sqliterc(
|
|
|
33007
32849
|
" cannot read ~/.sqliterc\n");
|
|
33008
32850
|
return;
|
|
33009
32851
|
}
|
|
33010
|
-
|
|
33011
|
-
shell_check_oom(
|
|
33012
|
-
sqliterc = zBuf;
|
|
32852
|
+
sqliterc = sqlite3_mprintf("%s/.sqliterc",home_dir);
|
|
32853
|
+
shell_check_oom(sqliterc);
|
|
33013
32854
|
}
|
|
33014
|
-
p->in = sqlite3_fopen(sqliterc,"rb");
|
|
32855
|
+
p->in = sqliterc ? sqlite3_fopen(sqliterc,"rb") : 0;
|
|
33015
32856
|
if( p->in ){
|
|
33016
32857
|
if( stdin_is_interactive ){
|
|
33017
32858
|
sqlite3_fprintf(stderr,"-- Loading resources from %s\n", sqliterc);
|
|
33018
32859
|
}
|
|
33019
|
-
if( process_input(p) && bail_on_error ) exit(1);
|
|
32860
|
+
if( process_input(p, sqliterc) && bail_on_error ) exit(1);
|
|
33020
32861
|
fclose(p->in);
|
|
33021
32862
|
}else if( sqliterc_override!=0 ){
|
|
33022
32863
|
sqlite3_fprintf(stderr,"cannot open: \"%s\"\n", sqliterc);
|
|
@@ -33024,7 +32865,9 @@ static void process_sqliterc(
|
|
|
33024
32865
|
}
|
|
33025
32866
|
p->in = inSaved;
|
|
33026
32867
|
p->lineno = savedLineno;
|
|
33027
|
-
|
|
32868
|
+
if( sqliterc != sqliterc_override ){
|
|
32869
|
+
sqlite3_free(sqliterc);
|
|
32870
|
+
}
|
|
33028
32871
|
}
|
|
33029
32872
|
|
|
33030
32873
|
/*
|
|
@@ -33055,6 +32898,7 @@ static const char zOptions[] =
|
|
|
33055
32898
|
#endif
|
|
33056
32899
|
" -help show this message\n"
|
|
33057
32900
|
" -html set output mode to HTML\n"
|
|
32901
|
+
" -ifexists only open if database already exists\n"
|
|
33058
32902
|
" -interactive force interactive I/O\n"
|
|
33059
32903
|
" -json set output mode to 'json'\n"
|
|
33060
32904
|
" -line set output mode to 'line'\n"
|
|
@@ -33399,12 +33243,20 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33399
33243
|
}else if( cli_strcmp(z,"-pagecache")==0 ){
|
|
33400
33244
|
sqlite3_int64 n, sz;
|
|
33401
33245
|
sz = integerValue(cmdline_option_value(argc,argv,++i));
|
|
33402
|
-
if( sz>
|
|
33246
|
+
if( sz>65536 ) sz = 65536;
|
|
33403
33247
|
if( sz<0 ) sz = 0;
|
|
33404
33248
|
n = integerValue(cmdline_option_value(argc,argv,++i));
|
|
33405
33249
|
if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
|
|
33406
33250
|
n = 0xffffffffffffLL/sz;
|
|
33407
33251
|
}
|
|
33252
|
+
if( sz>0 && (sz & (sz-1))==0 ){
|
|
33253
|
+
/* If SIZE is a power of two, round it up by the PCACHE_HDRSZ */
|
|
33254
|
+
int szHdr = 0;
|
|
33255
|
+
sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &szHdr);
|
|
33256
|
+
sz += szHdr;
|
|
33257
|
+
sqlite3_fprintf(stdout, "Page cache size increased to %d to accommodate"
|
|
33258
|
+
" the %d-byte headers\n", (int)sz, szHdr);
|
|
33259
|
+
}
|
|
33408
33260
|
verify_uninitialized();
|
|
33409
33261
|
sqlite3_config(SQLITE_CONFIG_PAGECACHE,
|
|
33410
33262
|
(n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
|
|
@@ -33417,7 +33269,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33417
33269
|
if( n<0 ) n = 0;
|
|
33418
33270
|
verify_uninitialized();
|
|
33419
33271
|
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
|
|
33420
|
-
if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
|
|
33272
|
+
if( (i64)sz*(i64)n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
|
|
33421
33273
|
}else if( cli_strcmp(z,"-threadsafe")==0 ){
|
|
33422
33274
|
int n;
|
|
33423
33275
|
n = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
|
@@ -33459,9 +33311,15 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33459
33311
|
data.szMax = integerValue(argv[++i]);
|
|
33460
33312
|
#endif
|
|
33461
33313
|
}else if( cli_strcmp(z,"-readonly")==0 ){
|
|
33462
|
-
data.
|
|
33314
|
+
data.openFlags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
|
33315
|
+
data.openFlags |= SQLITE_OPEN_READONLY;
|
|
33463
33316
|
}else if( cli_strcmp(z,"-nofollow")==0 ){
|
|
33464
|
-
data.openFlags
|
|
33317
|
+
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
|
|
33318
|
+
}else if( cli_strcmp(z,"-exclusive")==0 ){ /* UNDOCUMENTED */
|
|
33319
|
+
data.openFlags |= SQLITE_OPEN_EXCLUSIVE;
|
|
33320
|
+
}else if( cli_strcmp(z,"-ifexists")==0 ){
|
|
33321
|
+
data.openFlags &= ~(SQLITE_OPEN_CREATE);
|
|
33322
|
+
if( data.openFlags==0 ) data.openFlags = SQLITE_OPEN_READWRITE;
|
|
33465
33323
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
|
|
33466
33324
|
}else if( cli_strncmp(z, "-A",2)==0 ){
|
|
33467
33325
|
/* All remaining command-line arguments are passed to the ".archive"
|
|
@@ -33615,9 +33473,15 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33615
33473
|
data.szMax = integerValue(argv[++i]);
|
|
33616
33474
|
#endif
|
|
33617
33475
|
}else if( cli_strcmp(z,"-readonly")==0 ){
|
|
33618
|
-
data.
|
|
33476
|
+
data.openFlags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
|
33477
|
+
data.openFlags |= SQLITE_OPEN_READONLY;
|
|
33619
33478
|
}else if( cli_strcmp(z,"-nofollow")==0 ){
|
|
33620
33479
|
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
|
|
33480
|
+
}else if( cli_strcmp(z,"-exclusive")==0 ){ /* UNDOCUMENTED */
|
|
33481
|
+
data.openFlags |= SQLITE_OPEN_EXCLUSIVE;
|
|
33482
|
+
}else if( cli_strcmp(z,"-ifexists")==0 ){
|
|
33483
|
+
data.openFlags &= ~(SQLITE_OPEN_CREATE);
|
|
33484
|
+
if( data.openFlags==0 ) data.openFlags = SQLITE_OPEN_READWRITE;
|
|
33621
33485
|
}else if( cli_strcmp(z,"-ascii")==0 ){
|
|
33622
33486
|
data.mode = MODE_Ascii;
|
|
33623
33487
|
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,SEP_Unit);
|
|
@@ -33722,6 +33586,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33722
33586
|
rc = shell_exec(&data, z, &zErrMsg);
|
|
33723
33587
|
if( zErrMsg!=0 ){
|
|
33724
33588
|
shellEmitError(zErrMsg);
|
|
33589
|
+
sqlite3_free(zErrMsg);
|
|
33725
33590
|
if( bail_on_error ) return rc!=0 ? rc : 1;
|
|
33726
33591
|
}else if( rc!=0 ){
|
|
33727
33592
|
sqlite3_fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z);
|
|
@@ -33792,7 +33657,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33792
33657
|
if( stdin_is_interactive ){
|
|
33793
33658
|
char *zHome;
|
|
33794
33659
|
char *zHistory;
|
|
33795
|
-
int nHistory;
|
|
33796
33660
|
sqlite3_fprintf(stdout,
|
|
33797
33661
|
"SQLite version %s %.19s\n" /*extra-version-info*/
|
|
33798
33662
|
"Enter \".help\" for usage hints.\n",
|
|
@@ -33805,11 +33669,15 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33805
33669
|
}
|
|
33806
33670
|
zHistory = getenv("SQLITE_HISTORY");
|
|
33807
33671
|
if( zHistory ){
|
|
33808
|
-
zHistory =
|
|
33809
|
-
|
|
33810
|
-
|
|
33811
|
-
|
|
33812
|
-
|
|
33672
|
+
zHistory = sqlite3_mprintf("%s", zHistory);
|
|
33673
|
+
shell_check_oom(zHistory);
|
|
33674
|
+
}else{
|
|
33675
|
+
zHistory = find_xdg_file("XDG_STATE_HOME",
|
|
33676
|
+
".local/state",
|
|
33677
|
+
"sqlite_history");
|
|
33678
|
+
if( 0==zHistory && (zHome = find_home_dir(0))!=0 ){
|
|
33679
|
+
zHistory = sqlite3_mprintf("%s/.sqlite_history", zHome);
|
|
33680
|
+
shell_check_oom(zHistory);
|
|
33813
33681
|
}
|
|
33814
33682
|
}
|
|
33815
33683
|
if( zHistory ){ shell_read_history(zHistory); }
|
|
@@ -33821,21 +33689,21 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33821
33689
|
linenoiseSetCompletionCallback(linenoise_completion, NULL);
|
|
33822
33690
|
#endif
|
|
33823
33691
|
data.in = 0;
|
|
33824
|
-
rc = process_input(&data);
|
|
33692
|
+
rc = process_input(&data, "<stdin>");
|
|
33825
33693
|
if( zHistory ){
|
|
33826
33694
|
shell_stifle_history(2000);
|
|
33827
33695
|
shell_write_history(zHistory);
|
|
33828
|
-
|
|
33696
|
+
sqlite3_free(zHistory);
|
|
33829
33697
|
}
|
|
33830
33698
|
}else{
|
|
33831
33699
|
data.in = stdin;
|
|
33832
|
-
rc = process_input(&data);
|
|
33700
|
+
rc = process_input(&data, "<stdin>");
|
|
33833
33701
|
}
|
|
33834
33702
|
}
|
|
33835
33703
|
#ifndef SQLITE_SHELL_FIDDLE
|
|
33836
33704
|
/* In WASM mode we have to leave the db state in place so that
|
|
33837
33705
|
** client code can "push" SQL into it after this call returns. */
|
|
33838
|
-
#
|
|
33706
|
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
|
|
33839
33707
|
if( data.expert.pExpert ){
|
|
33840
33708
|
expertFinish(&data, 1, 0);
|
|
33841
33709
|
}
|
|
@@ -34011,7 +33879,7 @@ void fiddle_exec(const char * zSql){
|
|
|
34011
33879
|
if('.'==*zSql) puts(zSql);
|
|
34012
33880
|
shellState.wasm.zInput = zSql;
|
|
34013
33881
|
shellState.wasm.zPos = zSql;
|
|
34014
|
-
process_input(&shellState);
|
|
33882
|
+
process_input(&shellState, "<stdin>");
|
|
34015
33883
|
shellState.wasm.zInput = shellState.wasm.zPos = 0;
|
|
34016
33884
|
}
|
|
34017
33885
|
}
|