Fossil SCM

Sync with trunk.

florian 2026-01-10 14:16 UTC standard-cli-colors merge
Commit ceee00be59bb7e844b801bc7f4b5fabe6bdc250b6e5c579e34927bd5b308442b
118 files changed +2 -2 +7 -7 +12 -1 +1140 -519 +2565 -2637 +37 -15 +2 -2 +1 -1 +8 -7 +18 -5 +1 -1 +1 -1 +6 -6 +7 -7 +1 -1 +2 -2 +3 -3 +10 -9 +26 -2 +32 -16 +16 -19 +1 -1 +3 -3 +1 -1 +1 -1 +4 -4 +9 -9 +22 -5 +2 -2 +1 -1 +1 -1 +5 -5 +116 -64 +116 -64 +1 -1 +2 -2 +1 -1 +3 -3 +1 -1 +1 -1 +4 -4 +1 -1 +1 -1 +54 -8 +1 -1 +1 -1 +1 -1 +2 -2 +1 -1 +2 -2 +1 -1 +1 -1 +1 -1 +35 -15 +12 -1 +26 -80 +4 -4 +1 -1 +1 -1 +16 -10 +18 -10 +18 -10 +2 +3 -4 +4 -4 +1 -1 +3 -3 +2 -2 +1 -1 +1 -1 +7 -7 +3 -3 +1 -1 +3 -3 +2 -2 +2 -2 +39 -10 +43 -11 +1 -1 +1 -1 +1 -1 +1 -1 +1 -1 +1 -1 +10 -5 +23 -1 +17 -5 +21 -23 +3 -3 +1 -1 +1 -1 +1 -1 +5 -5 +12 -12 +2 -2 +1 -1 +2 -2 +1 -1 +3 -3 +4 -1 +1 -1 +7 -4 +1 -1 +5 -5 +5 -5 +1 -1 +18 -6 +7 -4 +7 -4 +3 -3 +1 -1 +1 +61 -23 +2 -2 +2 +2 +7 -2 +1 -1
~ Makefile.in ~ extsrc/cson_amalgamation.c ~ extsrc/qrf.h ~ extsrc/shell.c ~ extsrc/sqlite3.c ~ extsrc/sqlite3.h ~ src/add.c ~ src/ajax.c ~ src/alerts.c ~ src/allrepo.c ~ src/backlink.c ~ src/bisect.c ~ src/blob.c ~ src/branch.c ~ src/builtin.c ~ src/cache.c ~ src/captcha.c ~ src/cgi.c ~ src/chat.c ~ src/checkin.c ~ src/checkout.c ~ src/color.c ~ src/comformat.c ~ src/config.h ~ src/configure.c ~ src/content.c ~ src/db.c ~ src/default.css ~ src/delta.c ~ src/descendants.c ~ src/diff.c ~ src/diffcmd.c ~ src/dispatch.c ~ src/dispatch.c ~ src/event.c ~ src/export.c ~ src/file.c ~ src/fileedit.c ~ src/forum.c ~ src/fossil.confirmer.js ~ src/fossil.diff.js ~ src/fossil.dom.js ~ src/fossil.fetch.js ~ src/fossil.page.chat.js ~ src/fossil.page.fileedit.js ~ src/fossil.page.wikiedit.js ~ src/fossil.pikchr.js ~ src/fossil.wikiedit-wysiwyg.js ~ src/fshell.c ~ src/glob.c ~ src/graph.c ~ src/hname.c ~ src/hook.c ~ src/http.c ~ src/http_socket.c ~ src/http_ssl.c ~ src/json.c ~ src/json_report.c ~ src/json_status.c ~ src/login.c ~ src/main.c ~ src/main.c ~ src/main.mk ~ src/manifest.c ~ src/markdown.c ~ src/match.c ~ src/merge.c ~ src/merge3.c ~ src/name.c ~ src/piechart.c ~ src/printf.c ~ src/purge.c ~ src/report.c ~ src/schema.c ~ src/search.c ~ src/search.c ~ src/security_audit.c ~ src/setup.c ~ src/setupuser.c ~ src/sha1.c ~ src/skins.c ~ src/smtp.c ~ src/sqlcmd.c ~ src/stat.c ~ src/style.c ~ src/style.chat.css ~ src/sync.c ~ src/tag.c ~ src/tar.c ~ src/terminal.c ~ src/terminal.c ~ src/th.c ~ src/th_main.c ~ src/timeline.c ~ src/tkt.c ~ src/tktsetup.c ~ src/undo.c ~ src/unicode.c ~ src/update.c ~ src/url.c ~ src/user.c ~ src/util.c ~ src/wiki.c ~ src/wikiformat.c ~ src/wikiformat.c ~ src/winhttp.c ~ src/xfer.c ~ src/xsystem.c ~ src/xsystem.c ~ src/zip.c ~ tools/codecheck1.c ~ tools/makemake.tcl ~ tools/mkindex.c ~ win/Makefile.dmc ~ win/Makefile.mingw ~ win/Makefile.msc ~ www/changes.wiki ~ www/serverext.wiki
+2 -2
--- Makefile.in
+++ Makefile.in
@@ -75,11 +75,11 @@
7575
#
7676
# APPNAME = fossil-fuzz
7777
# may be more appropriate for fuzzing.
7878
7979
#### Emscripten stuff for optionally doing in-tree builds
80
-# of any WASM components. We store precompiled WASM in the the SCM, so
80
+# of any WASM components. We store precompiled WASM in the SCM, so
8181
# this is only useful for people who actively work on WASM
8282
# components. EMSDK_ENV refers to the "environment" script which comes
8383
# with the Emscripten SDK package:
8484
# https://emscripten.org/docs/getting_started/downloads.html
8585
EMSDK_HOME = @EMSDK_HOME@
@@ -114,11 +114,11 @@
114114
#
115115
# The "touch" is necessary to avoid a make loop due to a new upstream
116116
# feature in autosetup (GH 0a71e3c3b7) which rewrites *.in outputs only
117117
# if doing so will write different contents; otherwise, it leaves them
118118
# alone so the mtime doesn't change. This means that if you change one
119
-# our depdendencies besides Makefile.in, we'll reconfigure but Makefile
119
+# of our dependencies besides Makefile.in, we'll reconfigure but Makefile
120120
# won't change, so this rule will remain out of date, so we'll reconfig
121121
# but Makefile won't change, so we'll reconfig but... endlessly.
122122
#
123123
# This is also why we repeat the reconfig target's command here instead
124124
# of delegating to it with "$(MAKE) reconfig": having children running
125125
--- Makefile.in
+++ Makefile.in
@@ -75,11 +75,11 @@
75 #
76 # APPNAME = fossil-fuzz
77 # may be more appropriate for fuzzing.
78
79 #### Emscripten stuff for optionally doing in-tree builds
80 # of any WASM components. We store precompiled WASM in the the SCM, so
81 # this is only useful for people who actively work on WASM
82 # components. EMSDK_ENV refers to the "environment" script which comes
83 # with the Emscripten SDK package:
84 # https://emscripten.org/docs/getting_started/downloads.html
85 EMSDK_HOME = @EMSDK_HOME@
@@ -114,11 +114,11 @@
114 #
115 # The "touch" is necessary to avoid a make loop due to a new upstream
116 # feature in autosetup (GH 0a71e3c3b7) which rewrites *.in outputs only
117 # if doing so will write different contents; otherwise, it leaves them
118 # alone so the mtime doesn't change. This means that if you change one
119 # our depdendencies besides Makefile.in, we'll reconfigure but Makefile
120 # won't change, so this rule will remain out of date, so we'll reconfig
121 # but Makefile won't change, so we'll reconfig but... endlessly.
122 #
123 # This is also why we repeat the reconfig target's command here instead
124 # of delegating to it with "$(MAKE) reconfig": having children running
125
--- Makefile.in
+++ Makefile.in
@@ -75,11 +75,11 @@
75 #
76 # APPNAME = fossil-fuzz
77 # may be more appropriate for fuzzing.
78
79 #### Emscripten stuff for optionally doing in-tree builds
80 # of any WASM components. We store precompiled WASM in the SCM, so
81 # this is only useful for people who actively work on WASM
82 # components. EMSDK_ENV refers to the "environment" script which comes
83 # with the Emscripten SDK package:
84 # https://emscripten.org/docs/getting_started/downloads.html
85 EMSDK_HOME = @EMSDK_HOME@
@@ -114,11 +114,11 @@
114 #
115 # The "touch" is necessary to avoid a make loop due to a new upstream
116 # feature in autosetup (GH 0a71e3c3b7) which rewrites *.in outputs only
117 # if doing so will write different contents; otherwise, it leaves them
118 # alone so the mtime doesn't change. This means that if you change one
119 # of our dependencies besides Makefile.in, we'll reconfigure but Makefile
120 # won't change, so this rule will remain out of date, so we'll reconfig
121 # but Makefile won't change, so we'll reconfig but... endlessly.
122 #
123 # This is also why we repeat the reconfig target's command here instead
124 # of delegating to it with "$(MAKE) reconfig": having children running
125
--- extsrc/cson_amalgamation.c
+++ extsrc/cson_amalgamation.c
@@ -13,20 +13,20 @@
1313
#include <stddef.h>
1414
1515
/* Windows DLL stuff */
1616
#ifdef JSON_PARSER_DLL
1717
# ifdef _MSC_VER
18
-# ifdef JSON_PARSER_DLL_EXPORTS
19
-# define JSON_PARSER_DLL_API __declspec(dllexport)
20
-# else
21
-# define JSON_PARSER_DLL_API __declspec(dllimport)
22
-# endif
18
+# ifdef JSON_PARSER_DLL_EXPORTS
19
+# define JSON_PARSER_DLL_API __declspec(dllexport)
20
+# else
21
+# define JSON_PARSER_DLL_API __declspec(dllimport)
22
+# endif
2323
# else
24
-# define JSON_PARSER_DLL_API
24
+# define JSON_PARSER_DLL_API
2525
# endif
2626
#else
27
-# define JSON_PARSER_DLL_API
27
+# define JSON_PARSER_DLL_API
2828
#endif
2929
3030
/* Determine the integer type use to parse non-floating point numbers */
3131
#ifdef _WIN32
3232
typedef __int64 JSON_int_t;
3333
--- extsrc/cson_amalgamation.c
+++ extsrc/cson_amalgamation.c
@@ -13,20 +13,20 @@
13 #include <stddef.h>
14
15 /* Windows DLL stuff */
16 #ifdef JSON_PARSER_DLL
17 # ifdef _MSC_VER
18 # ifdef JSON_PARSER_DLL_EXPORTS
19 # define JSON_PARSER_DLL_API __declspec(dllexport)
20 # else
21 # define JSON_PARSER_DLL_API __declspec(dllimport)
22 # endif
23 # else
24 # define JSON_PARSER_DLL_API
25 # endif
26 #else
27 # define JSON_PARSER_DLL_API
28 #endif
29
30 /* Determine the integer type use to parse non-floating point numbers */
31 #ifdef _WIN32
32 typedef __int64 JSON_int_t;
33
--- extsrc/cson_amalgamation.c
+++ extsrc/cson_amalgamation.c
@@ -13,20 +13,20 @@
13 #include <stddef.h>
14
15 /* Windows DLL stuff */
16 #ifdef JSON_PARSER_DLL
17 # ifdef _MSC_VER
18 # ifdef JSON_PARSER_DLL_EXPORTS
19 # define JSON_PARSER_DLL_API __declspec(dllexport)
20 # else
21 # define JSON_PARSER_DLL_API __declspec(dllimport)
22 # endif
23 # else
24 # define JSON_PARSER_DLL_API
25 # endif
26 #else
27 # define JSON_PARSER_DLL_API
28 #endif
29
30 /* Determine the integer type use to parse non-floating point numbers */
31 #ifdef _WIN32
32 typedef __int64 JSON_int_t;
33
+12 -1
--- extsrc/qrf.h
+++ extsrc/qrf.h
@@ -35,13 +35,15 @@
3535
unsigned char bWordWrap; /* Try to wrap on word boundaries */
3636
unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
3737
unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
3838
unsigned char eTitleAlign; /* Alignment for column headers */
3939
unsigned char bSplitColumn; /* Wrap single-column output into many columns */
40
+ unsigned char bBorder; /* Show outer border in Box and Table styles */
4041
short int nWrap; /* Wrap columns wider than this */
4142
short int nScreenWidth; /* Maximum overall table width */
4243
short int nLineLimit; /* Maximum number of lines for any row */
44
+ short int nTitleLimit; /* Maximum number of characters in a title */
4345
int nCharLimit; /* Maximum number of characters in a cell */
4446
int nWidth; /* Number of entries in aWidth[] */
4547
int nAlign; /* Number of entries in aAlignment[] */
4648
short int *aWidth; /* Column widths */
4749
unsigned char *aAlign; /* Column alignments */
@@ -106,10 +108,11 @@
106108
#define QRF_TEXT_Sql 2 /* Quote as an SQL literal */
107109
#define QRF_TEXT_Csv 3 /* CSV-style quoting */
108110
#define QRF_TEXT_Html 4 /* HTML-style quoting */
109111
#define QRF_TEXT_Tcl 5 /* C/Tcl quoting */
110112
#define QRF_TEXT_Json 6 /* JSON quoting */
113
+#define QRF_TEXT_Relaxed 7 /* Relaxed SQL quoting */
111114
112115
/*
113116
** Quoting styles for BLOBs
114117
** Allowed values for sqlite3_qrf_spec.eBlob
115118
*/
@@ -173,17 +176,25 @@
173176
/*
174177
** Return an estimate of the width, in columns, for the single Unicode
175178
** character c. For normal characters, the answer is always 1. But the
176179
** estimate might be 0 or 2 for zero-width and double-width characters.
177180
**
178
-** Different display devices display unicode using different widths. So
181
+** Different devices display unicode using different widths. So
179182
** it is impossible to know that true display width with 100% accuracy.
180183
** Inaccuracies in the width estimates might cause columns to be misaligned.
181184
** Unfortunately, there is nothing we can do about that.
182185
*/
183186
int sqlite3_qrf_wcwidth(int c);
184187
188
+/*
189
+** Return an estimate of the number of display columns used by the
190
+** string in the argument. The width of individual characters is
191
+** determined as for sqlite3_qrf_wcwidth(). VT100 escape code sequences
192
+** are assigned a width of zero.
193
+*/
194
+size_t sqlite3_qrf_wcswidth(const char*);
195
+
185196
186197
#ifdef __cplusplus
187198
}
188199
#endif
189200
#endif /* !defined(SQLITE_QRF_H) */
190201
--- extsrc/qrf.h
+++ extsrc/qrf.h
@@ -35,13 +35,15 @@
35 unsigned char bWordWrap; /* Try to wrap on word boundaries */
36 unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
37 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
38 unsigned char eTitleAlign; /* Alignment for column headers */
39 unsigned char bSplitColumn; /* Wrap single-column output into many columns */
 
40 short int nWrap; /* Wrap columns wider than this */
41 short int nScreenWidth; /* Maximum overall table width */
42 short int nLineLimit; /* Maximum number of lines for any row */
 
43 int nCharLimit; /* Maximum number of characters in a cell */
44 int nWidth; /* Number of entries in aWidth[] */
45 int nAlign; /* Number of entries in aAlignment[] */
46 short int *aWidth; /* Column widths */
47 unsigned char *aAlign; /* Column alignments */
@@ -106,10 +108,11 @@
106 #define QRF_TEXT_Sql 2 /* Quote as an SQL literal */
107 #define QRF_TEXT_Csv 3 /* CSV-style quoting */
108 #define QRF_TEXT_Html 4 /* HTML-style quoting */
109 #define QRF_TEXT_Tcl 5 /* C/Tcl quoting */
110 #define QRF_TEXT_Json 6 /* JSON quoting */
 
111
112 /*
113 ** Quoting styles for BLOBs
114 ** Allowed values for sqlite3_qrf_spec.eBlob
115 */
@@ -173,17 +176,25 @@
173 /*
174 ** Return an estimate of the width, in columns, for the single Unicode
175 ** character c. For normal characters, the answer is always 1. But the
176 ** estimate might be 0 or 2 for zero-width and double-width characters.
177 **
178 ** Different display devices display unicode using different widths. So
179 ** it is impossible to know that true display width with 100% accuracy.
180 ** Inaccuracies in the width estimates might cause columns to be misaligned.
181 ** Unfortunately, there is nothing we can do about that.
182 */
183 int sqlite3_qrf_wcwidth(int c);
184
 
 
 
 
 
 
 
 
185
186 #ifdef __cplusplus
187 }
188 #endif
189 #endif /* !defined(SQLITE_QRF_H) */
190
--- extsrc/qrf.h
+++ extsrc/qrf.h
@@ -35,13 +35,15 @@
35 unsigned char bWordWrap; /* Try to wrap on word boundaries */
36 unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
37 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
38 unsigned char eTitleAlign; /* Alignment for column headers */
39 unsigned char bSplitColumn; /* Wrap single-column output into many columns */
40 unsigned char bBorder; /* Show outer border in Box and Table styles */
41 short int nWrap; /* Wrap columns wider than this */
42 short int nScreenWidth; /* Maximum overall table width */
43 short int nLineLimit; /* Maximum number of lines for any row */
44 short int nTitleLimit; /* Maximum number of characters in a title */
45 int nCharLimit; /* Maximum number of characters in a cell */
46 int nWidth; /* Number of entries in aWidth[] */
47 int nAlign; /* Number of entries in aAlignment[] */
48 short int *aWidth; /* Column widths */
49 unsigned char *aAlign; /* Column alignments */
@@ -106,10 +108,11 @@
108 #define QRF_TEXT_Sql 2 /* Quote as an SQL literal */
109 #define QRF_TEXT_Csv 3 /* CSV-style quoting */
110 #define QRF_TEXT_Html 4 /* HTML-style quoting */
111 #define QRF_TEXT_Tcl 5 /* C/Tcl quoting */
112 #define QRF_TEXT_Json 6 /* JSON quoting */
113 #define QRF_TEXT_Relaxed 7 /* Relaxed SQL quoting */
114
115 /*
116 ** Quoting styles for BLOBs
117 ** Allowed values for sqlite3_qrf_spec.eBlob
118 */
@@ -173,17 +176,25 @@
176 /*
177 ** Return an estimate of the width, in columns, for the single Unicode
178 ** character c. For normal characters, the answer is always 1. But the
179 ** estimate might be 0 or 2 for zero-width and double-width characters.
180 **
181 ** Different devices display unicode using different widths. So
182 ** it is impossible to know that true display width with 100% accuracy.
183 ** Inaccuracies in the width estimates might cause columns to be misaligned.
184 ** Unfortunately, there is nothing we can do about that.
185 */
186 int sqlite3_qrf_wcwidth(int c);
187
188 /*
189 ** Return an estimate of the number of display columns used by the
190 ** string in the argument. The width of individual characters is
191 ** determined as for sqlite3_qrf_wcwidth(). VT100 escape code sequences
192 ** are assigned a width of zero.
193 */
194 size_t sqlite3_qrf_wcswidth(const char*);
195
196
197 #ifdef __cplusplus
198 }
199 #endif
200 #endif /* !defined(SQLITE_QRF_H) */
201
+1140 -519
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -35,11 +35,11 @@
3535
** ext/recover/sqlite3recover.h
3636
** src/shell.c.in
3737
**
3838
** To modify this program, get a copy of the canonical SQLite source tree,
3939
** edit the src/shell.c.in file and/or some of the other files that are
40
-** listed above, then rerun the rerun "make shell.c".
40
+** listed above, then rerun the command "make shell.c".
4141
*/
4242
/************************* Begin src/shell.c.in ******************/
4343
/*
4444
** 2001 September 15
4545
**
@@ -49,11 +49,11 @@
4949
** May you do good and not evil.
5050
** May you find forgiveness for yourself and forgive others.
5151
** May you share freely, never taking more than you give.
5252
**
5353
*************************************************************************
54
-** This file contains code to implement the "sqlite" command line
54
+** This file contains code to implement the "sqlite3" command line
5555
** utility for accessing SQLite databases.
5656
*/
5757
#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
5858
/* This needs to come before any includes for MSVC compiler */
5959
#define _CRT_SECURE_NO_WARNINGS
@@ -71,26 +71,22 @@
7171
# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
7272
#ifdef SQLITE_CUSTOM_INCLUDE
7373
# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
7474
#endif
7575
76
-/*
77
-** Determine if we are dealing with WinRT, which provides only a subset of
78
-** the full Win32 API.
79
-*/
80
-#if !defined(SQLITE_OS_WINRT)
81
-# define SQLITE_OS_WINRT 0
82
-#endif
83
-
8476
/*
8577
** If SQLITE_SHELL_FIDDLE is defined then the shell is modified
8678
** somewhat for use as a WASM module in a web browser. This flag
8779
** should only be used when building the "fiddle" web application, as
8880
** the browser-mode build has much different user input requirements
8981
** and this build mode rewires the user input subsystem to account for
9082
** that.
9183
*/
84
+#if defined(SQLITE_SHELL_FIDDLE)
85
+# undef SQLITE_OMIT_LOAD_EXTENSION
86
+# define SQLITE_OMIT_LOAD_EXTENSION 1
87
+#endif
9288
9389
/*
9490
** Warning pragmas copied from msvc.h in the core.
9591
*/
9692
#if defined(_MSC_VER)
@@ -218,13 +214,10 @@
218214
# define deliberate_fall_through
219215
# endif
220216
#endif
221217
222218
#if defined(_WIN32) || defined(WIN32)
223
-# if SQLITE_OS_WINRT
224
-# define SQLITE_OMIT_POPEN 1
225
-# else
226219
# include <io.h>
227220
# include <fcntl.h>
228221
# define isatty(h) _isatty(h)
229222
# ifndef access
230223
# define access(f,m) _access((f),(m))
@@ -235,11 +228,10 @@
235228
# ifndef strdup
236229
# define strdup _strdup
237230
# endif
238231
# undef pclose
239232
# define pclose _pclose
240
-# endif
241233
#else
242234
/* Make sure isatty() has a prototype. */
243235
extern int isatty(int);
244236
245237
# if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI)
@@ -266,13 +258,10 @@
266258
#define ToLower(X) (char)tolower((unsigned char)X)
267259
#define IsAlnum(X) isalnum((unsigned char)X)
268260
#define IsAlpha(X) isalpha((unsigned char)X)
269261
270262
#if defined(_WIN32) || defined(WIN32)
271
-#if SQLITE_OS_WINRT
272
-#include <intrin.h>
273
-#endif
274263
#undef WIN32_LEAN_AND_MEAN
275264
#define WIN32_LEAN_AND_MEAN
276265
#include <windows.h>
277266
278267
/* string conversion routines only needed on Win32 */
@@ -704,13 +693,15 @@
704693
unsigned char bWordWrap; /* Try to wrap on word boundaries */
705694
unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
706695
unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
707696
unsigned char eTitleAlign; /* Alignment for column headers */
708697
unsigned char bSplitColumn; /* Wrap single-column output into many columns */
698
+ unsigned char bBorder; /* Show outer border in Box and Table styles */
709699
short int nWrap; /* Wrap columns wider than this */
710700
short int nScreenWidth; /* Maximum overall table width */
711701
short int nLineLimit; /* Maximum number of lines for any row */
702
+ short int nTitleLimit; /* Maximum number of characters in a title */
712703
int nCharLimit; /* Maximum number of characters in a cell */
713704
int nWidth; /* Number of entries in aWidth[] */
714705
int nAlign; /* Number of entries in aAlignment[] */
715706
short int *aWidth; /* Column widths */
716707
unsigned char *aAlign; /* Column alignments */
@@ -775,10 +766,11 @@
775766
#define QRF_TEXT_Sql 2 /* Quote as an SQL literal */
776767
#define QRF_TEXT_Csv 3 /* CSV-style quoting */
777768
#define QRF_TEXT_Html 4 /* HTML-style quoting */
778769
#define QRF_TEXT_Tcl 5 /* C/Tcl quoting */
779770
#define QRF_TEXT_Json 6 /* JSON quoting */
771
+#define QRF_TEXT_Relaxed 7 /* Relaxed SQL quoting */
780772
781773
/*
782774
** Quoting styles for BLOBs
783775
** Allowed values for sqlite3_qrf_spec.eBlob
784776
*/
@@ -842,17 +834,25 @@
842834
/*
843835
** Return an estimate of the width, in columns, for the single Unicode
844836
** character c. For normal characters, the answer is always 1. But the
845837
** estimate might be 0 or 2 for zero-width and double-width characters.
846838
**
847
-** Different display devices display unicode using different widths. So
839
+** Different devices display unicode using different widths. So
848840
** it is impossible to know that true display width with 100% accuracy.
849841
** Inaccuracies in the width estimates might cause columns to be misaligned.
850842
** Unfortunately, there is nothing we can do about that.
851843
*/
852844
int sqlite3_qrf_wcwidth(int c);
853845
846
+/*
847
+** Return an estimate of the number of display columns used by the
848
+** string in the argument. The width of individual characters is
849
+** determined as for sqlite3_qrf_wcwidth(). VT100 escape code sequences
850
+** are assigned a width of zero.
851
+*/
852
+size_t sqlite3_qrf_wcswidth(const char*);
853
+
854854
855855
#ifdef __cplusplus
856856
}
857857
#endif
858858
#endif /* !defined(SQLITE_QRF_H) */
@@ -915,11 +915,11 @@
915915
int mxWidth; /* Screen width */
916916
int mxHeight; /* nLineLimit */
917917
union {
918918
struct { /* Content for QRF_STYLE_Line */
919919
int mxColWth; /* Maximum display width of any column */
920
- const char **azCol; /* Names of output columns (MODE_Line) */
920
+ char **azCol; /* Names of output columns (MODE_Line) */
921921
} sLine;
922922
qrfEQPGraph *pGraph; /* EQP graph (Eqp, Stats, and StatsEst) */
923923
struct { /* Content for QRF_STYLE_Explain */
924924
int nIndent; /* Slots allocated for aiIndent */
925925
int iIndent; /* Current slot */
@@ -961,10 +961,19 @@
961961
#define qrfSpace(x) ((qrfCType[(unsigned char)x]&1)!=0)
962962
#define qrfDigit(x) ((qrfCType[(unsigned char)x]&2)!=0)
963963
#define qrfAlpha(x) ((qrfCType[(unsigned char)x]&4)!=0)
964964
#define qrfAlnum(x) ((qrfCType[(unsigned char)x]&6)!=0)
965965
966
+#ifndef deliberate_fall_through
967
+/* Quiet some compilers about some of our intentional code. */
968
+# if defined(GCC_VERSION) && GCC_VERSION>=7000000
969
+# define deliberate_fall_through __attribute__((fallthrough));
970
+# else
971
+# define deliberate_fall_through
972
+# endif
973
+#endif
974
+
966975
/*
967976
** Set an error code and error message.
968977
*/
969978
static void qrfError(
970979
Qrf *p, /* Query result state */
@@ -990,10 +999,19 @@
990999
*/
9911000
static void qrfOom(Qrf *p){
9921001
qrfError(p, SQLITE_NOMEM, "out of memory");
9931002
}
9941003
1004
+/*
1005
+** Transfer any error in pStr over into p.
1006
+*/
1007
+static void qrfStrErr(Qrf *p, sqlite3_str *pStr){
1008
+ int rc = pStr ? sqlite3_str_errcode(pStr) : 0;
1009
+ if( rc ){
1010
+ qrfError(p, rc, sqlite3_errstr(rc));
1011
+ }
1012
+}
9951013
9961014
9971015
/*
9981016
** Add a new entry to the EXPLAIN QUERY PLAN data
9991017
*/
@@ -1212,11 +1230,13 @@
12121230
sqlite3_str_reset(pLine);
12131231
}else{
12141232
qrfEqpAppend(p, iId, iPid, zo);
12151233
}
12161234
}
1235
+ qrfStrErr(p, pLine);
12171236
sqlite3_free(sqlite3_str_finish(pLine));
1237
+ qrfStrErr(p, pStats);
12181238
sqlite3_free(sqlite3_str_finish(pStats));
12191239
#endif
12201240
}
12211241
12221242
@@ -1287,11 +1307,11 @@
12871307
{1, 0x00ece}, {0, 0x00f18}, {1, 0x00f1a}, {0, 0x00f35}, {1, 0x00f36},
12881308
{0, 0x00f37}, {1, 0x00f38}, {0, 0x00f39}, {1, 0x00f3a}, {0, 0x00f71},
12891309
{1, 0x00f7f}, {0, 0x00f80}, {1, 0x00f85}, {0, 0x00f86}, {1, 0x00f88},
12901310
{0, 0x00f90}, {1, 0x00f98}, {0, 0x00f99}, {1, 0x00fbd}, {0, 0x00fc6},
12911311
{1, 0x00fc7}, {0, 0x0102d}, {1, 0x01031}, {0, 0x01032}, {1, 0x01033},
1292
- {0, 0x01036}, {1, 0x01038}, {0, 0x01039}, {1, 0x0103a}, {0, 0x01058},
1312
+ {0, 0x01036}, {1, 0x0103b}, {0, 0x01058},
12931313
{1, 0x0105a}, {2, 0x01100}, {0, 0x01160}, {1, 0x01200}, {0, 0x0135f},
12941314
{1, 0x01360}, {0, 0x01712}, {1, 0x01715}, {0, 0x01732}, {1, 0x01735},
12951315
{0, 0x01752}, {1, 0x01754}, {0, 0x01772}, {1, 0x01774}, {0, 0x017b4},
12961316
{1, 0x017b6}, {0, 0x017b7}, {1, 0x017be}, {0, 0x017c6}, {1, 0x017c7},
12971317
{0, 0x017c9}, {1, 0x017d4}, {0, 0x017dd}, {1, 0x017de}, {0, 0x0180b},
@@ -1330,11 +1350,11 @@
13301350
*/
13311351
int sqlite3_qrf_wcwidth(int c){
13321352
int iFirst, iLast;
13331353
13341354
/* Fast path for common characters */
1335
- if( c<=0x300 ) return 1;
1355
+ if( c<0x300 ) return 1;
13361356
13371357
/* The general case */
13381358
iFirst = 0;
13391359
iLast = sizeof(aQrfUWidth)/sizeof(aQrfUWidth[0]) - 1;
13401360
while( iFirst<iLast-1 ){
@@ -1396,17 +1416,24 @@
13961416
return i+1;
13971417
}
13981418
13991419
/*
14001420
** Return the length of a string in display characters.
1401
-** Multibyte UTF8 characters count as a single character
1402
-** for single-width characters, or as two characters for
1403
-** double-width characters.
1421
+**
1422
+** Most characters of the input string count as 1, including
1423
+** multi-byte UTF8 characters. However, zero-width unicode
1424
+** characters and VT100 escape sequences count as zero, and
1425
+** double-width characters count as two.
1426
+**
1427
+** The definition of "zero-width" and "double-width" characters
1428
+** is not precise. It depends on the output device, to some extent,
1429
+** and it varies according to the Unicode version. This routine
1430
+** makes the best guess that it can.
14041431
*/
1405
-static int qrfDisplayLength(const char *zIn){
1432
+size_t sqlite3_qrf_wcswidth(const char *zIn){
14061433
const unsigned char *z = (const unsigned char*)zIn;
1407
- int n = 0;
1434
+ size_t n = 0;
14081435
while( *z ){
14091436
if( z[0]<' ' ){
14101437
int k;
14111438
if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
14121439
z += k;
@@ -1436,15 +1463,18 @@
14361463
** Write the number of newlines into *pnNL. So, *pnNL will
14371464
** return 0 if everything fits on one line, or positive it
14381465
** it will need to be split.
14391466
*/
14401467
static int qrfDisplayWidth(const char *zIn, sqlite3_int64 nByte, int *pnNL){
1441
- const unsigned char *z = (const unsigned char*)zIn;
1442
- const unsigned char *zEnd = &z[nByte];
1468
+ const unsigned char *z;
1469
+ const unsigned char *zEnd;
14431470
int mx = 0;
14441471
int n = 0;
14451472
int nNL = 0;
1473
+ if( zIn==0 ) zIn = "";
1474
+ z = (const unsigned char*)zIn;
1475
+ zEnd = &z[nByte];
14461476
while( z<zEnd ){
14471477
if( z[0]<' ' ){
14481478
int k;
14491479
if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
14501480
z += k;
@@ -1551,10 +1581,51 @@
15511581
zOut[j++] = '^';
15521582
zOut[j++] = 0x40+c;
15531583
}
15541584
}
15551585
}
1586
+
1587
+/*
1588
+** Determine if the string z[] can be shown as plain text. Return true
1589
+** if z[] is unambiguously text. Return false if z[] needs to be
1590
+** quoted.
1591
+**
1592
+** All of the following must be true in order for z[] to be relaxable:
1593
+**
1594
+** (1) z[] does not begin or end with ' or whitespace
1595
+** (2) z[] is not the same as the NULL rendering
1596
+** (3) z[] does not looks like a numeric literal
1597
+*/
1598
+static int qrfRelaxable(Qrf *p, const char *z){
1599
+ size_t i, n;
1600
+ if( z[0]=='\'' || qrfSpace(z[0]) ) return 0;
1601
+ if( z[0]==0 ){
1602
+ return (p->spec.zNull!=0 && p->spec.zNull[0]!=0);
1603
+ }
1604
+ n = strlen(z);
1605
+ if( n==0 || z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0;
1606
+ if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0;
1607
+ i = (z[0]=='-' || z[0]=='+');
1608
+ if( strcmp(z+i,"Inf")==0 ) return 0;
1609
+ if( !qrfDigit(z[i]) ) return 1;
1610
+ i++;
1611
+ while( qrfDigit(z[i]) ){ i++; }
1612
+ if( z[i]==0 ) return 0;
1613
+ if( z[i]=='.' ){
1614
+ i++;
1615
+ while( qrfDigit(z[i]) ){ i++; }
1616
+ if( z[i]==0 ) return 0;
1617
+ }
1618
+ if( z[i]=='e' || z[i]=='E' ){
1619
+ i++;
1620
+ if( z[i]=='+' || z[i]=='-' ){ i++; }
1621
+ if( !qrfDigit(z[i]) ) return 1;
1622
+ i++;
1623
+ while( qrfDigit(z[i]) ){ i++; }
1624
+ }
1625
+ return z[i]!=0;
1626
+}
15561627
15571628
/*
15581629
** If a field contains any character identified by a 1 in the following
15591630
** array, then the string must be quoted for CSV.
15601631
*/
@@ -1581,10 +1652,16 @@
15811652
** Encode text appropriately and append it to pOut.
15821653
*/
15831654
static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){
15841655
int iStart = sqlite3_str_length(pOut);
15851656
switch( p->spec.eText ){
1657
+ case QRF_TEXT_Relaxed:
1658
+ if( qrfRelaxable(p, zTxt) ){
1659
+ sqlite3_str_appendall(pOut, zTxt);
1660
+ break;
1661
+ }
1662
+ deliberate_fall_through; /* FALLTHRU */
15861663
case QRF_TEXT_Sql: {
15871664
if( p->spec.eEsc==QRF_ESC_Off ){
15881665
sqlite3_str_appendf(pOut, "%Q", zTxt);
15891666
}else{
15901667
sqlite3_str_appendf(pOut, "%#Q", zTxt);
@@ -1739,10 +1816,57 @@
17391816
return (const char*)sqlite3_column_text(p->pJTrans, 0);
17401817
}else{
17411818
return 0;
17421819
}
17431820
}
1821
+
1822
+/*
1823
+** Adjust the input string zIn[] such that it is no more than N display
1824
+** characters wide. If it is wider than that, then truncate and add
1825
+** ellipsis. Or if zIn[] contains a \r or \n, truncate at that point,
1826
+** adding ellipsis. Embedded tabs in zIn[] are converted into ordinary
1827
+** spaces.
1828
+**
1829
+** Return this display width of the modified title string.
1830
+*/
1831
+static int qrfTitleLimit(char *zIn, int N){
1832
+ unsigned char *z = (unsigned char*)zIn;
1833
+ int n = 0;
1834
+ unsigned char *zEllipsis = 0;
1835
+ while( 1 /*exit-by-break*/ ){
1836
+ if( z[0]<' ' ){
1837
+ int k;
1838
+ if( z[0]==0 ){
1839
+ zEllipsis = 0;
1840
+ break;
1841
+ }else if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
1842
+ z += k;
1843
+ }else if( z[0]=='\t' ){
1844
+ z[0] = ' ';
1845
+ }else if( z[0]=='\n' || z[0]=='\r' ){
1846
+ z[0] = ' ';
1847
+ }else{
1848
+ z++;
1849
+ }
1850
+ }else if( (0x80&z[0])==0 ){
1851
+ if( n>=(N-3) && zEllipsis==0 ) zEllipsis = z;
1852
+ if( n==N ){ z[0] = 0; break; }
1853
+ n++;
1854
+ z++;
1855
+ }else{
1856
+ int u = 0;
1857
+ int len = sqlite3_qrf_decode_utf8(z, &u);
1858
+ if( n+len>(N-3) && zEllipsis==0 ) zEllipsis = z;
1859
+ if( n+len>N ){ z[0] = 0; break; }
1860
+ z += len;
1861
+ n += sqlite3_qrf_wcwidth(u);
1862
+ }
1863
+ }
1864
+ if( zEllipsis && N>=3 ) memcpy(zEllipsis,"...",4);
1865
+ return n;
1866
+}
1867
+
17441868
17451869
/*
17461870
** Render value pVal into pOut
17471871
*/
17481872
static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){
@@ -2124,40 +2248,10 @@
21242248
}
21252249
}
21262250
sqlite3_str_append(pOut, (const char*)z, i);
21272251
}
21282252
2129
-/*
2130
-** Output horizontally justified text into pOut. The text is the
2131
-** first nVal bytes of zVal. Include nWS bytes of whitespace, either
2132
-** split between both sides, or on the left, or on the right, depending
2133
-** on eAlign.
2134
-*/
2135
-static void qrfPrintAligned(
2136
- sqlite3_str *pOut, /* Append text here */
2137
- const char *zVal, /* Text to append */
2138
- int nVal, /* Use only the first nVal bytes of zVal[] */
2139
- int nWS, /* Whitespace for horizonal alignment */
2140
- unsigned char eAlign /* Alignment type */
2141
-){
2142
- eAlign &= QRF_ALIGN_HMASK;
2143
- if( eAlign==QRF_ALIGN_Center ){
2144
- /* Center the text */
2145
- sqlite3_str_appendchar(pOut, nWS/2, ' ');
2146
- qrfAppendWithTabs(pOut, zVal, nVal);
2147
- sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
2148
- }else if( eAlign==QRF_ALIGN_Right){
2149
- /* Right justify the text */
2150
- sqlite3_str_appendchar(pOut, nWS, ' ');
2151
- qrfAppendWithTabs(pOut, zVal, nVal);
2152
- }else{
2153
- /* Left justify the next */
2154
- qrfAppendWithTabs(pOut, zVal, nVal);
2155
- sqlite3_str_appendchar(pOut, nWS, ' ');
2156
- }
2157
-}
2158
-
21592253
/*
21602254
** GCC does not define the offsetof() macro so we'll have to do it
21612255
** ourselves.
21622256
*/
21632257
#ifndef offsetof
@@ -2177,27 +2271,60 @@
21772271
sqlite3_int64 nRow; /* Number of rows */
21782272
sqlite3_int64 nAlloc; /* Number of cells allocated */
21792273
sqlite3_int64 n; /* Number of cells. nCol*nRow */
21802274
char **az; /* Content of all cells */
21812275
int *aiWth; /* Width of each cell */
2276
+ unsigned char *abNum; /* True for each numeric cell */
21822277
struct qrfPerCol { /* Per-column data */
21832278
char *z; /* Cache of text for current row */
21842279
int w; /* Computed width of this column */
21852280
int mxW; /* Maximum natural (unwrapped) width */
21862281
unsigned char e; /* Alignment */
21872282
unsigned char fx; /* Width is fixed */
2283
+ unsigned char bNum; /* True if is numeric */
21882284
} *a; /* One per column */
21892285
};
2286
+
2287
+/*
2288
+** Output horizontally justified text into pOut. The text is the
2289
+** first nVal bytes of zVal. Include nWS bytes of whitespace, either
2290
+** split between both sides, or on the left, or on the right, depending
2291
+** on eAlign.
2292
+*/
2293
+static void qrfPrintAligned(
2294
+ sqlite3_str *pOut, /* Append text here */
2295
+ struct qrfPerCol *pCol, /* Information about the text to print */
2296
+ int nVal, /* Use only the first nVal bytes of zVal[] */
2297
+ int nWS /* Whitespace for horizonal alignment */
2298
+){
2299
+ unsigned char eAlign = pCol->e & QRF_ALIGN_HMASK;
2300
+ if( eAlign==QRF_Auto && pCol->bNum ) eAlign = QRF_ALIGN_Right;
2301
+ if( eAlign==QRF_ALIGN_Center ){
2302
+ /* Center the text */
2303
+ sqlite3_str_appendchar(pOut, nWS/2, ' ');
2304
+ qrfAppendWithTabs(pOut, pCol->z, nVal);
2305
+ sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
2306
+ }else if( eAlign==QRF_ALIGN_Right ){
2307
+ /* Right justify the text */
2308
+ sqlite3_str_appendchar(pOut, nWS, ' ');
2309
+ qrfAppendWithTabs(pOut, pCol->z, nVal);
2310
+ }else{
2311
+ /* Left justify the text */
2312
+ qrfAppendWithTabs(pOut, pCol->z, nVal);
2313
+ sqlite3_str_appendchar(pOut, nWS, ' ');
2314
+ }
2315
+}
21902316
21912317
/*
21922318
** Free all the memory allocates in the qrfColData object
21932319
*/
21942320
static void qrfColDataFree(qrfColData *p){
21952321
sqlite3_int64 i;
21962322
for(i=0; i<p->n; i++) sqlite3_free(p->az[i]);
21972323
sqlite3_free(p->az);
21982324
sqlite3_free(p->aiWth);
2325
+ sqlite3_free(p->abNum);
21992326
sqlite3_free(p->a);
22002327
memset(p, 0, sizeof(*p));
22012328
}
22022329
22032330
/*
@@ -2205,10 +2332,11 @@
22052332
** Return non-zero if a memory allocation fails.
22062333
*/
22072334
static int qrfColDataEnlarge(qrfColData *p){
22082335
char **azData;
22092336
int *aiWth;
2337
+ unsigned char *abNum;
22102338
p->nAlloc = 2*p->nAlloc + 10*p->nCol;
22112339
azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*));
22122340
if( azData==0 ){
22132341
qrfOom(p->p);
22142342
qrfColDataFree(p);
@@ -2220,26 +2348,38 @@
22202348
qrfOom(p->p);
22212349
qrfColDataFree(p);
22222350
return 1;
22232351
}
22242352
p->aiWth = aiWth;
2353
+ abNum = sqlite3_realloc64(p->abNum, p->nAlloc);
2354
+ if( abNum==0 ){
2355
+ qrfOom(p->p);
2356
+ qrfColDataFree(p);
2357
+ return 1;
2358
+ }
2359
+ p->abNum = abNum;
22252360
return 0;
22262361
}
22272362
22282363
/*
22292364
** Print a markdown or table-style row separator using ascii-art
22302365
*/
22312366
static void qrfRowSeparator(sqlite3_str *pOut, qrfColData *p, char cSep){
22322367
int i;
22332368
if( p->nCol>0 ){
2234
- sqlite3_str_append(pOut, &cSep, 1);
2369
+ int useBorder = p->p->spec.bBorder!=QRF_No;
2370
+ if( useBorder ){
2371
+ sqlite3_str_append(pOut, &cSep, 1);
2372
+ }
22352373
sqlite3_str_appendchar(pOut, p->a[0].w+p->nMargin, '-');
22362374
for(i=1; i<p->nCol; i++){
22372375
sqlite3_str_append(pOut, &cSep, 1);
22382376
sqlite3_str_appendchar(pOut, p->a[i].w+p->nMargin, '-');
22392377
}
2240
- sqlite3_str_append(pOut, &cSep, 1);
2378
+ if( useBorder ){
2379
+ sqlite3_str_append(pOut, &cSep, 1);
2380
+ }
22412381
}
22422382
sqlite3_str_append(pOut, "\n", 1);
22432383
}
22442384
22452385
/*
@@ -2265,24 +2405,37 @@
22652405
#define BOX_134 "\342\224\244" /* U+2524 -| */
22662406
#define BOX_234 "\342\224\254" /* U+252c -,- */
22672407
#define BOX_124 "\342\224\264" /* U+2534 -'- */
22682408
#define BOX_1234 "\342\224\274" /* U+253c -|- */
22692409
2410
+/* Rounded corners: */
2411
+#define BOX_R12 "\342\225\260" /* U+2570 '- */
2412
+#define BOX_R23 "\342\225\255" /* U+256d ,- */
2413
+#define BOX_R34 "\342\225\256" /* U+256e -, */
2414
+#define BOX_R14 "\342\225\257" /* U+256f -' */
2415
+
2416
+/* Doubled horizontal lines: */
2417
+#define DBL_24 "\342\225\220" /* U+2550 === */
2418
+#define DBL_123 "\342\225\236" /* U+255e |= */
2419
+#define DBL_134 "\342\225\241" /* U+2561 =| */
2420
+#define DBL_1234 "\342\225\252" /* U+256a =|= */
2421
+
22702422
/* Draw horizontal line N characters long using unicode box
22712423
** characters
22722424
*/
2273
-static void qrfBoxLine(sqlite3_str *pOut, int N){
2274
- const char zDash[] =
2275
- BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
2276
- BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
2277
- const int nDash = sizeof(zDash) - 1;
2425
+static void qrfBoxLine(sqlite3_str *pOut, int N, int bDbl){
2426
+ const char *azDash[2] = {
2427
+ BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24,
2428
+ DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24
2429
+ };/* 0 1 2 3 4 5 6 7 8 9 */
2430
+ const int nDash = 30;
22782431
N *= 3;
22792432
while( N>nDash ){
2280
- sqlite3_str_append(pOut, zDash, nDash);
2433
+ sqlite3_str_append(pOut, azDash[bDbl], nDash);
22812434
N -= nDash;
22822435
}
2283
- sqlite3_str_append(pOut, zDash, N);
2436
+ sqlite3_str_append(pOut, azDash[bDbl], N);
22842437
}
22852438
22862439
/*
22872440
** Draw a horizontal separator for a QRF_STYLE_Box table.
22882441
*/
@@ -2289,21 +2442,27 @@
22892442
static void qrfBoxSeparator(
22902443
sqlite3_str *pOut,
22912444
qrfColData *p,
22922445
const char *zSep1,
22932446
const char *zSep2,
2294
- const char *zSep3
2447
+ const char *zSep3,
2448
+ int bDbl
22952449
){
22962450
int i;
22972451
if( p->nCol>0 ){
2298
- sqlite3_str_appendall(pOut, zSep1);
2299
- qrfBoxLine(pOut, p->a[0].w+p->nMargin);
2452
+ int useBorder = p->p->spec.bBorder!=QRF_No;
2453
+ if( useBorder ){
2454
+ sqlite3_str_appendall(pOut, zSep1);
2455
+ }
2456
+ qrfBoxLine(pOut, p->a[0].w+p->nMargin, bDbl);
23002457
for(i=1; i<p->nCol; i++){
23012458
sqlite3_str_appendall(pOut, zSep2);
2302
- qrfBoxLine(pOut, p->a[i].w+p->nMargin);
2459
+ qrfBoxLine(pOut, p->a[i].w+p->nMargin, bDbl);
23032460
}
2304
- sqlite3_str_appendall(pOut, zSep3);
2461
+ if( useBorder ){
2462
+ sqlite3_str_appendall(pOut, zSep3);
2463
+ }
23052464
}
23062465
sqlite3_str_append(pOut, "\n", 1);
23072466
}
23082467
23092468
/*
@@ -2382,10 +2541,11 @@
23822541
static void qrfSplitColumn(qrfColData *pData, Qrf *p){
23832542
int nCol = 1;
23842543
int *aw = 0;
23852544
char **az = 0;
23862545
int *aiWth = 0;
2546
+ unsigned char *abNum = 0;
23872547
int nColNext = 2;
23882548
int w;
23892549
struct qrfPerCol *a = 0;
23902550
sqlite3_int64 nRow = 1;
23912551
sqlite3_int64 i;
@@ -2419,35 +2579,47 @@
24192579
if( a==0 ){
24202580
sqlite3_free(az);
24212581
sqlite3_free(aiWth);
24222582
qrfOom(p);
24232583
return;
2584
+ }
2585
+ abNum = sqlite3_malloc64( nRow*nCol );
2586
+ if( abNum==0 ){
2587
+ sqlite3_free(az);
2588
+ sqlite3_free(aiWth);
2589
+ sqlite3_free(a);
2590
+ qrfOom(p);
2591
+ return;
24242592
}
24252593
for(i=0; i<pData->n; i++){
24262594
sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
24272595
az[j] = pData->az[i];
2596
+ abNum[j]= pData->abNum[i];
24282597
pData->az[i] = 0;
24292598
aiWth[j] = pData->aiWth[i];
24302599
}
24312600
while( i<nRow*nCol ){
24322601
sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
24332602
az[j] = sqlite3_mprintf("");
24342603
if( az[j]==0 ) qrfOom(p);
24352604
aiWth[j] = 0;
2605
+ abNum[j] = 0;
24362606
i++;
24372607
}
24382608
for(i=0; i<nCol; i++){
24392609
a[i].fx = a[i].mxW = a[i].w = aw[i];
24402610
a[i].e = pData->a[0].e;
24412611
}
24422612
sqlite3_free(pData->az);
24432613
sqlite3_free(pData->aiWth);
24442614
sqlite3_free(pData->a);
2615
+ sqlite3_free(pData->abNum);
24452616
sqlite3_free(aw);
24462617
pData->az = az;
24472618
pData->aiWth = aiWth;
24482619
pData->a = a;
2620
+ pData->abNum = abNum;
24492621
pData->nCol = nCol;
24502622
pData->n = pData->nAlloc = nRow*nCol;
24512623
for(i=w=0; i<nCol; i++) w += a[i].w;
24522624
pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1);
24532625
if( pData->nMargin>5 ) pData->nMargin = 5;
@@ -2467,10 +2639,11 @@
24672639
if( p->spec.nScreenWidth==0 ) return;
24682640
if( p->spec.eStyle==QRF_STYLE_Column ){
24692641
sepW = pData->nCol*2 - 2;
24702642
}else{
24712643
sepW = pData->nCol*3 + 1;
2644
+ if( p->spec.bBorder==QRF_No ) sepW -= 2;
24722645
}
24732646
nCol = pData->nCol;
24742647
for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
24752648
if( p->spec.nScreenWidth >= sumW+sepW ) return;
24762649
@@ -2478,10 +2651,11 @@
24782651
pData->nMargin = 0;
24792652
if( p->spec.eStyle==QRF_STYLE_Column ){
24802653
sepW = pData->nCol - 1;
24812654
}else{
24822655
sepW = pData->nCol + 1;
2656
+ if( p->spec.bBorder==QRF_No ) sepW -= 2;
24832657
}
24842658
targetW = p->spec.nScreenWidth - sepW;
24852659
24862660
#define MIN_SQUOZE 8
24872661
#define MIN_EX_SQUOZE 16
@@ -2550,10 +2724,11 @@
25502724
}
25512725
25522726
/* Initialize the data container */
25532727
memset(&data, 0, sizeof(data));
25542728
data.nCol = p->nCol;
2729
+ data.p = p;
25552730
data.a = sqlite3_malloc64( nColumn*sizeof(struct qrfPerCol) );
25562731
if( data.a==0 ){
25572732
qrfOom(p);
25582733
return;
25592734
}
@@ -2563,19 +2738,27 @@
25632738
25642739
/* Load the column header names and all cell content into data */
25652740
if( p->spec.bTitles==QRF_Yes ){
25662741
unsigned char saved_eText = p->spec.eText;
25672742
p->spec.eText = p->spec.eTitle;
2743
+ memset(data.abNum, 0, nColumn);
25682744
for(i=0; i<nColumn; i++){
25692745
const char *z = (const char*)sqlite3_column_name(p->pStmt,i);
25702746
int nNL = 0;
25712747
int n, w;
25722748
pStr = sqlite3_str_new(p->db);
25732749
qrfEncodeText(p, pStr, z ? z : "");
25742750
n = sqlite3_str_length(pStr);
2751
+ qrfStrErr(p, pStr);
25752752
z = data.az[data.n] = sqlite3_str_finish(pStr);
2576
- data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
2753
+ if( p->spec.nTitleLimit ){
2754
+ nNL = 0;
2755
+ data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n],
2756
+ p->spec.nTitleLimit );
2757
+ }else{
2758
+ data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
2759
+ }
25772760
data.n++;
25782761
if( w>data.a[i].mxW ) data.a[i].mxW = w;
25792762
if( nNL ) data.bMultiRow = 1;
25802763
}
25812764
p->spec.eText = saved_eText;
@@ -2587,14 +2770,17 @@
25872770
}
25882771
for(i=0; i<nColumn; i++){
25892772
char *z;
25902773
int nNL = 0;
25912774
int n, w;
2775
+ int eType = sqlite3_column_type(p->pStmt,i);
25922776
pStr = sqlite3_str_new(p->db);
25932777
qrfRenderValue(p, pStr, i);
25942778
n = sqlite3_str_length(pStr);
2779
+ qrfStrErr(p, pStr);
25952780
z = data.az[data.n] = sqlite3_str_finish(pStr);
2781
+ data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT;
25962782
data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
25972783
data.n++;
25982784
if( w>data.a[i].mxW ) data.a[i].mxW = w;
25992785
if( nNL ) data.bMultiRow = 1;
26002786
}
@@ -2680,11 +2866,16 @@
26802866
}else{
26812867
rowStart = BOX_13;
26822868
colSep = BOX_13;
26832869
rowSep = BOX_13 "\n";
26842870
}
2685
- qrfBoxSeparator(p->pOut, &data, BOX_23, BOX_234, BOX_34);
2871
+ if( p->spec.bBorder==QRF_No){
2872
+ rowStart += 3;
2873
+ rowSep = "\n";
2874
+ }else{
2875
+ qrfBoxSeparator(p->pOut, &data, BOX_R23, BOX_234, BOX_R34, 0);
2876
+ }
26862877
break;
26872878
case QRF_STYLE_Table:
26882879
if( data.nMargin ){
26892880
rowStart = "| ";
26902881
colSep = " | ";
@@ -2692,11 +2883,16 @@
26922883
}else{
26932884
rowStart = "|";
26942885
colSep = "|";
26952886
rowSep = "|\n";
26962887
}
2697
- qrfRowSeparator(p->pOut, &data, '+');
2888
+ if( p->spec.bBorder==QRF_No ){
2889
+ rowStart += 1;
2890
+ rowSep = "\n";
2891
+ }else{
2892
+ qrfRowSeparator(p->pOut, &data, '+');
2893
+ }
26982894
break;
26992895
case QRF_STYLE_Column: {
27002896
static const char zSpace[] = " ";
27012897
rowStart = "";
27022898
if( data.nMargin<2 ){
@@ -2724,20 +2920,32 @@
27242920
szRowStart = (int)strlen(rowStart);
27252921
szRowSep = (int)strlen(rowSep);
27262922
szColSep = (int)strlen(colSep);
27272923
27282924
bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
2729
- bRTrim = (p->spec.eStyle==QRF_STYLE_Column);
2730
- for(i=0; i<data.n; i+=nColumn){
2925
+ if( p->spec.eStyle==QRF_STYLE_Column
2926
+ || (p->spec.bBorder==QRF_No
2927
+ && (p->spec.eStyle==QRF_STYLE_Box || p->spec.eStyle==QRF_STYLE_Table)
2928
+ )
2929
+ ){
2930
+ bRTrim = 1;
2931
+ }else{
2932
+ bRTrim = 0;
2933
+ }
2934
+ for(i=0; i<data.n && sqlite3_str_errcode(p->pOut)==SQLITE_OK; i+=nColumn){
27312935
int bMore;
27322936
int nRow = 0;
27332937
27342938
/* Draw a single row of the table. This might be the title line
27352939
** (if there is a title line) or a row in the body of the table.
27362940
** The column number will be j. The row number is i/nColumn.
27372941
*/
2738
- for(j=0; j<nColumn; j++){ data.a[j].z = data.az[i+j]; }
2942
+ for(j=0; j<nColumn; j++){
2943
+ data.a[j].z = data.az[i+j];
2944
+ if( data.a[j].z==0 ) data.a[j].z = "";
2945
+ data.a[j].bNum = data.abNum[i+j];
2946
+ }
27392947
do{
27402948
sqlite3_str_append(p->pOut, rowStart, szRowStart);
27412949
bMore = 0;
27422950
for(j=0; j<nColumn; j++){
27432951
int nThis = 0;
@@ -2744,11 +2952,11 @@
27442952
int nWide = 0;
27452953
int iNext = 0;
27462954
int nWS;
27472955
qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
27482956
nWS = data.a[j].w - nWide;
2749
- qrfPrintAligned(p->pOut, data.a[j].z, nThis, nWS, data.a[j].e);
2957
+ qrfPrintAligned(p->pOut, &data.a[j], nThis, nWS);
27502958
data.a[j].z += iNext;
27512959
if( data.a[j].z[0]!=0 ){
27522960
bMore = 1;
27532961
}
27542962
if( j<nColumn-1 ){
@@ -2766,11 +2974,12 @@
27662974
if( data.a[j].z[0]==0 ){
27672975
sqlite3_str_appendchar(p->pOut, data.a[j].w, ' ');
27682976
}else{
27692977
int nE = 3;
27702978
if( nE>data.a[j].w ) nE = data.a[j].w;
2771
- qrfPrintAligned(p->pOut, "...", nE, data.a[j].w-nE, data.a[j].e);
2979
+ data.a[j].z = "...";
2980
+ qrfPrintAligned(p->pOut, &data.a[j], nE, data.a[j].w-nE);
27722981
}
27732982
if( j<nColumn-1 ){
27742983
sqlite3_str_append(p->pOut, colSep, szColSep);
27752984
}else{
27762985
if( bRTrim ) qrfRTrim(p->pOut);
@@ -2794,12 +3003,14 @@
27943003
qrfRowSeparator(p->pOut, &data, '+');
27953004
}
27963005
break;
27973006
}
27983007
case QRF_STYLE_Box: {
2799
- if( isTitleDataSeparator || data.bMultiRow ){
2800
- qrfBoxSeparator(p->pOut, &data, BOX_123, BOX_1234, BOX_134);
3008
+ if( isTitleDataSeparator ){
3009
+ qrfBoxSeparator(p->pOut, &data, DBL_123, DBL_1234, DBL_134, 1);
3010
+ }else if( data.bMultiRow ){
3011
+ qrfBoxSeparator(p->pOut, &data, BOX_123, BOX_1234, BOX_134, 0);
28013012
}
28023013
break;
28033014
}
28043015
case QRF_STYLE_Markdown: {
28053016
if( isTitleDataSeparator ){
@@ -2827,17 +3038,19 @@
28273038
}
28283039
}
28293040
}
28303041
28313042
/* Draw the line across the bottom of the table */
2832
- switch( p->spec.eStyle ){
2833
- case QRF_STYLE_Box:
2834
- qrfBoxSeparator(p->pOut, &data, BOX_12, BOX_124, BOX_14);
2835
- break;
2836
- case QRF_STYLE_Table:
2837
- qrfRowSeparator(p->pOut, &data, '+');
2838
- break;
3043
+ if( p->spec.bBorder!=QRF_No ){
3044
+ switch( p->spec.eStyle ){
3045
+ case QRF_STYLE_Box:
3046
+ qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0);
3047
+ break;
3048
+ case QRF_STYLE_Table:
3049
+ qrfRowSeparator(p->pOut, &data, '+');
3050
+ break;
3051
+ }
28393052
}
28403053
qrfWrite(p);
28413054
28423055
qrfColDataFree(&data);
28433056
return;
@@ -2903,11 +3116,11 @@
29033116
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) );
29043117
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) );
29053118
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) );
29063119
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) );
29073120
2908
- for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt); iOp++){
3121
+ for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){
29093122
int iAddr = sqlite3_column_int(p->pStmt, 0);
29103123
const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1);
29113124
int p1 = sqlite3_column_int(p->pStmt, 2);
29123125
int p2 = sqlite3_column_int(p->pStmt, 3);
29133126
@@ -2960,11 +3173,11 @@
29603173
nWidth = sizeof(aScanExpWidth)/sizeof(int);
29613174
iIndent = 3;
29623175
}
29633176
if( nArg>nWidth ) nArg = nWidth;
29643177
2965
- for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW; iOp++){
3178
+ for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW && !p->iErr; iOp++){
29663179
/* If this is the first row seen, print out the headers */
29673180
if( iOp==0 ){
29683181
for(i=0; i<nArg; i++){
29693182
const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]);
29703183
qrfWidthPrint(p,p->pOut, aWidth[i], zCol);
@@ -2989,11 +3202,11 @@
29893202
int w = aWidth[i];
29903203
const char *zVal = (const char*)sqlite3_column_text(p->pStmt, aMap[i]);
29913204
int len;
29923205
if( i==nArg-1 ) w = 0;
29933206
if( zVal==0 ) zVal = "";
2994
- len = qrfDisplayLength(zVal);
3207
+ len = (int)sqlite3_qrf_wcswidth(zVal);
29953208
if( len>w ){
29963209
w = len;
29973210
zSep = " ";
29983211
}
29993212
if( i==iIndent && aiIndent && iOp<nIndent ){
@@ -3168,34 +3381,40 @@
31683381
}
31693382
case QRF_STYLE_Line: {
31703383
sqlite3_str *pVal;
31713384
int mxW;
31723385
int bWW;
3386
+ int nSep;
31733387
if( p->u.sLine.azCol==0 ){
31743388
p->u.sLine.azCol = sqlite3_malloc64( p->nCol*sizeof(char*) );
31753389
if( p->u.sLine.azCol==0 ){
31763390
qrfOom(p);
31773391
break;
31783392
}
31793393
p->u.sLine.mxColWth = 0;
31803394
for(i=0; i<p->nCol; i++){
31813395
int sz;
3182
- p->u.sLine.azCol[i] = sqlite3_column_name(p->pStmt, i);
3183
- if( p->u.sLine.azCol[i]==0 ) p->u.sLine.azCol[i] = "unknown";
3184
- sz = qrfDisplayLength(p->u.sLine.azCol[i]);
3396
+ const char *zCName = sqlite3_column_name(p->pStmt, i);
3397
+ if( zCName==0 ) zCName = "unknown";
3398
+ p->u.sLine.azCol[i] = sqlite3_mprintf("%s", zCName);
3399
+ if( p->spec.nTitleLimit>0 ){
3400
+ (void)qrfTitleLimit(p->u.sLine.azCol[i], p->spec.nTitleLimit);
3401
+ }
3402
+ sz = (int)sqlite3_qrf_wcswidth(p->u.sLine.azCol[i]);
31853403
if( sz > p->u.sLine.mxColWth ) p->u.sLine.mxColWth = sz;
31863404
}
31873405
}
31883406
if( p->nRow ) sqlite3_str_append(p->pOut, "\n", 1);
31893407
pVal = sqlite3_str_new(p->db);
3190
- mxW = p->mxWidth - (3 + p->u.sLine.mxColWth);
3408
+ nSep = (int)strlen(p->spec.zColumnSep);
3409
+ mxW = p->mxWidth - (nSep + p->u.sLine.mxColWth);
31913410
bWW = p->spec.bWordWrap==QRF_Yes;
31923411
for(i=0; i<p->nCol; i++){
31933412
const char *zVal;
31943413
int cnt = 0;
31953414
qrfWidthPrint(p, p->pOut, -p->u.sLine.mxColWth, p->u.sLine.azCol[i]);
3196
- sqlite3_str_append(p->pOut, " = ", 3);
3415
+ sqlite3_str_append(p->pOut, p->spec.zColumnSep, nSep);
31973416
qrfRenderValue(p, pVal, i);
31983417
zVal = sqlite3_str_value(pVal);
31993418
if( zVal==0 ) zVal = "";
32003419
do{
32013420
int nThis, nWide, iNext;
@@ -3210,10 +3429,11 @@
32103429
sqlite3_str_append(p->pOut, "\n", 1);
32113430
zVal += iNext;
32123431
}while( zVal[0] );
32133432
sqlite3_str_reset(pVal);
32143433
}
3434
+ qrfStrErr(p, pVal);
32153435
sqlite3_free(sqlite3_str_finish(pVal));
32163436
qrfWrite(p);
32173437
break;
32183438
}
32193439
case QRF_STYLE_Eqp: {
@@ -3273,11 +3493,11 @@
32733493
p->pOut = sqlite3_str_new(p->db);
32743494
if( p->pOut==0 ){
32753495
qrfOom(p);
32763496
return;
32773497
}
3278
- p->iErr = 0;
3498
+ p->iErr = SQLITE_OK;
32793499
p->nCol = sqlite3_column_count(p->pStmt);
32803500
p->nRow = 0;
32813501
sz = sizeof(sqlite3_qrf_spec);
32823502
memcpy(&p->spec, pSpec, sz);
32833503
if( p->spec.zNull==0 ) p->spec.zNull = "";
@@ -3285,12 +3505,12 @@
32853505
if( p->mxWidth<=0 ) p->mxWidth = QRF_MAX_WIDTH;
32863506
p->mxHeight = p->spec.nLineLimit;
32873507
if( p->mxHeight<=0 ) p->mxHeight = 2147483647;
32883508
if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto;
32893509
if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto;
3290
- if( p->spec.eText>QRF_TEXT_Json ) p->spec.eText = QRF_Auto;
3291
- if( p->spec.eTitle>QRF_TEXT_Json ) p->spec.eTitle = QRF_Auto;
3510
+ if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto;
3511
+ if( p->spec.eTitle>QRF_TEXT_Relaxed ) p->spec.eTitle = QRF_Auto;
32923512
if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto;
32933513
qrf_reinit:
32943514
switch( p->spec.eStyle ){
32953515
case QRF_Auto: {
32963516
switch( sqlite3_stmt_isexplain(pStmt) ){
@@ -3321,10 +3541,16 @@
33213541
p->spec.zNull = "NULL";
33223542
if( p->spec.zTableName==0 || p->spec.zTableName[0]==0 ){
33233543
p->spec.zTableName = "tab";
33243544
}
33253545
break;
3546
+ }
3547
+ case QRF_STYLE_Line: {
3548
+ if( p->spec.zColumnSep==0 ){
3549
+ p->spec.zColumnSep = ": ";
3550
+ }
3551
+ break;
33263552
}
33273553
case QRF_STYLE_Csv: {
33283554
p->spec.eStyle = QRF_STYLE_List;
33293555
p->spec.eText = QRF_TEXT_Csv;
33303556
p->spec.zColumnSep = ",";
@@ -3430,11 +3656,15 @@
34303656
qrfWrite(p);
34313657
}
34323658
break;
34333659
}
34343660
case QRF_STYLE_Line: {
3435
- if( p->u.sLine.azCol ) sqlite3_free(p->u.sLine.azCol);
3661
+ if( p->u.sLine.azCol ){
3662
+ int i;
3663
+ for(i=0; i<p->nCol; i++) sqlite3_free(p->u.sLine.azCol[i]);
3664
+ sqlite3_free(p->u.sLine.azCol);
3665
+ }
34363666
break;
34373667
}
34383668
case QRF_STYLE_Stats:
34393669
case QRF_STYLE_StatsEst:
34403670
case QRF_STYLE_Eqp: {
@@ -3441,10 +3671,11 @@
34413671
qrfEqpRender(p, 0);
34423672
qrfWrite(p);
34433673
break;
34443674
}
34453675
}
3676
+ qrfStrErr(p, p->pOut);
34463677
if( p->spec.pzOutput ){
34473678
if( p->spec.pzOutput[0] ){
34483679
sqlite3_int64 n, sz;
34493680
char *zCombined;
34503681
sz = strlen(p->spec.pzOutput[0]);
@@ -3624,11 +3855,11 @@
36243855
36253856
/* Return the current wall-clock time in microseconds since the
36263857
** Unix epoch (1970-01-01T00:00:00Z)
36273858
*/
36283859
static sqlite3_int64 timeOfDay(void){
3629
-#if defined(_WIN64)
3860
+#if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8
36303861
sqlite3_uint64 t;
36313862
FILETIME tm;
36323863
GetSystemTimePreciseAsFileTime(&tm);
36333864
t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
36343865
t += 116444736000000000LL;
@@ -3724,11 +3955,10 @@
37243955
*/
37253956
static int hasTimer(void){
37263957
if( getProcessTimesAddr ){
37273958
return 1;
37283959
} else {
3729
-#if !SQLITE_OS_WINRT
37303960
/* GetProcessTimes() isn't supported in WIN95 and some other Windows
37313961
** versions. See if the version we are running on has it, and if it
37323962
** does, save off a pointer to it and the current process handle.
37333963
*/
37343964
hProcess = GetCurrentProcess();
@@ -3741,11 +3971,10 @@
37413971
return 1;
37423972
}
37433973
FreeLibrary(hinstLib);
37443974
}
37453975
}
3746
-#endif
37473976
}
37483977
return 0;
37493978
}
37503979
37513980
/*
@@ -3860,10 +4089,18 @@
38604089
#define PROMPT_LEN_MAX 128
38614090
/* First line prompt. default: "sqlite> " */
38624091
static char mainPrompt[PROMPT_LEN_MAX];
38634092
/* Continuation prompt. default: " ...> " */
38644093
static char continuePrompt[PROMPT_LEN_MAX];
4094
+
4095
+/*
4096
+** Write I/O traces to the following stream.
4097
+*/
4098
+#ifdef SQLITE_ENABLE_IOTRACE
4099
+static FILE *iotrace = 0;
4100
+#endif
4101
+
38654102
38664103
/* This is variant of the standard-library strncpy() routine with the
38674104
** one change that the destination string is always zero-terminated, even
38684105
** if there is no zero-terminator in the first n-1 characters of the source
38694106
** string.
@@ -3980,17 +4217,10 @@
39804217
*/
39814218
static void shell_check_oom(const void *p){
39824219
if( p==0 ) shell_out_of_memory();
39834220
}
39844221
3985
-/*
3986
-** Write I/O traces to the following stream.
3987
-*/
3988
-#ifdef SQLITE_ENABLE_IOTRACE
3989
-static FILE *iotrace = 0;
3990
-#endif
3991
-
39924222
/*
39934223
** This routine works like printf in that its first argument is a
39944224
** format string and subsequent arguments are values to be substituted
39954225
** in place of % fields. The result of formatting this string
39964226
** is written to iotrace.
@@ -6013,17 +6243,20 @@
60136243
}
60146244
/* End of the hashing logic
60156245
*****************************************************************************/
60166246
60176247
/*
6018
-** Implementation of the sha1(X) function.
6248
+** Two SQL functions: sha1(X) and sha1b(X).
60196249
**
6020
-** Return a lower-case hexadecimal rendering of the SHA1 hash of the
6021
-** argument X. If X is a BLOB, it is hashed as is. For all other
6250
+** sha1(X) returns a lower-case hexadecimal rendering of the SHA1 hash
6251
+** of the argument X. If X is a BLOB, it is hashed as is. For all other
60226252
** types of input, X is converted into a UTF-8 string and the string
6023
-** is hash without the trailing 0x00 terminator. The hash of a NULL
6253
+** is hashed without the trailing 0x00 terminator. The hash of a NULL
60246254
** value is NULL.
6255
+**
6256
+** sha1b(X) is the same except that it returns a 20-byte BLOB containing
6257
+** the binary hash instead of a hexadecimal string.
60256258
*/
60266259
static void sha1Func(
60276260
sqlite3_context *context,
60286261
int argc,
60296262
sqlite3_value **argv
@@ -6040,15 +6273,17 @@
60406273
hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
60416274
}else{
60426275
hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
60436276
}
60446277
if( sqlite3_user_data(context)!=0 ){
6278
+ /* sha1b() - binary result */
60456279
hash_finish(&cx, zOut, 1);
60466280
sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
60476281
}else{
6282
+ /* sha1() - hexadecimal text result */
60486283
hash_finish(&cx, zOut, 0);
6049
- sqlite3_result_blob(context, zOut, 40, SQLITE_TRANSIENT);
6284
+ sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
60506285
}
60516286
}
60526287
60536288
/*
60546289
** Implementation of the sha1_query(SQL) function.
@@ -8136,13 +8371,13 @@
81368371
}else if( e<-10000 ){
81378372
e = -10000;
81388373
}
81398374
81408375
if( m<0 ){
8376
+ if( m<(-9223372036854775807LL) ) return;
81418377
isNeg = 1;
81428378
m = -m;
8143
- if( m<0 ) return;
81448379
}else if( m==0 && e>-1000 && e<1000 ){
81458380
sqlite3_result_double(context, 0.0);
81468381
return;
81478382
}
81488383
while( (m>>32)&0xffe00000 ){
@@ -9259,11 +9494,11 @@
92599494
** (X) match X
92609495
** X|Y X or Y
92619496
** ^X X occurring at the beginning of the string
92629497
** X$ X occurring at the end of the string
92639498
** . Match any single character
9264
-** \c Character c where c is one of \{}()[]|*+?.
9499
+** \c Character c where c is one of \{}()[]|*+?-.
92659500
** \c C-language escapes for c in afnrtv. ex: \t or \n
92669501
** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
92679502
** \xXX Where XX is exactly 2 hex digits, unicode value XX
92689503
** [abc] Any single character from the set abc
92699504
** [^abc] Any single character not in the set abc
@@ -9644,11 +9879,11 @@
96449879
96459880
/* A backslash character has been seen, read the next character and
96469881
** return its interpretation.
96479882
*/
96489883
static unsigned re_esc_char(ReCompiled *p){
9649
- static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]";
9884
+ static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]-";
96509885
static const char zTrans[] = "\a\f\n\r\t\v";
96519886
int i, v = 0;
96529887
char c;
96539888
if( p->sIn.i>=p->sIn.mx ) return 0;
96549889
c = p->sIn.z[p->sIn.i];
@@ -9967,15 +10202,22 @@
996710202
}
996810203
return pRe->zErr;
996910204
}
997010205
997110206
/*
9972
-** Compute a reasonable limit on the length of the REGEXP NFA.
10207
+** The value of LIMIT_MAX_PATTERN_LENGTH.
997310208
*/
997410209
static int re_maxlen(sqlite3_context *context){
997510210
sqlite3 *db = sqlite3_context_db_handle(context);
9976
- return 75 + sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1)/2;
10211
+ return sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1);
10212
+}
10213
+
10214
+/*
10215
+** Maximum NFA size given a maximum pattern length.
10216
+*/
10217
+static int re_maxnfa(int mxlen){
10218
+ return 75+mxlen/2;
997710219
}
997810220
997910221
/*
998010222
** Implementation of the regexp() SQL function. This function implements
998110223
** the build-in REGEXP operator. The first argument to the function is the
@@ -9997,14 +10239,21 @@
999710239
int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
999810240
999910241
(void)argc; /* Unused */
1000010242
pRe = sqlite3_get_auxdata(context, 0);
1000110243
if( pRe==0 ){
10244
+ int mxLen = re_maxlen(context);
10245
+ int nPattern;
1000210246
zPattern = (const char*)sqlite3_value_text(argv[0]);
1000310247
if( zPattern==0 ) return;
10004
- zErr = re_compile(&pRe, zPattern, re_maxlen(context),
10005
- sqlite3_user_data(context)!=0);
10248
+ nPattern = sqlite3_value_bytes(argv[0]);
10249
+ if( nPattern>mxLen ){
10250
+ zErr = "REGEXP pattern too big";
10251
+ }else{
10252
+ zErr = re_compile(&pRe, zPattern, re_maxnfa(mxLen),
10253
+ sqlite3_user_data(context)!=0);
10254
+ }
1000610255
if( zErr ){
1000710256
re_free(pRe);
1000810257
sqlite3_result_error(context, zErr, -1);
1000910258
return;
1001010259
}
@@ -10066,11 +10315,11 @@
1006610315
"ATSTART",
1006710316
};
1006810317
1006910318
zPattern = (const char*)sqlite3_value_text(argv[0]);
1007010319
if( zPattern==0 ) return;
10071
- zErr = re_compile(&pRe, zPattern, re_maxlen(context),
10320
+ zErr = re_compile(&pRe, zPattern, re_maxnfa(re_maxlen(context)),
1007210321
sqlite3_user_data(context)!=0);
1007310322
if( zErr ){
1007410323
re_free(pRe);
1007510324
sqlite3_result_error(context, zErr, -1);
1007610325
return;
@@ -10474,10 +10723,11 @@
1047410723
if( b1==0 ) return 1;
1047510724
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
1047610725
b1[sz] = 0;
1047710726
rc = _wstat(b1, pStatBuf);
1047810727
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
10728
+ sqlite3_free(b1);
1047910729
return rc;
1048010730
#else
1048110731
return stat(zPath, pStatBuf);
1048210732
#endif
1048310733
}
@@ -10604,11 +10854,10 @@
1060410854
}
1060510855
}
1060610856
1060710857
if( mtime>=0 ){
1060810858
#if defined(_WIN32)
10609
-#if !SQLITE_OS_WINRT
1061010859
/* Windows */
1061110860
FILETIME lastAccess;
1061210861
FILETIME lastWrite;
1061310862
SYSTEMTIME currentTime;
1061410863
LONGLONG intervals;
@@ -10635,11 +10884,10 @@
1063510884
CloseHandle(hFile);
1063610885
return !bResult;
1063710886
}else{
1063810887
return 1;
1063910888
}
10640
-#endif
1064110889
#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
1064210890
/* Recent unix */
1064310891
struct timespec times[2];
1064410892
times[0].tv_nsec = times[1].tv_nsec = 0;
1064510893
times[0].tv_sec = time(0);
@@ -13337,11 +13585,11 @@
1333713585
rc = zipfileReadData(
1333813586
pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
1333913587
);
1334013588
}else{
1334113589
aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
13342
- if( (iOff + ZIPFILE_LFH_FIXED_SZ + nFile + nExtra)>nBlob ){
13590
+ if( (iOff + ZIPFILE_CDS_FIXED_SZ + nFile + nExtra)>nBlob ){
1334313591
rc = zipfileCorrupt(pzErr);
1334413592
}
1334513593
}
1334613594
}
1334713595
@@ -13362,15 +13610,16 @@
1336213610
ZipfileLFH lfh;
1336313611
if( pFile ){
1336413612
rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
1336513613
}else{
1336613614
aRead = (u8*)&aBlob[pNew->cds.iOffset];
13367
- if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){
13615
+ if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>(unsigned)nBlob ){
1336813616
rc = zipfileCorrupt(pzErr);
1336913617
}
1337013618
}
1337113619
13620
+ memset(&lfh, 0, sizeof(lfh));
1337213621
if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
1337313622
if( rc==SQLITE_OK ){
1337413623
pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
1337513624
pNew->iDataOff += lfh.nFile + lfh.nExtra;
1337613625
if( aBlob && pNew->cds.szCompressed ){
@@ -13470,11 +13719,11 @@
1347013719
}else{
1347113720
err = inflate(&str, Z_NO_FLUSH);
1347213721
if( err!=Z_STREAM_END ){
1347313722
zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
1347413723
}else{
13475
- sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
13724
+ sqlite3_result_blob(pCtx, aRes, (int)str.total_out, zipfileFree);
1347613725
aRes = 0;
1347713726
}
1347813727
}
1347913728
sqlite3_free(aRes);
1348013729
inflateEnd(&str);
@@ -23948,28 +24197,28 @@
2394824197
u8 autoExplain; /* Automatically turn on .explain mode */
2394924198
u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
2395024199
u8 autoEQPtrace; /* autoEQP is in trace mode */
2395124200
u8 scanstatsOn; /* True to display scan stats before each finalize */
2395224201
u8 bAutoScreenWidth; /* Using the TTY to determine screen width */
23953
- u8 mFlags; /* MFLG_ECHO and/or MFLG_CRLF */
24202
+ u8 mFlags; /* MFLG_ECHO, MFLG_CRLF, etc. */
2395424203
u8 eMode; /* One of the MODE_ values */
2395524204
sqlite3_qrf_spec spec; /* Spec to be passed into QRF */
2395624205
} Mode;
2395724206
2395824207
/* Flags for Mode.mFlags */
2395924208
#define MFLG_ECHO 0x01 /* Echo inputs to output */
2396024209
#define MFLG_CRLF 0x02 /* Use CR/LF output line endings */
24210
+#define MFLG_HDR 0x04 /* .header used to change headers on/off */
2396124211
2396224212
2396324213
/*
2396424214
** State information about the database connection is contained in an
2396524215
** instance of the following structure.
2396624216
*/
2396724217
typedef struct ShellState ShellState;
2396824218
struct ShellState {
2396924219
sqlite3 *db; /* The database */
23970
- int iCompat; /* Compatibility date YYYYMMDD */
2397124220
u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
2397224221
u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
2397324222
u8 nEqpLevel; /* Depth of the EQP output graph */
2397424223
u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
2397524224
u8 bSafeMode; /* True to prohibit unsafe operations */
@@ -24078,11 +24327,11 @@
2407824327
2407924328
/* Names of values for Mode.spec.eEsc and Mode.spec.eText
2408024329
*/
2408124330
static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" };
2408224331
static const char *qrfQuoteNames[] =
24083
- { "off","off","sql","hex","csv","tcl","json"};
24332
+ { "off","off","sql","hex","csv","tcl","json","relaxed"};
2408424333
2408524334
/*
2408624335
** These are the allowed shellFlgs values
2408724336
*/
2408824337
#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
@@ -24120,19 +24369,20 @@
2412024369
#define MODE_Json 10 /* Output JSON */
2412124370
#define MODE_Line 11 /* One column per line. Blank line between records */
2412224371
#define MODE_List 12 /* One record per line with a separator */
2412324372
#define MODE_Markdown 13 /* Markdown formatting */
2412424373
#define MODE_Off 14 /* No query output shown */
24125
-#define MODE_QBox 15 /* BOX with SQL-quoted content */
24126
-#define MODE_Quote 16 /* Quote values as for SQL */
24127
-#define MODE_Split 17 /* Split-column mode */
24128
-#define MODE_Table 18 /* MySQL-style table formatting */
24129
-#define MODE_Tabs 19 /* Tab-separated values */
24130
-#define MODE_Tcl 20 /* Space-separated list of TCL strings */
24131
-#define MODE_Www 21 /* Full web-page output */
24132
-
24133
-#define MODE_BUILTIN 21 /* Maximum built-in mode */
24374
+#define MODE_Psql 15 /* Similar to psql */
24375
+#define MODE_QBox 16 /* BOX with SQL-quoted content */
24376
+#define MODE_Quote 17 /* Quote values as for SQL */
24377
+#define MODE_Split 18 /* Split-column mode */
24378
+#define MODE_Table 19 /* MySQL-style table formatting */
24379
+#define MODE_Tabs 20 /* Tab-separated values */
24380
+#define MODE_Tcl 21 /* Space-separated list of TCL strings */
24381
+#define MODE_Www 22 /* Full web-page output */
24382
+
24383
+#define MODE_BUILTIN 22 /* Maximum built-in mode */
2413424384
#define MODE_BATCH 50 /* Default mode for batch processing */
2413524385
#define MODE_TTY 51 /* Default mode for interactive processing */
2413624386
#define MODE_USER 75 /* First user-defined mode */
2413724387
#define MODE_N_USER 25 /* Maximum number of user-defined modes */
2413824388
@@ -24149,43 +24399,45 @@
2414924399
unsigned char eHdr; /* Default header encoding. */
2415024400
unsigned char eBlob; /* Default blob encoding. */
2415124401
unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */
2415224402
unsigned char eStyle; /* Underlying QRF style */
2415324403
unsigned char eCx; /* 0: other, 1: line, 2: columnar */
24404
+ unsigned char mFlg; /* Flags. 1=border-off 2=split-column */
2415424405
};
2415524406
2415624407
/* String constants used by built-in modes */
2415724408
static const char *aModeStr[] =
2415824409
/* 0 1 2 3 4 5 6 7 8 */
2415924410
{ 0, "\n", "|", " ", ",", "\r\n", "\036", "\037", "\t",
24160
- "", "NULL", "null", "\"\"" };
24161
- /* 9 10 11 12 */
24411
+ "", "NULL", "null", "\"\"", ": ", };
24412
+ /* 9 10 11 12 13 */
2416224413
2416324414
static const ModeInfo aModeInfo[] = {
24164
-/* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx */
24165
- { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0 },
24166
- { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2 },
24167
- { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0 },
24168
- { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2 },
24169
- { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0 },
24170
- { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0 },
24171
- { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0 },
24172
- { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0 },
24173
- { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0 },
24174
- { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0 },
24175
- { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0 },
24176
- { "line", 0, 1, 9, 1, 1, 0, 0, 11, 1 },
24177
- { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0 },
24178
- { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2 },
24179
- { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0 },
24180
- { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2 },
24181
- { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0 },
24182
- { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2 },
24183
- { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2 },
24184
- { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0 },
24185
- { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0 },
24186
- { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0 }
24415
+/* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */
24416
+ { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0, 0 },
24417
+ { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2, 0 },
24418
+ { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0, 0 },
24419
+ { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2, 0 },
24420
+ { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
24421
+ { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0, 0 },
24422
+ { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 },
24423
+ { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0, 0 },
24424
+ { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0, 0 },
24425
+ { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0, 0 },
24426
+ { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0, 0 },
24427
+ { "line", 13, 1, 9, 1, 1, 0, 0, 11, 1, 0 },
24428
+ { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0, 0 },
24429
+ { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2, 0 },
24430
+ { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0, 0 },
24431
+ { "psql", 0, 0, 9, 1, 1, 0, 2, 19, 2, 1 },
24432
+ { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2, 0 },
24433
+ { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0, 0 },
24434
+ { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2, 2 },
24435
+ { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2, 0 },
24436
+ { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0, 0 },
24437
+ { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0, 0 },
24438
+ { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 }
2418724439
}; /* | / / | / / | | \
2418824440
** | / / | / / | | \_ 2: columnar
2418924441
** Index into aModeStr[] | / / | | 1: line
2419024442
** | / / | | 0: other
2419124443
** | / / | \
@@ -24212,10 +24464,23 @@
2421224464
#define SEP_Comma ","
2421324465
#define SEP_CrLf "\r\n"
2421424466
#define SEP_Unit "\x1F"
2421524467
#define SEP_Record "\x1E"
2421624468
24469
+/*
24470
+** Default values for the various QRF limits
24471
+*/
24472
+#ifndef DFLT_CHAR_LIMIT
24473
+# define DFLT_CHAR_LIMIT 300
24474
+#endif
24475
+#ifndef DFLT_LINE_LIMIT
24476
+# define DFLT_LINE_LIMIT 5
24477
+#endif
24478
+#ifndef DFLT_TITLE_LIMIT
24479
+# define DFLT_TITLE_LIMIT 20
24480
+#endif
24481
+
2421724482
/*
2421824483
** Limit input nesting via .read or any other input redirect.
2421924484
** It's not too expensive, so a generous allowance can be made.
2422024485
*/
2422124486
#define MAX_INPUT_NESTING 25
@@ -24305,13 +24570,20 @@
2430524570
if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]);
2430624571
if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]);
2430724572
if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
2430824573
pM->spec.eText = pI->eText;
2430924574
pM->spec.eBlob = pI->eBlob;
24310
- pM->spec.bTitles = pI->bHdr;
24575
+ if( (pM->mFlags & MFLG_HDR)==0 ){
24576
+ pM->spec.bTitles = pI->bHdr;
24577
+ }
2431124578
pM->spec.eTitle = pI->eHdr;
24312
- if( eMode==MODE_Split ){
24579
+ if( pI->mFlg & 0x01 ){
24580
+ pM->spec.bBorder = QRF_No;
24581
+ }else{
24582
+ pM->spec.bBorder = QRF_Auto;
24583
+ }
24584
+ if( pI->mFlg & 0x02 ){
2431324585
pM->spec.bSplitColumn = QRF_Yes;
2431424586
pM->bAutoScreenWidth = 1;
2431524587
}else{
2431624588
pM->spec.bSplitColumn = QRF_No;
2431724589
}
@@ -24326,26 +24598,27 @@
2432624598
}else if( eMode==MODE_TTY ){
2432724599
u8 mFlags = p->mode.mFlags;
2432824600
modeFree(&p->mode);
2432924601
modeChange(p, MODE_QBox);
2433024602
p->mode.bAutoScreenWidth = 1;
24331
- p->mode.spec.nCharLimit = 300;
24332
- p->mode.spec.nLineLimit = 5;
24603
+ p->mode.spec.eText = QRF_TEXT_Relaxed;
24604
+ p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
24605
+ p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
2433324606
p->mode.spec.bTextJsonb = QRF_Yes;
24607
+ p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
2433424608
p->mode.mFlags = mFlags;
2433524609
}
2433624610
}
2433724611
2433824612
/*
24339
-** Set the mode to the default according to p->iCompat. It assumed
24340
-** that the mode has already been freed and zeroed prior to calling
24341
-** this routine.
24613
+** Set the mode to the default. It assumed that the mode has
24614
+** already been freed and zeroed prior to calling this routine.
2434224615
*/
2434324616
static void modeDefault(ShellState *p){
2434424617
p->mode.spec.iVersion = 1;
2434524618
p->mode.autoExplain = 1;
24346
- if( p->iCompat>=20251115 && (stdin_is_interactive || stdout_is_console) ){
24619
+ if( stdin_is_interactive || stdout_is_console ){
2434724620
modeChange(p, MODE_TTY);
2434824621
}else{
2434924622
modeChange(p, MODE_BATCH);
2435024623
}
2435124624
}
@@ -25075,10 +25348,12 @@
2507525348
z[j] = 0;
2507625349
if( strlen30(z)>=79 ){
2507725350
for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
2507825351
if( c==cEnd ){
2507925352
cEnd = 0;
25353
+ }else if( cEnd!=0){
25354
+ /* No-op */
2508025355
}else if( c=='"' || c=='\'' || c=='`' ){
2508125356
cEnd = c;
2508225357
}else if( c=='[' ){
2508325358
cEnd = ']';
2508425359
}else if( c=='-' && z[i+1]=='-' ){
@@ -25889,10 +26164,11 @@
2588926164
if( pArg->mode.bAutoScreenWidth ){
2589026165
spec.nScreenWidth = shellScreenWidth();
2589126166
}
2589226167
if( spec.eBlob==QRF_BLOB_Auto ){
2589326168
switch( spec.eText ){
26169
+ case QRF_TEXT_Relaxed: /* fall through */
2589426170
case QRF_TEXT_Sql: spec.eBlob = QRF_BLOB_Sql; break;
2589526171
case QRF_TEXT_Json: spec.eBlob = QRF_BLOB_Json; break;
2589626172
default: spec.eBlob = QRF_BLOB_Text; break;
2589726173
}
2589826174
}
@@ -25902,11 +26178,11 @@
2590226178
rc = expertHandleSQL(pArg, zSql, pzErrMsg);
2590326179
return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
2590426180
}
2590526181
#endif
2590626182
25907
- while( zSql[0] && (SQLITE_OK == rc) ){
26183
+ while( zSql && zSql[0] && (SQLITE_OK == rc) ){
2590826184
static const char *zStmtSql;
2590926185
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
2591026186
if( SQLITE_OK != rc ){
2591126187
if( pzErrMsg ){
2591226188
*pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
@@ -26365,12 +26641,12 @@
2636526641
".bail on|off Stop after hitting an error. Default OFF",
2636626642
#ifndef SQLITE_SHELL_FIDDLE
2636726643
".cd DIRECTORY Change the working directory to DIRECTORY",
2636826644
#endif
2636926645
".changes on|off Show number of rows changed by SQL",
26646
+ ".check OPTIONS ... Verify the results of a .testcase",
2637026647
#ifndef SQLITE_SHELL_FIDDLE
26371
- ".check GLOB Fail if output since .testcase does not match",
2637226648
".clone NEWDB Clone data into NEWDB from the existing database",
2637326649
#endif
2637426650
".connection [close] [#] Open or close an auxiliary database connection",
2637526651
".crlf ?on|off? Whether or not to use \\r\\n line endings",
2637626652
".databases List names and files of attached databases",
@@ -26546,13 +26822,11 @@
2654626822
" vmstep Show the virtual machine step count only",
2654726823
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
2654826824
".system CMD ARGS... Run CMD ARGS... in a system shell",
2654926825
#endif
2655026826
".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
26551
-#ifndef SQLITE_SHELL_FIDDLE
26552
- ",testcase NAME Begin redirecting output to 'testcase-out.txt'",
26553
-#endif
26827
+ ".testcase NAME Begin a test case.",
2655426828
",testctrl CMD ... Run various sqlite3_test_control() operations",
2655526829
" Run \".testctrl\" with no arguments for details",
2655626830
".timeout MS Try opening locked tables for MS milliseconds",
2655726831
".timer on|off Turn SQL timer on or off",
2655826832
#ifndef SQLITE_OMIT_TRACE
@@ -26597,19 +26871,31 @@
2659726871
"USAGE: .import [OPTIONS] FILE TABLE\n"
2659826872
"\n"
2659926873
"Import CSV or similar text from FILE into TABLE. If TABLE does\n"
2660026874
"not exist, it is created using the first row of FILE as the column\n"
2660126875
"names. If FILE begins with \"|\" then it is a command that is run\n"
26602
-"and the output from the command is used as the input data.\n"
26876
+"and the output from the command is used as the input data. If\n"
26877
+"FILE begins with \"<<\" followed by a label, then content is read from\n"
26878
+"the script until the first line that matches the label.\n"
26879
+"\n"
26880
+"The content of FILE is interpreted using RFC-4180 (\"CSV\") quoting\n"
26881
+"rules unless the current mode is \"ascii\" or \"tabs\" or unless one\n"
26882
+"the --ascii option is used.\n"
2660326883
"\n"
26604
-"FILE is assumed to be in a CSV format, unless the current mode\n"
26605
-"is \"ascii\" or \"tabs\" or unless one of the options below specify\n"
26606
-"an alternative.\n"
26884
+"The column and row separators must be single ASCII characters. If\n"
26885
+"multiple characters or a Unicode character are specified for the\n"
26886
+"separators, then only the first byte of the separator is used. Except,\n"
26887
+"if the row separator is \\n and the mode is not --ascii, then \\r\\n is\n"
26888
+"understood as a row separator too.\n"
2660726889
"\n"
2660826890
"Options:\n"
26609
-" --ascii Use \\037 and \\036 as column and row separators on input\n"
26891
+" --ascii Do not use RFC-4180 quoting. Use \\037 and \\036\n"
26892
+" as column and row separators on input, unless other\n"
26893
+" delimiters are specified using --colsep and/or --rowsep\n"
26894
+" --colsep CHAR Use CHAR as the column separator.\n"
2661026895
" --csv Input is standard RFC-4180 CSV.\n"
26896
+" --rowsep CHAR Use CHAR as the row separator.\n"
2661126897
" --schema S When creating TABLE, put it in schema S\n"
2661226898
" --skip N Ignore the first N rows of input\n"
2661326899
" -v Verbose mode\n"
2661426900
},
2661526901
{ ".mode",
@@ -26625,10 +26911,11 @@
2662526911
" meaning \"left\", \"centered\", and \"right\", with\n"
2662626912
" one letter per column starting from the left.\n"
2662726913
" Unspecified alignment defaults to 'L'.\n"
2662826914
" --blob-quote ARG ARG can be \"auto\", \"text\", \"sql\", \"hex\", \"tcl\",\n"
2662926915
" \"json\", or \"size\". Default is \"auto\".\n"
26916
+" --border on|off Show outer border on \"box\" and \"table\" modes.\n"
2663026917
" --charlimit N Set the maximum number of output characters to\n"
2663126918
" show for any single SQL value to N. Longer values\n"
2663226919
" truncated. Zero means \"no limit\".\n"
2663326920
" --colsep STRING Use STRING as the column separator\n"
2663426921
" --escape ESC Enable/disable escaping of control characters\n"
@@ -26636,19 +26923,22 @@
2663626923
" or \"symbol\".\n"
2663726924
" --linelimit N Set the maximum number of output lines to show for\n"
2663826925
" any single SQL value to N. Longer values are\n"
2663926926
" truncated. Zero means \"no limit\". Only works\n"
2664026927
" in \"line\" mode and in columnar modes.\n"
26641
-" --limits L,C Shorthand for \"--linelimit L --charlimit C\".\n"
26642
-" Or \"off\" to mean \"0,0\". Or \"on\" for \"5,300\".\n"
26928
+" --limits L,C,T Shorthand for \"--linelimit L --charlimit C\n"
26929
+" --titlelimit T\". The \",T\" can be omitted in which\n"
26930
+" case the --titlelimit is unchanged. The argument\n"
26931
+" can also be \"off\" to mean \"0,0,0\" or \"on\" to\n"
26932
+" mean \"5,300,20\".\n"
2664326933
" --list List available modes\n"
2664426934
" --null STRING Render SQL NULL values as the given string\n"
2664526935
" --once Setting changes to the right are reverted after\n"
2664626936
" the next SQL command.\n"
2664726937
" --quote ARG Enable/disable quoting of text. ARG can be\n"
26648
-" \"off\", \"on\", \"sql\", \"csv\", \"html\", \"tcl\",\n"
26649
-" or \"json\". \"off\" means show the text as-is.\n"
26938
+" \"off\", \"on\", \"sql\", \"relaxed\", \"csv\", \"html\",\n"
26939
+" \"tcl\", or \"json\". \"off\" means show the text as-is.\n"
2665026940
" \"on\" is an alias for \"sql\".\n"
2665126941
" --reset Changes all mode settings back to their default.\n"
2665226942
" --rowsep STRING Use STRING as the row separator\n"
2665326943
" --sw|--screenwidth N Declare the screen width of the output device\n"
2665426944
" to be N characters. An attempt may be made to\n"
@@ -26659,10 +26949,11 @@
2665926949
" --tag NAME Save mode to the left as NAME.\n"
2666026950
" --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON.\n"
2666126951
" --title ARG Whether or not to show column headers, and if so\n"
2666226952
" how to encode them. ARG can be \"off\", \"on\",\n"
2666326953
" \"sql\", \"csv\", \"html\", \"tcl\", or \"json\".\n"
26954
+" --titlelimit N Limit the length of column titles to N characters.\n"
2666426955
" -v|--verbose Verbose output\n"
2666526956
" --widths LIST Set the columns widths for columnar modes. The\n"
2666626957
" argument is a list of integers, one for each\n"
2666726958
" column. A \"0\" width means use a dynamic width\n"
2666826959
" based on the actual width of data. If there are\n"
@@ -26686,23 +26977,17 @@
2668626977
" --bom Prepend a byte-order mark to the output\n"
2668726978
" -e Accumulate output in a temporary text file then\n"
2668826979
" launch a text editor when the redirection ends.\n"
2668926980
" --error-prefix X Use X as the left-margin prefix for error messages.\n"
2669026981
" Set to an empty string to restore the default.\n"
26691
-" --glob GLOB Raise an error if the memory buffer does not match\n"
26692
-" the GLOB pattern.\n"
26693
-" --keep Continue using the same \"memory\" buffer. Do not\n"
26694
-" reset it or delete it. Useful in combination with\n"
26695
-" --glob, --not-glob, and/or --verify.\n"
26696
-" ---notglob GLOB Raise an error if the memory buffer does not match\n"
26697
-" the GLOB pattern.\n"
26982
+" --keep Keep redirecting output to its current destination.\n"
26983
+" Use this option in combination with --show or\n"
26984
+" with --error-prefix when you do not want to stop\n"
26985
+" a current redirection.\n"
2669826986
" --plain Use plain text rather than HTML tables with -w\n"
26699
-" --show Write the memory buffer to the screen, for debugging.\n"
26700
-" --verify ENDMARK Read subsequent lines of text until the first line\n"
26701
-" that matches ENDMARK. Discard the ENDMARK. Compare\n"
26702
-" the text against the accumulated output in memory and\n"
26703
-" raise an error if there are any differences.\n"
26987
+" --show Show output text captured by .testcase or by\n"
26988
+" redirecting to \"memory\".\n"
2670426989
" -w Show the output in a web browser. Output is\n"
2670526990
" written into a temporary HTML file until the\n"
2670626991
" redirect ends, then the web browser is launched.\n"
2670726992
" Query results are shown as HTML tables, unless\n"
2670826993
" the --plain is used too.\n"
@@ -26726,10 +27011,39 @@
2672627011
" file in a web browser\n"
2672727012
" -x Show the output in a spreadsheet. Output is\n"
2672827013
" written to a temp file as CSV then the spreadsheet\n"
2672927014
" is launched when\n"
2673027015
},
27016
+ { ".check",
27017
+"USAGE: .check [OPTIONS] PATTERN\n"
27018
+"\n"
27019
+"Verify results of commands since the most recent .testcase command.\n"
27020
+"Restore output to the console, unless --keep is used.\n"
27021
+"\n"
27022
+"If PATTERN starts with \"<<ENDMARK\" then the actual pattern is taken from\n"
27023
+"subsequent lines of text up to the first line that begins with ENDMARK.\n"
27024
+"All pattern lines and the ENDMARK are discarded.\n"
27025
+"\n"
27026
+"Options:\n"
27027
+" --exact Do an exact comparison including leading and\n"
27028
+" trailing whitespace.\n"
27029
+" --glob Treat PATTERN as a GLOB\n"
27030
+" --keep Do not reset the testcase. More .check commands\n"
27031
+" will follow.\n"
27032
+" --notglob Output should not match PATTERN\n"
27033
+" --show Write testcase output to the screen, for debugging.\n"
27034
+ },
27035
+ { ".testcase",
27036
+"USAGE: .testcase [OPTIONS] NAME\n"
27037
+"\n"
27038
+"Start a new test case identified by NAME. All output\n"
27039
+"through the next \".check\" command is captured for comparison. See the\n"
27040
+"\".check\" commandn for additional informatioon.\n"
27041
+"\n"
27042
+"Options:\n"
27043
+" --error-prefix TEXT Change error message prefix text to TEXT\n"
27044
+ },
2673127045
};
2673227046
2673327047
/*
2673427048
** Return a pointer to usage text for zCmd, or NULL if none exists.
2673527049
*/
@@ -26949,10 +27263,56 @@
2694927263
if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
2695027264
}
2695127265
return 1;
2695227266
}
2695327267
#endif
27268
+
27269
+/*
27270
+** Return the size of the named file in bytes. Or return a negative
27271
+** number if the file does not exist.
27272
+*/
27273
+static sqlite3_int64 fileSize(const char *zFile){
27274
+#if defined(_WIN32) || defined(WIN32)
27275
+ struct _stat64 x;
27276
+ if( _stat64(zFile, &x)!=0 ) return -1;
27277
+ return (sqlite3_int64)x.st_size;
27278
+#else
27279
+ struct stat x;
27280
+ if( stat(zFile, &x)!=0 ) return -1;
27281
+ return (sqlite3_int64)x.st_size;
27282
+#endif
27283
+}
27284
+
27285
+/*
27286
+** Return true if zFile is an SQLite database.
27287
+**
27288
+** Algorithm:
27289
+** * If the file does not exist -> return false
27290
+** * If the size of the file is not a multiple of 512 -> return false
27291
+** * If sqlite3_open() fails -> return false
27292
+** * if sqlite3_prepare() or sqlite3_step() fails -> return false
27293
+** * Otherwise -> return true
27294
+*/
27295
+static int isDatabaseFile(const char *zFile, int openFlags){
27296
+ sqlite3 *db = 0;
27297
+ sqlite3_stmt *pStmt = 0;
27298
+ int rc;
27299
+ sqlite3_int64 sz = fileSize(zFile);
27300
+ if( sz<512 || (sz%512)!=0 ) return 0;
27301
+ if( sqlite3_open_v2(zFile, &db, openFlags, 0)==SQLITE_OK
27302
+ && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
27303
+ ==SQLITE_OK
27304
+ && sqlite3_step(pStmt)==SQLITE_ROW
27305
+ ){
27306
+ rc = 1;
27307
+ }else{
27308
+ rc = 0;
27309
+ }
27310
+ sqlite3_finalize(pStmt);
27311
+ sqlite3_close(db);
27312
+ return rc;
27313
+}
2695427314
2695527315
/*
2695627316
** Try to deduce the type of file for zName based on its content. Return
2695727317
** one of the SHELL_OPEN_* constants.
2695827318
**
@@ -26962,24 +27322,16 @@
2696227322
** the type cannot be determined from content.
2696327323
*/
2696427324
int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
2696527325
FILE *f;
2696627326
size_t n;
26967
- sqlite3 *db = 0;
26968
- sqlite3_stmt *pStmt = 0;
2696927327
int rc = SHELL_OPEN_UNSPEC;
2697027328
char zBuf[100];
2697127329
if( access(zName,0)!=0 ) goto database_type_by_name;
26972
- if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK
26973
- && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
26974
- ==SQLITE_OK
26975
- && sqlite3_step(pStmt)==SQLITE_ROW
26976
- ){
27330
+ if( isDatabaseFile(zName, openFlags) ){
2697727331
rc = SHELL_OPEN_NORMAL;
2697827332
}
26979
- sqlite3_finalize(pStmt);
26980
- sqlite3_close(db);
2698127333
if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
2698227334
f = sqlite3_fopen(zName, "rb");
2698327335
if( f==0 ) goto database_type_by_name;
2698427336
n = fread(zBuf, 16, 1, f);
2698527337
if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
@@ -27009,10 +27361,37 @@
2700927361
}else{
2701027362
rc = SHELL_OPEN_NORMAL;
2701127363
}
2701227364
return rc;
2701327365
}
27366
+
27367
+/*
27368
+** If the text in z[] is the name of a readable file and that file appears
27369
+** to contain SQL text and/or dot-commands, then return true. If z[] is
27370
+** not a file, or if the file is unreadable, or if the file is a database
27371
+** or anything else that is not SQL text and dot-commands, then return false.
27372
+**
27373
+** If the bLeaveUninit flag is set, then be sure to leave SQLite in an
27374
+** uninitialized state. This means invoking sqlite3_shutdown() after any
27375
+** SQLite API is used.
27376
+**
27377
+** Some amount of guesswork is involved in this decision.
27378
+*/
27379
+static int isScriptFile(const char *z, int bLeaveUninit){
27380
+ sqlite3_int64 sz = fileSize(z);
27381
+ if( sz<=0 ) return 0;
27382
+ if( (sz%512)==0 ){
27383
+ int rc = isDatabaseFile(z, SQLITE_OPEN_READONLY);
27384
+ if( bLeaveUninit ){
27385
+ sqlite3_shutdown();
27386
+ }
27387
+ if( rc ) return 0; /* Is a database */
27388
+ }
27389
+ if( sqlite3_strlike("%.sql",z,0)==0 ) return 1;
27390
+ if( sqlite3_strlike("%.txt",z,0)==0 ) return 1;
27391
+ return 0;
27392
+}
2701427393
2701527394
#ifndef SQLITE_OMIT_DESERIALIZE
2701627395
/*
2701727396
** Reconstruct an in-memory database using the output from the "dbtotxt"
2701827397
** program. Read content from the file in p->aAuxDb[].zDbFilename.
@@ -27655,11 +28034,13 @@
2765528034
typedef struct ImportCtx ImportCtx;
2765628035
struct ImportCtx {
2765728036
const char *zFile; /* Name of the input file */
2765828037
FILE *in; /* Read the CSV text from this input stream */
2765928038
int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
28039
+ char *zIn; /* Input text */
2766028040
char *z; /* Accumulated text for a field */
28041
+ i64 nUsed; /* Bytes of zIn[] used so far */
2766128042
i64 n; /* Number of bytes in z */
2766228043
i64 nAlloc; /* Space allocated for z[] */
2766328044
int nLine; /* Current line number */
2766428045
int nRow; /* Number of rows imported */
2766528046
int nErr; /* Number of errors encountered */
@@ -27675,13 +28056,32 @@
2767528056
p->xCloser(p->in);
2767628057
p->in = 0;
2767728058
}
2767828059
sqlite3_free(p->z);
2767928060
p->z = 0;
28061
+ if( p->zIn ){
28062
+ sqlite3_free(p->zIn);
28063
+ p->zIn = 0;
28064
+ }
2768028065
}
2768128066
27682
-/* Append a single byte to z[] */
28067
+/* Read a single character of the .import input text. Return EOF
28068
+** at end-of-file.
28069
+*/
28070
+static int import_getc(ImportCtx *p){
28071
+ if( p->in ){
28072
+ return fgetc(p->in);
28073
+ }else if( p->zIn && p->zIn[p->nUsed]!=0 ){
28074
+ return p->zIn[p->nUsed++];
28075
+ }else{
28076
+ return EOF;
28077
+ }
28078
+}
28079
+
28080
+/* Append a single byte to the field value begin constructed
28081
+** in the p->z[] buffer
28082
+*/
2768328083
static void import_append_char(ImportCtx *p, int c){
2768428084
if( p->n+1>=p->nAlloc ){
2768528085
p->nAlloc += p->nAlloc + 100;
2768628086
p->z = sqlite3_realloc64(p->z, p->nAlloc);
2768728087
shell_check_oom(p->z);
@@ -27693,12 +28093,12 @@
2769328093
** with the option of having a separator other than ",".
2769428094
**
2769528095
** + Input comes from p->in.
2769628096
** + Store results in p->z of length p->n. Space to hold p->z comes
2769728097
** from sqlite3_malloc64().
27698
-** + Use p->cSep as the column separator. The default is ",".
27699
-** + Use p->rSep as the row separator. The default is "\n".
28098
+** + Use p->cColSep as the column separator. The default is ",".
28099
+** + Use p->cRowSep as the row separator. The default is "\n".
2770028100
** + Keep track of the line number in p->nLine.
2770128101
** + Store the character that terminates the field in p->cTerm. Store
2770228102
** EOF on end-of-file.
2770328103
** + Report syntax errors on stderr
2770428104
*/
@@ -27705,11 +28105,11 @@
2770528105
static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
2770628106
int c;
2770728107
int cSep = (u8)p->cColSep;
2770828108
int rSep = (u8)p->cRowSep;
2770928109
p->n = 0;
27710
- c = fgetc(p->in);
28110
+ c = import_getc(p);
2771128111
if( c==EOF || seenInterrupt ){
2771228112
p->cTerm = EOF;
2771328113
return 0;
2771428114
}
2771528115
if( c=='"' ){
@@ -27716,11 +28116,11 @@
2771628116
int pc, ppc;
2771728117
int startLine = p->nLine;
2771828118
int cQuote = c;
2771928119
pc = ppc = 0;
2772028120
while( 1 ){
27721
- c = fgetc(p->in);
28121
+ c = import_getc(p);
2772228122
if( c==rSep ) p->nLine++;
2772328123
if( c==cQuote ){
2772428124
if( pc==cQuote ){
2772528125
pc = 0;
2772628126
continue;
@@ -27752,24 +28152,24 @@
2775228152
}else{
2775328153
/* If this is the first field being parsed and it begins with the
2775428154
** UTF-8 BOM (0xEF BB BF) then skip the BOM */
2775528155
if( (c&0xff)==0xef && p->bNotFirst==0 ){
2775628156
import_append_char(p, c);
27757
- c = fgetc(p->in);
28157
+ c = import_getc(p);
2775828158
if( (c&0xff)==0xbb ){
2775928159
import_append_char(p, c);
27760
- c = fgetc(p->in);
28160
+ c = import_getc(p);
2776128161
if( (c&0xff)==0xbf ){
2776228162
p->bNotFirst = 1;
2776328163
p->n = 0;
2776428164
return csv_read_one_field(p);
2776528165
}
2776628166
}
2776728167
}
2776828168
while( c!=EOF && c!=cSep && c!=rSep ){
2776928169
import_append_char(p, c);
27770
- c = fgetc(p->in);
28170
+ c = import_getc(p);
2777128171
}
2777228172
if( c==rSep ){
2777328173
p->nLine++;
2777428174
if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
2777528175
}
@@ -27783,12 +28183,12 @@
2778328183
/* Read a single field of ASCII delimited text.
2778428184
**
2778528185
** + Input comes from p->in.
2778628186
** + Store results in p->z of length p->n. Space to hold p->z comes
2778728187
** from sqlite3_malloc64().
27788
-** + Use p->cSep as the column separator. The default is "\x1F".
27789
-** + Use p->rSep as the row separator. The default is "\x1E".
28188
+** + Use p->cColSep as the column separator. The default is "\x1F".
28189
+** + Use p->cRowSep as the row separator. The default is "\x1E".
2779028190
** + Keep track of the row number in p->nLine.
2779128191
** + Store the character that terminates the field in p->cTerm. Store
2779228192
** EOF on end-of-file.
2779328193
** + Report syntax errors on stderr
2779428194
*/
@@ -27795,18 +28195,18 @@
2779528195
static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
2779628196
int c;
2779728197
int cSep = (u8)p->cColSep;
2779828198
int rSep = (u8)p->cRowSep;
2779928199
p->n = 0;
27800
- c = fgetc(p->in);
28200
+ c = import_getc(p);
2780128201
if( c==EOF || seenInterrupt ){
2780228202
p->cTerm = EOF;
2780328203
return 0;
2780428204
}
2780528205
while( c!=EOF && c!=cSep && c!=rSep ){
2780628206
import_append_char(p, c);
27807
- c = fgetc(p->in);
28207
+ c = import_getc(p);
2780828208
}
2780928209
if( c==rSep ){
2781028210
p->nLine++;
2781128211
}
2781228212
p->cTerm = c;
@@ -29721,11 +30121,13 @@
2972130121
2972230122
p = sqlite3_recover_init_sql(
2972330123
pState->db, "main", recoverSqlCb, (void*)pState
2972430124
);
2972530125
29726
- sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */
30126
+ if( !pState->bSafeMode ){
30127
+ sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */
30128
+ }
2972730129
sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
2972830130
sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
2972930131
sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
2973030132
2973130133
cli_printf(pState->out, ".dbconfig defensive off\n");
@@ -30105,19 +30507,31 @@
3010530507
** USAGE: .import [OPTIONS] FILE TABLE
3010630508
**
3010730509
** Import CSV or similar text from FILE into TABLE. If TABLE does
3010830510
** not exist, it is created using the first row of FILE as the column
3010930511
** names. If FILE begins with "|" then it is a command that is run
30110
-** and the output from the command is used as the input data.
30512
+** and the output from the command is used as the input data. If
30513
+** FILE begins with "<<" followed by a label, then content is read from
30514
+** the script until the first line that matches the label.
30515
+**
30516
+** The content of FILE is interpreted using RFC-4180 ("CSV") quoting
30517
+** rules unless the current mode is "ascii" or "tabs" or unless one
30518
+** the --ascii option is used.
3011130519
**
30112
-** FILE is assumed to be in a CSV format, unless the current mode
30113
-** is "ascii" or "tabs" or unless one of the options below specify
30114
-** an alternative.
30520
+** The column and row separators must be single ASCII characters. If
30521
+** multiple characters or a Unicode character are specified for the
30522
+** separators, then only the first byte of the separator is used. Except,
30523
+** if the row separator is \n and the mode is not --ascii, then \r\n is
30524
+** understood as a row separator too.
3011530525
**
3011630526
** Options:
30117
-** --ascii Use \037 and \036 as column and row separators on input
30527
+** --ascii Do not use RFC-4180 quoting. Use \037 and \036
30528
+** as column and row separators on input, unless other
30529
+** delimiters are specified using --colsep and/or --rowsep
30530
+** --colsep CHAR Use CHAR as the column separator.
3011830531
** --csv Input is standard RFC-4180 CSV.
30532
+** --rowsep CHAR Use CHAR as the row separator.
3011930533
** --schema S When creating TABLE, put it in schema S
3012030534
** --skip N Ignore the first N rows of input
3012130535
** -v Verbose mode
3012230536
*/
3012330537
static int dotCmdImport(ShellState *p){
@@ -30129,17 +30543,16 @@
3012930543
sqlite3_stmt *pStmt = NULL; /* A statement */
3013030544
int nCol; /* Number of columns in the table */
3013130545
i64 nByte; /* Number of bytes in an SQL string */
3013230546
int i, j; /* Loop counters */
3013330547
int needCommit; /* True to COMMIT or ROLLBACK at end */
30134
- int nSep; /* Number of bytes in spec.zColumnSep */
3013530548
char *zSql = 0; /* An SQL statement */
3013630549
ImportCtx sCtx; /* Reader context */
3013730550
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
3013830551
int eVerbose = 0; /* Larger for more console output */
3013930552
i64 nSkip = 0; /* Initial lines to skip */
30140
- int useOutputMode = 1; /* Use output mode to determine separators */
30553
+ i64 iLineOffset = 0; /* Offset to the first line of input */
3014130554
char *zCreate = 0; /* CREATE TABLE statement text */
3014230555
int rc; /* Result code */
3014330556
3014430557
failIfSafeMode(p, "cannot run .import in safe mode");
3014530558
memset(&sCtx, 0, sizeof(sCtx));
@@ -30165,70 +30578,67 @@
3016530578
}else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
3016630579
zSchema = azArg[++i];
3016730580
}else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
3016830581
nSkip = integerValue(azArg[++i]);
3016930582
}else if( cli_strcmp(z,"-ascii")==0 ){
30170
- sCtx.cColSep = SEP_Unit[0];
30171
- sCtx.cRowSep = SEP_Record[0];
30583
+ if( sCtx.cColSep==0 ) sCtx.cColSep = SEP_Unit[0];
30584
+ if( sCtx.cRowSep==0 ) sCtx.cRowSep = SEP_Record[0];
3017230585
xRead = ascii_read_one_field;
30173
- useOutputMode = 0;
3017430586
}else if( cli_strcmp(z,"-csv")==0 ){
30175
- sCtx.cColSep = ',';
30176
- sCtx.cRowSep = '\n';
30587
+ if( sCtx.cColSep==0 ) sCtx.cColSep = ',';
30588
+ if( sCtx.cRowSep==0 ) sCtx.cRowSep = '\n';
3017730589
xRead = csv_read_one_field;
30178
- useOutputMode = 0;
30590
+ }else if( cli_strcmp(z,"-colsep")==0 ){
30591
+ if( i==nArg-1 ){
30592
+ dotCmdError(p, i, "missing argument", 0);
30593
+ return 1;
30594
+ }
30595
+ i++;
30596
+ sCtx.cColSep = azArg[i][0];
30597
+ }else if( cli_strcmp(z,"-rowsep")==0 ){
30598
+ if( i==nArg-1 ){
30599
+ dotCmdError(p, i, "missing argument", 0);
30600
+ return 1;
30601
+ }
30602
+ i++;
30603
+ sCtx.cRowSep = azArg[i][0];
3017930604
}else{
3018030605
dotCmdError(p, i, "unknown option", 0);
3018130606
return 1;
3018230607
}
3018330608
}
3018430609
if( zTable==0 ){
30185
- cli_printf(p->out, "ERROR: missing %s argument\n",
30610
+ dotCmdError(p, nArg, 0, "Missing %s argument\n",
3018630611
zFile==0 ? "FILE" : "TABLE");
3018730612
return 1;
3018830613
}
3018930614
seenInterrupt = 0;
3019030615
open_db(p, 0);
30191
- if( useOutputMode ){
30192
- /* If neither the --csv or --ascii options are specified, then set
30193
- ** the column and row separator characters from the output mode. */
30194
- if( p->mode.spec.zColumnSep==0 ){
30195
- modeSetStr(&p->mode.spec.zColumnSep, ",");
30196
- nSep = 1;
30197
- }else if( (nSep = strlen30(p->mode.spec.zColumnSep))==0 ){
30198
- eputz("Error: non-null column separator required for import\n");
30199
- return 1;
30200
- }
30201
- if( nSep>1 ){
30202
- eputz("Error: multi-character column separators not allowed"
30203
- " for import\n");
30204
- return 1;
30205
- }
30206
- if( p->mode.spec.zRowSep==0 ){
30207
- modeSetStr(&p->mode.spec.zRowSep, "\n");
30208
- nSep = 1;
30209
- }else if( (nSep = strlen30(p->mode.spec.zRowSep))==0 ){
30210
- eputz("Error: non-null row separator required for import\n");
30211
- return 1;
30212
- }
30213
- if( nSep==2 && p->mode.eMode==MODE_Csv
30214
- && cli_strcmp(p->mode.spec.zRowSep,SEP_CrLf)==0
30215
- ){
30216
- /* When importing CSV (only), if the row separator is set to the
30217
- ** default output row separator, change it to the default input
30218
- ** row separator. This avoids having to maintain different input
30219
- ** and output row separators. */
30220
- modeSetStr(&p->mode.spec.zRowSep, SEP_Row);
30221
- nSep = strlen30(p->mode.spec.zRowSep);
30222
- }
30223
- if( nSep>1 ){
30224
- eputz("Error: multi-character row separators not allowed"
30225
- " for import\n");
30226
- return 1;
30227
- }
30228
- sCtx.cColSep = (u8)p->mode.spec.zColumnSep[0];
30229
- sCtx.cRowSep = (u8)p->mode.spec.zRowSep[0];
30616
+ if( sCtx.cColSep==0 ){
30617
+ if( p->mode.spec.zColumnSep && p->mode.spec.zColumnSep[0]!=0 ){
30618
+ sCtx.cColSep = p->mode.spec.zColumnSep[0];
30619
+ }else{
30620
+ sCtx.cColSep = ',';
30621
+ }
30622
+ }
30623
+ if( (sCtx.cColSep & 0x80)!=0 ){
30624
+ eputz("Error: .import column separator must be ASCII\n");
30625
+ return 1;
30626
+ }
30627
+ if( sCtx.cRowSep==0 ){
30628
+ if( p->mode.spec.zRowSep && p->mode.spec.zRowSep[0]!=0 ){
30629
+ sCtx.cRowSep = p->mode.spec.zRowSep[0];
30630
+ }else{
30631
+ sCtx.cRowSep = '\n';
30632
+ }
30633
+ }
30634
+ if( sCtx.cRowSep=='\r' && xRead!=ascii_read_one_field ){
30635
+ sCtx.cRowSep = '\n';
30636
+ }
30637
+ if( (sCtx.cRowSep & 0x80)!=0 ){
30638
+ eputz("Error: .import row separator must be ASCII\n");
30639
+ return 1;
3023030640
}
3023130641
sCtx.zFile = zFile;
3023230642
sCtx.nLine = 1;
3023330643
if( sCtx.zFile[0]=='|' ){
3023430644
#ifdef SQLITE_OMIT_POPEN
@@ -30237,19 +30647,58 @@
3023730647
#else
3023830648
sCtx.in = sqlite3_popen(sCtx.zFile+1, "r");
3023930649
sCtx.zFile = "<pipe>";
3024030650
sCtx.xCloser = pclose;
3024130651
#endif
30652
+ }else if( sCtx.zFile[0]=='<' && sCtx.zFile[1]=='<' && sCtx.zFile[2]!=0 ){
30653
+ /* Input text comes from subsequent lines of script until the zFile
30654
+ ** delimiter */
30655
+ int nEndMark = strlen30(zFile)-2;
30656
+ char *zEndMark = &zFile[2];
30657
+ sqlite3_str *pContent = sqlite3_str_new(p->db);
30658
+ int ckEnd = 1;
30659
+ i64 iStart = p->lineno;
30660
+ char zLine[2000];
30661
+ sCtx.zFile = p->zInFile;
30662
+ sCtx.nLine = p->lineno+1;
30663
+ iLineOffset = p->lineno;
30664
+ while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
30665
+ if( ckEnd && cli_strncmp(zLine,zEndMark,nEndMark)==0 ){
30666
+ ckEnd = 2;
30667
+ if( strchr(zLine,'\n') ) p->lineno++;
30668
+ break;
30669
+ }
30670
+ if( strchr(zLine,'\n') ){
30671
+ p->lineno++;
30672
+ ckEnd = 1;
30673
+ }else{
30674
+ ckEnd = 0;
30675
+ }
30676
+ sqlite3_str_appendall(pContent, zLine);
30677
+ }
30678
+ sCtx.zIn = sqlite3_str_finish(pContent);
30679
+ if( sCtx.zIn==0 ){
30680
+ sCtx.zIn = sqlite3_mprintf("");
30681
+ }
30682
+ if( ckEnd<2 ){
30683
+ i64 savedLn = p->lineno;
30684
+ p->lineno = iStart;
30685
+ dotCmdError(p, 0, 0,"Content terminator \"%s\" not found.",zEndMark);
30686
+ p->lineno = savedLn;
30687
+ import_cleanup(&sCtx);
30688
+ return 1;
30689
+ }
3024230690
}else{
3024330691
sCtx.in = sqlite3_fopen(sCtx.zFile, "rb");
3024430692
sCtx.xCloser = fclose;
3024530693
}
30246
- if( sCtx.in==0 ){
30247
- cli_printf(stderr,"Error: cannot open \"%s\"\n", zFile);
30694
+ if( sCtx.in==0 && sCtx.zIn==0 ){
30695
+ dotCmdError(p, 0, 0, "cannot open \"%s\"", zFile);
30696
+ import_cleanup(&sCtx);
3024830697
return 1;
3024930698
}
30250
- if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
30699
+ if( eVerbose>=1 ){
3025130700
char zSep[2];
3025230701
zSep[1] = 0;
3025330702
zSep[0] = sCtx.cColSep;
3025430703
cli_puts("Column separator ", p->out);
3025530704
output_c_string(p->out, zSep);
@@ -30402,10 +30851,14 @@
3040230851
if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){
3040330852
z = "";
3040430853
}
3040530854
sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
3040630855
if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
30856
+ if( i==0 && (strcmp(z,"\n")==0 || strcmp(z,"\r\n")==0) ){
30857
+ /* Ignore trailing \n or \r\n when some other row separator */
30858
+ break;
30859
+ }
3040730860
cli_printf(stderr,"%s:%d: expected %d columns but found %d"
3040830861
" - filling the rest with NULL\n",
3040930862
sCtx.zFile, startLine, nCol, i+1);
3041030863
i += 2;
3041130864
while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
@@ -30425,10 +30878,11 @@
3042530878
rc = sqlite3_reset(pStmt);
3042630879
if( rc!=SQLITE_OK ){
3042730880
cli_printf(stderr,"%s:%d: INSERT failed: %s\n",
3042830881
sCtx.zFile, startLine, sqlite3_errmsg(p->db));
3042930882
sCtx.nErr++;
30883
+ if( bail_on_error ) break;
3043030884
}else{
3043130885
sCtx.nRow++;
3043230886
}
3043330887
}
3043430888
}while( sCtx.cTerm!=EOF );
@@ -30437,13 +30891,13 @@
3043730891
sqlite3_finalize(pStmt);
3043830892
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
3043930893
if( eVerbose>0 ){
3044030894
cli_printf(p->out,
3044130895
"Added %d rows with %d errors using %d lines of input\n",
30442
- sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
30896
+ sCtx.nRow, sCtx.nErr, sCtx.nLine-1-iLineOffset);
3044330897
}
30444
- return 0;
30898
+ return sCtx.nErr ? 1 : 0;
3044530899
}
3044630900
3044730901
3044830902
/*
3044930903
** This function computes what to show the user about the configured
@@ -30508,10 +30962,11 @@
3050830962
** meaning "left", "centered", and "right", with
3050930963
** one letter per column starting from the left.
3051030964
** Unspecified alignment defaults to 'L'.
3051130965
** --blob-quote ARG ARG can be "auto", "text", "sql", "hex", "tcl",
3051230966
** "json", or "size". Default is "auto".
30967
+** --border on|off Show outer border on "box" and "table" modes.
3051330968
** --charlimit N Set the maximum number of output characters to
3051430969
** show for any single SQL value to N. Longer values
3051530970
** truncated. Zero means "no limit".
3051630971
** --colsep STRING Use STRING as the column separator
3051730972
** --escape ESC Enable/disable escaping of control characters
@@ -30519,19 +30974,22 @@
3051930974
** or "symbol".
3052030975
** --linelimit N Set the maximum number of output lines to show for
3052130976
** any single SQL value to N. Longer values are
3052230977
** truncated. Zero means "no limit". Only works
3052330978
** in "line" mode and in columnar modes.
30524
-** --limits L,C Shorthand for "--linelimit L --charlimit C".
30525
-** Or "off" to mean "0,0". Or "on" for "5,300".
30979
+** --limits L,C,T Shorthand for "--linelimit L --charlimit C
30980
+** --titlelimit T". The ",T" can be omitted in which
30981
+** case the --titlelimit is unchanged. The argument
30982
+** can also be "off" to mean "0,0,0" or "on" to
30983
+** mean "5,300,20".
3052630984
** --list List available modes
3052730985
** --null STRING Render SQL NULL values as the given string
3052830986
** --once Setting changes to the right are reverted after
3052930987
** the next SQL command.
3053030988
** --quote ARG Enable/disable quoting of text. ARG can be
30531
-** "off", "on", "sql", "csv", "html", "tcl",
30532
-** or "json". "off" means show the text as-is.
30989
+** "off", "on", "sql", "relaxed", "csv", "html",
30990
+** "tcl", or "json". "off" means show the text as-is.
3053330991
** "on" is an alias for "sql".
3053430992
** --reset Changes all mode settings back to their default.
3053530993
** --rowsep STRING Use STRING as the row separator
3053630994
** --sw|--screenwidth N Declare the screen width of the output device
3053730995
** to be N characters. An attempt may be made to
@@ -30542,10 +31000,11 @@
3054231000
** --tag NAME Save mode to the left as NAME.
3054331001
** --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON.
3054431002
** --title ARG Whether or not to show column headers, and if so
3054531003
** how to encode them. ARG can be "off", "on",
3054631004
** "sql", "csv", "html", "tcl", or "json".
31005
+** --titlelimit N Limit the length of column titles to N characters.
3054731006
** -v|--verbose Verbose output
3054831007
** --widths LIST Set the columns widths for columnar modes. The
3054931008
** argument is a list of integers, one for each
3055031009
** column. A "0" width means use a dynamic width
3055131010
** based on the actual width of data. If there are
@@ -30626,21 +31085,31 @@
3062631085
** Must match QRF_BLOB_xxxx values. See also tag-20251124a */
3062731086
if( k>=0 ){
3062831087
p->mode.spec.eBlob = k & 0xff;
3062931088
}
3063031089
chng = 1;
30631
- }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","")) ){
31090
+ }else if( optionMatch(z,"border") ){
31091
+ if( (++i)>=nArg ){
31092
+ dotCmdError(p, i-1, "missing argument", 0);
31093
+ return 1;
31094
+ }
31095
+ k = pickStr(azArg[i], 0, "auto", "off", "on", "");
31096
+ if( k>=0 ){
31097
+ p->mode.spec.bBorder = k & 0x3;
31098
+ }
31099
+ chng = 1;
31100
+ }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","-titlelimit","")) ){
3063231101
int w; /* 0 1 */
3063331102
if( i+1>=nArg ){
3063431103
dotCmdError(p, i, "missing argument", 0);
3063531104
return 1;
3063631105
}
3063731106
w = integerValue(azArg[++i]);
30638
- if( k==0 ){
30639
- p->mode.spec.nCharLimit = w;
30640
- }else{
30641
- p->mode.spec.nLineLimit = w;
31107
+ switch( k ){
31108
+ case 0: p->mode.spec.nCharLimit = w; break;
31109
+ case 1: p->mode.spec.nLineLimit = w; break;
31110
+ default: p->mode.spec.nTitleLimit = w; break;
3064231111
}
3064331112
chng = 1;
3064431113
}else if( 0<=(k=pickStr(z,0,"-tablename","-rowsep","-colsep","-null","")) ){
3064531114
/* 0 1 2 3 */
3064631115
if( i+1>=nArg ){
@@ -30675,25 +31144,28 @@
3067531144
dotCmdError(p, i-1, "missing argument", 0);
3067631145
return 1;
3067731146
}
3067831147
k = pickStr(azArg[i],0,"on","off","");
3067931148
if( k==0 ){
30680
- p->mode.spec.nLineLimit = 5;
30681
- p->mode.spec.nCharLimit = 300;
31149
+ p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
31150
+ p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
31151
+ p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
3068231152
}else if( k==1 ){
3068331153
p->mode.spec.nLineLimit = 0;
3068431154
p->mode.spec.nCharLimit = 0;
31155
+ p->mode.spec.nTitleLimit = 0;
3068531156
}else{
30686
- int L, C;
30687
- int nNum = sscanf(azArg[i], "%d,%d", &L, &C);
30688
- if( nNum!=2 || L<0 || C<0 ){
30689
- dotCmdError(p, i, "bad argument", "Should be \"L,C\" where L and C"
30690
- " are unsigned integers");
31157
+ int L, C, T = 0;
31158
+ int nNum = sscanf(azArg[i], "%d,%d,%d", &L, &C, &T);
31159
+ if( nNum<2 || L<0 || C<0 || T<0){
31160
+ dotCmdError(p, i, "bad argument", "Should be \"L,C,T\" where L, C"
31161
+ " and T are unsigned integers");
3069131162
return 1;
3069231163
}
3069331164
p->mode.spec.nLineLimit = L;
3069431165
p->mode.spec.nCharLimit = C;
31166
+ if( nNum==3 ) p->mode.spec.nTitleLimit = T;
3069531167
}
3069631168
chng = 1;
3069731169
}else if( optionMatch(z,"list") ){
3069831170
int ii;
3069931171
cli_puts("available modes:", p->out);
@@ -30726,13 +31198,14 @@
3072631198
** how to set quoting. */
3072731199
i++;
3072831200
if( (k = pickStr(azArg[i],0,"no","yes","0","1",""))>=0 ){
3072931201
k &= 1; /* 0 for "off". 1 for "on". */
3073031202
}else{
30731
- char *zErr = 0; /* 0 1 2 3 4 5 6 */
30732
- k = pickStr(azArg[i],&zErr,"off","on","sql","csv","html","tcl","json",
30733
- "");
31203
+ char *zErr = 0;
31204
+ k = pickStr(azArg[i],&zErr,
31205
+ "off","on","sql","csv","html","tcl","json","relaxed","");
31206
+ /* 0 1 2 3 4 5 6 7 */
3073431207
if( k<0 ){
3073531208
dotCmdError(p, i, "unknown", "%z", zErr);
3073631209
return 1;
3073731210
}
3073831211
}
@@ -30757,10 +31230,13 @@
3075731230
p->mode.spec.eText = QRF_TEXT_Tcl;
3075831231
break;
3075931232
case 6: /* json */
3076031233
p->mode.spec.eText = QRF_TEXT_Json;
3076131234
break;
31235
+ case 7: /* relaxed */
31236
+ p->mode.spec.eText = QRF_TEXT_Relaxed;
31237
+ break;
3076231238
default: /* off */
3076331239
p->mode.spec.eText = QRF_TEXT_Plain;
3076431240
break;
3076531241
}
3076631242
chng = 1;
@@ -30832,10 +31308,11 @@
3083231308
if( k<0 ){
3083331309
dotCmdError(p, i, "bad --titles value","%z", zErr);
3083431310
return 1;
3083531311
}
3083631312
p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No;
31313
+ p->mode.mFlags &= ~MFLG_HDR;
3083731314
p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr;
3083831315
chng = 1;
3083931316
}else if( optionMatch(z,"widths") || optionMatch(z,"width") ){
3084031317
int nWidth = 0;
3084131318
short int *aWidth;
@@ -30847,16 +31324,16 @@
3084731324
zW = azArg[++i];
3084831325
/* Every width value takes at least 2 bytes in the input string to
3084931326
** specify, so strlen(zW) bytes should be plenty of space to hold the
3085031327
** result. */
3085131328
aWidth = malloc( strlen(zW) );
30852
- while( isspace(zW[0]) ) zW++;
31329
+ while( IsSpace(zW[0]) ) zW++;
3085331330
while( zW[0] ){
3085431331
int w = 0;
3085531332
int nDigit = 0;
30856
- k = zW[0]=='-' && isdigit(zW[1]);
30857
- while( isdigit(zW[k]) ){
31333
+ k = zW[0]=='-' && IsDigit(zW[1]);
31334
+ while( IsDigit(zW[k]) ){
3085831335
w = w*10 + zW[k] - '0';
3085931336
if( w>QRF_MAX_WIDTH ){
3086031337
dotCmdError(p,i+1,"width too big",
3086131338
"Maximum column width is %d", QRF_MAX_WIDTH);
3086231339
free(aWidth);
@@ -30873,11 +31350,11 @@
3087331350
}
3087431351
if( zW[0]=='-' ) w = -w;
3087531352
aWidth[nWidth++] = w;
3087631353
zW += k;
3087731354
if( zW[0]==',' ) zW++;
30878
- while( isspace(zW[0]) ) zW++;
31355
+ while( IsSpace(zW[0]) ) zW++;
3087931356
}
3088031357
free(p->mode.spec.aWidth);
3088131358
p->mode.spec.aWidth = aWidth;
3088231359
p->mode.spec.nWidth = nWidth;
3088331360
chng = 1;
@@ -30928,39 +31405,52 @@
3092831405
unsigned char a = p->mode.spec.aAlign[ii];
3092931406
sqlite3_str_appendchar(pDesc, 1, "LLCR"[a&3]);
3093031407
}
3093131408
sqlite3_str_append(pDesc, "\"", 1);
3093231409
}
31410
+ if( bAll
31411
+ || (p->mode.spec.bBorder==QRF_No) != ((pI->mFlg&1)!=0)
31412
+ ){
31413
+ sqlite3_str_appendf(pDesc," --border %s",
31414
+ p->mode.spec.bBorder==QRF_No ? "off" : "on");
31415
+ }
3093331416
if( bAll || p->mode.spec.eBlob!=QRF_BLOB_Auto ){
3093431417
const char *azBQuote[] =
3093531418
{ "auto", "text", "sql", "hex", "tcl", "json", "size" };
3093631419
/* 0 1 2 3 4 5 6
3093731420
** Must match QRF_BLOB_xxxx values. See all instances of tag-20251124a */
3093831421
u8 e = p->mode.spec.eBlob;
3093931422
sqlite3_str_appendf(pDesc, " --blob-quote %s", azBQuote[e]);
3094031423
}
30941
- if( !bAll && p->mode.spec.nLineLimit==0 && p->mode.spec.nCharLimit>0 ){
30942
- sqlite3_str_appendf(pDesc, " --charlimit %d",p->mode.spec.nCharLimit);
30943
- }
3094431424
zSetting = aModeStr[pI->eCSep];
3094531425
if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zColumnSep)!=0) ){
3094631426
sqlite3_str_appendf(pDesc, " --colsep ");
3094731427
append_c_string(pDesc, p->mode.spec.zColumnSep);
3094831428
}
3094931429
if( bAll || p->mode.spec.eEsc!=QRF_Auto ){
3095031430
sqlite3_str_appendf(pDesc, " --escape %s",qrfEscNames[p->mode.spec.eEsc]);
3095131431
}
30952
- if( bAll || (p->mode.spec.nLineLimit>0 && p->mode.spec.nCharLimit>0) ){
30953
- if( p->mode.spec.nLineLimit==0 && p->mode.spec.nCharLimit==0 ){
31432
+ if( bAll
31433
+ || (p->mode.spec.nLineLimit>0 && pI->eCx>0)
31434
+ || p->mode.spec.nCharLimit>0
31435
+ || (p->mode.spec.nTitleLimit>0 && pI->eCx>0)
31436
+ ){
31437
+ if( p->mode.spec.nLineLimit==0
31438
+ && p->mode.spec.nCharLimit==0
31439
+ && p->mode.spec.nTitleLimit==0
31440
+ ){
3095431441
sqlite3_str_appendf(pDesc, " --limits off");
31442
+ }else if( p->mode.spec.nLineLimit==DFLT_LINE_LIMIT
31443
+ && p->mode.spec.nCharLimit==DFLT_CHAR_LIMIT
31444
+ && p->mode.spec.nTitleLimit==DFLT_TITLE_LIMIT
31445
+ ){
31446
+ sqlite3_str_appendf(pDesc, " --limits on");
3095531447
}else{
30956
- sqlite3_str_appendf(pDesc, " --limits %d,%d",
30957
- p->mode.spec.nLineLimit, p->mode.spec.nCharLimit);
31448
+ sqlite3_str_appendf(pDesc, " --limits %d,%d,%d",
31449
+ p->mode.spec.nLineLimit, p->mode.spec.nCharLimit,
31450
+ p->mode.spec.nTitleLimit);
3095831451
}
30959
- }else
30960
- if( p->mode.spec.nCharLimit==0 && p->mode.spec.nLineLimit>0 && pI->eCx>0 ){
30961
- sqlite3_str_appendf(pDesc, " --linelimit %d",p->mode.spec.nLineLimit);
3096231452
}
3096331453
zSetting = aModeStr[pI->eNull];
3096431454
if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zNull)!=0) ){
3096531455
sqlite3_str_appendf(pDesc, " --null ");
3096631456
append_c_string(pDesc, p->mode.spec.zNull);
@@ -30977,13 +31467,13 @@
3097731467
}
3097831468
if( bAll
3097931469
|| (pI->eCx && (p->mode.spec.nScreenWidth>0 || p->mode.bAutoScreenWidth))
3098031470
){
3098131471
if( p->mode.bAutoScreenWidth ){
30982
- sqlite3_str_appendall(pDesc, " --screenwidth auto");
31472
+ sqlite3_str_appendall(pDesc, " --sw auto");
3098331473
}else{
30984
- sqlite3_str_appendf(pDesc," --screenwidth %d",
31474
+ sqlite3_str_appendf(pDesc," --sw %d",
3098531475
p->mode.spec.nScreenWidth);
3098631476
}
3098731477
}
3098831478
if( bAll || p->mode.eMode==MODE_Insert ){
3098931479
sqlite3_str_appendf(pDesc," --tablename ");
@@ -31023,11 +31513,11 @@
3102331513
sqlite3_str_appendf(pDesc, " --wrap %d", p->mode.spec.nWrap);
3102431514
}
3102531515
if( !bAll ) sqlite3_str_append(pDesc, " --ww", 5);
3102631516
}
3102731517
zDesc = sqlite3_str_finish(pDesc);
31028
- cli_printf(p->out, "current output mode: %s\n", zDesc);
31518
+ cli_printf(p->out, ".mode %s\n", zDesc);
3102931519
fflush(p->out);
3103031520
sqlite3_free(zDesc);
3103131521
}
3103231522
return 0;
3103331523
}
@@ -31047,23 +31537,17 @@
3104731537
** --bom Prepend a byte-order mark to the output
3104831538
** -e Accumulate output in a temporary text file then
3104931539
** launch a text editor when the redirection ends.
3105031540
** --error-prefix X Use X as the left-margin prefix for error messages.
3105131541
** Set to an empty string to restore the default.
31052
-** --glob GLOB Raise an error if the memory buffer does not match
31053
-** the GLOB pattern.
31054
-** --keep Continue using the same "memory" buffer. Do not
31055
-** reset it or delete it. Useful in combination with
31056
-** --glob, --not-glob, and/or --verify.
31057
-** ---notglob GLOB Raise an error if the memory buffer does not match
31058
-** the GLOB pattern.
31542
+** --keep Keep redirecting output to its current destination.
31543
+** Use this option in combination with --show or
31544
+** with --error-prefix when you do not want to stop
31545
+** a current redirection.
3105931546
** --plain Use plain text rather than HTML tables with -w
31060
-** --show Write the memory buffer to the screen, for debugging.
31061
-** --verify ENDMARK Read subsequent lines of text until the first line
31062
-** that matches ENDMARK. Discard the ENDMARK. Compare
31063
-** the text against the accumulated output in memory and
31064
-** raise an error if there are any differences.
31547
+** --show Show output text captured by .testcase or by
31548
+** redirecting to "memory".
3106531549
** -w Show the output in a web browser. Output is
3106631550
** written into a temporary HTML file until the
3106731551
** redirect ends, then the web browser is launched.
3106831552
** Query results are shown as HTML tables, unless
3106931553
** the --plain is used too.
@@ -31101,13 +31585,11 @@
3110131585
char *zFile = 0; /* The FILE argument */
3110231586
int i; /* Loop counter */
3110331587
int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */
3110431588
int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */
3110531589
int bPlain = 0; /* --plain option */
31106
- int bKeep = 0; /* --keep option */
31107
- char *zCheck = 0; /* Argument to --glob, --notglob, --verify */
31108
- int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --verify */
31590
+ int bKeep = 0; /* Keep redirecting */
3110931591
static const char *zBomUtf8 = "\357\273\277";
3111031592
const char *zBom = 0;
3111131593
char c = azArg[0][0];
3111231594
int n = strlen30(azArg[0]);
3111331595
@@ -31129,36 +31611,21 @@
3112931611
zBom = zBomUtf8;
3113031612
}else if( cli_strcmp(z,"-plain")==0 ){
3113131613
bPlain = 1;
3113231614
}else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
3113331615
&& (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
31134
- if( bKeep || eMode || eCheck ){
31616
+ if( bKeep || eMode ){
3113531617
dotCmdError(p, i, "incompatible with prior options",0);
3113631618
goto dotCmdOutput_error;
3113731619
}
3113831620
eMode = z[1];
31139
- }else if( cli_strcmp(z,"-keep")==0 ){
31140
- bKeep = 1;
3114131621
}else if( cli_strcmp(z,"-show")==0 ){
3114231622
if( cli_output_capture ){
3114331623
sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
3114431624
}
31625
+ }else if( cli_strcmp(z,"-keep")==0 ){
3114531626
bKeep = 1;
31146
- }else if( cli_strcmp(z,"-glob")==0
31147
- || cli_strcmp(z,"-notglob")==0
31148
- || cli_strcmp(z,"-verify")==0
31149
- ){
31150
- if( eCheck || eMode ){
31151
- dotCmdError(p, i, "incompatible with prior options",0);
31152
- goto dotCmdOutput_error;
31153
- }
31154
- if( i+1>=nArg ){
31155
- dotCmdError(p, i, "missing argument", 0);
31156
- goto dotCmdOutput_error;
31157
- }
31158
- zCheck = azArg[++i];
31159
- eCheck = z[1]=='g' ? 1 : z[1]=='n' ? 2 : 3;
3116031627
}else if( optionMatch(z,"error-prefix") ){
3116131628
if( i+1>=nArg ){
3116231629
dotCmdError(p, i, "missing argument", 0);
3116331630
return 1;
3116431631
}
@@ -31169,11 +31636,11 @@
3116931636
dotCmdError(p, i, "unknown option", 0);
3117031637
sqlite3_free(zFile);
3117131638
return 1;
3117231639
}
3117331640
}else if( zFile==0 && eMode==0 ){
31174
- if( bKeep || eCheck ){
31641
+ if( bKeep ){
3117531642
dotCmdError(p, i, "incompatible with prior options",0);
3117631643
goto dotCmdOutput_error;
3117731644
}
3117831645
if( cli_strcmp(z, "memory")==0 && bOnce ){
3117931646
dotCmdError(p, 0, "cannot redirect to \"memory\"", 0);
@@ -31205,53 +31672,10 @@
3120531672
if( bOnce ){
3120631673
p->nPopOutput = 2;
3120731674
}else{
3120831675
p->nPopOutput = 0;
3120931676
}
31210
- if( eCheck ){
31211
- char *zTest;
31212
- if( cli_output_capture ){
31213
- zTest = sqlite3_str_value(cli_output_capture);
31214
- }else{
31215
- zTest = "";
31216
- }
31217
- p->nTestRun++;
31218
- if( eCheck==3 ){
31219
- int nCheck = strlen30(zCheck);
31220
- sqlite3_str *pPattern = sqlite3_str_new(p->db);
31221
- char *zPattern;
31222
- sqlite3_int64 iStart = p->lineno;
31223
- char zLine[2000];
31224
- while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
31225
- if( strchr(zLine,'\n') ) p->lineno++;
31226
- if( cli_strncmp(zCheck,zLine,nCheck)==0 ) break;
31227
- sqlite3_str_appendall(pPattern, zLine);
31228
- }
31229
- zPattern = sqlite3_str_finish(pPattern);
31230
- if( cli_strcmp(zPattern,zTest)!=0 ){
31231
- sqlite3_fprintf(stderr,
31232
- "%s:%lld: --verify does matches prior output\n",
31233
- p->zInFile, iStart);
31234
- p->nTestErr++;
31235
- }
31236
- sqlite3_free(zPattern);
31237
- }else{
31238
- char *zGlob = sqlite3_mprintf("*%s*", zCheck);
31239
- if( eCheck==1 && sqlite3_strglob(zGlob, zTest)!=0 ){
31240
- sqlite3_fprintf(stderr,
31241
- "%s:%lld: --glob \"%s\" does not match prior output\n",
31242
- p->zInFile, p->lineno, zCheck);
31243
- p->nTestErr++;
31244
- }else if( eCheck==2 && sqlite3_strglob(zGlob, zTest)==0 ){
31245
- sqlite3_fprintf(stderr,
31246
- "%s:%lld: --notglob \"%s\" matches prior output\n",
31247
- p->zInFile, p->lineno, zCheck);
31248
- p->nTestErr++;
31249
- }
31250
- sqlite3_free(zGlob);
31251
- }
31252
- }
3125331677
if( !bKeep ) output_reset(p);
3125431678
#ifndef SQLITE_NOHAVE_SYSTEM
3125531679
if( eMode=='e' || eMode=='x' || eMode=='w' ){
3125631680
p->doXdgOpen = 1;
3125731681
modePush(p);
@@ -31328,10 +31752,199 @@
3132831752
3132931753
dotCmdOutput_error:
3133031754
sqlite3_free(zFile);
3133131755
return 1;
3133231756
}
31757
+
31758
+/*
31759
+** DOT-COMMAND: .check
31760
+** USAGE: .check [OPTIONS] PATTERN
31761
+**
31762
+** Verify results of commands since the most recent .testcase command.
31763
+** Restore output to the console, unless --keep is used.
31764
+**
31765
+** If PATTERN starts with "<<ENDMARK" then the actual pattern is taken from
31766
+** subsequent lines of text up to the first line that begins with ENDMARK.
31767
+** All pattern lines and the ENDMARK are discarded.
31768
+**
31769
+** Options:
31770
+** --exact Do an exact comparison including leading and
31771
+** trailing whitespace.
31772
+** --glob Treat PATTERN as a GLOB
31773
+** --keep Do not reset the testcase. More .check commands
31774
+** will follow.
31775
+** --notglob Output should not match PATTERN
31776
+** --show Write testcase output to the screen, for debugging.
31777
+*/
31778
+static int dotCmdCheck(ShellState *p){
31779
+ int nArg = p->dot.nArg; /* Number of arguments */
31780
+ char **azArg = p->dot.azArg; /* Text of the arguments */
31781
+ int i; /* Loop counter */
31782
+ int k; /* Result of pickStr() */
31783
+ char *zTest; /* Textcase result */
31784
+ int bKeep = 0; /* --keep option */
31785
+ char *zCheck = 0; /* PATTERN argument */
31786
+ char *zPattern = 0; /* Actual test pattern */
31787
+ int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --exact */
31788
+ int isOk; /* True if results are OK */
31789
+ sqlite3_int64 iStart = p->lineno; /* Line number of .check statement */
31790
+
31791
+ if( p->zTestcase[0]==0 ){
31792
+ dotCmdError(p, 0, "no .testcase is active", 0);
31793
+ return 1;
31794
+ }
31795
+ for(i=1; i<nArg; i++){
31796
+ char *z = azArg[i];
31797
+ if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++;
31798
+ if( cli_strcmp(z,"-keep")==0 ){
31799
+ bKeep = 1;
31800
+ }else if( cli_strcmp(z,"-show")==0 ){
31801
+ if( cli_output_capture ){
31802
+ sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
31803
+ }
31804
+ bKeep = 1;
31805
+ }else if( z[0]=='-'
31806
+ && (k = pickStr(&z[1],0,"glob","notglob","exact",""))>=0
31807
+ ){
31808
+ if( eCheck && eCheck!=k+1 ){
31809
+ dotCmdError(p, i, "incompatible with prior options",0);
31810
+ return 1;
31811
+ }
31812
+ eCheck = k+1;
31813
+ }else if( zCheck ){
31814
+ dotCmdError(p, i, "unknown option", 0);
31815
+ return 1;
31816
+ }else{
31817
+ zCheck = azArg[i];
31818
+ }
31819
+ }
31820
+ if( zCheck==0 ){
31821
+ dotCmdError(p, 0, "no PATTERN specified", 0);
31822
+ return 1;
31823
+ }
31824
+ if( cli_output_capture && sqlite3_str_length(cli_output_capture) ){
31825
+ zTest = sqlite3_str_value(cli_output_capture);
31826
+ shell_check_oom(zTest);
31827
+ }else{
31828
+ zTest = "";
31829
+ }
31830
+ p->nTestRun++;
31831
+ if( zCheck[0]=='<' && zCheck[1]=='<' && zCheck[2]!=0 ){
31832
+ int nCheck = strlen30(zCheck);
31833
+ sqlite3_str *pPattern = sqlite3_str_new(p->db);
31834
+ char zLine[2000];
31835
+ while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
31836
+ if( strchr(zLine,'\n') ) p->lineno++;
31837
+ if( cli_strncmp(&zCheck[2],zLine,nCheck-2)==0 ) break;
31838
+ sqlite3_str_appendall(pPattern, zLine);
31839
+ }
31840
+ zPattern = sqlite3_str_finish(pPattern);
31841
+ if( zPattern==0 ){
31842
+ zPattern = sqlite3_mprintf("");
31843
+ }
31844
+ }else{
31845
+ zPattern = zCheck;
31846
+ }
31847
+ shell_check_oom(zPattern);
31848
+ switch( eCheck ){
31849
+ case 1: {
31850
+ char *zGlob = sqlite3_mprintf("*%s*", zPattern);
31851
+ isOk = testcase_glob(zGlob, zTest)!=0;
31852
+ sqlite3_free(zGlob);
31853
+ break;
31854
+ }
31855
+ case 2: {
31856
+ char *zGlob = sqlite3_mprintf("*%s*", zPattern);
31857
+ isOk = testcase_glob(zGlob, zTest)==0;
31858
+ sqlite3_free(zGlob);
31859
+ break;
31860
+ }
31861
+ case 3: {
31862
+ isOk = cli_strcmp(zTest,zPattern)==0;
31863
+ break;
31864
+ }
31865
+ default: {
31866
+ /* Skip leading and trailing \n and \r on both pattern and test output */
31867
+ const char *z1 = zPattern;
31868
+ const char *z2 = zTest;
31869
+ size_t n1, n2;
31870
+ while( z1[0]=='\n' || z1[0]=='\r' ) z1++;
31871
+ n1 = strlen(z1);
31872
+ while( n1>0 && (z1[n1-1]=='\n' || z1[n1-1]=='\r') ) n1--;
31873
+ while( z2[0]=='\n' || z2[0]=='\r' ) z2++;
31874
+ n2 = strlen(z2);
31875
+ while( n2>0 && (z2[n2-1]=='\n' || z2[n2-1]=='\r') ) n2--;
31876
+ isOk = n1==n2 && memcmp(z1,z2,n1)==0;
31877
+ break;
31878
+ }
31879
+ }
31880
+ if( !isOk ){
31881
+ sqlite3_fprintf(stderr,
31882
+ "%s:%lld: .check failed for testcase %s\n",
31883
+ p->zInFile, iStart, p->zTestcase);
31884
+ p->nTestErr++;
31885
+ sqlite3_fprintf(stderr, "Expected: [%s]\n", zPattern);
31886
+ sqlite3_fprintf(stderr, "Got: [%s]\n", zTest);
31887
+ }
31888
+ if( zPattern!=zCheck ){
31889
+ sqlite3_free(zPattern);
31890
+ }
31891
+ if( !bKeep ){
31892
+ output_reset(p);
31893
+ p->zTestcase[0] = 0;
31894
+ }
31895
+ return 0;
31896
+}
31897
+
31898
+/*
31899
+** DOT-COMMAND: .testcase
31900
+** USAGE: .testcase [OPTIONS] NAME
31901
+**
31902
+** Start a new test case identified by NAME. All output
31903
+** through the next ".check" command is captured for comparison. See the
31904
+** ".check" commandn for additional informatioon.
31905
+**
31906
+** Options:
31907
+** --error-prefix TEXT Change error message prefix text to TEXT
31908
+*/
31909
+static int dotCmdTestcase(ShellState *p){
31910
+ int nArg = p->dot.nArg; /* Number of arguments */
31911
+ char **azArg = p->dot.azArg; /* Text of the arguments */
31912
+ int i; /* Loop counter */
31913
+ const char *zName = 0; /* Testcase name */
31914
+
31915
+ for(i=1; i<nArg; i++){
31916
+ char *z = azArg[i];
31917
+ if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++;
31918
+ if( optionMatch(z,"error-prefix") ){
31919
+ if( i+1>=nArg ){
31920
+ dotCmdError(p, i, "missing argument", 0);
31921
+ return 1;
31922
+ }
31923
+ free(p->zErrPrefix);
31924
+ i++;
31925
+ p->zErrPrefix = azArg[i][0]==0 ? 0 : strdup(azArg[i]);
31926
+ }else if( zName ){
31927
+ dotCmdError(p, i, "unknown option", 0);
31928
+ return 1;
31929
+ }else{
31930
+ zName = azArg[i];
31931
+ }
31932
+ }
31933
+ output_reset(p);
31934
+ if( cli_output_capture ){
31935
+ sqlite3_str_free(cli_output_capture);
31936
+ }
31937
+ cli_output_capture = sqlite3_str_new(0);
31938
+ if( zName ){
31939
+ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", zName);
31940
+ }else{
31941
+ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s:%lld",
31942
+ p->zInFile, p->lineno);
31943
+ }
31944
+ return 0;
31945
+}
3133331946
3133431947
/*
3133531948
** Enlarge the space allocated in p->dot so that it can hold more
3133631949
** than nArg parsed command-line arguments.
3133731950
*/
@@ -31360,11 +31973,11 @@
3136031973
free(p->dot.zCopy);
3136131974
z = p->dot.zCopy = strdup(zLine);
3136231975
shell_check_oom(z);
3136331976
szLine = strlen(z);
3136431977
while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31365
- if( szLine>0 && z[szLine-1]==';' && p->iCompat>=20251115 ){
31978
+ if( szLine>0 && z[szLine-1]==';' ){
3136631979
szLine--;
3136731980
while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
3136831981
}
3136931982
z[szLine] = 0;
3137031983
parseDotRealloc(p, 2);
@@ -31580,35 +32193,17 @@
3158032193
eputz("Usage: .changes on|off\n");
3158132194
rc = 1;
3158232195
}
3158332196
}else
3158432197
31585
-#ifndef SQLITE_SHELL_FIDDLE
3158632198
/* Cancel output redirection, if it is currently set (by .testcase)
3158732199
** Then read the content of the testcase-out.txt file and compare against
3158832200
** azArg[1]. If there are differences, report an error and exit.
3158932201
*/
3159032202
if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
31591
- char *zRes = 0;
31592
- output_reset(p);
31593
- if( nArg!=2 ){
31594
- eputz("Usage: .check GLOB-PATTERN\n");
31595
- rc = 2;
31596
- }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
31597
- rc = 2;
31598
- }else if( testcase_glob(azArg[1],zRes)==0 ){
31599
- cli_printf(stderr,
31600
- "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
31601
- p->zTestcase, azArg[1], zRes);
31602
- rc = 1;
31603
- }else{
31604
- cli_printf(p->out, "testcase-%s ok\n", p->zTestcase);
31605
- p->nCheck++;
31606
- }
31607
- sqlite3_free(zRes);
32203
+ rc = dotCmdCheck(p);
3160832204
}else
31609
-#endif /* !defined(SQLITE_SHELL_FIDDLE) */
3161032205
3161132206
#ifndef SQLITE_SHELL_FIDDLE
3161232207
if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
3161332208
failIfSafeMode(p, "cannot run .clone in safe mode");
3161432209
if( nArg==2 ){
@@ -32187,10 +32782,11 @@
3218732782
}else
3218832783
3218932784
if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
3219032785
if( nArg==2 ){
3219132786
p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No;
32787
+ p->mode.mFlags |= MFLG_HDR;
3219232788
p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr;
3219332789
}else{
3219432790
eputz("Usage: .headers on|off\n");
3219532791
rc = 1;
3219632792
}
@@ -32240,14 +32836,14 @@
3224032836
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
3224132837
goto meta_command_exit;
3224232838
}
3224332839
zSql = sqlite3_mprintf(
3224432840
"SELECT rootpage, 0 FROM sqlite_schema"
32245
- " WHERE name='%q' AND type='index'"
32841
+ " WHERE type='index' AND lower(name)=lower('%q')"
3224632842
"UNION ALL "
3224732843
"SELECT rootpage, 1 FROM sqlite_schema"
32248
- " WHERE name='%q' AND type='table'"
32844
+ " WHERE type='table' AND lower(name)=lower('%q')"
3224932845
" AND sql LIKE '%%without%%rowid%%'",
3225032846
azArg[1], azArg[1]
3225132847
);
3225232848
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3225332849
sqlite3_free(zSql);
@@ -32401,13 +32997,14 @@
3240132997
goto meta_command_exit;
3240232998
}
3240332999
if( nArg==3 ){
3240433000
sqlite3_limit(p->db, aLimit[iLimit].limitCode,
3240533001
(int)integerValue(azArg[2]));
33002
+ }else{
33003
+ cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
33004
+ sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
3240633005
}
32407
- cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
32408
- sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
3240933006
}
3241033007
}else
3241133008
3241233009
if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
3241333010
open_db(p, 0);
@@ -32493,21 +33090,23 @@
3249333090
int iName = 1; /* Index in azArg[] of the filename */
3249433091
int newFlag = 0; /* True to delete file before opening */
3249533092
int openMode = SHELL_OPEN_UNSPEC;
3249633093
int openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
3249733094
33095
+ if( p->bSafeMode ) openFlags = SQLITE_OPEN_READONLY;
33096
+
3249833097
/* Check for command-line arguments */
3249933098
for(iName=1; iName<nArg; iName++){
3250033099
const char *z = azArg[iName];
3250133100
#ifndef SQLITE_SHELL_FIDDLE
3250233101
if( optionMatch(z,"new") ){
3250333102
newFlag = 1;
3250433103
#ifdef SQLITE_HAVE_ZLIB
32505
- }else if( optionMatch(z, "zip") ){
33104
+ }else if( optionMatch(z, "zip") && !p->bSafeMode ){
3250633105
openMode = SHELL_OPEN_ZIPFILE;
3250733106
#endif
32508
- }else if( optionMatch(z, "append") ){
33107
+ }else if( optionMatch(z, "append") && !p->bSafeMode ){
3250933108
openMode = SHELL_OPEN_APPENDVFS;
3251033109
}else if( optionMatch(z, "readonly") ){
3251133110
openFlags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
3251233111
openFlags |= SQLITE_OPEN_READONLY;
3251333112
}else if( optionMatch(z, "exclusive") ){
@@ -32950,21 +33549,22 @@
3295033549
|| sqlite3_strlike(zName, "sqlite_schema", '\\')==0
3295133550
|| sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
3295233551
|| sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
3295333552
if( isSchema ){
3295433553
cli_printf(p->out,
32955
- "CREATE TABLE %s (\n"
33554
+ "CREATE TABLE %ssqlite_schema (\n"
3295633555
" type text,\n"
3295733556
" name text,\n"
3295833557
" tbl_name text,\n"
3295933558
" rootpage integer,\n"
3296033559
" sql text\n"
32961
- ");\n", zName);
33560
+ ");\n",
33561
+ sqlite3_strlike("sqlite_t%",zName,0)==0 ? "temp." : ""
33562
+ );
3296233563
}
3296333564
}
32964
- rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
32965
- -1, &pStmt, 0);
33565
+ rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
3296633566
if( rc ){
3296733567
shellDatabaseError(p->db);
3296833568
sqlite3_finalize(pStmt);
3296933569
3297033570
rc = 1;
@@ -32972,11 +33572,11 @@
3297233572
}
3297333573
pSql = sqlite3_str_new(p->db);
3297433574
sqlite3_str_appendf(pSql, "SELECT sql FROM", 0);
3297533575
iSchema = 0;
3297633576
while( sqlite3_step(pStmt)==SQLITE_ROW ){
32977
- const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
33577
+ const char *zDb = (const char*)sqlite3_column_text(pStmt, 1);
3297833578
char zScNum[30];
3297933579
sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
3298033580
sqlite3_str_appendall(pSql, zDiv);
3298133581
zDiv = " UNION ALL ";
3298233582
if( sqlite3_stricmp(zDb, "main")==0 ){
@@ -32992,11 +33592,12 @@
3299233592
" AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname",
3299333593
++iSchema, zDb);
3299433594
sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb);
3299533595
}
3299633596
sqlite3_finalize(pStmt);
32997
-#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
33597
+#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) \
33598
+ && !defined(SQLITE_OMIT_VIRTUALTABLE)
3299833599
if( zName ){
3299933600
sqlite3_str_appendall(pSql,
3300033601
" UNION ALL SELECT shell_module_schema(name),"
3300133602
" 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list");
3300233603
}
@@ -33016,11 +33617,11 @@
3301633617
}else{
3301733618
sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName);
3301833619
}
3301933620
}
3302033621
if( bNoSystemTabs ){
33021
- sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCALE '_' AND ");
33622
+ sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ");
3302233623
}
3302333624
sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid");
3302433625
if( bDebug ){
3302533626
cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql));
3302633627
}else{
@@ -33734,25 +34335,15 @@
3373434335
sqlite3_str_free(pSql);
3373534336
modePop(p);
3373634337
if( rc ) return shellDatabaseError(p->db);
3373734338
}else
3373834339
33739
-#ifndef SQLITE_SHELL_FIDDLE
33740
- /* Begin redirecting output to the file "testcase-out.txt" */
34340
+ /* Set the p->zTestcase name and begin redirecting output into
34341
+ ** the cli_output_capture sqlite3_str */
3374134342
if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
33742
- output_reset(p);
33743
- p->out = output_file_open(p, "testcase-out.txt");
33744
- if( p->out==0 ){
33745
- eputz("Error: cannot open 'testcase-out.txt'\n");
33746
- }
33747
- if( nArg>=2 ){
33748
- sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
33749
- }else{
33750
- sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
33751
- }
34343
+ rc = dotCmdTestcase(p);
3375234344
}else
33753
-#endif /* !defined(SQLITE_SHELL_FIDDLE) */
3375434345
3375534346
#ifndef SQLITE_UNTESTABLE
3375634347
if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
3375734348
static const struct {
3375834349
const char *zCtrlName; /* Name of a test-control option */
@@ -35068,11 +35659,10 @@
3506835659
" -bail stop after hitting an error\n"
3506935660
" -batch force batch I/O\n"
3507035661
" -box set output mode to 'box'\n"
3507135662
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
3507235663
" -column set output mode to 'column'\n"
35073
- " -compat YYYYMMDD set default options for date YYYYMMDD\n"
3507435664
" -csv set output mode to 'csv'\n"
3507535665
#if !defined(SQLITE_OMIT_DESERIALIZE)
3507635666
" -deserialize open the database using sqlite3_deserialize()\n"
3507735667
#endif
3507835668
" -echo print inputs before execution\n"
@@ -35152,15 +35742,10 @@
3515235742
/*
3515335743
** Initialize the state information in data
3515435744
*/
3515535745
static void main_init(ShellState *p) {
3515635746
memset(p, 0, sizeof(*p));
35157
-#if defined(COMPATIBILITY_DATE)
35158
- p->iCompat = COMPATIBILITY_DATE;
35159
-#else
35160
- p->iCompat = 20251116;
35161
-#endif
3516235747
p->pAuxDb = &p->aAuxDb[0];
3516335748
p->shellFlgs = SHFLG_Lookaside;
3516435749
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p);
3516535750
#if !defined(SQLITE_SHELL_FIDDLE)
3516635751
verify_uninitialized();
@@ -35174,22 +35759,18 @@
3517435759
/*
3517535760
** Output text to the console in a font that attracts extra attention.
3517635761
*/
3517735762
#if defined(_WIN32) || defined(WIN32)
3517835763
static void printBold(const char *zText){
35179
-#if !SQLITE_OS_WINRT
3518035764
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
3518135765
CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
3518235766
GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
3518335767
SetConsoleTextAttribute(out,
3518435768
FOREGROUND_RED|FOREGROUND_INTENSITY
3518535769
);
35186
-#endif
3518735770
sputz(stdout, zText);
35188
-#if !SQLITE_OS_WINRT
3518935771
SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
35190
-#endif
3519135772
}
3519235773
#else
3519335774
static void printBold(const char *zText){
3519435775
cli_printf(stdout, "\033[1m%s\033[0m", zText);
3519535776
}
@@ -35219,29 +35800,65 @@
3521935800
cli_puts(z, p->out);
3522035801
fflush(p->out);
3522135802
return 1;
3522235803
}
3522335804
35224
-#ifndef SQLITE_SHELL_IS_UTF8
35225
-# if (defined(_WIN32) || defined(WIN32)) \
35226
- && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
35227
-# define SQLITE_SHELL_IS_UTF8 (0)
35228
-# else
35229
-# define SQLITE_SHELL_IS_UTF8 (1)
35230
-# endif
35231
-#endif
35232
-
35805
+/* Alternative name to the entry point for Fiddle */
3523335806
#ifdef SQLITE_SHELL_FIDDLE
3523435807
# define main fiddle_main
3523535808
#endif
3523635809
35237
-#if SQLITE_SHELL_IS_UTF8
35238
-int SQLITE_CDECL main(int argc, char **argv){
35239
-#else
35810
+/* Use the wmain() entry point on Windows. Translate arguments to
35811
+** UTF8, then invoke the traditional main() entry point which is
35812
+** renamed using a #define to utf8_main() .
35813
+*/
35814
+#if defined(_WIN32) && !defined(main)
35815
+# define main utf8_main /* Rename entry point to utf_main() */
35816
+int SQLITE_CDECL utf8_main(int,char**); /* Forward declaration */
3524035817
int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
35241
- char **argv;
35242
-#endif
35818
+ int rc, i;
35819
+ char **argv = malloc( sizeof(char*) * (argc+1) );
35820
+ char **orig = argv;
35821
+ if( argv==0 ){
35822
+ fprintf(stderr, "malloc failed\n");
35823
+ exit(1);
35824
+ }
35825
+ for(i=0; i<argc; i++){
35826
+ int nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, 0, 0, 0, 0);
35827
+ if( nByte==0 ){
35828
+ argv[i] = 0;
35829
+ }else{
35830
+ argv[i] = malloc( nByte );
35831
+ if( argv[i]==0 ){
35832
+ fprintf(stderr, "malloc failed\n");
35833
+ exit(1);
35834
+ }
35835
+ nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i],nByte,0,0);
35836
+ if( nByte==0 ){
35837
+ free(argv[i]);
35838
+ argv[i] = 0;
35839
+ }
35840
+ }
35841
+ }
35842
+ argv[argc] = 0;
35843
+ rc = utf8_main(argc, argv);
35844
+ for(i=0; i<argc; i++) free(orig[i]);
35845
+ free(argv);
35846
+ return rc;
35847
+}
35848
+#endif /* WIN32 */
35849
+
35850
+/*
35851
+** This is the main entry point for the process. Everything starts here.
35852
+**
35853
+** The "main" identifier may have been #defined to something else:
35854
+**
35855
+** utf8_main On Windows
35856
+** fiddle_main In Fiddle
35857
+** sqlite3_shell Other projects that use shell.c as a subroutine
35858
+*/
35859
+int SQLITE_CDECL main(int argc, char **argv){
3524335860
#ifdef SQLITE_DEBUG
3524435861
sqlite3_int64 mem_main_enter = 0;
3524535862
#endif
3524635863
char *zErrMsg = 0;
3524735864
#ifdef SQLITE_SHELL_FIDDLE
@@ -35259,14 +35876,10 @@
3525935876
int nOptsEnd = argc;
3526035877
int bEnableVfstrace = 0;
3526135878
char **azCmd = 0;
3526235879
int *aiCmd = 0;
3526335880
const char *zVfs = 0; /* Value of -vfs command-line option */
35264
-#if !SQLITE_SHELL_IS_UTF8
35265
- char **argvToFree = 0;
35266
- int argcToFree = 0;
35267
-#endif
3526835881
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
3526935882
3527035883
#ifdef SQLITE_SHELL_FIDDLE
3527135884
stdin_is_interactive = 0;
3527235885
stdout_is_console = 1;
@@ -35291,15 +35904,11 @@
3529135904
){
3529235905
exit(1);
3529335906
}
3529435907
}else{
3529535908
#if defined(_WIN32) || defined(WIN32)
35296
-#if SQLITE_OS_WINRT
35297
- __debugbreak();
35298
-#else
3529935909
DebugBreak();
35300
-#endif
3530135910
#elif defined(SIGTRAP)
3530235911
raise(SIGTRAP);
3530335912
#endif
3530435913
}
3530535914
}
@@ -35321,36 +35930,10 @@
3532135930
exit(1);
3532235931
}
3532335932
#endif
3532435933
main_init(&data);
3532535934
35326
- /* On Windows, we must translate command-line arguments into UTF-8.
35327
- ** The SQLite memory allocator subsystem has to be enabled in order to
35328
- ** do this. But we want to run an sqlite3_shutdown() afterwards so that
35329
- ** subsequent sqlite3_config() calls will work. So copy all results into
35330
- ** memory that does not come from the SQLite memory allocator.
35331
- */
35332
-#if !SQLITE_SHELL_IS_UTF8
35333
- sqlite3_initialize();
35334
- argvToFree = malloc(sizeof(argv[0])*argc*2);
35335
- shell_check_oom(argvToFree);
35336
- argcToFree = argc;
35337
- argv = argvToFree + argc;
35338
- for(i=0; i<argc; i++){
35339
- char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
35340
- i64 n;
35341
- shell_check_oom(z);
35342
- n = strlen(z);
35343
- argv[i] = malloc( n+1 );
35344
- shell_check_oom(argv[i]);
35345
- memcpy(argv[i], z, n+1);
35346
- argvToFree[i] = argv[i];
35347
- sqlite3_free(z);
35348
- }
35349
- sqlite3_shutdown();
35350
-#endif
35351
-
3535235935
assert( argc>=1 && argv && argv[0] );
3535335936
Argv0 = argv[0];
3535435937
3535535938
#ifdef SQLITE_SHELL_DBNAME_PROC
3535635939
{
@@ -35362,11 +35945,11 @@
3536235945
SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
3536335946
warnInmemoryDb = 0;
3536435947
}
3536535948
#endif
3536635949
35367
- /* Do an initial pass through the command-line argument to locate
35950
+ /* Do an initial pass through the command-line arguments to locate
3536835951
** the name of the database file, the name of the initialization file,
3536935952
** the size of the alternative malloc heap, options affecting commands
3537035953
** or SQL run from the command line, and the first command to execute.
3537135954
*/
3537235955
#ifndef SQLITE_SHELL_FIDDLE
@@ -35374,11 +35957,11 @@
3537435957
#endif
3537535958
for(i=1; i<argc; i++){
3537635959
char *z;
3537735960
z = argv[i];
3537835961
if( z[0]!='-' || i>nOptsEnd ){
35379
- if( data.aAuxDb->zDbFilename==0 ){
35962
+ if( data.aAuxDb->zDbFilename==0 && !isScriptFile(z,1) ){
3538035963
data.aAuxDb->zDbFilename = z;
3538135964
}else{
3538235965
/* Excess arguments are interpreted as SQL (or dot-commands) and
3538335966
** mean that nothing is read from stdin */
3538435967
readStdin = 0;
@@ -35419,15 +36002,10 @@
3541936002
if( n<2 ){
3542036003
sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n");
3542136004
exit(1);
3542236005
}
3542336006
stdout_tty_width = n;
35424
- }else if( cli_strcmp(z,"-compat")==0 ){
35425
- data.iCompat = atoi(cmdline_option_value(argc, argv, ++i));
35426
- modeFree(&data.mode);
35427
- memset(&data.mode, 0, sizeof(data.mode));
35428
- modeDefault(&data);
3542936007
}else if( cli_strcmp(z,"-utf8")==0 ){
3543036008
}else if( cli_strcmp(z,"-no-utf8")==0 ){
3543136009
}else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
3543236010
int val = 0;
3543336011
sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val);
@@ -35547,10 +36125,20 @@
3554736125
}else if( cli_strcmp(z,"-safe")==0 ){
3554836126
/* no-op - catch this on the second pass */
3554936127
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
3555036128
/* skip over the argument */
3555136129
i++;
36130
+ }else if( cli_strcmp(z,"-test-argv")==0 ){
36131
+ /* Undocumented test option. Print the values in argv[] and exit.
36132
+ ** Use this to verify that any translation of the argv[], for example
36133
+ ** on Windows that receives wargv[] from the OS and must convert
36134
+ ** to UTF8 prior to calling this routine. */
36135
+ int kk;
36136
+ for(kk=0; kk<argc; kk++){
36137
+ sqlite3_fprintf(stdout,"argv[%d] = \"%s\"\n", kk, argv[kk]);
36138
+ }
36139
+ return 0;
3555236140
}
3555336141
}
3555436142
#ifndef SQLITE_SHELL_FIDDLE
3555536143
if( !bEnableVfstrace ) verify_uninitialized();
3555636144
#endif
@@ -35573,11 +36161,30 @@
3557336161
3557436162
if( zVfs ){
3557536163
sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
3557636164
if( pVfs ){
3557736165
sqlite3_vfs_register(pVfs, 1);
35578
- }else{
36166
+ }
36167
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
36168
+ else if( access(zVfs,0)==0 ){
36169
+ /* If the VFS name is not the name of an existing VFS, but it is
36170
+ ** the name of a file, then try to load that file as an extension.
36171
+ ** Presumably the extension implements the desired VFS. */
36172
+ sqlite3 *db = 0;
36173
+ char *zErr = 0;
36174
+ sqlite3_open(":memory:", &db);
36175
+ sqlite3_enable_load_extension(db, 1);
36176
+ rc = sqlite3_load_extension(db, zVfs, 0, &zErr);
36177
+ sqlite3_close(db);
36178
+ if( (rc&0xff)!=SQLITE_OK ){
36179
+ cli_printf(stderr, "could not load extension VFS \"%s\": %s\n",
36180
+ zVfs, zErr);
36181
+ exit(1);
36182
+ }
36183
+ }
36184
+#endif
36185
+ else{
3557936186
cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs);
3558036187
exit(1);
3558136188
}
3558236189
}
3558336190
@@ -35586,11 +36193,12 @@
3558636193
data.pAuxDb->zDbFilename = ":memory:";
3558736194
warnInmemoryDb = argc==1;
3558836195
#else
3558936196
cli_printf(stderr,
3559036197
"%s: Error: no database filename specified\n", Argv0);
35591
- return 1;
36198
+ rc = 1;
36199
+ goto shell_main_exit;
3559236200
#endif
3559336201
}
3559436202
data.out = stdout;
3559536203
if( bEnableVfstrace ){
3559636204
vfstrace_register("trace",0,vfstraceOut, &data, 1);
@@ -35613,11 +36221,11 @@
3561336221
** is given on the command line, look for a file named ~/.sqliterc and
3561436222
** try to process it.
3561536223
*/
3561636224
if( !noInit ) process_sqliterc(&data,zInitFile);
3561736225
35618
- /* Make a second pass through the command-line argument and set
36226
+ /* Make a second pass through the command-line arguments and set
3561936227
** options. This second pass is delayed until after the initialization
3562036228
** file is processed so that the command-line arguments will override
3562136229
** settings in the initialization file.
3562236230
*/
3562336231
for(i=1; i<argc; i++){
@@ -35640,10 +36248,12 @@
3564036248
modeChange(&data, MODE_Json);
3564136249
}else if( cli_strcmp(z,"-markdown")==0 ){
3564236250
modeChange(&data, MODE_Markdown);
3564336251
}else if( cli_strcmp(z,"-table")==0 ){
3564436252
modeChange(&data, MODE_Table);
36253
+ }else if( cli_strcmp(z,"-psql")==0 ){
36254
+ modeChange(&data, MODE_Psql);
3564536255
}else if( cli_strcmp(z,"-box")==0 ){
3564636256
modeChange(&data, MODE_Box);
3564736257
}else if( cli_strcmp(z,"-csv")==0 ){
3564836258
modeChange(&data, MODE_Csv);
3564936259
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
@@ -35726,22 +36336,21 @@
3572636336
}else if( cli_strcmp(z,"-bail")==0 ){
3572736337
/* No-op. The bail_on_error flag should already be set. */
3572836338
}else if( cli_strcmp(z,"-version")==0 ){
3572936339
cli_printf(stdout, "%s %s (%d-bit)\n",
3573036340
sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
35731
- return 0;
36341
+ rc = 0;
36342
+ goto shell_main_exit;
3573236343
}else if( cli_strcmp(z,"-interactive")==0 ){
3573336344
/* Need to check for interactive override here to so that it can
3573436345
** affect console setup (for Windows only) and testing thereof.
3573536346
*/
3573636347
stdin_is_interactive = 1;
3573736348
}else if( cli_strcmp(z,"-batch")==0 ){
3573836349
/* already handled */
3573936350
}else if( cli_strcmp(z,"-screenwidth")==0 ){
3574036351
i++;
35741
- }else if( cli_strcmp(z,"-compat")==0 ){
35742
- i++;
3574336352
}else if( cli_strcmp(z,"-utf8")==0 ){
3574436353
/* already handled */
3574536354
}else if( cli_strcmp(z,"-no-utf8")==0 ){
3574636355
/* already handled */
3574736356
}else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
@@ -35783,29 +36392,33 @@
3578336392
** we retain the goofy behavior for historical compatibility. */
3578436393
if( i==argc-1 ) break;
3578536394
z = cmdline_option_value(argc,argv,++i);
3578636395
if( z[0]=='.' ){
3578736396
rc = do_meta_command(z, &data);
35788
- if( rc && bail_on_error ) return rc==2 ? 0 : rc;
36397
+ if( rc && bail_on_error ){
36398
+ if( rc==2 ) rc = 0;
36399
+ goto shell_main_exit;
36400
+ }
3578936401
}else{
3579036402
open_db(&data, 0);
3579136403
rc = shell_exec(&data, z, &zErrMsg);
3579236404
if( zErrMsg!=0 ){
3579336405
shellEmitError(zErrMsg);
3579436406
sqlite3_free(zErrMsg);
35795
- if( bail_on_error ) return rc!=0 ? rc : 1;
36407
+ if( !rc ) rc = 1;
3579636408
}else if( rc!=0 ){
3579736409
cli_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
35798
- if( bail_on_error ) return rc;
3579936410
}
36411
+ if( bail_on_error ) goto shell_main_exit;
3580036412
}
3580136413
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
3580236414
}else if( cli_strncmp(z, "-A", 2)==0 ){
3580336415
if( nCmd>0 ){
3580436416
cli_printf(stderr,"Error: cannot mix regular SQL or dot-commands"
3580536417
" with \"%s\"\n", z);
35806
- return 1;
36418
+ rc = 1;
36419
+ goto shell_main_exit;
3580736420
}
3580836421
open_db(&data, OPEN_DB_ZIPFILE);
3580936422
if( z[2] ){
3581036423
argv[i] = &z[2];
3581136424
arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
@@ -35821,11 +36434,12 @@
3582136434
}else if( cli_strcmp(z,"-unsafe-testing")==0 ){
3582236435
/* Acted upon in first pass. */
3582336436
}else{
3582436437
cli_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
3582536438
eputz("Use -help for a list of options.\n");
35826
- return 1;
36439
+ rc = 1;
36440
+ goto shell_main_exit;
3582736441
}
3582836442
}
3582936443
3583036444
if( !readStdin ){
3583136445
/* Run all arguments that do not begin with '-' as if they were separate
@@ -35832,11 +36446,22 @@
3583236446
** command-line inputs, except for the argToSkip argument which contains
3583336447
** the database filename.
3583436448
*/
3583536449
for(i=0; i<nCmd; i++){
3583636450
echo_group_input(&data, azCmd[i]);
35837
- if( azCmd[i][0]=='.' ){
36451
+ if( isScriptFile(azCmd[i],0) ){
36452
+ FILE *inSaved = data.in;
36453
+ i64 savedLineno = data.lineno;
36454
+ int res = 1;
36455
+ if( (data.in = openChrSource(azCmd[i]))!=0 ){
36456
+ res = process_input(&data, azCmd[i]);
36457
+ fclose(data.in);
36458
+ }
36459
+ data.in = inSaved;
36460
+ data.lineno = savedLineno;
36461
+ if( res ) i = nCmd;
36462
+ }else if( azCmd[i][0]=='.' ){
3583836463
char *zErrCtx = malloc( 64 );
3583936464
shell_check_oom(zErrCtx);
3584036465
sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]);
3584136466
data.zInFile = "<cmdline>";
3584236467
data.zErrPrefix = zErrCtx;
@@ -35947,14 +36572,10 @@
3594736572
}
3594836573
find_home_dir(1);
3594936574
output_reset(&data);
3595036575
data.doXdgOpen = 0;
3595136576
clearTempFile(&data);
35952
-#if !SQLITE_SHELL_IS_UTF8
35953
- for(i=0; i<argcToFree; i++) free(argvToFree[i]);
35954
- free(argvToFree);
35955
-#endif
3595636577
modeFree(&data.mode);
3595736578
if( data.nSavedModes ){
3595836579
int ii;
3595936580
for(ii=0; ii<data.nSavedModes; ii++){
3596036581
modeFree(&data.aSavedModes[ii].mode);
3596136582
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -35,11 +35,11 @@
35 ** ext/recover/sqlite3recover.h
36 ** src/shell.c.in
37 **
38 ** To modify this program, get a copy of the canonical SQLite source tree,
39 ** edit the src/shell.c.in file and/or some of the other files that are
40 ** listed above, then rerun the rerun "make shell.c".
41 */
42 /************************* Begin src/shell.c.in ******************/
43 /*
44 ** 2001 September 15
45 **
@@ -49,11 +49,11 @@
49 ** May you do good and not evil.
50 ** May you find forgiveness for yourself and forgive others.
51 ** May you share freely, never taking more than you give.
52 **
53 *************************************************************************
54 ** This file contains code to implement the "sqlite" command line
55 ** utility for accessing SQLite databases.
56 */
57 #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
58 /* This needs to come before any includes for MSVC compiler */
59 #define _CRT_SECURE_NO_WARNINGS
@@ -71,26 +71,22 @@
71 # define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
72 #ifdef SQLITE_CUSTOM_INCLUDE
73 # include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
74 #endif
75
76 /*
77 ** Determine if we are dealing with WinRT, which provides only a subset of
78 ** the full Win32 API.
79 */
80 #if !defined(SQLITE_OS_WINRT)
81 # define SQLITE_OS_WINRT 0
82 #endif
83
84 /*
85 ** If SQLITE_SHELL_FIDDLE is defined then the shell is modified
86 ** somewhat for use as a WASM module in a web browser. This flag
87 ** should only be used when building the "fiddle" web application, as
88 ** the browser-mode build has much different user input requirements
89 ** and this build mode rewires the user input subsystem to account for
90 ** that.
91 */
 
 
 
 
92
93 /*
94 ** Warning pragmas copied from msvc.h in the core.
95 */
96 #if defined(_MSC_VER)
@@ -218,13 +214,10 @@
218 # define deliberate_fall_through
219 # endif
220 #endif
221
222 #if defined(_WIN32) || defined(WIN32)
223 # if SQLITE_OS_WINRT
224 # define SQLITE_OMIT_POPEN 1
225 # else
226 # include <io.h>
227 # include <fcntl.h>
228 # define isatty(h) _isatty(h)
229 # ifndef access
230 # define access(f,m) _access((f),(m))
@@ -235,11 +228,10 @@
235 # ifndef strdup
236 # define strdup _strdup
237 # endif
238 # undef pclose
239 # define pclose _pclose
240 # endif
241 #else
242 /* Make sure isatty() has a prototype. */
243 extern int isatty(int);
244
245 # if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI)
@@ -266,13 +258,10 @@
266 #define ToLower(X) (char)tolower((unsigned char)X)
267 #define IsAlnum(X) isalnum((unsigned char)X)
268 #define IsAlpha(X) isalpha((unsigned char)X)
269
270 #if defined(_WIN32) || defined(WIN32)
271 #if SQLITE_OS_WINRT
272 #include <intrin.h>
273 #endif
274 #undef WIN32_LEAN_AND_MEAN
275 #define WIN32_LEAN_AND_MEAN
276 #include <windows.h>
277
278 /* string conversion routines only needed on Win32 */
@@ -704,13 +693,15 @@
704 unsigned char bWordWrap; /* Try to wrap on word boundaries */
705 unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
706 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
707 unsigned char eTitleAlign; /* Alignment for column headers */
708 unsigned char bSplitColumn; /* Wrap single-column output into many columns */
 
709 short int nWrap; /* Wrap columns wider than this */
710 short int nScreenWidth; /* Maximum overall table width */
711 short int nLineLimit; /* Maximum number of lines for any row */
 
712 int nCharLimit; /* Maximum number of characters in a cell */
713 int nWidth; /* Number of entries in aWidth[] */
714 int nAlign; /* Number of entries in aAlignment[] */
715 short int *aWidth; /* Column widths */
716 unsigned char *aAlign; /* Column alignments */
@@ -775,10 +766,11 @@
775 #define QRF_TEXT_Sql 2 /* Quote as an SQL literal */
776 #define QRF_TEXT_Csv 3 /* CSV-style quoting */
777 #define QRF_TEXT_Html 4 /* HTML-style quoting */
778 #define QRF_TEXT_Tcl 5 /* C/Tcl quoting */
779 #define QRF_TEXT_Json 6 /* JSON quoting */
 
780
781 /*
782 ** Quoting styles for BLOBs
783 ** Allowed values for sqlite3_qrf_spec.eBlob
784 */
@@ -842,17 +834,25 @@
842 /*
843 ** Return an estimate of the width, in columns, for the single Unicode
844 ** character c. For normal characters, the answer is always 1. But the
845 ** estimate might be 0 or 2 for zero-width and double-width characters.
846 **
847 ** Different display devices display unicode using different widths. So
848 ** it is impossible to know that true display width with 100% accuracy.
849 ** Inaccuracies in the width estimates might cause columns to be misaligned.
850 ** Unfortunately, there is nothing we can do about that.
851 */
852 int sqlite3_qrf_wcwidth(int c);
853
 
 
 
 
 
 
 
 
854
855 #ifdef __cplusplus
856 }
857 #endif
858 #endif /* !defined(SQLITE_QRF_H) */
@@ -915,11 +915,11 @@
915 int mxWidth; /* Screen width */
916 int mxHeight; /* nLineLimit */
917 union {
918 struct { /* Content for QRF_STYLE_Line */
919 int mxColWth; /* Maximum display width of any column */
920 const char **azCol; /* Names of output columns (MODE_Line) */
921 } sLine;
922 qrfEQPGraph *pGraph; /* EQP graph (Eqp, Stats, and StatsEst) */
923 struct { /* Content for QRF_STYLE_Explain */
924 int nIndent; /* Slots allocated for aiIndent */
925 int iIndent; /* Current slot */
@@ -961,10 +961,19 @@
961 #define qrfSpace(x) ((qrfCType[(unsigned char)x]&1)!=0)
962 #define qrfDigit(x) ((qrfCType[(unsigned char)x]&2)!=0)
963 #define qrfAlpha(x) ((qrfCType[(unsigned char)x]&4)!=0)
964 #define qrfAlnum(x) ((qrfCType[(unsigned char)x]&6)!=0)
965
 
 
 
 
 
 
 
 
 
966 /*
967 ** Set an error code and error message.
968 */
969 static void qrfError(
970 Qrf *p, /* Query result state */
@@ -990,10 +999,19 @@
990 */
991 static void qrfOom(Qrf *p){
992 qrfError(p, SQLITE_NOMEM, "out of memory");
993 }
994
 
 
 
 
 
 
 
 
 
995
996
997 /*
998 ** Add a new entry to the EXPLAIN QUERY PLAN data
999 */
@@ -1212,11 +1230,13 @@
1212 sqlite3_str_reset(pLine);
1213 }else{
1214 qrfEqpAppend(p, iId, iPid, zo);
1215 }
1216 }
 
1217 sqlite3_free(sqlite3_str_finish(pLine));
 
1218 sqlite3_free(sqlite3_str_finish(pStats));
1219 #endif
1220 }
1221
1222
@@ -1287,11 +1307,11 @@
1287 {1, 0x00ece}, {0, 0x00f18}, {1, 0x00f1a}, {0, 0x00f35}, {1, 0x00f36},
1288 {0, 0x00f37}, {1, 0x00f38}, {0, 0x00f39}, {1, 0x00f3a}, {0, 0x00f71},
1289 {1, 0x00f7f}, {0, 0x00f80}, {1, 0x00f85}, {0, 0x00f86}, {1, 0x00f88},
1290 {0, 0x00f90}, {1, 0x00f98}, {0, 0x00f99}, {1, 0x00fbd}, {0, 0x00fc6},
1291 {1, 0x00fc7}, {0, 0x0102d}, {1, 0x01031}, {0, 0x01032}, {1, 0x01033},
1292 {0, 0x01036}, {1, 0x01038}, {0, 0x01039}, {1, 0x0103a}, {0, 0x01058},
1293 {1, 0x0105a}, {2, 0x01100}, {0, 0x01160}, {1, 0x01200}, {0, 0x0135f},
1294 {1, 0x01360}, {0, 0x01712}, {1, 0x01715}, {0, 0x01732}, {1, 0x01735},
1295 {0, 0x01752}, {1, 0x01754}, {0, 0x01772}, {1, 0x01774}, {0, 0x017b4},
1296 {1, 0x017b6}, {0, 0x017b7}, {1, 0x017be}, {0, 0x017c6}, {1, 0x017c7},
1297 {0, 0x017c9}, {1, 0x017d4}, {0, 0x017dd}, {1, 0x017de}, {0, 0x0180b},
@@ -1330,11 +1350,11 @@
1330 */
1331 int sqlite3_qrf_wcwidth(int c){
1332 int iFirst, iLast;
1333
1334 /* Fast path for common characters */
1335 if( c<=0x300 ) return 1;
1336
1337 /* The general case */
1338 iFirst = 0;
1339 iLast = sizeof(aQrfUWidth)/sizeof(aQrfUWidth[0]) - 1;
1340 while( iFirst<iLast-1 ){
@@ -1396,17 +1416,24 @@
1396 return i+1;
1397 }
1398
1399 /*
1400 ** Return the length of a string in display characters.
1401 ** Multibyte UTF8 characters count as a single character
1402 ** for single-width characters, or as two characters for
1403 ** double-width characters.
 
 
 
 
 
 
 
1404 */
1405 static int qrfDisplayLength(const char *zIn){
1406 const unsigned char *z = (const unsigned char*)zIn;
1407 int n = 0;
1408 while( *z ){
1409 if( z[0]<' ' ){
1410 int k;
1411 if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
1412 z += k;
@@ -1436,15 +1463,18 @@
1436 ** Write the number of newlines into *pnNL. So, *pnNL will
1437 ** return 0 if everything fits on one line, or positive it
1438 ** it will need to be split.
1439 */
1440 static int qrfDisplayWidth(const char *zIn, sqlite3_int64 nByte, int *pnNL){
1441 const unsigned char *z = (const unsigned char*)zIn;
1442 const unsigned char *zEnd = &z[nByte];
1443 int mx = 0;
1444 int n = 0;
1445 int nNL = 0;
 
 
 
1446 while( z<zEnd ){
1447 if( z[0]<' ' ){
1448 int k;
1449 if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
1450 z += k;
@@ -1551,10 +1581,51 @@
1551 zOut[j++] = '^';
1552 zOut[j++] = 0x40+c;
1553 }
1554 }
1555 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1556
1557 /*
1558 ** If a field contains any character identified by a 1 in the following
1559 ** array, then the string must be quoted for CSV.
1560 */
@@ -1581,10 +1652,16 @@
1581 ** Encode text appropriately and append it to pOut.
1582 */
1583 static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){
1584 int iStart = sqlite3_str_length(pOut);
1585 switch( p->spec.eText ){
 
 
 
 
 
 
1586 case QRF_TEXT_Sql: {
1587 if( p->spec.eEsc==QRF_ESC_Off ){
1588 sqlite3_str_appendf(pOut, "%Q", zTxt);
1589 }else{
1590 sqlite3_str_appendf(pOut, "%#Q", zTxt);
@@ -1739,10 +1816,57 @@
1739 return (const char*)sqlite3_column_text(p->pJTrans, 0);
1740 }else{
1741 return 0;
1742 }
1743 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1744
1745 /*
1746 ** Render value pVal into pOut
1747 */
1748 static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){
@@ -2124,40 +2248,10 @@
2124 }
2125 }
2126 sqlite3_str_append(pOut, (const char*)z, i);
2127 }
2128
2129 /*
2130 ** Output horizontally justified text into pOut. The text is the
2131 ** first nVal bytes of zVal. Include nWS bytes of whitespace, either
2132 ** split between both sides, or on the left, or on the right, depending
2133 ** on eAlign.
2134 */
2135 static void qrfPrintAligned(
2136 sqlite3_str *pOut, /* Append text here */
2137 const char *zVal, /* Text to append */
2138 int nVal, /* Use only the first nVal bytes of zVal[] */
2139 int nWS, /* Whitespace for horizonal alignment */
2140 unsigned char eAlign /* Alignment type */
2141 ){
2142 eAlign &= QRF_ALIGN_HMASK;
2143 if( eAlign==QRF_ALIGN_Center ){
2144 /* Center the text */
2145 sqlite3_str_appendchar(pOut, nWS/2, ' ');
2146 qrfAppendWithTabs(pOut, zVal, nVal);
2147 sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
2148 }else if( eAlign==QRF_ALIGN_Right){
2149 /* Right justify the text */
2150 sqlite3_str_appendchar(pOut, nWS, ' ');
2151 qrfAppendWithTabs(pOut, zVal, nVal);
2152 }else{
2153 /* Left justify the next */
2154 qrfAppendWithTabs(pOut, zVal, nVal);
2155 sqlite3_str_appendchar(pOut, nWS, ' ');
2156 }
2157 }
2158
2159 /*
2160 ** GCC does not define the offsetof() macro so we'll have to do it
2161 ** ourselves.
2162 */
2163 #ifndef offsetof
@@ -2177,27 +2271,60 @@
2177 sqlite3_int64 nRow; /* Number of rows */
2178 sqlite3_int64 nAlloc; /* Number of cells allocated */
2179 sqlite3_int64 n; /* Number of cells. nCol*nRow */
2180 char **az; /* Content of all cells */
2181 int *aiWth; /* Width of each cell */
 
2182 struct qrfPerCol { /* Per-column data */
2183 char *z; /* Cache of text for current row */
2184 int w; /* Computed width of this column */
2185 int mxW; /* Maximum natural (unwrapped) width */
2186 unsigned char e; /* Alignment */
2187 unsigned char fx; /* Width is fixed */
 
2188 } *a; /* One per column */
2189 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2190
2191 /*
2192 ** Free all the memory allocates in the qrfColData object
2193 */
2194 static void qrfColDataFree(qrfColData *p){
2195 sqlite3_int64 i;
2196 for(i=0; i<p->n; i++) sqlite3_free(p->az[i]);
2197 sqlite3_free(p->az);
2198 sqlite3_free(p->aiWth);
 
2199 sqlite3_free(p->a);
2200 memset(p, 0, sizeof(*p));
2201 }
2202
2203 /*
@@ -2205,10 +2332,11 @@
2205 ** Return non-zero if a memory allocation fails.
2206 */
2207 static int qrfColDataEnlarge(qrfColData *p){
2208 char **azData;
2209 int *aiWth;
 
2210 p->nAlloc = 2*p->nAlloc + 10*p->nCol;
2211 azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*));
2212 if( azData==0 ){
2213 qrfOom(p->p);
2214 qrfColDataFree(p);
@@ -2220,26 +2348,38 @@
2220 qrfOom(p->p);
2221 qrfColDataFree(p);
2222 return 1;
2223 }
2224 p->aiWth = aiWth;
 
 
 
 
 
 
 
2225 return 0;
2226 }
2227
2228 /*
2229 ** Print a markdown or table-style row separator using ascii-art
2230 */
2231 static void qrfRowSeparator(sqlite3_str *pOut, qrfColData *p, char cSep){
2232 int i;
2233 if( p->nCol>0 ){
2234 sqlite3_str_append(pOut, &cSep, 1);
 
 
 
2235 sqlite3_str_appendchar(pOut, p->a[0].w+p->nMargin, '-');
2236 for(i=1; i<p->nCol; i++){
2237 sqlite3_str_append(pOut, &cSep, 1);
2238 sqlite3_str_appendchar(pOut, p->a[i].w+p->nMargin, '-');
2239 }
2240 sqlite3_str_append(pOut, &cSep, 1);
 
 
2241 }
2242 sqlite3_str_append(pOut, "\n", 1);
2243 }
2244
2245 /*
@@ -2265,24 +2405,37 @@
2265 #define BOX_134 "\342\224\244" /* U+2524 -| */
2266 #define BOX_234 "\342\224\254" /* U+252c -,- */
2267 #define BOX_124 "\342\224\264" /* U+2534 -'- */
2268 #define BOX_1234 "\342\224\274" /* U+253c -|- */
2269
 
 
 
 
 
 
 
 
 
 
 
 
2270 /* Draw horizontal line N characters long using unicode box
2271 ** characters
2272 */
2273 static void qrfBoxLine(sqlite3_str *pOut, int N){
2274 const char zDash[] =
2275 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
2276 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
2277 const int nDash = sizeof(zDash) - 1;
 
2278 N *= 3;
2279 while( N>nDash ){
2280 sqlite3_str_append(pOut, zDash, nDash);
2281 N -= nDash;
2282 }
2283 sqlite3_str_append(pOut, zDash, N);
2284 }
2285
2286 /*
2287 ** Draw a horizontal separator for a QRF_STYLE_Box table.
2288 */
@@ -2289,21 +2442,27 @@
2289 static void qrfBoxSeparator(
2290 sqlite3_str *pOut,
2291 qrfColData *p,
2292 const char *zSep1,
2293 const char *zSep2,
2294 const char *zSep3
 
2295 ){
2296 int i;
2297 if( p->nCol>0 ){
2298 sqlite3_str_appendall(pOut, zSep1);
2299 qrfBoxLine(pOut, p->a[0].w+p->nMargin);
 
 
 
2300 for(i=1; i<p->nCol; i++){
2301 sqlite3_str_appendall(pOut, zSep2);
2302 qrfBoxLine(pOut, p->a[i].w+p->nMargin);
2303 }
2304 sqlite3_str_appendall(pOut, zSep3);
 
 
2305 }
2306 sqlite3_str_append(pOut, "\n", 1);
2307 }
2308
2309 /*
@@ -2382,10 +2541,11 @@
2382 static void qrfSplitColumn(qrfColData *pData, Qrf *p){
2383 int nCol = 1;
2384 int *aw = 0;
2385 char **az = 0;
2386 int *aiWth = 0;
 
2387 int nColNext = 2;
2388 int w;
2389 struct qrfPerCol *a = 0;
2390 sqlite3_int64 nRow = 1;
2391 sqlite3_int64 i;
@@ -2419,35 +2579,47 @@
2419 if( a==0 ){
2420 sqlite3_free(az);
2421 sqlite3_free(aiWth);
2422 qrfOom(p);
2423 return;
 
 
 
 
 
 
 
 
2424 }
2425 for(i=0; i<pData->n; i++){
2426 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2427 az[j] = pData->az[i];
 
2428 pData->az[i] = 0;
2429 aiWth[j] = pData->aiWth[i];
2430 }
2431 while( i<nRow*nCol ){
2432 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2433 az[j] = sqlite3_mprintf("");
2434 if( az[j]==0 ) qrfOom(p);
2435 aiWth[j] = 0;
 
2436 i++;
2437 }
2438 for(i=0; i<nCol; i++){
2439 a[i].fx = a[i].mxW = a[i].w = aw[i];
2440 a[i].e = pData->a[0].e;
2441 }
2442 sqlite3_free(pData->az);
2443 sqlite3_free(pData->aiWth);
2444 sqlite3_free(pData->a);
 
2445 sqlite3_free(aw);
2446 pData->az = az;
2447 pData->aiWth = aiWth;
2448 pData->a = a;
 
2449 pData->nCol = nCol;
2450 pData->n = pData->nAlloc = nRow*nCol;
2451 for(i=w=0; i<nCol; i++) w += a[i].w;
2452 pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1);
2453 if( pData->nMargin>5 ) pData->nMargin = 5;
@@ -2467,10 +2639,11 @@
2467 if( p->spec.nScreenWidth==0 ) return;
2468 if( p->spec.eStyle==QRF_STYLE_Column ){
2469 sepW = pData->nCol*2 - 2;
2470 }else{
2471 sepW = pData->nCol*3 + 1;
 
2472 }
2473 nCol = pData->nCol;
2474 for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
2475 if( p->spec.nScreenWidth >= sumW+sepW ) return;
2476
@@ -2478,10 +2651,11 @@
2478 pData->nMargin = 0;
2479 if( p->spec.eStyle==QRF_STYLE_Column ){
2480 sepW = pData->nCol - 1;
2481 }else{
2482 sepW = pData->nCol + 1;
 
2483 }
2484 targetW = p->spec.nScreenWidth - sepW;
2485
2486 #define MIN_SQUOZE 8
2487 #define MIN_EX_SQUOZE 16
@@ -2550,10 +2724,11 @@
2550 }
2551
2552 /* Initialize the data container */
2553 memset(&data, 0, sizeof(data));
2554 data.nCol = p->nCol;
 
2555 data.a = sqlite3_malloc64( nColumn*sizeof(struct qrfPerCol) );
2556 if( data.a==0 ){
2557 qrfOom(p);
2558 return;
2559 }
@@ -2563,19 +2738,27 @@
2563
2564 /* Load the column header names and all cell content into data */
2565 if( p->spec.bTitles==QRF_Yes ){
2566 unsigned char saved_eText = p->spec.eText;
2567 p->spec.eText = p->spec.eTitle;
 
2568 for(i=0; i<nColumn; i++){
2569 const char *z = (const char*)sqlite3_column_name(p->pStmt,i);
2570 int nNL = 0;
2571 int n, w;
2572 pStr = sqlite3_str_new(p->db);
2573 qrfEncodeText(p, pStr, z ? z : "");
2574 n = sqlite3_str_length(pStr);
 
2575 z = data.az[data.n] = sqlite3_str_finish(pStr);
2576 data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
 
 
 
 
 
 
2577 data.n++;
2578 if( w>data.a[i].mxW ) data.a[i].mxW = w;
2579 if( nNL ) data.bMultiRow = 1;
2580 }
2581 p->spec.eText = saved_eText;
@@ -2587,14 +2770,17 @@
2587 }
2588 for(i=0; i<nColumn; i++){
2589 char *z;
2590 int nNL = 0;
2591 int n, w;
 
2592 pStr = sqlite3_str_new(p->db);
2593 qrfRenderValue(p, pStr, i);
2594 n = sqlite3_str_length(pStr);
 
2595 z = data.az[data.n] = sqlite3_str_finish(pStr);
 
2596 data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
2597 data.n++;
2598 if( w>data.a[i].mxW ) data.a[i].mxW = w;
2599 if( nNL ) data.bMultiRow = 1;
2600 }
@@ -2680,11 +2866,16 @@
2680 }else{
2681 rowStart = BOX_13;
2682 colSep = BOX_13;
2683 rowSep = BOX_13 "\n";
2684 }
2685 qrfBoxSeparator(p->pOut, &data, BOX_23, BOX_234, BOX_34);
 
 
 
 
 
2686 break;
2687 case QRF_STYLE_Table:
2688 if( data.nMargin ){
2689 rowStart = "| ";
2690 colSep = " | ";
@@ -2692,11 +2883,16 @@
2692 }else{
2693 rowStart = "|";
2694 colSep = "|";
2695 rowSep = "|\n";
2696 }
2697 qrfRowSeparator(p->pOut, &data, '+');
 
 
 
 
 
2698 break;
2699 case QRF_STYLE_Column: {
2700 static const char zSpace[] = " ";
2701 rowStart = "";
2702 if( data.nMargin<2 ){
@@ -2724,20 +2920,32 @@
2724 szRowStart = (int)strlen(rowStart);
2725 szRowSep = (int)strlen(rowSep);
2726 szColSep = (int)strlen(colSep);
2727
2728 bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
2729 bRTrim = (p->spec.eStyle==QRF_STYLE_Column);
2730 for(i=0; i<data.n; i+=nColumn){
 
 
 
 
 
 
 
 
2731 int bMore;
2732 int nRow = 0;
2733
2734 /* Draw a single row of the table. This might be the title line
2735 ** (if there is a title line) or a row in the body of the table.
2736 ** The column number will be j. The row number is i/nColumn.
2737 */
2738 for(j=0; j<nColumn; j++){ data.a[j].z = data.az[i+j]; }
 
 
 
 
2739 do{
2740 sqlite3_str_append(p->pOut, rowStart, szRowStart);
2741 bMore = 0;
2742 for(j=0; j<nColumn; j++){
2743 int nThis = 0;
@@ -2744,11 +2952,11 @@
2744 int nWide = 0;
2745 int iNext = 0;
2746 int nWS;
2747 qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
2748 nWS = data.a[j].w - nWide;
2749 qrfPrintAligned(p->pOut, data.a[j].z, nThis, nWS, data.a[j].e);
2750 data.a[j].z += iNext;
2751 if( data.a[j].z[0]!=0 ){
2752 bMore = 1;
2753 }
2754 if( j<nColumn-1 ){
@@ -2766,11 +2974,12 @@
2766 if( data.a[j].z[0]==0 ){
2767 sqlite3_str_appendchar(p->pOut, data.a[j].w, ' ');
2768 }else{
2769 int nE = 3;
2770 if( nE>data.a[j].w ) nE = data.a[j].w;
2771 qrfPrintAligned(p->pOut, "...", nE, data.a[j].w-nE, data.a[j].e);
 
2772 }
2773 if( j<nColumn-1 ){
2774 sqlite3_str_append(p->pOut, colSep, szColSep);
2775 }else{
2776 if( bRTrim ) qrfRTrim(p->pOut);
@@ -2794,12 +3003,14 @@
2794 qrfRowSeparator(p->pOut, &data, '+');
2795 }
2796 break;
2797 }
2798 case QRF_STYLE_Box: {
2799 if( isTitleDataSeparator || data.bMultiRow ){
2800 qrfBoxSeparator(p->pOut, &data, BOX_123, BOX_1234, BOX_134);
 
 
2801 }
2802 break;
2803 }
2804 case QRF_STYLE_Markdown: {
2805 if( isTitleDataSeparator ){
@@ -2827,17 +3038,19 @@
2827 }
2828 }
2829 }
2830
2831 /* Draw the line across the bottom of the table */
2832 switch( p->spec.eStyle ){
2833 case QRF_STYLE_Box:
2834 qrfBoxSeparator(p->pOut, &data, BOX_12, BOX_124, BOX_14);
2835 break;
2836 case QRF_STYLE_Table:
2837 qrfRowSeparator(p->pOut, &data, '+');
2838 break;
 
 
2839 }
2840 qrfWrite(p);
2841
2842 qrfColDataFree(&data);
2843 return;
@@ -2903,11 +3116,11 @@
2903 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) );
2904 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) );
2905 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) );
2906 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) );
2907
2908 for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt); iOp++){
2909 int iAddr = sqlite3_column_int(p->pStmt, 0);
2910 const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1);
2911 int p1 = sqlite3_column_int(p->pStmt, 2);
2912 int p2 = sqlite3_column_int(p->pStmt, 3);
2913
@@ -2960,11 +3173,11 @@
2960 nWidth = sizeof(aScanExpWidth)/sizeof(int);
2961 iIndent = 3;
2962 }
2963 if( nArg>nWidth ) nArg = nWidth;
2964
2965 for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW; iOp++){
2966 /* If this is the first row seen, print out the headers */
2967 if( iOp==0 ){
2968 for(i=0; i<nArg; i++){
2969 const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]);
2970 qrfWidthPrint(p,p->pOut, aWidth[i], zCol);
@@ -2989,11 +3202,11 @@
2989 int w = aWidth[i];
2990 const char *zVal = (const char*)sqlite3_column_text(p->pStmt, aMap[i]);
2991 int len;
2992 if( i==nArg-1 ) w = 0;
2993 if( zVal==0 ) zVal = "";
2994 len = qrfDisplayLength(zVal);
2995 if( len>w ){
2996 w = len;
2997 zSep = " ";
2998 }
2999 if( i==iIndent && aiIndent && iOp<nIndent ){
@@ -3168,34 +3381,40 @@
3168 }
3169 case QRF_STYLE_Line: {
3170 sqlite3_str *pVal;
3171 int mxW;
3172 int bWW;
 
3173 if( p->u.sLine.azCol==0 ){
3174 p->u.sLine.azCol = sqlite3_malloc64( p->nCol*sizeof(char*) );
3175 if( p->u.sLine.azCol==0 ){
3176 qrfOom(p);
3177 break;
3178 }
3179 p->u.sLine.mxColWth = 0;
3180 for(i=0; i<p->nCol; i++){
3181 int sz;
3182 p->u.sLine.azCol[i] = sqlite3_column_name(p->pStmt, i);
3183 if( p->u.sLine.azCol[i]==0 ) p->u.sLine.azCol[i] = "unknown";
3184 sz = qrfDisplayLength(p->u.sLine.azCol[i]);
 
 
 
 
3185 if( sz > p->u.sLine.mxColWth ) p->u.sLine.mxColWth = sz;
3186 }
3187 }
3188 if( p->nRow ) sqlite3_str_append(p->pOut, "\n", 1);
3189 pVal = sqlite3_str_new(p->db);
3190 mxW = p->mxWidth - (3 + p->u.sLine.mxColWth);
 
3191 bWW = p->spec.bWordWrap==QRF_Yes;
3192 for(i=0; i<p->nCol; i++){
3193 const char *zVal;
3194 int cnt = 0;
3195 qrfWidthPrint(p, p->pOut, -p->u.sLine.mxColWth, p->u.sLine.azCol[i]);
3196 sqlite3_str_append(p->pOut, " = ", 3);
3197 qrfRenderValue(p, pVal, i);
3198 zVal = sqlite3_str_value(pVal);
3199 if( zVal==0 ) zVal = "";
3200 do{
3201 int nThis, nWide, iNext;
@@ -3210,10 +3429,11 @@
3210 sqlite3_str_append(p->pOut, "\n", 1);
3211 zVal += iNext;
3212 }while( zVal[0] );
3213 sqlite3_str_reset(pVal);
3214 }
 
3215 sqlite3_free(sqlite3_str_finish(pVal));
3216 qrfWrite(p);
3217 break;
3218 }
3219 case QRF_STYLE_Eqp: {
@@ -3273,11 +3493,11 @@
3273 p->pOut = sqlite3_str_new(p->db);
3274 if( p->pOut==0 ){
3275 qrfOom(p);
3276 return;
3277 }
3278 p->iErr = 0;
3279 p->nCol = sqlite3_column_count(p->pStmt);
3280 p->nRow = 0;
3281 sz = sizeof(sqlite3_qrf_spec);
3282 memcpy(&p->spec, pSpec, sz);
3283 if( p->spec.zNull==0 ) p->spec.zNull = "";
@@ -3285,12 +3505,12 @@
3285 if( p->mxWidth<=0 ) p->mxWidth = QRF_MAX_WIDTH;
3286 p->mxHeight = p->spec.nLineLimit;
3287 if( p->mxHeight<=0 ) p->mxHeight = 2147483647;
3288 if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto;
3289 if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto;
3290 if( p->spec.eText>QRF_TEXT_Json ) p->spec.eText = QRF_Auto;
3291 if( p->spec.eTitle>QRF_TEXT_Json ) p->spec.eTitle = QRF_Auto;
3292 if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto;
3293 qrf_reinit:
3294 switch( p->spec.eStyle ){
3295 case QRF_Auto: {
3296 switch( sqlite3_stmt_isexplain(pStmt) ){
@@ -3321,10 +3541,16 @@
3321 p->spec.zNull = "NULL";
3322 if( p->spec.zTableName==0 || p->spec.zTableName[0]==0 ){
3323 p->spec.zTableName = "tab";
3324 }
3325 break;
 
 
 
 
 
 
3326 }
3327 case QRF_STYLE_Csv: {
3328 p->spec.eStyle = QRF_STYLE_List;
3329 p->spec.eText = QRF_TEXT_Csv;
3330 p->spec.zColumnSep = ",";
@@ -3430,11 +3656,15 @@
3430 qrfWrite(p);
3431 }
3432 break;
3433 }
3434 case QRF_STYLE_Line: {
3435 if( p->u.sLine.azCol ) sqlite3_free(p->u.sLine.azCol);
 
 
 
 
3436 break;
3437 }
3438 case QRF_STYLE_Stats:
3439 case QRF_STYLE_StatsEst:
3440 case QRF_STYLE_Eqp: {
@@ -3441,10 +3671,11 @@
3441 qrfEqpRender(p, 0);
3442 qrfWrite(p);
3443 break;
3444 }
3445 }
 
3446 if( p->spec.pzOutput ){
3447 if( p->spec.pzOutput[0] ){
3448 sqlite3_int64 n, sz;
3449 char *zCombined;
3450 sz = strlen(p->spec.pzOutput[0]);
@@ -3624,11 +3855,11 @@
3624
3625 /* Return the current wall-clock time in microseconds since the
3626 ** Unix epoch (1970-01-01T00:00:00Z)
3627 */
3628 static sqlite3_int64 timeOfDay(void){
3629 #if defined(_WIN64)
3630 sqlite3_uint64 t;
3631 FILETIME tm;
3632 GetSystemTimePreciseAsFileTime(&tm);
3633 t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
3634 t += 116444736000000000LL;
@@ -3724,11 +3955,10 @@
3724 */
3725 static int hasTimer(void){
3726 if( getProcessTimesAddr ){
3727 return 1;
3728 } else {
3729 #if !SQLITE_OS_WINRT
3730 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
3731 ** versions. See if the version we are running on has it, and if it
3732 ** does, save off a pointer to it and the current process handle.
3733 */
3734 hProcess = GetCurrentProcess();
@@ -3741,11 +3971,10 @@
3741 return 1;
3742 }
3743 FreeLibrary(hinstLib);
3744 }
3745 }
3746 #endif
3747 }
3748 return 0;
3749 }
3750
3751 /*
@@ -3860,10 +4089,18 @@
3860 #define PROMPT_LEN_MAX 128
3861 /* First line prompt. default: "sqlite> " */
3862 static char mainPrompt[PROMPT_LEN_MAX];
3863 /* Continuation prompt. default: " ...> " */
3864 static char continuePrompt[PROMPT_LEN_MAX];
 
 
 
 
 
 
 
 
3865
3866 /* This is variant of the standard-library strncpy() routine with the
3867 ** one change that the destination string is always zero-terminated, even
3868 ** if there is no zero-terminator in the first n-1 characters of the source
3869 ** string.
@@ -3980,17 +4217,10 @@
3980 */
3981 static void shell_check_oom(const void *p){
3982 if( p==0 ) shell_out_of_memory();
3983 }
3984
3985 /*
3986 ** Write I/O traces to the following stream.
3987 */
3988 #ifdef SQLITE_ENABLE_IOTRACE
3989 static FILE *iotrace = 0;
3990 #endif
3991
3992 /*
3993 ** This routine works like printf in that its first argument is a
3994 ** format string and subsequent arguments are values to be substituted
3995 ** in place of % fields. The result of formatting this string
3996 ** is written to iotrace.
@@ -6013,17 +6243,20 @@
6013 }
6014 /* End of the hashing logic
6015 *****************************************************************************/
6016
6017 /*
6018 ** Implementation of the sha1(X) function.
6019 **
6020 ** Return a lower-case hexadecimal rendering of the SHA1 hash of the
6021 ** argument X. If X is a BLOB, it is hashed as is. For all other
6022 ** types of input, X is converted into a UTF-8 string and the string
6023 ** is hash without the trailing 0x00 terminator. The hash of a NULL
6024 ** value is NULL.
 
 
 
6025 */
6026 static void sha1Func(
6027 sqlite3_context *context,
6028 int argc,
6029 sqlite3_value **argv
@@ -6040,15 +6273,17 @@
6040 hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
6041 }else{
6042 hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
6043 }
6044 if( sqlite3_user_data(context)!=0 ){
 
6045 hash_finish(&cx, zOut, 1);
6046 sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
6047 }else{
 
6048 hash_finish(&cx, zOut, 0);
6049 sqlite3_result_blob(context, zOut, 40, SQLITE_TRANSIENT);
6050 }
6051 }
6052
6053 /*
6054 ** Implementation of the sha1_query(SQL) function.
@@ -8136,13 +8371,13 @@
8136 }else if( e<-10000 ){
8137 e = -10000;
8138 }
8139
8140 if( m<0 ){
 
8141 isNeg = 1;
8142 m = -m;
8143 if( m<0 ) return;
8144 }else if( m==0 && e>-1000 && e<1000 ){
8145 sqlite3_result_double(context, 0.0);
8146 return;
8147 }
8148 while( (m>>32)&0xffe00000 ){
@@ -9259,11 +9494,11 @@
9259 ** (X) match X
9260 ** X|Y X or Y
9261 ** ^X X occurring at the beginning of the string
9262 ** X$ X occurring at the end of the string
9263 ** . Match any single character
9264 ** \c Character c where c is one of \{}()[]|*+?.
9265 ** \c C-language escapes for c in afnrtv. ex: \t or \n
9266 ** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
9267 ** \xXX Where XX is exactly 2 hex digits, unicode value XX
9268 ** [abc] Any single character from the set abc
9269 ** [^abc] Any single character not in the set abc
@@ -9644,11 +9879,11 @@
9644
9645 /* A backslash character has been seen, read the next character and
9646 ** return its interpretation.
9647 */
9648 static unsigned re_esc_char(ReCompiled *p){
9649 static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]";
9650 static const char zTrans[] = "\a\f\n\r\t\v";
9651 int i, v = 0;
9652 char c;
9653 if( p->sIn.i>=p->sIn.mx ) return 0;
9654 c = p->sIn.z[p->sIn.i];
@@ -9967,15 +10202,22 @@
9967 }
9968 return pRe->zErr;
9969 }
9970
9971 /*
9972 ** Compute a reasonable limit on the length of the REGEXP NFA.
9973 */
9974 static int re_maxlen(sqlite3_context *context){
9975 sqlite3 *db = sqlite3_context_db_handle(context);
9976 return 75 + sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1)/2;
 
 
 
 
 
 
 
9977 }
9978
9979 /*
9980 ** Implementation of the regexp() SQL function. This function implements
9981 ** the build-in REGEXP operator. The first argument to the function is the
@@ -9997,14 +10239,21 @@
9997 int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
9998
9999 (void)argc; /* Unused */
10000 pRe = sqlite3_get_auxdata(context, 0);
10001 if( pRe==0 ){
 
 
10002 zPattern = (const char*)sqlite3_value_text(argv[0]);
10003 if( zPattern==0 ) return;
10004 zErr = re_compile(&pRe, zPattern, re_maxlen(context),
10005 sqlite3_user_data(context)!=0);
 
 
 
 
 
10006 if( zErr ){
10007 re_free(pRe);
10008 sqlite3_result_error(context, zErr, -1);
10009 return;
10010 }
@@ -10066,11 +10315,11 @@
10066 "ATSTART",
10067 };
10068
10069 zPattern = (const char*)sqlite3_value_text(argv[0]);
10070 if( zPattern==0 ) return;
10071 zErr = re_compile(&pRe, zPattern, re_maxlen(context),
10072 sqlite3_user_data(context)!=0);
10073 if( zErr ){
10074 re_free(pRe);
10075 sqlite3_result_error(context, zErr, -1);
10076 return;
@@ -10474,10 +10723,11 @@
10474 if( b1==0 ) return 1;
10475 sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
10476 b1[sz] = 0;
10477 rc = _wstat(b1, pStatBuf);
10478 if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
 
10479 return rc;
10480 #else
10481 return stat(zPath, pStatBuf);
10482 #endif
10483 }
@@ -10604,11 +10854,10 @@
10604 }
10605 }
10606
10607 if( mtime>=0 ){
10608 #if defined(_WIN32)
10609 #if !SQLITE_OS_WINRT
10610 /* Windows */
10611 FILETIME lastAccess;
10612 FILETIME lastWrite;
10613 SYSTEMTIME currentTime;
10614 LONGLONG intervals;
@@ -10635,11 +10884,10 @@
10635 CloseHandle(hFile);
10636 return !bResult;
10637 }else{
10638 return 1;
10639 }
10640 #endif
10641 #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
10642 /* Recent unix */
10643 struct timespec times[2];
10644 times[0].tv_nsec = times[1].tv_nsec = 0;
10645 times[0].tv_sec = time(0);
@@ -13337,11 +13585,11 @@
13337 rc = zipfileReadData(
13338 pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
13339 );
13340 }else{
13341 aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
13342 if( (iOff + ZIPFILE_LFH_FIXED_SZ + nFile + nExtra)>nBlob ){
13343 rc = zipfileCorrupt(pzErr);
13344 }
13345 }
13346 }
13347
@@ -13362,15 +13610,16 @@
13362 ZipfileLFH lfh;
13363 if( pFile ){
13364 rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
13365 }else{
13366 aRead = (u8*)&aBlob[pNew->cds.iOffset];
13367 if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){
13368 rc = zipfileCorrupt(pzErr);
13369 }
13370 }
13371
 
13372 if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
13373 if( rc==SQLITE_OK ){
13374 pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
13375 pNew->iDataOff += lfh.nFile + lfh.nExtra;
13376 if( aBlob && pNew->cds.szCompressed ){
@@ -13470,11 +13719,11 @@
13470 }else{
13471 err = inflate(&str, Z_NO_FLUSH);
13472 if( err!=Z_STREAM_END ){
13473 zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
13474 }else{
13475 sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
13476 aRes = 0;
13477 }
13478 }
13479 sqlite3_free(aRes);
13480 inflateEnd(&str);
@@ -23948,28 +24197,28 @@
23948 u8 autoExplain; /* Automatically turn on .explain mode */
23949 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
23950 u8 autoEQPtrace; /* autoEQP is in trace mode */
23951 u8 scanstatsOn; /* True to display scan stats before each finalize */
23952 u8 bAutoScreenWidth; /* Using the TTY to determine screen width */
23953 u8 mFlags; /* MFLG_ECHO and/or MFLG_CRLF */
23954 u8 eMode; /* One of the MODE_ values */
23955 sqlite3_qrf_spec spec; /* Spec to be passed into QRF */
23956 } Mode;
23957
23958 /* Flags for Mode.mFlags */
23959 #define MFLG_ECHO 0x01 /* Echo inputs to output */
23960 #define MFLG_CRLF 0x02 /* Use CR/LF output line endings */
 
23961
23962
23963 /*
23964 ** State information about the database connection is contained in an
23965 ** instance of the following structure.
23966 */
23967 typedef struct ShellState ShellState;
23968 struct ShellState {
23969 sqlite3 *db; /* The database */
23970 int iCompat; /* Compatibility date YYYYMMDD */
23971 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
23972 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
23973 u8 nEqpLevel; /* Depth of the EQP output graph */
23974 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
23975 u8 bSafeMode; /* True to prohibit unsafe operations */
@@ -24078,11 +24327,11 @@
24078
24079 /* Names of values for Mode.spec.eEsc and Mode.spec.eText
24080 */
24081 static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" };
24082 static const char *qrfQuoteNames[] =
24083 { "off","off","sql","hex","csv","tcl","json"};
24084
24085 /*
24086 ** These are the allowed shellFlgs values
24087 */
24088 #define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
@@ -24120,19 +24369,20 @@
24120 #define MODE_Json 10 /* Output JSON */
24121 #define MODE_Line 11 /* One column per line. Blank line between records */
24122 #define MODE_List 12 /* One record per line with a separator */
24123 #define MODE_Markdown 13 /* Markdown formatting */
24124 #define MODE_Off 14 /* No query output shown */
24125 #define MODE_QBox 15 /* BOX with SQL-quoted content */
24126 #define MODE_Quote 16 /* Quote values as for SQL */
24127 #define MODE_Split 17 /* Split-column mode */
24128 #define MODE_Table 18 /* MySQL-style table formatting */
24129 #define MODE_Tabs 19 /* Tab-separated values */
24130 #define MODE_Tcl 20 /* Space-separated list of TCL strings */
24131 #define MODE_Www 21 /* Full web-page output */
24132
24133 #define MODE_BUILTIN 21 /* Maximum built-in mode */
 
24134 #define MODE_BATCH 50 /* Default mode for batch processing */
24135 #define MODE_TTY 51 /* Default mode for interactive processing */
24136 #define MODE_USER 75 /* First user-defined mode */
24137 #define MODE_N_USER 25 /* Maximum number of user-defined modes */
24138
@@ -24149,43 +24399,45 @@
24149 unsigned char eHdr; /* Default header encoding. */
24150 unsigned char eBlob; /* Default blob encoding. */
24151 unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */
24152 unsigned char eStyle; /* Underlying QRF style */
24153 unsigned char eCx; /* 0: other, 1: line, 2: columnar */
 
24154 };
24155
24156 /* String constants used by built-in modes */
24157 static const char *aModeStr[] =
24158 /* 0 1 2 3 4 5 6 7 8 */
24159 { 0, "\n", "|", " ", ",", "\r\n", "\036", "\037", "\t",
24160 "", "NULL", "null", "\"\"" };
24161 /* 9 10 11 12 */
24162
24163 static const ModeInfo aModeInfo[] = {
24164 /* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx */
24165 { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0 },
24166 { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2 },
24167 { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0 },
24168 { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2 },
24169 { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0 },
24170 { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0 },
24171 { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0 },
24172 { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0 },
24173 { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0 },
24174 { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0 },
24175 { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0 },
24176 { "line", 0, 1, 9, 1, 1, 0, 0, 11, 1 },
24177 { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0 },
24178 { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2 },
24179 { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0 },
24180 { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2 },
24181 { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0 },
24182 { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2 },
24183 { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2 },
24184 { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0 },
24185 { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0 },
24186 { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0 }
 
24187 }; /* | / / | / / | | \
24188 ** | / / | / / | | \_ 2: columnar
24189 ** Index into aModeStr[] | / / | | 1: line
24190 ** | / / | | 0: other
24191 ** | / / | \
@@ -24212,10 +24464,23 @@
24212 #define SEP_Comma ","
24213 #define SEP_CrLf "\r\n"
24214 #define SEP_Unit "\x1F"
24215 #define SEP_Record "\x1E"
24216
 
 
 
 
 
 
 
 
 
 
 
 
 
24217 /*
24218 ** Limit input nesting via .read or any other input redirect.
24219 ** It's not too expensive, so a generous allowance can be made.
24220 */
24221 #define MAX_INPUT_NESTING 25
@@ -24305,13 +24570,20 @@
24305 if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]);
24306 if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]);
24307 if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
24308 pM->spec.eText = pI->eText;
24309 pM->spec.eBlob = pI->eBlob;
24310 pM->spec.bTitles = pI->bHdr;
 
 
24311 pM->spec.eTitle = pI->eHdr;
24312 if( eMode==MODE_Split ){
 
 
 
 
 
24313 pM->spec.bSplitColumn = QRF_Yes;
24314 pM->bAutoScreenWidth = 1;
24315 }else{
24316 pM->spec.bSplitColumn = QRF_No;
24317 }
@@ -24326,26 +24598,27 @@
24326 }else if( eMode==MODE_TTY ){
24327 u8 mFlags = p->mode.mFlags;
24328 modeFree(&p->mode);
24329 modeChange(p, MODE_QBox);
24330 p->mode.bAutoScreenWidth = 1;
24331 p->mode.spec.nCharLimit = 300;
24332 p->mode.spec.nLineLimit = 5;
 
24333 p->mode.spec.bTextJsonb = QRF_Yes;
 
24334 p->mode.mFlags = mFlags;
24335 }
24336 }
24337
24338 /*
24339 ** Set the mode to the default according to p->iCompat. It assumed
24340 ** that the mode has already been freed and zeroed prior to calling
24341 ** this routine.
24342 */
24343 static void modeDefault(ShellState *p){
24344 p->mode.spec.iVersion = 1;
24345 p->mode.autoExplain = 1;
24346 if( p->iCompat>=20251115 && (stdin_is_interactive || stdout_is_console) ){
24347 modeChange(p, MODE_TTY);
24348 }else{
24349 modeChange(p, MODE_BATCH);
24350 }
24351 }
@@ -25075,10 +25348,12 @@
25075 z[j] = 0;
25076 if( strlen30(z)>=79 ){
25077 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
25078 if( c==cEnd ){
25079 cEnd = 0;
 
 
25080 }else if( c=='"' || c=='\'' || c=='`' ){
25081 cEnd = c;
25082 }else if( c=='[' ){
25083 cEnd = ']';
25084 }else if( c=='-' && z[i+1]=='-' ){
@@ -25889,10 +26164,11 @@
25889 if( pArg->mode.bAutoScreenWidth ){
25890 spec.nScreenWidth = shellScreenWidth();
25891 }
25892 if( spec.eBlob==QRF_BLOB_Auto ){
25893 switch( spec.eText ){
 
25894 case QRF_TEXT_Sql: spec.eBlob = QRF_BLOB_Sql; break;
25895 case QRF_TEXT_Json: spec.eBlob = QRF_BLOB_Json; break;
25896 default: spec.eBlob = QRF_BLOB_Text; break;
25897 }
25898 }
@@ -25902,11 +26178,11 @@
25902 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
25903 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
25904 }
25905 #endif
25906
25907 while( zSql[0] && (SQLITE_OK == rc) ){
25908 static const char *zStmtSql;
25909 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
25910 if( SQLITE_OK != rc ){
25911 if( pzErrMsg ){
25912 *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
@@ -26365,12 +26641,12 @@
26365 ".bail on|off Stop after hitting an error. Default OFF",
26366 #ifndef SQLITE_SHELL_FIDDLE
26367 ".cd DIRECTORY Change the working directory to DIRECTORY",
26368 #endif
26369 ".changes on|off Show number of rows changed by SQL",
 
26370 #ifndef SQLITE_SHELL_FIDDLE
26371 ".check GLOB Fail if output since .testcase does not match",
26372 ".clone NEWDB Clone data into NEWDB from the existing database",
26373 #endif
26374 ".connection [close] [#] Open or close an auxiliary database connection",
26375 ".crlf ?on|off? Whether or not to use \\r\\n line endings",
26376 ".databases List names and files of attached databases",
@@ -26546,13 +26822,11 @@
26546 " vmstep Show the virtual machine step count only",
26547 #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
26548 ".system CMD ARGS... Run CMD ARGS... in a system shell",
26549 #endif
26550 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
26551 #ifndef SQLITE_SHELL_FIDDLE
26552 ",testcase NAME Begin redirecting output to 'testcase-out.txt'",
26553 #endif
26554 ",testctrl CMD ... Run various sqlite3_test_control() operations",
26555 " Run \".testctrl\" with no arguments for details",
26556 ".timeout MS Try opening locked tables for MS milliseconds",
26557 ".timer on|off Turn SQL timer on or off",
26558 #ifndef SQLITE_OMIT_TRACE
@@ -26597,19 +26871,31 @@
26597 "USAGE: .import [OPTIONS] FILE TABLE\n"
26598 "\n"
26599 "Import CSV or similar text from FILE into TABLE. If TABLE does\n"
26600 "not exist, it is created using the first row of FILE as the column\n"
26601 "names. If FILE begins with \"|\" then it is a command that is run\n"
26602 "and the output from the command is used as the input data.\n"
 
 
 
 
 
 
26603 "\n"
26604 "FILE is assumed to be in a CSV format, unless the current mode\n"
26605 "is \"ascii\" or \"tabs\" or unless one of the options below specify\n"
26606 "an alternative.\n"
 
 
26607 "\n"
26608 "Options:\n"
26609 " --ascii Use \\037 and \\036 as column and row separators on input\n"
 
 
 
26610 " --csv Input is standard RFC-4180 CSV.\n"
 
26611 " --schema S When creating TABLE, put it in schema S\n"
26612 " --skip N Ignore the first N rows of input\n"
26613 " -v Verbose mode\n"
26614 },
26615 { ".mode",
@@ -26625,10 +26911,11 @@
26625 " meaning \"left\", \"centered\", and \"right\", with\n"
26626 " one letter per column starting from the left.\n"
26627 " Unspecified alignment defaults to 'L'.\n"
26628 " --blob-quote ARG ARG can be \"auto\", \"text\", \"sql\", \"hex\", \"tcl\",\n"
26629 " \"json\", or \"size\". Default is \"auto\".\n"
 
26630 " --charlimit N Set the maximum number of output characters to\n"
26631 " show for any single SQL value to N. Longer values\n"
26632 " truncated. Zero means \"no limit\".\n"
26633 " --colsep STRING Use STRING as the column separator\n"
26634 " --escape ESC Enable/disable escaping of control characters\n"
@@ -26636,19 +26923,22 @@
26636 " or \"symbol\".\n"
26637 " --linelimit N Set the maximum number of output lines to show for\n"
26638 " any single SQL value to N. Longer values are\n"
26639 " truncated. Zero means \"no limit\". Only works\n"
26640 " in \"line\" mode and in columnar modes.\n"
26641 " --limits L,C Shorthand for \"--linelimit L --charlimit C\".\n"
26642 " Or \"off\" to mean \"0,0\". Or \"on\" for \"5,300\".\n"
 
 
 
26643 " --list List available modes\n"
26644 " --null STRING Render SQL NULL values as the given string\n"
26645 " --once Setting changes to the right are reverted after\n"
26646 " the next SQL command.\n"
26647 " --quote ARG Enable/disable quoting of text. ARG can be\n"
26648 " \"off\", \"on\", \"sql\", \"csv\", \"html\", \"tcl\",\n"
26649 " or \"json\". \"off\" means show the text as-is.\n"
26650 " \"on\" is an alias for \"sql\".\n"
26651 " --reset Changes all mode settings back to their default.\n"
26652 " --rowsep STRING Use STRING as the row separator\n"
26653 " --sw|--screenwidth N Declare the screen width of the output device\n"
26654 " to be N characters. An attempt may be made to\n"
@@ -26659,10 +26949,11 @@
26659 " --tag NAME Save mode to the left as NAME.\n"
26660 " --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON.\n"
26661 " --title ARG Whether or not to show column headers, and if so\n"
26662 " how to encode them. ARG can be \"off\", \"on\",\n"
26663 " \"sql\", \"csv\", \"html\", \"tcl\", or \"json\".\n"
 
26664 " -v|--verbose Verbose output\n"
26665 " --widths LIST Set the columns widths for columnar modes. The\n"
26666 " argument is a list of integers, one for each\n"
26667 " column. A \"0\" width means use a dynamic width\n"
26668 " based on the actual width of data. If there are\n"
@@ -26686,23 +26977,17 @@
26686 " --bom Prepend a byte-order mark to the output\n"
26687 " -e Accumulate output in a temporary text file then\n"
26688 " launch a text editor when the redirection ends.\n"
26689 " --error-prefix X Use X as the left-margin prefix for error messages.\n"
26690 " Set to an empty string to restore the default.\n"
26691 " --glob GLOB Raise an error if the memory buffer does not match\n"
26692 " the GLOB pattern.\n"
26693 " --keep Continue using the same \"memory\" buffer. Do not\n"
26694 " reset it or delete it. Useful in combination with\n"
26695 " --glob, --not-glob, and/or --verify.\n"
26696 " ---notglob GLOB Raise an error if the memory buffer does not match\n"
26697 " the GLOB pattern.\n"
26698 " --plain Use plain text rather than HTML tables with -w\n"
26699 " --show Write the memory buffer to the screen, for debugging.\n"
26700 " --verify ENDMARK Read subsequent lines of text until the first line\n"
26701 " that matches ENDMARK. Discard the ENDMARK. Compare\n"
26702 " the text against the accumulated output in memory and\n"
26703 " raise an error if there are any differences.\n"
26704 " -w Show the output in a web browser. Output is\n"
26705 " written into a temporary HTML file until the\n"
26706 " redirect ends, then the web browser is launched.\n"
26707 " Query results are shown as HTML tables, unless\n"
26708 " the --plain is used too.\n"
@@ -26726,10 +27011,39 @@
26726 " file in a web browser\n"
26727 " -x Show the output in a spreadsheet. Output is\n"
26728 " written to a temp file as CSV then the spreadsheet\n"
26729 " is launched when\n"
26730 },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26731 };
26732
26733 /*
26734 ** Return a pointer to usage text for zCmd, or NULL if none exists.
26735 */
@@ -26949,10 +27263,56 @@
26949 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
26950 }
26951 return 1;
26952 }
26953 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26954
26955 /*
26956 ** Try to deduce the type of file for zName based on its content. Return
26957 ** one of the SHELL_OPEN_* constants.
26958 **
@@ -26962,24 +27322,16 @@
26962 ** the type cannot be determined from content.
26963 */
26964 int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
26965 FILE *f;
26966 size_t n;
26967 sqlite3 *db = 0;
26968 sqlite3_stmt *pStmt = 0;
26969 int rc = SHELL_OPEN_UNSPEC;
26970 char zBuf[100];
26971 if( access(zName,0)!=0 ) goto database_type_by_name;
26972 if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK
26973 && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
26974 ==SQLITE_OK
26975 && sqlite3_step(pStmt)==SQLITE_ROW
26976 ){
26977 rc = SHELL_OPEN_NORMAL;
26978 }
26979 sqlite3_finalize(pStmt);
26980 sqlite3_close(db);
26981 if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
26982 f = sqlite3_fopen(zName, "rb");
26983 if( f==0 ) goto database_type_by_name;
26984 n = fread(zBuf, 16, 1, f);
26985 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
@@ -27009,10 +27361,37 @@
27009 }else{
27010 rc = SHELL_OPEN_NORMAL;
27011 }
27012 return rc;
27013 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27014
27015 #ifndef SQLITE_OMIT_DESERIALIZE
27016 /*
27017 ** Reconstruct an in-memory database using the output from the "dbtotxt"
27018 ** program. Read content from the file in p->aAuxDb[].zDbFilename.
@@ -27655,11 +28034,13 @@
27655 typedef struct ImportCtx ImportCtx;
27656 struct ImportCtx {
27657 const char *zFile; /* Name of the input file */
27658 FILE *in; /* Read the CSV text from this input stream */
27659 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
 
27660 char *z; /* Accumulated text for a field */
 
27661 i64 n; /* Number of bytes in z */
27662 i64 nAlloc; /* Space allocated for z[] */
27663 int nLine; /* Current line number */
27664 int nRow; /* Number of rows imported */
27665 int nErr; /* Number of errors encountered */
@@ -27675,13 +28056,32 @@
27675 p->xCloser(p->in);
27676 p->in = 0;
27677 }
27678 sqlite3_free(p->z);
27679 p->z = 0;
 
 
 
 
27680 }
27681
27682 /* Append a single byte to z[] */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27683 static void import_append_char(ImportCtx *p, int c){
27684 if( p->n+1>=p->nAlloc ){
27685 p->nAlloc += p->nAlloc + 100;
27686 p->z = sqlite3_realloc64(p->z, p->nAlloc);
27687 shell_check_oom(p->z);
@@ -27693,12 +28093,12 @@
27693 ** with the option of having a separator other than ",".
27694 **
27695 ** + Input comes from p->in.
27696 ** + Store results in p->z of length p->n. Space to hold p->z comes
27697 ** from sqlite3_malloc64().
27698 ** + Use p->cSep as the column separator. The default is ",".
27699 ** + Use p->rSep as the row separator. The default is "\n".
27700 ** + Keep track of the line number in p->nLine.
27701 ** + Store the character that terminates the field in p->cTerm. Store
27702 ** EOF on end-of-file.
27703 ** + Report syntax errors on stderr
27704 */
@@ -27705,11 +28105,11 @@
27705 static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
27706 int c;
27707 int cSep = (u8)p->cColSep;
27708 int rSep = (u8)p->cRowSep;
27709 p->n = 0;
27710 c = fgetc(p->in);
27711 if( c==EOF || seenInterrupt ){
27712 p->cTerm = EOF;
27713 return 0;
27714 }
27715 if( c=='"' ){
@@ -27716,11 +28116,11 @@
27716 int pc, ppc;
27717 int startLine = p->nLine;
27718 int cQuote = c;
27719 pc = ppc = 0;
27720 while( 1 ){
27721 c = fgetc(p->in);
27722 if( c==rSep ) p->nLine++;
27723 if( c==cQuote ){
27724 if( pc==cQuote ){
27725 pc = 0;
27726 continue;
@@ -27752,24 +28152,24 @@
27752 }else{
27753 /* If this is the first field being parsed and it begins with the
27754 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
27755 if( (c&0xff)==0xef && p->bNotFirst==0 ){
27756 import_append_char(p, c);
27757 c = fgetc(p->in);
27758 if( (c&0xff)==0xbb ){
27759 import_append_char(p, c);
27760 c = fgetc(p->in);
27761 if( (c&0xff)==0xbf ){
27762 p->bNotFirst = 1;
27763 p->n = 0;
27764 return csv_read_one_field(p);
27765 }
27766 }
27767 }
27768 while( c!=EOF && c!=cSep && c!=rSep ){
27769 import_append_char(p, c);
27770 c = fgetc(p->in);
27771 }
27772 if( c==rSep ){
27773 p->nLine++;
27774 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
27775 }
@@ -27783,12 +28183,12 @@
27783 /* Read a single field of ASCII delimited text.
27784 **
27785 ** + Input comes from p->in.
27786 ** + Store results in p->z of length p->n. Space to hold p->z comes
27787 ** from sqlite3_malloc64().
27788 ** + Use p->cSep as the column separator. The default is "\x1F".
27789 ** + Use p->rSep as the row separator. The default is "\x1E".
27790 ** + Keep track of the row number in p->nLine.
27791 ** + Store the character that terminates the field in p->cTerm. Store
27792 ** EOF on end-of-file.
27793 ** + Report syntax errors on stderr
27794 */
@@ -27795,18 +28195,18 @@
27795 static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
27796 int c;
27797 int cSep = (u8)p->cColSep;
27798 int rSep = (u8)p->cRowSep;
27799 p->n = 0;
27800 c = fgetc(p->in);
27801 if( c==EOF || seenInterrupt ){
27802 p->cTerm = EOF;
27803 return 0;
27804 }
27805 while( c!=EOF && c!=cSep && c!=rSep ){
27806 import_append_char(p, c);
27807 c = fgetc(p->in);
27808 }
27809 if( c==rSep ){
27810 p->nLine++;
27811 }
27812 p->cTerm = c;
@@ -29721,11 +30121,13 @@
29721
29722 p = sqlite3_recover_init_sql(
29723 pState->db, "main", recoverSqlCb, (void*)pState
29724 );
29725
29726 sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */
 
 
29727 sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
29728 sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
29729 sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
29730
29731 cli_printf(pState->out, ".dbconfig defensive off\n");
@@ -30105,19 +30507,31 @@
30105 ** USAGE: .import [OPTIONS] FILE TABLE
30106 **
30107 ** Import CSV or similar text from FILE into TABLE. If TABLE does
30108 ** not exist, it is created using the first row of FILE as the column
30109 ** names. If FILE begins with "|" then it is a command that is run
30110 ** and the output from the command is used as the input data.
 
 
 
 
 
 
30111 **
30112 ** FILE is assumed to be in a CSV format, unless the current mode
30113 ** is "ascii" or "tabs" or unless one of the options below specify
30114 ** an alternative.
 
 
30115 **
30116 ** Options:
30117 ** --ascii Use \037 and \036 as column and row separators on input
 
 
 
30118 ** --csv Input is standard RFC-4180 CSV.
 
30119 ** --schema S When creating TABLE, put it in schema S
30120 ** --skip N Ignore the first N rows of input
30121 ** -v Verbose mode
30122 */
30123 static int dotCmdImport(ShellState *p){
@@ -30129,17 +30543,16 @@
30129 sqlite3_stmt *pStmt = NULL; /* A statement */
30130 int nCol; /* Number of columns in the table */
30131 i64 nByte; /* Number of bytes in an SQL string */
30132 int i, j; /* Loop counters */
30133 int needCommit; /* True to COMMIT or ROLLBACK at end */
30134 int nSep; /* Number of bytes in spec.zColumnSep */
30135 char *zSql = 0; /* An SQL statement */
30136 ImportCtx sCtx; /* Reader context */
30137 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
30138 int eVerbose = 0; /* Larger for more console output */
30139 i64 nSkip = 0; /* Initial lines to skip */
30140 int useOutputMode = 1; /* Use output mode to determine separators */
30141 char *zCreate = 0; /* CREATE TABLE statement text */
30142 int rc; /* Result code */
30143
30144 failIfSafeMode(p, "cannot run .import in safe mode");
30145 memset(&sCtx, 0, sizeof(sCtx));
@@ -30165,70 +30578,67 @@
30165 }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
30166 zSchema = azArg[++i];
30167 }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
30168 nSkip = integerValue(azArg[++i]);
30169 }else if( cli_strcmp(z,"-ascii")==0 ){
30170 sCtx.cColSep = SEP_Unit[0];
30171 sCtx.cRowSep = SEP_Record[0];
30172 xRead = ascii_read_one_field;
30173 useOutputMode = 0;
30174 }else if( cli_strcmp(z,"-csv")==0 ){
30175 sCtx.cColSep = ',';
30176 sCtx.cRowSep = '\n';
30177 xRead = csv_read_one_field;
30178 useOutputMode = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
30179 }else{
30180 dotCmdError(p, i, "unknown option", 0);
30181 return 1;
30182 }
30183 }
30184 if( zTable==0 ){
30185 cli_printf(p->out, "ERROR: missing %s argument\n",
30186 zFile==0 ? "FILE" : "TABLE");
30187 return 1;
30188 }
30189 seenInterrupt = 0;
30190 open_db(p, 0);
30191 if( useOutputMode ){
30192 /* If neither the --csv or --ascii options are specified, then set
30193 ** the column and row separator characters from the output mode. */
30194 if( p->mode.spec.zColumnSep==0 ){
30195 modeSetStr(&p->mode.spec.zColumnSep, ",");
30196 nSep = 1;
30197 }else if( (nSep = strlen30(p->mode.spec.zColumnSep))==0 ){
30198 eputz("Error: non-null column separator required for import\n");
30199 return 1;
30200 }
30201 if( nSep>1 ){
30202 eputz("Error: multi-character column separators not allowed"
30203 " for import\n");
30204 return 1;
30205 }
30206 if( p->mode.spec.zRowSep==0 ){
30207 modeSetStr(&p->mode.spec.zRowSep, "\n");
30208 nSep = 1;
30209 }else if( (nSep = strlen30(p->mode.spec.zRowSep))==0 ){
30210 eputz("Error: non-null row separator required for import\n");
30211 return 1;
30212 }
30213 if( nSep==2 && p->mode.eMode==MODE_Csv
30214 && cli_strcmp(p->mode.spec.zRowSep,SEP_CrLf)==0
30215 ){
30216 /* When importing CSV (only), if the row separator is set to the
30217 ** default output row separator, change it to the default input
30218 ** row separator. This avoids having to maintain different input
30219 ** and output row separators. */
30220 modeSetStr(&p->mode.spec.zRowSep, SEP_Row);
30221 nSep = strlen30(p->mode.spec.zRowSep);
30222 }
30223 if( nSep>1 ){
30224 eputz("Error: multi-character row separators not allowed"
30225 " for import\n");
30226 return 1;
30227 }
30228 sCtx.cColSep = (u8)p->mode.spec.zColumnSep[0];
30229 sCtx.cRowSep = (u8)p->mode.spec.zRowSep[0];
30230 }
30231 sCtx.zFile = zFile;
30232 sCtx.nLine = 1;
30233 if( sCtx.zFile[0]=='|' ){
30234 #ifdef SQLITE_OMIT_POPEN
@@ -30237,19 +30647,58 @@
30237 #else
30238 sCtx.in = sqlite3_popen(sCtx.zFile+1, "r");
30239 sCtx.zFile = "<pipe>";
30240 sCtx.xCloser = pclose;
30241 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30242 }else{
30243 sCtx.in = sqlite3_fopen(sCtx.zFile, "rb");
30244 sCtx.xCloser = fclose;
30245 }
30246 if( sCtx.in==0 ){
30247 cli_printf(stderr,"Error: cannot open \"%s\"\n", zFile);
 
30248 return 1;
30249 }
30250 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
30251 char zSep[2];
30252 zSep[1] = 0;
30253 zSep[0] = sCtx.cColSep;
30254 cli_puts("Column separator ", p->out);
30255 output_c_string(p->out, zSep);
@@ -30402,10 +30851,14 @@
30402 if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){
30403 z = "";
30404 }
30405 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
30406 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
 
 
 
 
30407 cli_printf(stderr,"%s:%d: expected %d columns but found %d"
30408 " - filling the rest with NULL\n",
30409 sCtx.zFile, startLine, nCol, i+1);
30410 i += 2;
30411 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
@@ -30425,10 +30878,11 @@
30425 rc = sqlite3_reset(pStmt);
30426 if( rc!=SQLITE_OK ){
30427 cli_printf(stderr,"%s:%d: INSERT failed: %s\n",
30428 sCtx.zFile, startLine, sqlite3_errmsg(p->db));
30429 sCtx.nErr++;
 
30430 }else{
30431 sCtx.nRow++;
30432 }
30433 }
30434 }while( sCtx.cTerm!=EOF );
@@ -30437,13 +30891,13 @@
30437 sqlite3_finalize(pStmt);
30438 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
30439 if( eVerbose>0 ){
30440 cli_printf(p->out,
30441 "Added %d rows with %d errors using %d lines of input\n",
30442 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
30443 }
30444 return 0;
30445 }
30446
30447
30448 /*
30449 ** This function computes what to show the user about the configured
@@ -30508,10 +30962,11 @@
30508 ** meaning "left", "centered", and "right", with
30509 ** one letter per column starting from the left.
30510 ** Unspecified alignment defaults to 'L'.
30511 ** --blob-quote ARG ARG can be "auto", "text", "sql", "hex", "tcl",
30512 ** "json", or "size". Default is "auto".
 
30513 ** --charlimit N Set the maximum number of output characters to
30514 ** show for any single SQL value to N. Longer values
30515 ** truncated. Zero means "no limit".
30516 ** --colsep STRING Use STRING as the column separator
30517 ** --escape ESC Enable/disable escaping of control characters
@@ -30519,19 +30974,22 @@
30519 ** or "symbol".
30520 ** --linelimit N Set the maximum number of output lines to show for
30521 ** any single SQL value to N. Longer values are
30522 ** truncated. Zero means "no limit". Only works
30523 ** in "line" mode and in columnar modes.
30524 ** --limits L,C Shorthand for "--linelimit L --charlimit C".
30525 ** Or "off" to mean "0,0". Or "on" for "5,300".
 
 
 
30526 ** --list List available modes
30527 ** --null STRING Render SQL NULL values as the given string
30528 ** --once Setting changes to the right are reverted after
30529 ** the next SQL command.
30530 ** --quote ARG Enable/disable quoting of text. ARG can be
30531 ** "off", "on", "sql", "csv", "html", "tcl",
30532 ** or "json". "off" means show the text as-is.
30533 ** "on" is an alias for "sql".
30534 ** --reset Changes all mode settings back to their default.
30535 ** --rowsep STRING Use STRING as the row separator
30536 ** --sw|--screenwidth N Declare the screen width of the output device
30537 ** to be N characters. An attempt may be made to
@@ -30542,10 +31000,11 @@
30542 ** --tag NAME Save mode to the left as NAME.
30543 ** --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON.
30544 ** --title ARG Whether or not to show column headers, and if so
30545 ** how to encode them. ARG can be "off", "on",
30546 ** "sql", "csv", "html", "tcl", or "json".
 
30547 ** -v|--verbose Verbose output
30548 ** --widths LIST Set the columns widths for columnar modes. The
30549 ** argument is a list of integers, one for each
30550 ** column. A "0" width means use a dynamic width
30551 ** based on the actual width of data. If there are
@@ -30626,21 +31085,31 @@
30626 ** Must match QRF_BLOB_xxxx values. See also tag-20251124a */
30627 if( k>=0 ){
30628 p->mode.spec.eBlob = k & 0xff;
30629 }
30630 chng = 1;
30631 }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","")) ){
 
 
 
 
 
 
 
 
 
 
30632 int w; /* 0 1 */
30633 if( i+1>=nArg ){
30634 dotCmdError(p, i, "missing argument", 0);
30635 return 1;
30636 }
30637 w = integerValue(azArg[++i]);
30638 if( k==0 ){
30639 p->mode.spec.nCharLimit = w;
30640 }else{
30641 p->mode.spec.nLineLimit = w;
30642 }
30643 chng = 1;
30644 }else if( 0<=(k=pickStr(z,0,"-tablename","-rowsep","-colsep","-null","")) ){
30645 /* 0 1 2 3 */
30646 if( i+1>=nArg ){
@@ -30675,25 +31144,28 @@
30675 dotCmdError(p, i-1, "missing argument", 0);
30676 return 1;
30677 }
30678 k = pickStr(azArg[i],0,"on","off","");
30679 if( k==0 ){
30680 p->mode.spec.nLineLimit = 5;
30681 p->mode.spec.nCharLimit = 300;
 
30682 }else if( k==1 ){
30683 p->mode.spec.nLineLimit = 0;
30684 p->mode.spec.nCharLimit = 0;
 
30685 }else{
30686 int L, C;
30687 int nNum = sscanf(azArg[i], "%d,%d", &L, &C);
30688 if( nNum!=2 || L<0 || C<0 ){
30689 dotCmdError(p, i, "bad argument", "Should be \"L,C\" where L and C"
30690 " are unsigned integers");
30691 return 1;
30692 }
30693 p->mode.spec.nLineLimit = L;
30694 p->mode.spec.nCharLimit = C;
 
30695 }
30696 chng = 1;
30697 }else if( optionMatch(z,"list") ){
30698 int ii;
30699 cli_puts("available modes:", p->out);
@@ -30726,13 +31198,14 @@
30726 ** how to set quoting. */
30727 i++;
30728 if( (k = pickStr(azArg[i],0,"no","yes","0","1",""))>=0 ){
30729 k &= 1; /* 0 for "off". 1 for "on". */
30730 }else{
30731 char *zErr = 0; /* 0 1 2 3 4 5 6 */
30732 k = pickStr(azArg[i],&zErr,"off","on","sql","csv","html","tcl","json",
30733 "");
 
30734 if( k<0 ){
30735 dotCmdError(p, i, "unknown", "%z", zErr);
30736 return 1;
30737 }
30738 }
@@ -30757,10 +31230,13 @@
30757 p->mode.spec.eText = QRF_TEXT_Tcl;
30758 break;
30759 case 6: /* json */
30760 p->mode.spec.eText = QRF_TEXT_Json;
30761 break;
 
 
 
30762 default: /* off */
30763 p->mode.spec.eText = QRF_TEXT_Plain;
30764 break;
30765 }
30766 chng = 1;
@@ -30832,10 +31308,11 @@
30832 if( k<0 ){
30833 dotCmdError(p, i, "bad --titles value","%z", zErr);
30834 return 1;
30835 }
30836 p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No;
 
30837 p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr;
30838 chng = 1;
30839 }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){
30840 int nWidth = 0;
30841 short int *aWidth;
@@ -30847,16 +31324,16 @@
30847 zW = azArg[++i];
30848 /* Every width value takes at least 2 bytes in the input string to
30849 ** specify, so strlen(zW) bytes should be plenty of space to hold the
30850 ** result. */
30851 aWidth = malloc( strlen(zW) );
30852 while( isspace(zW[0]) ) zW++;
30853 while( zW[0] ){
30854 int w = 0;
30855 int nDigit = 0;
30856 k = zW[0]=='-' && isdigit(zW[1]);
30857 while( isdigit(zW[k]) ){
30858 w = w*10 + zW[k] - '0';
30859 if( w>QRF_MAX_WIDTH ){
30860 dotCmdError(p,i+1,"width too big",
30861 "Maximum column width is %d", QRF_MAX_WIDTH);
30862 free(aWidth);
@@ -30873,11 +31350,11 @@
30873 }
30874 if( zW[0]=='-' ) w = -w;
30875 aWidth[nWidth++] = w;
30876 zW += k;
30877 if( zW[0]==',' ) zW++;
30878 while( isspace(zW[0]) ) zW++;
30879 }
30880 free(p->mode.spec.aWidth);
30881 p->mode.spec.aWidth = aWidth;
30882 p->mode.spec.nWidth = nWidth;
30883 chng = 1;
@@ -30928,39 +31405,52 @@
30928 unsigned char a = p->mode.spec.aAlign[ii];
30929 sqlite3_str_appendchar(pDesc, 1, "LLCR"[a&3]);
30930 }
30931 sqlite3_str_append(pDesc, "\"", 1);
30932 }
 
 
 
 
 
 
30933 if( bAll || p->mode.spec.eBlob!=QRF_BLOB_Auto ){
30934 const char *azBQuote[] =
30935 { "auto", "text", "sql", "hex", "tcl", "json", "size" };
30936 /* 0 1 2 3 4 5 6
30937 ** Must match QRF_BLOB_xxxx values. See all instances of tag-20251124a */
30938 u8 e = p->mode.spec.eBlob;
30939 sqlite3_str_appendf(pDesc, " --blob-quote %s", azBQuote[e]);
30940 }
30941 if( !bAll && p->mode.spec.nLineLimit==0 && p->mode.spec.nCharLimit>0 ){
30942 sqlite3_str_appendf(pDesc, " --charlimit %d",p->mode.spec.nCharLimit);
30943 }
30944 zSetting = aModeStr[pI->eCSep];
30945 if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zColumnSep)!=0) ){
30946 sqlite3_str_appendf(pDesc, " --colsep ");
30947 append_c_string(pDesc, p->mode.spec.zColumnSep);
30948 }
30949 if( bAll || p->mode.spec.eEsc!=QRF_Auto ){
30950 sqlite3_str_appendf(pDesc, " --escape %s",qrfEscNames[p->mode.spec.eEsc]);
30951 }
30952 if( bAll || (p->mode.spec.nLineLimit>0 && p->mode.spec.nCharLimit>0) ){
30953 if( p->mode.spec.nLineLimit==0 && p->mode.spec.nCharLimit==0 ){
 
 
 
 
 
 
 
30954 sqlite3_str_appendf(pDesc, " --limits off");
 
 
 
 
 
30955 }else{
30956 sqlite3_str_appendf(pDesc, " --limits %d,%d",
30957 p->mode.spec.nLineLimit, p->mode.spec.nCharLimit);
 
30958 }
30959 }else
30960 if( p->mode.spec.nCharLimit==0 && p->mode.spec.nLineLimit>0 && pI->eCx>0 ){
30961 sqlite3_str_appendf(pDesc, " --linelimit %d",p->mode.spec.nLineLimit);
30962 }
30963 zSetting = aModeStr[pI->eNull];
30964 if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zNull)!=0) ){
30965 sqlite3_str_appendf(pDesc, " --null ");
30966 append_c_string(pDesc, p->mode.spec.zNull);
@@ -30977,13 +31467,13 @@
30977 }
30978 if( bAll
30979 || (pI->eCx && (p->mode.spec.nScreenWidth>0 || p->mode.bAutoScreenWidth))
30980 ){
30981 if( p->mode.bAutoScreenWidth ){
30982 sqlite3_str_appendall(pDesc, " --screenwidth auto");
30983 }else{
30984 sqlite3_str_appendf(pDesc," --screenwidth %d",
30985 p->mode.spec.nScreenWidth);
30986 }
30987 }
30988 if( bAll || p->mode.eMode==MODE_Insert ){
30989 sqlite3_str_appendf(pDesc," --tablename ");
@@ -31023,11 +31513,11 @@
31023 sqlite3_str_appendf(pDesc, " --wrap %d", p->mode.spec.nWrap);
31024 }
31025 if( !bAll ) sqlite3_str_append(pDesc, " --ww", 5);
31026 }
31027 zDesc = sqlite3_str_finish(pDesc);
31028 cli_printf(p->out, "current output mode: %s\n", zDesc);
31029 fflush(p->out);
31030 sqlite3_free(zDesc);
31031 }
31032 return 0;
31033 }
@@ -31047,23 +31537,17 @@
31047 ** --bom Prepend a byte-order mark to the output
31048 ** -e Accumulate output in a temporary text file then
31049 ** launch a text editor when the redirection ends.
31050 ** --error-prefix X Use X as the left-margin prefix for error messages.
31051 ** Set to an empty string to restore the default.
31052 ** --glob GLOB Raise an error if the memory buffer does not match
31053 ** the GLOB pattern.
31054 ** --keep Continue using the same "memory" buffer. Do not
31055 ** reset it or delete it. Useful in combination with
31056 ** --glob, --not-glob, and/or --verify.
31057 ** ---notglob GLOB Raise an error if the memory buffer does not match
31058 ** the GLOB pattern.
31059 ** --plain Use plain text rather than HTML tables with -w
31060 ** --show Write the memory buffer to the screen, for debugging.
31061 ** --verify ENDMARK Read subsequent lines of text until the first line
31062 ** that matches ENDMARK. Discard the ENDMARK. Compare
31063 ** the text against the accumulated output in memory and
31064 ** raise an error if there are any differences.
31065 ** -w Show the output in a web browser. Output is
31066 ** written into a temporary HTML file until the
31067 ** redirect ends, then the web browser is launched.
31068 ** Query results are shown as HTML tables, unless
31069 ** the --plain is used too.
@@ -31101,13 +31585,11 @@
31101 char *zFile = 0; /* The FILE argument */
31102 int i; /* Loop counter */
31103 int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */
31104 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */
31105 int bPlain = 0; /* --plain option */
31106 int bKeep = 0; /* --keep option */
31107 char *zCheck = 0; /* Argument to --glob, --notglob, --verify */
31108 int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --verify */
31109 static const char *zBomUtf8 = "\357\273\277";
31110 const char *zBom = 0;
31111 char c = azArg[0][0];
31112 int n = strlen30(azArg[0]);
31113
@@ -31129,36 +31611,21 @@
31129 zBom = zBomUtf8;
31130 }else if( cli_strcmp(z,"-plain")==0 ){
31131 bPlain = 1;
31132 }else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
31133 && (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
31134 if( bKeep || eMode || eCheck ){
31135 dotCmdError(p, i, "incompatible with prior options",0);
31136 goto dotCmdOutput_error;
31137 }
31138 eMode = z[1];
31139 }else if( cli_strcmp(z,"-keep")==0 ){
31140 bKeep = 1;
31141 }else if( cli_strcmp(z,"-show")==0 ){
31142 if( cli_output_capture ){
31143 sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
31144 }
 
31145 bKeep = 1;
31146 }else if( cli_strcmp(z,"-glob")==0
31147 || cli_strcmp(z,"-notglob")==0
31148 || cli_strcmp(z,"-verify")==0
31149 ){
31150 if( eCheck || eMode ){
31151 dotCmdError(p, i, "incompatible with prior options",0);
31152 goto dotCmdOutput_error;
31153 }
31154 if( i+1>=nArg ){
31155 dotCmdError(p, i, "missing argument", 0);
31156 goto dotCmdOutput_error;
31157 }
31158 zCheck = azArg[++i];
31159 eCheck = z[1]=='g' ? 1 : z[1]=='n' ? 2 : 3;
31160 }else if( optionMatch(z,"error-prefix") ){
31161 if( i+1>=nArg ){
31162 dotCmdError(p, i, "missing argument", 0);
31163 return 1;
31164 }
@@ -31169,11 +31636,11 @@
31169 dotCmdError(p, i, "unknown option", 0);
31170 sqlite3_free(zFile);
31171 return 1;
31172 }
31173 }else if( zFile==0 && eMode==0 ){
31174 if( bKeep || eCheck ){
31175 dotCmdError(p, i, "incompatible with prior options",0);
31176 goto dotCmdOutput_error;
31177 }
31178 if( cli_strcmp(z, "memory")==0 && bOnce ){
31179 dotCmdError(p, 0, "cannot redirect to \"memory\"", 0);
@@ -31205,53 +31672,10 @@
31205 if( bOnce ){
31206 p->nPopOutput = 2;
31207 }else{
31208 p->nPopOutput = 0;
31209 }
31210 if( eCheck ){
31211 char *zTest;
31212 if( cli_output_capture ){
31213 zTest = sqlite3_str_value(cli_output_capture);
31214 }else{
31215 zTest = "";
31216 }
31217 p->nTestRun++;
31218 if( eCheck==3 ){
31219 int nCheck = strlen30(zCheck);
31220 sqlite3_str *pPattern = sqlite3_str_new(p->db);
31221 char *zPattern;
31222 sqlite3_int64 iStart = p->lineno;
31223 char zLine[2000];
31224 while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
31225 if( strchr(zLine,'\n') ) p->lineno++;
31226 if( cli_strncmp(zCheck,zLine,nCheck)==0 ) break;
31227 sqlite3_str_appendall(pPattern, zLine);
31228 }
31229 zPattern = sqlite3_str_finish(pPattern);
31230 if( cli_strcmp(zPattern,zTest)!=0 ){
31231 sqlite3_fprintf(stderr,
31232 "%s:%lld: --verify does matches prior output\n",
31233 p->zInFile, iStart);
31234 p->nTestErr++;
31235 }
31236 sqlite3_free(zPattern);
31237 }else{
31238 char *zGlob = sqlite3_mprintf("*%s*", zCheck);
31239 if( eCheck==1 && sqlite3_strglob(zGlob, zTest)!=0 ){
31240 sqlite3_fprintf(stderr,
31241 "%s:%lld: --glob \"%s\" does not match prior output\n",
31242 p->zInFile, p->lineno, zCheck);
31243 p->nTestErr++;
31244 }else if( eCheck==2 && sqlite3_strglob(zGlob, zTest)==0 ){
31245 sqlite3_fprintf(stderr,
31246 "%s:%lld: --notglob \"%s\" matches prior output\n",
31247 p->zInFile, p->lineno, zCheck);
31248 p->nTestErr++;
31249 }
31250 sqlite3_free(zGlob);
31251 }
31252 }
31253 if( !bKeep ) output_reset(p);
31254 #ifndef SQLITE_NOHAVE_SYSTEM
31255 if( eMode=='e' || eMode=='x' || eMode=='w' ){
31256 p->doXdgOpen = 1;
31257 modePush(p);
@@ -31328,10 +31752,199 @@
31328
31329 dotCmdOutput_error:
31330 sqlite3_free(zFile);
31331 return 1;
31332 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31333
31334 /*
31335 ** Enlarge the space allocated in p->dot so that it can hold more
31336 ** than nArg parsed command-line arguments.
31337 */
@@ -31360,11 +31973,11 @@
31360 free(p->dot.zCopy);
31361 z = p->dot.zCopy = strdup(zLine);
31362 shell_check_oom(z);
31363 szLine = strlen(z);
31364 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31365 if( szLine>0 && z[szLine-1]==';' && p->iCompat>=20251115 ){
31366 szLine--;
31367 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31368 }
31369 z[szLine] = 0;
31370 parseDotRealloc(p, 2);
@@ -31580,35 +32193,17 @@
31580 eputz("Usage: .changes on|off\n");
31581 rc = 1;
31582 }
31583 }else
31584
31585 #ifndef SQLITE_SHELL_FIDDLE
31586 /* Cancel output redirection, if it is currently set (by .testcase)
31587 ** Then read the content of the testcase-out.txt file and compare against
31588 ** azArg[1]. If there are differences, report an error and exit.
31589 */
31590 if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
31591 char *zRes = 0;
31592 output_reset(p);
31593 if( nArg!=2 ){
31594 eputz("Usage: .check GLOB-PATTERN\n");
31595 rc = 2;
31596 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
31597 rc = 2;
31598 }else if( testcase_glob(azArg[1],zRes)==0 ){
31599 cli_printf(stderr,
31600 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
31601 p->zTestcase, azArg[1], zRes);
31602 rc = 1;
31603 }else{
31604 cli_printf(p->out, "testcase-%s ok\n", p->zTestcase);
31605 p->nCheck++;
31606 }
31607 sqlite3_free(zRes);
31608 }else
31609 #endif /* !defined(SQLITE_SHELL_FIDDLE) */
31610
31611 #ifndef SQLITE_SHELL_FIDDLE
31612 if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
31613 failIfSafeMode(p, "cannot run .clone in safe mode");
31614 if( nArg==2 ){
@@ -32187,10 +32782,11 @@
32187 }else
32188
32189 if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
32190 if( nArg==2 ){
32191 p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No;
 
32192 p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr;
32193 }else{
32194 eputz("Usage: .headers on|off\n");
32195 rc = 1;
32196 }
@@ -32240,14 +32836,14 @@
32240 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
32241 goto meta_command_exit;
32242 }
32243 zSql = sqlite3_mprintf(
32244 "SELECT rootpage, 0 FROM sqlite_schema"
32245 " WHERE name='%q' AND type='index'"
32246 "UNION ALL "
32247 "SELECT rootpage, 1 FROM sqlite_schema"
32248 " WHERE name='%q' AND type='table'"
32249 " AND sql LIKE '%%without%%rowid%%'",
32250 azArg[1], azArg[1]
32251 );
32252 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
32253 sqlite3_free(zSql);
@@ -32401,13 +32997,14 @@
32401 goto meta_command_exit;
32402 }
32403 if( nArg==3 ){
32404 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
32405 (int)integerValue(azArg[2]));
 
 
 
32406 }
32407 cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
32408 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
32409 }
32410 }else
32411
32412 if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
32413 open_db(p, 0);
@@ -32493,21 +33090,23 @@
32493 int iName = 1; /* Index in azArg[] of the filename */
32494 int newFlag = 0; /* True to delete file before opening */
32495 int openMode = SHELL_OPEN_UNSPEC;
32496 int openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
32497
 
 
32498 /* Check for command-line arguments */
32499 for(iName=1; iName<nArg; iName++){
32500 const char *z = azArg[iName];
32501 #ifndef SQLITE_SHELL_FIDDLE
32502 if( optionMatch(z,"new") ){
32503 newFlag = 1;
32504 #ifdef SQLITE_HAVE_ZLIB
32505 }else if( optionMatch(z, "zip") ){
32506 openMode = SHELL_OPEN_ZIPFILE;
32507 #endif
32508 }else if( optionMatch(z, "append") ){
32509 openMode = SHELL_OPEN_APPENDVFS;
32510 }else if( optionMatch(z, "readonly") ){
32511 openFlags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
32512 openFlags |= SQLITE_OPEN_READONLY;
32513 }else if( optionMatch(z, "exclusive") ){
@@ -32950,21 +33549,22 @@
32950 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
32951 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
32952 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
32953 if( isSchema ){
32954 cli_printf(p->out,
32955 "CREATE TABLE %s (\n"
32956 " type text,\n"
32957 " name text,\n"
32958 " tbl_name text,\n"
32959 " rootpage integer,\n"
32960 " sql text\n"
32961 ");\n", zName);
 
 
32962 }
32963 }
32964 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
32965 -1, &pStmt, 0);
32966 if( rc ){
32967 shellDatabaseError(p->db);
32968 sqlite3_finalize(pStmt);
32969
32970 rc = 1;
@@ -32972,11 +33572,11 @@
32972 }
32973 pSql = sqlite3_str_new(p->db);
32974 sqlite3_str_appendf(pSql, "SELECT sql FROM", 0);
32975 iSchema = 0;
32976 while( sqlite3_step(pStmt)==SQLITE_ROW ){
32977 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
32978 char zScNum[30];
32979 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
32980 sqlite3_str_appendall(pSql, zDiv);
32981 zDiv = " UNION ALL ";
32982 if( sqlite3_stricmp(zDb, "main")==0 ){
@@ -32992,11 +33592,12 @@
32992 " AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname",
32993 ++iSchema, zDb);
32994 sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb);
32995 }
32996 sqlite3_finalize(pStmt);
32997 #ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
 
32998 if( zName ){
32999 sqlite3_str_appendall(pSql,
33000 " UNION ALL SELECT shell_module_schema(name),"
33001 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list");
33002 }
@@ -33016,11 +33617,11 @@
33016 }else{
33017 sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName);
33018 }
33019 }
33020 if( bNoSystemTabs ){
33021 sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCALE '_' AND ");
33022 }
33023 sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid");
33024 if( bDebug ){
33025 cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql));
33026 }else{
@@ -33734,25 +34335,15 @@
33734 sqlite3_str_free(pSql);
33735 modePop(p);
33736 if( rc ) return shellDatabaseError(p->db);
33737 }else
33738
33739 #ifndef SQLITE_SHELL_FIDDLE
33740 /* Begin redirecting output to the file "testcase-out.txt" */
33741 if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
33742 output_reset(p);
33743 p->out = output_file_open(p, "testcase-out.txt");
33744 if( p->out==0 ){
33745 eputz("Error: cannot open 'testcase-out.txt'\n");
33746 }
33747 if( nArg>=2 ){
33748 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
33749 }else{
33750 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
33751 }
33752 }else
33753 #endif /* !defined(SQLITE_SHELL_FIDDLE) */
33754
33755 #ifndef SQLITE_UNTESTABLE
33756 if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
33757 static const struct {
33758 const char *zCtrlName; /* Name of a test-control option */
@@ -35068,11 +35659,10 @@
35068 " -bail stop after hitting an error\n"
35069 " -batch force batch I/O\n"
35070 " -box set output mode to 'box'\n"
35071 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
35072 " -column set output mode to 'column'\n"
35073 " -compat YYYYMMDD set default options for date YYYYMMDD\n"
35074 " -csv set output mode to 'csv'\n"
35075 #if !defined(SQLITE_OMIT_DESERIALIZE)
35076 " -deserialize open the database using sqlite3_deserialize()\n"
35077 #endif
35078 " -echo print inputs before execution\n"
@@ -35152,15 +35742,10 @@
35152 /*
35153 ** Initialize the state information in data
35154 */
35155 static void main_init(ShellState *p) {
35156 memset(p, 0, sizeof(*p));
35157 #if defined(COMPATIBILITY_DATE)
35158 p->iCompat = COMPATIBILITY_DATE;
35159 #else
35160 p->iCompat = 20251116;
35161 #endif
35162 p->pAuxDb = &p->aAuxDb[0];
35163 p->shellFlgs = SHFLG_Lookaside;
35164 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p);
35165 #if !defined(SQLITE_SHELL_FIDDLE)
35166 verify_uninitialized();
@@ -35174,22 +35759,18 @@
35174 /*
35175 ** Output text to the console in a font that attracts extra attention.
35176 */
35177 #if defined(_WIN32) || defined(WIN32)
35178 static void printBold(const char *zText){
35179 #if !SQLITE_OS_WINRT
35180 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
35181 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
35182 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
35183 SetConsoleTextAttribute(out,
35184 FOREGROUND_RED|FOREGROUND_INTENSITY
35185 );
35186 #endif
35187 sputz(stdout, zText);
35188 #if !SQLITE_OS_WINRT
35189 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
35190 #endif
35191 }
35192 #else
35193 static void printBold(const char *zText){
35194 cli_printf(stdout, "\033[1m%s\033[0m", zText);
35195 }
@@ -35219,29 +35800,65 @@
35219 cli_puts(z, p->out);
35220 fflush(p->out);
35221 return 1;
35222 }
35223
35224 #ifndef SQLITE_SHELL_IS_UTF8
35225 # if (defined(_WIN32) || defined(WIN32)) \
35226 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
35227 # define SQLITE_SHELL_IS_UTF8 (0)
35228 # else
35229 # define SQLITE_SHELL_IS_UTF8 (1)
35230 # endif
35231 #endif
35232
35233 #ifdef SQLITE_SHELL_FIDDLE
35234 # define main fiddle_main
35235 #endif
35236
35237 #if SQLITE_SHELL_IS_UTF8
35238 int SQLITE_CDECL main(int argc, char **argv){
35239 #else
 
 
 
 
35240 int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
35241 char **argv;
35242 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35243 #ifdef SQLITE_DEBUG
35244 sqlite3_int64 mem_main_enter = 0;
35245 #endif
35246 char *zErrMsg = 0;
35247 #ifdef SQLITE_SHELL_FIDDLE
@@ -35259,14 +35876,10 @@
35259 int nOptsEnd = argc;
35260 int bEnableVfstrace = 0;
35261 char **azCmd = 0;
35262 int *aiCmd = 0;
35263 const char *zVfs = 0; /* Value of -vfs command-line option */
35264 #if !SQLITE_SHELL_IS_UTF8
35265 char **argvToFree = 0;
35266 int argcToFree = 0;
35267 #endif
35268 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
35269
35270 #ifdef SQLITE_SHELL_FIDDLE
35271 stdin_is_interactive = 0;
35272 stdout_is_console = 1;
@@ -35291,15 +35904,11 @@
35291 ){
35292 exit(1);
35293 }
35294 }else{
35295 #if defined(_WIN32) || defined(WIN32)
35296 #if SQLITE_OS_WINRT
35297 __debugbreak();
35298 #else
35299 DebugBreak();
35300 #endif
35301 #elif defined(SIGTRAP)
35302 raise(SIGTRAP);
35303 #endif
35304 }
35305 }
@@ -35321,36 +35930,10 @@
35321 exit(1);
35322 }
35323 #endif
35324 main_init(&data);
35325
35326 /* On Windows, we must translate command-line arguments into UTF-8.
35327 ** The SQLite memory allocator subsystem has to be enabled in order to
35328 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
35329 ** subsequent sqlite3_config() calls will work. So copy all results into
35330 ** memory that does not come from the SQLite memory allocator.
35331 */
35332 #if !SQLITE_SHELL_IS_UTF8
35333 sqlite3_initialize();
35334 argvToFree = malloc(sizeof(argv[0])*argc*2);
35335 shell_check_oom(argvToFree);
35336 argcToFree = argc;
35337 argv = argvToFree + argc;
35338 for(i=0; i<argc; i++){
35339 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
35340 i64 n;
35341 shell_check_oom(z);
35342 n = strlen(z);
35343 argv[i] = malloc( n+1 );
35344 shell_check_oom(argv[i]);
35345 memcpy(argv[i], z, n+1);
35346 argvToFree[i] = argv[i];
35347 sqlite3_free(z);
35348 }
35349 sqlite3_shutdown();
35350 #endif
35351
35352 assert( argc>=1 && argv && argv[0] );
35353 Argv0 = argv[0];
35354
35355 #ifdef SQLITE_SHELL_DBNAME_PROC
35356 {
@@ -35362,11 +35945,11 @@
35362 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
35363 warnInmemoryDb = 0;
35364 }
35365 #endif
35366
35367 /* Do an initial pass through the command-line argument to locate
35368 ** the name of the database file, the name of the initialization file,
35369 ** the size of the alternative malloc heap, options affecting commands
35370 ** or SQL run from the command line, and the first command to execute.
35371 */
35372 #ifndef SQLITE_SHELL_FIDDLE
@@ -35374,11 +35957,11 @@
35374 #endif
35375 for(i=1; i<argc; i++){
35376 char *z;
35377 z = argv[i];
35378 if( z[0]!='-' || i>nOptsEnd ){
35379 if( data.aAuxDb->zDbFilename==0 ){
35380 data.aAuxDb->zDbFilename = z;
35381 }else{
35382 /* Excess arguments are interpreted as SQL (or dot-commands) and
35383 ** mean that nothing is read from stdin */
35384 readStdin = 0;
@@ -35419,15 +36002,10 @@
35419 if( n<2 ){
35420 sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n");
35421 exit(1);
35422 }
35423 stdout_tty_width = n;
35424 }else if( cli_strcmp(z,"-compat")==0 ){
35425 data.iCompat = atoi(cmdline_option_value(argc, argv, ++i));
35426 modeFree(&data.mode);
35427 memset(&data.mode, 0, sizeof(data.mode));
35428 modeDefault(&data);
35429 }else if( cli_strcmp(z,"-utf8")==0 ){
35430 }else if( cli_strcmp(z,"-no-utf8")==0 ){
35431 }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
35432 int val = 0;
35433 sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val);
@@ -35547,10 +36125,20 @@
35547 }else if( cli_strcmp(z,"-safe")==0 ){
35548 /* no-op - catch this on the second pass */
35549 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
35550 /* skip over the argument */
35551 i++;
 
 
 
 
 
 
 
 
 
 
35552 }
35553 }
35554 #ifndef SQLITE_SHELL_FIDDLE
35555 if( !bEnableVfstrace ) verify_uninitialized();
35556 #endif
@@ -35573,11 +36161,30 @@
35573
35574 if( zVfs ){
35575 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
35576 if( pVfs ){
35577 sqlite3_vfs_register(pVfs, 1);
35578 }else{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35579 cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs);
35580 exit(1);
35581 }
35582 }
35583
@@ -35586,11 +36193,12 @@
35586 data.pAuxDb->zDbFilename = ":memory:";
35587 warnInmemoryDb = argc==1;
35588 #else
35589 cli_printf(stderr,
35590 "%s: Error: no database filename specified\n", Argv0);
35591 return 1;
 
35592 #endif
35593 }
35594 data.out = stdout;
35595 if( bEnableVfstrace ){
35596 vfstrace_register("trace",0,vfstraceOut, &data, 1);
@@ -35613,11 +36221,11 @@
35613 ** is given on the command line, look for a file named ~/.sqliterc and
35614 ** try to process it.
35615 */
35616 if( !noInit ) process_sqliterc(&data,zInitFile);
35617
35618 /* Make a second pass through the command-line argument and set
35619 ** options. This second pass is delayed until after the initialization
35620 ** file is processed so that the command-line arguments will override
35621 ** settings in the initialization file.
35622 */
35623 for(i=1; i<argc; i++){
@@ -35640,10 +36248,12 @@
35640 modeChange(&data, MODE_Json);
35641 }else if( cli_strcmp(z,"-markdown")==0 ){
35642 modeChange(&data, MODE_Markdown);
35643 }else if( cli_strcmp(z,"-table")==0 ){
35644 modeChange(&data, MODE_Table);
 
 
35645 }else if( cli_strcmp(z,"-box")==0 ){
35646 modeChange(&data, MODE_Box);
35647 }else if( cli_strcmp(z,"-csv")==0 ){
35648 modeChange(&data, MODE_Csv);
35649 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
@@ -35726,22 +36336,21 @@
35726 }else if( cli_strcmp(z,"-bail")==0 ){
35727 /* No-op. The bail_on_error flag should already be set. */
35728 }else if( cli_strcmp(z,"-version")==0 ){
35729 cli_printf(stdout, "%s %s (%d-bit)\n",
35730 sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
35731 return 0;
 
35732 }else if( cli_strcmp(z,"-interactive")==0 ){
35733 /* Need to check for interactive override here to so that it can
35734 ** affect console setup (for Windows only) and testing thereof.
35735 */
35736 stdin_is_interactive = 1;
35737 }else if( cli_strcmp(z,"-batch")==0 ){
35738 /* already handled */
35739 }else if( cli_strcmp(z,"-screenwidth")==0 ){
35740 i++;
35741 }else if( cli_strcmp(z,"-compat")==0 ){
35742 i++;
35743 }else if( cli_strcmp(z,"-utf8")==0 ){
35744 /* already handled */
35745 }else if( cli_strcmp(z,"-no-utf8")==0 ){
35746 /* already handled */
35747 }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
@@ -35783,29 +36392,33 @@
35783 ** we retain the goofy behavior for historical compatibility. */
35784 if( i==argc-1 ) break;
35785 z = cmdline_option_value(argc,argv,++i);
35786 if( z[0]=='.' ){
35787 rc = do_meta_command(z, &data);
35788 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
 
 
 
35789 }else{
35790 open_db(&data, 0);
35791 rc = shell_exec(&data, z, &zErrMsg);
35792 if( zErrMsg!=0 ){
35793 shellEmitError(zErrMsg);
35794 sqlite3_free(zErrMsg);
35795 if( bail_on_error ) return rc!=0 ? rc : 1;
35796 }else if( rc!=0 ){
35797 cli_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
35798 if( bail_on_error ) return rc;
35799 }
 
35800 }
35801 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
35802 }else if( cli_strncmp(z, "-A", 2)==0 ){
35803 if( nCmd>0 ){
35804 cli_printf(stderr,"Error: cannot mix regular SQL or dot-commands"
35805 " with \"%s\"\n", z);
35806 return 1;
 
35807 }
35808 open_db(&data, OPEN_DB_ZIPFILE);
35809 if( z[2] ){
35810 argv[i] = &z[2];
35811 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
@@ -35821,11 +36434,12 @@
35821 }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
35822 /* Acted upon in first pass. */
35823 }else{
35824 cli_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
35825 eputz("Use -help for a list of options.\n");
35826 return 1;
 
35827 }
35828 }
35829
35830 if( !readStdin ){
35831 /* Run all arguments that do not begin with '-' as if they were separate
@@ -35832,11 +36446,22 @@
35832 ** command-line inputs, except for the argToSkip argument which contains
35833 ** the database filename.
35834 */
35835 for(i=0; i<nCmd; i++){
35836 echo_group_input(&data, azCmd[i]);
35837 if( azCmd[i][0]=='.' ){
 
 
 
 
 
 
 
 
 
 
 
35838 char *zErrCtx = malloc( 64 );
35839 shell_check_oom(zErrCtx);
35840 sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]);
35841 data.zInFile = "<cmdline>";
35842 data.zErrPrefix = zErrCtx;
@@ -35947,14 +36572,10 @@
35947 }
35948 find_home_dir(1);
35949 output_reset(&data);
35950 data.doXdgOpen = 0;
35951 clearTempFile(&data);
35952 #if !SQLITE_SHELL_IS_UTF8
35953 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
35954 free(argvToFree);
35955 #endif
35956 modeFree(&data.mode);
35957 if( data.nSavedModes ){
35958 int ii;
35959 for(ii=0; ii<data.nSavedModes; ii++){
35960 modeFree(&data.aSavedModes[ii].mode);
35961
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -35,11 +35,11 @@
35 ** ext/recover/sqlite3recover.h
36 ** src/shell.c.in
37 **
38 ** To modify this program, get a copy of the canonical SQLite source tree,
39 ** edit the src/shell.c.in file and/or some of the other files that are
40 ** listed above, then rerun the command "make shell.c".
41 */
42 /************************* Begin src/shell.c.in ******************/
43 /*
44 ** 2001 September 15
45 **
@@ -49,11 +49,11 @@
49 ** May you do good and not evil.
50 ** May you find forgiveness for yourself and forgive others.
51 ** May you share freely, never taking more than you give.
52 **
53 *************************************************************************
54 ** This file contains code to implement the "sqlite3" command line
55 ** utility for accessing SQLite databases.
56 */
57 #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
58 /* This needs to come before any includes for MSVC compiler */
59 #define _CRT_SECURE_NO_WARNINGS
@@ -71,26 +71,22 @@
71 # define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
72 #ifdef SQLITE_CUSTOM_INCLUDE
73 # include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
74 #endif
75
 
 
 
 
 
 
 
 
76 /*
77 ** If SQLITE_SHELL_FIDDLE is defined then the shell is modified
78 ** somewhat for use as a WASM module in a web browser. This flag
79 ** should only be used when building the "fiddle" web application, as
80 ** the browser-mode build has much different user input requirements
81 ** and this build mode rewires the user input subsystem to account for
82 ** that.
83 */
84 #if defined(SQLITE_SHELL_FIDDLE)
85 # undef SQLITE_OMIT_LOAD_EXTENSION
86 # define SQLITE_OMIT_LOAD_EXTENSION 1
87 #endif
88
89 /*
90 ** Warning pragmas copied from msvc.h in the core.
91 */
92 #if defined(_MSC_VER)
@@ -218,13 +214,10 @@
214 # define deliberate_fall_through
215 # endif
216 #endif
217
218 #if defined(_WIN32) || defined(WIN32)
 
 
 
219 # include <io.h>
220 # include <fcntl.h>
221 # define isatty(h) _isatty(h)
222 # ifndef access
223 # define access(f,m) _access((f),(m))
@@ -235,11 +228,10 @@
228 # ifndef strdup
229 # define strdup _strdup
230 # endif
231 # undef pclose
232 # define pclose _pclose
 
233 #else
234 /* Make sure isatty() has a prototype. */
235 extern int isatty(int);
236
237 # if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI)
@@ -266,13 +258,10 @@
258 #define ToLower(X) (char)tolower((unsigned char)X)
259 #define IsAlnum(X) isalnum((unsigned char)X)
260 #define IsAlpha(X) isalpha((unsigned char)X)
261
262 #if defined(_WIN32) || defined(WIN32)
 
 
 
263 #undef WIN32_LEAN_AND_MEAN
264 #define WIN32_LEAN_AND_MEAN
265 #include <windows.h>
266
267 /* string conversion routines only needed on Win32 */
@@ -704,13 +693,15 @@
693 unsigned char bWordWrap; /* Try to wrap on word boundaries */
694 unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
695 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
696 unsigned char eTitleAlign; /* Alignment for column headers */
697 unsigned char bSplitColumn; /* Wrap single-column output into many columns */
698 unsigned char bBorder; /* Show outer border in Box and Table styles */
699 short int nWrap; /* Wrap columns wider than this */
700 short int nScreenWidth; /* Maximum overall table width */
701 short int nLineLimit; /* Maximum number of lines for any row */
702 short int nTitleLimit; /* Maximum number of characters in a title */
703 int nCharLimit; /* Maximum number of characters in a cell */
704 int nWidth; /* Number of entries in aWidth[] */
705 int nAlign; /* Number of entries in aAlignment[] */
706 short int *aWidth; /* Column widths */
707 unsigned char *aAlign; /* Column alignments */
@@ -775,10 +766,11 @@
766 #define QRF_TEXT_Sql 2 /* Quote as an SQL literal */
767 #define QRF_TEXT_Csv 3 /* CSV-style quoting */
768 #define QRF_TEXT_Html 4 /* HTML-style quoting */
769 #define QRF_TEXT_Tcl 5 /* C/Tcl quoting */
770 #define QRF_TEXT_Json 6 /* JSON quoting */
771 #define QRF_TEXT_Relaxed 7 /* Relaxed SQL quoting */
772
773 /*
774 ** Quoting styles for BLOBs
775 ** Allowed values for sqlite3_qrf_spec.eBlob
776 */
@@ -842,17 +834,25 @@
834 /*
835 ** Return an estimate of the width, in columns, for the single Unicode
836 ** character c. For normal characters, the answer is always 1. But the
837 ** estimate might be 0 or 2 for zero-width and double-width characters.
838 **
839 ** Different devices display unicode using different widths. So
840 ** it is impossible to know that true display width with 100% accuracy.
841 ** Inaccuracies in the width estimates might cause columns to be misaligned.
842 ** Unfortunately, there is nothing we can do about that.
843 */
844 int sqlite3_qrf_wcwidth(int c);
845
846 /*
847 ** Return an estimate of the number of display columns used by the
848 ** string in the argument. The width of individual characters is
849 ** determined as for sqlite3_qrf_wcwidth(). VT100 escape code sequences
850 ** are assigned a width of zero.
851 */
852 size_t sqlite3_qrf_wcswidth(const char*);
853
854
855 #ifdef __cplusplus
856 }
857 #endif
858 #endif /* !defined(SQLITE_QRF_H) */
@@ -915,11 +915,11 @@
915 int mxWidth; /* Screen width */
916 int mxHeight; /* nLineLimit */
917 union {
918 struct { /* Content for QRF_STYLE_Line */
919 int mxColWth; /* Maximum display width of any column */
920 char **azCol; /* Names of output columns (MODE_Line) */
921 } sLine;
922 qrfEQPGraph *pGraph; /* EQP graph (Eqp, Stats, and StatsEst) */
923 struct { /* Content for QRF_STYLE_Explain */
924 int nIndent; /* Slots allocated for aiIndent */
925 int iIndent; /* Current slot */
@@ -961,10 +961,19 @@
961 #define qrfSpace(x) ((qrfCType[(unsigned char)x]&1)!=0)
962 #define qrfDigit(x) ((qrfCType[(unsigned char)x]&2)!=0)
963 #define qrfAlpha(x) ((qrfCType[(unsigned char)x]&4)!=0)
964 #define qrfAlnum(x) ((qrfCType[(unsigned char)x]&6)!=0)
965
966 #ifndef deliberate_fall_through
967 /* Quiet some compilers about some of our intentional code. */
968 # if defined(GCC_VERSION) && GCC_VERSION>=7000000
969 # define deliberate_fall_through __attribute__((fallthrough));
970 # else
971 # define deliberate_fall_through
972 # endif
973 #endif
974
975 /*
976 ** Set an error code and error message.
977 */
978 static void qrfError(
979 Qrf *p, /* Query result state */
@@ -990,10 +999,19 @@
999 */
1000 static void qrfOom(Qrf *p){
1001 qrfError(p, SQLITE_NOMEM, "out of memory");
1002 }
1003
1004 /*
1005 ** Transfer any error in pStr over into p.
1006 */
1007 static void qrfStrErr(Qrf *p, sqlite3_str *pStr){
1008 int rc = pStr ? sqlite3_str_errcode(pStr) : 0;
1009 if( rc ){
1010 qrfError(p, rc, sqlite3_errstr(rc));
1011 }
1012 }
1013
1014
1015 /*
1016 ** Add a new entry to the EXPLAIN QUERY PLAN data
1017 */
@@ -1212,11 +1230,13 @@
1230 sqlite3_str_reset(pLine);
1231 }else{
1232 qrfEqpAppend(p, iId, iPid, zo);
1233 }
1234 }
1235 qrfStrErr(p, pLine);
1236 sqlite3_free(sqlite3_str_finish(pLine));
1237 qrfStrErr(p, pStats);
1238 sqlite3_free(sqlite3_str_finish(pStats));
1239 #endif
1240 }
1241
1242
@@ -1287,11 +1307,11 @@
1307 {1, 0x00ece}, {0, 0x00f18}, {1, 0x00f1a}, {0, 0x00f35}, {1, 0x00f36},
1308 {0, 0x00f37}, {1, 0x00f38}, {0, 0x00f39}, {1, 0x00f3a}, {0, 0x00f71},
1309 {1, 0x00f7f}, {0, 0x00f80}, {1, 0x00f85}, {0, 0x00f86}, {1, 0x00f88},
1310 {0, 0x00f90}, {1, 0x00f98}, {0, 0x00f99}, {1, 0x00fbd}, {0, 0x00fc6},
1311 {1, 0x00fc7}, {0, 0x0102d}, {1, 0x01031}, {0, 0x01032}, {1, 0x01033},
1312 {0, 0x01036}, {1, 0x0103b}, {0, 0x01058},
1313 {1, 0x0105a}, {2, 0x01100}, {0, 0x01160}, {1, 0x01200}, {0, 0x0135f},
1314 {1, 0x01360}, {0, 0x01712}, {1, 0x01715}, {0, 0x01732}, {1, 0x01735},
1315 {0, 0x01752}, {1, 0x01754}, {0, 0x01772}, {1, 0x01774}, {0, 0x017b4},
1316 {1, 0x017b6}, {0, 0x017b7}, {1, 0x017be}, {0, 0x017c6}, {1, 0x017c7},
1317 {0, 0x017c9}, {1, 0x017d4}, {0, 0x017dd}, {1, 0x017de}, {0, 0x0180b},
@@ -1330,11 +1350,11 @@
1350 */
1351 int sqlite3_qrf_wcwidth(int c){
1352 int iFirst, iLast;
1353
1354 /* Fast path for common characters */
1355 if( c<0x300 ) return 1;
1356
1357 /* The general case */
1358 iFirst = 0;
1359 iLast = sizeof(aQrfUWidth)/sizeof(aQrfUWidth[0]) - 1;
1360 while( iFirst<iLast-1 ){
@@ -1396,17 +1416,24 @@
1416 return i+1;
1417 }
1418
1419 /*
1420 ** Return the length of a string in display characters.
1421 **
1422 ** Most characters of the input string count as 1, including
1423 ** multi-byte UTF8 characters. However, zero-width unicode
1424 ** characters and VT100 escape sequences count as zero, and
1425 ** double-width characters count as two.
1426 **
1427 ** The definition of "zero-width" and "double-width" characters
1428 ** is not precise. It depends on the output device, to some extent,
1429 ** and it varies according to the Unicode version. This routine
1430 ** makes the best guess that it can.
1431 */
1432 size_t sqlite3_qrf_wcswidth(const char *zIn){
1433 const unsigned char *z = (const unsigned char*)zIn;
1434 size_t n = 0;
1435 while( *z ){
1436 if( z[0]<' ' ){
1437 int k;
1438 if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
1439 z += k;
@@ -1436,15 +1463,18 @@
1463 ** Write the number of newlines into *pnNL. So, *pnNL will
1464 ** return 0 if everything fits on one line, or positive it
1465 ** it will need to be split.
1466 */
1467 static int qrfDisplayWidth(const char *zIn, sqlite3_int64 nByte, int *pnNL){
1468 const unsigned char *z;
1469 const unsigned char *zEnd;
1470 int mx = 0;
1471 int n = 0;
1472 int nNL = 0;
1473 if( zIn==0 ) zIn = "";
1474 z = (const unsigned char*)zIn;
1475 zEnd = &z[nByte];
1476 while( z<zEnd ){
1477 if( z[0]<' ' ){
1478 int k;
1479 if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
1480 z += k;
@@ -1551,10 +1581,51 @@
1581 zOut[j++] = '^';
1582 zOut[j++] = 0x40+c;
1583 }
1584 }
1585 }
1586
1587 /*
1588 ** Determine if the string z[] can be shown as plain text. Return true
1589 ** if z[] is unambiguously text. Return false if z[] needs to be
1590 ** quoted.
1591 **
1592 ** All of the following must be true in order for z[] to be relaxable:
1593 **
1594 ** (1) z[] does not begin or end with ' or whitespace
1595 ** (2) z[] is not the same as the NULL rendering
1596 ** (3) z[] does not looks like a numeric literal
1597 */
1598 static int qrfRelaxable(Qrf *p, const char *z){
1599 size_t i, n;
1600 if( z[0]=='\'' || qrfSpace(z[0]) ) return 0;
1601 if( z[0]==0 ){
1602 return (p->spec.zNull!=0 && p->spec.zNull[0]!=0);
1603 }
1604 n = strlen(z);
1605 if( n==0 || z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0;
1606 if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0;
1607 i = (z[0]=='-' || z[0]=='+');
1608 if( strcmp(z+i,"Inf")==0 ) return 0;
1609 if( !qrfDigit(z[i]) ) return 1;
1610 i++;
1611 while( qrfDigit(z[i]) ){ i++; }
1612 if( z[i]==0 ) return 0;
1613 if( z[i]=='.' ){
1614 i++;
1615 while( qrfDigit(z[i]) ){ i++; }
1616 if( z[i]==0 ) return 0;
1617 }
1618 if( z[i]=='e' || z[i]=='E' ){
1619 i++;
1620 if( z[i]=='+' || z[i]=='-' ){ i++; }
1621 if( !qrfDigit(z[i]) ) return 1;
1622 i++;
1623 while( qrfDigit(z[i]) ){ i++; }
1624 }
1625 return z[i]!=0;
1626 }
1627
1628 /*
1629 ** If a field contains any character identified by a 1 in the following
1630 ** array, then the string must be quoted for CSV.
1631 */
@@ -1581,10 +1652,16 @@
1652 ** Encode text appropriately and append it to pOut.
1653 */
1654 static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){
1655 int iStart = sqlite3_str_length(pOut);
1656 switch( p->spec.eText ){
1657 case QRF_TEXT_Relaxed:
1658 if( qrfRelaxable(p, zTxt) ){
1659 sqlite3_str_appendall(pOut, zTxt);
1660 break;
1661 }
1662 deliberate_fall_through; /* FALLTHRU */
1663 case QRF_TEXT_Sql: {
1664 if( p->spec.eEsc==QRF_ESC_Off ){
1665 sqlite3_str_appendf(pOut, "%Q", zTxt);
1666 }else{
1667 sqlite3_str_appendf(pOut, "%#Q", zTxt);
@@ -1739,10 +1816,57 @@
1816 return (const char*)sqlite3_column_text(p->pJTrans, 0);
1817 }else{
1818 return 0;
1819 }
1820 }
1821
1822 /*
1823 ** Adjust the input string zIn[] such that it is no more than N display
1824 ** characters wide. If it is wider than that, then truncate and add
1825 ** ellipsis. Or if zIn[] contains a \r or \n, truncate at that point,
1826 ** adding ellipsis. Embedded tabs in zIn[] are converted into ordinary
1827 ** spaces.
1828 **
1829 ** Return this display width of the modified title string.
1830 */
1831 static int qrfTitleLimit(char *zIn, int N){
1832 unsigned char *z = (unsigned char*)zIn;
1833 int n = 0;
1834 unsigned char *zEllipsis = 0;
1835 while( 1 /*exit-by-break*/ ){
1836 if( z[0]<' ' ){
1837 int k;
1838 if( z[0]==0 ){
1839 zEllipsis = 0;
1840 break;
1841 }else if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
1842 z += k;
1843 }else if( z[0]=='\t' ){
1844 z[0] = ' ';
1845 }else if( z[0]=='\n' || z[0]=='\r' ){
1846 z[0] = ' ';
1847 }else{
1848 z++;
1849 }
1850 }else if( (0x80&z[0])==0 ){
1851 if( n>=(N-3) && zEllipsis==0 ) zEllipsis = z;
1852 if( n==N ){ z[0] = 0; break; }
1853 n++;
1854 z++;
1855 }else{
1856 int u = 0;
1857 int len = sqlite3_qrf_decode_utf8(z, &u);
1858 if( n+len>(N-3) && zEllipsis==0 ) zEllipsis = z;
1859 if( n+len>N ){ z[0] = 0; break; }
1860 z += len;
1861 n += sqlite3_qrf_wcwidth(u);
1862 }
1863 }
1864 if( zEllipsis && N>=3 ) memcpy(zEllipsis,"...",4);
1865 return n;
1866 }
1867
1868
1869 /*
1870 ** Render value pVal into pOut
1871 */
1872 static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){
@@ -2124,40 +2248,10 @@
2248 }
2249 }
2250 sqlite3_str_append(pOut, (const char*)z, i);
2251 }
2252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2253 /*
2254 ** GCC does not define the offsetof() macro so we'll have to do it
2255 ** ourselves.
2256 */
2257 #ifndef offsetof
@@ -2177,27 +2271,60 @@
2271 sqlite3_int64 nRow; /* Number of rows */
2272 sqlite3_int64 nAlloc; /* Number of cells allocated */
2273 sqlite3_int64 n; /* Number of cells. nCol*nRow */
2274 char **az; /* Content of all cells */
2275 int *aiWth; /* Width of each cell */
2276 unsigned char *abNum; /* True for each numeric cell */
2277 struct qrfPerCol { /* Per-column data */
2278 char *z; /* Cache of text for current row */
2279 int w; /* Computed width of this column */
2280 int mxW; /* Maximum natural (unwrapped) width */
2281 unsigned char e; /* Alignment */
2282 unsigned char fx; /* Width is fixed */
2283 unsigned char bNum; /* True if is numeric */
2284 } *a; /* One per column */
2285 };
2286
2287 /*
2288 ** Output horizontally justified text into pOut. The text is the
2289 ** first nVal bytes of zVal. Include nWS bytes of whitespace, either
2290 ** split between both sides, or on the left, or on the right, depending
2291 ** on eAlign.
2292 */
2293 static void qrfPrintAligned(
2294 sqlite3_str *pOut, /* Append text here */
2295 struct qrfPerCol *pCol, /* Information about the text to print */
2296 int nVal, /* Use only the first nVal bytes of zVal[] */
2297 int nWS /* Whitespace for horizonal alignment */
2298 ){
2299 unsigned char eAlign = pCol->e & QRF_ALIGN_HMASK;
2300 if( eAlign==QRF_Auto && pCol->bNum ) eAlign = QRF_ALIGN_Right;
2301 if( eAlign==QRF_ALIGN_Center ){
2302 /* Center the text */
2303 sqlite3_str_appendchar(pOut, nWS/2, ' ');
2304 qrfAppendWithTabs(pOut, pCol->z, nVal);
2305 sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
2306 }else if( eAlign==QRF_ALIGN_Right ){
2307 /* Right justify the text */
2308 sqlite3_str_appendchar(pOut, nWS, ' ');
2309 qrfAppendWithTabs(pOut, pCol->z, nVal);
2310 }else{
2311 /* Left justify the text */
2312 qrfAppendWithTabs(pOut, pCol->z, nVal);
2313 sqlite3_str_appendchar(pOut, nWS, ' ');
2314 }
2315 }
2316
2317 /*
2318 ** Free all the memory allocates in the qrfColData object
2319 */
2320 static void qrfColDataFree(qrfColData *p){
2321 sqlite3_int64 i;
2322 for(i=0; i<p->n; i++) sqlite3_free(p->az[i]);
2323 sqlite3_free(p->az);
2324 sqlite3_free(p->aiWth);
2325 sqlite3_free(p->abNum);
2326 sqlite3_free(p->a);
2327 memset(p, 0, sizeof(*p));
2328 }
2329
2330 /*
@@ -2205,10 +2332,11 @@
2332 ** Return non-zero if a memory allocation fails.
2333 */
2334 static int qrfColDataEnlarge(qrfColData *p){
2335 char **azData;
2336 int *aiWth;
2337 unsigned char *abNum;
2338 p->nAlloc = 2*p->nAlloc + 10*p->nCol;
2339 azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*));
2340 if( azData==0 ){
2341 qrfOom(p->p);
2342 qrfColDataFree(p);
@@ -2220,26 +2348,38 @@
2348 qrfOom(p->p);
2349 qrfColDataFree(p);
2350 return 1;
2351 }
2352 p->aiWth = aiWth;
2353 abNum = sqlite3_realloc64(p->abNum, p->nAlloc);
2354 if( abNum==0 ){
2355 qrfOom(p->p);
2356 qrfColDataFree(p);
2357 return 1;
2358 }
2359 p->abNum = abNum;
2360 return 0;
2361 }
2362
2363 /*
2364 ** Print a markdown or table-style row separator using ascii-art
2365 */
2366 static void qrfRowSeparator(sqlite3_str *pOut, qrfColData *p, char cSep){
2367 int i;
2368 if( p->nCol>0 ){
2369 int useBorder = p->p->spec.bBorder!=QRF_No;
2370 if( useBorder ){
2371 sqlite3_str_append(pOut, &cSep, 1);
2372 }
2373 sqlite3_str_appendchar(pOut, p->a[0].w+p->nMargin, '-');
2374 for(i=1; i<p->nCol; i++){
2375 sqlite3_str_append(pOut, &cSep, 1);
2376 sqlite3_str_appendchar(pOut, p->a[i].w+p->nMargin, '-');
2377 }
2378 if( useBorder ){
2379 sqlite3_str_append(pOut, &cSep, 1);
2380 }
2381 }
2382 sqlite3_str_append(pOut, "\n", 1);
2383 }
2384
2385 /*
@@ -2265,24 +2405,37 @@
2405 #define BOX_134 "\342\224\244" /* U+2524 -| */
2406 #define BOX_234 "\342\224\254" /* U+252c -,- */
2407 #define BOX_124 "\342\224\264" /* U+2534 -'- */
2408 #define BOX_1234 "\342\224\274" /* U+253c -|- */
2409
2410 /* Rounded corners: */
2411 #define BOX_R12 "\342\225\260" /* U+2570 '- */
2412 #define BOX_R23 "\342\225\255" /* U+256d ,- */
2413 #define BOX_R34 "\342\225\256" /* U+256e -, */
2414 #define BOX_R14 "\342\225\257" /* U+256f -' */
2415
2416 /* Doubled horizontal lines: */
2417 #define DBL_24 "\342\225\220" /* U+2550 === */
2418 #define DBL_123 "\342\225\236" /* U+255e |= */
2419 #define DBL_134 "\342\225\241" /* U+2561 =| */
2420 #define DBL_1234 "\342\225\252" /* U+256a =|= */
2421
2422 /* Draw horizontal line N characters long using unicode box
2423 ** characters
2424 */
2425 static void qrfBoxLine(sqlite3_str *pOut, int N, int bDbl){
2426 const char *azDash[2] = {
2427 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24,
2428 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24
2429 };/* 0 1 2 3 4 5 6 7 8 9 */
2430 const int nDash = 30;
2431 N *= 3;
2432 while( N>nDash ){
2433 sqlite3_str_append(pOut, azDash[bDbl], nDash);
2434 N -= nDash;
2435 }
2436 sqlite3_str_append(pOut, azDash[bDbl], N);
2437 }
2438
2439 /*
2440 ** Draw a horizontal separator for a QRF_STYLE_Box table.
2441 */
@@ -2289,21 +2442,27 @@
2442 static void qrfBoxSeparator(
2443 sqlite3_str *pOut,
2444 qrfColData *p,
2445 const char *zSep1,
2446 const char *zSep2,
2447 const char *zSep3,
2448 int bDbl
2449 ){
2450 int i;
2451 if( p->nCol>0 ){
2452 int useBorder = p->p->spec.bBorder!=QRF_No;
2453 if( useBorder ){
2454 sqlite3_str_appendall(pOut, zSep1);
2455 }
2456 qrfBoxLine(pOut, p->a[0].w+p->nMargin, bDbl);
2457 for(i=1; i<p->nCol; i++){
2458 sqlite3_str_appendall(pOut, zSep2);
2459 qrfBoxLine(pOut, p->a[i].w+p->nMargin, bDbl);
2460 }
2461 if( useBorder ){
2462 sqlite3_str_appendall(pOut, zSep3);
2463 }
2464 }
2465 sqlite3_str_append(pOut, "\n", 1);
2466 }
2467
2468 /*
@@ -2382,10 +2541,11 @@
2541 static void qrfSplitColumn(qrfColData *pData, Qrf *p){
2542 int nCol = 1;
2543 int *aw = 0;
2544 char **az = 0;
2545 int *aiWth = 0;
2546 unsigned char *abNum = 0;
2547 int nColNext = 2;
2548 int w;
2549 struct qrfPerCol *a = 0;
2550 sqlite3_int64 nRow = 1;
2551 sqlite3_int64 i;
@@ -2419,35 +2579,47 @@
2579 if( a==0 ){
2580 sqlite3_free(az);
2581 sqlite3_free(aiWth);
2582 qrfOom(p);
2583 return;
2584 }
2585 abNum = sqlite3_malloc64( nRow*nCol );
2586 if( abNum==0 ){
2587 sqlite3_free(az);
2588 sqlite3_free(aiWth);
2589 sqlite3_free(a);
2590 qrfOom(p);
2591 return;
2592 }
2593 for(i=0; i<pData->n; i++){
2594 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2595 az[j] = pData->az[i];
2596 abNum[j]= pData->abNum[i];
2597 pData->az[i] = 0;
2598 aiWth[j] = pData->aiWth[i];
2599 }
2600 while( i<nRow*nCol ){
2601 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2602 az[j] = sqlite3_mprintf("");
2603 if( az[j]==0 ) qrfOom(p);
2604 aiWth[j] = 0;
2605 abNum[j] = 0;
2606 i++;
2607 }
2608 for(i=0; i<nCol; i++){
2609 a[i].fx = a[i].mxW = a[i].w = aw[i];
2610 a[i].e = pData->a[0].e;
2611 }
2612 sqlite3_free(pData->az);
2613 sqlite3_free(pData->aiWth);
2614 sqlite3_free(pData->a);
2615 sqlite3_free(pData->abNum);
2616 sqlite3_free(aw);
2617 pData->az = az;
2618 pData->aiWth = aiWth;
2619 pData->a = a;
2620 pData->abNum = abNum;
2621 pData->nCol = nCol;
2622 pData->n = pData->nAlloc = nRow*nCol;
2623 for(i=w=0; i<nCol; i++) w += a[i].w;
2624 pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1);
2625 if( pData->nMargin>5 ) pData->nMargin = 5;
@@ -2467,10 +2639,11 @@
2639 if( p->spec.nScreenWidth==0 ) return;
2640 if( p->spec.eStyle==QRF_STYLE_Column ){
2641 sepW = pData->nCol*2 - 2;
2642 }else{
2643 sepW = pData->nCol*3 + 1;
2644 if( p->spec.bBorder==QRF_No ) sepW -= 2;
2645 }
2646 nCol = pData->nCol;
2647 for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
2648 if( p->spec.nScreenWidth >= sumW+sepW ) return;
2649
@@ -2478,10 +2651,11 @@
2651 pData->nMargin = 0;
2652 if( p->spec.eStyle==QRF_STYLE_Column ){
2653 sepW = pData->nCol - 1;
2654 }else{
2655 sepW = pData->nCol + 1;
2656 if( p->spec.bBorder==QRF_No ) sepW -= 2;
2657 }
2658 targetW = p->spec.nScreenWidth - sepW;
2659
2660 #define MIN_SQUOZE 8
2661 #define MIN_EX_SQUOZE 16
@@ -2550,10 +2724,11 @@
2724 }
2725
2726 /* Initialize the data container */
2727 memset(&data, 0, sizeof(data));
2728 data.nCol = p->nCol;
2729 data.p = p;
2730 data.a = sqlite3_malloc64( nColumn*sizeof(struct qrfPerCol) );
2731 if( data.a==0 ){
2732 qrfOom(p);
2733 return;
2734 }
@@ -2563,19 +2738,27 @@
2738
2739 /* Load the column header names and all cell content into data */
2740 if( p->spec.bTitles==QRF_Yes ){
2741 unsigned char saved_eText = p->spec.eText;
2742 p->spec.eText = p->spec.eTitle;
2743 memset(data.abNum, 0, nColumn);
2744 for(i=0; i<nColumn; i++){
2745 const char *z = (const char*)sqlite3_column_name(p->pStmt,i);
2746 int nNL = 0;
2747 int n, w;
2748 pStr = sqlite3_str_new(p->db);
2749 qrfEncodeText(p, pStr, z ? z : "");
2750 n = sqlite3_str_length(pStr);
2751 qrfStrErr(p, pStr);
2752 z = data.az[data.n] = sqlite3_str_finish(pStr);
2753 if( p->spec.nTitleLimit ){
2754 nNL = 0;
2755 data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n],
2756 p->spec.nTitleLimit );
2757 }else{
2758 data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
2759 }
2760 data.n++;
2761 if( w>data.a[i].mxW ) data.a[i].mxW = w;
2762 if( nNL ) data.bMultiRow = 1;
2763 }
2764 p->spec.eText = saved_eText;
@@ -2587,14 +2770,17 @@
2770 }
2771 for(i=0; i<nColumn; i++){
2772 char *z;
2773 int nNL = 0;
2774 int n, w;
2775 int eType = sqlite3_column_type(p->pStmt,i);
2776 pStr = sqlite3_str_new(p->db);
2777 qrfRenderValue(p, pStr, i);
2778 n = sqlite3_str_length(pStr);
2779 qrfStrErr(p, pStr);
2780 z = data.az[data.n] = sqlite3_str_finish(pStr);
2781 data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT;
2782 data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
2783 data.n++;
2784 if( w>data.a[i].mxW ) data.a[i].mxW = w;
2785 if( nNL ) data.bMultiRow = 1;
2786 }
@@ -2680,11 +2866,16 @@
2866 }else{
2867 rowStart = BOX_13;
2868 colSep = BOX_13;
2869 rowSep = BOX_13 "\n";
2870 }
2871 if( p->spec.bBorder==QRF_No){
2872 rowStart += 3;
2873 rowSep = "\n";
2874 }else{
2875 qrfBoxSeparator(p->pOut, &data, BOX_R23, BOX_234, BOX_R34, 0);
2876 }
2877 break;
2878 case QRF_STYLE_Table:
2879 if( data.nMargin ){
2880 rowStart = "| ";
2881 colSep = " | ";
@@ -2692,11 +2883,16 @@
2883 }else{
2884 rowStart = "|";
2885 colSep = "|";
2886 rowSep = "|\n";
2887 }
2888 if( p->spec.bBorder==QRF_No ){
2889 rowStart += 1;
2890 rowSep = "\n";
2891 }else{
2892 qrfRowSeparator(p->pOut, &data, '+');
2893 }
2894 break;
2895 case QRF_STYLE_Column: {
2896 static const char zSpace[] = " ";
2897 rowStart = "";
2898 if( data.nMargin<2 ){
@@ -2724,20 +2920,32 @@
2920 szRowStart = (int)strlen(rowStart);
2921 szRowSep = (int)strlen(rowSep);
2922 szColSep = (int)strlen(colSep);
2923
2924 bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
2925 if( p->spec.eStyle==QRF_STYLE_Column
2926 || (p->spec.bBorder==QRF_No
2927 && (p->spec.eStyle==QRF_STYLE_Box || p->spec.eStyle==QRF_STYLE_Table)
2928 )
2929 ){
2930 bRTrim = 1;
2931 }else{
2932 bRTrim = 0;
2933 }
2934 for(i=0; i<data.n && sqlite3_str_errcode(p->pOut)==SQLITE_OK; i+=nColumn){
2935 int bMore;
2936 int nRow = 0;
2937
2938 /* Draw a single row of the table. This might be the title line
2939 ** (if there is a title line) or a row in the body of the table.
2940 ** The column number will be j. The row number is i/nColumn.
2941 */
2942 for(j=0; j<nColumn; j++){
2943 data.a[j].z = data.az[i+j];
2944 if( data.a[j].z==0 ) data.a[j].z = "";
2945 data.a[j].bNum = data.abNum[i+j];
2946 }
2947 do{
2948 sqlite3_str_append(p->pOut, rowStart, szRowStart);
2949 bMore = 0;
2950 for(j=0; j<nColumn; j++){
2951 int nThis = 0;
@@ -2744,11 +2952,11 @@
2952 int nWide = 0;
2953 int iNext = 0;
2954 int nWS;
2955 qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
2956 nWS = data.a[j].w - nWide;
2957 qrfPrintAligned(p->pOut, &data.a[j], nThis, nWS);
2958 data.a[j].z += iNext;
2959 if( data.a[j].z[0]!=0 ){
2960 bMore = 1;
2961 }
2962 if( j<nColumn-1 ){
@@ -2766,11 +2974,12 @@
2974 if( data.a[j].z[0]==0 ){
2975 sqlite3_str_appendchar(p->pOut, data.a[j].w, ' ');
2976 }else{
2977 int nE = 3;
2978 if( nE>data.a[j].w ) nE = data.a[j].w;
2979 data.a[j].z = "...";
2980 qrfPrintAligned(p->pOut, &data.a[j], nE, data.a[j].w-nE);
2981 }
2982 if( j<nColumn-1 ){
2983 sqlite3_str_append(p->pOut, colSep, szColSep);
2984 }else{
2985 if( bRTrim ) qrfRTrim(p->pOut);
@@ -2794,12 +3003,14 @@
3003 qrfRowSeparator(p->pOut, &data, '+');
3004 }
3005 break;
3006 }
3007 case QRF_STYLE_Box: {
3008 if( isTitleDataSeparator ){
3009 qrfBoxSeparator(p->pOut, &data, DBL_123, DBL_1234, DBL_134, 1);
3010 }else if( data.bMultiRow ){
3011 qrfBoxSeparator(p->pOut, &data, BOX_123, BOX_1234, BOX_134, 0);
3012 }
3013 break;
3014 }
3015 case QRF_STYLE_Markdown: {
3016 if( isTitleDataSeparator ){
@@ -2827,17 +3038,19 @@
3038 }
3039 }
3040 }
3041
3042 /* Draw the line across the bottom of the table */
3043 if( p->spec.bBorder!=QRF_No ){
3044 switch( p->spec.eStyle ){
3045 case QRF_STYLE_Box:
3046 qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0);
3047 break;
3048 case QRF_STYLE_Table:
3049 qrfRowSeparator(p->pOut, &data, '+');
3050 break;
3051 }
3052 }
3053 qrfWrite(p);
3054
3055 qrfColDataFree(&data);
3056 return;
@@ -2903,11 +3116,11 @@
3116 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) );
3117 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) );
3118 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) );
3119 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) );
3120
3121 for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){
3122 int iAddr = sqlite3_column_int(p->pStmt, 0);
3123 const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1);
3124 int p1 = sqlite3_column_int(p->pStmt, 2);
3125 int p2 = sqlite3_column_int(p->pStmt, 3);
3126
@@ -2960,11 +3173,11 @@
3173 nWidth = sizeof(aScanExpWidth)/sizeof(int);
3174 iIndent = 3;
3175 }
3176 if( nArg>nWidth ) nArg = nWidth;
3177
3178 for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW && !p->iErr; iOp++){
3179 /* If this is the first row seen, print out the headers */
3180 if( iOp==0 ){
3181 for(i=0; i<nArg; i++){
3182 const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]);
3183 qrfWidthPrint(p,p->pOut, aWidth[i], zCol);
@@ -2989,11 +3202,11 @@
3202 int w = aWidth[i];
3203 const char *zVal = (const char*)sqlite3_column_text(p->pStmt, aMap[i]);
3204 int len;
3205 if( i==nArg-1 ) w = 0;
3206 if( zVal==0 ) zVal = "";
3207 len = (int)sqlite3_qrf_wcswidth(zVal);
3208 if( len>w ){
3209 w = len;
3210 zSep = " ";
3211 }
3212 if( i==iIndent && aiIndent && iOp<nIndent ){
@@ -3168,34 +3381,40 @@
3381 }
3382 case QRF_STYLE_Line: {
3383 sqlite3_str *pVal;
3384 int mxW;
3385 int bWW;
3386 int nSep;
3387 if( p->u.sLine.azCol==0 ){
3388 p->u.sLine.azCol = sqlite3_malloc64( p->nCol*sizeof(char*) );
3389 if( p->u.sLine.azCol==0 ){
3390 qrfOom(p);
3391 break;
3392 }
3393 p->u.sLine.mxColWth = 0;
3394 for(i=0; i<p->nCol; i++){
3395 int sz;
3396 const char *zCName = sqlite3_column_name(p->pStmt, i);
3397 if( zCName==0 ) zCName = "unknown";
3398 p->u.sLine.azCol[i] = sqlite3_mprintf("%s", zCName);
3399 if( p->spec.nTitleLimit>0 ){
3400 (void)qrfTitleLimit(p->u.sLine.azCol[i], p->spec.nTitleLimit);
3401 }
3402 sz = (int)sqlite3_qrf_wcswidth(p->u.sLine.azCol[i]);
3403 if( sz > p->u.sLine.mxColWth ) p->u.sLine.mxColWth = sz;
3404 }
3405 }
3406 if( p->nRow ) sqlite3_str_append(p->pOut, "\n", 1);
3407 pVal = sqlite3_str_new(p->db);
3408 nSep = (int)strlen(p->spec.zColumnSep);
3409 mxW = p->mxWidth - (nSep + p->u.sLine.mxColWth);
3410 bWW = p->spec.bWordWrap==QRF_Yes;
3411 for(i=0; i<p->nCol; i++){
3412 const char *zVal;
3413 int cnt = 0;
3414 qrfWidthPrint(p, p->pOut, -p->u.sLine.mxColWth, p->u.sLine.azCol[i]);
3415 sqlite3_str_append(p->pOut, p->spec.zColumnSep, nSep);
3416 qrfRenderValue(p, pVal, i);
3417 zVal = sqlite3_str_value(pVal);
3418 if( zVal==0 ) zVal = "";
3419 do{
3420 int nThis, nWide, iNext;
@@ -3210,10 +3429,11 @@
3429 sqlite3_str_append(p->pOut, "\n", 1);
3430 zVal += iNext;
3431 }while( zVal[0] );
3432 sqlite3_str_reset(pVal);
3433 }
3434 qrfStrErr(p, pVal);
3435 sqlite3_free(sqlite3_str_finish(pVal));
3436 qrfWrite(p);
3437 break;
3438 }
3439 case QRF_STYLE_Eqp: {
@@ -3273,11 +3493,11 @@
3493 p->pOut = sqlite3_str_new(p->db);
3494 if( p->pOut==0 ){
3495 qrfOom(p);
3496 return;
3497 }
3498 p->iErr = SQLITE_OK;
3499 p->nCol = sqlite3_column_count(p->pStmt);
3500 p->nRow = 0;
3501 sz = sizeof(sqlite3_qrf_spec);
3502 memcpy(&p->spec, pSpec, sz);
3503 if( p->spec.zNull==0 ) p->spec.zNull = "";
@@ -3285,12 +3505,12 @@
3505 if( p->mxWidth<=0 ) p->mxWidth = QRF_MAX_WIDTH;
3506 p->mxHeight = p->spec.nLineLimit;
3507 if( p->mxHeight<=0 ) p->mxHeight = 2147483647;
3508 if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto;
3509 if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto;
3510 if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto;
3511 if( p->spec.eTitle>QRF_TEXT_Relaxed ) p->spec.eTitle = QRF_Auto;
3512 if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto;
3513 qrf_reinit:
3514 switch( p->spec.eStyle ){
3515 case QRF_Auto: {
3516 switch( sqlite3_stmt_isexplain(pStmt) ){
@@ -3321,10 +3541,16 @@
3541 p->spec.zNull = "NULL";
3542 if( p->spec.zTableName==0 || p->spec.zTableName[0]==0 ){
3543 p->spec.zTableName = "tab";
3544 }
3545 break;
3546 }
3547 case QRF_STYLE_Line: {
3548 if( p->spec.zColumnSep==0 ){
3549 p->spec.zColumnSep = ": ";
3550 }
3551 break;
3552 }
3553 case QRF_STYLE_Csv: {
3554 p->spec.eStyle = QRF_STYLE_List;
3555 p->spec.eText = QRF_TEXT_Csv;
3556 p->spec.zColumnSep = ",";
@@ -3430,11 +3656,15 @@
3656 qrfWrite(p);
3657 }
3658 break;
3659 }
3660 case QRF_STYLE_Line: {
3661 if( p->u.sLine.azCol ){
3662 int i;
3663 for(i=0; i<p->nCol; i++) sqlite3_free(p->u.sLine.azCol[i]);
3664 sqlite3_free(p->u.sLine.azCol);
3665 }
3666 break;
3667 }
3668 case QRF_STYLE_Stats:
3669 case QRF_STYLE_StatsEst:
3670 case QRF_STYLE_Eqp: {
@@ -3441,10 +3671,11 @@
3671 qrfEqpRender(p, 0);
3672 qrfWrite(p);
3673 break;
3674 }
3675 }
3676 qrfStrErr(p, p->pOut);
3677 if( p->spec.pzOutput ){
3678 if( p->spec.pzOutput[0] ){
3679 sqlite3_int64 n, sz;
3680 char *zCombined;
3681 sz = strlen(p->spec.pzOutput[0]);
@@ -3624,11 +3855,11 @@
3855
3856 /* Return the current wall-clock time in microseconds since the
3857 ** Unix epoch (1970-01-01T00:00:00Z)
3858 */
3859 static sqlite3_int64 timeOfDay(void){
3860 #if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8
3861 sqlite3_uint64 t;
3862 FILETIME tm;
3863 GetSystemTimePreciseAsFileTime(&tm);
3864 t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
3865 t += 116444736000000000LL;
@@ -3724,11 +3955,10 @@
3955 */
3956 static int hasTimer(void){
3957 if( getProcessTimesAddr ){
3958 return 1;
3959 } else {
 
3960 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
3961 ** versions. See if the version we are running on has it, and if it
3962 ** does, save off a pointer to it and the current process handle.
3963 */
3964 hProcess = GetCurrentProcess();
@@ -3741,11 +3971,10 @@
3971 return 1;
3972 }
3973 FreeLibrary(hinstLib);
3974 }
3975 }
 
3976 }
3977 return 0;
3978 }
3979
3980 /*
@@ -3860,10 +4089,18 @@
4089 #define PROMPT_LEN_MAX 128
4090 /* First line prompt. default: "sqlite> " */
4091 static char mainPrompt[PROMPT_LEN_MAX];
4092 /* Continuation prompt. default: " ...> " */
4093 static char continuePrompt[PROMPT_LEN_MAX];
4094
4095 /*
4096 ** Write I/O traces to the following stream.
4097 */
4098 #ifdef SQLITE_ENABLE_IOTRACE
4099 static FILE *iotrace = 0;
4100 #endif
4101
4102
4103 /* This is variant of the standard-library strncpy() routine with the
4104 ** one change that the destination string is always zero-terminated, even
4105 ** if there is no zero-terminator in the first n-1 characters of the source
4106 ** string.
@@ -3980,17 +4217,10 @@
4217 */
4218 static void shell_check_oom(const void *p){
4219 if( p==0 ) shell_out_of_memory();
4220 }
4221
 
 
 
 
 
 
 
4222 /*
4223 ** This routine works like printf in that its first argument is a
4224 ** format string and subsequent arguments are values to be substituted
4225 ** in place of % fields. The result of formatting this string
4226 ** is written to iotrace.
@@ -6013,17 +6243,20 @@
6243 }
6244 /* End of the hashing logic
6245 *****************************************************************************/
6246
6247 /*
6248 ** Two SQL functions: sha1(X) and sha1b(X).
6249 **
6250 ** sha1(X) returns a lower-case hexadecimal rendering of the SHA1 hash
6251 ** of the argument X. If X is a BLOB, it is hashed as is. For all other
6252 ** types of input, X is converted into a UTF-8 string and the string
6253 ** is hashed without the trailing 0x00 terminator. The hash of a NULL
6254 ** value is NULL.
6255 **
6256 ** sha1b(X) is the same except that it returns a 20-byte BLOB containing
6257 ** the binary hash instead of a hexadecimal string.
6258 */
6259 static void sha1Func(
6260 sqlite3_context *context,
6261 int argc,
6262 sqlite3_value **argv
@@ -6040,15 +6273,17 @@
6273 hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
6274 }else{
6275 hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
6276 }
6277 if( sqlite3_user_data(context)!=0 ){
6278 /* sha1b() - binary result */
6279 hash_finish(&cx, zOut, 1);
6280 sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
6281 }else{
6282 /* sha1() - hexadecimal text result */
6283 hash_finish(&cx, zOut, 0);
6284 sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
6285 }
6286 }
6287
6288 /*
6289 ** Implementation of the sha1_query(SQL) function.
@@ -8136,13 +8371,13 @@
8371 }else if( e<-10000 ){
8372 e = -10000;
8373 }
8374
8375 if( m<0 ){
8376 if( m<(-9223372036854775807LL) ) return;
8377 isNeg = 1;
8378 m = -m;
 
8379 }else if( m==0 && e>-1000 && e<1000 ){
8380 sqlite3_result_double(context, 0.0);
8381 return;
8382 }
8383 while( (m>>32)&0xffe00000 ){
@@ -9259,11 +9494,11 @@
9494 ** (X) match X
9495 ** X|Y X or Y
9496 ** ^X X occurring at the beginning of the string
9497 ** X$ X occurring at the end of the string
9498 ** . Match any single character
9499 ** \c Character c where c is one of \{}()[]|*+?-.
9500 ** \c C-language escapes for c in afnrtv. ex: \t or \n
9501 ** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
9502 ** \xXX Where XX is exactly 2 hex digits, unicode value XX
9503 ** [abc] Any single character from the set abc
9504 ** [^abc] Any single character not in the set abc
@@ -9644,11 +9879,11 @@
9879
9880 /* A backslash character has been seen, read the next character and
9881 ** return its interpretation.
9882 */
9883 static unsigned re_esc_char(ReCompiled *p){
9884 static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]-";
9885 static const char zTrans[] = "\a\f\n\r\t\v";
9886 int i, v = 0;
9887 char c;
9888 if( p->sIn.i>=p->sIn.mx ) return 0;
9889 c = p->sIn.z[p->sIn.i];
@@ -9967,15 +10202,22 @@
10202 }
10203 return pRe->zErr;
10204 }
10205
10206 /*
10207 ** The value of LIMIT_MAX_PATTERN_LENGTH.
10208 */
10209 static int re_maxlen(sqlite3_context *context){
10210 sqlite3 *db = sqlite3_context_db_handle(context);
10211 return sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1);
10212 }
10213
10214 /*
10215 ** Maximum NFA size given a maximum pattern length.
10216 */
10217 static int re_maxnfa(int mxlen){
10218 return 75+mxlen/2;
10219 }
10220
10221 /*
10222 ** Implementation of the regexp() SQL function. This function implements
10223 ** the build-in REGEXP operator. The first argument to the function is the
@@ -9997,14 +10239,21 @@
10239 int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
10240
10241 (void)argc; /* Unused */
10242 pRe = sqlite3_get_auxdata(context, 0);
10243 if( pRe==0 ){
10244 int mxLen = re_maxlen(context);
10245 int nPattern;
10246 zPattern = (const char*)sqlite3_value_text(argv[0]);
10247 if( zPattern==0 ) return;
10248 nPattern = sqlite3_value_bytes(argv[0]);
10249 if( nPattern>mxLen ){
10250 zErr = "REGEXP pattern too big";
10251 }else{
10252 zErr = re_compile(&pRe, zPattern, re_maxnfa(mxLen),
10253 sqlite3_user_data(context)!=0);
10254 }
10255 if( zErr ){
10256 re_free(pRe);
10257 sqlite3_result_error(context, zErr, -1);
10258 return;
10259 }
@@ -10066,11 +10315,11 @@
10315 "ATSTART",
10316 };
10317
10318 zPattern = (const char*)sqlite3_value_text(argv[0]);
10319 if( zPattern==0 ) return;
10320 zErr = re_compile(&pRe, zPattern, re_maxnfa(re_maxlen(context)),
10321 sqlite3_user_data(context)!=0);
10322 if( zErr ){
10323 re_free(pRe);
10324 sqlite3_result_error(context, zErr, -1);
10325 return;
@@ -10474,10 +10723,11 @@
10723 if( b1==0 ) return 1;
10724 sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
10725 b1[sz] = 0;
10726 rc = _wstat(b1, pStatBuf);
10727 if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
10728 sqlite3_free(b1);
10729 return rc;
10730 #else
10731 return stat(zPath, pStatBuf);
10732 #endif
10733 }
@@ -10604,11 +10854,10 @@
10854 }
10855 }
10856
10857 if( mtime>=0 ){
10858 #if defined(_WIN32)
 
10859 /* Windows */
10860 FILETIME lastAccess;
10861 FILETIME lastWrite;
10862 SYSTEMTIME currentTime;
10863 LONGLONG intervals;
@@ -10635,11 +10884,10 @@
10884 CloseHandle(hFile);
10885 return !bResult;
10886 }else{
10887 return 1;
10888 }
 
10889 #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
10890 /* Recent unix */
10891 struct timespec times[2];
10892 times[0].tv_nsec = times[1].tv_nsec = 0;
10893 times[0].tv_sec = time(0);
@@ -13337,11 +13585,11 @@
13585 rc = zipfileReadData(
13586 pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
13587 );
13588 }else{
13589 aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
13590 if( (iOff + ZIPFILE_CDS_FIXED_SZ + nFile + nExtra)>nBlob ){
13591 rc = zipfileCorrupt(pzErr);
13592 }
13593 }
13594 }
13595
@@ -13362,15 +13610,16 @@
13610 ZipfileLFH lfh;
13611 if( pFile ){
13612 rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
13613 }else{
13614 aRead = (u8*)&aBlob[pNew->cds.iOffset];
13615 if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>(unsigned)nBlob ){
13616 rc = zipfileCorrupt(pzErr);
13617 }
13618 }
13619
13620 memset(&lfh, 0, sizeof(lfh));
13621 if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
13622 if( rc==SQLITE_OK ){
13623 pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
13624 pNew->iDataOff += lfh.nFile + lfh.nExtra;
13625 if( aBlob && pNew->cds.szCompressed ){
@@ -13470,11 +13719,11 @@
13719 }else{
13720 err = inflate(&str, Z_NO_FLUSH);
13721 if( err!=Z_STREAM_END ){
13722 zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
13723 }else{
13724 sqlite3_result_blob(pCtx, aRes, (int)str.total_out, zipfileFree);
13725 aRes = 0;
13726 }
13727 }
13728 sqlite3_free(aRes);
13729 inflateEnd(&str);
@@ -23948,28 +24197,28 @@
24197 u8 autoExplain; /* Automatically turn on .explain mode */
24198 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
24199 u8 autoEQPtrace; /* autoEQP is in trace mode */
24200 u8 scanstatsOn; /* True to display scan stats before each finalize */
24201 u8 bAutoScreenWidth; /* Using the TTY to determine screen width */
24202 u8 mFlags; /* MFLG_ECHO, MFLG_CRLF, etc. */
24203 u8 eMode; /* One of the MODE_ values */
24204 sqlite3_qrf_spec spec; /* Spec to be passed into QRF */
24205 } Mode;
24206
24207 /* Flags for Mode.mFlags */
24208 #define MFLG_ECHO 0x01 /* Echo inputs to output */
24209 #define MFLG_CRLF 0x02 /* Use CR/LF output line endings */
24210 #define MFLG_HDR 0x04 /* .header used to change headers on/off */
24211
24212
24213 /*
24214 ** State information about the database connection is contained in an
24215 ** instance of the following structure.
24216 */
24217 typedef struct ShellState ShellState;
24218 struct ShellState {
24219 sqlite3 *db; /* The database */
 
24220 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
24221 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
24222 u8 nEqpLevel; /* Depth of the EQP output graph */
24223 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
24224 u8 bSafeMode; /* True to prohibit unsafe operations */
@@ -24078,11 +24327,11 @@
24327
24328 /* Names of values for Mode.spec.eEsc and Mode.spec.eText
24329 */
24330 static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" };
24331 static const char *qrfQuoteNames[] =
24332 { "off","off","sql","hex","csv","tcl","json","relaxed"};
24333
24334 /*
24335 ** These are the allowed shellFlgs values
24336 */
24337 #define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
@@ -24120,19 +24369,20 @@
24369 #define MODE_Json 10 /* Output JSON */
24370 #define MODE_Line 11 /* One column per line. Blank line between records */
24371 #define MODE_List 12 /* One record per line with a separator */
24372 #define MODE_Markdown 13 /* Markdown formatting */
24373 #define MODE_Off 14 /* No query output shown */
24374 #define MODE_Psql 15 /* Similar to psql */
24375 #define MODE_QBox 16 /* BOX with SQL-quoted content */
24376 #define MODE_Quote 17 /* Quote values as for SQL */
24377 #define MODE_Split 18 /* Split-column mode */
24378 #define MODE_Table 19 /* MySQL-style table formatting */
24379 #define MODE_Tabs 20 /* Tab-separated values */
24380 #define MODE_Tcl 21 /* Space-separated list of TCL strings */
24381 #define MODE_Www 22 /* Full web-page output */
24382
24383 #define MODE_BUILTIN 22 /* Maximum built-in mode */
24384 #define MODE_BATCH 50 /* Default mode for batch processing */
24385 #define MODE_TTY 51 /* Default mode for interactive processing */
24386 #define MODE_USER 75 /* First user-defined mode */
24387 #define MODE_N_USER 25 /* Maximum number of user-defined modes */
24388
@@ -24149,43 +24399,45 @@
24399 unsigned char eHdr; /* Default header encoding. */
24400 unsigned char eBlob; /* Default blob encoding. */
24401 unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */
24402 unsigned char eStyle; /* Underlying QRF style */
24403 unsigned char eCx; /* 0: other, 1: line, 2: columnar */
24404 unsigned char mFlg; /* Flags. 1=border-off 2=split-column */
24405 };
24406
24407 /* String constants used by built-in modes */
24408 static const char *aModeStr[] =
24409 /* 0 1 2 3 4 5 6 7 8 */
24410 { 0, "\n", "|", " ", ",", "\r\n", "\036", "\037", "\t",
24411 "", "NULL", "null", "\"\"", ": ", };
24412 /* 9 10 11 12 13 */
24413
24414 static const ModeInfo aModeInfo[] = {
24415 /* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */
24416 { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0, 0 },
24417 { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2, 0 },
24418 { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0, 0 },
24419 { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2, 0 },
24420 { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
24421 { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0, 0 },
24422 { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 },
24423 { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0, 0 },
24424 { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0, 0 },
24425 { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0, 0 },
24426 { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0, 0 },
24427 { "line", 13, 1, 9, 1, 1, 0, 0, 11, 1, 0 },
24428 { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0, 0 },
24429 { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2, 0 },
24430 { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0, 0 },
24431 { "psql", 0, 0, 9, 1, 1, 0, 2, 19, 2, 1 },
24432 { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2, 0 },
24433 { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0, 0 },
24434 { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2, 2 },
24435 { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2, 0 },
24436 { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0, 0 },
24437 { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0, 0 },
24438 { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 }
24439 }; /* | / / | / / | | \
24440 ** | / / | / / | | \_ 2: columnar
24441 ** Index into aModeStr[] | / / | | 1: line
24442 ** | / / | | 0: other
24443 ** | / / | \
@@ -24212,10 +24464,23 @@
24464 #define SEP_Comma ","
24465 #define SEP_CrLf "\r\n"
24466 #define SEP_Unit "\x1F"
24467 #define SEP_Record "\x1E"
24468
24469 /*
24470 ** Default values for the various QRF limits
24471 */
24472 #ifndef DFLT_CHAR_LIMIT
24473 # define DFLT_CHAR_LIMIT 300
24474 #endif
24475 #ifndef DFLT_LINE_LIMIT
24476 # define DFLT_LINE_LIMIT 5
24477 #endif
24478 #ifndef DFLT_TITLE_LIMIT
24479 # define DFLT_TITLE_LIMIT 20
24480 #endif
24481
24482 /*
24483 ** Limit input nesting via .read or any other input redirect.
24484 ** It's not too expensive, so a generous allowance can be made.
24485 */
24486 #define MAX_INPUT_NESTING 25
@@ -24305,13 +24570,20 @@
24570 if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]);
24571 if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]);
24572 if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
24573 pM->spec.eText = pI->eText;
24574 pM->spec.eBlob = pI->eBlob;
24575 if( (pM->mFlags & MFLG_HDR)==0 ){
24576 pM->spec.bTitles = pI->bHdr;
24577 }
24578 pM->spec.eTitle = pI->eHdr;
24579 if( pI->mFlg & 0x01 ){
24580 pM->spec.bBorder = QRF_No;
24581 }else{
24582 pM->spec.bBorder = QRF_Auto;
24583 }
24584 if( pI->mFlg & 0x02 ){
24585 pM->spec.bSplitColumn = QRF_Yes;
24586 pM->bAutoScreenWidth = 1;
24587 }else{
24588 pM->spec.bSplitColumn = QRF_No;
24589 }
@@ -24326,26 +24598,27 @@
24598 }else if( eMode==MODE_TTY ){
24599 u8 mFlags = p->mode.mFlags;
24600 modeFree(&p->mode);
24601 modeChange(p, MODE_QBox);
24602 p->mode.bAutoScreenWidth = 1;
24603 p->mode.spec.eText = QRF_TEXT_Relaxed;
24604 p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
24605 p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
24606 p->mode.spec.bTextJsonb = QRF_Yes;
24607 p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
24608 p->mode.mFlags = mFlags;
24609 }
24610 }
24611
24612 /*
24613 ** Set the mode to the default. It assumed that the mode has
24614 ** already been freed and zeroed prior to calling this routine.
 
24615 */
24616 static void modeDefault(ShellState *p){
24617 p->mode.spec.iVersion = 1;
24618 p->mode.autoExplain = 1;
24619 if( stdin_is_interactive || stdout_is_console ){
24620 modeChange(p, MODE_TTY);
24621 }else{
24622 modeChange(p, MODE_BATCH);
24623 }
24624 }
@@ -25075,10 +25348,12 @@
25348 z[j] = 0;
25349 if( strlen30(z)>=79 ){
25350 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
25351 if( c==cEnd ){
25352 cEnd = 0;
25353 }else if( cEnd!=0){
25354 /* No-op */
25355 }else if( c=='"' || c=='\'' || c=='`' ){
25356 cEnd = c;
25357 }else if( c=='[' ){
25358 cEnd = ']';
25359 }else if( c=='-' && z[i+1]=='-' ){
@@ -25889,10 +26164,11 @@
26164 if( pArg->mode.bAutoScreenWidth ){
26165 spec.nScreenWidth = shellScreenWidth();
26166 }
26167 if( spec.eBlob==QRF_BLOB_Auto ){
26168 switch( spec.eText ){
26169 case QRF_TEXT_Relaxed: /* fall through */
26170 case QRF_TEXT_Sql: spec.eBlob = QRF_BLOB_Sql; break;
26171 case QRF_TEXT_Json: spec.eBlob = QRF_BLOB_Json; break;
26172 default: spec.eBlob = QRF_BLOB_Text; break;
26173 }
26174 }
@@ -25902,11 +26178,11 @@
26178 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
26179 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
26180 }
26181 #endif
26182
26183 while( zSql && zSql[0] && (SQLITE_OK == rc) ){
26184 static const char *zStmtSql;
26185 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
26186 if( SQLITE_OK != rc ){
26187 if( pzErrMsg ){
26188 *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
@@ -26365,12 +26641,12 @@
26641 ".bail on|off Stop after hitting an error. Default OFF",
26642 #ifndef SQLITE_SHELL_FIDDLE
26643 ".cd DIRECTORY Change the working directory to DIRECTORY",
26644 #endif
26645 ".changes on|off Show number of rows changed by SQL",
26646 ".check OPTIONS ... Verify the results of a .testcase",
26647 #ifndef SQLITE_SHELL_FIDDLE
 
26648 ".clone NEWDB Clone data into NEWDB from the existing database",
26649 #endif
26650 ".connection [close] [#] Open or close an auxiliary database connection",
26651 ".crlf ?on|off? Whether or not to use \\r\\n line endings",
26652 ".databases List names and files of attached databases",
@@ -26546,13 +26822,11 @@
26822 " vmstep Show the virtual machine step count only",
26823 #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
26824 ".system CMD ARGS... Run CMD ARGS... in a system shell",
26825 #endif
26826 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
26827 ".testcase NAME Begin a test case.",
 
 
26828 ",testctrl CMD ... Run various sqlite3_test_control() operations",
26829 " Run \".testctrl\" with no arguments for details",
26830 ".timeout MS Try opening locked tables for MS milliseconds",
26831 ".timer on|off Turn SQL timer on or off",
26832 #ifndef SQLITE_OMIT_TRACE
@@ -26597,19 +26871,31 @@
26871 "USAGE: .import [OPTIONS] FILE TABLE\n"
26872 "\n"
26873 "Import CSV or similar text from FILE into TABLE. If TABLE does\n"
26874 "not exist, it is created using the first row of FILE as the column\n"
26875 "names. If FILE begins with \"|\" then it is a command that is run\n"
26876 "and the output from the command is used as the input data. If\n"
26877 "FILE begins with \"<<\" followed by a label, then content is read from\n"
26878 "the script until the first line that matches the label.\n"
26879 "\n"
26880 "The content of FILE is interpreted using RFC-4180 (\"CSV\") quoting\n"
26881 "rules unless the current mode is \"ascii\" or \"tabs\" or unless one\n"
26882 "the --ascii option is used.\n"
26883 "\n"
26884 "The column and row separators must be single ASCII characters. If\n"
26885 "multiple characters or a Unicode character are specified for the\n"
26886 "separators, then only the first byte of the separator is used. Except,\n"
26887 "if the row separator is \\n and the mode is not --ascii, then \\r\\n is\n"
26888 "understood as a row separator too.\n"
26889 "\n"
26890 "Options:\n"
26891 " --ascii Do not use RFC-4180 quoting. Use \\037 and \\036\n"
26892 " as column and row separators on input, unless other\n"
26893 " delimiters are specified using --colsep and/or --rowsep\n"
26894 " --colsep CHAR Use CHAR as the column separator.\n"
26895 " --csv Input is standard RFC-4180 CSV.\n"
26896 " --rowsep CHAR Use CHAR as the row separator.\n"
26897 " --schema S When creating TABLE, put it in schema S\n"
26898 " --skip N Ignore the first N rows of input\n"
26899 " -v Verbose mode\n"
26900 },
26901 { ".mode",
@@ -26625,10 +26911,11 @@
26911 " meaning \"left\", \"centered\", and \"right\", with\n"
26912 " one letter per column starting from the left.\n"
26913 " Unspecified alignment defaults to 'L'.\n"
26914 " --blob-quote ARG ARG can be \"auto\", \"text\", \"sql\", \"hex\", \"tcl\",\n"
26915 " \"json\", or \"size\". Default is \"auto\".\n"
26916 " --border on|off Show outer border on \"box\" and \"table\" modes.\n"
26917 " --charlimit N Set the maximum number of output characters to\n"
26918 " show for any single SQL value to N. Longer values\n"
26919 " truncated. Zero means \"no limit\".\n"
26920 " --colsep STRING Use STRING as the column separator\n"
26921 " --escape ESC Enable/disable escaping of control characters\n"
@@ -26636,19 +26923,22 @@
26923 " or \"symbol\".\n"
26924 " --linelimit N Set the maximum number of output lines to show for\n"
26925 " any single SQL value to N. Longer values are\n"
26926 " truncated. Zero means \"no limit\". Only works\n"
26927 " in \"line\" mode and in columnar modes.\n"
26928 " --limits L,C,T Shorthand for \"--linelimit L --charlimit C\n"
26929 " --titlelimit T\". The \",T\" can be omitted in which\n"
26930 " case the --titlelimit is unchanged. The argument\n"
26931 " can also be \"off\" to mean \"0,0,0\" or \"on\" to\n"
26932 " mean \"5,300,20\".\n"
26933 " --list List available modes\n"
26934 " --null STRING Render SQL NULL values as the given string\n"
26935 " --once Setting changes to the right are reverted after\n"
26936 " the next SQL command.\n"
26937 " --quote ARG Enable/disable quoting of text. ARG can be\n"
26938 " \"off\", \"on\", \"sql\", \"relaxed\", \"csv\", \"html\",\n"
26939 " \"tcl\", or \"json\". \"off\" means show the text as-is.\n"
26940 " \"on\" is an alias for \"sql\".\n"
26941 " --reset Changes all mode settings back to their default.\n"
26942 " --rowsep STRING Use STRING as the row separator\n"
26943 " --sw|--screenwidth N Declare the screen width of the output device\n"
26944 " to be N characters. An attempt may be made to\n"
@@ -26659,10 +26949,11 @@
26949 " --tag NAME Save mode to the left as NAME.\n"
26950 " --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON.\n"
26951 " --title ARG Whether or not to show column headers, and if so\n"
26952 " how to encode them. ARG can be \"off\", \"on\",\n"
26953 " \"sql\", \"csv\", \"html\", \"tcl\", or \"json\".\n"
26954 " --titlelimit N Limit the length of column titles to N characters.\n"
26955 " -v|--verbose Verbose output\n"
26956 " --widths LIST Set the columns widths for columnar modes. The\n"
26957 " argument is a list of integers, one for each\n"
26958 " column. A \"0\" width means use a dynamic width\n"
26959 " based on the actual width of data. If there are\n"
@@ -26686,23 +26977,17 @@
26977 " --bom Prepend a byte-order mark to the output\n"
26978 " -e Accumulate output in a temporary text file then\n"
26979 " launch a text editor when the redirection ends.\n"
26980 " --error-prefix X Use X as the left-margin prefix for error messages.\n"
26981 " Set to an empty string to restore the default.\n"
26982 " --keep Keep redirecting output to its current destination.\n"
26983 " Use this option in combination with --show or\n"
26984 " with --error-prefix when you do not want to stop\n"
26985 " a current redirection.\n"
 
 
 
26986 " --plain Use plain text rather than HTML tables with -w\n"
26987 " --show Show output text captured by .testcase or by\n"
26988 " redirecting to \"memory\".\n"
 
 
 
26989 " -w Show the output in a web browser. Output is\n"
26990 " written into a temporary HTML file until the\n"
26991 " redirect ends, then the web browser is launched.\n"
26992 " Query results are shown as HTML tables, unless\n"
26993 " the --plain is used too.\n"
@@ -26726,10 +27011,39 @@
27011 " file in a web browser\n"
27012 " -x Show the output in a spreadsheet. Output is\n"
27013 " written to a temp file as CSV then the spreadsheet\n"
27014 " is launched when\n"
27015 },
27016 { ".check",
27017 "USAGE: .check [OPTIONS] PATTERN\n"
27018 "\n"
27019 "Verify results of commands since the most recent .testcase command.\n"
27020 "Restore output to the console, unless --keep is used.\n"
27021 "\n"
27022 "If PATTERN starts with \"<<ENDMARK\" then the actual pattern is taken from\n"
27023 "subsequent lines of text up to the first line that begins with ENDMARK.\n"
27024 "All pattern lines and the ENDMARK are discarded.\n"
27025 "\n"
27026 "Options:\n"
27027 " --exact Do an exact comparison including leading and\n"
27028 " trailing whitespace.\n"
27029 " --glob Treat PATTERN as a GLOB\n"
27030 " --keep Do not reset the testcase. More .check commands\n"
27031 " will follow.\n"
27032 " --notglob Output should not match PATTERN\n"
27033 " --show Write testcase output to the screen, for debugging.\n"
27034 },
27035 { ".testcase",
27036 "USAGE: .testcase [OPTIONS] NAME\n"
27037 "\n"
27038 "Start a new test case identified by NAME. All output\n"
27039 "through the next \".check\" command is captured for comparison. See the\n"
27040 "\".check\" commandn for additional informatioon.\n"
27041 "\n"
27042 "Options:\n"
27043 " --error-prefix TEXT Change error message prefix text to TEXT\n"
27044 },
27045 };
27046
27047 /*
27048 ** Return a pointer to usage text for zCmd, or NULL if none exists.
27049 */
@@ -26949,10 +27263,56 @@
27263 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
27264 }
27265 return 1;
27266 }
27267 #endif
27268
27269 /*
27270 ** Return the size of the named file in bytes. Or return a negative
27271 ** number if the file does not exist.
27272 */
27273 static sqlite3_int64 fileSize(const char *zFile){
27274 #if defined(_WIN32) || defined(WIN32)
27275 struct _stat64 x;
27276 if( _stat64(zFile, &x)!=0 ) return -1;
27277 return (sqlite3_int64)x.st_size;
27278 #else
27279 struct stat x;
27280 if( stat(zFile, &x)!=0 ) return -1;
27281 return (sqlite3_int64)x.st_size;
27282 #endif
27283 }
27284
27285 /*
27286 ** Return true if zFile is an SQLite database.
27287 **
27288 ** Algorithm:
27289 ** * If the file does not exist -> return false
27290 ** * If the size of the file is not a multiple of 512 -> return false
27291 ** * If sqlite3_open() fails -> return false
27292 ** * if sqlite3_prepare() or sqlite3_step() fails -> return false
27293 ** * Otherwise -> return true
27294 */
27295 static int isDatabaseFile(const char *zFile, int openFlags){
27296 sqlite3 *db = 0;
27297 sqlite3_stmt *pStmt = 0;
27298 int rc;
27299 sqlite3_int64 sz = fileSize(zFile);
27300 if( sz<512 || (sz%512)!=0 ) return 0;
27301 if( sqlite3_open_v2(zFile, &db, openFlags, 0)==SQLITE_OK
27302 && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
27303 ==SQLITE_OK
27304 && sqlite3_step(pStmt)==SQLITE_ROW
27305 ){
27306 rc = 1;
27307 }else{
27308 rc = 0;
27309 }
27310 sqlite3_finalize(pStmt);
27311 sqlite3_close(db);
27312 return rc;
27313 }
27314
27315 /*
27316 ** Try to deduce the type of file for zName based on its content. Return
27317 ** one of the SHELL_OPEN_* constants.
27318 **
@@ -26962,24 +27322,16 @@
27322 ** the type cannot be determined from content.
27323 */
27324 int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
27325 FILE *f;
27326 size_t n;
 
 
27327 int rc = SHELL_OPEN_UNSPEC;
27328 char zBuf[100];
27329 if( access(zName,0)!=0 ) goto database_type_by_name;
27330 if( isDatabaseFile(zName, openFlags) ){
 
 
 
 
27331 rc = SHELL_OPEN_NORMAL;
27332 }
 
 
27333 if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
27334 f = sqlite3_fopen(zName, "rb");
27335 if( f==0 ) goto database_type_by_name;
27336 n = fread(zBuf, 16, 1, f);
27337 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
@@ -27009,10 +27361,37 @@
27361 }else{
27362 rc = SHELL_OPEN_NORMAL;
27363 }
27364 return rc;
27365 }
27366
27367 /*
27368 ** If the text in z[] is the name of a readable file and that file appears
27369 ** to contain SQL text and/or dot-commands, then return true. If z[] is
27370 ** not a file, or if the file is unreadable, or if the file is a database
27371 ** or anything else that is not SQL text and dot-commands, then return false.
27372 **
27373 ** If the bLeaveUninit flag is set, then be sure to leave SQLite in an
27374 ** uninitialized state. This means invoking sqlite3_shutdown() after any
27375 ** SQLite API is used.
27376 **
27377 ** Some amount of guesswork is involved in this decision.
27378 */
27379 static int isScriptFile(const char *z, int bLeaveUninit){
27380 sqlite3_int64 sz = fileSize(z);
27381 if( sz<=0 ) return 0;
27382 if( (sz%512)==0 ){
27383 int rc = isDatabaseFile(z, SQLITE_OPEN_READONLY);
27384 if( bLeaveUninit ){
27385 sqlite3_shutdown();
27386 }
27387 if( rc ) return 0; /* Is a database */
27388 }
27389 if( sqlite3_strlike("%.sql",z,0)==0 ) return 1;
27390 if( sqlite3_strlike("%.txt",z,0)==0 ) return 1;
27391 return 0;
27392 }
27393
27394 #ifndef SQLITE_OMIT_DESERIALIZE
27395 /*
27396 ** Reconstruct an in-memory database using the output from the "dbtotxt"
27397 ** program. Read content from the file in p->aAuxDb[].zDbFilename.
@@ -27655,11 +28034,13 @@
28034 typedef struct ImportCtx ImportCtx;
28035 struct ImportCtx {
28036 const char *zFile; /* Name of the input file */
28037 FILE *in; /* Read the CSV text from this input stream */
28038 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
28039 char *zIn; /* Input text */
28040 char *z; /* Accumulated text for a field */
28041 i64 nUsed; /* Bytes of zIn[] used so far */
28042 i64 n; /* Number of bytes in z */
28043 i64 nAlloc; /* Space allocated for z[] */
28044 int nLine; /* Current line number */
28045 int nRow; /* Number of rows imported */
28046 int nErr; /* Number of errors encountered */
@@ -27675,13 +28056,32 @@
28056 p->xCloser(p->in);
28057 p->in = 0;
28058 }
28059 sqlite3_free(p->z);
28060 p->z = 0;
28061 if( p->zIn ){
28062 sqlite3_free(p->zIn);
28063 p->zIn = 0;
28064 }
28065 }
28066
28067 /* Read a single character of the .import input text. Return EOF
28068 ** at end-of-file.
28069 */
28070 static int import_getc(ImportCtx *p){
28071 if( p->in ){
28072 return fgetc(p->in);
28073 }else if( p->zIn && p->zIn[p->nUsed]!=0 ){
28074 return p->zIn[p->nUsed++];
28075 }else{
28076 return EOF;
28077 }
28078 }
28079
28080 /* Append a single byte to the field value begin constructed
28081 ** in the p->z[] buffer
28082 */
28083 static void import_append_char(ImportCtx *p, int c){
28084 if( p->n+1>=p->nAlloc ){
28085 p->nAlloc += p->nAlloc + 100;
28086 p->z = sqlite3_realloc64(p->z, p->nAlloc);
28087 shell_check_oom(p->z);
@@ -27693,12 +28093,12 @@
28093 ** with the option of having a separator other than ",".
28094 **
28095 ** + Input comes from p->in.
28096 ** + Store results in p->z of length p->n. Space to hold p->z comes
28097 ** from sqlite3_malloc64().
28098 ** + Use p->cColSep as the column separator. The default is ",".
28099 ** + Use p->cRowSep as the row separator. The default is "\n".
28100 ** + Keep track of the line number in p->nLine.
28101 ** + Store the character that terminates the field in p->cTerm. Store
28102 ** EOF on end-of-file.
28103 ** + Report syntax errors on stderr
28104 */
@@ -27705,11 +28105,11 @@
28105 static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
28106 int c;
28107 int cSep = (u8)p->cColSep;
28108 int rSep = (u8)p->cRowSep;
28109 p->n = 0;
28110 c = import_getc(p);
28111 if( c==EOF || seenInterrupt ){
28112 p->cTerm = EOF;
28113 return 0;
28114 }
28115 if( c=='"' ){
@@ -27716,11 +28116,11 @@
28116 int pc, ppc;
28117 int startLine = p->nLine;
28118 int cQuote = c;
28119 pc = ppc = 0;
28120 while( 1 ){
28121 c = import_getc(p);
28122 if( c==rSep ) p->nLine++;
28123 if( c==cQuote ){
28124 if( pc==cQuote ){
28125 pc = 0;
28126 continue;
@@ -27752,24 +28152,24 @@
28152 }else{
28153 /* If this is the first field being parsed and it begins with the
28154 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
28155 if( (c&0xff)==0xef && p->bNotFirst==0 ){
28156 import_append_char(p, c);
28157 c = import_getc(p);
28158 if( (c&0xff)==0xbb ){
28159 import_append_char(p, c);
28160 c = import_getc(p);
28161 if( (c&0xff)==0xbf ){
28162 p->bNotFirst = 1;
28163 p->n = 0;
28164 return csv_read_one_field(p);
28165 }
28166 }
28167 }
28168 while( c!=EOF && c!=cSep && c!=rSep ){
28169 import_append_char(p, c);
28170 c = import_getc(p);
28171 }
28172 if( c==rSep ){
28173 p->nLine++;
28174 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
28175 }
@@ -27783,12 +28183,12 @@
28183 /* Read a single field of ASCII delimited text.
28184 **
28185 ** + Input comes from p->in.
28186 ** + Store results in p->z of length p->n. Space to hold p->z comes
28187 ** from sqlite3_malloc64().
28188 ** + Use p->cColSep as the column separator. The default is "\x1F".
28189 ** + Use p->cRowSep as the row separator. The default is "\x1E".
28190 ** + Keep track of the row number in p->nLine.
28191 ** + Store the character that terminates the field in p->cTerm. Store
28192 ** EOF on end-of-file.
28193 ** + Report syntax errors on stderr
28194 */
@@ -27795,18 +28195,18 @@
28195 static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
28196 int c;
28197 int cSep = (u8)p->cColSep;
28198 int rSep = (u8)p->cRowSep;
28199 p->n = 0;
28200 c = import_getc(p);
28201 if( c==EOF || seenInterrupt ){
28202 p->cTerm = EOF;
28203 return 0;
28204 }
28205 while( c!=EOF && c!=cSep && c!=rSep ){
28206 import_append_char(p, c);
28207 c = import_getc(p);
28208 }
28209 if( c==rSep ){
28210 p->nLine++;
28211 }
28212 p->cTerm = c;
@@ -29721,11 +30121,13 @@
30121
30122 p = sqlite3_recover_init_sql(
30123 pState->db, "main", recoverSqlCb, (void*)pState
30124 );
30125
30126 if( !pState->bSafeMode ){
30127 sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */
30128 }
30129 sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
30130 sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
30131 sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
30132
30133 cli_printf(pState->out, ".dbconfig defensive off\n");
@@ -30105,19 +30507,31 @@
30507 ** USAGE: .import [OPTIONS] FILE TABLE
30508 **
30509 ** Import CSV or similar text from FILE into TABLE. If TABLE does
30510 ** not exist, it is created using the first row of FILE as the column
30511 ** names. If FILE begins with "|" then it is a command that is run
30512 ** and the output from the command is used as the input data. If
30513 ** FILE begins with "<<" followed by a label, then content is read from
30514 ** the script until the first line that matches the label.
30515 **
30516 ** The content of FILE is interpreted using RFC-4180 ("CSV") quoting
30517 ** rules unless the current mode is "ascii" or "tabs" or unless one
30518 ** the --ascii option is used.
30519 **
30520 ** The column and row separators must be single ASCII characters. If
30521 ** multiple characters or a Unicode character are specified for the
30522 ** separators, then only the first byte of the separator is used. Except,
30523 ** if the row separator is \n and the mode is not --ascii, then \r\n is
30524 ** understood as a row separator too.
30525 **
30526 ** Options:
30527 ** --ascii Do not use RFC-4180 quoting. Use \037 and \036
30528 ** as column and row separators on input, unless other
30529 ** delimiters are specified using --colsep and/or --rowsep
30530 ** --colsep CHAR Use CHAR as the column separator.
30531 ** --csv Input is standard RFC-4180 CSV.
30532 ** --rowsep CHAR Use CHAR as the row separator.
30533 ** --schema S When creating TABLE, put it in schema S
30534 ** --skip N Ignore the first N rows of input
30535 ** -v Verbose mode
30536 */
30537 static int dotCmdImport(ShellState *p){
@@ -30129,17 +30543,16 @@
30543 sqlite3_stmt *pStmt = NULL; /* A statement */
30544 int nCol; /* Number of columns in the table */
30545 i64 nByte; /* Number of bytes in an SQL string */
30546 int i, j; /* Loop counters */
30547 int needCommit; /* True to COMMIT or ROLLBACK at end */
 
30548 char *zSql = 0; /* An SQL statement */
30549 ImportCtx sCtx; /* Reader context */
30550 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
30551 int eVerbose = 0; /* Larger for more console output */
30552 i64 nSkip = 0; /* Initial lines to skip */
30553 i64 iLineOffset = 0; /* Offset to the first line of input */
30554 char *zCreate = 0; /* CREATE TABLE statement text */
30555 int rc; /* Result code */
30556
30557 failIfSafeMode(p, "cannot run .import in safe mode");
30558 memset(&sCtx, 0, sizeof(sCtx));
@@ -30165,70 +30578,67 @@
30578 }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
30579 zSchema = azArg[++i];
30580 }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
30581 nSkip = integerValue(azArg[++i]);
30582 }else if( cli_strcmp(z,"-ascii")==0 ){
30583 if( sCtx.cColSep==0 ) sCtx.cColSep = SEP_Unit[0];
30584 if( sCtx.cRowSep==0 ) sCtx.cRowSep = SEP_Record[0];
30585 xRead = ascii_read_one_field;
 
30586 }else if( cli_strcmp(z,"-csv")==0 ){
30587 if( sCtx.cColSep==0 ) sCtx.cColSep = ',';
30588 if( sCtx.cRowSep==0 ) sCtx.cRowSep = '\n';
30589 xRead = csv_read_one_field;
30590 }else if( cli_strcmp(z,"-colsep")==0 ){
30591 if( i==nArg-1 ){
30592 dotCmdError(p, i, "missing argument", 0);
30593 return 1;
30594 }
30595 i++;
30596 sCtx.cColSep = azArg[i][0];
30597 }else if( cli_strcmp(z,"-rowsep")==0 ){
30598 if( i==nArg-1 ){
30599 dotCmdError(p, i, "missing argument", 0);
30600 return 1;
30601 }
30602 i++;
30603 sCtx.cRowSep = azArg[i][0];
30604 }else{
30605 dotCmdError(p, i, "unknown option", 0);
30606 return 1;
30607 }
30608 }
30609 if( zTable==0 ){
30610 dotCmdError(p, nArg, 0, "Missing %s argument\n",
30611 zFile==0 ? "FILE" : "TABLE");
30612 return 1;
30613 }
30614 seenInterrupt = 0;
30615 open_db(p, 0);
30616 if( sCtx.cColSep==0 ){
30617 if( p->mode.spec.zColumnSep && p->mode.spec.zColumnSep[0]!=0 ){
30618 sCtx.cColSep = p->mode.spec.zColumnSep[0];
30619 }else{
30620 sCtx.cColSep = ',';
30621 }
30622 }
30623 if( (sCtx.cColSep & 0x80)!=0 ){
30624 eputz("Error: .import column separator must be ASCII\n");
30625 return 1;
30626 }
30627 if( sCtx.cRowSep==0 ){
30628 if( p->mode.spec.zRowSep && p->mode.spec.zRowSep[0]!=0 ){
30629 sCtx.cRowSep = p->mode.spec.zRowSep[0];
30630 }else{
30631 sCtx.cRowSep = '\n';
30632 }
30633 }
30634 if( sCtx.cRowSep=='\r' && xRead!=ascii_read_one_field ){
30635 sCtx.cRowSep = '\n';
30636 }
30637 if( (sCtx.cRowSep & 0x80)!=0 ){
30638 eputz("Error: .import row separator must be ASCII\n");
30639 return 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30640 }
30641 sCtx.zFile = zFile;
30642 sCtx.nLine = 1;
30643 if( sCtx.zFile[0]=='|' ){
30644 #ifdef SQLITE_OMIT_POPEN
@@ -30237,19 +30647,58 @@
30647 #else
30648 sCtx.in = sqlite3_popen(sCtx.zFile+1, "r");
30649 sCtx.zFile = "<pipe>";
30650 sCtx.xCloser = pclose;
30651 #endif
30652 }else if( sCtx.zFile[0]=='<' && sCtx.zFile[1]=='<' && sCtx.zFile[2]!=0 ){
30653 /* Input text comes from subsequent lines of script until the zFile
30654 ** delimiter */
30655 int nEndMark = strlen30(zFile)-2;
30656 char *zEndMark = &zFile[2];
30657 sqlite3_str *pContent = sqlite3_str_new(p->db);
30658 int ckEnd = 1;
30659 i64 iStart = p->lineno;
30660 char zLine[2000];
30661 sCtx.zFile = p->zInFile;
30662 sCtx.nLine = p->lineno+1;
30663 iLineOffset = p->lineno;
30664 while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
30665 if( ckEnd && cli_strncmp(zLine,zEndMark,nEndMark)==0 ){
30666 ckEnd = 2;
30667 if( strchr(zLine,'\n') ) p->lineno++;
30668 break;
30669 }
30670 if( strchr(zLine,'\n') ){
30671 p->lineno++;
30672 ckEnd = 1;
30673 }else{
30674 ckEnd = 0;
30675 }
30676 sqlite3_str_appendall(pContent, zLine);
30677 }
30678 sCtx.zIn = sqlite3_str_finish(pContent);
30679 if( sCtx.zIn==0 ){
30680 sCtx.zIn = sqlite3_mprintf("");
30681 }
30682 if( ckEnd<2 ){
30683 i64 savedLn = p->lineno;
30684 p->lineno = iStart;
30685 dotCmdError(p, 0, 0,"Content terminator \"%s\" not found.",zEndMark);
30686 p->lineno = savedLn;
30687 import_cleanup(&sCtx);
30688 return 1;
30689 }
30690 }else{
30691 sCtx.in = sqlite3_fopen(sCtx.zFile, "rb");
30692 sCtx.xCloser = fclose;
30693 }
30694 if( sCtx.in==0 && sCtx.zIn==0 ){
30695 dotCmdError(p, 0, 0, "cannot open \"%s\"", zFile);
30696 import_cleanup(&sCtx);
30697 return 1;
30698 }
30699 if( eVerbose>=1 ){
30700 char zSep[2];
30701 zSep[1] = 0;
30702 zSep[0] = sCtx.cColSep;
30703 cli_puts("Column separator ", p->out);
30704 output_c_string(p->out, zSep);
@@ -30402,10 +30851,14 @@
30851 if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){
30852 z = "";
30853 }
30854 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
30855 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
30856 if( i==0 && (strcmp(z,"\n")==0 || strcmp(z,"\r\n")==0) ){
30857 /* Ignore trailing \n or \r\n when some other row separator */
30858 break;
30859 }
30860 cli_printf(stderr,"%s:%d: expected %d columns but found %d"
30861 " - filling the rest with NULL\n",
30862 sCtx.zFile, startLine, nCol, i+1);
30863 i += 2;
30864 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
@@ -30425,10 +30878,11 @@
30878 rc = sqlite3_reset(pStmt);
30879 if( rc!=SQLITE_OK ){
30880 cli_printf(stderr,"%s:%d: INSERT failed: %s\n",
30881 sCtx.zFile, startLine, sqlite3_errmsg(p->db));
30882 sCtx.nErr++;
30883 if( bail_on_error ) break;
30884 }else{
30885 sCtx.nRow++;
30886 }
30887 }
30888 }while( sCtx.cTerm!=EOF );
@@ -30437,13 +30891,13 @@
30891 sqlite3_finalize(pStmt);
30892 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
30893 if( eVerbose>0 ){
30894 cli_printf(p->out,
30895 "Added %d rows with %d errors using %d lines of input\n",
30896 sCtx.nRow, sCtx.nErr, sCtx.nLine-1-iLineOffset);
30897 }
30898 return sCtx.nErr ? 1 : 0;
30899 }
30900
30901
30902 /*
30903 ** This function computes what to show the user about the configured
@@ -30508,10 +30962,11 @@
30962 ** meaning "left", "centered", and "right", with
30963 ** one letter per column starting from the left.
30964 ** Unspecified alignment defaults to 'L'.
30965 ** --blob-quote ARG ARG can be "auto", "text", "sql", "hex", "tcl",
30966 ** "json", or "size". Default is "auto".
30967 ** --border on|off Show outer border on "box" and "table" modes.
30968 ** --charlimit N Set the maximum number of output characters to
30969 ** show for any single SQL value to N. Longer values
30970 ** truncated. Zero means "no limit".
30971 ** --colsep STRING Use STRING as the column separator
30972 ** --escape ESC Enable/disable escaping of control characters
@@ -30519,19 +30974,22 @@
30974 ** or "symbol".
30975 ** --linelimit N Set the maximum number of output lines to show for
30976 ** any single SQL value to N. Longer values are
30977 ** truncated. Zero means "no limit". Only works
30978 ** in "line" mode and in columnar modes.
30979 ** --limits L,C,T Shorthand for "--linelimit L --charlimit C
30980 ** --titlelimit T". The ",T" can be omitted in which
30981 ** case the --titlelimit is unchanged. The argument
30982 ** can also be "off" to mean "0,0,0" or "on" to
30983 ** mean "5,300,20".
30984 ** --list List available modes
30985 ** --null STRING Render SQL NULL values as the given string
30986 ** --once Setting changes to the right are reverted after
30987 ** the next SQL command.
30988 ** --quote ARG Enable/disable quoting of text. ARG can be
30989 ** "off", "on", "sql", "relaxed", "csv", "html",
30990 ** "tcl", or "json". "off" means show the text as-is.
30991 ** "on" is an alias for "sql".
30992 ** --reset Changes all mode settings back to their default.
30993 ** --rowsep STRING Use STRING as the row separator
30994 ** --sw|--screenwidth N Declare the screen width of the output device
30995 ** to be N characters. An attempt may be made to
@@ -30542,10 +31000,11 @@
31000 ** --tag NAME Save mode to the left as NAME.
31001 ** --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON.
31002 ** --title ARG Whether or not to show column headers, and if so
31003 ** how to encode them. ARG can be "off", "on",
31004 ** "sql", "csv", "html", "tcl", or "json".
31005 ** --titlelimit N Limit the length of column titles to N characters.
31006 ** -v|--verbose Verbose output
31007 ** --widths LIST Set the columns widths for columnar modes. The
31008 ** argument is a list of integers, one for each
31009 ** column. A "0" width means use a dynamic width
31010 ** based on the actual width of data. If there are
@@ -30626,21 +31085,31 @@
31085 ** Must match QRF_BLOB_xxxx values. See also tag-20251124a */
31086 if( k>=0 ){
31087 p->mode.spec.eBlob = k & 0xff;
31088 }
31089 chng = 1;
31090 }else if( optionMatch(z,"border") ){
31091 if( (++i)>=nArg ){
31092 dotCmdError(p, i-1, "missing argument", 0);
31093 return 1;
31094 }
31095 k = pickStr(azArg[i], 0, "auto", "off", "on", "");
31096 if( k>=0 ){
31097 p->mode.spec.bBorder = k & 0x3;
31098 }
31099 chng = 1;
31100 }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","-titlelimit","")) ){
31101 int w; /* 0 1 */
31102 if( i+1>=nArg ){
31103 dotCmdError(p, i, "missing argument", 0);
31104 return 1;
31105 }
31106 w = integerValue(azArg[++i]);
31107 switch( k ){
31108 case 0: p->mode.spec.nCharLimit = w; break;
31109 case 1: p->mode.spec.nLineLimit = w; break;
31110 default: p->mode.spec.nTitleLimit = w; break;
31111 }
31112 chng = 1;
31113 }else if( 0<=(k=pickStr(z,0,"-tablename","-rowsep","-colsep","-null","")) ){
31114 /* 0 1 2 3 */
31115 if( i+1>=nArg ){
@@ -30675,25 +31144,28 @@
31144 dotCmdError(p, i-1, "missing argument", 0);
31145 return 1;
31146 }
31147 k = pickStr(azArg[i],0,"on","off","");
31148 if( k==0 ){
31149 p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
31150 p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
31151 p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
31152 }else if( k==1 ){
31153 p->mode.spec.nLineLimit = 0;
31154 p->mode.spec.nCharLimit = 0;
31155 p->mode.spec.nTitleLimit = 0;
31156 }else{
31157 int L, C, T = 0;
31158 int nNum = sscanf(azArg[i], "%d,%d,%d", &L, &C, &T);
31159 if( nNum<2 || L<0 || C<0 || T<0){
31160 dotCmdError(p, i, "bad argument", "Should be \"L,C,T\" where L, C"
31161 " and T are unsigned integers");
31162 return 1;
31163 }
31164 p->mode.spec.nLineLimit = L;
31165 p->mode.spec.nCharLimit = C;
31166 if( nNum==3 ) p->mode.spec.nTitleLimit = T;
31167 }
31168 chng = 1;
31169 }else if( optionMatch(z,"list") ){
31170 int ii;
31171 cli_puts("available modes:", p->out);
@@ -30726,13 +31198,14 @@
31198 ** how to set quoting. */
31199 i++;
31200 if( (k = pickStr(azArg[i],0,"no","yes","0","1",""))>=0 ){
31201 k &= 1; /* 0 for "off". 1 for "on". */
31202 }else{
31203 char *zErr = 0;
31204 k = pickStr(azArg[i],&zErr,
31205 "off","on","sql","csv","html","tcl","json","relaxed","");
31206 /* 0 1 2 3 4 5 6 7 */
31207 if( k<0 ){
31208 dotCmdError(p, i, "unknown", "%z", zErr);
31209 return 1;
31210 }
31211 }
@@ -30757,10 +31230,13 @@
31230 p->mode.spec.eText = QRF_TEXT_Tcl;
31231 break;
31232 case 6: /* json */
31233 p->mode.spec.eText = QRF_TEXT_Json;
31234 break;
31235 case 7: /* relaxed */
31236 p->mode.spec.eText = QRF_TEXT_Relaxed;
31237 break;
31238 default: /* off */
31239 p->mode.spec.eText = QRF_TEXT_Plain;
31240 break;
31241 }
31242 chng = 1;
@@ -30832,10 +31308,11 @@
31308 if( k<0 ){
31309 dotCmdError(p, i, "bad --titles value","%z", zErr);
31310 return 1;
31311 }
31312 p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No;
31313 p->mode.mFlags &= ~MFLG_HDR;
31314 p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr;
31315 chng = 1;
31316 }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){
31317 int nWidth = 0;
31318 short int *aWidth;
@@ -30847,16 +31324,16 @@
31324 zW = azArg[++i];
31325 /* Every width value takes at least 2 bytes in the input string to
31326 ** specify, so strlen(zW) bytes should be plenty of space to hold the
31327 ** result. */
31328 aWidth = malloc( strlen(zW) );
31329 while( IsSpace(zW[0]) ) zW++;
31330 while( zW[0] ){
31331 int w = 0;
31332 int nDigit = 0;
31333 k = zW[0]=='-' && IsDigit(zW[1]);
31334 while( IsDigit(zW[k]) ){
31335 w = w*10 + zW[k] - '0';
31336 if( w>QRF_MAX_WIDTH ){
31337 dotCmdError(p,i+1,"width too big",
31338 "Maximum column width is %d", QRF_MAX_WIDTH);
31339 free(aWidth);
@@ -30873,11 +31350,11 @@
31350 }
31351 if( zW[0]=='-' ) w = -w;
31352 aWidth[nWidth++] = w;
31353 zW += k;
31354 if( zW[0]==',' ) zW++;
31355 while( IsSpace(zW[0]) ) zW++;
31356 }
31357 free(p->mode.spec.aWidth);
31358 p->mode.spec.aWidth = aWidth;
31359 p->mode.spec.nWidth = nWidth;
31360 chng = 1;
@@ -30928,39 +31405,52 @@
31405 unsigned char a = p->mode.spec.aAlign[ii];
31406 sqlite3_str_appendchar(pDesc, 1, "LLCR"[a&3]);
31407 }
31408 sqlite3_str_append(pDesc, "\"", 1);
31409 }
31410 if( bAll
31411 || (p->mode.spec.bBorder==QRF_No) != ((pI->mFlg&1)!=0)
31412 ){
31413 sqlite3_str_appendf(pDesc," --border %s",
31414 p->mode.spec.bBorder==QRF_No ? "off" : "on");
31415 }
31416 if( bAll || p->mode.spec.eBlob!=QRF_BLOB_Auto ){
31417 const char *azBQuote[] =
31418 { "auto", "text", "sql", "hex", "tcl", "json", "size" };
31419 /* 0 1 2 3 4 5 6
31420 ** Must match QRF_BLOB_xxxx values. See all instances of tag-20251124a */
31421 u8 e = p->mode.spec.eBlob;
31422 sqlite3_str_appendf(pDesc, " --blob-quote %s", azBQuote[e]);
31423 }
 
 
 
31424 zSetting = aModeStr[pI->eCSep];
31425 if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zColumnSep)!=0) ){
31426 sqlite3_str_appendf(pDesc, " --colsep ");
31427 append_c_string(pDesc, p->mode.spec.zColumnSep);
31428 }
31429 if( bAll || p->mode.spec.eEsc!=QRF_Auto ){
31430 sqlite3_str_appendf(pDesc, " --escape %s",qrfEscNames[p->mode.spec.eEsc]);
31431 }
31432 if( bAll
31433 || (p->mode.spec.nLineLimit>0 && pI->eCx>0)
31434 || p->mode.spec.nCharLimit>0
31435 || (p->mode.spec.nTitleLimit>0 && pI->eCx>0)
31436 ){
31437 if( p->mode.spec.nLineLimit==0
31438 && p->mode.spec.nCharLimit==0
31439 && p->mode.spec.nTitleLimit==0
31440 ){
31441 sqlite3_str_appendf(pDesc, " --limits off");
31442 }else if( p->mode.spec.nLineLimit==DFLT_LINE_LIMIT
31443 && p->mode.spec.nCharLimit==DFLT_CHAR_LIMIT
31444 && p->mode.spec.nTitleLimit==DFLT_TITLE_LIMIT
31445 ){
31446 sqlite3_str_appendf(pDesc, " --limits on");
31447 }else{
31448 sqlite3_str_appendf(pDesc, " --limits %d,%d,%d",
31449 p->mode.spec.nLineLimit, p->mode.spec.nCharLimit,
31450 p->mode.spec.nTitleLimit);
31451 }
 
 
 
31452 }
31453 zSetting = aModeStr[pI->eNull];
31454 if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zNull)!=0) ){
31455 sqlite3_str_appendf(pDesc, " --null ");
31456 append_c_string(pDesc, p->mode.spec.zNull);
@@ -30977,13 +31467,13 @@
31467 }
31468 if( bAll
31469 || (pI->eCx && (p->mode.spec.nScreenWidth>0 || p->mode.bAutoScreenWidth))
31470 ){
31471 if( p->mode.bAutoScreenWidth ){
31472 sqlite3_str_appendall(pDesc, " --sw auto");
31473 }else{
31474 sqlite3_str_appendf(pDesc," --sw %d",
31475 p->mode.spec.nScreenWidth);
31476 }
31477 }
31478 if( bAll || p->mode.eMode==MODE_Insert ){
31479 sqlite3_str_appendf(pDesc," --tablename ");
@@ -31023,11 +31513,11 @@
31513 sqlite3_str_appendf(pDesc, " --wrap %d", p->mode.spec.nWrap);
31514 }
31515 if( !bAll ) sqlite3_str_append(pDesc, " --ww", 5);
31516 }
31517 zDesc = sqlite3_str_finish(pDesc);
31518 cli_printf(p->out, ".mode %s\n", zDesc);
31519 fflush(p->out);
31520 sqlite3_free(zDesc);
31521 }
31522 return 0;
31523 }
@@ -31047,23 +31537,17 @@
31537 ** --bom Prepend a byte-order mark to the output
31538 ** -e Accumulate output in a temporary text file then
31539 ** launch a text editor when the redirection ends.
31540 ** --error-prefix X Use X as the left-margin prefix for error messages.
31541 ** Set to an empty string to restore the default.
31542 ** --keep Keep redirecting output to its current destination.
31543 ** Use this option in combination with --show or
31544 ** with --error-prefix when you do not want to stop
31545 ** a current redirection.
 
 
 
31546 ** --plain Use plain text rather than HTML tables with -w
31547 ** --show Show output text captured by .testcase or by
31548 ** redirecting to "memory".
 
 
 
31549 ** -w Show the output in a web browser. Output is
31550 ** written into a temporary HTML file until the
31551 ** redirect ends, then the web browser is launched.
31552 ** Query results are shown as HTML tables, unless
31553 ** the --plain is used too.
@@ -31101,13 +31585,11 @@
31585 char *zFile = 0; /* The FILE argument */
31586 int i; /* Loop counter */
31587 int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */
31588 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */
31589 int bPlain = 0; /* --plain option */
31590 int bKeep = 0; /* Keep redirecting */
 
 
31591 static const char *zBomUtf8 = "\357\273\277";
31592 const char *zBom = 0;
31593 char c = azArg[0][0];
31594 int n = strlen30(azArg[0]);
31595
@@ -31129,36 +31611,21 @@
31611 zBom = zBomUtf8;
31612 }else if( cli_strcmp(z,"-plain")==0 ){
31613 bPlain = 1;
31614 }else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
31615 && (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
31616 if( bKeep || eMode ){
31617 dotCmdError(p, i, "incompatible with prior options",0);
31618 goto dotCmdOutput_error;
31619 }
31620 eMode = z[1];
 
 
31621 }else if( cli_strcmp(z,"-show")==0 ){
31622 if( cli_output_capture ){
31623 sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
31624 }
31625 }else if( cli_strcmp(z,"-keep")==0 ){
31626 bKeep = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31627 }else if( optionMatch(z,"error-prefix") ){
31628 if( i+1>=nArg ){
31629 dotCmdError(p, i, "missing argument", 0);
31630 return 1;
31631 }
@@ -31169,11 +31636,11 @@
31636 dotCmdError(p, i, "unknown option", 0);
31637 sqlite3_free(zFile);
31638 return 1;
31639 }
31640 }else if( zFile==0 && eMode==0 ){
31641 if( bKeep ){
31642 dotCmdError(p, i, "incompatible with prior options",0);
31643 goto dotCmdOutput_error;
31644 }
31645 if( cli_strcmp(z, "memory")==0 && bOnce ){
31646 dotCmdError(p, 0, "cannot redirect to \"memory\"", 0);
@@ -31205,53 +31672,10 @@
31672 if( bOnce ){
31673 p->nPopOutput = 2;
31674 }else{
31675 p->nPopOutput = 0;
31676 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31677 if( !bKeep ) output_reset(p);
31678 #ifndef SQLITE_NOHAVE_SYSTEM
31679 if( eMode=='e' || eMode=='x' || eMode=='w' ){
31680 p->doXdgOpen = 1;
31681 modePush(p);
@@ -31328,10 +31752,199 @@
31752
31753 dotCmdOutput_error:
31754 sqlite3_free(zFile);
31755 return 1;
31756 }
31757
31758 /*
31759 ** DOT-COMMAND: .check
31760 ** USAGE: .check [OPTIONS] PATTERN
31761 **
31762 ** Verify results of commands since the most recent .testcase command.
31763 ** Restore output to the console, unless --keep is used.
31764 **
31765 ** If PATTERN starts with "<<ENDMARK" then the actual pattern is taken from
31766 ** subsequent lines of text up to the first line that begins with ENDMARK.
31767 ** All pattern lines and the ENDMARK are discarded.
31768 **
31769 ** Options:
31770 ** --exact Do an exact comparison including leading and
31771 ** trailing whitespace.
31772 ** --glob Treat PATTERN as a GLOB
31773 ** --keep Do not reset the testcase. More .check commands
31774 ** will follow.
31775 ** --notglob Output should not match PATTERN
31776 ** --show Write testcase output to the screen, for debugging.
31777 */
31778 static int dotCmdCheck(ShellState *p){
31779 int nArg = p->dot.nArg; /* Number of arguments */
31780 char **azArg = p->dot.azArg; /* Text of the arguments */
31781 int i; /* Loop counter */
31782 int k; /* Result of pickStr() */
31783 char *zTest; /* Textcase result */
31784 int bKeep = 0; /* --keep option */
31785 char *zCheck = 0; /* PATTERN argument */
31786 char *zPattern = 0; /* Actual test pattern */
31787 int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --exact */
31788 int isOk; /* True if results are OK */
31789 sqlite3_int64 iStart = p->lineno; /* Line number of .check statement */
31790
31791 if( p->zTestcase[0]==0 ){
31792 dotCmdError(p, 0, "no .testcase is active", 0);
31793 return 1;
31794 }
31795 for(i=1; i<nArg; i++){
31796 char *z = azArg[i];
31797 if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++;
31798 if( cli_strcmp(z,"-keep")==0 ){
31799 bKeep = 1;
31800 }else if( cli_strcmp(z,"-show")==0 ){
31801 if( cli_output_capture ){
31802 sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
31803 }
31804 bKeep = 1;
31805 }else if( z[0]=='-'
31806 && (k = pickStr(&z[1],0,"glob","notglob","exact",""))>=0
31807 ){
31808 if( eCheck && eCheck!=k+1 ){
31809 dotCmdError(p, i, "incompatible with prior options",0);
31810 return 1;
31811 }
31812 eCheck = k+1;
31813 }else if( zCheck ){
31814 dotCmdError(p, i, "unknown option", 0);
31815 return 1;
31816 }else{
31817 zCheck = azArg[i];
31818 }
31819 }
31820 if( zCheck==0 ){
31821 dotCmdError(p, 0, "no PATTERN specified", 0);
31822 return 1;
31823 }
31824 if( cli_output_capture && sqlite3_str_length(cli_output_capture) ){
31825 zTest = sqlite3_str_value(cli_output_capture);
31826 shell_check_oom(zTest);
31827 }else{
31828 zTest = "";
31829 }
31830 p->nTestRun++;
31831 if( zCheck[0]=='<' && zCheck[1]=='<' && zCheck[2]!=0 ){
31832 int nCheck = strlen30(zCheck);
31833 sqlite3_str *pPattern = sqlite3_str_new(p->db);
31834 char zLine[2000];
31835 while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
31836 if( strchr(zLine,'\n') ) p->lineno++;
31837 if( cli_strncmp(&zCheck[2],zLine,nCheck-2)==0 ) break;
31838 sqlite3_str_appendall(pPattern, zLine);
31839 }
31840 zPattern = sqlite3_str_finish(pPattern);
31841 if( zPattern==0 ){
31842 zPattern = sqlite3_mprintf("");
31843 }
31844 }else{
31845 zPattern = zCheck;
31846 }
31847 shell_check_oom(zPattern);
31848 switch( eCheck ){
31849 case 1: {
31850 char *zGlob = sqlite3_mprintf("*%s*", zPattern);
31851 isOk = testcase_glob(zGlob, zTest)!=0;
31852 sqlite3_free(zGlob);
31853 break;
31854 }
31855 case 2: {
31856 char *zGlob = sqlite3_mprintf("*%s*", zPattern);
31857 isOk = testcase_glob(zGlob, zTest)==0;
31858 sqlite3_free(zGlob);
31859 break;
31860 }
31861 case 3: {
31862 isOk = cli_strcmp(zTest,zPattern)==0;
31863 break;
31864 }
31865 default: {
31866 /* Skip leading and trailing \n and \r on both pattern and test output */
31867 const char *z1 = zPattern;
31868 const char *z2 = zTest;
31869 size_t n1, n2;
31870 while( z1[0]=='\n' || z1[0]=='\r' ) z1++;
31871 n1 = strlen(z1);
31872 while( n1>0 && (z1[n1-1]=='\n' || z1[n1-1]=='\r') ) n1--;
31873 while( z2[0]=='\n' || z2[0]=='\r' ) z2++;
31874 n2 = strlen(z2);
31875 while( n2>0 && (z2[n2-1]=='\n' || z2[n2-1]=='\r') ) n2--;
31876 isOk = n1==n2 && memcmp(z1,z2,n1)==0;
31877 break;
31878 }
31879 }
31880 if( !isOk ){
31881 sqlite3_fprintf(stderr,
31882 "%s:%lld: .check failed for testcase %s\n",
31883 p->zInFile, iStart, p->zTestcase);
31884 p->nTestErr++;
31885 sqlite3_fprintf(stderr, "Expected: [%s]\n", zPattern);
31886 sqlite3_fprintf(stderr, "Got: [%s]\n", zTest);
31887 }
31888 if( zPattern!=zCheck ){
31889 sqlite3_free(zPattern);
31890 }
31891 if( !bKeep ){
31892 output_reset(p);
31893 p->zTestcase[0] = 0;
31894 }
31895 return 0;
31896 }
31897
31898 /*
31899 ** DOT-COMMAND: .testcase
31900 ** USAGE: .testcase [OPTIONS] NAME
31901 **
31902 ** Start a new test case identified by NAME. All output
31903 ** through the next ".check" command is captured for comparison. See the
31904 ** ".check" commandn for additional informatioon.
31905 **
31906 ** Options:
31907 ** --error-prefix TEXT Change error message prefix text to TEXT
31908 */
31909 static int dotCmdTestcase(ShellState *p){
31910 int nArg = p->dot.nArg; /* Number of arguments */
31911 char **azArg = p->dot.azArg; /* Text of the arguments */
31912 int i; /* Loop counter */
31913 const char *zName = 0; /* Testcase name */
31914
31915 for(i=1; i<nArg; i++){
31916 char *z = azArg[i];
31917 if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++;
31918 if( optionMatch(z,"error-prefix") ){
31919 if( i+1>=nArg ){
31920 dotCmdError(p, i, "missing argument", 0);
31921 return 1;
31922 }
31923 free(p->zErrPrefix);
31924 i++;
31925 p->zErrPrefix = azArg[i][0]==0 ? 0 : strdup(azArg[i]);
31926 }else if( zName ){
31927 dotCmdError(p, i, "unknown option", 0);
31928 return 1;
31929 }else{
31930 zName = azArg[i];
31931 }
31932 }
31933 output_reset(p);
31934 if( cli_output_capture ){
31935 sqlite3_str_free(cli_output_capture);
31936 }
31937 cli_output_capture = sqlite3_str_new(0);
31938 if( zName ){
31939 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", zName);
31940 }else{
31941 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s:%lld",
31942 p->zInFile, p->lineno);
31943 }
31944 return 0;
31945 }
31946
31947 /*
31948 ** Enlarge the space allocated in p->dot so that it can hold more
31949 ** than nArg parsed command-line arguments.
31950 */
@@ -31360,11 +31973,11 @@
31973 free(p->dot.zCopy);
31974 z = p->dot.zCopy = strdup(zLine);
31975 shell_check_oom(z);
31976 szLine = strlen(z);
31977 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31978 if( szLine>0 && z[szLine-1]==';' ){
31979 szLine--;
31980 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31981 }
31982 z[szLine] = 0;
31983 parseDotRealloc(p, 2);
@@ -31580,35 +32193,17 @@
32193 eputz("Usage: .changes on|off\n");
32194 rc = 1;
32195 }
32196 }else
32197
 
32198 /* Cancel output redirection, if it is currently set (by .testcase)
32199 ** Then read the content of the testcase-out.txt file and compare against
32200 ** azArg[1]. If there are differences, report an error and exit.
32201 */
32202 if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
32203 rc = dotCmdCheck(p);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32204 }else
 
32205
32206 #ifndef SQLITE_SHELL_FIDDLE
32207 if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
32208 failIfSafeMode(p, "cannot run .clone in safe mode");
32209 if( nArg==2 ){
@@ -32187,10 +32782,11 @@
32782 }else
32783
32784 if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
32785 if( nArg==2 ){
32786 p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No;
32787 p->mode.mFlags |= MFLG_HDR;
32788 p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr;
32789 }else{
32790 eputz("Usage: .headers on|off\n");
32791 rc = 1;
32792 }
@@ -32240,14 +32836,14 @@
32836 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
32837 goto meta_command_exit;
32838 }
32839 zSql = sqlite3_mprintf(
32840 "SELECT rootpage, 0 FROM sqlite_schema"
32841 " WHERE type='index' AND lower(name)=lower('%q')"
32842 "UNION ALL "
32843 "SELECT rootpage, 1 FROM sqlite_schema"
32844 " WHERE type='table' AND lower(name)=lower('%q')"
32845 " AND sql LIKE '%%without%%rowid%%'",
32846 azArg[1], azArg[1]
32847 );
32848 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
32849 sqlite3_free(zSql);
@@ -32401,13 +32997,14 @@
32997 goto meta_command_exit;
32998 }
32999 if( nArg==3 ){
33000 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
33001 (int)integerValue(azArg[2]));
33002 }else{
33003 cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
33004 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
33005 }
 
 
33006 }
33007 }else
33008
33009 if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
33010 open_db(p, 0);
@@ -32493,21 +33090,23 @@
33090 int iName = 1; /* Index in azArg[] of the filename */
33091 int newFlag = 0; /* True to delete file before opening */
33092 int openMode = SHELL_OPEN_UNSPEC;
33093 int openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
33094
33095 if( p->bSafeMode ) openFlags = SQLITE_OPEN_READONLY;
33096
33097 /* Check for command-line arguments */
33098 for(iName=1; iName<nArg; iName++){
33099 const char *z = azArg[iName];
33100 #ifndef SQLITE_SHELL_FIDDLE
33101 if( optionMatch(z,"new") ){
33102 newFlag = 1;
33103 #ifdef SQLITE_HAVE_ZLIB
33104 }else if( optionMatch(z, "zip") && !p->bSafeMode ){
33105 openMode = SHELL_OPEN_ZIPFILE;
33106 #endif
33107 }else if( optionMatch(z, "append") && !p->bSafeMode ){
33108 openMode = SHELL_OPEN_APPENDVFS;
33109 }else if( optionMatch(z, "readonly") ){
33110 openFlags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
33111 openFlags |= SQLITE_OPEN_READONLY;
33112 }else if( optionMatch(z, "exclusive") ){
@@ -32950,21 +33549,22 @@
33549 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
33550 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
33551 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
33552 if( isSchema ){
33553 cli_printf(p->out,
33554 "CREATE TABLE %ssqlite_schema (\n"
33555 " type text,\n"
33556 " name text,\n"
33557 " tbl_name text,\n"
33558 " rootpage integer,\n"
33559 " sql text\n"
33560 ");\n",
33561 sqlite3_strlike("sqlite_t%",zName,0)==0 ? "temp." : ""
33562 );
33563 }
33564 }
33565 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
 
33566 if( rc ){
33567 shellDatabaseError(p->db);
33568 sqlite3_finalize(pStmt);
33569
33570 rc = 1;
@@ -32972,11 +33572,11 @@
33572 }
33573 pSql = sqlite3_str_new(p->db);
33574 sqlite3_str_appendf(pSql, "SELECT sql FROM", 0);
33575 iSchema = 0;
33576 while( sqlite3_step(pStmt)==SQLITE_ROW ){
33577 const char *zDb = (const char*)sqlite3_column_text(pStmt, 1);
33578 char zScNum[30];
33579 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
33580 sqlite3_str_appendall(pSql, zDiv);
33581 zDiv = " UNION ALL ";
33582 if( sqlite3_stricmp(zDb, "main")==0 ){
@@ -32992,11 +33592,12 @@
33592 " AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname",
33593 ++iSchema, zDb);
33594 sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb);
33595 }
33596 sqlite3_finalize(pStmt);
33597 #if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) \
33598 && !defined(SQLITE_OMIT_VIRTUALTABLE)
33599 if( zName ){
33600 sqlite3_str_appendall(pSql,
33601 " UNION ALL SELECT shell_module_schema(name),"
33602 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list");
33603 }
@@ -33016,11 +33617,11 @@
33617 }else{
33618 sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName);
33619 }
33620 }
33621 if( bNoSystemTabs ){
33622 sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ");
33623 }
33624 sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid");
33625 if( bDebug ){
33626 cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql));
33627 }else{
@@ -33734,25 +34335,15 @@
34335 sqlite3_str_free(pSql);
34336 modePop(p);
34337 if( rc ) return shellDatabaseError(p->db);
34338 }else
34339
34340 /* Set the p->zTestcase name and begin redirecting output into
34341 ** the cli_output_capture sqlite3_str */
34342 if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
34343 rc = dotCmdTestcase(p);
 
 
 
 
 
 
 
 
 
34344 }else
 
34345
34346 #ifndef SQLITE_UNTESTABLE
34347 if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
34348 static const struct {
34349 const char *zCtrlName; /* Name of a test-control option */
@@ -35068,11 +35659,10 @@
35659 " -bail stop after hitting an error\n"
35660 " -batch force batch I/O\n"
35661 " -box set output mode to 'box'\n"
35662 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
35663 " -column set output mode to 'column'\n"
 
35664 " -csv set output mode to 'csv'\n"
35665 #if !defined(SQLITE_OMIT_DESERIALIZE)
35666 " -deserialize open the database using sqlite3_deserialize()\n"
35667 #endif
35668 " -echo print inputs before execution\n"
@@ -35152,15 +35742,10 @@
35742 /*
35743 ** Initialize the state information in data
35744 */
35745 static void main_init(ShellState *p) {
35746 memset(p, 0, sizeof(*p));
 
 
 
 
 
35747 p->pAuxDb = &p->aAuxDb[0];
35748 p->shellFlgs = SHFLG_Lookaside;
35749 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p);
35750 #if !defined(SQLITE_SHELL_FIDDLE)
35751 verify_uninitialized();
@@ -35174,22 +35759,18 @@
35759 /*
35760 ** Output text to the console in a font that attracts extra attention.
35761 */
35762 #if defined(_WIN32) || defined(WIN32)
35763 static void printBold(const char *zText){
 
35764 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
35765 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
35766 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
35767 SetConsoleTextAttribute(out,
35768 FOREGROUND_RED|FOREGROUND_INTENSITY
35769 );
 
35770 sputz(stdout, zText);
 
35771 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
 
35772 }
35773 #else
35774 static void printBold(const char *zText){
35775 cli_printf(stdout, "\033[1m%s\033[0m", zText);
35776 }
@@ -35219,29 +35800,65 @@
35800 cli_puts(z, p->out);
35801 fflush(p->out);
35802 return 1;
35803 }
35804
35805 /* Alternative name to the entry point for Fiddle */
 
 
 
 
 
 
 
 
35806 #ifdef SQLITE_SHELL_FIDDLE
35807 # define main fiddle_main
35808 #endif
35809
35810 /* Use the wmain() entry point on Windows. Translate arguments to
35811 ** UTF8, then invoke the traditional main() entry point which is
35812 ** renamed using a #define to utf8_main() .
35813 */
35814 #if defined(_WIN32) && !defined(main)
35815 # define main utf8_main /* Rename entry point to utf_main() */
35816 int SQLITE_CDECL utf8_main(int,char**); /* Forward declaration */
35817 int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
35818 int rc, i;
35819 char **argv = malloc( sizeof(char*) * (argc+1) );
35820 char **orig = argv;
35821 if( argv==0 ){
35822 fprintf(stderr, "malloc failed\n");
35823 exit(1);
35824 }
35825 for(i=0; i<argc; i++){
35826 int nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, 0, 0, 0, 0);
35827 if( nByte==0 ){
35828 argv[i] = 0;
35829 }else{
35830 argv[i] = malloc( nByte );
35831 if( argv[i]==0 ){
35832 fprintf(stderr, "malloc failed\n");
35833 exit(1);
35834 }
35835 nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i],nByte,0,0);
35836 if( nByte==0 ){
35837 free(argv[i]);
35838 argv[i] = 0;
35839 }
35840 }
35841 }
35842 argv[argc] = 0;
35843 rc = utf8_main(argc, argv);
35844 for(i=0; i<argc; i++) free(orig[i]);
35845 free(argv);
35846 return rc;
35847 }
35848 #endif /* WIN32 */
35849
35850 /*
35851 ** This is the main entry point for the process. Everything starts here.
35852 **
35853 ** The "main" identifier may have been #defined to something else:
35854 **
35855 ** utf8_main On Windows
35856 ** fiddle_main In Fiddle
35857 ** sqlite3_shell Other projects that use shell.c as a subroutine
35858 */
35859 int SQLITE_CDECL main(int argc, char **argv){
35860 #ifdef SQLITE_DEBUG
35861 sqlite3_int64 mem_main_enter = 0;
35862 #endif
35863 char *zErrMsg = 0;
35864 #ifdef SQLITE_SHELL_FIDDLE
@@ -35259,14 +35876,10 @@
35876 int nOptsEnd = argc;
35877 int bEnableVfstrace = 0;
35878 char **azCmd = 0;
35879 int *aiCmd = 0;
35880 const char *zVfs = 0; /* Value of -vfs command-line option */
 
 
 
 
35881 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
35882
35883 #ifdef SQLITE_SHELL_FIDDLE
35884 stdin_is_interactive = 0;
35885 stdout_is_console = 1;
@@ -35291,15 +35904,11 @@
35904 ){
35905 exit(1);
35906 }
35907 }else{
35908 #if defined(_WIN32) || defined(WIN32)
 
 
 
35909 DebugBreak();
 
35910 #elif defined(SIGTRAP)
35911 raise(SIGTRAP);
35912 #endif
35913 }
35914 }
@@ -35321,36 +35930,10 @@
35930 exit(1);
35931 }
35932 #endif
35933 main_init(&data);
35934
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35935 assert( argc>=1 && argv && argv[0] );
35936 Argv0 = argv[0];
35937
35938 #ifdef SQLITE_SHELL_DBNAME_PROC
35939 {
@@ -35362,11 +35945,11 @@
35945 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
35946 warnInmemoryDb = 0;
35947 }
35948 #endif
35949
35950 /* Do an initial pass through the command-line arguments to locate
35951 ** the name of the database file, the name of the initialization file,
35952 ** the size of the alternative malloc heap, options affecting commands
35953 ** or SQL run from the command line, and the first command to execute.
35954 */
35955 #ifndef SQLITE_SHELL_FIDDLE
@@ -35374,11 +35957,11 @@
35957 #endif
35958 for(i=1; i<argc; i++){
35959 char *z;
35960 z = argv[i];
35961 if( z[0]!='-' || i>nOptsEnd ){
35962 if( data.aAuxDb->zDbFilename==0 && !isScriptFile(z,1) ){
35963 data.aAuxDb->zDbFilename = z;
35964 }else{
35965 /* Excess arguments are interpreted as SQL (or dot-commands) and
35966 ** mean that nothing is read from stdin */
35967 readStdin = 0;
@@ -35419,15 +36002,10 @@
36002 if( n<2 ){
36003 sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n");
36004 exit(1);
36005 }
36006 stdout_tty_width = n;
 
 
 
 
 
36007 }else if( cli_strcmp(z,"-utf8")==0 ){
36008 }else if( cli_strcmp(z,"-no-utf8")==0 ){
36009 }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
36010 int val = 0;
36011 sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val);
@@ -35547,10 +36125,20 @@
36125 }else if( cli_strcmp(z,"-safe")==0 ){
36126 /* no-op - catch this on the second pass */
36127 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
36128 /* skip over the argument */
36129 i++;
36130 }else if( cli_strcmp(z,"-test-argv")==0 ){
36131 /* Undocumented test option. Print the values in argv[] and exit.
36132 ** Use this to verify that any translation of the argv[], for example
36133 ** on Windows that receives wargv[] from the OS and must convert
36134 ** to UTF8 prior to calling this routine. */
36135 int kk;
36136 for(kk=0; kk<argc; kk++){
36137 sqlite3_fprintf(stdout,"argv[%d] = \"%s\"\n", kk, argv[kk]);
36138 }
36139 return 0;
36140 }
36141 }
36142 #ifndef SQLITE_SHELL_FIDDLE
36143 if( !bEnableVfstrace ) verify_uninitialized();
36144 #endif
@@ -35573,11 +36161,30 @@
36161
36162 if( zVfs ){
36163 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
36164 if( pVfs ){
36165 sqlite3_vfs_register(pVfs, 1);
36166 }
36167 #if !defined(SQLITE_OMIT_LOAD_EXTENSION)
36168 else if( access(zVfs,0)==0 ){
36169 /* If the VFS name is not the name of an existing VFS, but it is
36170 ** the name of a file, then try to load that file as an extension.
36171 ** Presumably the extension implements the desired VFS. */
36172 sqlite3 *db = 0;
36173 char *zErr = 0;
36174 sqlite3_open(":memory:", &db);
36175 sqlite3_enable_load_extension(db, 1);
36176 rc = sqlite3_load_extension(db, zVfs, 0, &zErr);
36177 sqlite3_close(db);
36178 if( (rc&0xff)!=SQLITE_OK ){
36179 cli_printf(stderr, "could not load extension VFS \"%s\": %s\n",
36180 zVfs, zErr);
36181 exit(1);
36182 }
36183 }
36184 #endif
36185 else{
36186 cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs);
36187 exit(1);
36188 }
36189 }
36190
@@ -35586,11 +36193,12 @@
36193 data.pAuxDb->zDbFilename = ":memory:";
36194 warnInmemoryDb = argc==1;
36195 #else
36196 cli_printf(stderr,
36197 "%s: Error: no database filename specified\n", Argv0);
36198 rc = 1;
36199 goto shell_main_exit;
36200 #endif
36201 }
36202 data.out = stdout;
36203 if( bEnableVfstrace ){
36204 vfstrace_register("trace",0,vfstraceOut, &data, 1);
@@ -35613,11 +36221,11 @@
36221 ** is given on the command line, look for a file named ~/.sqliterc and
36222 ** try to process it.
36223 */
36224 if( !noInit ) process_sqliterc(&data,zInitFile);
36225
36226 /* Make a second pass through the command-line arguments and set
36227 ** options. This second pass is delayed until after the initialization
36228 ** file is processed so that the command-line arguments will override
36229 ** settings in the initialization file.
36230 */
36231 for(i=1; i<argc; i++){
@@ -35640,10 +36248,12 @@
36248 modeChange(&data, MODE_Json);
36249 }else if( cli_strcmp(z,"-markdown")==0 ){
36250 modeChange(&data, MODE_Markdown);
36251 }else if( cli_strcmp(z,"-table")==0 ){
36252 modeChange(&data, MODE_Table);
36253 }else if( cli_strcmp(z,"-psql")==0 ){
36254 modeChange(&data, MODE_Psql);
36255 }else if( cli_strcmp(z,"-box")==0 ){
36256 modeChange(&data, MODE_Box);
36257 }else if( cli_strcmp(z,"-csv")==0 ){
36258 modeChange(&data, MODE_Csv);
36259 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
@@ -35726,22 +36336,21 @@
36336 }else if( cli_strcmp(z,"-bail")==0 ){
36337 /* No-op. The bail_on_error flag should already be set. */
36338 }else if( cli_strcmp(z,"-version")==0 ){
36339 cli_printf(stdout, "%s %s (%d-bit)\n",
36340 sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
36341 rc = 0;
36342 goto shell_main_exit;
36343 }else if( cli_strcmp(z,"-interactive")==0 ){
36344 /* Need to check for interactive override here to so that it can
36345 ** affect console setup (for Windows only) and testing thereof.
36346 */
36347 stdin_is_interactive = 1;
36348 }else if( cli_strcmp(z,"-batch")==0 ){
36349 /* already handled */
36350 }else if( cli_strcmp(z,"-screenwidth")==0 ){
36351 i++;
 
 
36352 }else if( cli_strcmp(z,"-utf8")==0 ){
36353 /* already handled */
36354 }else if( cli_strcmp(z,"-no-utf8")==0 ){
36355 /* already handled */
36356 }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
@@ -35783,29 +36392,33 @@
36392 ** we retain the goofy behavior for historical compatibility. */
36393 if( i==argc-1 ) break;
36394 z = cmdline_option_value(argc,argv,++i);
36395 if( z[0]=='.' ){
36396 rc = do_meta_command(z, &data);
36397 if( rc && bail_on_error ){
36398 if( rc==2 ) rc = 0;
36399 goto shell_main_exit;
36400 }
36401 }else{
36402 open_db(&data, 0);
36403 rc = shell_exec(&data, z, &zErrMsg);
36404 if( zErrMsg!=0 ){
36405 shellEmitError(zErrMsg);
36406 sqlite3_free(zErrMsg);
36407 if( !rc ) rc = 1;
36408 }else if( rc!=0 ){
36409 cli_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
 
36410 }
36411 if( bail_on_error ) goto shell_main_exit;
36412 }
36413 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
36414 }else if( cli_strncmp(z, "-A", 2)==0 ){
36415 if( nCmd>0 ){
36416 cli_printf(stderr,"Error: cannot mix regular SQL or dot-commands"
36417 " with \"%s\"\n", z);
36418 rc = 1;
36419 goto shell_main_exit;
36420 }
36421 open_db(&data, OPEN_DB_ZIPFILE);
36422 if( z[2] ){
36423 argv[i] = &z[2];
36424 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
@@ -35821,11 +36434,12 @@
36434 }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
36435 /* Acted upon in first pass. */
36436 }else{
36437 cli_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
36438 eputz("Use -help for a list of options.\n");
36439 rc = 1;
36440 goto shell_main_exit;
36441 }
36442 }
36443
36444 if( !readStdin ){
36445 /* Run all arguments that do not begin with '-' as if they were separate
@@ -35832,11 +36446,22 @@
36446 ** command-line inputs, except for the argToSkip argument which contains
36447 ** the database filename.
36448 */
36449 for(i=0; i<nCmd; i++){
36450 echo_group_input(&data, azCmd[i]);
36451 if( isScriptFile(azCmd[i],0) ){
36452 FILE *inSaved = data.in;
36453 i64 savedLineno = data.lineno;
36454 int res = 1;
36455 if( (data.in = openChrSource(azCmd[i]))!=0 ){
36456 res = process_input(&data, azCmd[i]);
36457 fclose(data.in);
36458 }
36459 data.in = inSaved;
36460 data.lineno = savedLineno;
36461 if( res ) i = nCmd;
36462 }else if( azCmd[i][0]=='.' ){
36463 char *zErrCtx = malloc( 64 );
36464 shell_check_oom(zErrCtx);
36465 sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]);
36466 data.zInFile = "<cmdline>";
36467 data.zErrPrefix = zErrCtx;
@@ -35947,14 +36572,10 @@
36572 }
36573 find_home_dir(1);
36574 output_reset(&data);
36575 data.doXdgOpen = 0;
36576 clearTempFile(&data);
 
 
 
 
36577 modeFree(&data.mode);
36578 if( data.nSavedModes ){
36579 int ii;
36580 for(ii=0; ii<data.nSavedModes; ii++){
36581 modeFree(&data.aSavedModes[ii].mode);
36582
+2565 -2637
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
1616
** if you want a wrapper to interface SQLite with your choice of programming
1717
** language. The code for the "sqlite3" command-line shell is also in a
1818
** separate file. This file contains only code for the core SQLite library.
1919
**
2020
** The content in this amalgamation comes from Fossil check-in
21
-** 5804ba4874cc41b11e8bb559d5533283c289 with changes in files:
21
+** 9adab8b2bef4130abd358d53384cb5f4dd69 with changes in files:
2222
**
2323
**
2424
*/
2525
#ifndef SQLITE_AMALGAMATION
2626
#define SQLITE_CORE 1
@@ -467,14 +467,14 @@
467467
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
468468
** [sqlite_version()] and [sqlite_source_id()].
469469
*/
470470
#define SQLITE_VERSION "3.52.0"
471471
#define SQLITE_VERSION_NUMBER 3052000
472
-#define SQLITE_SOURCE_ID "2025-11-25 18:20:33 5804ba4874cc41b11e8bb559d5533283c2895d2b13316830955663575567f911"
472
+#define SQLITE_SOURCE_ID "2026-01-09 00:41:35 9adab8b2bef4130abd358d53384cb5f4dd691b808336bb7102793b0165b1c516"
473473
#define SQLITE_SCM_BRANCH "trunk"
474474
#define SQLITE_SCM_TAGS ""
475
-#define SQLITE_SCM_DATETIME "2025-11-25T18:20:33.534Z"
475
+#define SQLITE_SCM_DATETIME "2026-01-09T00:41:35.433Z"
476476
477477
/*
478478
** CAPI3REF: Run-Time Library Version Numbers
479479
** KEYWORDS: sqlite3_version sqlite3_sourceid
480480
**
@@ -1809,11 +1809,11 @@
18091809
** ^SQLite will use the xCurrentTimeInt64() method to get the current
18101810
** date and time if that method is available (if iVersion is 2 or
18111811
** greater and the function pointer is not NULL) and will fall back
18121812
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
18131813
**
1814
-** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
1814
+** ^The xSetSystemCall(), xGetSystemCall(), and xNextSystemCall() interfaces
18151815
** are not used by the SQLite core. These optional interfaces are provided
18161816
** by some VFSes to facilitate testing of the VFS code. By overriding
18171817
** system calls with functions under its control, a test program can
18181818
** simulate faults and error conditions that would otherwise be difficult
18191819
** or impossible to induce. The set of system calls that can be overridden
@@ -4493,10 +4493,11 @@
44934493
** <li> sqlite3_errcode()
44944494
** <li> sqlite3_extended_errcode()
44954495
** <li> sqlite3_errmsg()
44964496
** <li> sqlite3_errmsg16()
44974497
** <li> sqlite3_error_offset()
4498
+** <li> sqlite3_db_handle()
44984499
** </ul>
44994500
**
45004501
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
45014502
** text that describes the error, as either UTF-8 or UTF-16 respectively,
45024503
** or NULL if no error message is available.
@@ -4751,16 +4752,32 @@
47514752
** compiles to see if some SQL syntax is well-formed, without generating
47524753
** messages on the global error log when it is not. If the test compile
47534754
** fails, the sqlite3_prepare_v3() call returns the same error indications
47544755
** with or without this flag; it just omits the call to [sqlite3_log()] that
47554756
** logs the error.
4757
+**
4758
+** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt>
4759
+** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to behave as if
4760
+** the SQL statement is part of a database schema. This makes a difference
4761
+** when the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] option is set to off.
4762
+** When this option is used and SQLITE_DBCONFIG_TRUSTED_SCHEMA is off,
4763
+** SQL functions may not be called unless they are tagged with
4764
+** [SQLITE_INNOCUOUS] and virtual tables may not be used unless tagged
4765
+** with [SQLITE_VTAB_INNOCUOUS]. Use the SQLITE_PREPARE_FROM_DDL option
4766
+** when preparing SQL that is derived from parts of the database
4767
+** schema. In particular, virtual table implementations that
4768
+** run SQL statements based on the arguments to their CREATE VIRTUAL
4769
+** TABLE statement should use [sqlite3_prepare_v3()] and set the
4770
+** SQLITE_PREPARE_FROM_DLL flag to prevent bypass of the
4771
+** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
47564772
** </dl>
47574773
*/
47584774
#define SQLITE_PREPARE_PERSISTENT 0x01
47594775
#define SQLITE_PREPARE_NORMALIZE 0x02
47604776
#define SQLITE_PREPARE_NO_VTAB 0x04
47614777
#define SQLITE_PREPARE_DONT_LOG 0x10
4778
+#define SQLITE_PREPARE_FROM_DDL 0x20
47624779
47634780
/*
47644781
** CAPI3REF: Compiling An SQL Statement
47654782
** KEYWORDS: {SQL statement compiler}
47664783
** METHOD: sqlite3
@@ -4770,12 +4787,13 @@
47704787
** program using one of these routines. Or, in other words, these routines
47714788
** are constructors for the [prepared statement] object.
47724789
**
47734790
** The preferred routine to use is [sqlite3_prepare_v2()]. The
47744791
** [sqlite3_prepare()] interface is legacy and should be avoided.
4775
-** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
4776
-** for special purposes.
4792
+** [sqlite3_prepare_v3()] has an extra
4793
+** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times
4794
+** needed for special purpose or to pass along security restrictions.
47774795
**
47784796
** The use of the UTF-8 interfaces is preferred, as SQLite currently
47794797
** does all parsing using UTF-8. The UTF-16 interfaces are provided
47804798
** as a convenience. The UTF-16 interfaces work by converting the
47814799
** input text into UTF-8, then invoking the corresponding UTF-8 interface.
@@ -6605,14 +6623,18 @@
66056623
** use for client data is to provide a mechanism for wrapper libraries
66066624
** to store additional information about an SQLite database connection.
66076625
**
66086626
** There is no limit (other than available memory) on the number of different
66096627
** client data pointers (with different names) that can be attached to a
6610
-** single database connection. However, the implementation is optimized
6611
-** for the case of having only one or two different client data names.
6612
-** Applications and wrapper libraries are discouraged from using more than
6613
-** one client data name each.
6628
+** single database connection. However, the current implementation stores
6629
+** the content on a linked list. Insert and retrieval performance will
6630
+** be proportional to the number of entries. The design use case, and
6631
+** the use case for which the implementation is optimized, is
6632
+** that an application will store only small number of client data names,
6633
+** typically just one or two. This interface is not intended to be a
6634
+** generalized key/value store for thousands or millions of keys. It
6635
+** will work for that, but performance might be disappointing.
66146636
**
66156637
** There is no way to enumerate the client data pointers
66166638
** associated with a database connection. The N parameter can be thought
66176639
** of as a secret key such that only code that knows the secret key is able
66186640
** to access the associated data.
@@ -7745,22 +7767,22 @@
77457767
** ^This interface loads an SQLite extension library from the named file.
77467768
**
77477769
** ^The sqlite3_load_extension() interface attempts to load an
77487770
** [SQLite extension] library contained in the file zFile. If
77497771
** the file cannot be loaded directly, attempts are made to load
7750
-** with various operating-system specific extensions added.
7772
+** with various operating-system specific filename extensions added.
77517773
** So for example, if "samplelib" cannot be loaded, then names like
77527774
** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
77537775
** be tried also.
77547776
**
77557777
** ^The entry point is zProc.
77567778
** ^(zProc may be 0, in which case SQLite will try to come up with an
77577779
** entry point name on its own. It first tries "sqlite3_extension_init".
7758
-** If that does not work, it constructs a name "sqlite3_X_init" where
7759
-** X consists of the lower-case equivalent of all ASCII alphabetic
7760
-** characters in the filename from the last "/" to the first following
7761
-** "." and omitting any initial "lib".)^
7780
+** If that does not work, it tries names of the form "sqlite3_X_init"
7781
+** where X consists of the lower-case equivalent of all ASCII alphabetic
7782
+** characters or all ASCII alphanumeric characters in the filename from
7783
+** the last "/" to the first following "." and omitting any initial "lib".)^
77627784
** ^The sqlite3_load_extension() interface returns
77637785
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
77647786
** ^If an error occurs and pzErrMsg is not 0, then the
77657787
** [sqlite3_load_extension()] interface shall attempt to
77667788
** fill *pzErrMsg with error message text stored in memory
@@ -9049,11 +9071,11 @@
90499071
** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()]
90509072
** that contains the constructed string. The calling application should
90519073
** pass the returned value to [sqlite3_free()] to avoid a memory leak.
90529074
** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any
90539075
** errors were encountered during construction of the string. ^The
9054
-** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the
9076
+** [sqlite3_str_finish(X)] interface might also return a NULL pointer if the
90559077
** string in [sqlite3_str] object X is zero bytes long.
90569078
**
90579079
** ^The [sqlite3_str_free(X)] interface destroys both the sqlite3_str object
90589080
** X and the string content it contains. Calling sqlite3_str_free(X) is
90599081
** the equivalent of calling [sqlite3_free](sqlite3_str_finish(X)).
@@ -14386,10 +14408,13 @@
1438614408
** The maximum length of a single SQL statement in bytes.
1438714409
**
1438814410
** It used to be the case that setting this value to zero would
1438914411
** turn the limit off. That is no longer true. It is not possible
1439014412
** to turn this limit off.
14413
+**
14414
+** The hard limit is the largest possible 32-bit signed integer less
14415
+** 1024, or 2147482624.
1439114416
*/
1439214417
#ifndef SQLITE_MAX_SQL_LENGTH
1439314418
# define SQLITE_MAX_SQL_LENGTH 1000000000
1439414419
#endif
1439514420
@@ -17525,11 +17550,11 @@
1752517550
1752617551
/*
1752717552
** Additional non-public SQLITE_PREPARE_* flags
1752817553
*/
1752917554
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
17530
-#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
17555
+#define SQLITE_PREPARE_MASK 0x3f /* Mask of public flags */
1753117556
1753217557
/*
1753317558
** Prototypes for the VDBE interface. See comments on the implementation
1753417559
** for a description of what each of these routines does.
1753517560
*/
@@ -20765,23 +20790,23 @@
2076520790
**
2076620791
** (op == TK_INSERT)
2076720792
** orconf -> stores the ON CONFLICT algorithm
2076820793
** pSelect -> The content to be inserted - either a SELECT statement or
2076920794
** a VALUES clause.
20770
-** zTarget -> Dequoted name of the table to insert into.
20795
+** pSrc -> Table to insert into.
2077120796
** pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
2077220797
** statement, then this stores the column-names to be
2077320798
** inserted into.
2077420799
** pUpsert -> The ON CONFLICT clauses for an Upsert
2077520800
**
2077620801
** (op == TK_DELETE)
20777
-** zTarget -> Dequoted name of the table to delete from.
20802
+** pSrc -> Table to delete from
2077820803
** pWhere -> The WHERE clause of the DELETE statement if one is specified.
2077920804
** Otherwise NULL.
2078020805
**
2078120806
** (op == TK_UPDATE)
20782
-** zTarget -> Dequoted name of the table to update.
20807
+** pSrc -> Table to update, followed by any FROM clause tables.
2078320808
** pWhere -> The WHERE clause of the UPDATE statement if one is specified.
2078420809
** Otherwise NULL.
2078520810
** pExprList -> A list of the columns to update and the expressions to update
2078620811
** them to. See sqlite3Update() documentation of "pChanges"
2078720812
** argument.
@@ -20797,12 +20822,11 @@
2079720822
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT,
2079820823
** or TK_RETURNING */
2079920824
u8 orconf; /* OE_Rollback etc. */
2080020825
Trigger *pTrig; /* The trigger that this step is a part of */
2080120826
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
20802
- char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
20803
- SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */
20827
+ SrcList *pSrc; /* Table to insert/update/delete */
2080420828
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
2080520829
ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */
2080620830
IdList *pIdList; /* Column names for INSERT */
2080720831
Upsert *pUpsert; /* Upsert clauses on an INSERT */
2080820832
char *zSpan; /* Original SQL text of this command */
@@ -21547,10 +21571,11 @@
2154721571
#ifdef SQLITE_DEBUG
2154821572
SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int);
2154921573
#endif
2155021574
SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
2155121575
SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*);
21576
+SQLITE_PRIVATE Expr *sqlite3ExprInt32(sqlite3*,int);
2155221577
SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
2155321578
SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
2155421579
SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
2155521580
SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
2155621581
SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*);
@@ -21865,21 +21890,20 @@
2186521890
SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
2186621891
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
2186721892
SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
2186821893
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
2186921894
const char*,const char*);
21870
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
21895
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,SrcList*, IdList*,
2187121896
Select*,u8,Upsert*,
2187221897
const char*,const char*);
21873
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*,
21898
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,SrcList*,SrcList*,ExprList*,
2187421899
Expr*, u8, const char*,const char*);
21875
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
21900
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,SrcList*, Expr*,
2187621901
const char*,const char*);
2187721902
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
2187821903
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
2187921904
SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
21880
-SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*);
2188121905
# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
2188221906
# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
2188321907
#else
2188421908
# define sqlite3TriggersExist(B,C,D,E,F) 0
2188521909
# define sqlite3DeleteTrigger(A,B)
@@ -21889,11 +21913,10 @@
2188921913
# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
2189021914
# define sqlite3TriggerList(X, Y) 0
2189121915
# define sqlite3ParseToplevel(p) p
2189221916
# define sqlite3IsToplevel(p) 1
2189321917
# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
21894
-# define sqlite3TriggerStepSrc(A,B) 0
2189521918
#endif
2189621919
2189721920
SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*);
2189821921
SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol);
2189921922
SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem*,int);
@@ -30648,18 +30671,10 @@
3064830671
# define SQLITE_OS_WINCE 1
3064930672
#else
3065030673
# define SQLITE_OS_WINCE 0
3065130674
#endif
3065230675
30653
-/*
30654
-** Determine if we are dealing with WinRT, which provides only a subset of
30655
-** the full Win32 API.
30656
-*/
30657
-#if !defined(SQLITE_OS_WINRT)
30658
-# define SQLITE_OS_WINRT 0
30659
-#endif
30660
-
3066130676
/*
3066230677
** For WinCE, some API function parameters do not appear to be declared as
3066330678
** volatile.
3066430679
*/
3066530680
#if SQLITE_OS_WINCE
@@ -30670,11 +30685,11 @@
3067030685
3067130686
/*
3067230687
** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
3067330688
** functions are not available (e.g. those not using MSVC, Cygwin, etc).
3067430689
*/
30675
-#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
30690
+#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && \
3067630691
SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
3067730692
# define SQLITE_OS_WIN_THREADS 1
3067830693
#else
3067930694
# define SQLITE_OS_WIN_THREADS 0
3068030695
#endif
@@ -30787,15 +30802,11 @@
3078730802
static int winMutexInit(void){
3078830803
/* The first to increment to 1 does actual initialization */
3078930804
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
3079030805
int i;
3079130806
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
30792
-#if SQLITE_OS_WINRT
30793
- InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
30794
-#else
3079530807
InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
30796
-#endif
3079730808
}
3079830809
winMutex_isInit = 1;
3079930810
}else{
3080030811
/* Another thread is (in the process of) initializing the static
3080130812
** mutexes */
@@ -30881,15 +30892,11 @@
3088130892
#ifdef SQLITE_DEBUG
3088230893
#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
3088330894
p->trace = 1;
3088430895
#endif
3088530896
#endif
30886
-#if SQLITE_OS_WINRT
30887
- InitializeCriticalSectionEx(&p->mutex, 0, 0);
30888
-#else
3088930897
InitializeCriticalSection(&p->mutex);
30890
-#endif
3089130898
}
3089230899
break;
3089330900
}
3089430901
default: {
3089530902
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -38298,11 +38305,11 @@
3829838305
3829938306
/*****************************************************************************
3830038307
** Debugging logic
3830138308
*/
3830238309
38303
-/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */
38310
+/* SQLITE_KV_TRACE() is used for tracing calls to kvrecord routines. */
3830438311
#if 0
3830538312
#define SQLITE_KV_TRACE(X) printf X
3830638313
#else
3830738314
#define SQLITE_KV_TRACE(X)
3830838315
#endif
@@ -38312,18 +38319,22 @@
3831238319
#define SQLITE_KV_LOG(X) printf X
3831338320
#else
3831438321
#define SQLITE_KV_LOG(X)
3831538322
#endif
3831638323
38317
-
3831838324
/*
3831938325
** Forward declaration of objects used by this VFS implementation
3832038326
*/
3832138327
typedef struct KVVfsFile KVVfsFile;
3832238328
3832338329
/* A single open file. There are only two files represented by this
3832438330
** VFS - the database and the rollback journal.
38331
+**
38332
+** Maintenance reminder: if this struct changes in any way, the JSON
38333
+** rendering of its structure must be updated in
38334
+** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
38335
+** compatibility concerns, so it does not need an iVersion member.
3832538336
*/
3832638337
struct KVVfsFile {
3832738338
sqlite3_file base; /* IO methods */
3832838339
const char *zClass; /* Storage class */
3832938340
int isJournal; /* True if this is a journal file */
@@ -38369,11 +38380,11 @@
3836938380
static int kvvfsSleep(sqlite3_vfs*, int microseconds);
3837038381
static int kvvfsCurrentTime(sqlite3_vfs*, double*);
3837138382
static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
3837238383
3837338384
static sqlite3_vfs sqlite3OsKvvfsObject = {
38374
- 1, /* iVersion */
38385
+ 2, /* iVersion */
3837538386
sizeof(KVVfsFile), /* szOsFile */
3837638387
1024, /* mxPathname */
3837738388
0, /* pNext */
3837838389
"kvvfs", /* zName */
3837938390
0, /* pAppData */
@@ -38445,42 +38456,56 @@
3844538456
#include <sys/stat.h>
3844638457
#include <unistd.h>
3844738458
3844838459
/* Forward declarations for the low-level storage engine
3844938460
*/
38450
-static int kvstorageWrite(const char*, const char *zKey, const char *zData);
38451
-static int kvstorageDelete(const char*, const char *zKey);
38452
-static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
38453
-#define KVSTORAGE_KEY_SZ 32
38461
+#ifndef SQLITE_WASM
38462
+/* In WASM builds these are implemented in JS. */
38463
+static int kvrecordWrite(const char*, const char *zKey, const char *zData);
38464
+static int kvrecordDelete(const char*, const char *zKey);
38465
+static int kvrecordRead(const char*, const char *zKey, char *zBuf, int nBuf);
38466
+#endif
38467
+#ifndef KVRECORD_KEY_SZ
38468
+#define KVRECORD_KEY_SZ 32
38469
+#endif
3845438470
3845538471
/* Expand the key name with an appropriate prefix and put the result
3845638472
** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least
38457
-** KVSTORAGE_KEY_SZ bytes.
38473
+** KVRECORD_KEY_SZ bytes.
3845838474
*/
38459
-static void kvstorageMakeKey(
38475
+static void kvrecordMakeKey(
3846038476
const char *zClass,
3846138477
const char *zKeyIn,
3846238478
char *zKeyOut
3846338479
){
38464
- sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn);
38480
+ assert( zKeyIn );
38481
+ assert( zKeyOut );
38482
+ assert( zClass );
38483
+ sqlite3_snprintf(KVRECORD_KEY_SZ, zKeyOut, "kvvfs-%s-%s",
38484
+ zClass, zKeyIn);
3846538485
}
3846638486
38487
+#ifndef SQLITE_WASM
38488
+/* In WASM builds do not define APIs which use fopen(), fwrite(),
38489
+** and the like because those APIs are a portability issue for
38490
+** WASM.
38491
+*/
3846738492
/* Write content into a key. zClass is the particular namespace of the
3846838493
** underlying key/value store to use - either "local" or "session".
3846938494
**
3847038495
** Both zKey and zData are zero-terminated pure text strings.
3847138496
**
3847238497
** Return the number of errors.
3847338498
*/
38474
-static int kvstorageWrite(
38499
+static int kvrecordWrite(
3847538500
const char *zClass,
3847638501
const char *zKey,
3847738502
const char *zData
3847838503
){
3847938504
FILE *fd;
38480
- char zXKey[KVSTORAGE_KEY_SZ];
38481
- kvstorageMakeKey(zClass, zKey, zXKey);
38505
+ char zXKey[KVRECORD_KEY_SZ];
38506
+ kvrecordMakeKey(zClass, zKey, zXKey);
3848238507
fd = fopen(zXKey, "wb");
3848338508
if( fd ){
3848438509
SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey,
3848538510
(int)strlen(zData), zData,
3848638511
strlen(zData)>50 ? "..." : ""));
@@ -38494,13 +38519,13 @@
3849438519
3849538520
/* Delete a key (with its corresponding data) from the key/value
3849638521
** namespace given by zClass. If the key does not previously exist,
3849738522
** this routine is a no-op.
3849838523
*/
38499
-static int kvstorageDelete(const char *zClass, const char *zKey){
38500
- char zXKey[KVSTORAGE_KEY_SZ];
38501
- kvstorageMakeKey(zClass, zKey, zXKey);
38524
+static int kvrecordDelete(const char *zClass, const char *zKey){
38525
+ char zXKey[KVRECORD_KEY_SZ];
38526
+ kvrecordMakeKey(zClass, zKey, zXKey);
3850238527
unlink(zXKey);
3850338528
SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey));
3850438529
return 0;
3850538530
}
3850638531
@@ -38517,20 +38542,20 @@
3851738542
** If nBuf<=0 then this routine simply returns the size of the data
3851838543
** without actually reading it. Similarly, if nBuf==1 then it
3851938544
** zero-terminates zBuf at zBuf[0] and returns the size of the data
3852038545
** without reading it.
3852138546
*/
38522
-static int kvstorageRead(
38547
+static int kvrecordRead(
3852338548
const char *zClass,
3852438549
const char *zKey,
3852538550
char *zBuf,
3852638551
int nBuf
3852738552
){
3852838553
FILE *fd;
3852938554
struct stat buf;
38530
- char zXKey[KVSTORAGE_KEY_SZ];
38531
- kvstorageMakeKey(zClass, zKey, zXKey);
38555
+ char zXKey[KVRECORD_KEY_SZ];
38556
+ kvrecordMakeKey(zClass, zKey, zXKey);
3853238557
if( access(zXKey, R_OK)!=0
3853338558
|| stat(zXKey, &buf)!=0
3853438559
|| !S_ISREG(buf.st_mode)
3853538560
){
3853638561
SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey));
@@ -38558,27 +38583,39 @@
3855838583
SQLITE_KV_TRACE(("KVVFS-READ %-15s (%lld) %.50s%s\n", zXKey,
3855938584
n, zBuf, n>50 ? "..." : ""));
3856038585
return (int)n;
3856138586
}
3856238587
}
38588
+#endif /* #ifndef SQLITE_WASM */
38589
+
3856338590
3856438591
/*
3856538592
** An internal level of indirection which enables us to replace the
3856638593
** kvvfs i/o methods with JavaScript implementations in WASM builds.
3856738594
** Maintenance reminder: if this struct changes in any way, the JSON
3856838595
** rendering of its structure must be updated in
3856938596
** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
38570
-** compatibility concerns, so it does not need an iVersion
38571
-** member.
38597
+** compatibility concerns, so it does not need an iVersion member.
3857238598
*/
3857338599
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
3857438600
struct sqlite3_kvvfs_methods {
38575
- int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf);
38576
- int (*xWrite)(const char *zClass, const char *zKey, const char *zData);
38577
- int (*xDelete)(const char *zClass, const char *zKey);
38601
+ int (*xRcrdRead)(const char*, const char *zKey, char *zBuf, int nBuf);
38602
+ int (*xRcrdWrite)(const char*, const char *zKey, const char *zData);
38603
+ int (*xRcrdDelete)(const char*, const char *zKey);
3857838604
const int nKeySize;
38605
+ const int nBufferSize;
38606
+#ifndef SQLITE_WASM
38607
+# define MAYBE_CONST const
38608
+#else
38609
+# define MAYBE_CONST
38610
+#endif
38611
+ MAYBE_CONST sqlite3_vfs * pVfs;
38612
+ MAYBE_CONST sqlite3_io_methods *pIoDb;
38613
+ MAYBE_CONST sqlite3_io_methods *pIoJrnl;
38614
+#undef MAYBE_CONST
3857938615
};
38616
+
3858038617
3858138618
/*
3858238619
** This object holds the kvvfs I/O methods which may be swapped out
3858338620
** for JavaScript-side implementations in WASM builds. In such builds
3858438621
** it cannot be const, but in native builds it should be so that
@@ -38590,14 +38627,24 @@
3859038627
*/
3859138628
#ifndef SQLITE_WASM
3859238629
const
3859338630
#endif
3859438631
SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = {
38595
-kvstorageRead,
38596
-kvstorageWrite,
38597
-kvstorageDelete,
38598
-KVSTORAGE_KEY_SZ
38632
+#ifndef SQLITE_WASM
38633
+ .xRcrdRead = kvrecordRead,
38634
+ .xRcrdWrite = kvrecordWrite,
38635
+ .xRcrdDelete = kvrecordDelete,
38636
+#else
38637
+ .xRcrdRead = 0,
38638
+ .xRcrdWrite = 0,
38639
+ .xRcrdDelete = 0,
38640
+#endif
38641
+ .nKeySize = KVRECORD_KEY_SZ,
38642
+ .nBufferSize = SQLITE_KVOS_SZ,
38643
+ .pVfs = &sqlite3OsKvvfsObject,
38644
+ .pIoDb = &kvvfs_db_io_methods,
38645
+ .pIoJrnl = &kvvfs_jrnl_io_methods
3859938646
};
3860038647
3860138648
/****** Utility subroutines ************************************************/
3860238649
3860338650
/*
@@ -38620,11 +38667,14 @@
3862038667
**
3862138668
** * Because there is no overlap between the encoding characters
3862238669
** of hexadecimal and base-26 numbers, it is always clear where
3862338670
** one stops and the next begins.
3862438671
*/
38625
-static int kvvfsEncode(const char *aData, int nData, char *aOut){
38672
+#ifndef SQLITE_WASM
38673
+static
38674
+#endif
38675
+int kvvfsEncode(const char *aData, int nData, char *aOut){
3862638676
int i, j;
3862738677
const unsigned char *a = (const unsigned char*)aData;
3862838678
for(i=j=0; i<nData; i++){
3862938679
unsigned char c = a[i];
3863038680
if( c!=0 ){
@@ -38671,13 +38721,17 @@
3867138721
3867238722
/*
3867338723
** Decode the text encoding back to binary. The binary content is
3867438724
** written into pOut, which must be at least nOut bytes in length.
3867538725
**
38676
-** The return value is the number of bytes actually written into aOut[].
38726
+** The return value is the number of bytes actually written into aOut[], or
38727
+** -1 for malformed inputs.
3867738728
*/
38678
-static int kvvfsDecode(const char *a, char *aOut, int nOut){
38729
+#ifndef SQLITE_WASM
38730
+static
38731
+#endif
38732
+int kvvfsDecode(const char *a, char *aOut, int nOut){
3867938733
int i, j;
3868038734
int c;
3868138735
const unsigned char *aIn = (const unsigned char*)a;
3868238736
i = 0;
3868338737
j = 0;
@@ -38698,11 +38752,11 @@
3869838752
j += n;
3869938753
if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
3870038754
}else{
3870138755
aOut[j] = c<<4;
3870238756
c = kvvfsHexValue[aIn[++i]];
38703
- if( c<0 ) break;
38757
+ if( c<0 ) return -1 /* hex bytes are always in pairs */;
3870438758
aOut[j++] += c;
3870538759
i++;
3870638760
}
3870738761
}
3870838762
return j;
@@ -38751,17 +38805,18 @@
3875138805
** Read or write the "sz" element, containing the database file size.
3875238806
*/
3875338807
static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){
3875438808
char zData[50];
3875538809
zData[0] = 0;
38756
- sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1);
38810
+ sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "sz", zData,
38811
+ sizeof(zData)-1);
3875738812
return strtoll(zData, 0, 0);
3875838813
}
3875938814
static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){
3876038815
char zData[50];
3876138816
sqlite3_snprintf(sizeof(zData), zData, "%lld", sz);
38762
- return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData);
38817
+ return sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "sz", zData);
3876338818
}
3876438819
3876538820
/****** sqlite3_io_methods methods ******************************************/
3876638821
3876738822
/*
@@ -38772,10 +38827,13 @@
3877238827
3877338828
SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass,
3877438829
pFile->isJournal ? "journal" : "db"));
3877538830
sqlite3_free(pFile->aJrnl);
3877638831
sqlite3_free(pFile->aData);
38832
+#ifdef SQLITE_WASM
38833
+ memset(pFile, 0, sizeof(*pFile));
38834
+#endif
3877738835
return SQLITE_OK;
3877838836
}
3877938837
3878038838
/*
3878138839
** Read from the -journal file.
@@ -38788,20 +38846,26 @@
3878838846
){
3878938847
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
3879038848
assert( pFile->isJournal );
3879138849
SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
3879238850
if( pFile->aJrnl==0 ){
38793
- int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0);
38851
+ int rc;
38852
+ int szTxt = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl",
38853
+ 0, 0);
3879438854
char *aTxt;
3879538855
if( szTxt<=4 ){
3879638856
return SQLITE_IOERR;
3879738857
}
3879838858
aTxt = sqlite3_malloc64( szTxt+1 );
3879938859
if( aTxt==0 ) return SQLITE_NOMEM;
38800
- kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1);
38801
- kvvfsDecodeJournal(pFile, aTxt, szTxt);
38860
+ rc = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl",
38861
+ aTxt, szTxt+1);
38862
+ if( rc>=0 ){
38863
+ kvvfsDecodeJournal(pFile, aTxt, szTxt);
38864
+ }
3880238865
sqlite3_free(aTxt);
38866
+ if( rc ) return rc;
3880338867
if( pFile->aJrnl==0 ) return SQLITE_IOERR;
3880438868
}
3880538869
if( iOfst+iAmt>pFile->nJrnl ){
3880638870
return SQLITE_IOERR_SHORT_READ;
3880738871
}
@@ -38837,12 +38901,12 @@
3883738901
pgno = 1 + iOfst/iAmt;
3883838902
}else{
3883938903
pgno = 1;
3884038904
}
3884138905
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
38842
- got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey,
38843
- aData, SQLITE_KVOS_SZ-1);
38906
+ got = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, zKey,
38907
+ aData, SQLITE_KVOS_SZ-1);
3884438908
if( got<0 ){
3884538909
n = 0;
3884638910
}else{
3884738911
aData[got] = 0;
3884838912
if( iOfst+iAmt<512 ){
@@ -38906,35 +38970,36 @@
3890638970
){
3890738971
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
3890838972
unsigned int pgno;
3890938973
char zKey[30];
3891038974
char *aData = pFile->aData;
38975
+ int rc;
3891138976
SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
3891238977
assert( iAmt>=512 && iAmt<=65536 );
3891338978
assert( (iAmt & (iAmt-1))==0 );
3891438979
assert( pFile->szPage<0 || pFile->szPage==iAmt );
3891538980
pFile->szPage = iAmt;
3891638981
pgno = 1 + iOfst/iAmt;
3891738982
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
3891838983
kvvfsEncode(zBuf, iAmt, aData);
38919
- if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){
38920
- return SQLITE_IOERR;
38984
+ rc = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, zKey, aData);
38985
+ if( 0==rc ){
38986
+ if( iOfst+iAmt > pFile->szDb ){
38987
+ pFile->szDb = iOfst + iAmt;
38988
+ }
3892138989
}
38922
- if( iOfst+iAmt > pFile->szDb ){
38923
- pFile->szDb = iOfst + iAmt;
38924
- }
38925
- return SQLITE_OK;
38990
+ return rc;
3892638991
}
3892738992
3892838993
/*
3892938994
** Truncate an kvvfs-file.
3893038995
*/
3893138996
static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){
3893238997
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
3893338998
SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size));
3893438999
assert( size==0 );
38935
- sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl");
39000
+ sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, "jrnl");
3893639001
sqlite3_free(pFile->aJrnl);
3893739002
pFile->aJrnl = 0;
3893839003
pFile->nJrnl = 0;
3893939004
return SQLITE_OK;
3894039005
}
@@ -38949,11 +39014,11 @@
3894939014
SQLITE_KV_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size));
3895039015
pgno = 1 + size/pFile->szPage;
3895139016
pgnoMax = 2 + pFile->szDb/pFile->szPage;
3895239017
while( pgno<=pgnoMax ){
3895339018
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
38954
- sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey);
39019
+ sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, zKey);
3895539020
pgno++;
3895639021
}
3895739022
pFile->szDb = size;
3895839023
return kvvfsWriteFileSize(pFile, size) ? SQLITE_IOERR : SQLITE_OK;
3895939024
}
@@ -38981,11 +39046,11 @@
3898139046
zOut[i++] = 'a' + (n%26);
3898239047
n /= 26;
3898339048
}while( n>0 );
3898439049
zOut[i++] = ' ';
3898539050
kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]);
38986
- i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut);
39051
+ i = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "jrnl", zOut);
3898739052
sqlite3_free(zOut);
3898839053
return i ? SQLITE_IOERR : SQLITE_OK;
3898939054
}
3899039055
static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){
3899139056
return SQLITE_OK;
@@ -39095,53 +39160,56 @@
3909539160
int *pOutFlags
3909639161
){
3909739162
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
3909839163
if( zName==0 ) zName = "";
3909939164
SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName));
39100
- if( strcmp(zName, "local")==0
39101
- || strcmp(zName, "session")==0
39102
- ){
39103
- pFile->isJournal = 0;
39104
- pFile->base.pMethods = &kvvfs_db_io_methods;
39105
- }else
39106
- if( strcmp(zName, "local-journal")==0
39107
- || strcmp(zName, "session-journal")==0
39108
- ){
39165
+ assert(!pFile->zClass);
39166
+ assert(!pFile->aData);
39167
+ assert(!pFile->aJrnl);
39168
+ assert(!pFile->nJrnl);
39169
+ assert(!pFile->base.pMethods);
39170
+ pFile->szPage = -1;
39171
+ pFile->szDb = -1;
39172
+ if( 0==sqlite3_strglob("*-journal", zName) ){
3910939173
pFile->isJournal = 1;
3911039174
pFile->base.pMethods = &kvvfs_jrnl_io_methods;
39175
+ if( 0==strcmp("session-journal",zName) ){
39176
+ pFile->zClass = "session";
39177
+ }else if( 0==strcmp("local-journal",zName) ){
39178
+ pFile->zClass = "local";
39179
+ }
3911139180
}else{
39112
- return SQLITE_CANTOPEN;
39181
+ pFile->isJournal = 0;
39182
+ pFile->base.pMethods = &kvvfs_db_io_methods;
3911339183
}
39114
- if( zName[0]=='s' ){
39115
- pFile->zClass = "session";
39116
- }else{
39117
- pFile->zClass = "local";
39184
+ if( !pFile->zClass ){
39185
+ pFile->zClass = zName;
3911839186
}
3911939187
pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ);
3912039188
if( pFile->aData==0 ){
3912139189
return SQLITE_NOMEM;
3912239190
}
39123
- pFile->aJrnl = 0;
39124
- pFile->nJrnl = 0;
39125
- pFile->szPage = -1;
39126
- pFile->szDb = -1;
3912739191
return SQLITE_OK;
3912839192
}
3912939193
3913039194
/*
3913139195
** Delete the file located at zPath. If the dirSync argument is true,
3913239196
** ensure the file-system modifications are synced to disk before
3913339197
** returning.
3913439198
*/
3913539199
static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
39200
+ int rc /* The JS impl can fail with OOM in argument conversion */;
3913639201
if( strcmp(zPath, "local-journal")==0 ){
39137
- sqlite3KvvfsMethods.xDelete("local", "jrnl");
39202
+ rc = sqlite3KvvfsMethods.xRcrdDelete("local", "jrnl");
3913839203
}else
3913939204
if( strcmp(zPath, "session-journal")==0 ){
39140
- sqlite3KvvfsMethods.xDelete("session", "jrnl");
39205
+ rc = sqlite3KvvfsMethods.xRcrdDelete("session", "jrnl");
3914139206
}
39142
- return SQLITE_OK;
39207
+ else{
39208
+ rc = 0;
39209
+ }
39210
+ return rc;
3914339211
}
3914439212
3914539213
/*
3914639214
** Test for access permissions. Return true if the requested permission
3914739215
** is available, or false otherwise.
@@ -39151,25 +39219,46 @@
3915139219
const char *zPath,
3915239220
int flags,
3915339221
int *pResOut
3915439222
){
3915539223
SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath));
39224
+#if 0 && defined(SQLITE_WASM)
39225
+ /*
39226
+ ** This is not having the desired effect in the JS bindings.
39227
+ ** It's ostensibly the same logic as the #else block, but
39228
+ ** it's not behaving that way.
39229
+ **
39230
+ ** In JS we map all zPaths to Storage objects, and -journal files
39231
+ ** are mapped to the storage for the main db (which is is exactly
39232
+ ** what the mapping of "local-journal" -> "local" is doing).
39233
+ */
39234
+ const char *zKey = (0==sqlite3_strglob("*-journal", zPath))
39235
+ ? "jrnl" : "sz";
39236
+ *pResOut =
39237
+ sqlite3KvvfsMethods.xRcrdRead(zPath, zKey, 0, 0)>0;
39238
+#else
3915639239
if( strcmp(zPath, "local-journal")==0 ){
39157
- *pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0;
39240
+ *pResOut =
39241
+ sqlite3KvvfsMethods.xRcrdRead("local", "jrnl", 0, 0)>0;
3915839242
}else
3915939243
if( strcmp(zPath, "session-journal")==0 ){
39160
- *pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0;
39244
+ *pResOut =
39245
+ sqlite3KvvfsMethods.xRcrdRead("session", "jrnl", 0, 0)>0;
3916139246
}else
3916239247
if( strcmp(zPath, "local")==0 ){
39163
- *pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0;
39248
+ *pResOut =
39249
+ sqlite3KvvfsMethods.xRcrdRead("local", "sz", 0, 0)>0;
3916439250
}else
3916539251
if( strcmp(zPath, "session")==0 ){
39166
- *pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0;
39252
+ *pResOut =
39253
+ sqlite3KvvfsMethods.xRcrdRead("session", "sz", 0, 0)>0;
3916739254
}else
3916839255
{
3916939256
*pResOut = 0;
3917039257
}
39258
+ /*all current JS tests avoid triggering: assert( *pResOut == 0 ); */
39259
+#endif
3917139260
SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut));
3917239261
return SQLITE_OK;
3917339262
}
3917439263
3917539264
/*
@@ -41286,15 +41375,21 @@
4128641375
}else{
4128741376
pFile->eFileLock = SHARED_LOCK;
4128841377
pInode->nLock++;
4128941378
pInode->nShared = 1;
4129041379
}
41291
- }else if( (eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1)
41292
- || unixIsSharingShmNode(pFile)
41293
- ){
41380
+ }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
4129441381
/* We are trying for an exclusive lock but another thread in this
4129541382
** same process is still holding a shared lock. */
41383
+ rc = SQLITE_BUSY;
41384
+ }else if( unixIsSharingShmNode(pFile) ){
41385
+ /* We are in WAL mode and attempting to delete the SHM and WAL
41386
+ ** files due to closing the connection or changing out of WAL mode,
41387
+ ** but another process still holds locks on the SHM file, thus
41388
+ ** indicating that database locks have been broken, perhaps due
41389
+ ** to a rogue close(open(dbFile)) or similar.
41390
+ */
4129641391
rc = SQLITE_BUSY;
4129741392
}else{
4129841393
/* The request was for a RESERVED or EXCLUSIVE lock. It is
4129941394
** assumed that there is a SHARED or greater lock on the file
4130041395
** already.
@@ -43930,30 +44025,25 @@
4393044025
** connection from running "PRAGMA journal_mode=DELETE" in order to take
4393144026
** the database out of WAL mode, which is perhaps more serious, but is
4393244027
** still not a disaster.
4393344028
*/
4393444029
static int unixIsSharingShmNode(unixFile *pFile){
43935
- int rc;
4393644030
unixShmNode *pShmNode;
44031
+ struct flock lock;
4393744032
if( pFile->pShm==0 ) return 0;
4393844033
if( pFile->ctrlFlags & UNIXFILE_EXCL ) return 0;
4393944034
pShmNode = pFile->pShm->pShmNode;
43940
- rc = 1;
43941
- unixEnterMutex();
43942
- if( ALWAYS(pShmNode->nRef==1) ){
43943
- struct flock lock;
43944
- lock.l_whence = SEEK_SET;
43945
- lock.l_start = UNIX_SHM_DMS;
43946
- lock.l_len = 1;
43947
- lock.l_type = F_WRLCK;
43948
- osFcntl(pShmNode->hShm, F_GETLK, &lock);
43949
- if( lock.l_type==F_UNLCK ){
43950
- rc = 0;
43951
- }
43952
- }
43953
- unixLeaveMutex();
43954
- return rc;
44035
+#if SQLITE_ATOMIC_INTRINSICS
44036
+ assert( AtomicLoad(&pShmNode->nRef)==1 );
44037
+#endif
44038
+ memset(&lock, 0, sizeof(lock));
44039
+ lock.l_whence = SEEK_SET;
44040
+ lock.l_start = UNIX_SHM_DMS;
44041
+ lock.l_len = 1;
44042
+ lock.l_type = F_WRLCK;
44043
+ osFcntl(pShmNode->hShm, F_GETLK, &lock);
44044
+ return (lock.l_type!=F_UNLCK);
4395544045
}
4395644046
4395744047
/*
4395844048
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
4395944049
**
@@ -47893,19 +47983,19 @@
4789347983
4789447984
/*
4789547985
** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
4789647986
** based on the sub-platform)?
4789747987
*/
47898
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI)
47988
+#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_ANSI)
4789947989
# define SQLITE_WIN32_HAS_ANSI
4790047990
#endif
4790147991
4790247992
/*
4790347993
** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
4790447994
** based on the sub-platform)?
4790547995
*/
47906
-#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \
47996
+#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT) && \
4790747997
!defined(SQLITE_WIN32_NO_WIDE)
4790847998
# define SQLITE_WIN32_HAS_WIDE
4790947999
#endif
4791048000
4791148001
/*
@@ -48040,20 +48130,11 @@
4804048130
** mode or memory mapped files (e.g. these APIs are available in the Windows
4804148131
** CE SDK; however, they are not present in the header file)?
4804248132
*/
4804348133
#if SQLITE_WIN32_FILEMAPPING_API && \
4804448134
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
48045
-/*
48046
-** Two of the file mapping APIs are different under WinRT. Figure out which
48047
-** set we need.
48048
-*/
48049
-#if SQLITE_OS_WINRT
48050
-WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
48051
- LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
48052
-
48053
-WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
48054
-#else
48135
+
4805548136
#if defined(SQLITE_WIN32_HAS_ANSI)
4805648137
WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
4805748138
DWORD, DWORD, DWORD, LPCSTR);
4805848139
#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
4805948140
@@ -48061,11 +48142,10 @@
4806148142
WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
4806248143
DWORD, DWORD, DWORD, LPCWSTR);
4806348144
#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
4806448145
4806548146
WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
48066
-#endif /* SQLITE_OS_WINRT */
4806748147
4806848148
/*
4806948149
** These file mapping APIs are common to both Win32 and WinRT.
4807048150
*/
4807148151
@@ -48352,11 +48432,11 @@
4835248432
4835348433
/*
4835448434
** This function is not available on Windows CE or WinRT.
4835548435
*/
4835648436
48357
-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
48437
+#if SQLITE_OS_WINCE
4835848438
# define osAreFileApisANSI() 1
4835948439
#endif
4836048440
4836148441
/*
4836248442
** Many system calls are accessed through pointer-to-functions so that
@@ -48367,11 +48447,11 @@
4836748447
static struct win_syscall {
4836848448
const char *zName; /* Name of the system call */
4836948449
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
4837048450
sqlite3_syscall_ptr pDefault; /* Default value */
4837148451
} aSyscall[] = {
48372
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
48452
+#if !SQLITE_OS_WINCE
4837348453
{ "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 },
4837448454
#else
4837548455
{ "AreFileApisANSI", (SYSCALL)0, 0 },
4837648456
#endif
4837748457
@@ -48406,20 +48486,20 @@
4840648486
#endif
4840748487
4840848488
#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
4840948489
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
4841048490
48411
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
48491
+#if defined(SQLITE_WIN32_HAS_WIDE)
4841248492
{ "CreateFileW", (SYSCALL)CreateFileW, 0 },
4841348493
#else
4841448494
{ "CreateFileW", (SYSCALL)0, 0 },
4841548495
#endif
4841648496
4841748497
#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
4841848498
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
4841948499
48420
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
48500
+#if defined(SQLITE_WIN32_HAS_ANSI) && \
4842148501
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \
4842248502
SQLITE_WIN32_CREATEFILEMAPPINGA
4842348503
{ "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
4842448504
#else
4842548505
{ "CreateFileMappingA", (SYSCALL)0, 0 },
@@ -48426,21 +48506,21 @@
4842648506
#endif
4842748507
4842848508
#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
4842948509
DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
4843048510
48431
-#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
48432
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
48511
+#if (SQLITE_OS_WINCE || defined(SQLITE_WIN32_HAS_WIDE)) && \
48512
+ (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
4843348513
{ "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
4843448514
#else
4843548515
{ "CreateFileMappingW", (SYSCALL)0, 0 },
4843648516
#endif
4843748517
4843848518
#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
4843948519
DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
4844048520
48441
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
48521
+#if defined(SQLITE_WIN32_HAS_WIDE)
4844248522
{ "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
4844348523
#else
4844448524
{ "CreateMutexW", (SYSCALL)0, 0 },
4844548525
#endif
4844648526
@@ -48522,11 +48602,11 @@
4852248602
#endif
4852348603
4852448604
#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
4852548605
LPDWORD))aSyscall[18].pCurrent)
4852648606
48527
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
48607
+#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
4852848608
{ "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
4852948609
#else
4853048610
{ "GetDiskFreeSpaceW", (SYSCALL)0, 0 },
4853148611
#endif
4853248612
@@ -48539,11 +48619,11 @@
4853948619
{ "GetFileAttributesA", (SYSCALL)0, 0 },
4854048620
#endif
4854148621
4854248622
#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
4854348623
48544
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
48624
+#if defined(SQLITE_WIN32_HAS_WIDE)
4854548625
{ "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
4854648626
#else
4854748627
{ "GetFileAttributesW", (SYSCALL)0, 0 },
4854848628
#endif
4854948629
@@ -48556,15 +48636,11 @@
4855648636
#endif
4855748637
4855848638
#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
4855948639
LPVOID))aSyscall[22].pCurrent)
4856048640
48561
-#if !SQLITE_OS_WINRT
4856248641
{ "GetFileSize", (SYSCALL)GetFileSize, 0 },
48563
-#else
48564
- { "GetFileSize", (SYSCALL)0, 0 },
48565
-#endif
4856648642
4856748643
#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
4856848644
4856948645
#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
4857048646
{ "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 },
@@ -48573,11 +48649,11 @@
4857348649
#endif
4857448650
4857548651
#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
4857648652
LPSTR*))aSyscall[24].pCurrent)
4857748653
48578
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
48654
+#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
4857948655
{ "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
4858048656
#else
4858148657
{ "GetFullPathNameW", (SYSCALL)0, 0 },
4858248658
#endif
4858348659
@@ -48608,20 +48684,14 @@
4860848684
#endif
4860948685
4861048686
#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
4861148687
LPCSTR))aSyscall[27].pCurrent)
4861248688
48613
-#if !SQLITE_OS_WINRT
4861448689
{ "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
48615
-#else
48616
- { "GetSystemInfo", (SYSCALL)0, 0 },
48617
-#endif
48618
-
4861948690
#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
4862048691
4862148692
{ "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
48622
-
4862348693
#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
4862448694
4862548695
#if !SQLITE_OS_WINCE
4862648696
{ "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
4862748697
#else
@@ -48637,23 +48707,19 @@
4863748707
{ "GetTempPathA", (SYSCALL)0, 0 },
4863848708
#endif
4863948709
4864048710
#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
4864148711
48642
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)