@rocicorp/zero-sqlite3 1.0.8 → 1.0.10
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/README.md +1 -0
- package/binding.gyp +1 -1
- package/deps/defines.gypi +1 -0
- package/deps/download.sh +6 -5
- package/deps/sqlite3/shell.c +1171 -512
- package/deps/sqlite3/sqlite3.c +6515 -4034
- package/deps/sqlite3/sqlite3.h +272 -73
- package/deps/sqlite3/sqlite3ext.h +4 -0
- package/deps/sqlite3.gyp +1 -1
- package/deps/test_extension.c +1 -1
- package/lib/database.js +13 -1
- package/lib/index.d.ts +30 -0
- package/lib/methods/transaction.js +3 -0
- package/package.json +9 -8
- package/src/addon.cpp +47 -0
- package/src/better_sqlite3.cpp +55 -2115
- package/src/objects/backup.cpp +120 -0
- package/src/objects/backup.hpp +36 -0
- package/src/objects/database.cpp +392 -0
- package/src/objects/database.hpp +102 -0
- package/src/objects/statement-iterator.cpp +113 -0
- package/src/objects/statement-iterator.hpp +50 -0
- package/src/objects/statement.cpp +446 -0
- package/src/objects/statement.hpp +59 -0
- package/src/util/bind-map.cpp +73 -0
- package/src/util/binder.cpp +193 -0
- package/src/util/constants.cpp +172 -0
- package/src/util/custom-aggregate.cpp +121 -0
- package/src/util/custom-function.cpp +59 -0
- package/src/util/custom-table.cpp +409 -0
- package/src/util/data-converter.cpp +17 -0
- package/src/util/data.cpp +194 -0
- package/src/util/helpers.cpp +109 -0
- package/src/util/macros.cpp +63 -0
- package/src/util/query-macros.cpp +71 -0
- package/src/util/row-builder.cpp +49 -0
- package/src/better_sqlite3.hpp +0 -1034
package/deps/sqlite3/shell.c
CHANGED
|
@@ -122,9 +122,6 @@ typedef unsigned short int u16;
|
|
|
122
122
|
typedef sqlite3_int64 i64;
|
|
123
123
|
typedef sqlite3_uint64 u64;
|
|
124
124
|
typedef unsigned char u8;
|
|
125
|
-
#if SQLITE_USER_AUTHENTICATION
|
|
126
|
-
# include "sqlite3userauth.h"
|
|
127
|
-
#endif
|
|
128
125
|
#include <ctype.h>
|
|
129
126
|
#include <stdarg.h>
|
|
130
127
|
|
|
@@ -239,6 +236,8 @@ typedef unsigned char u8;
|
|
|
239
236
|
#define IsSpace(X) isspace((unsigned char)X)
|
|
240
237
|
#define IsDigit(X) isdigit((unsigned char)X)
|
|
241
238
|
#define ToLower(X) (char)tolower((unsigned char)X)
|
|
239
|
+
#define IsAlnum(X) isalnum((unsigned char)X)
|
|
240
|
+
#define IsAlpha(X) isalpha((unsigned char)X)
|
|
242
241
|
|
|
243
242
|
#if defined(_WIN32) || defined(WIN32)
|
|
244
243
|
#if SQLITE_OS_WINRT
|
|
@@ -360,6 +359,11 @@ void sqlite3_fsetmode(FILE *stream, int mode);
|
|
|
360
359
|
** use O_U8TEXT when writing to the Windows console (or anything
|
|
361
360
|
** else for which _isatty() returns true) and to use O_BINARY or O_TEXT
|
|
362
361
|
** for all other output channels.
|
|
362
|
+
**
|
|
363
|
+
** The SQLITE_USE_W32_FOR_CONSOLE_IO macro is also available. If
|
|
364
|
+
** defined, it forces the use of Win32 APIs for all console I/O, both
|
|
365
|
+
** input and output. This is necessary for some non-Microsoft run-times
|
|
366
|
+
** that implement stdio differently from Microsoft/Visual-Studio.
|
|
363
367
|
*/
|
|
364
368
|
#if defined(SQLITE_U8TEXT_ONLY)
|
|
365
369
|
# define UseWtextForOutput(fd) 1
|
|
@@ -410,8 +414,8 @@ FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
|
|
|
410
414
|
|
|
411
415
|
sz1 = (int)strlen(zFilename);
|
|
412
416
|
sz2 = (int)strlen(zMode);
|
|
413
|
-
b1 =
|
|
414
|
-
b2 =
|
|
417
|
+
b1 = sqlite3_malloc( (sz1+1)*sizeof(b1[0]) );
|
|
418
|
+
b2 = sqlite3_malloc( (sz2+1)*sizeof(b1[0]) );
|
|
415
419
|
if( b1 && b2 ){
|
|
416
420
|
sz1 = MultiByteToWideChar(CP_UTF8, 0, zFilename, sz1, b1, sz1);
|
|
417
421
|
b1[sz1] = 0;
|
|
@@ -419,8 +423,8 @@ FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
|
|
|
419
423
|
b2[sz2] = 0;
|
|
420
424
|
fp = _wfopen(b1, b2);
|
|
421
425
|
}
|
|
422
|
-
|
|
423
|
-
|
|
426
|
+
sqlite3_free(b1);
|
|
427
|
+
sqlite3_free(b2);
|
|
424
428
|
simBinaryOther = 0;
|
|
425
429
|
return fp;
|
|
426
430
|
}
|
|
@@ -436,8 +440,8 @@ FILE *sqlite3_popen(const char *zCommand, const char *zMode){
|
|
|
436
440
|
|
|
437
441
|
sz1 = (int)strlen(zCommand);
|
|
438
442
|
sz2 = (int)strlen(zMode);
|
|
439
|
-
b1 =
|
|
440
|
-
b2 =
|
|
443
|
+
b1 = sqlite3_malloc( (sz1+1)*sizeof(b1[0]) );
|
|
444
|
+
b2 = sqlite3_malloc( (sz2+1)*sizeof(b1[0]) );
|
|
441
445
|
if( b1 && b2 ){
|
|
442
446
|
sz1 = MultiByteToWideChar(CP_UTF8, 0, zCommand, sz1, b1, sz1);
|
|
443
447
|
b1[sz1] = 0;
|
|
@@ -445,8 +449,8 @@ FILE *sqlite3_popen(const char *zCommand, const char *zMode){
|
|
|
445
449
|
b2[sz2] = 0;
|
|
446
450
|
fp = _wpopen(b1, b2);
|
|
447
451
|
}
|
|
448
|
-
|
|
449
|
-
|
|
452
|
+
sqlite3_free(b1);
|
|
453
|
+
sqlite3_free(b2);
|
|
450
454
|
return fp;
|
|
451
455
|
}
|
|
452
456
|
|
|
@@ -460,12 +464,22 @@ char *sqlite3_fgets(char *buf, int sz, FILE *in){
|
|
|
460
464
|
** that into UTF-8. Otherwise, non-ASCII characters all get translated
|
|
461
465
|
** into '?'.
|
|
462
466
|
*/
|
|
463
|
-
wchar_t *b1 =
|
|
467
|
+
wchar_t *b1 = sqlite3_malloc( sz*sizeof(wchar_t) );
|
|
464
468
|
if( b1==0 ) return 0;
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
+
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO
|
|
470
|
+
DWORD nRead = 0;
|
|
471
|
+
if( IsConsole(in)
|
|
472
|
+
&& ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), b1, sz-1, &nRead, 0)
|
|
473
|
+
){
|
|
474
|
+
b1[nRead] = 0;
|
|
475
|
+
}else
|
|
476
|
+
#endif
|
|
477
|
+
{
|
|
478
|
+
_setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT);
|
|
479
|
+
if( fgetws(b1, sz/4, in)==0 ){
|
|
480
|
+
sqlite3_free(b1);
|
|
481
|
+
return 0;
|
|
482
|
+
}
|
|
469
483
|
}
|
|
470
484
|
WideCharToMultiByte(CP_UTF8, 0, b1, -1, buf, sz, 0, 0);
|
|
471
485
|
sqlite3_free(b1);
|
|
@@ -521,20 +535,34 @@ int sqlite3_fputs(const char *z, FILE *out){
|
|
|
521
535
|
** any translation. */
|
|
522
536
|
return fputs(z, out);
|
|
523
537
|
}else{
|
|
524
|
-
/*
|
|
525
|
-
** to
|
|
526
|
-
** use O_U8TEXT for everything in text mode.
|
|
538
|
+
/* One must use UTF16 in order to get unicode support when writing
|
|
539
|
+
** to the console on Windows.
|
|
527
540
|
*/
|
|
528
541
|
int sz = (int)strlen(z);
|
|
529
|
-
wchar_t *b1 =
|
|
542
|
+
wchar_t *b1 = sqlite3_malloc( (sz+1)*sizeof(wchar_t) );
|
|
530
543
|
if( b1==0 ) return 0;
|
|
531
544
|
sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz);
|
|
532
545
|
b1[sz] = 0;
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
546
|
+
|
|
547
|
+
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO
|
|
548
|
+
DWORD nWr = 0;
|
|
549
|
+
if( IsConsole(out)
|
|
550
|
+
&& WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),b1,sz,&nWr,0)
|
|
551
|
+
){
|
|
552
|
+
/* If writing to the console, then the WriteConsoleW() is all we
|
|
553
|
+
** need to do. */
|
|
554
|
+
}else
|
|
555
|
+
#endif
|
|
556
|
+
{
|
|
557
|
+
/* As long as SQLITE_USE_W32_FOR_CONSOLE_IO is not defined, or for
|
|
558
|
+
** non-console I/O even if that macro is defined, write using the
|
|
559
|
+
** standard library. */
|
|
560
|
+
_setmode(_fileno(out), _O_U8TEXT);
|
|
561
|
+
if( UseBinaryWText(out) ){
|
|
562
|
+
piecemealOutput(b1, sz, out);
|
|
563
|
+
}else{
|
|
564
|
+
fputws(b1, out);
|
|
565
|
+
}
|
|
538
566
|
}
|
|
539
567
|
sqlite3_free(b1);
|
|
540
568
|
return 0;
|
|
@@ -825,7 +853,7 @@ static char *Argv0;
|
|
|
825
853
|
** Prompt strings. Initialized in main. Settable with
|
|
826
854
|
** .prompt main continue
|
|
827
855
|
*/
|
|
828
|
-
#define PROMPT_LEN_MAX
|
|
856
|
+
#define PROMPT_LEN_MAX 128
|
|
829
857
|
/* First line prompt. default: "sqlite> " */
|
|
830
858
|
static char mainPrompt[PROMPT_LEN_MAX];
|
|
831
859
|
/* Continuation prompt. default: " ...> " */
|
|
@@ -1137,6 +1165,23 @@ int cli_wcswidth(const char *z){
|
|
|
1137
1165
|
}
|
|
1138
1166
|
#endif
|
|
1139
1167
|
|
|
1168
|
+
/*
|
|
1169
|
+
** Check to see if z[] is a valid VT100 escape. If it is, then
|
|
1170
|
+
** return the number of bytes in the escape sequence. Return 0 if
|
|
1171
|
+
** z[] is not a VT100 escape.
|
|
1172
|
+
**
|
|
1173
|
+
** This routine assumes that z[0] is \033 (ESC).
|
|
1174
|
+
*/
|
|
1175
|
+
static int isVt100(const unsigned char *z){
|
|
1176
|
+
int i;
|
|
1177
|
+
if( z[1]!='[' ) return 0;
|
|
1178
|
+
i = 2;
|
|
1179
|
+
while( z[i]>=0x30 && z[i]<=0x3f ){ i++; }
|
|
1180
|
+
while( z[i]>=0x20 && z[i]<=0x2f ){ i++; }
|
|
1181
|
+
if( z[i]<0x40 || z[i]>0x7e ) return 0;
|
|
1182
|
+
return i+1;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1140
1185
|
/*
|
|
1141
1186
|
** Output string zUtf to stdout as w characters. If w is negative,
|
|
1142
1187
|
** then right-justify the text. W is the width in UTF-8 characters, not
|
|
@@ -1152,6 +1197,7 @@ static void utf8_width_print(FILE *out, int w, const char *zUtf){
|
|
|
1152
1197
|
unsigned char c;
|
|
1153
1198
|
int i = 0;
|
|
1154
1199
|
int n = 0;
|
|
1200
|
+
int k;
|
|
1155
1201
|
int aw = w<0 ? -w : w;
|
|
1156
1202
|
if( zUtf==0 ) zUtf = "";
|
|
1157
1203
|
while( (c = a[i])!=0 ){
|
|
@@ -1164,6 +1210,8 @@ static void utf8_width_print(FILE *out, int w, const char *zUtf){
|
|
|
1164
1210
|
}
|
|
1165
1211
|
i += len;
|
|
1166
1212
|
n += x;
|
|
1213
|
+
}else if( c==0x1b && (k = isVt100(&a[i]))>0 ){
|
|
1214
|
+
i += k;
|
|
1167
1215
|
}else if( n>=aw ){
|
|
1168
1216
|
break;
|
|
1169
1217
|
}else{
|
|
@@ -1482,9 +1530,9 @@ static void appendText(ShellText *p, const char *zAppend, char quote){
|
|
|
1482
1530
|
static char quoteChar(const char *zName){
|
|
1483
1531
|
int i;
|
|
1484
1532
|
if( zName==0 ) return '"';
|
|
1485
|
-
if( !
|
|
1533
|
+
if( !IsAlpha(zName[0]) && zName[0]!='_' ) return '"';
|
|
1486
1534
|
for(i=0; zName[i]; i++){
|
|
1487
|
-
if( !
|
|
1535
|
+
if( !IsAlnum(zName[i]) && zName[i]!='_' ) return '"';
|
|
1488
1536
|
}
|
|
1489
1537
|
return sqlite3_keyword_check(zName, i) ? '"' : 0;
|
|
1490
1538
|
}
|
|
@@ -1576,30 +1624,6 @@ static void shellDtostr(
|
|
|
1576
1624
|
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
|
|
1577
1625
|
}
|
|
1578
1626
|
|
|
1579
|
-
|
|
1580
|
-
/*
|
|
1581
|
-
** SQL function: shell_module_schema(X)
|
|
1582
|
-
**
|
|
1583
|
-
** Return a fake schema for the table-valued function or eponymous virtual
|
|
1584
|
-
** table X.
|
|
1585
|
-
*/
|
|
1586
|
-
static void shellModuleSchema(
|
|
1587
|
-
sqlite3_context *pCtx,
|
|
1588
|
-
int nVal,
|
|
1589
|
-
sqlite3_value **apVal
|
|
1590
|
-
){
|
|
1591
|
-
const char *zName;
|
|
1592
|
-
char *zFake;
|
|
1593
|
-
UNUSED_PARAMETER(nVal);
|
|
1594
|
-
zName = (const char*)sqlite3_value_text(apVal[0]);
|
|
1595
|
-
zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
|
|
1596
|
-
if( zFake ){
|
|
1597
|
-
sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
|
|
1598
|
-
-1, sqlite3_free);
|
|
1599
|
-
free(zFake);
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
|
|
1603
1627
|
/*
|
|
1604
1628
|
** SQL function: shell_add_schema(S,X)
|
|
1605
1629
|
**
|
|
@@ -1774,6 +1798,7 @@ static void shellAddSchemaName(
|
|
|
1774
1798
|
# else
|
|
1775
1799
|
# define NAME_MAX (260)
|
|
1776
1800
|
# endif
|
|
1801
|
+
# define DIRENT_NAME_MAX (NAME_MAX)
|
|
1777
1802
|
#endif
|
|
1778
1803
|
|
|
1779
1804
|
/*
|
|
@@ -1817,8 +1842,7 @@ struct DIR {
|
|
|
1817
1842
|
/*
|
|
1818
1843
|
** Provide a macro, for use by the implementation, to determine if a
|
|
1819
1844
|
** particular directory entry should be skipped over when searching for
|
|
1820
|
-
** the next directory entry that should be returned by the readdir()
|
|
1821
|
-
** readdir_r() functions.
|
|
1845
|
+
** the next directory entry that should be returned by the readdir().
|
|
1822
1846
|
*/
|
|
1823
1847
|
|
|
1824
1848
|
#ifndef is_filtered
|
|
@@ -1834,12 +1858,11 @@ extern const char *windirent_getenv(const char *name);
|
|
|
1834
1858
|
|
|
1835
1859
|
/*
|
|
1836
1860
|
** Finally, we can provide the function prototypes for the opendir(),
|
|
1837
|
-
** readdir(),
|
|
1861
|
+
** readdir(), and closedir() POSIX functions.
|
|
1838
1862
|
*/
|
|
1839
1863
|
|
|
1840
1864
|
extern LPDIR opendir(const char *dirname);
|
|
1841
1865
|
extern LPDIRENT readdir(LPDIR dirp);
|
|
1842
|
-
extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
|
|
1843
1866
|
extern INT closedir(LPDIR dirp);
|
|
1844
1867
|
|
|
1845
1868
|
#endif /* defined(WIN32) && defined(_MSC_VER) */
|
|
@@ -1896,11 +1919,13 @@ const char *windirent_getenv(
|
|
|
1896
1919
|
** Implementation of the POSIX opendir() function using the MSVCRT.
|
|
1897
1920
|
*/
|
|
1898
1921
|
LPDIR opendir(
|
|
1899
|
-
const char *dirname
|
|
1922
|
+
const char *dirname /* Directory name, UTF8 encoding */
|
|
1900
1923
|
){
|
|
1901
|
-
struct
|
|
1924
|
+
struct _wfinddata_t data;
|
|
1902
1925
|
LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
|
|
1903
1926
|
SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
|
|
1927
|
+
wchar_t *b1;
|
|
1928
|
+
sqlite3_int64 sz;
|
|
1904
1929
|
|
|
1905
1930
|
if( dirp==NULL ) return NULL;
|
|
1906
1931
|
memset(dirp, 0, sizeof(DIR));
|
|
@@ -1910,9 +1935,25 @@ LPDIR opendir(
|
|
|
1910
1935
|
dirname = windirent_getenv("SystemDrive");
|
|
1911
1936
|
}
|
|
1912
1937
|
|
|
1913
|
-
memset(&data, 0, sizeof(
|
|
1914
|
-
|
|
1915
|
-
|
|
1938
|
+
memset(&data, 0, sizeof(data));
|
|
1939
|
+
sz = strlen(dirname);
|
|
1940
|
+
b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
|
|
1941
|
+
if( b1==0 ){
|
|
1942
|
+
closedir(dirp);
|
|
1943
|
+
return NULL;
|
|
1944
|
+
}
|
|
1945
|
+
sz = MultiByteToWideChar(CP_UTF8, 0, dirname, sz, b1, sz);
|
|
1946
|
+
b1[sz++] = '\\';
|
|
1947
|
+
b1[sz++] = '*';
|
|
1948
|
+
b1[sz] = 0;
|
|
1949
|
+
if( sz+1>(sqlite3_int64)namesize ){
|
|
1950
|
+
closedir(dirp);
|
|
1951
|
+
sqlite3_free(b1);
|
|
1952
|
+
return NULL;
|
|
1953
|
+
}
|
|
1954
|
+
memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
|
|
1955
|
+
sqlite3_free(b1);
|
|
1956
|
+
dirp->d_handle = _wfindfirst(data.name, &data);
|
|
1916
1957
|
|
|
1917
1958
|
if( dirp->d_handle==BAD_INTPTR_T ){
|
|
1918
1959
|
closedir(dirp);
|
|
@@ -1923,8 +1964,8 @@ LPDIR opendir(
|
|
|
1923
1964
|
if( is_filtered(data) ){
|
|
1924
1965
|
next:
|
|
1925
1966
|
|
|
1926
|
-
memset(&data, 0, sizeof(
|
|
1927
|
-
if(
|
|
1967
|
+
memset(&data, 0, sizeof(data));
|
|
1968
|
+
if( _wfindnext(dirp->d_handle, &data)==-1 ){
|
|
1928
1969
|
closedir(dirp);
|
|
1929
1970
|
return NULL;
|
|
1930
1971
|
}
|
|
@@ -1934,9 +1975,8 @@ next:
|
|
|
1934
1975
|
}
|
|
1935
1976
|
|
|
1936
1977
|
dirp->d_first.d_attributes = data.attrib;
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1978
|
+
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
|
|
1979
|
+
dirp->d_first.d_name, DIRENT_NAME_MAX, 0, 0);
|
|
1940
1980
|
return dirp;
|
|
1941
1981
|
}
|
|
1942
1982
|
|
|
@@ -1946,7 +1986,7 @@ next:
|
|
|
1946
1986
|
LPDIRENT readdir(
|
|
1947
1987
|
LPDIR dirp
|
|
1948
1988
|
){
|
|
1949
|
-
struct
|
|
1989
|
+
struct _wfinddata_t data;
|
|
1950
1990
|
|
|
1951
1991
|
if( dirp==NULL ) return NULL;
|
|
1952
1992
|
|
|
@@ -1959,65 +1999,19 @@ LPDIRENT readdir(
|
|
|
1959
1999
|
|
|
1960
2000
|
next:
|
|
1961
2001
|
|
|
1962
|
-
memset(&data, 0, sizeof(
|
|
1963
|
-
if(
|
|
2002
|
+
memset(&data, 0, sizeof(data));
|
|
2003
|
+
if( _wfindnext(dirp->d_handle, &data)==-1 ) return NULL;
|
|
1964
2004
|
|
|
1965
2005
|
/* TODO: Remove this block to allow hidden and/or system files. */
|
|
1966
2006
|
if( is_filtered(data) ) goto next;
|
|
1967
2007
|
|
|
1968
2008
|
dirp->d_next.d_ino++;
|
|
1969
2009
|
dirp->d_next.d_attributes = data.attrib;
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
2010
|
+
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
|
|
2011
|
+
dirp->d_next.d_name, DIRENT_NAME_MAX, 0, 0);
|
|
1973
2012
|
return &dirp->d_next;
|
|
1974
2013
|
}
|
|
1975
2014
|
|
|
1976
|
-
/*
|
|
1977
|
-
** Implementation of the POSIX readdir_r() function using the MSVCRT.
|
|
1978
|
-
*/
|
|
1979
|
-
INT readdir_r(
|
|
1980
|
-
LPDIR dirp,
|
|
1981
|
-
LPDIRENT entry,
|
|
1982
|
-
LPDIRENT *result
|
|
1983
|
-
){
|
|
1984
|
-
struct _finddata_t data;
|
|
1985
|
-
|
|
1986
|
-
if( dirp==NULL ) return EBADF;
|
|
1987
|
-
|
|
1988
|
-
if( dirp->d_first.d_ino==0 ){
|
|
1989
|
-
dirp->d_first.d_ino++;
|
|
1990
|
-
dirp->d_next.d_ino++;
|
|
1991
|
-
|
|
1992
|
-
entry->d_ino = dirp->d_first.d_ino;
|
|
1993
|
-
entry->d_attributes = dirp->d_first.d_attributes;
|
|
1994
|
-
strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
|
|
1995
|
-
entry->d_name[NAME_MAX] = '\0';
|
|
1996
|
-
|
|
1997
|
-
*result = entry;
|
|
1998
|
-
return 0;
|
|
1999
|
-
}
|
|
2000
|
-
|
|
2001
|
-
next:
|
|
2002
|
-
|
|
2003
|
-
memset(&data, 0, sizeof(struct _finddata_t));
|
|
2004
|
-
if( _findnext(dirp->d_handle, &data)==-1 ){
|
|
2005
|
-
*result = NULL;
|
|
2006
|
-
return ENOENT;
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
/* TODO: Remove this block to allow hidden and/or system files. */
|
|
2010
|
-
if( is_filtered(data) ) goto next;
|
|
2011
|
-
|
|
2012
|
-
entry->d_ino = (ino_t)-1; /* not available */
|
|
2013
|
-
entry->d_attributes = data.attrib;
|
|
2014
|
-
strncpy(entry->d_name, data.name, NAME_MAX);
|
|
2015
|
-
entry->d_name[NAME_MAX] = '\0';
|
|
2016
|
-
|
|
2017
|
-
*result = entry;
|
|
2018
|
-
return 0;
|
|
2019
|
-
}
|
|
2020
|
-
|
|
2021
2015
|
/*
|
|
2022
2016
|
** Implementation of the POSIX closedir() function using the MSVCRT.
|
|
2023
2017
|
*/
|
|
@@ -2349,7 +2343,7 @@ int sqlite3PcacheTraceDeactivate(void){
|
|
|
2349
2343
|
**
|
|
2350
2344
|
** This SQLite extension implements functions that compute SHA3 hashes
|
|
2351
2345
|
** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard.
|
|
2352
|
-
**
|
|
2346
|
+
** Three SQL functions are implemented:
|
|
2353
2347
|
**
|
|
2354
2348
|
** sha3(X,SIZE)
|
|
2355
2349
|
** sha3_agg(Y,SIZE)
|
|
@@ -2401,7 +2395,7 @@ int sqlite3PcacheTraceDeactivate(void){
|
|
|
2401
2395
|
**
|
|
2402
2396
|
** typeof(Y)='blob' The hash is taken over prefix "Bnnn:" followed
|
|
2403
2397
|
** by the binary content of the blob. The "nnn"
|
|
2404
|
-
** in the prefix is the
|
|
2398
|
+
** in the prefix is the minimum-length decimal
|
|
2405
2399
|
** representation of the byte-length of the blob.
|
|
2406
2400
|
**
|
|
2407
2401
|
** According to the rules above, all of the following SELECT statements
|
|
@@ -3622,7 +3616,7 @@ int sqlite3_sha_init(
|
|
|
3622
3616
|
** of digits compare in numeric order.
|
|
3623
3617
|
**
|
|
3624
3618
|
** * Leading zeros are handled properly, in the sense that
|
|
3625
|
-
** they do not mess of the
|
|
3619
|
+
** they do not mess of the magnitude comparison of embedded
|
|
3626
3620
|
** strings of digits. "x00123y" is equal to "x123y".
|
|
3627
3621
|
**
|
|
3628
3622
|
** * Only unsigned integers are recognized. Plus and minus
|
|
@@ -3728,6 +3722,9 @@ SQLITE_EXTENSION_INIT1
|
|
|
3728
3722
|
# define UNUSED_PARAMETER(X) (void)(X)
|
|
3729
3723
|
#endif
|
|
3730
3724
|
|
|
3725
|
+
#ifndef IsSpace
|
|
3726
|
+
#define IsSpace(X) isspace((unsigned char)X)
|
|
3727
|
+
#endif
|
|
3731
3728
|
|
|
3732
3729
|
/* A decimal object */
|
|
3733
3730
|
typedef struct Decimal Decimal;
|
|
@@ -3777,7 +3774,7 @@ static Decimal *decimalNewFromText(const char *zIn, int n){
|
|
|
3777
3774
|
p->nFrac = 0;
|
|
3778
3775
|
p->a = sqlite3_malloc64( n+1 );
|
|
3779
3776
|
if( p->a==0 ) goto new_from_text_failed;
|
|
3780
|
-
for(i=0;
|
|
3777
|
+
for(i=0; IsSpace(zIn[i]); i++){}
|
|
3781
3778
|
if( zIn[i]=='-' ){
|
|
3782
3779
|
p->sign = 1;
|
|
3783
3780
|
i++;
|
|
@@ -4432,7 +4429,7 @@ static void decimalSubFunc(
|
|
|
4432
4429
|
decimal_free(pB);
|
|
4433
4430
|
}
|
|
4434
4431
|
|
|
4435
|
-
/* Aggregate
|
|
4432
|
+
/* Aggregate function: decimal_sum(X)
|
|
4436
4433
|
**
|
|
4437
4434
|
** Works like sum() except that it uses decimal arithmetic for unlimited
|
|
4438
4435
|
** precision.
|
|
@@ -4793,7 +4790,7 @@ static int percentBinarySearch(Percentile *p, double y, int bExact){
|
|
|
4793
4790
|
/*
|
|
4794
4791
|
** Generate an error for a percentile function.
|
|
4795
4792
|
**
|
|
4796
|
-
** The error format string must have exactly one
|
|
4793
|
+
** The error format string must have exactly one occurrence of "%%s()"
|
|
4797
4794
|
** (with two '%' characters). That substring will be replaced by the name
|
|
4798
4795
|
** of the function.
|
|
4799
4796
|
*/
|
|
@@ -5072,10 +5069,10 @@ int sqlite3_percentile_init(
|
|
|
5072
5069
|
){
|
|
5073
5070
|
int rc = SQLITE_OK;
|
|
5074
5071
|
unsigned int i;
|
|
5075
|
-
#
|
|
5076
|
-
(void)pApi; /* Unused parameter */
|
|
5077
|
-
#else
|
|
5072
|
+
#ifdef SQLITE3EXT_H
|
|
5078
5073
|
SQLITE_EXTENSION_INIT2(pApi);
|
|
5074
|
+
#else
|
|
5075
|
+
(void)pApi; /* Unused parameter */
|
|
5079
5076
|
#endif
|
|
5080
5077
|
(void)pzErrMsg; /* Unused parameter */
|
|
5081
5078
|
for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
|
|
@@ -5271,15 +5268,15 @@ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
|
|
|
5271
5268
|
case ND:
|
|
5272
5269
|
/* Treat dark non-digits as pad, but they terminate decode too. */
|
|
5273
5270
|
ncIn = 0;
|
|
5274
|
-
deliberate_fall_through;
|
|
5271
|
+
deliberate_fall_through; /* FALLTHRU */
|
|
5275
5272
|
case WS:
|
|
5276
5273
|
/* Treat whitespace as pad and terminate this group.*/
|
|
5277
5274
|
nti = nac;
|
|
5278
|
-
deliberate_fall_through;
|
|
5275
|
+
deliberate_fall_through; /* FALLTHRU */
|
|
5279
5276
|
case PC:
|
|
5280
5277
|
bdp = 0;
|
|
5281
5278
|
--nbo;
|
|
5282
|
-
deliberate_fall_through;
|
|
5279
|
+
deliberate_fall_through; /* FALLTHRU */
|
|
5283
5280
|
default: /* bdp is the digit value. */
|
|
5284
5281
|
qv = qv<<6 | bdp;
|
|
5285
5282
|
break;
|
|
@@ -5288,10 +5285,13 @@ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
|
|
|
5288
5285
|
switch( nbo ){
|
|
5289
5286
|
case 3:
|
|
5290
5287
|
pOut[2] = (qv) & 0xff;
|
|
5288
|
+
deliberate_fall_through; /* FALLTHRU */
|
|
5291
5289
|
case 2:
|
|
5292
5290
|
pOut[1] = (qv>>8) & 0xff;
|
|
5291
|
+
deliberate_fall_through; /* FALLTHRU */
|
|
5293
5292
|
case 1:
|
|
5294
5293
|
pOut[0] = (qv>>16) & 0xff;
|
|
5294
|
+
break;
|
|
5295
5295
|
}
|
|
5296
5296
|
pOut += nbo;
|
|
5297
5297
|
}
|
|
@@ -5626,12 +5626,16 @@ static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){
|
|
|
5626
5626
|
switch( nbo ){
|
|
5627
5627
|
case 4:
|
|
5628
5628
|
*pOut++ = (qv >> 24)&0xff;
|
|
5629
|
+
/* FALLTHRU */
|
|
5629
5630
|
case 3:
|
|
5630
5631
|
*pOut++ = (qv >> 16)&0xff;
|
|
5632
|
+
/* FALLTHRU */
|
|
5631
5633
|
case 2:
|
|
5632
5634
|
*pOut++ = (qv >> 8)&0xff;
|
|
5635
|
+
/* FALLTHRU */
|
|
5633
5636
|
case 1:
|
|
5634
5637
|
*pOut++ = qv&0xff;
|
|
5638
|
+
/* FALLTHRU */
|
|
5635
5639
|
case 0:
|
|
5636
5640
|
break;
|
|
5637
5641
|
}
|
|
@@ -5926,7 +5930,7 @@ int main(int na, char *av[]){
|
|
|
5926
5930
|
** WITH c(name,bin) AS (VALUES
|
|
5927
5931
|
** ('minimum positive value', x'0000000000000001'),
|
|
5928
5932
|
** ('maximum subnormal value', x'000fffffffffffff'),
|
|
5929
|
-
** ('
|
|
5933
|
+
** ('minimum positive normal value', x'0010000000000000'),
|
|
5930
5934
|
** ('maximum value', x'7fefffffffffffff'))
|
|
5931
5935
|
** SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
|
|
5932
5936
|
** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
|
|
@@ -6234,8 +6238,7 @@ int sqlite3_ieee_init(
|
|
|
6234
6238
|
** step HIDDEN
|
|
6235
6239
|
** );
|
|
6236
6240
|
**
|
|
6237
|
-
** The virtual table also has a rowid
|
|
6238
|
-
** "n" is the ascending integer in the aforesaid production definition.
|
|
6241
|
+
** The virtual table also has a rowid which is an alias for the value.
|
|
6239
6242
|
**
|
|
6240
6243
|
** Function arguments in queries against this virtual table are translated
|
|
6241
6244
|
** into equality constraints against successive hidden columns. In other
|
|
@@ -6290,6 +6293,7 @@ SQLITE_EXTENSION_INIT1
|
|
|
6290
6293
|
#include <assert.h>
|
|
6291
6294
|
#include <string.h>
|
|
6292
6295
|
#include <limits.h>
|
|
6296
|
+
#include <math.h>
|
|
6293
6297
|
|
|
6294
6298
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
6295
6299
|
/*
|
|
@@ -6313,7 +6317,7 @@ static sqlite3_int64 genSeqMember(
|
|
|
6313
6317
|
smBase += (mxI64 - mxI64/2) * smStep;
|
|
6314
6318
|
}
|
|
6315
6319
|
/* Under UBSAN (or on 1's complement machines), must do this last term
|
|
6316
|
-
* in steps to avoid the dreaded (and harmless) signed multiply
|
|
6320
|
+
* in steps to avoid the dreaded (and harmless) signed multiply overflow. */
|
|
6317
6321
|
if( ix>=2 ){
|
|
6318
6322
|
sqlite3_int64 ix2 = (sqlite3_int64)ix/2;
|
|
6319
6323
|
smBase += ix2*smStep;
|
|
@@ -6450,6 +6454,7 @@ static int seriesConnect(
|
|
|
6450
6454
|
int rc;
|
|
6451
6455
|
|
|
6452
6456
|
/* Column numbers */
|
|
6457
|
+
#define SERIES_COLUMN_ROWID (-1)
|
|
6453
6458
|
#define SERIES_COLUMN_VALUE 0
|
|
6454
6459
|
#define SERIES_COLUMN_START 1
|
|
6455
6460
|
#define SERIES_COLUMN_STOP 2
|
|
@@ -6537,13 +6542,11 @@ static int seriesColumn(
|
|
|
6537
6542
|
#endif
|
|
6538
6543
|
|
|
6539
6544
|
/*
|
|
6540
|
-
**
|
|
6541
|
-
** "n" is the ascending integer in the aforesaid production definition.
|
|
6545
|
+
** The rowid is the same as the value.
|
|
6542
6546
|
*/
|
|
6543
6547
|
static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
|
6544
6548
|
series_cursor *pCur = (series_cursor*)cur;
|
|
6545
|
-
|
|
6546
|
-
*pRowid = (sqlite3_int64)((n<LARGEST_UINT64)? n+1 : 0);
|
|
6549
|
+
*pRowid = pCur->ss.iValueNow;
|
|
6547
6550
|
return SQLITE_OK;
|
|
6548
6551
|
}
|
|
6549
6552
|
|
|
@@ -6656,25 +6659,52 @@ static int seriesFilter(
|
|
|
6656
6659
|
** constraints on the "value" column.
|
|
6657
6660
|
*/
|
|
6658
6661
|
if( idxNum & 0x0080 ){
|
|
6659
|
-
|
|
6662
|
+
if( sqlite3_value_numeric_type(argv[i])==SQLITE_FLOAT ){
|
|
6663
|
+
double r = sqlite3_value_double(argv[i++]);
|
|
6664
|
+
if( r==ceil(r) ){
|
|
6665
|
+
iMin = iMax = (sqlite3_int64)r;
|
|
6666
|
+
}else{
|
|
6667
|
+
returnNoRows = 1;
|
|
6668
|
+
}
|
|
6669
|
+
}else{
|
|
6670
|
+
iMin = iMax = sqlite3_value_int64(argv[i++]);
|
|
6671
|
+
}
|
|
6660
6672
|
}else{
|
|
6661
6673
|
if( idxNum & 0x0300 ){
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
if(
|
|
6665
|
-
|
|
6674
|
+
if( sqlite3_value_numeric_type(argv[i])==SQLITE_FLOAT ){
|
|
6675
|
+
double r = sqlite3_value_double(argv[i++]);
|
|
6676
|
+
if( idxNum & 0x0200 && r==ceil(r) ){
|
|
6677
|
+
iMin = (sqlite3_int64)ceil(r+1.0);
|
|
6666
6678
|
}else{
|
|
6667
|
-
iMin
|
|
6679
|
+
iMin = (sqlite3_int64)ceil(r);
|
|
6680
|
+
}
|
|
6681
|
+
}else{
|
|
6682
|
+
iMin = sqlite3_value_int64(argv[i++]);
|
|
6683
|
+
if( idxNum & 0x0200 ){
|
|
6684
|
+
if( iMin==LARGEST_INT64 ){
|
|
6685
|
+
returnNoRows = 1;
|
|
6686
|
+
}else{
|
|
6687
|
+
iMin++;
|
|
6688
|
+
}
|
|
6668
6689
|
}
|
|
6669
6690
|
}
|
|
6670
6691
|
}
|
|
6671
6692
|
if( idxNum & 0x3000 ){
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
if(
|
|
6675
|
-
|
|
6693
|
+
if( sqlite3_value_numeric_type(argv[i])==SQLITE_FLOAT ){
|
|
6694
|
+
double r = sqlite3_value_double(argv[i++]);
|
|
6695
|
+
if( (idxNum & 0x2000)!=0 && r==floor(r) ){
|
|
6696
|
+
iMax = (sqlite3_int64)(r-1.0);
|
|
6676
6697
|
}else{
|
|
6677
|
-
iMax
|
|
6698
|
+
iMax = (sqlite3_int64)floor(r);
|
|
6699
|
+
}
|
|
6700
|
+
}else{
|
|
6701
|
+
iMax = sqlite3_value_int64(argv[i++]);
|
|
6702
|
+
if( idxNum & 0x2000 ){
|
|
6703
|
+
if( iMax==SMALLEST_INT64 ){
|
|
6704
|
+
returnNoRows = 1;
|
|
6705
|
+
}else{
|
|
6706
|
+
iMax--;
|
|
6707
|
+
}
|
|
6678
6708
|
}
|
|
6679
6709
|
}
|
|
6680
6710
|
}
|
|
@@ -6693,8 +6723,7 @@ static int seriesFilter(
|
|
|
6693
6723
|
pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep;
|
|
6694
6724
|
}
|
|
6695
6725
|
if( pCur->ss.iTerm>iMax ){
|
|
6696
|
-
|
|
6697
|
-
pCur->ss.iTerm -= ((d+szStep-1)/szStep)*szStep;
|
|
6726
|
+
pCur->ss.iTerm = iMax;
|
|
6698
6727
|
}
|
|
6699
6728
|
}else{
|
|
6700
6729
|
sqlite3_int64 szStep = -pCur->ss.iStep;
|
|
@@ -6704,8 +6733,7 @@ static int seriesFilter(
|
|
|
6704
6733
|
pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep;
|
|
6705
6734
|
}
|
|
6706
6735
|
if( pCur->ss.iTerm<iMin ){
|
|
6707
|
-
|
|
6708
|
-
pCur->ss.iTerm += ((d+szStep-1)/szStep)*szStep;
|
|
6736
|
+
pCur->ss.iTerm = iMin;
|
|
6709
6737
|
}
|
|
6710
6738
|
}
|
|
6711
6739
|
}
|
|
@@ -6730,7 +6758,7 @@ static int seriesFilter(
|
|
|
6730
6758
|
for(i=0; i<argc; i++){
|
|
6731
6759
|
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
|
|
6732
6760
|
/* If any of the constraints have a NULL value, then return no rows.
|
|
6733
|
-
** See ticket https://
|
|
6761
|
+
** See ticket https://sqlite.org/src/info/fac496b61722daf2 */
|
|
6734
6762
|
returnNoRows = 1;
|
|
6735
6763
|
break;
|
|
6736
6764
|
}
|
|
@@ -6833,7 +6861,10 @@ static int seriesBestIndex(
|
|
|
6833
6861
|
continue;
|
|
6834
6862
|
}
|
|
6835
6863
|
if( pConstraint->iColumn<SERIES_COLUMN_START ){
|
|
6836
|
-
if( pConstraint->iColumn==SERIES_COLUMN_VALUE
|
|
6864
|
+
if( (pConstraint->iColumn==SERIES_COLUMN_VALUE ||
|
|
6865
|
+
pConstraint->iColumn==SERIES_COLUMN_ROWID)
|
|
6866
|
+
&& pConstraint->usable
|
|
6867
|
+
){
|
|
6837
6868
|
switch( op ){
|
|
6838
6869
|
case SQLITE_INDEX_CONSTRAINT_EQ:
|
|
6839
6870
|
case SQLITE_INDEX_CONSTRAINT_IS: {
|
|
@@ -6841,7 +6872,9 @@ static int seriesBestIndex(
|
|
|
6841
6872
|
idxNum &= ~0x3300;
|
|
6842
6873
|
aIdx[5] = i;
|
|
6843
6874
|
aIdx[6] = -1;
|
|
6875
|
+
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
|
6844
6876
|
bStartSeen = 1;
|
|
6877
|
+
#endif
|
|
6845
6878
|
break;
|
|
6846
6879
|
}
|
|
6847
6880
|
case SQLITE_INDEX_CONSTRAINT_GE: {
|
|
@@ -6849,7 +6882,9 @@ static int seriesBestIndex(
|
|
|
6849
6882
|
idxNum |= 0x0100;
|
|
6850
6883
|
idxNum &= ~0x0200;
|
|
6851
6884
|
aIdx[5] = i;
|
|
6885
|
+
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
|
6852
6886
|
bStartSeen = 1;
|
|
6887
|
+
#endif
|
|
6853
6888
|
break;
|
|
6854
6889
|
}
|
|
6855
6890
|
case SQLITE_INDEX_CONSTRAINT_GT: {
|
|
@@ -6857,7 +6892,9 @@ static int seriesBestIndex(
|
|
|
6857
6892
|
idxNum |= 0x0200;
|
|
6858
6893
|
idxNum &= ~0x0100;
|
|
6859
6894
|
aIdx[5] = i;
|
|
6895
|
+
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
|
6860
6896
|
bStartSeen = 1;
|
|
6897
|
+
#endif
|
|
6861
6898
|
break;
|
|
6862
6899
|
}
|
|
6863
6900
|
case SQLITE_INDEX_CONSTRAINT_LE: {
|
|
@@ -7668,7 +7705,8 @@ static const char *re_subcompile_string(ReCompiled *p){
|
|
|
7668
7705
|
** regular expression. Applications should invoke this routine once
|
|
7669
7706
|
** for every call to re_compile() to avoid memory leaks.
|
|
7670
7707
|
*/
|
|
7671
|
-
static void re_free(
|
|
7708
|
+
static void re_free(void *p){
|
|
7709
|
+
ReCompiled *pRe = (ReCompiled*)p;
|
|
7672
7710
|
if( pRe ){
|
|
7673
7711
|
sqlite3_free(pRe->aOp);
|
|
7674
7712
|
sqlite3_free(pRe->aArg);
|
|
@@ -7995,14 +8033,9 @@ SQLITE_EXTENSION_INIT1
|
|
|
7995
8033
|
# include <direct.h>
|
|
7996
8034
|
/* # include "test_windirent.h" */
|
|
7997
8035
|
# define dirent DIRENT
|
|
7998
|
-
#
|
|
7999
|
-
#
|
|
8000
|
-
#
|
|
8001
|
-
# ifndef stat
|
|
8002
|
-
# define stat _stat
|
|
8003
|
-
# endif
|
|
8004
|
-
# define mkdir(path,mode) _mkdir(path)
|
|
8005
|
-
# define lstat(path,buf) stat(path,buf)
|
|
8036
|
+
# define stat _stat
|
|
8037
|
+
# define chmod(path,mode) fileio_chmod(path,mode)
|
|
8038
|
+
# define mkdir(path,mode) fileio_mkdir(path)
|
|
8006
8039
|
#endif
|
|
8007
8040
|
#include <time.h>
|
|
8008
8041
|
#include <errno.h>
|
|
@@ -8027,6 +8060,40 @@ SQLITE_EXTENSION_INIT1
|
|
|
8027
8060
|
#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
|
|
8028
8061
|
#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
|
|
8029
8062
|
|
|
8063
|
+
/*
|
|
8064
|
+
** UTF8 chmod() function for Windows
|
|
8065
|
+
*/
|
|
8066
|
+
#if defined(_WIN32) || defined(WIN32)
|
|
8067
|
+
static int fileio_chmod(const char *zPath, int pmode){
|
|
8068
|
+
sqlite3_int64 sz = strlen(zPath);
|
|
8069
|
+
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
|
|
8070
|
+
int rc;
|
|
8071
|
+
if( b1==0 ) return -1;
|
|
8072
|
+
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
|
|
8073
|
+
b1[sz] = 0;
|
|
8074
|
+
rc = _wchmod(b1, pmode);
|
|
8075
|
+
sqlite3_free(b1);
|
|
8076
|
+
return rc;
|
|
8077
|
+
}
|
|
8078
|
+
#endif
|
|
8079
|
+
|
|
8080
|
+
/*
|
|
8081
|
+
** UTF8 mkdir() function for Windows
|
|
8082
|
+
*/
|
|
8083
|
+
#if defined(_WIN32) || defined(WIN32)
|
|
8084
|
+
static int fileio_mkdir(const char *zPath){
|
|
8085
|
+
sqlite3_int64 sz = strlen(zPath);
|
|
8086
|
+
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
|
|
8087
|
+
int rc;
|
|
8088
|
+
if( b1==0 ) return -1;
|
|
8089
|
+
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
|
|
8090
|
+
b1[sz] = 0;
|
|
8091
|
+
rc = _wmkdir(b1);
|
|
8092
|
+
sqlite3_free(b1);
|
|
8093
|
+
return rc;
|
|
8094
|
+
}
|
|
8095
|
+
#endif
|
|
8096
|
+
|
|
8030
8097
|
|
|
8031
8098
|
/*
|
|
8032
8099
|
** Set the result stored by context ctx to a blob containing the
|
|
@@ -8188,7 +8255,13 @@ static int fileStat(
|
|
|
8188
8255
|
struct stat *pStatBuf
|
|
8189
8256
|
){
|
|
8190
8257
|
#if defined(_WIN32)
|
|
8191
|
-
|
|
8258
|
+
sqlite3_int64 sz = strlen(zPath);
|
|
8259
|
+
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
|
|
8260
|
+
int rc;
|
|
8261
|
+
if( b1==0 ) return 1;
|
|
8262
|
+
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
|
|
8263
|
+
b1[sz] = 0;
|
|
8264
|
+
rc = _wstat(b1, pStatBuf);
|
|
8192
8265
|
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
|
|
8193
8266
|
return rc;
|
|
8194
8267
|
#else
|
|
@@ -8206,9 +8279,7 @@ static int fileLinkStat(
|
|
|
8206
8279
|
struct stat *pStatBuf
|
|
8207
8280
|
){
|
|
8208
8281
|
#if defined(_WIN32)
|
|
8209
|
-
|
|
8210
|
-
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
|
|
8211
|
-
return rc;
|
|
8282
|
+
return fileStat(zPath, pStatBuf);
|
|
8212
8283
|
#else
|
|
8213
8284
|
return lstat(zPath, pStatBuf);
|
|
8214
8285
|
#endif
|
|
@@ -8334,7 +8405,7 @@ static int writeFile(
|
|
|
8334
8405
|
|
|
8335
8406
|
GetSystemTime(¤tTime);
|
|
8336
8407
|
SystemTimeToFileTime(¤tTime, &lastAccess);
|
|
8337
|
-
intervals =
|
|
8408
|
+
intervals = (mtime*10000000) + 116444736000000000;
|
|
8338
8409
|
lastWrite.dwLowDateTime = (DWORD)intervals;
|
|
8339
8410
|
lastWrite.dwHighDateTime = intervals >> 32;
|
|
8340
8411
|
zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
|
|
@@ -8987,6 +9058,11 @@ SQLITE_EXTENSION_INIT1
|
|
|
8987
9058
|
|
|
8988
9059
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
8989
9060
|
|
|
9061
|
+
#ifndef IsAlnum
|
|
9062
|
+
#define IsAlnum(X) isalnum((unsigned char)X)
|
|
9063
|
+
#endif
|
|
9064
|
+
|
|
9065
|
+
|
|
8990
9066
|
/* completion_vtab is a subclass of sqlite3_vtab which will
|
|
8991
9067
|
** serve as the underlying representation of a completion virtual table
|
|
8992
9068
|
*/
|
|
@@ -9323,7 +9399,7 @@ static int completionFilter(
|
|
|
9323
9399
|
}
|
|
9324
9400
|
if( pCur->zLine!=0 && pCur->zPrefix==0 ){
|
|
9325
9401
|
int i = pCur->nLine;
|
|
9326
|
-
while( i>0 && (
|
|
9402
|
+
while( i>0 && (IsAlnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
|
|
9327
9403
|
i--;
|
|
9328
9404
|
}
|
|
9329
9405
|
pCur->nPrefix = pCur->nLine - i;
|
|
@@ -14169,7 +14245,7 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
|
|
|
14169
14245
|
}else{
|
|
14170
14246
|
IdxTable *pTab;
|
|
14171
14247
|
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
|
|
14172
|
-
if( rc==SQLITE_OK ){
|
|
14248
|
+
if( rc==SQLITE_OK && ALWAYS(pTab!=0) ){
|
|
14173
14249
|
int i;
|
|
14174
14250
|
char *zInner = 0;
|
|
14175
14251
|
char *zOuter = 0;
|
|
@@ -14730,7 +14806,7 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
|
|
|
14730
14806
|
sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
|
|
14731
14807
|
}
|
|
14732
14808
|
|
|
14733
|
-
/* If an error has occurred, free the new object and
|
|
14809
|
+
/* If an error has occurred, free the new object and return NULL. Otherwise,
|
|
14734
14810
|
** return the new sqlite3expert handle. */
|
|
14735
14811
|
if( rc!=SQLITE_OK ){
|
|
14736
14812
|
sqlite3_expert_destroy(pNew);
|
|
@@ -16237,7 +16313,27 @@ int sqlite3_stmtrand_init(
|
|
|
16237
16313
|
** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that
|
|
16238
16314
|
** the shell.c source file will know to include the -vfstrace command-line
|
|
16239
16315
|
** option and (2) you must compile and link the three source files
|
|
16240
|
-
** shell,c, test_vfstrace.c, and sqlite3.c.
|
|
16316
|
+
** shell,c, test_vfstrace.c, and sqlite3.c.
|
|
16317
|
+
**
|
|
16318
|
+
** RUNTIME CONTROL OF VFSTRACE OUTPUT
|
|
16319
|
+
**
|
|
16320
|
+
** The application can use the "vfstrace" pragma to control which VFS
|
|
16321
|
+
** APIs are traced. To disable all output:
|
|
16322
|
+
**
|
|
16323
|
+
** PRAGMA vfstrace('-all');
|
|
16324
|
+
**
|
|
16325
|
+
** To enable all output (which is the default setting):
|
|
16326
|
+
**
|
|
16327
|
+
** PRAGMA vfstrace('+all');
|
|
16328
|
+
**
|
|
16329
|
+
** Individual APIs can be enabled or disabled by name, with or without
|
|
16330
|
+
** the initial "x" character. For example, to set up for tracing lock
|
|
16331
|
+
** primitives only:
|
|
16332
|
+
**
|
|
16333
|
+
** PRAGMA vfstrace('-all, +Lock,Unlock,ShmLock');
|
|
16334
|
+
**
|
|
16335
|
+
** The argument to the vfstrace pragma ignores capitalization and any
|
|
16336
|
+
** characters other than alphabetics, '+', and '-'.
|
|
16241
16337
|
*/
|
|
16242
16338
|
#include <stdlib.h>
|
|
16243
16339
|
#include <string.h>
|
|
@@ -16251,6 +16347,8 @@ typedef struct vfstrace_info vfstrace_info;
|
|
|
16251
16347
|
struct vfstrace_info {
|
|
16252
16348
|
sqlite3_vfs *pRootVfs; /* The underlying real VFS */
|
|
16253
16349
|
int (*xOut)(const char*, void*); /* Send output here */
|
|
16350
|
+
unsigned int mTrace; /* Mask of interfaces to trace */
|
|
16351
|
+
u8 bOn; /* Tracing on/off */
|
|
16254
16352
|
void *pOutArg; /* First argument to xOut */
|
|
16255
16353
|
const char *zVfsName; /* Name of this trace-VFS */
|
|
16256
16354
|
sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */
|
|
@@ -16267,6 +16365,39 @@ struct vfstrace_file {
|
|
|
16267
16365
|
sqlite3_file *pReal; /* The real underlying file */
|
|
16268
16366
|
};
|
|
16269
16367
|
|
|
16368
|
+
/*
|
|
16369
|
+
** Bit values for vfstrace_info.mTrace.
|
|
16370
|
+
*/
|
|
16371
|
+
#define VTR_CLOSE 0x00000001
|
|
16372
|
+
#define VTR_READ 0x00000002
|
|
16373
|
+
#define VTR_WRITE 0x00000004
|
|
16374
|
+
#define VTR_TRUNC 0x00000008
|
|
16375
|
+
#define VTR_SYNC 0x00000010
|
|
16376
|
+
#define VTR_FSIZE 0x00000020
|
|
16377
|
+
#define VTR_LOCK 0x00000040
|
|
16378
|
+
#define VTR_UNLOCK 0x00000080
|
|
16379
|
+
#define VTR_CRL 0x00000100
|
|
16380
|
+
#define VTR_FCTRL 0x00000200
|
|
16381
|
+
#define VTR_SECSZ 0x00000400
|
|
16382
|
+
#define VTR_DEVCHAR 0x00000800
|
|
16383
|
+
#define VTR_SHMLOCK 0x00001000
|
|
16384
|
+
#define VTR_SHMMAP 0x00002000
|
|
16385
|
+
#define VTR_SHMBAR 0x00004000
|
|
16386
|
+
#define VTR_SHMUNMAP 0x00008000
|
|
16387
|
+
#define VTR_OPEN 0x00010000
|
|
16388
|
+
#define VTR_DELETE 0x00020000
|
|
16389
|
+
#define VTR_ACCESS 0x00040000
|
|
16390
|
+
#define VTR_FULLPATH 0x00080000
|
|
16391
|
+
#define VTR_DLOPEN 0x00100000
|
|
16392
|
+
#define VTR_DLERR 0x00200000
|
|
16393
|
+
#define VTR_DLSYM 0x00400000
|
|
16394
|
+
#define VTR_DLCLOSE 0x00800000
|
|
16395
|
+
#define VTR_RAND 0x01000000
|
|
16396
|
+
#define VTR_SLEEP 0x02000000
|
|
16397
|
+
#define VTR_CURTIME 0x04000000
|
|
16398
|
+
#define VTR_LASTERR 0x08000000
|
|
16399
|
+
#define VTR_FETCH 0x10000000 /* Also coverse xUnfetch */
|
|
16400
|
+
|
|
16270
16401
|
/*
|
|
16271
16402
|
** Method declarations for vfstrace_file.
|
|
16272
16403
|
*/
|
|
@@ -16331,11 +16462,13 @@ static void vfstrace_printf(
|
|
|
16331
16462
|
){
|
|
16332
16463
|
va_list ap;
|
|
16333
16464
|
char *zMsg;
|
|
16334
|
-
|
|
16335
|
-
|
|
16336
|
-
|
|
16337
|
-
|
|
16338
|
-
|
|
16465
|
+
if( pInfo->bOn ){
|
|
16466
|
+
va_start(ap, zFormat);
|
|
16467
|
+
zMsg = sqlite3_vmprintf(zFormat, ap);
|
|
16468
|
+
va_end(ap);
|
|
16469
|
+
pInfo->xOut(zMsg, pInfo->pOutArg);
|
|
16470
|
+
sqlite3_free(zMsg);
|
|
16471
|
+
}
|
|
16339
16472
|
}
|
|
16340
16473
|
|
|
16341
16474
|
/*
|
|
@@ -16434,6 +16567,13 @@ static void strappend(char *z, int *pI, const char *zAppend){
|
|
|
16434
16567
|
*pI = i;
|
|
16435
16568
|
}
|
|
16436
16569
|
|
|
16570
|
+
/*
|
|
16571
|
+
** Turn tracing output on or off according to mMask.
|
|
16572
|
+
*/
|
|
16573
|
+
static void vfstraceOnOff(vfstrace_info *pInfo, unsigned int mMask){
|
|
16574
|
+
pInfo->bOn = (pInfo->mTrace & mMask)!=0;
|
|
16575
|
+
}
|
|
16576
|
+
|
|
16437
16577
|
/*
|
|
16438
16578
|
** Close an vfstrace-file.
|
|
16439
16579
|
*/
|
|
@@ -16441,6 +16581,7 @@ static int vfstraceClose(sqlite3_file *pFile){
|
|
|
16441
16581
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16442
16582
|
vfstrace_info *pInfo = p->pInfo;
|
|
16443
16583
|
int rc;
|
|
16584
|
+
vfstraceOnOff(pInfo, VTR_CLOSE);
|
|
16444
16585
|
vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
|
|
16445
16586
|
rc = p->pReal->pMethods->xClose(p->pReal);
|
|
16446
16587
|
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
|
@@ -16463,6 +16604,7 @@ static int vfstraceRead(
|
|
|
16463
16604
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16464
16605
|
vfstrace_info *pInfo = p->pInfo;
|
|
16465
16606
|
int rc;
|
|
16607
|
+
vfstraceOnOff(pInfo, VTR_READ);
|
|
16466
16608
|
vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
|
|
16467
16609
|
pInfo->zVfsName, p->zFName, iAmt, iOfst);
|
|
16468
16610
|
rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
|
|
@@ -16482,6 +16624,7 @@ static int vfstraceWrite(
|
|
|
16482
16624
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16483
16625
|
vfstrace_info *pInfo = p->pInfo;
|
|
16484
16626
|
int rc;
|
|
16627
|
+
vfstraceOnOff(pInfo, VTR_WRITE);
|
|
16485
16628
|
vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
|
|
16486
16629
|
pInfo->zVfsName, p->zFName, iAmt, iOfst);
|
|
16487
16630
|
rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
|
|
@@ -16496,6 +16639,7 @@ static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
|
|
16496
16639
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16497
16640
|
vfstrace_info *pInfo = p->pInfo;
|
|
16498
16641
|
int rc;
|
|
16642
|
+
vfstraceOnOff(pInfo, VTR_TRUNC);
|
|
16499
16643
|
vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
|
|
16500
16644
|
size);
|
|
16501
16645
|
rc = p->pReal->pMethods->xTruncate(p->pReal, size);
|
|
@@ -16520,6 +16664,7 @@ static int vfstraceSync(sqlite3_file *pFile, int flags){
|
|
|
16520
16664
|
if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
|
|
16521
16665
|
sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
|
|
16522
16666
|
}
|
|
16667
|
+
vfstraceOnOff(pInfo, VTR_SYNC);
|
|
16523
16668
|
vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
|
|
16524
16669
|
&zBuf[1]);
|
|
16525
16670
|
rc = p->pReal->pMethods->xSync(p->pReal, flags);
|
|
@@ -16534,6 +16679,7 @@ static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
|
|
16534
16679
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16535
16680
|
vfstrace_info *pInfo = p->pInfo;
|
|
16536
16681
|
int rc;
|
|
16682
|
+
vfstraceOnOff(pInfo, VTR_FSIZE);
|
|
16537
16683
|
vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
|
|
16538
16684
|
rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
|
|
16539
16685
|
vfstrace_print_errcode(pInfo, " -> %s,", rc);
|
|
@@ -16562,6 +16708,7 @@ static int vfstraceLock(sqlite3_file *pFile, int eLock){
|
|
|
16562
16708
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16563
16709
|
vfstrace_info *pInfo = p->pInfo;
|
|
16564
16710
|
int rc;
|
|
16711
|
+
vfstraceOnOff(pInfo, VTR_LOCK);
|
|
16565
16712
|
vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
|
|
16566
16713
|
lockName(eLock));
|
|
16567
16714
|
rc = p->pReal->pMethods->xLock(p->pReal, eLock);
|
|
@@ -16576,6 +16723,7 @@ static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
|
|
|
16576
16723
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16577
16724
|
vfstrace_info *pInfo = p->pInfo;
|
|
16578
16725
|
int rc;
|
|
16726
|
+
vfstraceOnOff(pInfo, VTR_UNLOCK);
|
|
16579
16727
|
vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
|
|
16580
16728
|
lockName(eLock));
|
|
16581
16729
|
rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
|
|
@@ -16590,6 +16738,7 @@ static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
|
|
16590
16738
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16591
16739
|
vfstrace_info *pInfo = p->pInfo;
|
|
16592
16740
|
int rc;
|
|
16741
|
+
vfstraceOnOff(pInfo, VTR_CRL);
|
|
16593
16742
|
vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)",
|
|
16594
16743
|
pInfo->zVfsName, p->zFName);
|
|
16595
16744
|
rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
|
|
@@ -16609,6 +16758,7 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
|
|
16609
16758
|
char zBuf2[100];
|
|
16610
16759
|
char *zOp;
|
|
16611
16760
|
char *zRVal = 0;
|
|
16761
|
+
vfstraceOnOff(pInfo, VTR_FCTRL);
|
|
16612
16762
|
switch( op ){
|
|
16613
16763
|
case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
|
|
16614
16764
|
case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
|
|
@@ -16637,6 +16787,80 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
|
|
16637
16787
|
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
|
|
16638
16788
|
case SQLITE_FCNTL_PRAGMA: {
|
|
16639
16789
|
const char *const* a = (const char*const*)pArg;
|
|
16790
|
+
if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){
|
|
16791
|
+
const u8 *zArg = (const u8*)a[2];
|
|
16792
|
+
if( zArg[0]>='0' && zArg[0]<='9' ){
|
|
16793
|
+
pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0);
|
|
16794
|
+
}else{
|
|
16795
|
+
static const struct {
|
|
16796
|
+
const char *z;
|
|
16797
|
+
unsigned int m;
|
|
16798
|
+
} aKw[] = {
|
|
16799
|
+
{ "all", 0xffffffff },
|
|
16800
|
+
{ "close", VTR_CLOSE },
|
|
16801
|
+
{ "read", VTR_READ },
|
|
16802
|
+
{ "write", VTR_WRITE },
|
|
16803
|
+
{ "truncate", VTR_TRUNC },
|
|
16804
|
+
{ "sync", VTR_SYNC },
|
|
16805
|
+
{ "filesize", VTR_FSIZE },
|
|
16806
|
+
{ "lock", VTR_LOCK },
|
|
16807
|
+
{ "unlock", VTR_UNLOCK },
|
|
16808
|
+
{ "checkreservedlock", VTR_CRL },
|
|
16809
|
+
{ "filecontrol", VTR_FCTRL },
|
|
16810
|
+
{ "sectorsize", VTR_SECSZ },
|
|
16811
|
+
{ "devicecharacteristics", VTR_DEVCHAR },
|
|
16812
|
+
{ "shmlock", VTR_SHMLOCK },
|
|
16813
|
+
{ "shmmap", VTR_SHMMAP },
|
|
16814
|
+
{ "shmummap", VTR_SHMUNMAP },
|
|
16815
|
+
{ "shmbarrier", VTR_SHMBAR },
|
|
16816
|
+
{ "open", VTR_OPEN },
|
|
16817
|
+
{ "delete", VTR_DELETE },
|
|
16818
|
+
{ "access", VTR_ACCESS },
|
|
16819
|
+
{ "fullpathname", VTR_FULLPATH },
|
|
16820
|
+
{ "dlopen", VTR_DLOPEN },
|
|
16821
|
+
{ "dlerror", VTR_DLERR },
|
|
16822
|
+
{ "dlsym", VTR_DLSYM },
|
|
16823
|
+
{ "dlclose", VTR_DLCLOSE },
|
|
16824
|
+
{ "randomness", VTR_RAND },
|
|
16825
|
+
{ "sleep", VTR_SLEEP },
|
|
16826
|
+
{ "currenttime", VTR_CURTIME },
|
|
16827
|
+
{ "currenttimeint64", VTR_CURTIME },
|
|
16828
|
+
{ "getlasterror", VTR_LASTERR },
|
|
16829
|
+
{ "fetch", VTR_FETCH },
|
|
16830
|
+
};
|
|
16831
|
+
int onOff = 1;
|
|
16832
|
+
while( zArg[0] ){
|
|
16833
|
+
int jj, n;
|
|
16834
|
+
while( zArg[0]!=0 && zArg[0]!='-' && zArg[0]!='+'
|
|
16835
|
+
&& !isalpha(zArg[0]) ) zArg++;
|
|
16836
|
+
if( zArg[0]==0 ) break;
|
|
16837
|
+
if( zArg[0]=='-' ){
|
|
16838
|
+
onOff = 0;
|
|
16839
|
+
zArg++;
|
|
16840
|
+
}else if( zArg[0]=='+' ){
|
|
16841
|
+
onOff = 1;
|
|
16842
|
+
zArg++;
|
|
16843
|
+
}
|
|
16844
|
+
while( !isalpha(zArg[0]) ){
|
|
16845
|
+
if( zArg[0]==0 ) break;
|
|
16846
|
+
zArg++;
|
|
16847
|
+
}
|
|
16848
|
+
if( zArg[0]=='x' && isalpha(zArg[1]) ) zArg++;
|
|
16849
|
+
for(n=0; isalpha(zArg[n]); n++){}
|
|
16850
|
+
for(jj=0; jj<(int)(sizeof(aKw)/sizeof(aKw[0])); jj++){
|
|
16851
|
+
if( sqlite3_strnicmp(aKw[jj].z,(const char*)zArg,n)==0 ){
|
|
16852
|
+
if( onOff ){
|
|
16853
|
+
pInfo->mTrace |= aKw[jj].m;
|
|
16854
|
+
}else{
|
|
16855
|
+
pInfo->mTrace &= ~aKw[jj].m;
|
|
16856
|
+
}
|
|
16857
|
+
break;
|
|
16858
|
+
}
|
|
16859
|
+
}
|
|
16860
|
+
zArg += n;
|
|
16861
|
+
}
|
|
16862
|
+
}
|
|
16863
|
+
}
|
|
16640
16864
|
sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
|
|
16641
16865
|
zOp = zBuf;
|
|
16642
16866
|
break;
|
|
@@ -16732,6 +16956,7 @@ static int vfstraceSectorSize(sqlite3_file *pFile){
|
|
|
16732
16956
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16733
16957
|
vfstrace_info *pInfo = p->pInfo;
|
|
16734
16958
|
int rc;
|
|
16959
|
+
vfstraceOnOff(pInfo, VTR_SECSZ);
|
|
16735
16960
|
vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
|
|
16736
16961
|
rc = p->pReal->pMethods->xSectorSize(p->pReal);
|
|
16737
16962
|
vfstrace_printf(pInfo, " -> %d\n", rc);
|
|
@@ -16745,6 +16970,7 @@ static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
|
|
|
16745
16970
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16746
16971
|
vfstrace_info *pInfo = p->pInfo;
|
|
16747
16972
|
int rc;
|
|
16973
|
+
vfstraceOnOff(pInfo, VTR_DEVCHAR);
|
|
16748
16974
|
vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
|
|
16749
16975
|
pInfo->zVfsName, p->zFName);
|
|
16750
16976
|
rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
|
|
@@ -16756,11 +16982,22 @@ static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
|
|
|
16756
16982
|
** Shared-memory operations.
|
|
16757
16983
|
*/
|
|
16758
16984
|
static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
|
16985
|
+
static const char *azLockName[] = {
|
|
16986
|
+
"WRITE",
|
|
16987
|
+
"CKPT",
|
|
16988
|
+
"RECOVER",
|
|
16989
|
+
"READ0",
|
|
16990
|
+
"READ1",
|
|
16991
|
+
"READ2",
|
|
16992
|
+
"READ3",
|
|
16993
|
+
"READ4",
|
|
16994
|
+
};
|
|
16759
16995
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16760
16996
|
vfstrace_info *pInfo = p->pInfo;
|
|
16761
16997
|
int rc;
|
|
16762
16998
|
char zLck[100];
|
|
16763
16999
|
int i = 0;
|
|
17000
|
+
vfstraceOnOff(pInfo, VTR_SHMLOCK);
|
|
16764
17001
|
memcpy(zLck, "|0", 3);
|
|
16765
17002
|
if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK");
|
|
16766
17003
|
if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK");
|
|
@@ -16769,8 +17006,15 @@ static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
|
|
16769
17006
|
if( flags & ~(0xf) ){
|
|
16770
17007
|
sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
|
|
16771
17008
|
}
|
|
16772
|
-
|
|
16773
|
-
|
|
17009
|
+
if( ofst>=0 && ofst<(int)(sizeof(azLockName)/sizeof(azLockName[0])) ){
|
|
17010
|
+
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d(%s),n=%d,%s)",
|
|
17011
|
+
pInfo->zVfsName, p->zFName, ofst, azLockName[ofst],
|
|
17012
|
+
n, &zLck[1]);
|
|
17013
|
+
}else{
|
|
17014
|
+
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=5d,n=%d,%s)",
|
|
17015
|
+
pInfo->zVfsName, p->zFName, ofst,
|
|
17016
|
+
n, &zLck[1]);
|
|
17017
|
+
}
|
|
16774
17018
|
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
|
|
16775
17019
|
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
|
16776
17020
|
return rc;
|
|
@@ -16785,6 +17029,7 @@ static int vfstraceShmMap(
|
|
|
16785
17029
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16786
17030
|
vfstrace_info *pInfo = p->pInfo;
|
|
16787
17031
|
int rc;
|
|
17032
|
+
vfstraceOnOff(pInfo, VTR_SHMMAP);
|
|
16788
17033
|
vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
|
|
16789
17034
|
pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
|
|
16790
17035
|
rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
|
|
@@ -16794,6 +17039,7 @@ static int vfstraceShmMap(
|
|
|
16794
17039
|
static void vfstraceShmBarrier(sqlite3_file *pFile){
|
|
16795
17040
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16796
17041
|
vfstrace_info *pInfo = p->pInfo;
|
|
17042
|
+
vfstraceOnOff(pInfo, VTR_SHMBAR);
|
|
16797
17043
|
vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
|
|
16798
17044
|
p->pReal->pMethods->xShmBarrier(p->pReal);
|
|
16799
17045
|
}
|
|
@@ -16801,13 +17047,35 @@ static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
|
|
|
16801
17047
|
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
16802
17048
|
vfstrace_info *pInfo = p->pInfo;
|
|
16803
17049
|
int rc;
|
|
17050
|
+
vfstraceOnOff(pInfo, VTR_SHMUNMAP);
|
|
16804
17051
|
vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
|
|
16805
17052
|
pInfo->zVfsName, p->zFName, delFlag);
|
|
16806
17053
|
rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
|
|
16807
17054
|
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
|
16808
17055
|
return rc;
|
|
16809
17056
|
}
|
|
16810
|
-
|
|
17057
|
+
static int vfstraceFetch(sqlite3_file *pFile, i64 iOff, int nAmt, void **pptr){
|
|
17058
|
+
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
17059
|
+
vfstrace_info *pInfo = p->pInfo;
|
|
17060
|
+
int rc;
|
|
17061
|
+
vfstraceOnOff(pInfo, VTR_FETCH);
|
|
17062
|
+
vfstrace_printf(pInfo, "%s.xFetch(%s,iOff=%lld,nAmt=%d,p=%p)",
|
|
17063
|
+
pInfo->zVfsName, p->zFName, iOff, nAmt, *pptr);
|
|
17064
|
+
rc = p->pReal->pMethods->xFetch(p->pReal, iOff, nAmt, pptr);
|
|
17065
|
+
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
|
17066
|
+
return rc;
|
|
17067
|
+
}
|
|
17068
|
+
static int vfstraceUnfetch(sqlite3_file *pFile, i64 iOff, void *ptr){
|
|
17069
|
+
vfstrace_file *p = (vfstrace_file *)pFile;
|
|
17070
|
+
vfstrace_info *pInfo = p->pInfo;
|
|
17071
|
+
int rc;
|
|
17072
|
+
vfstraceOnOff(pInfo, VTR_FETCH);
|
|
17073
|
+
vfstrace_printf(pInfo, "%s.xUnfetch(%s,iOff=%lld,p=%p)",
|
|
17074
|
+
pInfo->zVfsName, p->zFName, iOff, ptr);
|
|
17075
|
+
rc = p->pReal->pMethods->xUnfetch(p->pReal, iOff, ptr);
|
|
17076
|
+
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
|
17077
|
+
return rc;
|
|
17078
|
+
}
|
|
16811
17079
|
|
|
16812
17080
|
|
|
16813
17081
|
/*
|
|
@@ -16828,6 +17096,7 @@ static int vfstraceOpen(
|
|
|
16828
17096
|
p->zFName = zName ? fileTail(zName) : "<temp>";
|
|
16829
17097
|
p->pReal = (sqlite3_file *)&p[1];
|
|
16830
17098
|
rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
|
|
17099
|
+
vfstraceOnOff(pInfo, VTR_OPEN);
|
|
16831
17100
|
vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
|
|
16832
17101
|
pInfo->zVfsName, p->zFName, flags);
|
|
16833
17102
|
if( p->pReal->pMethods ){
|
|
@@ -16853,6 +17122,10 @@ static int vfstraceOpen(
|
|
|
16853
17122
|
pNew->xShmBarrier = pSub->xShmBarrier ? vfstraceShmBarrier : 0;
|
|
16854
17123
|
pNew->xShmUnmap = pSub->xShmUnmap ? vfstraceShmUnmap : 0;
|
|
16855
17124
|
}
|
|
17125
|
+
if( pNew->iVersion>=3 ){
|
|
17126
|
+
pNew->xFetch = pSub->xFetch ? vfstraceFetch : 0;
|
|
17127
|
+
pNew->xUnfetch = pSub->xUnfetch ? vfstraceUnfetch : 0;
|
|
17128
|
+
}
|
|
16856
17129
|
pFile->pMethods = pNew;
|
|
16857
17130
|
}
|
|
16858
17131
|
vfstrace_print_errcode(pInfo, " -> %s", rc);
|
|
@@ -16873,6 +17146,7 @@ static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
|
|
16873
17146
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
16874
17147
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
16875
17148
|
int rc;
|
|
17149
|
+
vfstraceOnOff(pInfo, VTR_DELETE);
|
|
16876
17150
|
vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
|
|
16877
17151
|
pInfo->zVfsName, zPath, dirSync);
|
|
16878
17152
|
rc = pRoot->xDelete(pRoot, zPath, dirSync);
|
|
@@ -16893,6 +17167,7 @@ static int vfstraceAccess(
|
|
|
16893
17167
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
16894
17168
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
16895
17169
|
int rc;
|
|
17170
|
+
vfstraceOnOff(pInfo, VTR_ACCESS);
|
|
16896
17171
|
vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
|
|
16897
17172
|
pInfo->zVfsName, zPath, flags);
|
|
16898
17173
|
rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
|
|
@@ -16915,6 +17190,7 @@ static int vfstraceFullPathname(
|
|
|
16915
17190
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
16916
17191
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
16917
17192
|
int rc;
|
|
17193
|
+
vfstraceOnOff(pInfo, VTR_FULLPATH);
|
|
16918
17194
|
vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
|
|
16919
17195
|
pInfo->zVfsName, zPath);
|
|
16920
17196
|
rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
|
|
@@ -16929,6 +17205,7 @@ static int vfstraceFullPathname(
|
|
|
16929
17205
|
static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
|
16930
17206
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
16931
17207
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
17208
|
+
vfstraceOnOff(pInfo, VTR_DLOPEN);
|
|
16932
17209
|
vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
|
|
16933
17210
|
return pRoot->xDlOpen(pRoot, zPath);
|
|
16934
17211
|
}
|
|
@@ -16941,6 +17218,7 @@ static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
|
|
16941
17218
|
static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
|
16942
17219
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
16943
17220
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
17221
|
+
vfstraceOnOff(pInfo, VTR_DLERR);
|
|
16944
17222
|
vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
|
|
16945
17223
|
pRoot->xDlError(pRoot, nByte, zErrMsg);
|
|
16946
17224
|
vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
|
|
@@ -16962,7 +17240,8 @@ static void (*vfstraceDlSym(sqlite3_vfs *pVfs,void *p,const char *zSym))(void){
|
|
|
16962
17240
|
static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
|
16963
17241
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
16964
17242
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
16965
|
-
|
|
17243
|
+
vfstraceOnOff(pInfo, VTR_DLCLOSE);
|
|
17244
|
+
vfstrace_printf(pInfo, "%s.xDlClose()\n", pInfo->zVfsName);
|
|
16966
17245
|
pRoot->xDlClose(pRoot, pHandle);
|
|
16967
17246
|
}
|
|
16968
17247
|
|
|
@@ -16973,6 +17252,7 @@ static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
|
|
16973
17252
|
static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
|
16974
17253
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
16975
17254
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
17255
|
+
vfstraceOnOff(pInfo, VTR_RAND);
|
|
16976
17256
|
vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
|
|
16977
17257
|
return pRoot->xRandomness(pRoot, nByte, zBufOut);
|
|
16978
17258
|
}
|
|
@@ -16984,6 +17264,8 @@ static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
|
|
16984
17264
|
static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
|
|
16985
17265
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
16986
17266
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
17267
|
+
vfstraceOnOff(pInfo, VTR_SLEEP);
|
|
17268
|
+
vfstrace_printf(pInfo, "%s.xSleep(%d)\n", pInfo->zVfsName, nMicro);
|
|
16987
17269
|
return pRoot->xSleep(pRoot, nMicro);
|
|
16988
17270
|
}
|
|
16989
17271
|
|
|
@@ -16993,21 +17275,37 @@ static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
|
|
|
16993
17275
|
static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
|
16994
17276
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
16995
17277
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
16996
|
-
|
|
17278
|
+
int rc;
|
|
17279
|
+
vfstraceOnOff(pInfo, VTR_CURTIME);
|
|
17280
|
+
vfstrace_printf(pInfo, "%s.xCurrentTime()", pInfo->zVfsName);
|
|
17281
|
+
rc = pRoot->xCurrentTime(pRoot, pTimeOut);
|
|
17282
|
+
vfstrace_printf(pInfo, " -> %.17g\n", *pTimeOut);
|
|
17283
|
+
return rc;
|
|
16997
17284
|
}
|
|
16998
17285
|
static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
|
|
16999
17286
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
17000
17287
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
17001
|
-
|
|
17288
|
+
int rc;
|
|
17289
|
+
vfstraceOnOff(pInfo, VTR_CURTIME);
|
|
17290
|
+
vfstrace_printf(pInfo, "%s.xCurrentTimeInt64()", pInfo->zVfsName);
|
|
17291
|
+
rc = pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
|
|
17292
|
+
vfstrace_printf(pInfo, " -> %lld\n", *pTimeOut);
|
|
17293
|
+
return rc;
|
|
17002
17294
|
}
|
|
17003
17295
|
|
|
17004
17296
|
/*
|
|
17005
|
-
** Return
|
|
17297
|
+
** Return the most recent error code and message
|
|
17006
17298
|
*/
|
|
17007
|
-
static int vfstraceGetLastError(sqlite3_vfs *pVfs, int
|
|
17299
|
+
static int vfstraceGetLastError(sqlite3_vfs *pVfs, int nErr, char *zErr){
|
|
17008
17300
|
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
|
17009
17301
|
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
|
17010
|
-
|
|
17302
|
+
int rc;
|
|
17303
|
+
vfstraceOnOff(pInfo, VTR_LASTERR);
|
|
17304
|
+
vfstrace_printf(pInfo, "%s.xGetLastError(%d,zBuf)", pInfo->zVfsName, nErr);
|
|
17305
|
+
if( nErr ) zErr[0] = 0;
|
|
17306
|
+
rc = pRoot->xGetLastError(pRoot, nErr, zErr);
|
|
17307
|
+
vfstrace_printf(pInfo, " -> zBuf[] = \"%s\", rc = %d\n", nErr?zErr:"", rc);
|
|
17308
|
+
return rc;
|
|
17011
17309
|
}
|
|
17012
17310
|
|
|
17013
17311
|
/*
|
|
@@ -17101,6 +17399,8 @@ int vfstrace_register(
|
|
|
17101
17399
|
pInfo->pOutArg = pOutArg;
|
|
17102
17400
|
pInfo->zVfsName = pNew->zName;
|
|
17103
17401
|
pInfo->pTraceVfs = pNew;
|
|
17402
|
+
pInfo->mTrace = 0xffffffff;
|
|
17403
|
+
pInfo->bOn = 1;
|
|
17104
17404
|
vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
|
|
17105
17405
|
pInfo->zVfsName, pRoot->zName);
|
|
17106
17406
|
return sqlite3_vfs_register(pNew, makeDefault);
|
|
@@ -18390,6 +18690,9 @@ static int sqlite3DbdataRegister(sqlite3 *db){
|
|
|
18390
18690
|
return rc;
|
|
18391
18691
|
}
|
|
18392
18692
|
|
|
18693
|
+
#ifdef _WIN32
|
|
18694
|
+
|
|
18695
|
+
#endif
|
|
18393
18696
|
int sqlite3_dbdata_init(
|
|
18394
18697
|
sqlite3 *db,
|
|
18395
18698
|
char **pzErrMsg,
|
|
@@ -18438,6 +18741,16 @@ int sqlite3_dbdata_init(sqlite3*, char**, const sqlite3_api_routines*);
|
|
|
18438
18741
|
/* typedef unsigned char u8; */
|
|
18439
18742
|
/* typedef sqlite3_int64 i64; */
|
|
18440
18743
|
|
|
18744
|
+
/*
|
|
18745
|
+
** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
|
|
18746
|
+
** to avoid complaints from -fsanitize=strict-bounds.
|
|
18747
|
+
*/
|
|
18748
|
+
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
|
18749
|
+
# define FLEXARRAY
|
|
18750
|
+
#else
|
|
18751
|
+
# define FLEXARRAY 1
|
|
18752
|
+
#endif
|
|
18753
|
+
|
|
18441
18754
|
typedef struct RecoverTable RecoverTable;
|
|
18442
18755
|
typedef struct RecoverColumn RecoverColumn;
|
|
18443
18756
|
|
|
@@ -18545,9 +18858,12 @@ struct RecoverColumn {
|
|
|
18545
18858
|
typedef struct RecoverBitmap RecoverBitmap;
|
|
18546
18859
|
struct RecoverBitmap {
|
|
18547
18860
|
i64 nPg; /* Size of bitmap */
|
|
18548
|
-
u32 aElem[
|
|
18861
|
+
u32 aElem[FLEXARRAY]; /* Array of 32-bit bitmasks */
|
|
18549
18862
|
};
|
|
18550
18863
|
|
|
18864
|
+
/* Size in bytes of a RecoverBitmap object sufficient to cover 32 pages */
|
|
18865
|
+
#define SZ_RECOVERBITMAP_32 (16)
|
|
18866
|
+
|
|
18551
18867
|
/*
|
|
18552
18868
|
** State variables (part of the sqlite3_recover structure) used while
|
|
18553
18869
|
** recovering data for tables identified in the recovered schema (state
|
|
@@ -18787,7 +19103,7 @@ static int recoverError(
|
|
|
18787
19103
|
*/
|
|
18788
19104
|
static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){
|
|
18789
19105
|
int nElem = (nPg+1+31) / 32;
|
|
18790
|
-
int nByte =
|
|
19106
|
+
int nByte = SZ_RECOVERBITMAP_32 + nElem*sizeof(u32);
|
|
18791
19107
|
RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte);
|
|
18792
19108
|
|
|
18793
19109
|
if( pRet ){
|
|
@@ -20230,6 +20546,8 @@ static int recoverWriteDataStep(sqlite3_recover *p){
|
|
|
20230
20546
|
recoverError(p, SQLITE_NOMEM, 0);
|
|
20231
20547
|
}
|
|
20232
20548
|
p1->nVal = iField+1;
|
|
20549
|
+
}else if( pTab->nCol==0 ){
|
|
20550
|
+
p1->nVal = pTab->nCol;
|
|
20233
20551
|
}
|
|
20234
20552
|
p1->iPrevCell = iCell;
|
|
20235
20553
|
p1->iPrevPage = iPage;
|
|
@@ -20977,37 +21295,53 @@ static void recoverUninstallWrapper(sqlite3_recover *p){
|
|
|
20977
21295
|
static void recoverStep(sqlite3_recover *p){
|
|
20978
21296
|
assert( p && p->errCode==SQLITE_OK );
|
|
20979
21297
|
switch( p->eState ){
|
|
20980
|
-
case RECOVER_STATE_INIT:
|
|
21298
|
+
case RECOVER_STATE_INIT: {
|
|
21299
|
+
int bUseWrapper = 1;
|
|
20981
21300
|
/* This is the very first call to sqlite3_recover_step() on this object.
|
|
20982
21301
|
*/
|
|
20983
21302
|
recoverSqlCallback(p, "BEGIN");
|
|
20984
21303
|
recoverSqlCallback(p, "PRAGMA writable_schema = on");
|
|
21304
|
+
recoverSqlCallback(p, "PRAGMA foreign_keys = off");
|
|
20985
21305
|
|
|
20986
21306
|
recoverEnterMutex();
|
|
20987
|
-
recoverInstallWrapper(p);
|
|
20988
21307
|
|
|
20989
21308
|
/* Open the output database. And register required virtual tables and
|
|
20990
21309
|
** user functions with the new handle. */
|
|
20991
21310
|
recoverOpenOutput(p);
|
|
20992
21311
|
|
|
20993
|
-
/*
|
|
20994
|
-
|
|
20995
|
-
|
|
20996
|
-
|
|
20997
|
-
|
|
20998
|
-
|
|
20999
|
-
|
|
21000
|
-
|
|
21001
|
-
|
|
21002
|
-
|
|
21003
|
-
|
|
21004
|
-
|
|
21312
|
+
/* Attempt to open a transaction and read page 1 of the input database.
|
|
21313
|
+
** Two attempts may be made - one with a wrapper installed to ensure
|
|
21314
|
+
** that the database header is sane, and then if that attempt returns
|
|
21315
|
+
** SQLITE_NOTADB, then again with no wrapper. The second attempt is
|
|
21316
|
+
** required for encrypted databases. */
|
|
21317
|
+
if( p->errCode==SQLITE_OK ){
|
|
21318
|
+
do{
|
|
21319
|
+
p->errCode = SQLITE_OK;
|
|
21320
|
+
if( bUseWrapper ) recoverInstallWrapper(p);
|
|
21321
|
+
|
|
21322
|
+
/* Open a transaction on the input database. */
|
|
21323
|
+
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
|
|
21324
|
+
recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
|
|
21325
|
+
recoverExec(p, p->dbIn, "BEGIN");
|
|
21326
|
+
if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
|
|
21327
|
+
recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
|
|
21328
|
+
recoverTransferSettings(p);
|
|
21329
|
+
recoverOpenRecovery(p);
|
|
21330
|
+
recoverCacheSchema(p);
|
|
21331
|
+
|
|
21332
|
+
if( bUseWrapper ) recoverUninstallWrapper(p);
|
|
21333
|
+
}while( p->errCode==SQLITE_NOTADB
|
|
21334
|
+
&& (bUseWrapper--)
|
|
21335
|
+
&& SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
|
|
21336
|
+
);
|
|
21337
|
+
}
|
|
21005
21338
|
|
|
21339
|
+
recoverLeaveMutex();
|
|
21006
21340
|
recoverExec(p, p->dbOut, "BEGIN");
|
|
21007
|
-
|
|
21008
21341
|
recoverWriteSchema1(p);
|
|
21009
21342
|
p->eState = RECOVER_STATE_WRITING;
|
|
21010
21343
|
break;
|
|
21344
|
+
}
|
|
21011
21345
|
|
|
21012
21346
|
case RECOVER_STATE_WRITING: {
|
|
21013
21347
|
if( p->w1.pTbls==0 ){
|
|
@@ -21346,6 +21680,7 @@ struct ShellState {
|
|
|
21346
21680
|
u8 bSafeModePersist; /* The long-term value of bSafeMode */
|
|
21347
21681
|
u8 eRestoreState; /* See comments above doAutoDetectRestore() */
|
|
21348
21682
|
u8 crlfMode; /* Do NL-to-CRLF translations when enabled (maybe) */
|
|
21683
|
+
u8 eEscMode; /* Escape mode for text output */
|
|
21349
21684
|
ColModeOpts cmOpts; /* Option values affecting columnar mode output */
|
|
21350
21685
|
unsigned statsOn; /* True to display memory stats before each finalize */
|
|
21351
21686
|
unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */
|
|
@@ -21446,6 +21781,15 @@ static ShellState shellState;
|
|
|
21446
21781
|
** top-level SQL statement */
|
|
21447
21782
|
#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
|
|
21448
21783
|
|
|
21784
|
+
/* Allowed values for ShellState.eEscMode. The default value should
|
|
21785
|
+
** be 0, so to change the default, reorder the names.
|
|
21786
|
+
*/
|
|
21787
|
+
#define SHELL_ESC_ASCII 0 /* Substitute ^Y for X where Y=X+0x40 */
|
|
21788
|
+
#define SHELL_ESC_SYMBOL 1 /* Substitute U+2400 graphics */
|
|
21789
|
+
#define SHELL_ESC_OFF 2 /* Send characters verbatim */
|
|
21790
|
+
|
|
21791
|
+
static const char *shell_EscModeNames[] = { "ascii", "symbol", "off" };
|
|
21792
|
+
|
|
21449
21793
|
/*
|
|
21450
21794
|
** These are the allowed shellFlgs values
|
|
21451
21795
|
*/
|
|
@@ -21783,59 +22127,75 @@ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
|
|
|
21783
22127
|
}
|
|
21784
22128
|
|
|
21785
22129
|
/*
|
|
21786
|
-
**
|
|
21787
|
-
** to that string.
|
|
22130
|
+
** Output the given string as a quoted string using SQL quoting conventions:
|
|
21788
22131
|
**
|
|
21789
|
-
**
|
|
21790
|
-
**
|
|
21791
|
-
|
|
21792
|
-
|
|
21793
|
-
|
|
21794
|
-
|
|
21795
|
-
|
|
21796
|
-
){
|
|
21797
|
-
unsigned i = 0;
|
|
21798
|
-
if( strstr(z, zA)==0 ) return zA;
|
|
21799
|
-
if( strstr(z, zB)==0 ) return zB;
|
|
21800
|
-
do{
|
|
21801
|
-
sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
|
|
21802
|
-
}while( strstr(z,zBuf)!=0 );
|
|
21803
|
-
return zBuf;
|
|
21804
|
-
}
|
|
21805
|
-
|
|
21806
|
-
/*
|
|
21807
|
-
** Output the given string as a quoted string using SQL quoting conventions.
|
|
22132
|
+
** (1) Single quotes (') within the string are doubled
|
|
22133
|
+
** (2) The whle string is enclosed in '...'
|
|
22134
|
+
** (3) Control characters other than \n, \t, and \r\n are escaped
|
|
22135
|
+
** using \u00XX notation and if such substitutions occur,
|
|
22136
|
+
** the whole string is enclosed in unistr('...') instead of '...'.
|
|
22137
|
+
**
|
|
22138
|
+
** Step (3) is omitted if the control-character escape mode is OFF.
|
|
21808
22139
|
**
|
|
21809
|
-
** See also: output_quoted_escaped_string()
|
|
22140
|
+
** See also: output_quoted_escaped_string() which does the same except
|
|
22141
|
+
** that it does not make exceptions for \n, \t, and \r\n in step (3).
|
|
21810
22142
|
*/
|
|
21811
|
-
static void output_quoted_string(ShellState *p, const char *
|
|
22143
|
+
static void output_quoted_string(ShellState *p, const char *zInX){
|
|
21812
22144
|
int i;
|
|
21813
|
-
|
|
22145
|
+
int needUnistr = 0;
|
|
22146
|
+
int needDblQuote = 0;
|
|
22147
|
+
const unsigned char *z = (const unsigned char*)zInX;
|
|
22148
|
+
unsigned char c;
|
|
21814
22149
|
FILE *out = p->out;
|
|
21815
22150
|
sqlite3_fsetmode(out, _O_BINARY);
|
|
21816
22151
|
if( z==0 ) return;
|
|
21817
|
-
for(i=0; (c = z[i])!=0
|
|
21818
|
-
|
|
22152
|
+
for(i=0; (c = z[i])!=0; i++){
|
|
22153
|
+
if( c=='\'' ){ needDblQuote = 1; }
|
|
22154
|
+
if( c>0x1f ) continue;
|
|
22155
|
+
if( c=='\t' || c=='\n' ) continue;
|
|
22156
|
+
if( c=='\r' && z[i+1]=='\n' ) continue;
|
|
22157
|
+
needUnistr = 1;
|
|
22158
|
+
break;
|
|
22159
|
+
}
|
|
22160
|
+
if( (needDblQuote==0 && needUnistr==0)
|
|
22161
|
+
|| (needDblQuote==0 && p->eEscMode==SHELL_ESC_OFF)
|
|
22162
|
+
){
|
|
21819
22163
|
sqlite3_fprintf(out, "'%s'",z);
|
|
22164
|
+
}else if( p->eEscMode==SHELL_ESC_OFF ){
|
|
22165
|
+
char *zEncoded = sqlite3_mprintf("%Q", z);
|
|
22166
|
+
sqlite3_fputs(zEncoded, out);
|
|
22167
|
+
sqlite3_free(zEncoded);
|
|
21820
22168
|
}else{
|
|
21821
|
-
|
|
22169
|
+
if( needUnistr ){
|
|
22170
|
+
sqlite3_fputs("unistr('", out);
|
|
22171
|
+
}else{
|
|
22172
|
+
sqlite3_fputs("'", out);
|
|
22173
|
+
}
|
|
21822
22174
|
while( *z ){
|
|
21823
|
-
for(i=0; (c = z[i])!=0
|
|
21824
|
-
|
|
22175
|
+
for(i=0; (c = z[i])!=0; i++){
|
|
22176
|
+
if( c=='\'' ) break;
|
|
22177
|
+
if( c>0x1f ) continue;
|
|
22178
|
+
if( c=='\t' || c=='\n' ) continue;
|
|
22179
|
+
if( c=='\r' && z[i+1]=='\n' ) continue;
|
|
22180
|
+
break;
|
|
22181
|
+
}
|
|
21825
22182
|
if( i ){
|
|
21826
22183
|
sqlite3_fprintf(out, "%.*s", i, z);
|
|
21827
22184
|
z += i;
|
|
21828
22185
|
}
|
|
22186
|
+
if( c==0 ) break;
|
|
21829
22187
|
if( c=='\'' ){
|
|
21830
|
-
sqlite3_fputs("'", out);
|
|
21831
|
-
|
|
21832
|
-
|
|
21833
|
-
if( c==0 ){
|
|
21834
|
-
break;
|
|
22188
|
+
sqlite3_fputs("''", out);
|
|
22189
|
+
}else{
|
|
22190
|
+
sqlite3_fprintf(out, "\\u%04x", c);
|
|
21835
22191
|
}
|
|
21836
22192
|
z++;
|
|
21837
22193
|
}
|
|
21838
|
-
|
|
22194
|
+
if( needUnistr ){
|
|
22195
|
+
sqlite3_fputs("')", out);
|
|
22196
|
+
}else{
|
|
22197
|
+
sqlite3_fputs("'", out);
|
|
22198
|
+
}
|
|
21839
22199
|
}
|
|
21840
22200
|
setCrlfMode(p);
|
|
21841
22201
|
}
|
|
@@ -21850,61 +22210,15 @@ static void output_quoted_string(ShellState *p, const char *z){
|
|
|
21850
22210
|
** escape mechanism.
|
|
21851
22211
|
*/
|
|
21852
22212
|
static void output_quoted_escaped_string(ShellState *p, const char *z){
|
|
21853
|
-
|
|
21854
|
-
|
|
21855
|
-
|
|
21856
|
-
|
|
21857
|
-
for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
|
|
21858
|
-
if( c==0 ){
|
|
21859
|
-
sqlite3_fprintf(out, "'%s'",z);
|
|
22213
|
+
char *zEscaped;
|
|
22214
|
+
sqlite3_fsetmode(p->out, _O_BINARY);
|
|
22215
|
+
if( p->eEscMode==SHELL_ESC_OFF ){
|
|
22216
|
+
zEscaped = sqlite3_mprintf("%Q", z);
|
|
21860
22217
|
}else{
|
|
21861
|
-
|
|
21862
|
-
const char *zCR = 0;
|
|
21863
|
-
int nNL = 0;
|
|
21864
|
-
int nCR = 0;
|
|
21865
|
-
char zBuf1[20], zBuf2[20];
|
|
21866
|
-
for(i=0; z[i]; i++){
|
|
21867
|
-
if( z[i]=='\n' ) nNL++;
|
|
21868
|
-
if( z[i]=='\r' ) nCR++;
|
|
21869
|
-
}
|
|
21870
|
-
if( nNL ){
|
|
21871
|
-
sqlite3_fputs("replace(", out);
|
|
21872
|
-
zNL = unused_string(z, "\\n", "\\012", zBuf1);
|
|
21873
|
-
}
|
|
21874
|
-
if( nCR ){
|
|
21875
|
-
sqlite3_fputs("replace(", out);
|
|
21876
|
-
zCR = unused_string(z, "\\r", "\\015", zBuf2);
|
|
21877
|
-
}
|
|
21878
|
-
sqlite3_fputs("'", out);
|
|
21879
|
-
while( *z ){
|
|
21880
|
-
for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
|
|
21881
|
-
if( c=='\'' ) i++;
|
|
21882
|
-
if( i ){
|
|
21883
|
-
sqlite3_fprintf(out, "%.*s", i, z);
|
|
21884
|
-
z += i;
|
|
21885
|
-
}
|
|
21886
|
-
if( c=='\'' ){
|
|
21887
|
-
sqlite3_fputs("'", out);
|
|
21888
|
-
continue;
|
|
21889
|
-
}
|
|
21890
|
-
if( c==0 ){
|
|
21891
|
-
break;
|
|
21892
|
-
}
|
|
21893
|
-
z++;
|
|
21894
|
-
if( c=='\n' ){
|
|
21895
|
-
sqlite3_fputs(zNL, out);
|
|
21896
|
-
continue;
|
|
21897
|
-
}
|
|
21898
|
-
sqlite3_fputs(zCR, out);
|
|
21899
|
-
}
|
|
21900
|
-
sqlite3_fputs("'", out);
|
|
21901
|
-
if( nCR ){
|
|
21902
|
-
sqlite3_fprintf(out, ",'%s',char(13))", zCR);
|
|
21903
|
-
}
|
|
21904
|
-
if( nNL ){
|
|
21905
|
-
sqlite3_fprintf(out, ",'%s',char(10))", zNL);
|
|
21906
|
-
}
|
|
22218
|
+
zEscaped = sqlite3_mprintf("%#Q", z);
|
|
21907
22219
|
}
|
|
22220
|
+
sqlite3_fputs(zEscaped, p->out);
|
|
22221
|
+
sqlite3_free(zEscaped);
|
|
21908
22222
|
setCrlfMode(p);
|
|
21909
22223
|
}
|
|
21910
22224
|
|
|
@@ -21937,8 +22251,8 @@ const char *zSkipValidUtf8(const char *z, int nAccept, long ccm){
|
|
|
21937
22251
|
const char *pcLimit = (nAccept>=0)? z+nAccept : 0;
|
|
21938
22252
|
assert(z!=0);
|
|
21939
22253
|
while( (pcLimit)? (z<pcLimit) : (ng-- != 0) ){
|
|
21940
|
-
char c = *z;
|
|
21941
|
-
if(
|
|
22254
|
+
unsigned char c = *(u8*)z;
|
|
22255
|
+
if( c<0x7f ){
|
|
21942
22256
|
if( ccm != 0L && c < 0x20 && ((1L<<c) & ccm) != 0 ) return z;
|
|
21943
22257
|
++z; /* ASCII */
|
|
21944
22258
|
}else if( (c & 0xC0) != 0xC0 ) return z; /* not a lead byte */
|
|
@@ -22006,10 +22320,10 @@ static void output_c_string(FILE *out, const char *z){
|
|
|
22006
22320
|
}
|
|
22007
22321
|
|
|
22008
22322
|
/*
|
|
22009
|
-
** Output the given string as
|
|
22323
|
+
** Output the given string as quoted according to JSON quoting rules.
|
|
22010
22324
|
*/
|
|
22011
22325
|
static void output_json_string(FILE *out, const char *z, i64 n){
|
|
22012
|
-
char c;
|
|
22326
|
+
unsigned char c;
|
|
22013
22327
|
static const char *zq = "\"";
|
|
22014
22328
|
static long ctrlMask = ~0L;
|
|
22015
22329
|
static const char *zDQBS = "\"\\";
|
|
@@ -22029,7 +22343,7 @@ static void output_json_string(FILE *out, const char *z, i64 n){
|
|
|
22029
22343
|
z = pcEnd;
|
|
22030
22344
|
}
|
|
22031
22345
|
if( z >= pcLimit ) break;
|
|
22032
|
-
c = *(z++);
|
|
22346
|
+
c = (unsigned char)*(z++);
|
|
22033
22347
|
switch( c ){
|
|
22034
22348
|
case '"': case '\\':
|
|
22035
22349
|
cbsSay = (char)c;
|
|
@@ -22044,8 +22358,8 @@ static void output_json_string(FILE *out, const char *z, i64 n){
|
|
|
22044
22358
|
if( cbsSay ){
|
|
22045
22359
|
ace[1] = cbsSay;
|
|
22046
22360
|
sqlite3_fputs(ace, out);
|
|
22047
|
-
}else if( c<=0x1f ){
|
|
22048
|
-
sqlite3_fprintf(out, "u%04x", c);
|
|
22361
|
+
}else if( c<=0x1f || c>=0x7f ){
|
|
22362
|
+
sqlite3_fprintf(out, "\\u%04x", c);
|
|
22049
22363
|
}else{
|
|
22050
22364
|
ace[1] = (char)c;
|
|
22051
22365
|
sqlite3_fputs(ace+1, out);
|
|
@@ -22054,6 +22368,93 @@ static void output_json_string(FILE *out, const char *z, i64 n){
|
|
|
22054
22368
|
sqlite3_fputs(zq, out);
|
|
22055
22369
|
}
|
|
22056
22370
|
|
|
22371
|
+
/*
|
|
22372
|
+
** Escape the input string if it is needed and in accordance with
|
|
22373
|
+
** eEscMode.
|
|
22374
|
+
**
|
|
22375
|
+
** Escaping is needed if the string contains any control characters
|
|
22376
|
+
** other than \t, \n, and \r\n
|
|
22377
|
+
**
|
|
22378
|
+
** If no escaping is needed (the common case) then set *ppFree to NULL
|
|
22379
|
+
** and return the original string. If escapingn is needed, write the
|
|
22380
|
+
** escaped string into memory obtained from sqlite3_malloc64() or the
|
|
22381
|
+
** equivalent, and return the new string and set *ppFree to the new string
|
|
22382
|
+
** as well.
|
|
22383
|
+
**
|
|
22384
|
+
** The caller is responsible for freeing *ppFree if it is non-NULL in order
|
|
22385
|
+
** to reclaim memory.
|
|
22386
|
+
*/
|
|
22387
|
+
static const char *escapeOutput(
|
|
22388
|
+
ShellState *p,
|
|
22389
|
+
const char *zInX,
|
|
22390
|
+
char **ppFree
|
|
22391
|
+
){
|
|
22392
|
+
i64 i, j;
|
|
22393
|
+
i64 nCtrl = 0;
|
|
22394
|
+
unsigned char *zIn;
|
|
22395
|
+
unsigned char c;
|
|
22396
|
+
unsigned char *zOut;
|
|
22397
|
+
|
|
22398
|
+
|
|
22399
|
+
/* No escaping if disabled */
|
|
22400
|
+
if( p->eEscMode==SHELL_ESC_OFF ){
|
|
22401
|
+
*ppFree = 0;
|
|
22402
|
+
return zInX;
|
|
22403
|
+
}
|
|
22404
|
+
|
|
22405
|
+
/* Count the number of control characters in the string. */
|
|
22406
|
+
zIn = (unsigned char*)zInX;
|
|
22407
|
+
for(i=0; (c = zIn[i])!=0; i++){
|
|
22408
|
+
if( c<=0x1f
|
|
22409
|
+
&& c!='\t'
|
|
22410
|
+
&& c!='\n'
|
|
22411
|
+
&& (c!='\r' || zIn[i+1]!='\n')
|
|
22412
|
+
){
|
|
22413
|
+
nCtrl++;
|
|
22414
|
+
}
|
|
22415
|
+
}
|
|
22416
|
+
if( nCtrl==0 ){
|
|
22417
|
+
*ppFree = 0;
|
|
22418
|
+
return zInX;
|
|
22419
|
+
}
|
|
22420
|
+
if( p->eEscMode==SHELL_ESC_SYMBOL ) nCtrl *= 2;
|
|
22421
|
+
zOut = sqlite3_malloc64( i + nCtrl + 1 );
|
|
22422
|
+
shell_check_oom(zOut);
|
|
22423
|
+
for(i=j=0; (c = zIn[i])!=0; i++){
|
|
22424
|
+
if( c>0x1f
|
|
22425
|
+
|| c=='\t'
|
|
22426
|
+
|| c=='\n'
|
|
22427
|
+
|| (c=='\r' && zIn[i+1]=='\n')
|
|
22428
|
+
){
|
|
22429
|
+
continue;
|
|
22430
|
+
}
|
|
22431
|
+
if( i>0 ){
|
|
22432
|
+
memcpy(&zOut[j], zIn, i);
|
|
22433
|
+
j += i;
|
|
22434
|
+
}
|
|
22435
|
+
zIn += i+1;
|
|
22436
|
+
i = -1;
|
|
22437
|
+
switch( p->eEscMode ){
|
|
22438
|
+
case SHELL_ESC_SYMBOL:
|
|
22439
|
+
zOut[j++] = 0xe2;
|
|
22440
|
+
zOut[j++] = 0x90;
|
|
22441
|
+
zOut[j++] = 0x80+c;
|
|
22442
|
+
break;
|
|
22443
|
+
case SHELL_ESC_ASCII:
|
|
22444
|
+
zOut[j++] = '^';
|
|
22445
|
+
zOut[j++] = 0x40+c;
|
|
22446
|
+
break;
|
|
22447
|
+
}
|
|
22448
|
+
}
|
|
22449
|
+
if( i>0 ){
|
|
22450
|
+
memcpy(&zOut[j], zIn, i);
|
|
22451
|
+
j += i;
|
|
22452
|
+
}
|
|
22453
|
+
zOut[j] = 0;
|
|
22454
|
+
*ppFree = (char*)zOut;
|
|
22455
|
+
return (char*)zOut;
|
|
22456
|
+
}
|
|
22457
|
+
|
|
22057
22458
|
/*
|
|
22058
22459
|
** Output the given string with characters that are special to
|
|
22059
22460
|
** HTML escaped.
|
|
@@ -22497,8 +22898,12 @@ static int shell_callback(
|
|
|
22497
22898
|
}
|
|
22498
22899
|
if( p->cnt++>0 ) sqlite3_fputs(p->rowSeparator, p->out);
|
|
22499
22900
|
for(i=0; i<nArg; i++){
|
|
22901
|
+
char *pFree = 0;
|
|
22902
|
+
const char *pDisplay;
|
|
22903
|
+
pDisplay = escapeOutput(p, azArg[i] ? azArg[i] : p->nullValue, &pFree);
|
|
22500
22904
|
sqlite3_fprintf(p->out, "%*s = %s%s", w, azCol[i],
|
|
22501
|
-
|
|
22905
|
+
pDisplay, p->rowSeparator);
|
|
22906
|
+
if( pFree ) sqlite3_free(pFree);
|
|
22502
22907
|
}
|
|
22503
22908
|
break;
|
|
22504
22909
|
}
|
|
@@ -22568,6 +22973,8 @@ static int shell_callback(
|
|
|
22568
22973
|
char cEnd = 0;
|
|
22569
22974
|
char c;
|
|
22570
22975
|
int nLine = 0;
|
|
22976
|
+
int isIndex;
|
|
22977
|
+
int isWhere = 0;
|
|
22571
22978
|
assert( nArg==1 );
|
|
22572
22979
|
if( azArg[0]==0 ) break;
|
|
22573
22980
|
if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
|
|
@@ -22576,6 +22983,8 @@ static int shell_callback(
|
|
|
22576
22983
|
sqlite3_fprintf(p->out, "%s;\n", azArg[0]);
|
|
22577
22984
|
break;
|
|
22578
22985
|
}
|
|
22986
|
+
isIndex = sqlite3_strlike("CREATE INDEX%", azArg[0], 0)==0
|
|
22987
|
+
|| sqlite3_strlike("CREATE UNIQUE INDEX%", azArg[0], 0)==0;
|
|
22579
22988
|
z = sqlite3_mprintf("%s", azArg[0]);
|
|
22580
22989
|
shell_check_oom(z);
|
|
22581
22990
|
j = 0;
|
|
@@ -22605,14 +23014,26 @@ static int shell_callback(
|
|
|
22605
23014
|
nParen++;
|
|
22606
23015
|
}else if( c==')' ){
|
|
22607
23016
|
nParen--;
|
|
22608
|
-
if( nLine>0 && nParen==0 && j>0 ){
|
|
23017
|
+
if( nLine>0 && nParen==0 && j>0 && !isWhere ){
|
|
22609
23018
|
printSchemaLineN(p->out, z, j, "\n");
|
|
22610
23019
|
j = 0;
|
|
22611
23020
|
}
|
|
23021
|
+
}else if( (c=='w' || c=='W')
|
|
23022
|
+
&& nParen==0 && isIndex
|
|
23023
|
+
&& sqlite3_strnicmp("WHERE",&z[i],5)==0
|
|
23024
|
+
&& !IsAlnum(z[i+5]) && z[i+5]!='_' ){
|
|
23025
|
+
isWhere = 1;
|
|
23026
|
+
}else if( isWhere && (c=='A' || c=='a')
|
|
23027
|
+
&& nParen==0
|
|
23028
|
+
&& sqlite3_strnicmp("AND",&z[i],3)==0
|
|
23029
|
+
&& !IsAlnum(z[i+3]) && z[i+3]!='_' ){
|
|
23030
|
+
printSchemaLineN(p->out, z, j, "\n ");
|
|
23031
|
+
j = 0;
|
|
22612
23032
|
}
|
|
22613
23033
|
z[j++] = c;
|
|
22614
23034
|
if( nParen==1 && cEnd==0
|
|
22615
23035
|
&& (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
|
|
23036
|
+
&& !isWhere
|
|
22616
23037
|
){
|
|
22617
23038
|
if( c=='\n' ) j--;
|
|
22618
23039
|
printSchemaLineN(p->out, z, j, "\n ");
|
|
@@ -22630,15 +23051,23 @@ static int shell_callback(
|
|
|
22630
23051
|
case MODE_List: {
|
|
22631
23052
|
if( p->cnt++==0 && p->showHeader ){
|
|
22632
23053
|
for(i=0; i<nArg; i++){
|
|
22633
|
-
|
|
23054
|
+
char *z = azCol[i];
|
|
23055
|
+
char *pFree;
|
|
23056
|
+
const char *zOut = escapeOutput(p, z, &pFree);
|
|
23057
|
+
sqlite3_fprintf(p->out, "%s%s", zOut,
|
|
22634
23058
|
i==nArg-1 ? p->rowSeparator : p->colSeparator);
|
|
23059
|
+
if( pFree ) sqlite3_free(pFree);
|
|
22635
23060
|
}
|
|
22636
23061
|
}
|
|
22637
23062
|
if( azArg==0 ) break;
|
|
22638
23063
|
for(i=0; i<nArg; i++){
|
|
22639
23064
|
char *z = azArg[i];
|
|
23065
|
+
char *pFree;
|
|
23066
|
+
const char *zOut;
|
|
22640
23067
|
if( z==0 ) z = p->nullValue;
|
|
22641
|
-
|
|
23068
|
+
zOut = escapeOutput(p, z, &pFree);
|
|
23069
|
+
sqlite3_fputs(zOut, p->out);
|
|
23070
|
+
if( pFree ) sqlite3_free(pFree);
|
|
22642
23071
|
sqlite3_fputs((i<nArg-1)? p->colSeparator : p->rowSeparator, p->out);
|
|
22643
23072
|
}
|
|
22644
23073
|
break;
|
|
@@ -23757,6 +24186,7 @@ static void print_box_row_separator(
|
|
|
23757
24186
|
** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
|
|
23758
24187
|
*/
|
|
23759
24188
|
static char *translateForDisplayAndDup(
|
|
24189
|
+
ShellState *p, /* To access current settings */
|
|
23760
24190
|
const unsigned char *z, /* Input text to be transformed */
|
|
23761
24191
|
const unsigned char **pzTail, /* OUT: Tail of the input for next line */
|
|
23762
24192
|
int mxWidth, /* Max width. 0 means no limit */
|
|
@@ -23791,6 +24221,7 @@ static char *translateForDisplayAndDup(
|
|
|
23791
24221
|
j++;
|
|
23792
24222
|
continue;
|
|
23793
24223
|
}
|
|
24224
|
+
if( c==0 || c=='\n' || (c=='\r' && z[i+1]=='\n') ) break;
|
|
23794
24225
|
if( c=='\t' ){
|
|
23795
24226
|
do{
|
|
23796
24227
|
n++;
|
|
@@ -23799,16 +24230,23 @@ static char *translateForDisplayAndDup(
|
|
|
23799
24230
|
i++;
|
|
23800
24231
|
continue;
|
|
23801
24232
|
}
|
|
23802
|
-
|
|
24233
|
+
if( c==0x1b && p->eEscMode==SHELL_ESC_OFF && (k = isVt100(&z[i]))>0 ){
|
|
24234
|
+
i += k;
|
|
24235
|
+
j += k;
|
|
24236
|
+
}else{
|
|
24237
|
+
n++;
|
|
24238
|
+
j += 3;
|
|
24239
|
+
i++;
|
|
24240
|
+
}
|
|
23803
24241
|
}
|
|
23804
24242
|
if( n>=mxWidth && bWordWrap ){
|
|
23805
24243
|
/* Perhaps try to back up to a better place to break the line */
|
|
23806
24244
|
for(k=i; k>i/2; k--){
|
|
23807
|
-
if(
|
|
24245
|
+
if( IsSpace(z[k-1]) ) break;
|
|
23808
24246
|
}
|
|
23809
24247
|
if( k<=i/2 ){
|
|
23810
24248
|
for(k=i; k>i/2; k--){
|
|
23811
|
-
if(
|
|
24249
|
+
if( IsAlnum(z[k-1])!=IsAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
|
|
23812
24250
|
}
|
|
23813
24251
|
}
|
|
23814
24252
|
if( k<=i/2 ){
|
|
@@ -23846,6 +24284,7 @@ static char *translateForDisplayAndDup(
|
|
|
23846
24284
|
zOut[j++] = z[i++];
|
|
23847
24285
|
continue;
|
|
23848
24286
|
}
|
|
24287
|
+
if( c==0 ) break;
|
|
23849
24288
|
if( z[i]=='\t' ){
|
|
23850
24289
|
do{
|
|
23851
24290
|
n++;
|
|
@@ -23854,12 +24293,44 @@ static char *translateForDisplayAndDup(
|
|
|
23854
24293
|
i++;
|
|
23855
24294
|
continue;
|
|
23856
24295
|
}
|
|
23857
|
-
|
|
24296
|
+
switch( p->eEscMode ){
|
|
24297
|
+
case SHELL_ESC_SYMBOL:
|
|
24298
|
+
zOut[j++] = 0xe2;
|
|
24299
|
+
zOut[j++] = 0x90;
|
|
24300
|
+
zOut[j++] = 0x80 + c;
|
|
24301
|
+
break;
|
|
24302
|
+
case SHELL_ESC_ASCII:
|
|
24303
|
+
zOut[j++] = '^';
|
|
24304
|
+
zOut[j++] = 0x40 + c;
|
|
24305
|
+
break;
|
|
24306
|
+
case SHELL_ESC_OFF: {
|
|
24307
|
+
int nn;
|
|
24308
|
+
if( c==0x1b && (nn = isVt100(&z[i]))>0 ){
|
|
24309
|
+
memcpy(&zOut[j], &z[i], nn);
|
|
24310
|
+
j += nn;
|
|
24311
|
+
i += nn - 1;
|
|
24312
|
+
}else{
|
|
24313
|
+
zOut[j++] = c;
|
|
24314
|
+
}
|
|
24315
|
+
break;
|
|
24316
|
+
}
|
|
24317
|
+
}
|
|
24318
|
+
i++;
|
|
23858
24319
|
}
|
|
23859
24320
|
zOut[j] = 0;
|
|
23860
24321
|
return (char*)zOut;
|
|
23861
24322
|
}
|
|
23862
24323
|
|
|
24324
|
+
/* Return true if the text string z[] contains characters that need
|
|
24325
|
+
** unistr() escaping.
|
|
24326
|
+
*/
|
|
24327
|
+
static int needUnistr(const unsigned char *z){
|
|
24328
|
+
unsigned char c;
|
|
24329
|
+
if( z==0 ) return 0;
|
|
24330
|
+
while( (c = *z)>0x1f || c=='\t' || c=='\n' || (c=='\r' && z[1]=='\n') ){ z++; }
|
|
24331
|
+
return c!=0;
|
|
24332
|
+
}
|
|
24333
|
+
|
|
23863
24334
|
/* Extract the value of the i-th current column for pStmt as an SQL literal
|
|
23864
24335
|
** value. Memory is obtained from sqlite3_malloc64() and must be freed by
|
|
23865
24336
|
** the caller.
|
|
@@ -23874,7 +24345,8 @@ static char *quoted_column(sqlite3_stmt *pStmt, int i){
|
|
|
23874
24345
|
return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
|
|
23875
24346
|
}
|
|
23876
24347
|
case SQLITE_TEXT: {
|
|
23877
|
-
|
|
24348
|
+
const unsigned char *zText = sqlite3_column_text(pStmt,i);
|
|
24349
|
+
return sqlite3_mprintf(needUnistr(zText)?"%#Q":"%Q",zText);
|
|
23878
24350
|
}
|
|
23879
24351
|
case SQLITE_BLOB: {
|
|
23880
24352
|
int j;
|
|
@@ -23966,7 +24438,7 @@ static void exec_prepared_stmt_columnar(
|
|
|
23966
24438
|
if( wx<0 ) wx = -wx;
|
|
23967
24439
|
uz = (const unsigned char*)sqlite3_column_name(pStmt,i);
|
|
23968
24440
|
if( uz==0 ) uz = (u8*)"";
|
|
23969
|
-
azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw);
|
|
24441
|
+
azData[i] = translateForDisplayAndDup(p, uz, &zNotUsed, wx, bw);
|
|
23970
24442
|
}
|
|
23971
24443
|
do{
|
|
23972
24444
|
int useNextLine = bNextLine;
|
|
@@ -23990,6 +24462,7 @@ static void exec_prepared_stmt_columnar(
|
|
|
23990
24462
|
uz = azNextLine[i];
|
|
23991
24463
|
if( uz==0 ) uz = (u8*)zEmpty;
|
|
23992
24464
|
}else if( p->cmOpts.bQuote ){
|
|
24465
|
+
assert( azQuoted!=0 );
|
|
23993
24466
|
sqlite3_free(azQuoted[i]);
|
|
23994
24467
|
azQuoted[i] = quoted_column(pStmt,i);
|
|
23995
24468
|
uz = (const unsigned char*)azQuoted[i];
|
|
@@ -23998,7 +24471,7 @@ static void exec_prepared_stmt_columnar(
|
|
|
23998
24471
|
if( uz==0 ) uz = (u8*)zShowNull;
|
|
23999
24472
|
}
|
|
24000
24473
|
azData[nRow*nColumn + i]
|
|
24001
|
-
= translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
|
|
24474
|
+
= translateForDisplayAndDup(p, uz, &azNextLine[i], wx, bw);
|
|
24002
24475
|
if( azNextLine[i] ){
|
|
24003
24476
|
bNextLine = 1;
|
|
24004
24477
|
abRowDiv[nRow-1] = 0;
|
|
@@ -24786,9 +25259,9 @@ static int run_schema_dump_query(
|
|
|
24786
25259
|
}else{
|
|
24787
25260
|
rc = SQLITE_CORRUPT;
|
|
24788
25261
|
}
|
|
24789
|
-
sqlite3_free(zErr);
|
|
24790
25262
|
free(zQ2);
|
|
24791
25263
|
}
|
|
25264
|
+
sqlite3_free(zErr);
|
|
24792
25265
|
return rc;
|
|
24793
25266
|
}
|
|
24794
25267
|
|
|
@@ -24851,6 +25324,7 @@ static const char *(azHelp[]) = {
|
|
|
24851
25324
|
#if SQLITE_SHELL_HAVE_RECOVER
|
|
24852
25325
|
".dbinfo ?DB? Show status information about the database",
|
|
24853
25326
|
#endif
|
|
25327
|
+
".dbtotxt Hex dump of the database file",
|
|
24854
25328
|
".dump ?OBJECTS? Render database content as SQL",
|
|
24855
25329
|
" Options:",
|
|
24856
25330
|
" --data-only Output only INSERT statements",
|
|
@@ -24920,7 +25394,7 @@ static const char *(azHelp[]) = {
|
|
|
24920
25394
|
#else
|
|
24921
25395
|
".log on|off Turn logging on or off.",
|
|
24922
25396
|
#endif
|
|
24923
|
-
".mode MODE ?OPTIONS?
|
|
25397
|
+
".mode ?MODE? ?OPTIONS? Set output mode",
|
|
24924
25398
|
" MODE is one of:",
|
|
24925
25399
|
" ascii Columns/rows delimited by 0x1F and 0x1E",
|
|
24926
25400
|
" box Tables using unicode box-drawing characters",
|
|
@@ -24938,6 +25412,7 @@ static const char *(azHelp[]) = {
|
|
|
24938
25412
|
" tabs Tab-separated values",
|
|
24939
25413
|
" tcl TCL list elements",
|
|
24940
25414
|
" OPTIONS: (for columnar modes or insert mode):",
|
|
25415
|
+
" --escape T ctrl-char escape; T is one of: symbol, ascii, off",
|
|
24941
25416
|
" --wrap N Wrap output lines to no longer than N characters",
|
|
24942
25417
|
" --wordwrap B Wrap or not at word boundaries per B (on/off)",
|
|
24943
25418
|
" --ww Shorthand for \"--wordwrap 1\"",
|
|
@@ -24975,6 +25450,7 @@ static const char *(azHelp[]) = {
|
|
|
24975
25450
|
#ifndef SQLITE_SHELL_FIDDLE
|
|
24976
25451
|
".output ?FILE? Send output to FILE or stdout if FILE is omitted",
|
|
24977
25452
|
" If FILE begins with '|' then open it as a pipe.",
|
|
25453
|
+
" If FILE is 'off' then output is disabled.",
|
|
24978
25454
|
" Options:",
|
|
24979
25455
|
" --bom Prefix output with a UTF8 byte-order mark",
|
|
24980
25456
|
" -e Send output to the system text editor",
|
|
@@ -25100,103 +25576,104 @@ static const char *(azHelp[]) = {
|
|
|
25100
25576
|
};
|
|
25101
25577
|
|
|
25102
25578
|
/*
|
|
25103
|
-
** Output help text.
|
|
25579
|
+
** Output help text for commands that match zPattern.
|
|
25580
|
+
**
|
|
25581
|
+
** * If zPattern is NULL, then show all documented commands, but
|
|
25582
|
+
** only give a one-line summary of each.
|
|
25583
|
+
**
|
|
25584
|
+
** * If zPattern is "-a" or "-all" or "--all" then show all help text
|
|
25585
|
+
** for all commands except undocumented commands.
|
|
25586
|
+
**
|
|
25587
|
+
** * If zPattern is "0" then show all help for undocumented commands.
|
|
25588
|
+
** Undocumented commands begin with "," instead of "." in the azHelp[]
|
|
25589
|
+
** array.
|
|
25590
|
+
**
|
|
25591
|
+
** * If zPattern is a prefix for one or more documented commands, then
|
|
25592
|
+
** show help for those commands. If only a single command matches the
|
|
25593
|
+
** prefix, show the full text of the help. If multiple commands match,
|
|
25594
|
+
** Only show just the first line of each.
|
|
25104
25595
|
**
|
|
25105
|
-
**
|
|
25106
|
-
**
|
|
25107
|
-
**
|
|
25596
|
+
** * Otherwise, show the complete text of any documented command for which
|
|
25597
|
+
** zPattern is a LIKE match for any text within that command help
|
|
25598
|
+
** text.
|
|
25108
25599
|
**
|
|
25109
|
-
** Return the number
|
|
25600
|
+
** Return the number commands that match zPattern.
|
|
25110
25601
|
*/
|
|
25111
25602
|
static int showHelp(FILE *out, const char *zPattern){
|
|
25112
25603
|
int i = 0;
|
|
25113
25604
|
int j = 0;
|
|
25114
25605
|
int n = 0;
|
|
25115
25606
|
char *zPat;
|
|
25116
|
-
if( zPattern==0
|
|
25117
|
-
|
|
25118
|
-
|
|
25119
|
-
|
|
25120
|
-
|
|
25607
|
+
if( zPattern==0 ){
|
|
25608
|
+
/* Show just the first line for all help topics */
|
|
25609
|
+
zPattern = "[a-z]";
|
|
25610
|
+
}else if( cli_strcmp(zPattern,"-a")==0
|
|
25611
|
+
|| cli_strcmp(zPattern,"-all")==0
|
|
25612
|
+
|| cli_strcmp(zPattern,"--all")==0
|
|
25121
25613
|
){
|
|
25122
|
-
|
|
25123
|
-
|
|
25124
|
-
|
|
25125
|
-
|
|
25126
|
-
|
|
25127
|
-
** Otherwise => whole help for documented commands
|
|
25128
|
-
*/
|
|
25129
|
-
enum HelpWanted hw = HW_SummaryOnly;
|
|
25130
|
-
enum HelpHave hh = HH_More;
|
|
25131
|
-
if( zPattern!=0 ){
|
|
25132
|
-
hw = (*zPattern=='0')? HW_NoCull|HW_Undoc : HW_NoCull;
|
|
25133
|
-
}
|
|
25134
|
-
for(i=0; i<ArraySize(azHelp); i++){
|
|
25135
|
-
switch( azHelp[i][0] ){
|
|
25136
|
-
case ',':
|
|
25137
|
-
hh = HH_Summary|HH_Undoc;
|
|
25138
|
-
break;
|
|
25139
|
-
case '.':
|
|
25140
|
-
hh = HH_Summary;
|
|
25141
|
-
break;
|
|
25142
|
-
default:
|
|
25143
|
-
hh &= ~HH_Summary;
|
|
25144
|
-
break;
|
|
25145
|
-
}
|
|
25146
|
-
if( ((hw^hh)&HH_Undoc)==0 ){
|
|
25147
|
-
if( (hh&HH_Summary)!=0 ){
|
|
25148
|
-
sqlite3_fprintf(out, ".%s\n", azHelp[i]+1);
|
|
25149
|
-
++n;
|
|
25150
|
-
}else if( (hw&HW_SummaryOnly)==0 ){
|
|
25151
|
-
sqlite3_fprintf(out, "%s\n", azHelp[i]);
|
|
25152
|
-
}
|
|
25153
|
-
}
|
|
25154
|
-
}
|
|
25155
|
-
}else{
|
|
25156
|
-
/* Seek documented commands for which zPattern is an exact prefix */
|
|
25157
|
-
zPat = sqlite3_mprintf(".%s*", zPattern);
|
|
25158
|
-
shell_check_oom(zPat);
|
|
25614
|
+
/* Show everything except undocumented commands */
|
|
25615
|
+
zPattern = ".";
|
|
25616
|
+
}else if( cli_strcmp(zPattern,"0")==0 ){
|
|
25617
|
+
/* Show complete help text of undocumented commands */
|
|
25618
|
+
int show = 0;
|
|
25159
25619
|
for(i=0; i<ArraySize(azHelp); i++){
|
|
25160
|
-
if(
|
|
25161
|
-
|
|
25162
|
-
|
|
25620
|
+
if( azHelp[i][0]=='.' ){
|
|
25621
|
+
show = 0;
|
|
25622
|
+
}else if( azHelp[i][0]==',' ){
|
|
25623
|
+
show = 1;
|
|
25624
|
+
sqlite3_fprintf(out, ".%s\n", &azHelp[i][1]);
|
|
25163
25625
|
n++;
|
|
25626
|
+
}else if( show ){
|
|
25627
|
+
sqlite3_fprintf(out, "%s\n", azHelp[i]);
|
|
25164
25628
|
}
|
|
25165
25629
|
}
|
|
25166
|
-
|
|
25167
|
-
|
|
25168
|
-
|
|
25169
|
-
|
|
25170
|
-
|
|
25171
|
-
|
|
25172
|
-
|
|
25173
|
-
|
|
25174
|
-
|
|
25175
|
-
|
|
25176
|
-
|
|
25630
|
+
return n;
|
|
25631
|
+
}
|
|
25632
|
+
|
|
25633
|
+
/* Seek documented commands for which zPattern is an exact prefix */
|
|
25634
|
+
zPat = sqlite3_mprintf(".%s*", zPattern);
|
|
25635
|
+
shell_check_oom(zPat);
|
|
25636
|
+
for(i=0; i<ArraySize(azHelp); i++){
|
|
25637
|
+
if( sqlite3_strglob(zPat, azHelp[i])==0 ){
|
|
25638
|
+
sqlite3_fprintf(out, "%s\n", azHelp[i]);
|
|
25639
|
+
j = i+1;
|
|
25640
|
+
n++;
|
|
25177
25641
|
}
|
|
25178
|
-
|
|
25179
|
-
|
|
25180
|
-
|
|
25181
|
-
|
|
25182
|
-
|
|
25183
|
-
|
|
25184
|
-
|
|
25185
|
-
|
|
25642
|
+
}
|
|
25643
|
+
sqlite3_free(zPat);
|
|
25644
|
+
if( n ){
|
|
25645
|
+
if( n==1 ){
|
|
25646
|
+
/* when zPattern is a prefix of exactly one command, then include
|
|
25647
|
+
** the details of that command, which should begin at offset j */
|
|
25648
|
+
while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
|
|
25649
|
+
sqlite3_fprintf(out, "%s\n", azHelp[j]);
|
|
25650
|
+
j++;
|
|
25186
25651
|
}
|
|
25187
|
-
|
|
25188
|
-
|
|
25652
|
+
}
|
|
25653
|
+
return n;
|
|
25654
|
+
}
|
|
25655
|
+
|
|
25656
|
+
/* Look for documented commands that contain zPattern anywhere.
|
|
25657
|
+
** Show complete text of all documented commands that match. */
|
|
25658
|
+
zPat = sqlite3_mprintf("%%%s%%", zPattern);
|
|
25659
|
+
shell_check_oom(zPat);
|
|
25660
|
+
for(i=0; i<ArraySize(azHelp); i++){
|
|
25661
|
+
if( azHelp[i][0]==',' ){
|
|
25662
|
+
while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i;
|
|
25663
|
+
continue;
|
|
25664
|
+
}
|
|
25665
|
+
if( azHelp[i][0]=='.' ) j = i;
|
|
25666
|
+
if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
|
|
25667
|
+
sqlite3_fprintf(out, "%s\n", azHelp[j]);
|
|
25668
|
+
while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
|
|
25669
|
+
j++;
|
|
25189
25670
|
sqlite3_fprintf(out, "%s\n", azHelp[j]);
|
|
25190
|
-
while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
|
|
25191
|
-
j++;
|
|
25192
|
-
sqlite3_fprintf(out, "%s\n", azHelp[j]);
|
|
25193
|
-
}
|
|
25194
|
-
i = j;
|
|
25195
|
-
n++;
|
|
25196
25671
|
}
|
|
25672
|
+
i = j;
|
|
25673
|
+
n++;
|
|
25197
25674
|
}
|
|
25198
|
-
sqlite3_free(zPat);
|
|
25199
25675
|
}
|
|
25676
|
+
sqlite3_free(zPat);
|
|
25200
25677
|
return n;
|
|
25201
25678
|
}
|
|
25202
25679
|
|
|
@@ -25446,6 +25923,39 @@ static void shellUSleepFunc(
|
|
|
25446
25923
|
sqlite3_result_int(context, sleep);
|
|
25447
25924
|
}
|
|
25448
25925
|
|
|
25926
|
+
/*
|
|
25927
|
+
** SQL function: shell_module_schema(X)
|
|
25928
|
+
**
|
|
25929
|
+
** Return a fake schema for the table-valued function or eponymous virtual
|
|
25930
|
+
** table X.
|
|
25931
|
+
*/
|
|
25932
|
+
static void shellModuleSchema(
|
|
25933
|
+
sqlite3_context *pCtx,
|
|
25934
|
+
int nVal,
|
|
25935
|
+
sqlite3_value **apVal
|
|
25936
|
+
){
|
|
25937
|
+
const char *zName;
|
|
25938
|
+
char *zFake;
|
|
25939
|
+
ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
|
|
25940
|
+
FILE *pSavedLog = p->pLog;
|
|
25941
|
+
UNUSED_PARAMETER(nVal);
|
|
25942
|
+
zName = (const char*)sqlite3_value_text(apVal[0]);
|
|
25943
|
+
|
|
25944
|
+
/* Temporarily disable the ".log" when calling shellFakeSchema() because
|
|
25945
|
+
** shellFakeSchema() might generate failures for some ephemeral virtual
|
|
25946
|
+
** tables due to missing arguments. Example: fts4aux.
|
|
25947
|
+
** https://sqlite.org/forum/forumpost/42fe6520b803be51 */
|
|
25948
|
+
p->pLog = 0;
|
|
25949
|
+
zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
|
|
25950
|
+
p->pLog = pSavedLog;
|
|
25951
|
+
|
|
25952
|
+
if( zFake ){
|
|
25953
|
+
sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
|
|
25954
|
+
-1, sqlite3_free);
|
|
25955
|
+
free(zFake);
|
|
25956
|
+
}
|
|
25957
|
+
}
|
|
25958
|
+
|
|
25449
25959
|
/* Flags for open_db().
|
|
25450
25960
|
**
|
|
25451
25961
|
** The default behavior of open_db() is to exit(1) if the database fails to
|
|
@@ -25589,7 +26099,7 @@ static void open_db(ShellState *p, int openFlags){
|
|
|
25589
26099
|
shellDtostr, 0, 0);
|
|
25590
26100
|
sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
|
|
25591
26101
|
shellAddSchemaName, 0, 0);
|
|
25592
|
-
sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8,
|
|
26102
|
+
sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, p,
|
|
25593
26103
|
shellModuleSchema, 0, 0);
|
|
25594
26104
|
sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
|
|
25595
26105
|
shellPutsFunc, 0, 0);
|
|
@@ -25656,7 +26166,8 @@ void close_db(sqlite3 *db){
|
|
|
25656
26166
|
}
|
|
25657
26167
|
}
|
|
25658
26168
|
|
|
25659
|
-
#if HAVE_READLINE || HAVE_EDITLINE
|
|
26169
|
+
#if (HAVE_READLINE || HAVE_EDITLINE) \
|
|
26170
|
+
&& !defined(SQLITE_OMIT_READLINE_COMPLETION)
|
|
25660
26171
|
/*
|
|
25661
26172
|
** Readline completion callbacks
|
|
25662
26173
|
*/
|
|
@@ -25694,18 +26205,25 @@ static char **readline_completion(const char *zText, int iStart, int iEnd){
|
|
|
25694
26205
|
** Linenoise completion callback. Note that the 3rd argument is from
|
|
25695
26206
|
** the "msteveb" version of linenoise, not the "antirez" version.
|
|
25696
26207
|
*/
|
|
25697
|
-
static void linenoise_completion(
|
|
25698
|
-
|
|
26208
|
+
static void linenoise_completion(
|
|
26209
|
+
const char *zLine,
|
|
26210
|
+
linenoiseCompletions *lc
|
|
26211
|
+
#if HAVE_LINENOISE==2
|
|
26212
|
+
,void *pUserData
|
|
26213
|
+
#endif
|
|
26214
|
+
){
|
|
25699
26215
|
i64 nLine = strlen(zLine);
|
|
25700
26216
|
i64 i, iStart;
|
|
25701
26217
|
sqlite3_stmt *pStmt = 0;
|
|
25702
26218
|
char *zSql;
|
|
25703
26219
|
char zBuf[1000];
|
|
25704
26220
|
|
|
26221
|
+
#if HAVE_LINENOISE==2
|
|
25705
26222
|
UNUSED_PARAMETER(pUserData);
|
|
26223
|
+
#endif
|
|
25706
26224
|
if( nLine>(i64)sizeof(zBuf)-30 ) return;
|
|
25707
26225
|
if( zLine[0]=='.' || zLine[0]=='#') return;
|
|
25708
|
-
for(i=nLine-1; i>=0 && (
|
|
26226
|
+
for(i=nLine-1; i>=0 && (IsAlnum(zLine[i]) || zLine[i]=='_'); i--){}
|
|
25709
26227
|
if( i==nLine-1 ) return;
|
|
25710
26228
|
iStart = i+1;
|
|
25711
26229
|
memcpy(zBuf, zLine, iStart);
|
|
@@ -26392,14 +26910,20 @@ static void output_reset(ShellState *p){
|
|
|
26392
26910
|
/*
|
|
26393
26911
|
** Run an SQL command and return the single integer result.
|
|
26394
26912
|
*/
|
|
26395
|
-
static int db_int(sqlite3 *db, const char *zSql){
|
|
26913
|
+
static int db_int(sqlite3 *db, const char *zSql, ...){
|
|
26396
26914
|
sqlite3_stmt *pStmt;
|
|
26397
26915
|
int res = 0;
|
|
26398
|
-
|
|
26916
|
+
char *z;
|
|
26917
|
+
va_list ap;
|
|
26918
|
+
va_start(ap, zSql);
|
|
26919
|
+
z = sqlite3_vmprintf(zSql, ap);
|
|
26920
|
+
va_end(ap);
|
|
26921
|
+
sqlite3_prepare_v2(db, z, -1, &pStmt, 0);
|
|
26399
26922
|
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
|
|
26400
26923
|
res = sqlite3_column_int(pStmt,0);
|
|
26401
26924
|
}
|
|
26402
26925
|
sqlite3_finalize(pStmt);
|
|
26926
|
+
sqlite3_free(z);
|
|
26403
26927
|
return res;
|
|
26404
26928
|
}
|
|
26405
26929
|
|
|
@@ -26502,9 +27026,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
|
|
26502
27026
|
zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
|
|
26503
27027
|
}
|
|
26504
27028
|
for(i=0; i<ArraySize(aQuery); i++){
|
|
26505
|
-
|
|
26506
|
-
int val = db_int(p->db, zSql);
|
|
26507
|
-
sqlite3_free(zSql);
|
|
27029
|
+
int val = db_int(p->db, aQuery[i].zSql, zSchemaTab);
|
|
26508
27030
|
sqlite3_fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
|
|
26509
27031
|
}
|
|
26510
27032
|
sqlite3_free(zSchemaTab);
|
|
@@ -26514,6 +27036,99 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
|
|
26514
27036
|
}
|
|
26515
27037
|
#endif /* SQLITE_SHELL_HAVE_RECOVER */
|
|
26516
27038
|
|
|
27039
|
+
/*
|
|
27040
|
+
** Implementation of the ".dbtotxt" command.
|
|
27041
|
+
**
|
|
27042
|
+
** Return 1 on error, 2 to exit, and 0 otherwise.
|
|
27043
|
+
*/
|
|
27044
|
+
static int shell_dbtotxt_command(ShellState *p, int nArg, char **azArg){
|
|
27045
|
+
sqlite3_stmt *pStmt = 0;
|
|
27046
|
+
sqlite3_int64 nPage = 0;
|
|
27047
|
+
int pgSz = 0;
|
|
27048
|
+
const char *zTail;
|
|
27049
|
+
char *zName = 0;
|
|
27050
|
+
int rc, i, j;
|
|
27051
|
+
unsigned char bShow[256]; /* Characters ok to display */
|
|
27052
|
+
|
|
27053
|
+
UNUSED_PARAMETER(nArg);
|
|
27054
|
+
UNUSED_PARAMETER(azArg);
|
|
27055
|
+
memset(bShow, '.', sizeof(bShow));
|
|
27056
|
+
for(i=' '; i<='~'; i++){
|
|
27057
|
+
if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = (unsigned char)i;
|
|
27058
|
+
}
|
|
27059
|
+
rc = sqlite3_prepare_v2(p->db, "PRAGMA page_size", -1, &pStmt, 0);
|
|
27060
|
+
if( rc ) goto dbtotxt_error;
|
|
27061
|
+
rc = 0;
|
|
27062
|
+
if( sqlite3_step(pStmt)!=SQLITE_ROW ) goto dbtotxt_error;
|
|
27063
|
+
pgSz = sqlite3_column_int(pStmt, 0);
|
|
27064
|
+
sqlite3_finalize(pStmt);
|
|
27065
|
+
pStmt = 0;
|
|
27066
|
+
if( pgSz<512 || pgSz>65536 || (pgSz&(pgSz-1))!=0 ) goto dbtotxt_error;
|
|
27067
|
+
rc = sqlite3_prepare_v2(p->db, "PRAGMA page_count", -1, &pStmt, 0);
|
|
27068
|
+
if( rc ) goto dbtotxt_error;
|
|
27069
|
+
rc = 0;
|
|
27070
|
+
if( sqlite3_step(pStmt)!=SQLITE_ROW ) goto dbtotxt_error;
|
|
27071
|
+
nPage = sqlite3_column_int64(pStmt, 0);
|
|
27072
|
+
sqlite3_finalize(pStmt);
|
|
27073
|
+
pStmt = 0;
|
|
27074
|
+
if( nPage<1 ) goto dbtotxt_error;
|
|
27075
|
+
rc = sqlite3_prepare_v2(p->db, "PRAGMA databases", -1, &pStmt, 0);
|
|
27076
|
+
if( rc ) goto dbtotxt_error;
|
|
27077
|
+
if( sqlite3_step(pStmt)!=SQLITE_ROW ){
|
|
27078
|
+
zTail = "unk.db";
|
|
27079
|
+
}else{
|
|
27080
|
+
const char *zFilename = (const char*)sqlite3_column_text(pStmt, 2);
|
|
27081
|
+
if( zFilename==0 || zFilename[0]==0 ) zFilename = "unk.db";
|
|
27082
|
+
zTail = strrchr(zFilename, '/');
|
|
27083
|
+
#if defined(_WIN32)
|
|
27084
|
+
if( zTail==0 ) zTail = strrchr(zFilename, '\\');
|
|
27085
|
+
#endif
|
|
27086
|
+
}
|
|
27087
|
+
zName = strdup(zTail);
|
|
27088
|
+
shell_check_oom(zName);
|
|
27089
|
+
sqlite3_fprintf(p->out, "| size %lld pagesize %d filename %s\n",
|
|
27090
|
+
nPage*pgSz, pgSz, zName);
|
|
27091
|
+
sqlite3_finalize(pStmt);
|
|
27092
|
+
pStmt = 0;
|
|
27093
|
+
rc = sqlite3_prepare_v2(p->db,
|
|
27094
|
+
"SELECT pgno, data FROM sqlite_dbpage ORDER BY pgno", -1, &pStmt, 0);
|
|
27095
|
+
if( rc ) goto dbtotxt_error;
|
|
27096
|
+
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
|
27097
|
+
sqlite3_int64 pgno = sqlite3_column_int64(pStmt, 0);
|
|
27098
|
+
const u8 *aData = sqlite3_column_blob(pStmt, 1);
|
|
27099
|
+
int seenPageLabel = 0;
|
|
27100
|
+
for(i=0; i<pgSz; i+=16){
|
|
27101
|
+
const u8 *aLine = aData+i;
|
|
27102
|
+
for(j=0; j<16 && aLine[j]==0; j++){}
|
|
27103
|
+
if( j==16 ) continue;
|
|
27104
|
+
if( !seenPageLabel ){
|
|
27105
|
+
sqlite3_fprintf(p->out, "| page %lld offset %lld\n",pgno,(pgno-1)*pgSz);
|
|
27106
|
+
seenPageLabel = 1;
|
|
27107
|
+
}
|
|
27108
|
+
sqlite3_fprintf(p->out, "| %5d:", i);
|
|
27109
|
+
for(j=0; j<16; j++) sqlite3_fprintf(p->out, " %02x", aLine[j]);
|
|
27110
|
+
sqlite3_fprintf(p->out, " ");
|
|
27111
|
+
for(j=0; j<16; j++){
|
|
27112
|
+
unsigned char c = (unsigned char)aLine[j];
|
|
27113
|
+
sqlite3_fprintf(p->out, "%c", bShow[c]);
|
|
27114
|
+
}
|
|
27115
|
+
sqlite3_fprintf(p->out, "\n");
|
|
27116
|
+
}
|
|
27117
|
+
}
|
|
27118
|
+
sqlite3_finalize(pStmt);
|
|
27119
|
+
sqlite3_fprintf(p->out, "| end %s\n", zName);
|
|
27120
|
+
free(zName);
|
|
27121
|
+
return 0;
|
|
27122
|
+
|
|
27123
|
+
dbtotxt_error:
|
|
27124
|
+
if( rc ){
|
|
27125
|
+
sqlite3_fprintf(stderr, "ERROR: %s\n", sqlite3_errmsg(p->db));
|
|
27126
|
+
}
|
|
27127
|
+
sqlite3_finalize(pStmt);
|
|
27128
|
+
free(zName);
|
|
27129
|
+
return 1;
|
|
27130
|
+
}
|
|
27131
|
+
|
|
26517
27132
|
/*
|
|
26518
27133
|
** Print the given string as an error message.
|
|
26519
27134
|
*/
|
|
@@ -27131,7 +27746,7 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
|
|
27131
27746
|
break;
|
|
27132
27747
|
case AR_SWITCH_APPEND:
|
|
27133
27748
|
pAr->bAppend = 1;
|
|
27134
|
-
deliberate_fall_through;
|
|
27749
|
+
deliberate_fall_through; /* FALLTHRU */
|
|
27135
27750
|
case AR_SWITCH_FILE:
|
|
27136
27751
|
pAr->zFile = zArg;
|
|
27137
27752
|
break;
|
|
@@ -27848,6 +28463,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
|
|
|
27848
28463
|
sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
|
|
27849
28464
|
sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
|
|
27850
28465
|
|
|
28466
|
+
sqlite3_fprintf(pState->out, ".dbconfig defensive off\n");
|
|
27851
28467
|
sqlite3_recover_run(p);
|
|
27852
28468
|
if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
|
|
27853
28469
|
const char *zErr = sqlite3_recover_errmsg(p);
|
|
@@ -28069,8 +28685,8 @@ FROM (\
|
|
|
28069
28685
|
}else{
|
|
28070
28686
|
/* Formulate the columns spec, close the DB, zero *pDb. */
|
|
28071
28687
|
char *zColsSpec = 0;
|
|
28072
|
-
int hasDupes = db_int(*pDb, zHasDupes);
|
|
28073
|
-
int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
|
|
28688
|
+
int hasDupes = db_int(*pDb, "%s", zHasDupes);
|
|
28689
|
+
int nDigits = (hasDupes)? db_int(*pDb, "%s", zColDigits) : 0;
|
|
28074
28690
|
if( hasDupes ){
|
|
28075
28691
|
#ifdef SHELL_COLUMN_RENAME_CLEAN
|
|
28076
28692
|
rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
|
|
@@ -28085,7 +28701,7 @@ FROM (\
|
|
|
28085
28701
|
sqlite3_finalize(pStmt);
|
|
28086
28702
|
if( rc!=SQLITE_DONE ) rc_err_oom_die(SQLITE_NOMEM);
|
|
28087
28703
|
}
|
|
28088
|
-
assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
|
|
28704
|
+
assert(db_int(*pDb, "%s", zHasDupes)==0); /* Consider: remove this */
|
|
28089
28705
|
rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
|
|
28090
28706
|
rc_err_oom_die(rc);
|
|
28091
28707
|
rc = sqlite3_step(pStmt);
|
|
@@ -28519,6 +29135,9 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
28519
29135
|
const char *zName;
|
|
28520
29136
|
int op;
|
|
28521
29137
|
} aDbConfig[] = {
|
|
29138
|
+
{ "attach_create", SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE },
|
|
29139
|
+
{ "attach_write", SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE },
|
|
29140
|
+
{ "comments", SQLITE_DBCONFIG_ENABLE_COMMENTS },
|
|
28522
29141
|
{ "defensive", SQLITE_DBCONFIG_DEFENSIVE },
|
|
28523
29142
|
{ "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
|
|
28524
29143
|
{ "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
|
|
@@ -28691,6 +29310,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
28691
29310
|
}
|
|
28692
29311
|
}else
|
|
28693
29312
|
|
|
29313
|
+
if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
|
|
29314
|
+
rc = shell_dbtotxt_command(p, nArg, azArg);
|
|
29315
|
+
}else
|
|
29316
|
+
|
|
28694
29317
|
if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
|
|
28695
29318
|
if( nArg==2 ){
|
|
28696
29319
|
p->autoEQPtest = 0;
|
|
@@ -29131,7 +29754,11 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29131
29754
|
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
|
|
29132
29755
|
}
|
|
29133
29756
|
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
|
|
29134
|
-
if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0)
|
|
29757
|
+
if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0)
|
|
29758
|
+
&& 0==db_int(p->db, "SELECT count(*) FROM \"%w\".sqlite_schema"
|
|
29759
|
+
" WHERE name=%Q AND type='view'",
|
|
29760
|
+
zSchema ? zSchema : "main", zTable)
|
|
29761
|
+
){
|
|
29135
29762
|
/* Table does not exist. Create it. */
|
|
29136
29763
|
sqlite3 *dbCols = 0;
|
|
29137
29764
|
char *zRenames = 0;
|
|
@@ -29562,24 +30189,52 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29562
30189
|
const char *zMode = 0;
|
|
29563
30190
|
const char *zTabname = 0;
|
|
29564
30191
|
int i, n2;
|
|
30192
|
+
int chng = 0; /* 0x01: change to cmopts. 0x02: Any other change */
|
|
29565
30193
|
ColModeOpts cmOpts = ColModeOpts_default;
|
|
29566
30194
|
for(i=1; i<nArg; i++){
|
|
29567
30195
|
const char *z = azArg[i];
|
|
29568
30196
|
if( optionMatch(z,"wrap") && i+1<nArg ){
|
|
29569
30197
|
cmOpts.iWrap = integerValue(azArg[++i]);
|
|
30198
|
+
chng |= 1;
|
|
29570
30199
|
}else if( optionMatch(z,"ww") ){
|
|
29571
30200
|
cmOpts.bWordWrap = 1;
|
|
30201
|
+
chng |= 1;
|
|
29572
30202
|
}else if( optionMatch(z,"wordwrap") && i+1<nArg ){
|
|
29573
30203
|
cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]);
|
|
30204
|
+
chng |= 1;
|
|
29574
30205
|
}else if( optionMatch(z,"quote") ){
|
|
29575
30206
|
cmOpts.bQuote = 1;
|
|
30207
|
+
chng |= 1;
|
|
29576
30208
|
}else if( optionMatch(z,"noquote") ){
|
|
29577
30209
|
cmOpts.bQuote = 0;
|
|
30210
|
+
chng |= 1;
|
|
30211
|
+
}else if( optionMatch(z,"escape") && i+1<nArg ){
|
|
30212
|
+
/* See similar code at tag-20250224-1 */
|
|
30213
|
+
const char *zEsc = azArg[++i];
|
|
30214
|
+
int k;
|
|
30215
|
+
for(k=0; k<ArraySize(shell_EscModeNames); k++){
|
|
30216
|
+
if( sqlite3_stricmp(zEsc,shell_EscModeNames[k])==0 ){
|
|
30217
|
+
p->eEscMode = k;
|
|
30218
|
+
chng |= 2;
|
|
30219
|
+
break;
|
|
30220
|
+
}
|
|
30221
|
+
}
|
|
30222
|
+
if( k>=ArraySize(shell_EscModeNames) ){
|
|
30223
|
+
sqlite3_fprintf(stderr, "unknown control character escape mode \"%s\""
|
|
30224
|
+
" - choices:", zEsc);
|
|
30225
|
+
for(k=0; k<ArraySize(shell_EscModeNames); k++){
|
|
30226
|
+
sqlite3_fprintf(stderr, " %s", shell_EscModeNames[k]);
|
|
30227
|
+
}
|
|
30228
|
+
sqlite3_fprintf(stderr, "\n");
|
|
30229
|
+
rc = 1;
|
|
30230
|
+
goto meta_command_exit;
|
|
30231
|
+
}
|
|
29578
30232
|
}else if( zMode==0 ){
|
|
29579
30233
|
zMode = z;
|
|
29580
30234
|
/* Apply defaults for qbox pseudo-mode. If that
|
|
29581
30235
|
* overwrites already-set values, user was informed of this.
|
|
29582
30236
|
*/
|
|
30237
|
+
chng |= 1;
|
|
29583
30238
|
if( cli_strcmp(z, "qbox")==0 ){
|
|
29584
30239
|
ColModeOpts cmo = ColModeOpts_default_qbox;
|
|
29585
30240
|
zMode = "box";
|
|
@@ -29590,6 +30245,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29590
30245
|
}else if( z[0]=='-' ){
|
|
29591
30246
|
sqlite3_fprintf(stderr,"unknown option: %s\n", z);
|
|
29592
30247
|
eputz("options:\n"
|
|
30248
|
+
" --escape MODE\n"
|
|
29593
30249
|
" --noquote\n"
|
|
29594
30250
|
" --quote\n"
|
|
29595
30251
|
" --wordwrap on/off\n"
|
|
@@ -29603,20 +30259,29 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29603
30259
|
goto meta_command_exit;
|
|
29604
30260
|
}
|
|
29605
30261
|
}
|
|
29606
|
-
if(
|
|
30262
|
+
if( !chng ){
|
|
29607
30263
|
if( p->mode==MODE_Column
|
|
29608
30264
|
|| (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
|
|
29609
30265
|
){
|
|
29610
30266
|
sqlite3_fprintf(p->out,
|
|
29611
|
-
"current output mode: %s --wrap %d --wordwrap %s
|
|
30267
|
+
"current output mode: %s --wrap %d --wordwrap %s "
|
|
30268
|
+
"--%squote --escape %s\n",
|
|
29612
30269
|
modeDescr[p->mode], p->cmOpts.iWrap,
|
|
29613
30270
|
p->cmOpts.bWordWrap ? "on" : "off",
|
|
29614
|
-
p->cmOpts.bQuote ? "" : "no"
|
|
30271
|
+
p->cmOpts.bQuote ? "" : "no",
|
|
30272
|
+
shell_EscModeNames[p->eEscMode]
|
|
30273
|
+
);
|
|
29615
30274
|
}else{
|
|
29616
30275
|
sqlite3_fprintf(p->out,
|
|
29617
|
-
"current output mode: %s\n",
|
|
30276
|
+
"current output mode: %s --escape %s\n",
|
|
30277
|
+
modeDescr[p->mode],
|
|
30278
|
+
shell_EscModeNames[p->eEscMode]
|
|
30279
|
+
);
|
|
29618
30280
|
}
|
|
30281
|
+
}
|
|
30282
|
+
if( zMode==0 ){
|
|
29619
30283
|
zMode = modeDescr[p->mode];
|
|
30284
|
+
if( (chng&1)==0 ) cmOpts = p->cmOpts;
|
|
29620
30285
|
}
|
|
29621
30286
|
n2 = strlen30(zMode);
|
|
29622
30287
|
if( cli_strncmp(zMode,"lines",n2)==0 ){
|
|
@@ -29649,6 +30314,11 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29649
30314
|
}else if( cli_strncmp(zMode,"insert",n2)==0 ){
|
|
29650
30315
|
p->mode = MODE_Insert;
|
|
29651
30316
|
set_table_name(p, zTabname ? zTabname : "table");
|
|
30317
|
+
if( p->eEscMode==SHELL_ESC_OFF ){
|
|
30318
|
+
ShellSetFlag(p, SHFLG_Newlines);
|
|
30319
|
+
}else{
|
|
30320
|
+
ShellClearFlag(p, SHFLG_Newlines);
|
|
30321
|
+
}
|
|
29652
30322
|
}else if( cli_strncmp(zMode,"quote",n2)==0 ){
|
|
29653
30323
|
p->mode = MODE_Quote;
|
|
29654
30324
|
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
|
|
@@ -29810,9 +30480,9 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29810
30480
|
){
|
|
29811
30481
|
char *zFile = 0;
|
|
29812
30482
|
int i;
|
|
29813
|
-
int eMode = 0;
|
|
29814
|
-
int bOnce = 0;
|
|
29815
|
-
int bPlain = 0;
|
|
30483
|
+
int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */
|
|
30484
|
+
int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */
|
|
30485
|
+
int bPlain = 0; /* --plain option */
|
|
29816
30486
|
static const char *zBomUtf8 = "\357\273\277";
|
|
29817
30487
|
const char *zBom = 0;
|
|
29818
30488
|
|
|
@@ -29841,14 +30511,22 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29841
30511
|
}else if( c=='o' && cli_strcmp(z,"-w")==0 ){
|
|
29842
30512
|
eMode = 'w'; /* Web browser */
|
|
29843
30513
|
}else{
|
|
29844
|
-
sqlite3_fprintf(p->out,
|
|
30514
|
+
sqlite3_fprintf(p->out,
|
|
29845
30515
|
"ERROR: unknown option: \"%s\". Usage:\n", azArg[i]);
|
|
29846
30516
|
showHelp(p->out, azArg[0]);
|
|
29847
30517
|
rc = 1;
|
|
29848
30518
|
goto meta_command_exit;
|
|
29849
30519
|
}
|
|
29850
30520
|
}else if( zFile==0 && eMode==0 ){
|
|
29851
|
-
|
|
30521
|
+
if( cli_strcmp(z, "off")==0 ){
|
|
30522
|
+
#ifdef _WIN32
|
|
30523
|
+
zFile = sqlite3_mprintf("nul");
|
|
30524
|
+
#else
|
|
30525
|
+
zFile = sqlite3_mprintf("/dev/null");
|
|
30526
|
+
#endif
|
|
30527
|
+
}else{
|
|
30528
|
+
zFile = sqlite3_mprintf("%s", z);
|
|
30529
|
+
}
|
|
29852
30530
|
if( zFile && zFile[0]=='|' ){
|
|
29853
30531
|
while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
|
|
29854
30532
|
break;
|
|
@@ -29865,6 +30543,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29865
30543
|
if( zFile==0 ){
|
|
29866
30544
|
zFile = sqlite3_mprintf("stdout");
|
|
29867
30545
|
}
|
|
30546
|
+
shell_check_oom(zFile);
|
|
29868
30547
|
if( bOnce ){
|
|
29869
30548
|
p->outCount = 2;
|
|
29870
30549
|
}else{
|
|
@@ -29907,6 +30586,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29907
30586
|
#else
|
|
29908
30587
|
FILE *pfPipe = sqlite3_popen(zFile + 1, "w");
|
|
29909
30588
|
if( pfPipe==0 ){
|
|
30589
|
+
assert( stderr!=NULL );
|
|
29910
30590
|
sqlite3_fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
|
|
29911
30591
|
rc = 1;
|
|
29912
30592
|
}else{
|
|
@@ -29919,7 +30599,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
29919
30599
|
FILE *pfFile = output_file_open(zFile);
|
|
29920
30600
|
if( pfFile==0 ){
|
|
29921
30601
|
if( cli_strcmp(zFile,"off")!=0 ){
|
|
29922
|
-
|
|
30602
|
+
assert( stderr!=NULL );
|
|
30603
|
+
sqlite3_fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
|
|
29923
30604
|
}
|
|
29924
30605
|
rc = 1;
|
|
29925
30606
|
} else {
|
|
@@ -30023,6 +30704,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30023
30704
|
rc = 1;
|
|
30024
30705
|
}
|
|
30025
30706
|
}
|
|
30707
|
+
bind_prepared_stmt(p, pStmt);
|
|
30026
30708
|
sqlite3_step(pStmt);
|
|
30027
30709
|
sqlite3_finalize(pStmt);
|
|
30028
30710
|
}else
|
|
@@ -30203,7 +30885,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
30203
30885
|
}else
|
|
30204
30886
|
#endif /* !defined(SQLITE_SHELL_FIDDLE) */
|
|
30205
30887
|
|
|
30206
|
-
if( c=='s' &&
|
|
30888
|
+
if( c=='s' &&
|
|
30889
|
+
(cli_strncmp(azArg[0], "scanstats", n)==0 ||
|
|
30890
|
+
cli_strncmp(azArg[0], "scanstatus", n)==0)
|
|
30891
|
+
){
|
|
30207
30892
|
if( nArg==2 ){
|
|
30208
30893
|
if( cli_strcmp(azArg[1], "vm")==0 ){
|
|
30209
30894
|
p->scanstatsOn = 3;
|
|
@@ -31254,11 +31939,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31254
31939
|
{ 0x04000000, 1, "NullUnusedCols" },
|
|
31255
31940
|
{ 0x08000000, 1, "OnePass" },
|
|
31256
31941
|
{ 0x10000000, 1, "OrderBySubq" },
|
|
31942
|
+
{ 0x20000000, 1, "StarQuery" },
|
|
31257
31943
|
{ 0xffffffff, 0, "All" },
|
|
31258
31944
|
};
|
|
31259
31945
|
unsigned int curOpt;
|
|
31260
31946
|
unsigned int newOpt;
|
|
31947
|
+
unsigned int m;
|
|
31261
31948
|
int ii;
|
|
31949
|
+
int nOff;
|
|
31262
31950
|
sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, p->db, &curOpt);
|
|
31263
31951
|
newOpt = curOpt;
|
|
31264
31952
|
for(ii=2; ii<nArg; ii++){
|
|
@@ -31299,24 +31987,28 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31299
31987
|
}
|
|
31300
31988
|
if( curOpt!=newOpt ){
|
|
31301
31989
|
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,p->db,newOpt);
|
|
31302
|
-
}else if( nArg<3 ){
|
|
31303
|
-
curOpt = ~newOpt;
|
|
31304
31990
|
}
|
|
31305
|
-
|
|
31306
|
-
|
|
31307
|
-
}
|
|
31308
|
-
|
|
31991
|
+
for(ii=nOff=0, m=1; ii<32; ii++, m <<= 1){
|
|
31992
|
+
if( m & newOpt ) nOff++;
|
|
31993
|
+
}
|
|
31994
|
+
if( nOff<12 ){
|
|
31995
|
+
sqlite3_fputs("+All", p->out);
|
|
31996
|
+
for(ii=0; ii<ArraySize(aLabel); ii++){
|
|
31997
|
+
if( !aLabel[ii].bDsply ) continue;
|
|
31998
|
+
if( (newOpt & aLabel[ii].mask)!=0 ){
|
|
31999
|
+
sqlite3_fprintf(p->out, " -%s", aLabel[ii].zLabel);
|
|
32000
|
+
}
|
|
32001
|
+
}
|
|
31309
32002
|
}else{
|
|
31310
|
-
|
|
31311
|
-
for(
|
|
31312
|
-
|
|
31313
|
-
if(
|
|
31314
|
-
|
|
31315
|
-
sqlite3_fprintf(p->out, "%c%s\n", (newOpt & m)==0 ? '+' : '-',
|
|
31316
|
-
aLabel[jj].zLabel);
|
|
32003
|
+
sqlite3_fputs("-All", p->out);
|
|
32004
|
+
for(ii=0; ii<ArraySize(aLabel); ii++){
|
|
32005
|
+
if( !aLabel[ii].bDsply ) continue;
|
|
32006
|
+
if( (newOpt & aLabel[ii].mask)==0 ){
|
|
32007
|
+
sqlite3_fprintf(p->out, " +%s", aLabel[ii].zLabel);
|
|
31317
32008
|
}
|
|
31318
32009
|
}
|
|
31319
32010
|
}
|
|
32011
|
+
sqlite3_fputs("\n", p->out);
|
|
31320
32012
|
rc2 = isOk = 3;
|
|
31321
32013
|
break;
|
|
31322
32014
|
}
|
|
@@ -31654,69 +32346,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|
|
31654
32346
|
}else
|
|
31655
32347
|
#endif
|
|
31656
32348
|
|
|
31657
|
-
#if SQLITE_USER_AUTHENTICATION
|
|
31658
|
-
if( c=='u' && cli_strncmp(azArg[0], "user", n)==0 ){
|
|
31659
|
-
if( nArg<2 ){
|
|
31660
|
-
eputz("Usage: .user SUBCOMMAND ...\n");
|
|
31661
|
-
rc = 1;
|
|
31662
|
-
goto meta_command_exit;
|
|
31663
|
-
}
|
|
31664
|
-
open_db(p, 0);
|
|
31665
|
-
if( cli_strcmp(azArg[1],"login")==0 ){
|
|
31666
|
-
if( nArg!=4 ){
|
|
31667
|
-
eputz("Usage: .user login USER PASSWORD\n");
|
|
31668
|
-
rc = 1;
|
|
31669
|
-
goto meta_command_exit;
|
|
31670
|
-
}
|
|
31671
|
-
rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
|
|
31672
|
-
strlen30(azArg[3]));
|
|
31673
|
-
if( rc ){
|
|
31674
|
-
sqlite3_fprintf(stderr,"Authentication failed for user %s\n", azArg[2]);
|
|
31675
|
-
rc = 1;
|
|
31676
|
-
}
|
|
31677
|
-
}else if( cli_strcmp(azArg[1],"add")==0 ){
|
|
31678
|
-
if( nArg!=5 ){
|
|
31679
|
-
eputz("Usage: .user add USER PASSWORD ISADMIN\n");
|
|
31680
|
-
rc = 1;
|
|
31681
|
-
goto meta_command_exit;
|
|
31682
|
-
}
|
|
31683
|
-
rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
|
|
31684
|
-
booleanValue(azArg[4]));
|
|
31685
|
-
if( rc ){
|
|
31686
|
-
sqlite3_fprintf(stderr,"User-Add failed: %d\n", rc);
|
|
31687
|
-
rc = 1;
|
|
31688
|
-
}
|
|
31689
|
-
}else if( cli_strcmp(azArg[1],"edit")==0 ){
|
|
31690
|
-
if( nArg!=5 ){
|
|
31691
|
-
eputz("Usage: .user edit USER PASSWORD ISADMIN\n");
|
|
31692
|
-
rc = 1;
|
|
31693
|
-
goto meta_command_exit;
|
|
31694
|
-
}
|
|
31695
|
-
rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
|
|
31696
|
-
booleanValue(azArg[4]));
|
|
31697
|
-
if( rc ){
|
|
31698
|
-
sqlite3_fprintf(stderr,"User-Edit failed: %d\n", rc);
|
|
31699
|
-
rc = 1;
|
|
31700
|
-
}
|
|
31701
|
-
}else if( cli_strcmp(azArg[1],"delete")==0 ){
|
|
31702
|
-
if( nArg!=3 ){
|
|
31703
|
-
eputz("Usage: .user delete USER\n");
|
|
31704
|
-
rc = 1;
|
|
31705
|
-
goto meta_command_exit;
|
|
31706
|
-
}
|
|
31707
|
-
rc = sqlite3_user_delete(p->db, azArg[2]);
|
|
31708
|
-
if( rc ){
|
|
31709
|
-
sqlite3_fprintf(stderr,"User-Delete failed: %d\n", rc);
|
|
31710
|
-
rc = 1;
|
|
31711
|
-
}
|
|
31712
|
-
}else{
|
|
31713
|
-
eputz("Usage: .user login|add|edit|delete ...\n");
|
|
31714
|
-
rc = 1;
|
|
31715
|
-
goto meta_command_exit;
|
|
31716
|
-
}
|
|
31717
|
-
}else
|
|
31718
|
-
#endif /* SQLITE_USER_AUTHENTICATION */
|
|
31719
|
-
|
|
31720
32349
|
if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
|
|
31721
32350
|
char *zPtrSz = sizeof(void*)==8 ? "64-bit" : "32-bit";
|
|
31722
32351
|
sqlite3_fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
|
|
@@ -31840,7 +32469,6 @@ static QuickScanState quickscan(char *zLine, QuickScanState qss,
|
|
|
31840
32469
|
char cWait = (char)qss; /* intentional narrowing loss */
|
|
31841
32470
|
if( cWait==0 ){
|
|
31842
32471
|
PlainScan:
|
|
31843
|
-
assert( cWait==0 );
|
|
31844
32472
|
while( (cin = *zLine++)!=0 ){
|
|
31845
32473
|
if( IsSpace(cin) )
|
|
31846
32474
|
continue;
|
|
@@ -31866,7 +32494,7 @@ static QuickScanState quickscan(char *zLine, QuickScanState qss,
|
|
|
31866
32494
|
break;
|
|
31867
32495
|
case '[':
|
|
31868
32496
|
cin = ']';
|
|
31869
|
-
deliberate_fall_through;
|
|
32497
|
+
deliberate_fall_through; /* FALLTHRU */
|
|
31870
32498
|
case '`': case '\'': case '"':
|
|
31871
32499
|
cWait = cin;
|
|
31872
32500
|
qss = QSS_HasDark | cWait;
|
|
@@ -31892,7 +32520,6 @@ static QuickScanState quickscan(char *zLine, QuickScanState qss,
|
|
|
31892
32520
|
if( *zLine != '/' )
|
|
31893
32521
|
continue;
|
|
31894
32522
|
++zLine;
|
|
31895
|
-
cWait = 0;
|
|
31896
32523
|
CONTINUE_PROMPT_AWAITC(pst, 0);
|
|
31897
32524
|
qss = QSS_SETV(qss, 0);
|
|
31898
32525
|
goto PlainScan;
|
|
@@ -31902,9 +32529,8 @@ static QuickScanState quickscan(char *zLine, QuickScanState qss,
|
|
|
31902
32529
|
++zLine;
|
|
31903
32530
|
continue;
|
|
31904
32531
|
}
|
|
31905
|
-
deliberate_fall_through;
|
|
32532
|
+
deliberate_fall_through; /* FALLTHRU */
|
|
31906
32533
|
case ']':
|
|
31907
|
-
cWait = 0;
|
|
31908
32534
|
CONTINUE_PROMPT_AWAITC(pst, 0);
|
|
31909
32535
|
qss = QSS_SETV(qss, 0);
|
|
31910
32536
|
goto PlainScan;
|
|
@@ -31937,7 +32563,7 @@ static int line_is_command_terminator(char *zLine){
|
|
|
31937
32563
|
** out of the build if compiling with SQLITE_OMIT_COMPLETE.
|
|
31938
32564
|
*/
|
|
31939
32565
|
#ifdef SQLITE_OMIT_COMPLETE
|
|
31940
|
-
# error the CLI application is
|
|
32566
|
+
# error the CLI application is incompatible with SQLITE_OMIT_COMPLETE.
|
|
31941
32567
|
#endif
|
|
31942
32568
|
|
|
31943
32569
|
/*
|
|
@@ -32092,7 +32718,10 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
|
|
|
32092
32718
|
}
|
|
32093
32719
|
|
|
32094
32720
|
static void echo_group_input(ShellState *p, const char *zDo){
|
|
32095
|
-
if( ShellHasFlag(p, SHFLG_Echo) )
|
|
32721
|
+
if( ShellHasFlag(p, SHFLG_Echo) ){
|
|
32722
|
+
sqlite3_fprintf(p->out, "%s\n", zDo);
|
|
32723
|
+
fflush(p->out);
|
|
32724
|
+
}
|
|
32096
32725
|
}
|
|
32097
32726
|
|
|
32098
32727
|
#ifdef SQLITE_SHELL_FIDDLE
|
|
@@ -32113,7 +32742,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
|
|
|
32113
32742
|
if(!z || !*z){
|
|
32114
32743
|
return 0;
|
|
32115
32744
|
}
|
|
32116
|
-
while(*z &&
|
|
32745
|
+
while(*z && IsSpace(*z)) ++z;
|
|
32117
32746
|
zBegin = z;
|
|
32118
32747
|
for(; *z && '\n'!=*z; ++nZ, ++z){}
|
|
32119
32748
|
if(nZ>0 && '\r'==zBegin[nZ-1]){
|
|
@@ -32418,6 +33047,7 @@ static const char zOptions[] =
|
|
|
32418
33047
|
" -deserialize open the database using sqlite3_deserialize()\n"
|
|
32419
33048
|
#endif
|
|
32420
33049
|
" -echo print inputs before execution\n"
|
|
33050
|
+
" -escape T ctrl-char escape; T is one of: symbol, ascii, off\n"
|
|
32421
33051
|
" -init FILENAME read/process named file\n"
|
|
32422
33052
|
" -[no]header turn headers on or off\n"
|
|
32423
33053
|
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
|
|
@@ -32465,7 +33095,7 @@ static const char zOptions[] =
|
|
|
32465
33095
|
#endif
|
|
32466
33096
|
;
|
|
32467
33097
|
static void usage(int showDetail){
|
|
32468
|
-
sqlite3_fprintf(stderr,"Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
|
|
33098
|
+
sqlite3_fprintf(stderr,"Usage: %s [OPTIONS] [FILENAME [SQL...]]\n"
|
|
32469
33099
|
"FILENAME is the name of an SQLite database. A new database is created\n"
|
|
32470
33100
|
"if the file does not previously exist. Defaults to :memory:.\n", Argv0);
|
|
32471
33101
|
if( showDetail ){
|
|
@@ -32553,6 +33183,15 @@ static void sayAbnormalExit(void){
|
|
|
32553
33183
|
if( seenInterrupt ) eputz("Program interrupted.\n");
|
|
32554
33184
|
}
|
|
32555
33185
|
|
|
33186
|
+
/* Routine to output from vfstrace
|
|
33187
|
+
*/
|
|
33188
|
+
static int vfstraceOut(const char *z, void *pArg){
|
|
33189
|
+
ShellState *p = (ShellState*)pArg;
|
|
33190
|
+
sqlite3_fputs(z, p->out);
|
|
33191
|
+
fflush(p->out);
|
|
33192
|
+
return 1;
|
|
33193
|
+
}
|
|
33194
|
+
|
|
32556
33195
|
#ifndef SQLITE_SHELL_IS_UTF8
|
|
32557
33196
|
# if (defined(_WIN32) || defined(WIN32)) \
|
|
32558
33197
|
&& (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
|
|
@@ -32789,8 +33428,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
32789
33428
|
default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
|
|
32790
33429
|
}
|
|
32791
33430
|
}else if( cli_strcmp(z,"-vfstrace")==0 ){
|
|
32792
|
-
vfstrace_register("trace",0,(int(*)(const char*,void*))sqlite3_fputs,
|
|
32793
|
-
stderr,1);
|
|
32794
33431
|
bEnableVfstrace = 1;
|
|
32795
33432
|
#ifdef SQLITE_ENABLE_MULTIPLEX
|
|
32796
33433
|
}else if( cli_strcmp(z,"-multiplex")==0 ){
|
|
@@ -32844,6 +33481,9 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
32844
33481
|
ShellSetFlag(&data,SHFLG_TestingMode);
|
|
32845
33482
|
}else if( cli_strcmp(z,"-safe")==0 ){
|
|
32846
33483
|
/* no-op - catch this on the second pass */
|
|
33484
|
+
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
|
|
33485
|
+
/* skip over the argument */
|
|
33486
|
+
i++;
|
|
32847
33487
|
}
|
|
32848
33488
|
}
|
|
32849
33489
|
#ifndef SQLITE_SHELL_FIDDLE
|
|
@@ -32887,6 +33527,9 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
32887
33527
|
#endif
|
|
32888
33528
|
}
|
|
32889
33529
|
data.out = stdout;
|
|
33530
|
+
if( bEnableVfstrace ){
|
|
33531
|
+
vfstrace_register("trace",0,vfstraceOut, &data, 1);
|
|
33532
|
+
}
|
|
32890
33533
|
#ifndef SQLITE_SHELL_FIDDLE
|
|
32891
33534
|
sqlite3_appendvfs_init(0,0,0);
|
|
32892
33535
|
#endif
|
|
@@ -32940,6 +33583,25 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
32940
33583
|
}else if( cli_strcmp(z,"-csv")==0 ){
|
|
32941
33584
|
data.mode = MODE_Csv;
|
|
32942
33585
|
memcpy(data.colSeparator,",",2);
|
|
33586
|
+
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
|
|
33587
|
+
/* See similar code at tag-20250224-1 */
|
|
33588
|
+
const char *zEsc = argv[++i];
|
|
33589
|
+
int k;
|
|
33590
|
+
for(k=0; k<ArraySize(shell_EscModeNames); k++){
|
|
33591
|
+
if( sqlite3_stricmp(zEsc,shell_EscModeNames[k])==0 ){
|
|
33592
|
+
data.eEscMode = k;
|
|
33593
|
+
break;
|
|
33594
|
+
}
|
|
33595
|
+
}
|
|
33596
|
+
if( k>=ArraySize(shell_EscModeNames) ){
|
|
33597
|
+
sqlite3_fprintf(stderr, "unknown control character escape mode \"%s\""
|
|
33598
|
+
" - choices:", zEsc);
|
|
33599
|
+
for(k=0; k<ArraySize(shell_EscModeNames); k++){
|
|
33600
|
+
sqlite3_fprintf(stderr, " %s", shell_EscModeNames[k]);
|
|
33601
|
+
}
|
|
33602
|
+
sqlite3_fprintf(stderr, "\n");
|
|
33603
|
+
exit(1);
|
|
33604
|
+
}
|
|
32943
33605
|
#ifdef SQLITE_HAVE_ZLIB
|
|
32944
33606
|
}else if( cli_strcmp(z,"-zip")==0 ){
|
|
32945
33607
|
data.openMode = SHELL_OPEN_ZIPFILE;
|
|
@@ -33101,6 +33763,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33101
33763
|
** the database filename.
|
|
33102
33764
|
*/
|
|
33103
33765
|
for(i=0; i<nCmd; i++){
|
|
33766
|
+
echo_group_input(&data, azCmd[i]);
|
|
33104
33767
|
if( azCmd[i][0]=='.' ){
|
|
33105
33768
|
rc = do_meta_command(azCmd[i], &data);
|
|
33106
33769
|
if( rc ){
|
|
@@ -33109,7 +33772,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33109
33772
|
}
|
|
33110
33773
|
}else{
|
|
33111
33774
|
open_db(&data, 0);
|
|
33112
|
-
echo_group_input(&data, azCmd[i]);
|
|
33113
33775
|
rc = shell_exec(&data, azCmd[i], &zErrMsg);
|
|
33114
33776
|
if( zErrMsg || rc ){
|
|
33115
33777
|
if( zErrMsg!=0 ){
|
|
@@ -33131,15 +33793,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33131
33793
|
char *zHome;
|
|
33132
33794
|
char *zHistory;
|
|
33133
33795
|
int nHistory;
|
|
33134
|
-
#if CIO_WIN_WC_XLATE
|
|
33135
|
-
# define SHELL_CIO_CHAR_SET (stdout_is_console? " (UTF-16 console I/O)" : "")
|
|
33136
|
-
#else
|
|
33137
|
-
# define SHELL_CIO_CHAR_SET ""
|
|
33138
|
-
#endif
|
|
33139
33796
|
sqlite3_fprintf(stdout,
|
|
33140
|
-
"SQLite version %s %.19s
|
|
33797
|
+
"SQLite version %s %.19s\n" /*extra-version-info*/
|
|
33141
33798
|
"Enter \".help\" for usage hints.\n",
|
|
33142
|
-
sqlite3_libversion(), sqlite3_sourceid()
|
|
33799
|
+
sqlite3_libversion(), sqlite3_sourceid());
|
|
33143
33800
|
if( warnInmemoryDb ){
|
|
33144
33801
|
sputz(stdout, "Connected to a ");
|
|
33145
33802
|
printBold("transient in-memory database");
|
|
@@ -33156,9 +33813,11 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|
|
33156
33813
|
}
|
|
33157
33814
|
}
|
|
33158
33815
|
if( zHistory ){ shell_read_history(zHistory); }
|
|
33159
|
-
#if HAVE_READLINE || HAVE_EDITLINE
|
|
33816
|
+
#if (HAVE_READLINE || HAVE_EDITLINE) && !defined(SQLITE_OMIT_READLINE_COMPLETION)
|
|
33160
33817
|
rl_attempted_completion_function = readline_completion;
|
|
33161
|
-
#elif HAVE_LINENOISE
|
|
33818
|
+
#elif HAVE_LINENOISE==1
|
|
33819
|
+
linenoiseSetCompletionCallback(linenoise_completion);
|
|
33820
|
+
#elif HAVE_LINENOISE==2
|
|
33162
33821
|
linenoiseSetCompletionCallback(linenoise_completion, NULL);
|
|
33163
33822
|
#endif
|
|
33164
33823
|
data.in = 0;
|