@rocicorp/zero-sqlite3 1.0.8 → 1.0.9

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.
@@ -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 = malloc( (sz1+1)*sizeof(b1[0]) );
414
- b2 = malloc( (sz2+1)*sizeof(b1[0]) );
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
- free(b1);
423
- free(b2);
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 = malloc( (sz1+1)*sizeof(b1[0]) );
440
- b2 = malloc( (sz2+1)*sizeof(b1[0]) );
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
- free(b1);
449
- free(b2);
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 = malloc( sz*sizeof(wchar_t) );
467
+ wchar_t *b1 = sqlite3_malloc( sz*sizeof(wchar_t) );
464
468
  if( b1==0 ) return 0;
465
- _setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT);
466
- if( fgetws(b1, sz/4, in)==0 ){
467
- sqlite3_free(b1);
468
- return 0;
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
- /* When writing to the command-prompt in Windows, it is necessary
525
- ** to use O_U8TEXT to render Unicode U+0080 and greater. Go ahead
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 = malloc( (sz+1)*sizeof(wchar_t) );
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
- _setmode(_fileno(out), _O_U8TEXT);
534
- if( UseBinaryWText(out) ){
535
- piecemealOutput(b1, sz, out);
536
- }else{
537
- fputws(b1, out);
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 20
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( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
1533
+ if( !IsAlpha(zName[0]) && zName[0]!='_' ) return '"';
1486
1534
  for(i=0; zName[i]; i++){
1487
- if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
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() or
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(), readdir_r(), and closedir() POSIX functions.
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 _finddata_t data;
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(struct _finddata_t));
1914
- _snprintf(data.name, namesize, "%s\\*", dirname);
1915
- dirp->d_handle = _findfirst(data.name, &data);
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(struct _finddata_t));
1927
- if( _findnext(dirp->d_handle, &data)==-1 ){
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
- strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
1938
- dirp->d_first.d_name[NAME_MAX] = '\0';
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 _finddata_t data;
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(struct _finddata_t));
1963
- if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
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
- strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
1971
- dirp->d_next.d_name[NAME_MAX] = '\0';
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
- ** Two SQL functions are implemented:
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 mimimum-length decimal
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 maginitude comparison of embedded
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; isspace(zIn[i]); i++){}
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 funcion: decimal_sum(X)
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 occurrance of "%%s()"
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
- #if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
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
- ** ('mininum positive nornal value', x'0010000000000000'),
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, logically equivalent to n+1 where
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 overlow. */
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
- ** Return the rowid for the current row, logically equivalent to n+1 where
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
- sqlite3_uint64 n = pCur->ss.uSeqIndexNow;
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
- iMin = iMax = sqlite3_value_int64(argv[i++]);
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
- iMin = sqlite3_value_int64(argv[i++]);
6663
- if( idxNum & 0x0200 ){
6664
- if( iMin==LARGEST_INT64 ){
6665
- returnNoRows = 1;
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
- iMax = sqlite3_value_int64(argv[i++]);
6673
- if( idxNum & 0x2000 ){
6674
- if( iMax==SMALLEST_INT64 ){
6675
- returnNoRows = 1;
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
- sqlite3_uint64 d = pCur->ss.iTerm - iMax;
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
- sqlite3_uint64 d = iMin - pCur->ss.iTerm;
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://www.sqlite.org/src/info/fac496b61722daf2 */
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(ReCompiled *pRe){
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
- # ifndef chmod
7999
- # define chmod _chmod
8000
- # endif
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
- int rc = stat(zPath, pStatBuf);
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
- int rc = lstat(zPath, pStatBuf);
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(&currentTime);
8336
8407
  SystemTimeToFileTime(&currentTime, &lastAccess);
8337
- intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
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 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
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 reutrn NULL. Otherwise,
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
- va_start(ap, zFormat);
16335
- zMsg = sqlite3_vmprintf(zFormat, ap);
16336
- va_end(ap);
16337
- pInfo->xOut(zMsg, pInfo->pOutArg);
16338
- sqlite3_free(zMsg);
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
- vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d,n=%d,%s)",
16773
- pInfo->zVfsName, p->zFName, ofst, n, &zLck[1]);
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
- vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
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
- return pRoot->xCurrentTime(pRoot, pTimeOut);
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
- return pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
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 th3 most recent error code and message
17297
+ ** Return the most recent error code and message
17006
17298
  */
17007
- static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){
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
- return pRoot->xGetLastError(pRoot, iErr, zErr);
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[1]; /* Array of 32-bit bitmasks */
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 = sizeof(RecoverBitmap) + nElem*sizeof(u32);
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
- /* Open transactions on both the input and output databases. */
20994
- sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
20995
- recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
20996
- recoverExec(p, p->dbIn, "BEGIN");
20997
- if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
20998
- recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
20999
- recoverTransferSettings(p);
21000
- recoverOpenRecovery(p);
21001
- recoverCacheSchema(p);
21002
-
21003
- recoverUninstallWrapper(p);
21004
- recoverLeaveMutex();
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
- ** Find a string that is not found anywhere in z[]. Return a pointer
21787
- ** to that string.
22130
+ ** Output the given string as a quoted string using SQL quoting conventions:
21788
22131
  **
21789
- ** Try to use zA and zB first. If both of those are already found in z[]
21790
- ** then make up some string and store it in the buffer zBuf.
21791
- */
21792
- static const char *unused_string(
21793
- const char *z, /* Result must not appear anywhere in z */
21794
- const char *zA, const char *zB, /* Try these first */
21795
- char *zBuf /* Space to store a generated string */
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 *z){
22143
+ static void output_quoted_string(ShellState *p, const char *zInX){
21812
22144
  int i;
21813
- char c;
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 && c!='\''; i++){}
21818
- if( c==0 ){
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
- sqlite3_fputs("'", out);
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 && c!='\''; i++){}
21824
- if( c=='\'' ) i++;
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
- continue;
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
- sqlite3_fputs("'", out);
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
- int i;
21854
- char c;
21855
- FILE *out = p->out;
21856
- sqlite3_fsetmode(out, _O_BINARY);
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
- const char *zNL = 0;
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( (c & 0x80) == 0 ){
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 a quoted according to JSON quoting rules.
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
- azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
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
- sqlite3_fprintf(p->out, "%s%s", azCol[i],
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
- sqlite3_fputs(z, p->out);
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
- break;
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( isspace(z[k-1]) ) break;
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( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
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
- break;
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
- return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
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? Set output mode",
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
- ** zPattern describes the set of commands for which help text is provided.
25106
- ** If zPattern is NULL, then show all commands, but only give a one-line
25107
- ** description of each.
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 of matches.
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
- || zPattern[0]=='0'
25118
- || cli_strcmp(zPattern,"-a")==0
25119
- || cli_strcmp(zPattern,"-all")==0
25120
- || cli_strcmp(zPattern,"--all")==0
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
- enum HelpWanted { HW_NoCull = 0, HW_SummaryOnly = 1, HW_Undoc = 2 };
25123
- enum HelpHave { HH_Undoc = 2, HH_Summary = 1, HH_More = 0 };
25124
- /* Show all or most commands
25125
- ** *zPattern==0 => summary of documented commands only
25126
- ** *zPattern=='0' => whole help for undocumented commands
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( sqlite3_strglob(zPat, azHelp[i])==0 ){
25161
- sqlite3_fprintf(out, "%s\n", azHelp[i]);
25162
- j = i+1;
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
- sqlite3_free(zPat);
25167
- if( n ){
25168
- if( n==1 ){
25169
- /* when zPattern is a prefix of exactly one command, then include
25170
- ** the details of that command, which should begin at offset j */
25171
- while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
25172
- sqlite3_fprintf(out, "%s\n", azHelp[j]);
25173
- j++;
25174
- }
25175
- }
25176
- return n;
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
- /* Look for documented commands that contain zPattern anywhere.
25179
- ** Show complete text of all documented commands that match. */
25180
- zPat = sqlite3_mprintf("%%%s%%", zPattern);
25181
- shell_check_oom(zPat);
25182
- for(i=0; i<ArraySize(azHelp); i++){
25183
- if( azHelp[i][0]==',' ){
25184
- while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i;
25185
- continue;
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
- if( azHelp[i][0]=='.' ) j = i;
25188
- if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
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, 0,
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(const char *zLine, linenoiseCompletions *lc,
25698
- void *pUserData){
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 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
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
- sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
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
- char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
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( zMode==0 ){
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 --%squote\n",
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", modeDescr[p->mode]);
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; /* 0: .output, 1: .once, 2: .excel/.www */
29815
- int bPlain = 0; /* --plain option */
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
- zFile = sqlite3_mprintf("%s", z);
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
- sqlite3_fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
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' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
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
- if( newOpt==0 ){
31306
- sqlite3_fputs("+All\n", p->out);
31307
- }else if( newOpt==0xffffffff ){
31308
- sqlite3_fputs("-All\n", p->out);
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
- int jj;
31311
- for(jj=0; jj<ArraySize(aLabel); jj++){
31312
- unsigned int m = aLabel[jj].mask;
31313
- if( !aLabel[jj].bDsply ) continue;
31314
- if( (curOpt&m)!=(newOpt&m) ){
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 imcompatable with SQLITE_OMIT_COMPLETE.
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) ) sqlite3_fprintf(p->out, "%s\n", zDo);
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 && isspace(*z)) ++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%s\n" /*extra-version-info*/
33797
+ "SQLite version %s %.19s\n" /*extra-version-info*/
33141
33798
  "Enter \".help\" for usage hints.\n",
33142
- sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET);
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;