|
1
|
/* |
|
2
|
** This is the amalgamated source code to the "sqlite3" or "sqlite3.exe" |
|
3
|
** command-line shell (CLI) for SQLite. This file is automatically |
|
4
|
** generated by the tool/mkshellc.tcl script from the following sources: |
|
5
|
** |
|
6
|
** ext/expert/sqlite3expert.c |
|
7
|
** ext/expert/sqlite3expert.h |
|
8
|
** ext/intck/sqlite3intck.c |
|
9
|
** ext/intck/sqlite3intck.h |
|
10
|
** ext/misc/appendvfs.c |
|
11
|
** ext/misc/base64.c |
|
12
|
** ext/misc/base85.c |
|
13
|
** ext/misc/completion.c |
|
14
|
** ext/misc/decimal.c |
|
15
|
** ext/misc/diskused.c |
|
16
|
** ext/misc/fileio.c |
|
17
|
** ext/misc/ieee754.c |
|
18
|
** ext/misc/memtrace.c |
|
19
|
** ext/misc/optname.c |
|
20
|
** ext/misc/pcachetrace.c |
|
21
|
** ext/misc/regexp.c |
|
22
|
** ext/misc/series.c |
|
23
|
** ext/misc/sha1.c |
|
24
|
** ext/misc/shathree.c |
|
25
|
** ext/misc/sqlar.c |
|
26
|
** ext/misc/sqlite3_stdio.c |
|
27
|
** ext/misc/sqlite3_stdio.h |
|
28
|
** ext/misc/stmtrand.c |
|
29
|
** ext/misc/strdup.c |
|
30
|
** ext/misc/uint.c |
|
31
|
** ext/misc/vfstrace.c |
|
32
|
** ext/misc/windirent.h |
|
33
|
** ext/misc/zipfile.c |
|
34
|
** ext/qrf/qrf.c |
|
35
|
** ext/qrf/qrf.h |
|
36
|
** ext/recover/dbdata.c |
|
37
|
** ext/recover/sqlite3recover.c |
|
38
|
** ext/recover/sqlite3recover.h |
|
39
|
** src/shell.c.in |
|
40
|
** |
|
41
|
** To modify this program, get a copy of the canonical SQLite source tree, |
|
42
|
** edit the src/shell.c.in file and/or some of the other files that are |
|
43
|
** listed above, then rerun the command "make shell.c". |
|
44
|
*/ |
|
45
|
/************************* Begin src/shell.c.in ******************/ |
|
46
|
/* |
|
47
|
** 2001 September 15 |
|
48
|
** |
|
49
|
** The author disclaims copyright to this source code. In place of |
|
50
|
** a legal notice, here is a blessing: |
|
51
|
** |
|
52
|
** May you do good and not evil. |
|
53
|
** May you find forgiveness for yourself and forgive others. |
|
54
|
** May you share freely, never taking more than you give. |
|
55
|
** |
|
56
|
************************************************************************* |
|
57
|
** This file contains code to implement the "sqlite3" command line |
|
58
|
** utility for accessing SQLite databases. |
|
59
|
*/ |
|
60
|
#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) |
|
61
|
/* This needs to come before any includes for MSVC compiler */ |
|
62
|
#define _CRT_SECURE_NO_WARNINGS |
|
63
|
#endif |
|
64
|
typedef unsigned int u32; |
|
65
|
typedef unsigned short int u16; |
|
66
|
|
|
67
|
/* |
|
68
|
** Limit input nesting via .read or any other input redirect. |
|
69
|
** It's not too expensive, so a generous allowance can be made. |
|
70
|
*/ |
|
71
|
#define MAX_INPUT_NESTING 25 |
|
72
|
|
|
73
|
/* |
|
74
|
** Used to prevent warnings about unused parameters |
|
75
|
*/ |
|
76
|
#define UNUSED_PARAMETER(x) (void)(x) |
|
77
|
|
|
78
|
/* |
|
79
|
** Number of elements in an array |
|
80
|
*/ |
|
81
|
#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) |
|
82
|
|
|
83
|
/* |
|
84
|
** Optionally #include a user-defined header, whereby compilation options |
|
85
|
** may be set prior to where they take effect, but after platform setup. |
|
86
|
** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include |
|
87
|
** file. Note that this macro has a like effect on sqlite3.c compilation. |
|
88
|
*/ |
|
89
|
# define SHELL_STRINGIFY_(f) #f |
|
90
|
# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f) |
|
91
|
#ifdef SQLITE_CUSTOM_INCLUDE |
|
92
|
# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE) |
|
93
|
#endif |
|
94
|
|
|
95
|
/* |
|
96
|
** If SQLITE_SHELL_FIDDLE is defined then the shell is modified |
|
97
|
** somewhat for use as a WASM module in a web browser. This flag |
|
98
|
** should only be used when building the "fiddle" web application, as |
|
99
|
** the browser-mode build has much different user input requirements |
|
100
|
** and this build mode rewires the user input subsystem to account for |
|
101
|
** that. |
|
102
|
*/ |
|
103
|
#if defined(SQLITE_SHELL_FIDDLE) |
|
104
|
# undef SQLITE_OMIT_LOAD_EXTENSION |
|
105
|
# define SQLITE_OMIT_LOAD_EXTENSION 1 |
|
106
|
#endif |
|
107
|
|
|
108
|
/* |
|
109
|
** Warning pragmas copied from msvc.h in the core. |
|
110
|
*/ |
|
111
|
#if defined(_MSC_VER) |
|
112
|
#pragma warning(disable : 4054) |
|
113
|
#pragma warning(disable : 4055) |
|
114
|
#pragma warning(disable : 4100) |
|
115
|
#pragma warning(disable : 4127) |
|
116
|
#pragma warning(disable : 4130) |
|
117
|
#pragma warning(disable : 4152) |
|
118
|
#pragma warning(disable : 4189) |
|
119
|
#pragma warning(disable : 4206) |
|
120
|
#pragma warning(disable : 4210) |
|
121
|
#pragma warning(disable : 4232) |
|
122
|
#pragma warning(disable : 4244) |
|
123
|
#pragma warning(disable : 4305) |
|
124
|
#pragma warning(disable : 4306) |
|
125
|
#pragma warning(disable : 4702) |
|
126
|
#pragma warning(disable : 4706) |
|
127
|
#endif /* defined(_MSC_VER) */ |
|
128
|
|
|
129
|
/* |
|
130
|
** No support for loadable extensions in VxWorks. |
|
131
|
*/ |
|
132
|
#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION |
|
133
|
# define SQLITE_OMIT_LOAD_EXTENSION 1 |
|
134
|
#endif |
|
135
|
|
|
136
|
/* |
|
137
|
** Enable large-file support for fopen() and friends on unix. |
|
138
|
*/ |
|
139
|
#ifndef SQLITE_DISABLE_LFS |
|
140
|
# define _LARGE_FILE 1 |
|
141
|
# ifndef _FILE_OFFSET_BITS |
|
142
|
# define _FILE_OFFSET_BITS 64 |
|
143
|
# endif |
|
144
|
# define _LARGEFILE_SOURCE 1 |
|
145
|
#endif |
|
146
|
|
|
147
|
#if defined(SQLITE_SHELL_FIDDLE) && !defined(_POSIX_SOURCE) |
|
148
|
/* |
|
149
|
** emcc requires _POSIX_SOURCE (or one of several similar defines) |
|
150
|
** to expose strdup(). |
|
151
|
*/ |
|
152
|
# define _POSIX_SOURCE |
|
153
|
#endif |
|
154
|
|
|
155
|
#include <stdlib.h> |
|
156
|
#include <string.h> |
|
157
|
#include <stdio.h> |
|
158
|
#include <assert.h> |
|
159
|
#include <math.h> |
|
160
|
#include <stdint.h> |
|
161
|
#include <time.h> |
|
162
|
#include "sqlite3.h" |
|
163
|
typedef sqlite3_int64 i64; |
|
164
|
typedef sqlite3_uint64 u64; |
|
165
|
typedef unsigned char u8; |
|
166
|
#include <ctype.h> |
|
167
|
#include <stdarg.h> |
|
168
|
#ifndef _WIN32 |
|
169
|
# include <sys/time.h> |
|
170
|
# include <sys/ioctl.h> |
|
171
|
#endif |
|
172
|
|
|
173
|
#if !defined(_WIN32) && !defined(WIN32) |
|
174
|
# include <signal.h> |
|
175
|
# if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI) |
|
176
|
# include <pwd.h> |
|
177
|
# endif |
|
178
|
#endif |
|
179
|
#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__) |
|
180
|
# include <unistd.h> |
|
181
|
# include <dirent.h> |
|
182
|
# define GETPID getpid |
|
183
|
# if defined(__MINGW32__) |
|
184
|
# define DIRENT dirent |
|
185
|
# ifndef S_ISLNK |
|
186
|
# define S_ISLNK(mode) (0) |
|
187
|
# endif |
|
188
|
# endif |
|
189
|
#else |
|
190
|
# define GETPID (int)GetCurrentProcessId |
|
191
|
#endif |
|
192
|
#include <sys/types.h> |
|
193
|
#include <sys/stat.h> |
|
194
|
|
|
195
|
#if HAVE_READLINE |
|
196
|
# include <readline/readline.h> |
|
197
|
# include <readline/history.h> |
|
198
|
#elif HAVE_EDITLINE |
|
199
|
/* If both HAVE_READLINE and HAVE_EDITLINE are true, assume that this |
|
200
|
** libedit installation does not have its own headers, instead using |
|
201
|
** those from libreadline. */ |
|
202
|
# include <editline/readline.h> |
|
203
|
#endif |
|
204
|
|
|
205
|
#if HAVE_EDITLINE || HAVE_READLINE |
|
206
|
|
|
207
|
# define shell_add_history(X) add_history(X) |
|
208
|
# define shell_read_history(X) read_history(X) |
|
209
|
# define shell_write_history(X) write_history(X) |
|
210
|
# define shell_stifle_history(X) stifle_history(X) |
|
211
|
# define shell_readline(X) readline(X) |
|
212
|
# define SHELL_CMDLINE_EDIT_AVAILABLE 1 /* command-line editing available */ |
|
213
|
|
|
214
|
#elif HAVE_LINENOISE |
|
215
|
|
|
216
|
# include "linenoise.h" |
|
217
|
# define shell_add_history(X) linenoiseHistoryAdd(X) |
|
218
|
# define shell_read_history(X) linenoiseHistoryLoad(X) |
|
219
|
# define shell_write_history(X) linenoiseHistorySave(X) |
|
220
|
# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) |
|
221
|
# define shell_readline(X) linenoise(X) |
|
222
|
# define SHELL_CMDLINE_EDIT_AVAILABLE 1 /* command-line editing available */ |
|
223
|
|
|
224
|
#else |
|
225
|
|
|
226
|
# define shell_read_history(X) |
|
227
|
# define shell_write_history(X) |
|
228
|
# define shell_stifle_history(X) |
|
229
|
# define SHELL_CMDLINE_EDIT_AVAILABLE 0 /* command-line editing not available */ |
|
230
|
#endif |
|
231
|
|
|
232
|
/* |
|
233
|
** Global variable shellCmdLineEdit determines whether or not command-line |
|
234
|
** editing is enabled. It defaults to 1 if the CLI is linked against a |
|
235
|
** command-line editing library (linenoise, readline, or editline) and |
|
236
|
** to 0 if no command-line editing library is available. The |
|
237
|
** "--cmdline-edit off" command-line option will change this value to 0. |
|
238
|
*/ |
|
239
|
static int shellCmdLineEdit = SHELL_CMDLINE_EDIT_AVAILABLE; |
|
240
|
|
|
241
|
#ifndef deliberate_fall_through |
|
242
|
/* Quiet some compilers about some of our intentional code. */ |
|
243
|
# if defined(GCC_VERSION) && GCC_VERSION>=7000000 |
|
244
|
# define deliberate_fall_through __attribute__((fallthrough)); |
|
245
|
# else |
|
246
|
# define deliberate_fall_through |
|
247
|
# endif |
|
248
|
#endif |
|
249
|
|
|
250
|
#if defined(_WIN32) || defined(WIN32) |
|
251
|
# include <io.h> |
|
252
|
# include <fcntl.h> |
|
253
|
# define isatty(h) _isatty(h) |
|
254
|
# ifndef access |
|
255
|
# define access(f,m) _access((f),(m)) |
|
256
|
# endif |
|
257
|
# ifndef unlink |
|
258
|
# define unlink _unlink |
|
259
|
# endif |
|
260
|
# ifndef strdup |
|
261
|
# define strdup _strdup |
|
262
|
# endif |
|
263
|
# undef pclose |
|
264
|
# define pclose _pclose |
|
265
|
#else |
|
266
|
/* Make sure isatty() has a prototype. */ |
|
267
|
extern int isatty(int); |
|
268
|
|
|
269
|
# if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI) |
|
270
|
/* popen and pclose are not C89 functions and so are |
|
271
|
** sometimes omitted from the <stdio.h> header */ |
|
272
|
extern FILE *popen(const char*,const char*); |
|
273
|
extern int pclose(FILE*); |
|
274
|
# else |
|
275
|
# define SQLITE_OMIT_POPEN 1 |
|
276
|
# endif |
|
277
|
#endif |
|
278
|
|
|
279
|
#if defined(_WIN32_WCE) |
|
280
|
/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() |
|
281
|
* thus we always assume that we have a console. That can be |
|
282
|
* overridden with the -batch command line option. |
|
283
|
*/ |
|
284
|
#define isatty(x) 1 |
|
285
|
#endif |
|
286
|
|
|
287
|
/* ctype macros that work with signed characters */ |
|
288
|
#define IsSpace(X) isspace((unsigned char)X) |
|
289
|
#define IsDigit(X) isdigit((unsigned char)X) |
|
290
|
#define ToLower(X) (char)tolower((unsigned char)X) |
|
291
|
#define IsAlnum(X) isalnum((unsigned char)X) |
|
292
|
#define IsAlpha(X) isalpha((unsigned char)X) |
|
293
|
|
|
294
|
#if defined(_WIN32) || defined(WIN32) |
|
295
|
#undef WIN32_LEAN_AND_MEAN |
|
296
|
#define WIN32_LEAN_AND_MEAN |
|
297
|
#include <windows.h> |
|
298
|
|
|
299
|
/* string conversion routines only needed on Win32 */ |
|
300
|
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR); |
|
301
|
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); |
|
302
|
#endif |
|
303
|
|
|
304
|
/************************* Begin ext/misc/sqlite3_stdio.h ******************/ |
|
305
|
/* |
|
306
|
** 2024-09-24 |
|
307
|
** |
|
308
|
** The author disclaims copyright to this source code. In place of |
|
309
|
** a legal notice, here is a blessing: |
|
310
|
** |
|
311
|
** May you do good and not evil. |
|
312
|
** May you find forgiveness for yourself and forgive others. |
|
313
|
** May you share freely, never taking more than you give. |
|
314
|
** |
|
315
|
************************************************************************* |
|
316
|
** |
|
317
|
** This header file contains definitions of interfaces that provide |
|
318
|
** cross-platform I/O for UTF-8 content. |
|
319
|
** |
|
320
|
** On most platforms, the interfaces definitions in this file are |
|
321
|
** just #defines. For example sqlite3_fopen() is a macro that resolves |
|
322
|
** to the standard fopen() in the C-library. |
|
323
|
** |
|
324
|
** But Windows does not have a standard C-library, at least not one that |
|
325
|
** can handle UTF-8. So for windows build, the interfaces resolve to new |
|
326
|
** C-language routines contained in the separate sqlite3_stdio.c source file. |
|
327
|
** |
|
328
|
** So on all non-Windows platforms, simply #include this header file and |
|
329
|
** use the interfaces defined herein. Then to run your application on Windows, |
|
330
|
** also link in the accompanying sqlite3_stdio.c source file when compiling |
|
331
|
** to get compatible interfaces. |
|
332
|
*/ |
|
333
|
#ifndef _SQLITE3_STDIO_H_ |
|
334
|
#define _SQLITE3_STDIO_H_ 1 |
|
335
|
#ifdef _WIN32 |
|
336
|
/**** Definitions For Windows ****/ |
|
337
|
#include <stdio.h> |
|
338
|
#include <stdarg.h> |
|
339
|
#include <windows.h> |
|
340
|
|
|
341
|
FILE *sqlite3_fopen(const char *zFilename, const char *zMode); |
|
342
|
FILE *sqlite3_popen(const char *zCommand, const char *type); |
|
343
|
char *sqlite3_fgets(char *s, int size, FILE *stream); |
|
344
|
int sqlite3_fputs(const char *s, FILE *stream); |
|
345
|
int sqlite3_fprintf(FILE *stream, const char *format, ...); |
|
346
|
int sqlite3_vfprintf(FILE *stream, const char *format, va_list); |
|
347
|
void sqlite3_fsetmode(FILE *stream, int mode); |
|
348
|
|
|
349
|
|
|
350
|
#else |
|
351
|
/**** Definitions For All Other Platforms ****/ |
|
352
|
#include <stdio.h> |
|
353
|
#define sqlite3_fopen fopen |
|
354
|
#define sqlite3_popen popen |
|
355
|
#define sqlite3_fgets fgets |
|
356
|
#define sqlite3_fputs fputs |
|
357
|
#define sqlite3_fprintf fprintf |
|
358
|
#define sqlite3_vfprintf vfprintf |
|
359
|
#define sqlite3_fsetmode(F,X) /*no-op*/ |
|
360
|
|
|
361
|
#endif |
|
362
|
#endif /* _SQLITE3_STDIO_H_ */ |
|
363
|
|
|
364
|
/************************* End ext/misc/sqlite3_stdio.h ********************/ |
|
365
|
/************************* Begin ext/misc/sqlite3_stdio.c ******************/ |
|
366
|
/* |
|
367
|
** 2024-09-24 |
|
368
|
** |
|
369
|
** The author disclaims copyright to this source code. In place of |
|
370
|
** a legal notice, here is a blessing: |
|
371
|
** |
|
372
|
** May you do good and not evil. |
|
373
|
** May you find forgiveness for yourself and forgive others. |
|
374
|
** May you share freely, never taking more than you give. |
|
375
|
** |
|
376
|
************************************************************************* |
|
377
|
** |
|
378
|
** Implementation of standard I/O interfaces for UTF-8 that are missing |
|
379
|
** on Windows. |
|
380
|
*/ |
|
381
|
#ifdef _WIN32 /* This file is a no-op on all platforms except Windows */ |
|
382
|
#ifndef _SQLITE3_STDIO_H_ |
|
383
|
/* #include "sqlite3_stdio.h" */ |
|
384
|
#endif |
|
385
|
#undef WIN32_LEAN_AND_MEAN |
|
386
|
#define WIN32_LEAN_AND_MEAN |
|
387
|
#include <windows.h> |
|
388
|
#include <stdlib.h> |
|
389
|
#include <string.h> |
|
390
|
#include <stdio.h> |
|
391
|
#include <assert.h> |
|
392
|
/* #include "sqlite3.h" */ |
|
393
|
#include <ctype.h> |
|
394
|
#include <stdarg.h> |
|
395
|
#include <io.h> |
|
396
|
#include <fcntl.h> |
|
397
|
|
|
398
|
/* |
|
399
|
** If the SQLITE_U8TEXT_ONLY option is defined, then use O_U8TEXT |
|
400
|
** when appropriate on all output. (Sometimes use O_BINARY when |
|
401
|
** rendering ASCII text in cases where NL-to-CRLF expansion would |
|
402
|
** not be correct.) |
|
403
|
** |
|
404
|
** If the SQLITE_U8TEXT_STDIO option is defined, then use O_U8TEXT |
|
405
|
** when appropriate when writing to stdout or stderr. Use O_BINARY |
|
406
|
** or O_TEXT (depending on things like the .mode and the .crlf setting |
|
407
|
** in the CLI, or other context clues in other applications) for all |
|
408
|
** other output channels. |
|
409
|
** |
|
410
|
** The default behavior, if neither of the above is defined is to |
|
411
|
** use O_U8TEXT when writing to the Windows console (or anything |
|
412
|
** else for which _isatty() returns true) and to use O_BINARY or O_TEXT |
|
413
|
** for all other output channels. |
|
414
|
** |
|
415
|
** The SQLITE_USE_W32_FOR_CONSOLE_IO macro is also available. If |
|
416
|
** defined, it forces the use of Win32 APIs for all console I/O, both |
|
417
|
** input and output. This is necessary for some non-Microsoft run-times |
|
418
|
** that implement stdio differently from Microsoft/Visual-Studio. |
|
419
|
*/ |
|
420
|
#if defined(SQLITE_U8TEXT_ONLY) |
|
421
|
# define UseWtextForOutput(fd) 1 |
|
422
|
# define UseWtextForInput(fd) 1 |
|
423
|
# define IsConsole(fd) _isatty(_fileno(fd)) |
|
424
|
#elif defined(SQLITE_U8TEXT_STDIO) |
|
425
|
# define UseWtextForOutput(fd) ((fd)==stdout || (fd)==stderr) |
|
426
|
# define UseWtextForInput(fd) ((fd)==stdin) |
|
427
|
# define IsConsole(fd) _isatty(_fileno(fd)) |
|
428
|
#else |
|
429
|
# define UseWtextForOutput(fd) _isatty(_fileno(fd)) |
|
430
|
# define UseWtextForInput(fd) _isatty(_fileno(fd)) |
|
431
|
# define IsConsole(fd) 1 |
|
432
|
#endif |
|
433
|
|
|
434
|
/* |
|
435
|
** Global variables determine if simulated O_BINARY mode is to be |
|
436
|
** used for stdout or other, respectively. Simulated O_BINARY mode |
|
437
|
** means the mode is usually O_BINARY, but switches to O_U8TEXT for |
|
438
|
** unicode characters U+0080 or greater (any character that has a |
|
439
|
** multi-byte representation in UTF-8). This is the only way we |
|
440
|
** have found to render Unicode characters on a Windows console while |
|
441
|
** at the same time avoiding undesirable \n to \r\n translation. |
|
442
|
*/ |
|
443
|
static int simBinaryStdout = 0; |
|
444
|
static int simBinaryOther = 0; |
|
445
|
|
|
446
|
|
|
447
|
/* |
|
448
|
** Determine if simulated binary mode should be used for output to fd |
|
449
|
*/ |
|
450
|
static int UseBinaryWText(FILE *fd){ |
|
451
|
if( fd==stdout || fd==stderr ){ |
|
452
|
return simBinaryStdout; |
|
453
|
}else{ |
|
454
|
return simBinaryOther; |
|
455
|
} |
|
456
|
} |
|
457
|
|
|
458
|
|
|
459
|
/* |
|
460
|
** Work-alike for the fopen() routine from the standard C library. |
|
461
|
*/ |
|
462
|
FILE *sqlite3_fopen(const char *zFilename, const char *zMode){ |
|
463
|
FILE *fp = 0; |
|
464
|
wchar_t *b1, *b2; |
|
465
|
int sz1, sz2; |
|
466
|
|
|
467
|
sz1 = (int)strlen(zFilename); |
|
468
|
sz2 = (int)strlen(zMode); |
|
469
|
b1 = sqlite3_malloc64( (sz1+1)*sizeof(b1[0]) ); |
|
470
|
b2 = sqlite3_malloc64( (sz2+1)*sizeof(b1[0]) ); |
|
471
|
if( b1 && b2 ){ |
|
472
|
sz1 = MultiByteToWideChar(CP_UTF8, 0, zFilename, sz1, b1, sz1); |
|
473
|
b1[sz1] = 0; |
|
474
|
sz2 = MultiByteToWideChar(CP_UTF8, 0, zMode, sz2, b2, sz2); |
|
475
|
b2[sz2] = 0; |
|
476
|
fp = _wfopen(b1, b2); |
|
477
|
} |
|
478
|
sqlite3_free(b1); |
|
479
|
sqlite3_free(b2); |
|
480
|
simBinaryOther = 0; |
|
481
|
return fp; |
|
482
|
} |
|
483
|
|
|
484
|
|
|
485
|
/* |
|
486
|
** Work-alike for the popen() routine from the standard C library. |
|
487
|
*/ |
|
488
|
FILE *sqlite3_popen(const char *zCommand, const char *zMode){ |
|
489
|
FILE *fp = 0; |
|
490
|
wchar_t *b1, *b2; |
|
491
|
int sz1, sz2; |
|
492
|
|
|
493
|
sz1 = (int)strlen(zCommand); |
|
494
|
sz2 = (int)strlen(zMode); |
|
495
|
b1 = sqlite3_malloc64( (sz1+1)*sizeof(b1[0]) ); |
|
496
|
b2 = sqlite3_malloc64( (sz2+1)*sizeof(b1[0]) ); |
|
497
|
if( b1 && b2 ){ |
|
498
|
sz1 = MultiByteToWideChar(CP_UTF8, 0, zCommand, sz1, b1, sz1); |
|
499
|
b1[sz1] = 0; |
|
500
|
sz2 = MultiByteToWideChar(CP_UTF8, 0, zMode, sz2, b2, sz2); |
|
501
|
b2[sz2] = 0; |
|
502
|
fp = _wpopen(b1, b2); |
|
503
|
} |
|
504
|
sqlite3_free(b1); |
|
505
|
sqlite3_free(b2); |
|
506
|
return fp; |
|
507
|
} |
|
508
|
|
|
509
|
/* |
|
510
|
** Work-alike for fgets() from the standard C library. |
|
511
|
*/ |
|
512
|
char *sqlite3_fgets(char *buf, int sz, FILE *in){ |
|
513
|
if( UseWtextForInput(in) ){ |
|
514
|
/* When reading from the command-prompt in Windows, it is necessary |
|
515
|
** to use _O_WTEXT input mode to read UTF-16 characters, then translate |
|
516
|
** that into UTF-8. Otherwise, non-ASCII characters all get translated |
|
517
|
** into '?'. |
|
518
|
*/ |
|
519
|
wchar_t *b1 = sqlite3_malloc64( sz*sizeof(wchar_t) ); |
|
520
|
if( b1==0 ) return 0; |
|
521
|
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO |
|
522
|
DWORD nRead = 0; |
|
523
|
if( IsConsole(in) |
|
524
|
&& ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), b1, sz-1, &nRead, 0) |
|
525
|
){ |
|
526
|
b1[nRead] = 0; |
|
527
|
}else |
|
528
|
#endif |
|
529
|
{ |
|
530
|
_setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT); |
|
531
|
if( fgetws(b1, sz/4, in)==0 ){ |
|
532
|
sqlite3_free(b1); |
|
533
|
return 0; |
|
534
|
} |
|
535
|
} |
|
536
|
WideCharToMultiByte(CP_UTF8, 0, b1, -1, buf, sz, 0, 0); |
|
537
|
sqlite3_free(b1); |
|
538
|
return buf; |
|
539
|
}else{ |
|
540
|
/* Reading from a file or other input source, just read bytes without |
|
541
|
** any translation. */ |
|
542
|
return fgets(buf, sz, in); |
|
543
|
} |
|
544
|
} |
|
545
|
|
|
546
|
/* |
|
547
|
** Send ASCII text as O_BINARY. But for Unicode characters U+0080 and |
|
548
|
** greater, switch to O_U8TEXT. |
|
549
|
*/ |
|
550
|
static void piecemealOutput(wchar_t *b1, int sz, FILE *out){ |
|
551
|
int i; |
|
552
|
wchar_t c; |
|
553
|
while( sz>0 ){ |
|
554
|
for(i=0; i<sz && b1[i]>=0x80; i++){} |
|
555
|
if( i>0 ){ |
|
556
|
c = b1[i]; |
|
557
|
b1[i] = 0; |
|
558
|
fflush(out); |
|
559
|
_setmode(_fileno(out), _O_U8TEXT); |
|
560
|
fputws(b1, out); |
|
561
|
fflush(out); |
|
562
|
b1 += i; |
|
563
|
b1[0] = c; |
|
564
|
sz -= i; |
|
565
|
}else{ |
|
566
|
fflush(out); |
|
567
|
_setmode(_fileno(out), _O_TEXT); |
|
568
|
_setmode(_fileno(out), _O_BINARY); |
|
569
|
fwrite(&b1[0], 1, 1, out); |
|
570
|
for(i=1; i<sz && b1[i]<0x80; i++){ |
|
571
|
fwrite(&b1[i], 1, 1, out); |
|
572
|
} |
|
573
|
fflush(out); |
|
574
|
_setmode(_fileno(out), _O_U8TEXT); |
|
575
|
b1 += i; |
|
576
|
sz -= i; |
|
577
|
} |
|
578
|
} |
|
579
|
} |
|
580
|
|
|
581
|
/* |
|
582
|
** Work-alike for fputs() from the standard C library. |
|
583
|
*/ |
|
584
|
int sqlite3_fputs(const char *z, FILE *out){ |
|
585
|
if( !UseWtextForOutput(out) ){ |
|
586
|
/* Writing to a file or other destination, just write bytes without |
|
587
|
** any translation. */ |
|
588
|
return fputs(z, out); |
|
589
|
}else{ |
|
590
|
/* One must use UTF16 in order to get unicode support when writing |
|
591
|
** to the console on Windows. |
|
592
|
*/ |
|
593
|
int sz = (int)strlen(z); |
|
594
|
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(wchar_t) ); |
|
595
|
if( b1==0 ) return 0; |
|
596
|
sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz); |
|
597
|
b1[sz] = 0; |
|
598
|
|
|
599
|
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO |
|
600
|
DWORD nWr = 0; |
|
601
|
if( IsConsole(out) |
|
602
|
&& WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),b1,sz,&nWr,0) |
|
603
|
){ |
|
604
|
/* If writing to the console, then the WriteConsoleW() is all we |
|
605
|
** need to do. */ |
|
606
|
}else |
|
607
|
#endif |
|
608
|
{ |
|
609
|
/* As long as SQLITE_USE_W32_FOR_CONSOLE_IO is not defined, or for |
|
610
|
** non-console I/O even if that macro is defined, write using the |
|
611
|
** standard library. */ |
|
612
|
_setmode(_fileno(out), _O_U8TEXT); |
|
613
|
if( UseBinaryWText(out) ){ |
|
614
|
piecemealOutput(b1, sz, out); |
|
615
|
}else{ |
|
616
|
fputws(b1, out); |
|
617
|
} |
|
618
|
} |
|
619
|
sqlite3_free(b1); |
|
620
|
return 0; |
|
621
|
} |
|
622
|
} |
|
623
|
|
|
624
|
|
|
625
|
/* |
|
626
|
** Work-alikes for fprintf() and vfprintf() from the standard C library. |
|
627
|
*/ |
|
628
|
int sqlite3_fprintf(FILE *out, const char *zFormat, ...){ |
|
629
|
int rc; |
|
630
|
if( UseWtextForOutput(out) ){ |
|
631
|
/* When writing to the command-prompt in Windows, it is necessary |
|
632
|
** to use _O_WTEXT input mode and write UTF-16 characters. |
|
633
|
*/ |
|
634
|
char *z; |
|
635
|
va_list ap; |
|
636
|
|
|
637
|
va_start(ap, zFormat); |
|
638
|
z = sqlite3_vmprintf(zFormat, ap); |
|
639
|
va_end(ap); |
|
640
|
if( z==0 ) return -1; |
|
641
|
sqlite3_fputs(z, out); |
|
642
|
rc = (int)strlen(z); |
|
643
|
sqlite3_free(z); |
|
644
|
}else{ |
|
645
|
/* Writing to a file or other destination, just write bytes without |
|
646
|
** any translation. */ |
|
647
|
va_list ap; |
|
648
|
va_start(ap, zFormat); |
|
649
|
rc = vfprintf(out, zFormat, ap); |
|
650
|
va_end(ap); |
|
651
|
} |
|
652
|
return rc; |
|
653
|
} |
|
654
|
int sqlite3_vfprintf(FILE *out, const char *zFormat, va_list ap){ |
|
655
|
int rc; |
|
656
|
if( UseWtextForOutput(out) ){ |
|
657
|
/* When writing to the command-prompt in Windows, it is necessary |
|
658
|
** to use _O_WTEXT input mode and write UTF-16 characters. |
|
659
|
*/ |
|
660
|
char *z; |
|
661
|
z = sqlite3_vmprintf(zFormat, ap); |
|
662
|
if( z==0 ) return -1; |
|
663
|
sqlite3_fputs(z, out); |
|
664
|
rc = (int)strlen(z); |
|
665
|
sqlite3_free(z); |
|
666
|
}else{ |
|
667
|
/* Writing to a file or other destination, just write bytes without |
|
668
|
** any translation. */ |
|
669
|
rc = vfprintf(out, zFormat, ap); |
|
670
|
} |
|
671
|
return rc; |
|
672
|
} |
|
673
|
|
|
674
|
/* |
|
675
|
** Set the mode for an output stream. mode argument is typically _O_BINARY or |
|
676
|
** _O_TEXT. |
|
677
|
*/ |
|
678
|
void sqlite3_fsetmode(FILE *fp, int mode){ |
|
679
|
if( !UseWtextForOutput(fp) ){ |
|
680
|
fflush(fp); |
|
681
|
_setmode(_fileno(fp), mode); |
|
682
|
}else if( fp==stdout || fp==stderr ){ |
|
683
|
simBinaryStdout = (mode==_O_BINARY); |
|
684
|
}else{ |
|
685
|
simBinaryOther = (mode==_O_BINARY); |
|
686
|
} |
|
687
|
} |
|
688
|
|
|
689
|
#endif /* defined(_WIN32) */ |
|
690
|
|
|
691
|
/************************* End ext/misc/sqlite3_stdio.c ********************/ |
|
692
|
/************************* Begin ext/qrf/qrf.h ******************/ |
|
693
|
/* |
|
694
|
** 2025-10-20 |
|
695
|
** |
|
696
|
** The author disclaims copyright to this source code. In place of |
|
697
|
** a legal notice, here is a blessing: |
|
698
|
** |
|
699
|
** May you do good and not evil. |
|
700
|
** May you find forgiveness for yourself and forgive others. |
|
701
|
** May you share freely, never taking more than you give. |
|
702
|
** |
|
703
|
************************************************************************* |
|
704
|
** Header file for the Query Result-Format or "qrf" utility library for |
|
705
|
** SQLite. See the README.md documentation for additional information. |
|
706
|
*/ |
|
707
|
#ifndef SQLITE_QRF_H |
|
708
|
#define SQLITE_QRF_H |
|
709
|
#ifdef __cplusplus |
|
710
|
extern "C" { |
|
711
|
#endif |
|
712
|
#include <stdlib.h> |
|
713
|
/* #include "sqlite3.h" */ |
|
714
|
|
|
715
|
/* |
|
716
|
** Specification used by clients to define the output format they want |
|
717
|
*/ |
|
718
|
typedef struct sqlite3_qrf_spec sqlite3_qrf_spec; |
|
719
|
struct sqlite3_qrf_spec { |
|
720
|
unsigned char iVersion; /* Version number of this structure */ |
|
721
|
unsigned char eStyle; /* Formatting style. "box", "csv", etc... */ |
|
722
|
unsigned char eEsc; /* How to escape control characters in text */ |
|
723
|
unsigned char eText; /* Quoting style for text */ |
|
724
|
unsigned char eTitle; /* Quating style for the text of column names */ |
|
725
|
unsigned char eBlob; /* Quoting style for BLOBs */ |
|
726
|
unsigned char bTitles; /* True to show column names */ |
|
727
|
unsigned char bWordWrap; /* Try to wrap on word boundaries */ |
|
728
|
unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */ |
|
729
|
unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */ |
|
730
|
unsigned char eTitleAlign; /* Alignment for column headers */ |
|
731
|
unsigned char bSplitColumn; /* Wrap single-column output into many columns */ |
|
732
|
unsigned char bBorder; /* Show outer border in Box and Table styles */ |
|
733
|
short int nWrap; /* Wrap columns wider than this */ |
|
734
|
short int nScreenWidth; /* Maximum overall table width */ |
|
735
|
short int nLineLimit; /* Maximum number of lines for any row */ |
|
736
|
short int nTitleLimit; /* Maximum number of characters in a title */ |
|
737
|
unsigned int nMultiInsert; /* Add rows to one INSERT until size exceeds */ |
|
738
|
int nCharLimit; /* Maximum number of characters in a cell */ |
|
739
|
int nWidth; /* Number of entries in aWidth[] */ |
|
740
|
int nAlign; /* Number of entries in aAlignment[] */ |
|
741
|
short int *aWidth; /* Column widths */ |
|
742
|
unsigned char *aAlign; /* Column alignments */ |
|
743
|
char *zColumnSep; /* Alternative column separator */ |
|
744
|
char *zRowSep; /* Alternative row separator */ |
|
745
|
char *zTableName; /* Output table name */ |
|
746
|
char *zNull; /* Rendering of NULL */ |
|
747
|
char *(*xRender)(void*,sqlite3_value*); /* Render a value */ |
|
748
|
int (*xWrite)(void*,const char*,sqlite3_int64); /* Write output */ |
|
749
|
void *pRenderArg; /* First argument to the xRender callback */ |
|
750
|
void *pWriteArg; /* First argument to the xWrite callback */ |
|
751
|
char **pzOutput; /* Storage location for output string */ |
|
752
|
/* The following are available in iVersion 2 and later */ |
|
753
|
unsigned char bRowCount; /* Show the number of rows at end of each query */ |
|
754
|
char *zIFmt; /* Format string for integers */ |
|
755
|
char *zFpFmt; /* Format string for floating point */ |
|
756
|
/* Additional fields may be added in the future */ |
|
757
|
}; |
|
758
|
|
|
759
|
/* |
|
760
|
** Interfaces |
|
761
|
*/ |
|
762
|
int sqlite3_format_query_result( |
|
763
|
sqlite3_stmt *pStmt, /* SQL statement to run */ |
|
764
|
const sqlite3_qrf_spec *pSpec, /* Result format specification */ |
|
765
|
char **pzErr /* OUT: Write error message here */ |
|
766
|
); |
|
767
|
|
|
768
|
/* |
|
769
|
** Range of values for sqlite3_qrf_spec.aWidth[] entries. |
|
770
|
*/ |
|
771
|
#define QRF_MAX_WIDTH 10000 |
|
772
|
#define QRF_MIN_WIDTH 0 |
|
773
|
|
|
774
|
/* |
|
775
|
** Output styles: |
|
776
|
*/ |
|
777
|
#define QRF_STYLE_Auto 0 /* Choose a style automatically */ |
|
778
|
#define QRF_STYLE_Box 1 /* Unicode box-drawing characters */ |
|
779
|
#define QRF_STYLE_Column 2 /* One record per line in neat columns */ |
|
780
|
#define QRF_STYLE_Count 3 /* Output only a count of the rows of output */ |
|
781
|
#define QRF_STYLE_Csv 4 /* Comma-separated-value */ |
|
782
|
#define QRF_STYLE_Eqp 5 /* Format EXPLAIN QUERY PLAN output */ |
|
783
|
#define QRF_STYLE_Explain 6 /* EXPLAIN output */ |
|
784
|
#define QRF_STYLE_Html 7 /* Generate HTML-style <tr><td> output */ |
|
785
|
#define QRF_STYLE_Insert 8 /* Generate SQL "insert" statements */ |
|
786
|
#define QRF_STYLE_Json 9 /* Output is a list of JSON objects */ |
|
787
|
#define QRF_STYLE_JObject 10 /* Independent JSON objects for each row */ |
|
788
|
#define QRF_STYLE_Line 11 /* One column per line. */ |
|
789
|
#define QRF_STYLE_List 12 /* One record per line with a separator */ |
|
790
|
#define QRF_STYLE_Markdown 13 /* Markdown formatting */ |
|
791
|
#define QRF_STYLE_Off 14 /* No query output shown */ |
|
792
|
#define QRF_STYLE_Quote 15 /* SQL-quoted, comma-separated */ |
|
793
|
#define QRF_STYLE_Stats 16 /* EQP-like output but with performance stats */ |
|
794
|
#define QRF_STYLE_StatsEst 17 /* EQP-like output with planner estimates */ |
|
795
|
#define QRF_STYLE_StatsVm 18 /* EXPLAIN-like output with performance stats */ |
|
796
|
#define QRF_STYLE_Table 19 /* MySQL-style table formatting */ |
|
797
|
|
|
798
|
/* |
|
799
|
** Quoting styles for text. |
|
800
|
** Allowed values for sqlite3_qrf_spec.eText |
|
801
|
*/ |
|
802
|
#define QRF_TEXT_Auto 0 /* Choose text encoding automatically */ |
|
803
|
#define QRF_TEXT_Plain 1 /* Literal text */ |
|
804
|
#define QRF_TEXT_Sql 2 /* Quote as an SQL literal */ |
|
805
|
#define QRF_TEXT_Csv 3 /* CSV-style quoting */ |
|
806
|
#define QRF_TEXT_Html 4 /* HTML-style quoting */ |
|
807
|
#define QRF_TEXT_Tcl 5 /* C/Tcl quoting */ |
|
808
|
#define QRF_TEXT_Json 6 /* JSON quoting */ |
|
809
|
#define QRF_TEXT_Relaxed 7 /* Relaxed SQL quoting */ |
|
810
|
|
|
811
|
/* |
|
812
|
** Quoting styles for BLOBs |
|
813
|
** Allowed values for sqlite3_qrf_spec.eBlob |
|
814
|
*/ |
|
815
|
#define QRF_BLOB_Auto 0 /* Determine BLOB quoting using eText */ |
|
816
|
#define QRF_BLOB_Text 1 /* Display content exactly as it is */ |
|
817
|
#define QRF_BLOB_Sql 2 /* Quote as an SQL literal */ |
|
818
|
#define QRF_BLOB_Hex 3 /* Hexadecimal representation */ |
|
819
|
#define QRF_BLOB_Tcl 4 /* "\000" notation */ |
|
820
|
#define QRF_BLOB_Json 5 /* A JSON string */ |
|
821
|
#define QRF_BLOB_Size 6 /* Display the blob size only */ |
|
822
|
|
|
823
|
/* |
|
824
|
** Control-character escape modes. |
|
825
|
** Allowed values for sqlite3_qrf_spec.eEsc |
|
826
|
*/ |
|
827
|
#define QRF_ESC_Auto 0 /* Choose the ctrl-char escape automatically */ |
|
828
|
#define QRF_ESC_Off 1 /* Do not escape control characters */ |
|
829
|
#define QRF_ESC_Ascii 2 /* Unix-style escapes. Ex: U+0007 shows ^G */ |
|
830
|
#define QRF_ESC_Symbol 3 /* Unicode escapes. Ex: U+0007 shows U+2407 */ |
|
831
|
|
|
832
|
/* |
|
833
|
** Allowed values for "boolean" fields, such as "bColumnNames", "bWordWrap", |
|
834
|
** and "bTextJsonb". There is an extra "auto" variants so these are actually |
|
835
|
** tri-state settings, not booleans. |
|
836
|
*/ |
|
837
|
#define QRF_SW_Auto 0 /* Let QRF choose the best value */ |
|
838
|
#define QRF_SW_Off 1 /* This setting is forced off */ |
|
839
|
#define QRF_SW_On 2 /* This setting is forced on */ |
|
840
|
#define QRF_Auto 0 /* Alternate spelling for QRF_*_Auto */ |
|
841
|
#define QRF_No 1 /* Alternate spelling for QRF_SW_Off */ |
|
842
|
#define QRF_Yes 2 /* Alternate spelling for QRF_SW_On */ |
|
843
|
|
|
844
|
/* |
|
845
|
** Additional value allowed for bTitles |
|
846
|
*/ |
|
847
|
#define QRF_Always 3 /* Always show titles, even if no rows */ |
|
848
|
|
|
849
|
/* |
|
850
|
** Possible alignment values alignment settings |
|
851
|
** |
|
852
|
** Horizontal Vertial |
|
853
|
** ---------- -------- */ |
|
854
|
#define QRF_ALIGN_Auto 0 /* auto auto */ |
|
855
|
#define QRF_ALIGN_Left 1 /* left auto */ |
|
856
|
#define QRF_ALIGN_Center 2 /* center auto */ |
|
857
|
#define QRF_ALIGN_Right 3 /* right auto */ |
|
858
|
#define QRF_ALIGN_Top 4 /* auto top */ |
|
859
|
#define QRF_ALIGN_NW 5 /* left top */ |
|
860
|
#define QRF_ALIGN_N 6 /* center top */ |
|
861
|
#define QRF_ALIGN_NE 7 /* right top */ |
|
862
|
#define QRF_ALIGN_Middle 8 /* auto middle */ |
|
863
|
#define QRF_ALIGN_W 9 /* left middle */ |
|
864
|
#define QRF_ALIGN_C 10 /* center middle */ |
|
865
|
#define QRF_ALIGN_E 11 /* right middle */ |
|
866
|
#define QRF_ALIGN_Bottom 12 /* auto bottom */ |
|
867
|
#define QRF_ALIGN_SW 13 /* left bottom */ |
|
868
|
#define QRF_ALIGN_S 14 /* center bottom */ |
|
869
|
#define QRF_ALIGN_SE 15 /* right bottom */ |
|
870
|
#define QRF_ALIGN_HMASK 3 /* Horizontal alignment mask */ |
|
871
|
#define QRF_ALIGN_VMASK 12 /* Vertical alignment mask */ |
|
872
|
|
|
873
|
/* |
|
874
|
** Auxiliary routines contined within this module that might be useful |
|
875
|
** in other contexts, and which are therefore exported. |
|
876
|
*/ |
|
877
|
/* |
|
878
|
** Return an estimate of the width, in columns, for the single Unicode |
|
879
|
** character c. For normal characters, the answer is always 1. But the |
|
880
|
** estimate might be 0 or 2 for zero-width and double-width characters. |
|
881
|
** |
|
882
|
** Different devices display unicode using different widths. So |
|
883
|
** it is impossible to know that true display width with 100% accuracy. |
|
884
|
** Inaccuracies in the width estimates might cause columns to be misaligned. |
|
885
|
** Unfortunately, there is nothing we can do about that. |
|
886
|
*/ |
|
887
|
int sqlite3_qrf_wcwidth(int c); |
|
888
|
|
|
889
|
/* |
|
890
|
** Return an estimate of the number of display columns used by the |
|
891
|
** string in the argument. The width of individual characters is |
|
892
|
** determined as for sqlite3_qrf_wcwidth(). VT100 escape code sequences |
|
893
|
** are assigned a width of zero. |
|
894
|
*/ |
|
895
|
size_t sqlite3_qrf_wcswidth(const char*); |
|
896
|
|
|
897
|
/* |
|
898
|
** The argument is a proposed format string for the zIFmt or zFpFmt |
|
899
|
** parameters. Return value indicates: |
|
900
|
** |
|
901
|
** 0 The input is not a valid format string. If this string |
|
902
|
** appears in either zIFmt or zFpFmt, it will be ignored. |
|
903
|
** |
|
904
|
** 1 The input is a valid format string for integers. |
|
905
|
** |
|
906
|
** 2 The input is a valid format string for floating point. |
|
907
|
*/ |
|
908
|
int sqlite3_qrf_ckformat(const char*); |
|
909
|
|
|
910
|
#ifdef __cplusplus |
|
911
|
} |
|
912
|
#endif |
|
913
|
#endif /* !defined(SQLITE_QRF_H) */ |
|
914
|
|
|
915
|
/************************* End ext/qrf/qrf.h ********************/ |
|
916
|
/************************* Begin ext/qrf/qrf.c ******************/ |
|
917
|
/* |
|
918
|
** 2025-10-20 |
|
919
|
** |
|
920
|
** The author disclaims copyright to this source code. In place of |
|
921
|
** a legal notice, here is a blessing: |
|
922
|
** |
|
923
|
** May you do good and not evil. |
|
924
|
** May you find forgiveness for yourself and forgive others. |
|
925
|
** May you share freely, never taking more than you give. |
|
926
|
** |
|
927
|
************************************************************************* |
|
928
|
** Implementation of the Query Result-Format or "qrf" utility library for |
|
929
|
** SQLite. See the README.md documentation for additional information. |
|
930
|
*/ |
|
931
|
#ifndef SQLITE_QRF_H |
|
932
|
#include "qrf.h" |
|
933
|
#endif |
|
934
|
#include <string.h> |
|
935
|
#include <assert.h> |
|
936
|
#include <stdint.h> |
|
937
|
|
|
938
|
#ifndef SQLITE_AMALGAMATION |
|
939
|
/* typedef sqlite3_int64 i64; */ |
|
940
|
#endif |
|
941
|
|
|
942
|
/* A single line in the EQP output */ |
|
943
|
typedef struct qrfEQPGraphRow qrfEQPGraphRow; |
|
944
|
struct qrfEQPGraphRow { |
|
945
|
int iEqpId; /* ID for this row */ |
|
946
|
int iParentId; /* ID of the parent row */ |
|
947
|
qrfEQPGraphRow *pNext; /* Next row in sequence */ |
|
948
|
char zText[1]; /* Text to display for this row */ |
|
949
|
}; |
|
950
|
|
|
951
|
/* All EQP output is collected into an instance of the following */ |
|
952
|
typedef struct qrfEQPGraph qrfEQPGraph; |
|
953
|
struct qrfEQPGraph { |
|
954
|
qrfEQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ |
|
955
|
qrfEQPGraphRow *pLast; /* Last element of the pRow list */ |
|
956
|
int nWidth; /* Width of the graph */ |
|
957
|
char zPrefix[400]; /* Graph prefix */ |
|
958
|
}; |
|
959
|
|
|
960
|
/* |
|
961
|
** Private state information. Subject to change from one release to the |
|
962
|
** next. |
|
963
|
*/ |
|
964
|
typedef struct Qrf Qrf; |
|
965
|
struct Qrf { |
|
966
|
sqlite3_stmt *pStmt; /* The statement whose output is to be rendered */ |
|
967
|
sqlite3 *db; /* The corresponding database connection */ |
|
968
|
sqlite3_stmt *pJTrans; /* JSONB to JSON translator statement */ |
|
969
|
char **pzErr; /* Write error message here, if not NULL */ |
|
970
|
sqlite3_str *pOut; /* Accumulated output */ |
|
971
|
int iErr; /* Error code */ |
|
972
|
int nCol; /* Number of output columns */ |
|
973
|
int expMode; /* Original sqlite3_stmt_isexplain() plus 1 */ |
|
974
|
int mxWidth; /* Screen width */ |
|
975
|
int mxHeight; /* nLineLimit */ |
|
976
|
union { |
|
977
|
struct { /* Content for QRF_STYLE_Line */ |
|
978
|
int mxColWth; /* Maximum display width of any column */ |
|
979
|
char **azCol; /* Names of output columns (MODE_Line) */ |
|
980
|
} sLine; |
|
981
|
qrfEQPGraph *pGraph; /* EQP graph (Eqp, Stats, and StatsEst) */ |
|
982
|
struct { /* Content for QRF_STYLE_Explain */ |
|
983
|
int nIndent; /* Slots allocated for aiIndent */ |
|
984
|
int iIndent; /* Current slot */ |
|
985
|
int *aiIndent; /* Indentation for each opcode */ |
|
986
|
} sExpln; |
|
987
|
unsigned int nIns; /* Bytes used for current INSERT stmt */ |
|
988
|
} u; |
|
989
|
sqlite3_int64 nRow; /* Number of rows handled so far */ |
|
990
|
int *actualWidth; /* Actual width of each column */ |
|
991
|
char zFmt[24]; /* Space to hold the true integer rendering fmt */ |
|
992
|
sqlite3_qrf_spec spec; /* Copy of the original spec */ |
|
993
|
}; |
|
994
|
|
|
995
|
/* |
|
996
|
** Data for substitute ctype.h functions. Used for x-platform |
|
997
|
** consistency and so that '_' is counted as an alphabetic |
|
998
|
** character. |
|
999
|
** |
|
1000
|
** 0x01 - space |
|
1001
|
** 0x02 - digit |
|
1002
|
** 0x04 - alphabetic, including '_' |
|
1003
|
*/ |
|
1004
|
static const char qrfCType[] = { |
|
1005
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, |
|
1006
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1007
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1008
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, |
|
1009
|
0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
|
1010
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 4, |
|
1011
|
0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
|
1012
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, |
|
1013
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1014
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1015
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1016
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1017
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1018
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1019
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1020
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
|
1021
|
}; |
|
1022
|
#define qrfSpace(x) ((qrfCType[(unsigned char)x]&1)!=0) |
|
1023
|
#define qrfDigit(x) ((qrfCType[(unsigned char)x]&2)!=0) |
|
1024
|
#define qrfAlpha(x) ((qrfCType[(unsigned char)x]&4)!=0) |
|
1025
|
#define qrfAlnum(x) ((qrfCType[(unsigned char)x]&6)!=0) |
|
1026
|
|
|
1027
|
#ifndef deliberate_fall_through |
|
1028
|
/* Quiet some compilers about some of our intentional code. */ |
|
1029
|
# if defined(GCC_VERSION) && GCC_VERSION>=7000000 |
|
1030
|
# define deliberate_fall_through __attribute__((fallthrough)); |
|
1031
|
# else |
|
1032
|
# define deliberate_fall_through |
|
1033
|
# endif |
|
1034
|
#endif |
|
1035
|
|
|
1036
|
/* |
|
1037
|
** The argument is a proposed format string for the zIFmt or zFpFmt |
|
1038
|
** parameters. Return value indicates: |
|
1039
|
** |
|
1040
|
** 0 The input is not a valid format string. If this string |
|
1041
|
** appears in either zIFmt or zFpFmt, it will be ignored. |
|
1042
|
** |
|
1043
|
** 1 The input is a valid format string for integers. |
|
1044
|
** |
|
1045
|
** 2 The input is a valid format string for floating point. |
|
1046
|
*/ |
|
1047
|
int sqlite3_qrf_ckformat(const char *z){ |
|
1048
|
size_t n; |
|
1049
|
if( z==0 ) return 0; |
|
1050
|
if( z[0]!='%' ) return 0; |
|
1051
|
z++; |
|
1052
|
n = strspn(z,"+-,#0"); |
|
1053
|
if( n>5 ) return 0; |
|
1054
|
z += n; |
|
1055
|
if( z[0]>='1' && z[0]<='9' ){ |
|
1056
|
n = strspn(z,"0123456789"); |
|
1057
|
if( n>3 ) return 0; |
|
1058
|
z += n; |
|
1059
|
} |
|
1060
|
if( z[0]=='.' ){ |
|
1061
|
z++; |
|
1062
|
n = strspn(z,"0123456789"); |
|
1063
|
if( n>3 ) return 0; |
|
1064
|
z += n; |
|
1065
|
} |
|
1066
|
n = strspn(z,"eEgGf"); |
|
1067
|
if( n==1 && z[1]==0 ) return 2; |
|
1068
|
n = strspn(z,"dxXo"); |
|
1069
|
if( n==1 && z[1]==0 ) return 1; |
|
1070
|
return 0; |
|
1071
|
} |
|
1072
|
|
|
1073
|
|
|
1074
|
/* |
|
1075
|
** Set an error code and error message. |
|
1076
|
*/ |
|
1077
|
static void qrfError( |
|
1078
|
Qrf *p, /* Query result state */ |
|
1079
|
int iCode, /* Error code */ |
|
1080
|
const char *zFormat, /* Message format (or NULL) */ |
|
1081
|
... |
|
1082
|
){ |
|
1083
|
p->iErr = iCode; |
|
1084
|
if( p->pzErr!=0 ){ |
|
1085
|
sqlite3_free(*p->pzErr); |
|
1086
|
*p->pzErr = 0; |
|
1087
|
if( zFormat ){ |
|
1088
|
va_list ap; |
|
1089
|
va_start(ap, zFormat); |
|
1090
|
*p->pzErr = sqlite3_vmprintf(zFormat, ap); |
|
1091
|
va_end(ap); |
|
1092
|
} |
|
1093
|
} |
|
1094
|
} |
|
1095
|
|
|
1096
|
/* |
|
1097
|
** Out-of-memory error. |
|
1098
|
*/ |
|
1099
|
static void qrfOom(Qrf *p){ |
|
1100
|
qrfError(p, SQLITE_NOMEM, "out of memory"); |
|
1101
|
} |
|
1102
|
|
|
1103
|
/* |
|
1104
|
** Transfer any error in pStr over into p. |
|
1105
|
*/ |
|
1106
|
static void qrfStrErr(Qrf *p, sqlite3_str *pStr){ |
|
1107
|
int rc = pStr ? sqlite3_str_errcode(pStr) : 0; |
|
1108
|
if( rc ){ |
|
1109
|
qrfError(p, rc, sqlite3_errstr(rc)); |
|
1110
|
} |
|
1111
|
} |
|
1112
|
|
|
1113
|
|
|
1114
|
/* |
|
1115
|
** Add a new entry to the EXPLAIN QUERY PLAN data |
|
1116
|
*/ |
|
1117
|
static void qrfEqpAppend(Qrf *p, int iEqpId, int p2, const char *zText){ |
|
1118
|
qrfEQPGraphRow *pNew; |
|
1119
|
sqlite3_int64 nText; |
|
1120
|
if( zText==0 ) return; |
|
1121
|
if( p->u.pGraph==0 ){ |
|
1122
|
p->u.pGraph = sqlite3_malloc64( sizeof(qrfEQPGraph) ); |
|
1123
|
if( p->u.pGraph==0 ){ |
|
1124
|
qrfOom(p); |
|
1125
|
return; |
|
1126
|
} |
|
1127
|
memset(p->u.pGraph, 0, sizeof(qrfEQPGraph) ); |
|
1128
|
} |
|
1129
|
nText = strlen(zText); |
|
1130
|
pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); |
|
1131
|
if( pNew==0 ){ |
|
1132
|
qrfOom(p); |
|
1133
|
return; |
|
1134
|
} |
|
1135
|
pNew->iEqpId = iEqpId; |
|
1136
|
pNew->iParentId = p2; |
|
1137
|
memcpy(pNew->zText, zText, nText+1); |
|
1138
|
pNew->pNext = 0; |
|
1139
|
if( p->u.pGraph->pLast ){ |
|
1140
|
p->u.pGraph->pLast->pNext = pNew; |
|
1141
|
}else{ |
|
1142
|
p->u.pGraph->pRow = pNew; |
|
1143
|
} |
|
1144
|
p->u.pGraph->pLast = pNew; |
|
1145
|
} |
|
1146
|
|
|
1147
|
/* |
|
1148
|
** Free and reset the EXPLAIN QUERY PLAN data that has been collected |
|
1149
|
** in p->u.pGraph. |
|
1150
|
*/ |
|
1151
|
static void qrfEqpReset(Qrf *p){ |
|
1152
|
qrfEQPGraphRow *pRow, *pNext; |
|
1153
|
if( p->u.pGraph ){ |
|
1154
|
for(pRow = p->u.pGraph->pRow; pRow; pRow = pNext){ |
|
1155
|
pNext = pRow->pNext; |
|
1156
|
sqlite3_free(pRow); |
|
1157
|
} |
|
1158
|
sqlite3_free(p->u.pGraph); |
|
1159
|
p->u.pGraph = 0; |
|
1160
|
} |
|
1161
|
} |
|
1162
|
|
|
1163
|
/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after |
|
1164
|
** pOld, or return the first such line if pOld is NULL |
|
1165
|
*/ |
|
1166
|
static qrfEQPGraphRow *qrfEqpNextRow(Qrf *p, int iEqpId, qrfEQPGraphRow *pOld){ |
|
1167
|
qrfEQPGraphRow *pRow = pOld ? pOld->pNext : p->u.pGraph->pRow; |
|
1168
|
while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext; |
|
1169
|
return pRow; |
|
1170
|
} |
|
1171
|
|
|
1172
|
/* Render a single level of the graph that has iEqpId as its parent. Called |
|
1173
|
** recursively to render sublevels. |
|
1174
|
*/ |
|
1175
|
static void qrfEqpRenderLevel(Qrf *p, int iEqpId){ |
|
1176
|
qrfEQPGraphRow *pRow, *pNext; |
|
1177
|
i64 n = strlen(p->u.pGraph->zPrefix); |
|
1178
|
char *z; |
|
1179
|
for(pRow = qrfEqpNextRow(p, iEqpId, 0); pRow; pRow = pNext){ |
|
1180
|
pNext = qrfEqpNextRow(p, iEqpId, pRow); |
|
1181
|
z = pRow->zText; |
|
1182
|
sqlite3_str_appendf(p->pOut, "%s%s%s\n", p->u.pGraph->zPrefix, |
|
1183
|
pNext ? "|--" : "`--", z); |
|
1184
|
if( n<(i64)sizeof(p->u.pGraph->zPrefix)-7 ){ |
|
1185
|
memcpy(&p->u.pGraph->zPrefix[n], pNext ? "| " : " ", 4); |
|
1186
|
qrfEqpRenderLevel(p, pRow->iEqpId); |
|
1187
|
p->u.pGraph->zPrefix[n] = 0; |
|
1188
|
} |
|
1189
|
} |
|
1190
|
} |
|
1191
|
|
|
1192
|
/* |
|
1193
|
** Render the 64-bit value N in a more human-readable format into |
|
1194
|
** pOut. |
|
1195
|
** |
|
1196
|
** + Only show the first three significant digits. |
|
1197
|
** + Append suffixes K, M, G, T, P, and E for 1e3, 1e6, ... 1e18 |
|
1198
|
*/ |
|
1199
|
static void qrfApproxInt64(sqlite3_str *pOut, i64 N){ |
|
1200
|
static const char aSuffix[] = { 'K', 'M', 'G', 'T', 'P', 'E' }; |
|
1201
|
int i; |
|
1202
|
if( N<0 ){ |
|
1203
|
N = N==INT64_MIN ? INT64_MAX : -N; |
|
1204
|
sqlite3_str_append(pOut, "-", 1); |
|
1205
|
} |
|
1206
|
if( N<10000 ){ |
|
1207
|
sqlite3_str_appendf(pOut, "%4lld ", N); |
|
1208
|
return; |
|
1209
|
} |
|
1210
|
if( N>=9223372036854775800LL ){ |
|
1211
|
sqlite3_str_appendf(pOut, "%.2fE", 1e-18*(double)N); |
|
1212
|
return; |
|
1213
|
} |
|
1214
|
for(i=1; i<=18; i++){ |
|
1215
|
N = (N+5)/10; |
|
1216
|
if( N<10000 ){ |
|
1217
|
int n = (int)N; |
|
1218
|
switch( i%3 ){ |
|
1219
|
case 0: |
|
1220
|
sqlite3_str_appendf(pOut, "%d.%02d", n/1000, (n%1000)/10); |
|
1221
|
break; |
|
1222
|
case 1: |
|
1223
|
sqlite3_str_appendf(pOut, "%2d.%d", n/100, (n%100)/10); |
|
1224
|
break; |
|
1225
|
case 2: |
|
1226
|
sqlite3_str_appendf(pOut, "%4d", n/10); |
|
1227
|
break; |
|
1228
|
} |
|
1229
|
sqlite3_str_append(pOut, &aSuffix[i/3], 1); |
|
1230
|
break; |
|
1231
|
} |
|
1232
|
} |
|
1233
|
} |
|
1234
|
|
|
1235
|
/* |
|
1236
|
** Display and reset the EXPLAIN QUERY PLAN data |
|
1237
|
*/ |
|
1238
|
static void qrfEqpRender(Qrf *p, i64 nCycle){ |
|
1239
|
qrfEQPGraphRow *pRow; |
|
1240
|
if( p->u.pGraph!=0 && (pRow = p->u.pGraph->pRow)!=0 ){ |
|
1241
|
if( pRow->zText[0]=='-' ){ |
|
1242
|
if( pRow->pNext==0 ){ |
|
1243
|
qrfEqpReset(p); |
|
1244
|
return; |
|
1245
|
} |
|
1246
|
sqlite3_str_appendf(p->pOut, "%s\n", pRow->zText+3); |
|
1247
|
p->u.pGraph->pRow = pRow->pNext; |
|
1248
|
sqlite3_free(pRow); |
|
1249
|
}else if( nCycle>0 ){ |
|
1250
|
int nSp = p->u.pGraph->nWidth - 2; |
|
1251
|
if( p->spec.eStyle==QRF_STYLE_StatsEst ){ |
|
1252
|
sqlite3_str_appendchar(p->pOut, nSp, ' '); |
|
1253
|
sqlite3_str_appendall(p->pOut, |
|
1254
|
"Cycles Loops (est) Rows (est)\n"); |
|
1255
|
sqlite3_str_appendchar(p->pOut, nSp, ' '); |
|
1256
|
sqlite3_str_appendall(p->pOut, |
|
1257
|
"---------- ------------ ------------\n"); |
|
1258
|
}else{ |
|
1259
|
sqlite3_str_appendchar(p->pOut, nSp, ' '); |
|
1260
|
sqlite3_str_appendall(p->pOut, |
|
1261
|
"Cycles Loops Rows \n"); |
|
1262
|
sqlite3_str_appendchar(p->pOut, nSp, ' '); |
|
1263
|
sqlite3_str_appendall(p->pOut, |
|
1264
|
"---------- ----- -----\n"); |
|
1265
|
} |
|
1266
|
sqlite3_str_appendall(p->pOut, "QUERY PLAN"); |
|
1267
|
sqlite3_str_appendchar(p->pOut, nSp - 10, ' '); |
|
1268
|
qrfApproxInt64(p->pOut, nCycle); |
|
1269
|
sqlite3_str_appendall(p->pOut, " 100%\n"); |
|
1270
|
}else{ |
|
1271
|
sqlite3_str_appendall(p->pOut, "QUERY PLAN\n"); |
|
1272
|
} |
|
1273
|
p->u.pGraph->zPrefix[0] = 0; |
|
1274
|
qrfEqpRenderLevel(p, 0); |
|
1275
|
qrfEqpReset(p); |
|
1276
|
} |
|
1277
|
} |
|
1278
|
|
|
1279
|
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
|
1280
|
/* |
|
1281
|
** Helper function for qrfExpStats(). |
|
1282
|
** |
|
1283
|
*/ |
|
1284
|
static int qrfStatsHeight(sqlite3_stmt *p, int iEntry){ |
|
1285
|
int iPid = 0; |
|
1286
|
int ret = 1; |
|
1287
|
sqlite3_stmt_scanstatus_v2(p, iEntry, |
|
1288
|
SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid |
|
1289
|
); |
|
1290
|
while( iPid!=0 ){ |
|
1291
|
int ii; |
|
1292
|
for(ii=0; 1; ii++){ |
|
1293
|
int iId; |
|
1294
|
int res; |
|
1295
|
res = sqlite3_stmt_scanstatus_v2(p, ii, |
|
1296
|
SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iId |
|
1297
|
); |
|
1298
|
if( res ) break; |
|
1299
|
if( iId==iPid ){ |
|
1300
|
sqlite3_stmt_scanstatus_v2(p, ii, |
|
1301
|
SQLITE_SCANSTAT_PARENTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid |
|
1302
|
); |
|
1303
|
} |
|
1304
|
} |
|
1305
|
ret++; |
|
1306
|
} |
|
1307
|
return ret; |
|
1308
|
} |
|
1309
|
#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ |
|
1310
|
|
|
1311
|
|
|
1312
|
/* |
|
1313
|
** Generate ".scanstatus est" style of EQP output. |
|
1314
|
*/ |
|
1315
|
static void qrfEqpStats(Qrf *p){ |
|
1316
|
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS |
|
1317
|
qrfError(p, SQLITE_ERROR, "not available in this build"); |
|
1318
|
#else |
|
1319
|
static const int f = SQLITE_SCANSTAT_COMPLEX; |
|
1320
|
sqlite3_stmt *pS = p->pStmt; |
|
1321
|
int i = 0; |
|
1322
|
i64 nTotal = 0; |
|
1323
|
int nWidth = 0; |
|
1324
|
int prevPid = -1; /* Previous iPid */ |
|
1325
|
double rEstCum = 1.0; /* Cumulative row estimate */ |
|
1326
|
sqlite3_str *pLine = sqlite3_str_new(p->db); |
|
1327
|
sqlite3_str *pStats = sqlite3_str_new(p->db); |
|
1328
|
qrfEqpReset(p); |
|
1329
|
|
|
1330
|
for(i=0; 1; i++){ |
|
1331
|
const char *z = 0; |
|
1332
|
int n = 0; |
|
1333
|
if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){ |
|
1334
|
break; |
|
1335
|
} |
|
1336
|
n = (z ? (int)strlen(z) : 0) + qrfStatsHeight(pS,i)*3; |
|
1337
|
if( n>nWidth ) nWidth = n; |
|
1338
|
} |
|
1339
|
nWidth += 2; |
|
1340
|
|
|
1341
|
sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal); |
|
1342
|
for(i=0; 1; i++){ |
|
1343
|
i64 nLoop = 0; |
|
1344
|
i64 nRow = 0; |
|
1345
|
i64 nCycle = 0; |
|
1346
|
int iId = 0; |
|
1347
|
int iPid = 0; |
|
1348
|
const char *zo = 0; |
|
1349
|
const char *zName = 0; |
|
1350
|
double rEst = 0.0; |
|
1351
|
|
|
1352
|
if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){ |
|
1353
|
break; |
|
1354
|
} |
|
1355
|
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid); |
|
1356
|
if( iPid!=prevPid ){ |
|
1357
|
prevPid = iPid; |
|
1358
|
rEstCum = 1.0; |
|
1359
|
} |
|
1360
|
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst); |
|
1361
|
rEstCum *= rEst; |
|
1362
|
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop); |
|
1363
|
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow); |
|
1364
|
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle); |
|
1365
|
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId); |
|
1366
|
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName); |
|
1367
|
|
|
1368
|
if( nCycle>=0 || nLoop>=0 || nRow>=0 ){ |
|
1369
|
int nSp = 0; |
|
1370
|
sqlite3_str_reset(pStats); |
|
1371
|
if( nCycle>=0 && nTotal>0 ){ |
|
1372
|
qrfApproxInt64(pStats, nCycle); |
|
1373
|
sqlite3_str_appendf(pStats, " %3.0f%%", |
|
1374
|
((100.0*(double)nCycle)+nTotal/2.0) / (double)nTotal |
|
1375
|
); |
|
1376
|
nSp = 2; |
|
1377
|
} |
|
1378
|
if( nLoop>=0 ){ |
|
1379
|
if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' '); |
|
1380
|
qrfApproxInt64(pStats, nLoop); |
|
1381
|
nSp = 2; |
|
1382
|
if( p->spec.eStyle==QRF_STYLE_StatsEst ){ |
|
1383
|
sqlite3_str_appendf(pStats, " "); |
|
1384
|
qrfApproxInt64(pStats, (i64)(rEstCum/rEst)); |
|
1385
|
} |
|
1386
|
} |
|
1387
|
if( nRow>=0 ){ |
|
1388
|
if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' '); |
|
1389
|
qrfApproxInt64(pStats, nRow); |
|
1390
|
if( p->spec.eStyle==QRF_STYLE_StatsEst ){ |
|
1391
|
sqlite3_str_appendf(pStats, " "); |
|
1392
|
qrfApproxInt64(pStats, (i64)rEstCum); |
|
1393
|
} |
|
1394
|
} |
|
1395
|
sqlite3_str_appendf(pLine, |
|
1396
|
"% *s %s", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo, |
|
1397
|
sqlite3_str_value(pStats) |
|
1398
|
); |
|
1399
|
sqlite3_str_reset(pStats); |
|
1400
|
qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine)); |
|
1401
|
sqlite3_str_reset(pLine); |
|
1402
|
}else{ |
|
1403
|
qrfEqpAppend(p, iId, iPid, zo); |
|
1404
|
} |
|
1405
|
} |
|
1406
|
if( p->u.pGraph ) p->u.pGraph->nWidth = nWidth; |
|
1407
|
qrfStrErr(p, pLine); |
|
1408
|
sqlite3_free(sqlite3_str_finish(pLine)); |
|
1409
|
qrfStrErr(p, pStats); |
|
1410
|
sqlite3_free(sqlite3_str_finish(pStats)); |
|
1411
|
#endif |
|
1412
|
} |
|
1413
|
|
|
1414
|
|
|
1415
|
/* |
|
1416
|
** Reset the prepared statement. |
|
1417
|
*/ |
|
1418
|
static void qrfResetStmt(Qrf *p){ |
|
1419
|
int rc = sqlite3_reset(p->pStmt); |
|
1420
|
if( rc!=SQLITE_OK && p->iErr==SQLITE_OK ){ |
|
1421
|
qrfError(p, rc, "%s", sqlite3_errmsg(p->db)); |
|
1422
|
} |
|
1423
|
} |
|
1424
|
|
|
1425
|
/* |
|
1426
|
** If xWrite is defined, send all content of pOut to xWrite and |
|
1427
|
** reset pOut. |
|
1428
|
*/ |
|
1429
|
static void qrfWrite(Qrf *p){ |
|
1430
|
int n; |
|
1431
|
if( p->spec.xWrite && (n = sqlite3_str_length(p->pOut))>0 ){ |
|
1432
|
int rc = p->spec.xWrite(p->spec.pWriteArg, |
|
1433
|
sqlite3_str_value(p->pOut), |
|
1434
|
(sqlite3_int64)n); |
|
1435
|
sqlite3_str_reset(p->pOut); |
|
1436
|
if( rc ){ |
|
1437
|
qrfError(p, rc, "Failed to write %d bytes of output", n); |
|
1438
|
} |
|
1439
|
} |
|
1440
|
} |
|
1441
|
|
|
1442
|
/* Lookup table to estimate the number of columns consumed by a Unicode |
|
1443
|
** character. |
|
1444
|
*/ |
|
1445
|
static const struct { |
|
1446
|
unsigned char w; /* Width of the character in columns */ |
|
1447
|
int iFirst; /* First character in a span having this width */ |
|
1448
|
} aQrfUWidth[] = { |
|
1449
|
/* {1, 0x00000}, */ |
|
1450
|
{0, 0x00300}, {1, 0x00370}, {0, 0x00483}, {1, 0x00487}, {0, 0x00488}, |
|
1451
|
{1, 0x0048a}, {0, 0x00591}, {1, 0x005be}, {0, 0x005bf}, {1, 0x005c0}, |
|
1452
|
{0, 0x005c1}, {1, 0x005c3}, {0, 0x005c4}, {1, 0x005c6}, {0, 0x005c7}, |
|
1453
|
{1, 0x005c8}, {0, 0x00600}, {1, 0x00604}, {0, 0x00610}, {1, 0x00616}, |
|
1454
|
{0, 0x0064b}, {1, 0x0065f}, {0, 0x00670}, {1, 0x00671}, {0, 0x006d6}, |
|
1455
|
{1, 0x006e5}, {0, 0x006e7}, {1, 0x006e9}, {0, 0x006ea}, {1, 0x006ee}, |
|
1456
|
{0, 0x0070f}, {1, 0x00710}, {0, 0x00711}, {1, 0x00712}, {0, 0x00730}, |
|
1457
|
{1, 0x0074b}, {0, 0x007a6}, {1, 0x007b1}, {0, 0x007eb}, {1, 0x007f4}, |
|
1458
|
{0, 0x00901}, {1, 0x00903}, {0, 0x0093c}, {1, 0x0093d}, {0, 0x00941}, |
|
1459
|
{1, 0x00949}, {0, 0x0094d}, {1, 0x0094e}, {0, 0x00951}, {1, 0x00955}, |
|
1460
|
{0, 0x00962}, {1, 0x00964}, {0, 0x00981}, {1, 0x00982}, {0, 0x009bc}, |
|
1461
|
{1, 0x009bd}, {0, 0x009c1}, {1, 0x009c5}, {0, 0x009cd}, {1, 0x009ce}, |
|
1462
|
{0, 0x009e2}, {1, 0x009e4}, {0, 0x00a01}, {1, 0x00a03}, {0, 0x00a3c}, |
|
1463
|
{1, 0x00a3d}, {0, 0x00a41}, {1, 0x00a43}, {0, 0x00a47}, {1, 0x00a49}, |
|
1464
|
{0, 0x00a4b}, {1, 0x00a4e}, {0, 0x00a70}, {1, 0x00a72}, {0, 0x00a81}, |
|
1465
|
{1, 0x00a83}, {0, 0x00abc}, {1, 0x00abd}, {0, 0x00ac1}, {1, 0x00ac6}, |
|
1466
|
{0, 0x00ac7}, {1, 0x00ac9}, {0, 0x00acd}, {1, 0x00ace}, {0, 0x00ae2}, |
|
1467
|
{1, 0x00ae4}, {0, 0x00b01}, {1, 0x00b02}, {0, 0x00b3c}, {1, 0x00b3d}, |
|
1468
|
{0, 0x00b3f}, {1, 0x00b40}, {0, 0x00b41}, {1, 0x00b44}, {0, 0x00b4d}, |
|
1469
|
{1, 0x00b4e}, {0, 0x00b56}, {1, 0x00b57}, {0, 0x00b82}, {1, 0x00b83}, |
|
1470
|
{0, 0x00bc0}, {1, 0x00bc1}, {0, 0x00bcd}, {1, 0x00bce}, {0, 0x00c3e}, |
|
1471
|
{1, 0x00c41}, {0, 0x00c46}, {1, 0x00c49}, {0, 0x00c4a}, {1, 0x00c4e}, |
|
1472
|
{0, 0x00c55}, {1, 0x00c57}, {0, 0x00cbc}, {1, 0x00cbd}, {0, 0x00cbf}, |
|
1473
|
{1, 0x00cc0}, {0, 0x00cc6}, {1, 0x00cc7}, {0, 0x00ccc}, {1, 0x00cce}, |
|
1474
|
{0, 0x00ce2}, {1, 0x00ce4}, {0, 0x00d41}, {1, 0x00d44}, {0, 0x00d4d}, |
|
1475
|
{1, 0x00d4e}, {0, 0x00dca}, {1, 0x00dcb}, {0, 0x00dd2}, {1, 0x00dd5}, |
|
1476
|
{0, 0x00dd6}, {1, 0x00dd7}, {0, 0x00e31}, {1, 0x00e32}, {0, 0x00e34}, |
|
1477
|
{1, 0x00e3b}, {0, 0x00e47}, {1, 0x00e4f}, {0, 0x00eb1}, {1, 0x00eb2}, |
|
1478
|
{0, 0x00eb4}, {1, 0x00eba}, {0, 0x00ebb}, {1, 0x00ebd}, {0, 0x00ec8}, |
|
1479
|
{1, 0x00ece}, {0, 0x00f18}, {1, 0x00f1a}, {0, 0x00f35}, {1, 0x00f36}, |
|
1480
|
{0, 0x00f37}, {1, 0x00f38}, {0, 0x00f39}, {1, 0x00f3a}, {0, 0x00f71}, |
|
1481
|
{1, 0x00f7f}, {0, 0x00f80}, {1, 0x00f85}, {0, 0x00f86}, {1, 0x00f88}, |
|
1482
|
{0, 0x00f90}, {1, 0x00f98}, {0, 0x00f99}, {1, 0x00fbd}, {0, 0x00fc6}, |
|
1483
|
{1, 0x00fc7}, {0, 0x0102d}, {1, 0x01031}, {0, 0x01032}, {1, 0x01033}, |
|
1484
|
{0, 0x01036}, {1, 0x0103b}, {0, 0x01058}, |
|
1485
|
{1, 0x0105a}, {2, 0x01100}, {0, 0x01160}, {1, 0x01200}, {0, 0x0135f}, |
|
1486
|
{1, 0x01360}, {0, 0x01712}, {1, 0x01715}, {0, 0x01732}, {1, 0x01735}, |
|
1487
|
{0, 0x01752}, {1, 0x01754}, {0, 0x01772}, {1, 0x01774}, {0, 0x017b4}, |
|
1488
|
{1, 0x017b6}, {0, 0x017b7}, {1, 0x017be}, {0, 0x017c6}, {1, 0x017c7}, |
|
1489
|
{0, 0x017c9}, {1, 0x017d4}, {0, 0x017dd}, {1, 0x017de}, {0, 0x0180b}, |
|
1490
|
{1, 0x0180e}, {0, 0x018a9}, {1, 0x018aa}, {0, 0x01920}, {1, 0x01923}, |
|
1491
|
{0, 0x01927}, {1, 0x01929}, {0, 0x01932}, {1, 0x01933}, {0, 0x01939}, |
|
1492
|
{1, 0x0193c}, {0, 0x01a17}, {1, 0x01a19}, {0, 0x01b00}, {1, 0x01b04}, |
|
1493
|
{0, 0x01b34}, {1, 0x01b35}, {0, 0x01b36}, {1, 0x01b3b}, {0, 0x01b3c}, |
|
1494
|
{1, 0x01b3d}, {0, 0x01b42}, {1, 0x01b43}, {0, 0x01b6b}, {1, 0x01b74}, |
|
1495
|
{0, 0x01dc0}, {1, 0x01dcb}, {0, 0x01dfe}, {1, 0x01e00}, {0, 0x0200b}, |
|
1496
|
{1, 0x02010}, {0, 0x0202a}, {1, 0x0202f}, {0, 0x02060}, {1, 0x02064}, |
|
1497
|
{0, 0x0206a}, {1, 0x02070}, {0, 0x020d0}, {1, 0x020f0}, {2, 0x02329}, |
|
1498
|
{1, 0x0232b}, {2, 0x02e80}, {0, 0x0302a}, {2, 0x03030}, {1, 0x0303f}, |
|
1499
|
{2, 0x03040}, {0, 0x03099}, {2, 0x0309b}, {1, 0x0a4d0}, {0, 0x0a806}, |
|
1500
|
{1, 0x0a807}, {0, 0x0a80b}, {1, 0x0a80c}, {0, 0x0a825}, {1, 0x0a827}, |
|
1501
|
{2, 0x0ac00}, {1, 0x0d7a4}, {2, 0x0f900}, {1, 0x0fb00}, {0, 0x0fb1e}, |
|
1502
|
{1, 0x0fb1f}, {0, 0x0fe00}, {2, 0x0fe10}, {1, 0x0fe1a}, {0, 0x0fe20}, |
|
1503
|
{1, 0x0fe24}, {2, 0x0fe30}, {1, 0x0fe70}, {0, 0x0feff}, {2, 0x0ff00}, |
|
1504
|
{1, 0x0ff61}, {2, 0x0ffe0}, {1, 0x0ffe7}, {0, 0x0fff9}, {1, 0x0fffc}, |
|
1505
|
{0, 0x10a01}, {1, 0x10a04}, {0, 0x10a05}, {1, 0x10a07}, {0, 0x10a0c}, |
|
1506
|
{1, 0x10a10}, {0, 0x10a38}, {1, 0x10a3b}, {0, 0x10a3f}, {1, 0x10a40}, |
|
1507
|
{0, 0x1d167}, {1, 0x1d16a}, {0, 0x1d173}, {1, 0x1d183}, {0, 0x1d185}, |
|
1508
|
{1, 0x1d18c}, {0, 0x1d1aa}, {1, 0x1d1ae}, {0, 0x1d242}, {1, 0x1d245}, |
|
1509
|
{2, 0x20000}, {1, 0x2fffe}, {2, 0x30000}, {1, 0x3fffe}, {0, 0xe0001}, |
|
1510
|
{1, 0xe0002}, {0, 0xe0020}, {1, 0xe0080}, {0, 0xe0100}, {1, 0xe01f0} |
|
1511
|
}; |
|
1512
|
|
|
1513
|
/* |
|
1514
|
** Return an estimate of the width, in columns, for the single Unicode |
|
1515
|
** character c. For normal characters, the answer is always 1. But the |
|
1516
|
** estimate might be 0 or 2 for zero-width and double-width characters. |
|
1517
|
** |
|
1518
|
** Different display devices display unicode using different widths. So |
|
1519
|
** it is impossible to know that true display width with 100% accuracy. |
|
1520
|
** Inaccuracies in the width estimates might cause columns to be misaligned. |
|
1521
|
** Unfortunately, there is nothing we can do about that. |
|
1522
|
*/ |
|
1523
|
int sqlite3_qrf_wcwidth(int c){ |
|
1524
|
int iFirst, iLast; |
|
1525
|
|
|
1526
|
/* Fast path for common characters */ |
|
1527
|
if( c<0x300 ) return 1; |
|
1528
|
|
|
1529
|
/* The general case */ |
|
1530
|
iFirst = 0; |
|
1531
|
iLast = sizeof(aQrfUWidth)/sizeof(aQrfUWidth[0]) - 1; |
|
1532
|
while( iFirst<iLast-1 ){ |
|
1533
|
int iMid = (iFirst+iLast)/2; |
|
1534
|
int cMid = aQrfUWidth[iMid].iFirst; |
|
1535
|
if( cMid < c ){ |
|
1536
|
iFirst = iMid; |
|
1537
|
}else if( cMid > c ){ |
|
1538
|
iLast = iMid - 1; |
|
1539
|
}else{ |
|
1540
|
return aQrfUWidth[iMid].w; |
|
1541
|
} |
|
1542
|
} |
|
1543
|
if( aQrfUWidth[iLast].iFirst > c ) return aQrfUWidth[iFirst].w; |
|
1544
|
return aQrfUWidth[iLast].w; |
|
1545
|
} |
|
1546
|
|
|
1547
|
/* |
|
1548
|
** Compute the value and length of a multi-byte UTF-8 character that |
|
1549
|
** begins at z[0]. Return the length. Write the Unicode value into *pU. |
|
1550
|
** |
|
1551
|
** This routine only works for *multi-byte* UTF-8 characters. It does |
|
1552
|
** not attempt to detect illegal characters. |
|
1553
|
*/ |
|
1554
|
int sqlite3_qrf_decode_utf8(const unsigned char *z, int *pU){ |
|
1555
|
if( (z[0] & 0xe0)==0xc0 && (z[1] & 0xc0)==0x80 ){ |
|
1556
|
*pU = ((z[0] & 0x1f)<<6) | (z[1] & 0x3f); |
|
1557
|
return 2; |
|
1558
|
} |
|
1559
|
if( (z[0] & 0xf0)==0xe0 && (z[1] & 0xc0)==0x80 && (z[2] & 0xc0)==0x80 ){ |
|
1560
|
*pU = ((z[0] & 0x0f)<<12) | ((z[1] & 0x3f)<<6) | (z[2] & 0x3f); |
|
1561
|
return 3; |
|
1562
|
} |
|
1563
|
if( (z[0] & 0xf8)==0xf0 && (z[1] & 0xc0)==0x80 && (z[2] & 0xc0)==0x80 |
|
1564
|
&& (z[3] & 0xc0)==0x80 |
|
1565
|
){ |
|
1566
|
*pU = ((z[0] & 0x0f)<<18) | ((z[1] & 0x3f)<<12) | ((z[2] & 0x3f))<<6 |
|
1567
|
| (z[3] & 0x3f); |
|
1568
|
return 4; |
|
1569
|
} |
|
1570
|
*pU = 0; |
|
1571
|
return 1; |
|
1572
|
} |
|
1573
|
|
|
1574
|
/* |
|
1575
|
** Check to see if z[] is a valid VT100 escape. If it is, then |
|
1576
|
** return the number of bytes in the escape sequence. Return 0 if |
|
1577
|
** z[] is not a VT100 escape. |
|
1578
|
** |
|
1579
|
** This routine assumes that z[0] is \033 (ESC). |
|
1580
|
*/ |
|
1581
|
static int qrfIsVt100(const unsigned char *z){ |
|
1582
|
int i; |
|
1583
|
if( z[1]!='[' ) return 0; |
|
1584
|
i = 2; |
|
1585
|
while( z[i]>=0x30 && z[i]<=0x3f ){ i++; } |
|
1586
|
while( z[i]>=0x20 && z[i]<=0x2f ){ i++; } |
|
1587
|
if( z[i]<0x40 || z[i]>0x7e ) return 0; |
|
1588
|
return i+1; |
|
1589
|
} |
|
1590
|
|
|
1591
|
/* |
|
1592
|
** Return the length of a string in display characters. |
|
1593
|
** |
|
1594
|
** Most characters of the input string count as 1, including |
|
1595
|
** multi-byte UTF8 characters. However, zero-width unicode |
|
1596
|
** characters and VT100 escape sequences count as zero, and |
|
1597
|
** double-width characters count as two. |
|
1598
|
** |
|
1599
|
** The definition of "zero-width" and "double-width" characters |
|
1600
|
** is not precise. It depends on the output device, to some extent, |
|
1601
|
** and it varies according to the Unicode version. This routine |
|
1602
|
** makes the best guess that it can. |
|
1603
|
*/ |
|
1604
|
size_t sqlite3_qrf_wcswidth(const char *zIn){ |
|
1605
|
const unsigned char *z = (const unsigned char*)zIn; |
|
1606
|
size_t n = 0; |
|
1607
|
while( *z ){ |
|
1608
|
if( z[0]<' ' ){ |
|
1609
|
int k; |
|
1610
|
if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){ |
|
1611
|
z += k; |
|
1612
|
}else{ |
|
1613
|
z++; |
|
1614
|
} |
|
1615
|
}else if( (0x80&z[0])==0 ){ |
|
1616
|
n++; |
|
1617
|
z++; |
|
1618
|
}else{ |
|
1619
|
int u = 0; |
|
1620
|
int len = sqlite3_qrf_decode_utf8(z, &u); |
|
1621
|
z += len; |
|
1622
|
n += sqlite3_qrf_wcwidth(u); |
|
1623
|
} |
|
1624
|
} |
|
1625
|
return n; |
|
1626
|
} |
|
1627
|
|
|
1628
|
/* |
|
1629
|
** Return the display width of the longest line of text |
|
1630
|
** in the (possibly) multi-line input string zIn[0..nByte]. |
|
1631
|
** zIn[] is not necessarily zero-terminated. Take |
|
1632
|
** into account tab characters, zero- and double-width |
|
1633
|
** characters, CR and NL, and VT100 escape codes. |
|
1634
|
** |
|
1635
|
** Write the number of newlines into *pnNL. So, *pnNL will |
|
1636
|
** return 0 if everything fits on one line, or positive it |
|
1637
|
** it will need to be split. |
|
1638
|
*/ |
|
1639
|
static int qrfDisplayWidth(const char *zIn, sqlite3_int64 nByte, int *pnNL){ |
|
1640
|
const unsigned char *z; |
|
1641
|
const unsigned char *zEnd; |
|
1642
|
int mx = 0; |
|
1643
|
int n = 0; |
|
1644
|
int nNL = 0; |
|
1645
|
if( zIn==0 ) zIn = ""; |
|
1646
|
z = (const unsigned char*)zIn; |
|
1647
|
zEnd = &z[nByte]; |
|
1648
|
while( z<zEnd ){ |
|
1649
|
if( z[0]<' ' ){ |
|
1650
|
int k; |
|
1651
|
if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){ |
|
1652
|
z += k; |
|
1653
|
}else{ |
|
1654
|
if( z[0]=='\t' ){ |
|
1655
|
n = (n+8)&~7; |
|
1656
|
}else if( z[0]=='\n' || z[0]=='\r' ){ |
|
1657
|
nNL++; |
|
1658
|
if( n>mx ) mx = n; |
|
1659
|
n = 0; |
|
1660
|
} |
|
1661
|
z++; |
|
1662
|
} |
|
1663
|
}else if( (0x80&z[0])==0 ){ |
|
1664
|
n++; |
|
1665
|
z++; |
|
1666
|
}else{ |
|
1667
|
int u = 0; |
|
1668
|
int len = sqlite3_qrf_decode_utf8(z, &u); |
|
1669
|
z += len; |
|
1670
|
n += sqlite3_qrf_wcwidth(u); |
|
1671
|
} |
|
1672
|
} |
|
1673
|
if( mx>n ) n = mx; |
|
1674
|
if( pnNL ) *pnNL = nNL; |
|
1675
|
return n; |
|
1676
|
} |
|
1677
|
|
|
1678
|
/* |
|
1679
|
** Escape the text starting at byte iStart of pStr, if needed, using the |
|
1680
|
** escape encoding of eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol. |
|
1681
|
** The pStr string is modified appropriately. |
|
1682
|
** |
|
1683
|
** Escaping is needed if the string contains any control characters |
|
1684
|
** other than \t, \n, and \r\n |
|
1685
|
** |
|
1686
|
** If no escaping is needed (the common case) then pStr is unchanged. |
|
1687
|
** If escaping is required, then pStr is expanded and modified to hold |
|
1688
|
** an escaped representation of the text. |
|
1689
|
*/ |
|
1690
|
static void qrfEscape( |
|
1691
|
int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */ |
|
1692
|
sqlite3_str *pStr, /* String to be escaped */ |
|
1693
|
int iStart /* Begin escapding on this byte of pStr */ |
|
1694
|
){ |
|
1695
|
sqlite3_int64 i, j; /* Loop counters */ |
|
1696
|
sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */ |
|
1697
|
unsigned char *zIn; /* Text to be escaped */ |
|
1698
|
unsigned int nIn; /* Bytes of text to be escaped */ |
|
1699
|
unsigned char c; /* A single character of the text */ |
|
1700
|
unsigned char *zOut; /* Where to write the results */ |
|
1701
|
|
|
1702
|
/* Find the text to be escaped */ |
|
1703
|
zIn = (unsigned char*)sqlite3_str_value(pStr); |
|
1704
|
nIn = sqlite3_str_length(pStr); |
|
1705
|
if( zIn==0 ) return; |
|
1706
|
zIn += iStart; |
|
1707
|
nIn -= iStart; |
|
1708
|
|
|
1709
|
/* Count the control characters */ |
|
1710
|
for(i=0; i<nIn; i++){ |
|
1711
|
if( (c = zIn[i])<=0x1f |
|
1712
|
&& c!='\t' |
|
1713
|
&& c!='\n' |
|
1714
|
&& (c!='\r' || zIn[i+1]!='\n') |
|
1715
|
){ |
|
1716
|
nCtrl++; |
|
1717
|
} |
|
1718
|
} |
|
1719
|
if( nCtrl==0 ) return; /* Early out if no control characters */ |
|
1720
|
|
|
1721
|
/* Make space to hold the escapes. Copy the original text to the end |
|
1722
|
** of the available space. */ |
|
1723
|
if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2; |
|
1724
|
sqlite3_str_appendchar(pStr, nCtrl, ' '); |
|
1725
|
zOut = (unsigned char*)sqlite3_str_value(pStr); |
|
1726
|
if( zOut==0 ) return; |
|
1727
|
zOut += iStart; |
|
1728
|
zIn = zOut + nCtrl; |
|
1729
|
memmove(zIn,zOut,nIn); |
|
1730
|
|
|
1731
|
/* Convert the control characters */ |
|
1732
|
for(i=j=0; i<nIn; i++){ |
|
1733
|
if( (c = zIn[i])>0x1f |
|
1734
|
|| c=='\t' |
|
1735
|
|| c=='\n' |
|
1736
|
|| (c=='\r' && zIn[i+1]=='\n') |
|
1737
|
){ |
|
1738
|
continue; |
|
1739
|
} |
|
1740
|
if( i>0 ){ |
|
1741
|
memmove(&zOut[j], zIn, i); |
|
1742
|
j += i; |
|
1743
|
} |
|
1744
|
zIn += i+1; |
|
1745
|
nIn -= i+1; |
|
1746
|
i = -1; |
|
1747
|
if( eEsc==QRF_ESC_Symbol ){ |
|
1748
|
zOut[j++] = 0xe2; |
|
1749
|
zOut[j++] = 0x90; |
|
1750
|
zOut[j++] = 0x80+c; |
|
1751
|
}else{ |
|
1752
|
zOut[j++] = '^'; |
|
1753
|
zOut[j++] = 0x40+c; |
|
1754
|
} |
|
1755
|
} |
|
1756
|
} |
|
1757
|
|
|
1758
|
/* |
|
1759
|
** Determine if the string z[] can be shown as plain text. Return true |
|
1760
|
** if z[] is unambiguously text. Return false if z[] needs to be |
|
1761
|
** quoted. |
|
1762
|
** |
|
1763
|
** All of the following must be true in order for z[] to be relaxable: |
|
1764
|
** |
|
1765
|
** (1) z[] does not begin or end with ' or whitespace |
|
1766
|
** (2) z[] is not the same as the NULL rendering |
|
1767
|
** (3) z[] does not looks like a numeric literal |
|
1768
|
*/ |
|
1769
|
static int qrfRelaxable(Qrf *p, const char *z){ |
|
1770
|
size_t i, n; |
|
1771
|
if( z[0]=='\'' || qrfSpace(z[0]) ) return 0; |
|
1772
|
if( z[0]==0 ){ |
|
1773
|
return (p->spec.zNull!=0 && p->spec.zNull[0]!=0); |
|
1774
|
} |
|
1775
|
n = strlen(z); |
|
1776
|
if( n==0 || z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0; |
|
1777
|
if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0; |
|
1778
|
i = (z[0]=='-' || z[0]=='+'); |
|
1779
|
if( strcmp(z+i,"Inf")==0 ) return 0; |
|
1780
|
if( !qrfDigit(z[i]) ) return 1; |
|
1781
|
i++; |
|
1782
|
while( qrfDigit(z[i]) ){ i++; } |
|
1783
|
if( z[i]==0 ) return 0; |
|
1784
|
if( z[i]=='.' ){ |
|
1785
|
i++; |
|
1786
|
while( qrfDigit(z[i]) ){ i++; } |
|
1787
|
if( z[i]==0 ) return 0; |
|
1788
|
} |
|
1789
|
if( z[i]=='e' || z[i]=='E' ){ |
|
1790
|
i++; |
|
1791
|
if( z[i]=='+' || z[i]=='-' ){ i++; } |
|
1792
|
if( !qrfDigit(z[i]) ) return 1; |
|
1793
|
i++; |
|
1794
|
while( qrfDigit(z[i]) ){ i++; } |
|
1795
|
} |
|
1796
|
return z[i]!=0; |
|
1797
|
} |
|
1798
|
|
|
1799
|
/* |
|
1800
|
** If a field contains any character identified by a 1 in the following |
|
1801
|
** array, then the string must be quoted for CSV. |
|
1802
|
*/ |
|
1803
|
static const char qrfCsvQuote[] = { |
|
1804
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1805
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1806
|
1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1807
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1808
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1809
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1810
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
1811
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, |
|
1812
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1813
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1814
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1815
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1816
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1817
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1818
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1819
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
1820
|
}; |
|
1821
|
|
|
1822
|
/* |
|
1823
|
** Encode text appropriately and append it to pOut. |
|
1824
|
*/ |
|
1825
|
static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){ |
|
1826
|
int iStart = sqlite3_str_length(pOut); |
|
1827
|
switch( p->spec.eText ){ |
|
1828
|
case QRF_TEXT_Relaxed: |
|
1829
|
if( qrfRelaxable(p, zTxt) ){ |
|
1830
|
sqlite3_str_appendall(pOut, zTxt); |
|
1831
|
break; |
|
1832
|
} |
|
1833
|
deliberate_fall_through; /* FALLTHRU */ |
|
1834
|
case QRF_TEXT_Sql: { |
|
1835
|
if( p->spec.eEsc==QRF_ESC_Off ){ |
|
1836
|
sqlite3_str_appendf(pOut, "%Q", zTxt); |
|
1837
|
}else{ |
|
1838
|
sqlite3_str_appendf(pOut, "%#Q", zTxt); |
|
1839
|
} |
|
1840
|
break; |
|
1841
|
} |
|
1842
|
case QRF_TEXT_Csv: { |
|
1843
|
unsigned int i; |
|
1844
|
for(i=0; zTxt[i]; i++){ |
|
1845
|
if( qrfCsvQuote[((const unsigned char*)zTxt)[i]] ){ |
|
1846
|
i = 0; |
|
1847
|
break; |
|
1848
|
} |
|
1849
|
} |
|
1850
|
if( i==0 || strstr(zTxt, p->spec.zColumnSep)!=0 ){ |
|
1851
|
sqlite3_str_appendf(pOut, "\"%w\"", zTxt); |
|
1852
|
}else{ |
|
1853
|
sqlite3_str_appendall(pOut, zTxt); |
|
1854
|
} |
|
1855
|
break; |
|
1856
|
} |
|
1857
|
case QRF_TEXT_Html: { |
|
1858
|
const unsigned char *z = (const unsigned char*)zTxt; |
|
1859
|
while( *z ){ |
|
1860
|
unsigned int i = 0; |
|
1861
|
unsigned char c; |
|
1862
|
while( (c=z[i])>'>' |
|
1863
|
|| (c && c!='<' && c!='>' && c!='&' && c!='\"' && c!='\'') |
|
1864
|
){ |
|
1865
|
i++; |
|
1866
|
} |
|
1867
|
if( i>0 ){ |
|
1868
|
sqlite3_str_append(pOut, (const char*)z, i); |
|
1869
|
} |
|
1870
|
switch( z[i] ){ |
|
1871
|
case '>': sqlite3_str_append(pOut, ">", 4); break; |
|
1872
|
case '&': sqlite3_str_append(pOut, "&", 5); break; |
|
1873
|
case '<': sqlite3_str_append(pOut, "<", 4); break; |
|
1874
|
case '"': sqlite3_str_append(pOut, """, 6); break; |
|
1875
|
case '\'': sqlite3_str_append(pOut, "'", 5); break; |
|
1876
|
default: i--; |
|
1877
|
} |
|
1878
|
z += i + 1; |
|
1879
|
} |
|
1880
|
break; |
|
1881
|
} |
|
1882
|
case QRF_TEXT_Tcl: |
|
1883
|
case QRF_TEXT_Json: { |
|
1884
|
const unsigned char *z = (const unsigned char*)zTxt; |
|
1885
|
sqlite3_str_append(pOut, "\"", 1); |
|
1886
|
while( *z ){ |
|
1887
|
unsigned int i; |
|
1888
|
for(i=0; z[i]>=0x20 && z[i]!='\\' && z[i]!='"'; i++){} |
|
1889
|
if( i>0 ){ |
|
1890
|
sqlite3_str_append(pOut, (const char*)z, i); |
|
1891
|
} |
|
1892
|
if( z[i]==0 ) break; |
|
1893
|
switch( z[i] ){ |
|
1894
|
case '"': sqlite3_str_append(pOut, "\\\"", 2); break; |
|
1895
|
case '\\': sqlite3_str_append(pOut, "\\\\", 2); break; |
|
1896
|
case '\b': sqlite3_str_append(pOut, "\\b", 2); break; |
|
1897
|
case '\f': sqlite3_str_append(pOut, "\\f", 2); break; |
|
1898
|
case '\n': sqlite3_str_append(pOut, "\\n", 2); break; |
|
1899
|
case '\r': sqlite3_str_append(pOut, "\\r", 2); break; |
|
1900
|
case '\t': sqlite3_str_append(pOut, "\\t", 2); break; |
|
1901
|
default: { |
|
1902
|
if( p->spec.eText==QRF_TEXT_Json ){ |
|
1903
|
sqlite3_str_appendf(pOut, "\\u%04x", z[i]); |
|
1904
|
}else{ |
|
1905
|
sqlite3_str_appendf(pOut, "\\%03o", z[i]); |
|
1906
|
} |
|
1907
|
break; |
|
1908
|
} |
|
1909
|
} |
|
1910
|
z += i + 1; |
|
1911
|
} |
|
1912
|
sqlite3_str_append(pOut, "\"", 1); |
|
1913
|
break; |
|
1914
|
} |
|
1915
|
default: { |
|
1916
|
sqlite3_str_appendall(pOut, zTxt); |
|
1917
|
break; |
|
1918
|
} |
|
1919
|
} |
|
1920
|
if( p->spec.eEsc!=QRF_ESC_Off ){ |
|
1921
|
qrfEscape(p->spec.eEsc, pOut, iStart); |
|
1922
|
} |
|
1923
|
} |
|
1924
|
|
|
1925
|
/* |
|
1926
|
** Do a quick sanity check to see aBlob[0..nBlob-1] is valid JSONB |
|
1927
|
** return true if it is and false if it is not. |
|
1928
|
** |
|
1929
|
** False positives are possible, but not false negatives. |
|
1930
|
*/ |
|
1931
|
static int qrfJsonbQuickCheck(unsigned char *aBlob, int nBlob){ |
|
1932
|
unsigned char x; /* Payload size half-byte */ |
|
1933
|
int i; /* Loop counter */ |
|
1934
|
int n; /* Bytes in the payload size integer */ |
|
1935
|
sqlite3_uint64 sz; /* value of the payload size integer */ |
|
1936
|
|
|
1937
|
if( nBlob==0 ) return 0; |
|
1938
|
x = aBlob[0]>>4; |
|
1939
|
if( x<=11 ) return nBlob==(1+x); |
|
1940
|
n = x<14 ? x-11 : 4*(x-13); |
|
1941
|
if( nBlob<1+n ) return 0; |
|
1942
|
sz = aBlob[1]; |
|
1943
|
for(i=1; i<n; i++) sz = (sz<<8) + aBlob[i+1]; |
|
1944
|
return sz+n+1==(sqlite3_uint64)nBlob; |
|
1945
|
} |
|
1946
|
|
|
1947
|
/* |
|
1948
|
** The current iCol-th column of p->pStmt is known to be a BLOB. Check |
|
1949
|
** to see if that BLOB is really a JSONB blob. If it is, then translate |
|
1950
|
** it into a text JSON representation and return a pointer to that text JSON. |
|
1951
|
** If the BLOB is not JSONB, then return a NULL pointer. |
|
1952
|
** |
|
1953
|
** The memory used to hold the JSON text is managed internally by the |
|
1954
|
** "p" object and is overwritten and/or deallocated upon the next call |
|
1955
|
** to this routine (with the same p argument) or when the p object is |
|
1956
|
** finailized. |
|
1957
|
*/ |
|
1958
|
static const char *qrfJsonbToJson(Qrf *p, int iCol){ |
|
1959
|
int nByte; |
|
1960
|
const void *pBlob; |
|
1961
|
int rc; |
|
1962
|
nByte = sqlite3_column_bytes(p->pStmt, iCol); |
|
1963
|
pBlob = sqlite3_column_blob(p->pStmt, iCol); |
|
1964
|
if( qrfJsonbQuickCheck((unsigned char*)pBlob, nByte)==0 ){ |
|
1965
|
return 0; |
|
1966
|
} |
|
1967
|
if( p->pJTrans==0 ){ |
|
1968
|
sqlite3 *db; |
|
1969
|
rc = sqlite3_open(":memory:",&db); |
|
1970
|
if( rc ){ |
|
1971
|
sqlite3_close(db); |
|
1972
|
return 0; |
|
1973
|
} |
|
1974
|
rc = sqlite3_prepare_v2(db, "SELECT json(?1)", -1, &p->pJTrans, 0); |
|
1975
|
if( rc ){ |
|
1976
|
sqlite3_finalize(p->pJTrans); |
|
1977
|
p->pJTrans = 0; |
|
1978
|
sqlite3_close(db); |
|
1979
|
return 0; |
|
1980
|
} |
|
1981
|
}else{ |
|
1982
|
sqlite3_reset(p->pJTrans); |
|
1983
|
} |
|
1984
|
sqlite3_bind_blob(p->pJTrans, 1, (void*)pBlob, nByte, SQLITE_STATIC); |
|
1985
|
rc = sqlite3_step(p->pJTrans); |
|
1986
|
if( rc==SQLITE_ROW ){ |
|
1987
|
return (const char*)sqlite3_column_text(p->pJTrans, 0); |
|
1988
|
}else{ |
|
1989
|
return 0; |
|
1990
|
} |
|
1991
|
} |
|
1992
|
|
|
1993
|
/* |
|
1994
|
** Adjust the input string zIn[] such that it is no more than N display |
|
1995
|
** characters wide. If it is wider than that, then truncate and add |
|
1996
|
** ellipsis. Or if zIn[] contains a \r or \n, truncate at that point, |
|
1997
|
** adding ellipsis. Embedded tabs in zIn[] are converted into ordinary |
|
1998
|
** spaces. |
|
1999
|
** |
|
2000
|
** Return this display width of the modified title string. |
|
2001
|
*/ |
|
2002
|
static int qrfTitleLimit(char *zIn, int N){ |
|
2003
|
unsigned char *z = (unsigned char*)zIn; |
|
2004
|
int n = 0; |
|
2005
|
unsigned char *zEllipsis = 0; |
|
2006
|
while( 1 /*exit-by-break*/ ){ |
|
2007
|
if( z[0]<' ' ){ |
|
2008
|
int k; |
|
2009
|
if( z[0]==0 ){ |
|
2010
|
zEllipsis = 0; |
|
2011
|
break; |
|
2012
|
}else if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){ |
|
2013
|
z += k; |
|
2014
|
}else if( z[0]=='\t' ){ |
|
2015
|
z[0] = ' '; |
|
2016
|
}else if( z[0]=='\n' || z[0]=='\r' ){ |
|
2017
|
z[0] = ' '; |
|
2018
|
}else{ |
|
2019
|
z++; |
|
2020
|
} |
|
2021
|
}else if( (0x80&z[0])==0 ){ |
|
2022
|
if( n>=(N-3) && zEllipsis==0 ) zEllipsis = z; |
|
2023
|
if( n==N ){ z[0] = 0; break; } |
|
2024
|
n++; |
|
2025
|
z++; |
|
2026
|
}else{ |
|
2027
|
int u = 0; |
|
2028
|
int len = sqlite3_qrf_decode_utf8(z, &u); |
|
2029
|
if( n+len>(N-3) && zEllipsis==0 ) zEllipsis = z; |
|
2030
|
if( n+len>N ){ z[0] = 0; break; } |
|
2031
|
z += len; |
|
2032
|
n += sqlite3_qrf_wcwidth(u); |
|
2033
|
} |
|
2034
|
} |
|
2035
|
if( zEllipsis && N>=3 ) memcpy(zEllipsis,"...",4); |
|
2036
|
return n; |
|
2037
|
} |
|
2038
|
|
|
2039
|
|
|
2040
|
/* |
|
2041
|
** Render value pVal into pOut |
|
2042
|
*/ |
|
2043
|
static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){ |
|
2044
|
#if SQLITE_VERSION_NUMBER>=3052000 |
|
2045
|
int iStartLen = sqlite3_str_length(pOut); |
|
2046
|
#endif |
|
2047
|
if( p->spec.xRender ){ |
|
2048
|
sqlite3_value *pVal; |
|
2049
|
char *z; |
|
2050
|
pVal = sqlite3_value_dup(sqlite3_column_value(p->pStmt,iCol)); |
|
2051
|
z = p->spec.xRender(p->spec.pRenderArg, pVal); |
|
2052
|
sqlite3_value_free(pVal); |
|
2053
|
if( z ){ |
|
2054
|
sqlite3_str_appendall(pOut, z); |
|
2055
|
sqlite3_free(z); |
|
2056
|
return; |
|
2057
|
} |
|
2058
|
} |
|
2059
|
switch( sqlite3_column_type(p->pStmt,iCol) ){ |
|
2060
|
case SQLITE_INTEGER: { |
|
2061
|
sqlite3_str_appendf(pOut, p->spec.zIFmt, |
|
2062
|
sqlite3_column_int64(p->pStmt,iCol)); |
|
2063
|
break; |
|
2064
|
} |
|
2065
|
case SQLITE_FLOAT: { |
|
2066
|
if( p->spec.zFpFmt ){ |
|
2067
|
double r = sqlite3_column_double(p->pStmt,iCol); |
|
2068
|
sqlite3_str_appendf(pOut,p->spec.zFpFmt,r); |
|
2069
|
}else{ |
|
2070
|
const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol); |
|
2071
|
sqlite3_str_appendall(pOut, zTxt); |
|
2072
|
} |
|
2073
|
break; |
|
2074
|
} |
|
2075
|
case SQLITE_BLOB: { |
|
2076
|
if( p->spec.bTextJsonb==QRF_Yes ){ |
|
2077
|
const char *zJson = qrfJsonbToJson(p, iCol); |
|
2078
|
if( zJson ){ |
|
2079
|
if( p->spec.eText==QRF_TEXT_Sql ){ |
|
2080
|
sqlite3_str_append(pOut,"jsonb(",6); |
|
2081
|
qrfEncodeText(p, pOut, zJson); |
|
2082
|
sqlite3_str_append(pOut,")",1); |
|
2083
|
}else{ |
|
2084
|
qrfEncodeText(p, pOut, zJson); |
|
2085
|
} |
|
2086
|
break; |
|
2087
|
} |
|
2088
|
} |
|
2089
|
switch( p->spec.eBlob ){ |
|
2090
|
case QRF_BLOB_Hex: |
|
2091
|
case QRF_BLOB_Sql: { |
|
2092
|
int iStart; |
|
2093
|
int nBlob = sqlite3_column_bytes(p->pStmt,iCol); |
|
2094
|
int i, j; |
|
2095
|
char *zVal; |
|
2096
|
const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol); |
|
2097
|
if( p->spec.eBlob==QRF_BLOB_Sql ){ |
|
2098
|
sqlite3_str_append(pOut, "x'", 2); |
|
2099
|
} |
|
2100
|
iStart = sqlite3_str_length(pOut); |
|
2101
|
sqlite3_str_appendchar(pOut, nBlob, ' '); |
|
2102
|
sqlite3_str_appendchar(pOut, nBlob, ' '); |
|
2103
|
if( p->spec.eBlob==QRF_BLOB_Sql ){ |
|
2104
|
sqlite3_str_appendchar(pOut, 1, '\''); |
|
2105
|
} |
|
2106
|
if( sqlite3_str_errcode(pOut) ) return; |
|
2107
|
zVal = sqlite3_str_value(pOut); |
|
2108
|
for(i=0, j=iStart; i<nBlob; i++, j+=2){ |
|
2109
|
unsigned char c = a[i]; |
|
2110
|
zVal[j] = "0123456789abcdef"[(c>>4)&0xf]; |
|
2111
|
zVal[j+1] = "0123456789abcdef"[(c)&0xf]; |
|
2112
|
} |
|
2113
|
break; |
|
2114
|
} |
|
2115
|
case QRF_BLOB_Tcl: |
|
2116
|
case QRF_BLOB_Json: { |
|
2117
|
int iStart; |
|
2118
|
int nBlob = sqlite3_column_bytes(p->pStmt,iCol); |
|
2119
|
int i, j; |
|
2120
|
char *zVal; |
|
2121
|
const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol); |
|
2122
|
int szC = p->spec.eBlob==QRF_BLOB_Json ? 6 : 4; |
|
2123
|
sqlite3_str_append(pOut, "\"", 1); |
|
2124
|
iStart = sqlite3_str_length(pOut); |
|
2125
|
for(i=szC; i>0; i--){ |
|
2126
|
sqlite3_str_appendchar(pOut, nBlob, ' '); |
|
2127
|
} |
|
2128
|
sqlite3_str_appendchar(pOut, 1, '"'); |
|
2129
|
if( sqlite3_str_errcode(pOut) ) return; |
|
2130
|
zVal = sqlite3_str_value(pOut); |
|
2131
|
for(i=0, j=iStart; i<nBlob; i++, j+=szC){ |
|
2132
|
unsigned char c = a[i]; |
|
2133
|
zVal[j] = '\\'; |
|
2134
|
if( szC==4 ){ |
|
2135
|
zVal[j+1] = '0' + ((c>>6)&3); |
|
2136
|
zVal[j+2] = '0' + ((c>>3)&7); |
|
2137
|
zVal[j+3] = '0' + (c&7); |
|
2138
|
}else{ |
|
2139
|
zVal[j+1] = 'u'; |
|
2140
|
zVal[j+2] = '0'; |
|
2141
|
zVal[j+3] = '0'; |
|
2142
|
zVal[j+4] = "0123456789abcdef"[(c>>4)&0xf]; |
|
2143
|
zVal[j+5] = "0123456789abcdef"[(c)&0xf]; |
|
2144
|
} |
|
2145
|
} |
|
2146
|
break; |
|
2147
|
} |
|
2148
|
case QRF_BLOB_Size: { |
|
2149
|
int nBlob = sqlite3_column_bytes(p->pStmt,iCol); |
|
2150
|
sqlite3_str_appendf(pOut, "(%d-byte blob)", nBlob); |
|
2151
|
break; |
|
2152
|
} |
|
2153
|
default: { |
|
2154
|
const void *pBlob = sqlite3_column_blob(p->pStmt,iCol); |
|
2155
|
int nBlob = sqlite3_column_bytes(p->pStmt,iCol); |
|
2156
|
int rc; |
|
2157
|
qrfWrite(p); |
|
2158
|
if( nBlob==0 ){ |
|
2159
|
/* no-op */ |
|
2160
|
}else if( p->spec.eEsc==QRF_ESC_Off ){ |
|
2161
|
rc = p->spec.xWrite(p->spec.pWriteArg,pBlob,nBlob); |
|
2162
|
if( rc ){ |
|
2163
|
qrfError(p, rc, "Failed to write %d bytes of BLOB output", nBlob); |
|
2164
|
} |
|
2165
|
}else{ |
|
2166
|
sqlite3_str_append(pOut, pBlob, nBlob); |
|
2167
|
qrfEscape(p->spec.eEsc, pOut, 0); |
|
2168
|
qrfWrite(p); |
|
2169
|
} |
|
2170
|
} |
|
2171
|
} |
|
2172
|
break; |
|
2173
|
} |
|
2174
|
case SQLITE_NULL: { |
|
2175
|
sqlite3_str_appendall(pOut, p->spec.zNull); |
|
2176
|
break; |
|
2177
|
} |
|
2178
|
case SQLITE_TEXT: { |
|
2179
|
const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol); |
|
2180
|
qrfEncodeText(p, pOut, zTxt); |
|
2181
|
break; |
|
2182
|
} |
|
2183
|
} |
|
2184
|
#if SQLITE_VERSION_NUMBER>=3052000 |
|
2185
|
if( p->spec.nCharLimit>0 |
|
2186
|
&& (sqlite3_str_length(pOut) - iStartLen) > p->spec.nCharLimit |
|
2187
|
){ |
|
2188
|
const unsigned char *z; |
|
2189
|
int ii = 0, w = 0, limit = p->spec.nCharLimit; |
|
2190
|
z = (const unsigned char*)sqlite3_str_value(pOut) + iStartLen; |
|
2191
|
if( limit<4 ) limit = 4; |
|
2192
|
while( 1 ){ |
|
2193
|
if( z[ii]<' ' ){ |
|
2194
|
int k; |
|
2195
|
if( z[ii]=='\033' && (k = qrfIsVt100(z+ii))>0 ){ |
|
2196
|
ii += k; |
|
2197
|
}else if( z[ii]==0 ){ |
|
2198
|
break; |
|
2199
|
}else{ |
|
2200
|
ii++; |
|
2201
|
} |
|
2202
|
}else if( (0x80&z[ii])==0 ){ |
|
2203
|
w++; |
|
2204
|
if( w>limit ) break; |
|
2205
|
ii++; |
|
2206
|
}else{ |
|
2207
|
int u = 0; |
|
2208
|
int len = sqlite3_qrf_decode_utf8(&z[ii], &u); |
|
2209
|
w += sqlite3_qrf_wcwidth(u); |
|
2210
|
if( w>limit ) break; |
|
2211
|
ii += len; |
|
2212
|
} |
|
2213
|
} |
|
2214
|
if( w>limit ){ |
|
2215
|
sqlite3_str_truncate(pOut, iStartLen+ii); |
|
2216
|
sqlite3_str_append(pOut, "...", 3); |
|
2217
|
} |
|
2218
|
} |
|
2219
|
#endif |
|
2220
|
} |
|
2221
|
|
|
2222
|
/* Trim spaces of the end if pOut |
|
2223
|
*/ |
|
2224
|
static void qrfRTrim(sqlite3_str *pOut){ |
|
2225
|
#if SQLITE_VERSION_NUMBER>=3052000 |
|
2226
|
int nByte = sqlite3_str_length(pOut); |
|
2227
|
const char *zOut = sqlite3_str_value(pOut); |
|
2228
|
while( nByte>0 && zOut[nByte-1]==' ' ){ nByte--; } |
|
2229
|
sqlite3_str_truncate(pOut, nByte); |
|
2230
|
#endif |
|
2231
|
} |
|
2232
|
|
|
2233
|
/* |
|
2234
|
** Store string zUtf to pOut as w characters. If w is negative, |
|
2235
|
** then right-justify the text. W is the width in display characters, not |
|
2236
|
** in bytes. Double-width unicode characters count as two characters. |
|
2237
|
** VT100 escape sequences count as zero. And so forth. |
|
2238
|
*/ |
|
2239
|
static void qrfWidthPrint(Qrf *p, sqlite3_str *pOut, int w, const char *zUtf){ |
|
2240
|
const unsigned char *a = (const unsigned char*)zUtf; |
|
2241
|
static const int mxW = 10000000; |
|
2242
|
unsigned char c; |
|
2243
|
int i = 0; |
|
2244
|
int n = 0; |
|
2245
|
int k; |
|
2246
|
int aw; |
|
2247
|
(void)p; |
|
2248
|
if( w<-mxW ){ |
|
2249
|
w = -mxW; |
|
2250
|
}else if( w>mxW ){ |
|
2251
|
w= mxW; |
|
2252
|
} |
|
2253
|
aw = w<0 ? -w : w; |
|
2254
|
if( a==0 ) a = (const unsigned char*)""; |
|
2255
|
while( (c = a[i])!=0 ){ |
|
2256
|
if( (c&0xc0)==0xc0 ){ |
|
2257
|
int u; |
|
2258
|
int len = sqlite3_qrf_decode_utf8(a+i, &u); |
|
2259
|
int x = sqlite3_qrf_wcwidth(u); |
|
2260
|
if( x+n>aw ){ |
|
2261
|
break; |
|
2262
|
} |
|
2263
|
i += len; |
|
2264
|
n += x; |
|
2265
|
}else if( c==0x1b && (k = qrfIsVt100(&a[i]))>0 ){ |
|
2266
|
i += k; |
|
2267
|
}else if( n>=aw ){ |
|
2268
|
break; |
|
2269
|
}else{ |
|
2270
|
n++; |
|
2271
|
i++; |
|
2272
|
} |
|
2273
|
} |
|
2274
|
if( n>=aw ){ |
|
2275
|
sqlite3_str_append(pOut, zUtf, i); |
|
2276
|
}else if( w<0 ){ |
|
2277
|
if( aw>n ) sqlite3_str_appendchar(pOut, aw-n, ' '); |
|
2278
|
sqlite3_str_append(pOut, zUtf, i); |
|
2279
|
}else{ |
|
2280
|
sqlite3_str_append(pOut, zUtf, i); |
|
2281
|
if( aw>n ) sqlite3_str_appendchar(pOut, aw-n, ' '); |
|
2282
|
} |
|
2283
|
} |
|
2284
|
|
|
2285
|
/* |
|
2286
|
** (*pz)[] is a line of text that is to be displayed the box or table or |
|
2287
|
** similar tabular formats. z[] contain newlines or might be too wide |
|
2288
|
** to fit in the columns so will need to be split into multiple line. |
|
2289
|
** |
|
2290
|
** This routine determines: |
|
2291
|
** |
|
2292
|
** * How many bytes of z[] should be shown on the current line. |
|
2293
|
** * How many character positions those bytes will cover. |
|
2294
|
** * The byte offset to the start of the next line. |
|
2295
|
*/ |
|
2296
|
static void qrfWrapLine( |
|
2297
|
const char *zIn, /* Input text to be displayed */ |
|
2298
|
int w, /* Column width in characters (not bytes) */ |
|
2299
|
int bWrap, /* True if we should do word-wrapping */ |
|
2300
|
int *pnThis, /* OUT: How many bytes of z[] for the current line */ |
|
2301
|
int *pnWide, /* OUT: How wide is the text of this line */ |
|
2302
|
int *piNext /* OUT: Offset into z[] to start of the next line */ |
|
2303
|
){ |
|
2304
|
int i; /* Input bytes consumed */ |
|
2305
|
int k; /* Bytes in a VT100 code */ |
|
2306
|
int n; /* Output column number */ |
|
2307
|
const unsigned char *z = (const unsigned char*)zIn; |
|
2308
|
unsigned char c = 0; |
|
2309
|
|
|
2310
|
if( z[0]==0 ){ |
|
2311
|
*pnThis = 0; |
|
2312
|
*pnWide = 0; |
|
2313
|
*piNext = 0; |
|
2314
|
return; |
|
2315
|
} |
|
2316
|
n = 0; |
|
2317
|
for(i=0; n<=w; i++){ |
|
2318
|
c = z[i]; |
|
2319
|
if( c>=0xc0 ){ |
|
2320
|
int u; |
|
2321
|
int len = sqlite3_qrf_decode_utf8(&z[i], &u); |
|
2322
|
int wcw = sqlite3_qrf_wcwidth(u); |
|
2323
|
if( wcw+n>w ) break; |
|
2324
|
i += len-1; |
|
2325
|
n += wcw; |
|
2326
|
continue; |
|
2327
|
} |
|
2328
|
if( c>=' ' ){ |
|
2329
|
if( n==w ) break; |
|
2330
|
n++; |
|
2331
|
continue; |
|
2332
|
} |
|
2333
|
if( c==0 || c=='\n' ) break; |
|
2334
|
if( c=='\r' && z[i+1]=='\n' ){ c = z[++i]; break; } |
|
2335
|
if( c=='\t' ){ |
|
2336
|
int wcw = 8 - (n&7); |
|
2337
|
if( n+wcw>w ) break; |
|
2338
|
n += wcw; |
|
2339
|
continue; |
|
2340
|
} |
|
2341
|
if( c==0x1b && (k = qrfIsVt100(&z[i]))>0 ){ |
|
2342
|
i += k-1; |
|
2343
|
}else if( n==w ){ |
|
2344
|
break; |
|
2345
|
}else{ |
|
2346
|
n++; |
|
2347
|
} |
|
2348
|
} |
|
2349
|
if( c==0 ){ |
|
2350
|
*pnThis = i; |
|
2351
|
*pnWide = n; |
|
2352
|
*piNext = i; |
|
2353
|
return; |
|
2354
|
} |
|
2355
|
if( c=='\n' ){ |
|
2356
|
*pnThis = i; |
|
2357
|
*pnWide = n; |
|
2358
|
*piNext = i+1; |
|
2359
|
return; |
|
2360
|
} |
|
2361
|
|
|
2362
|
/* If we get this far, that means the current line will end at some |
|
2363
|
** point that is neither a "\n" or a 0x00. Figure out where that |
|
2364
|
** split should occur |
|
2365
|
*/ |
|
2366
|
if( bWrap && z[i]!=0 && !qrfSpace(z[i]) && qrfAlnum(c)==qrfAlnum(z[i]) ){ |
|
2367
|
/* Perhaps try to back up to a better place to break the line */ |
|
2368
|
for(k=i-1; k>=i/2; k--){ |
|
2369
|
if( qrfSpace(z[k]) ) break; |
|
2370
|
} |
|
2371
|
if( k<i/2 && i/2>0 ){ |
|
2372
|
for(k=i; k>=i/2; k--){ |
|
2373
|
if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break; |
|
2374
|
} |
|
2375
|
} |
|
2376
|
if( k>=i/2 ){ |
|
2377
|
i = k; |
|
2378
|
n = qrfDisplayWidth((const char*)z, k, 0); |
|
2379
|
} |
|
2380
|
} |
|
2381
|
*pnThis = i; |
|
2382
|
*pnWide = n; |
|
2383
|
while( zIn[i]==' ' || zIn[i]=='\t' || zIn[i]=='\r' ){ i++; } |
|
2384
|
*piNext = i; |
|
2385
|
} |
|
2386
|
|
|
2387
|
/* |
|
2388
|
** Append nVal bytes of text from zVal onto the end of pOut. |
|
2389
|
** Convert tab characters in zVal to the appropriate number of |
|
2390
|
** spaces. |
|
2391
|
*/ |
|
2392
|
static void qrfAppendWithTabs( |
|
2393
|
sqlite3_str *pOut, /* Append text here */ |
|
2394
|
const char *zVal, /* Text to append */ |
|
2395
|
int nVal /* Use only the first nVal bytes of zVal[] */ |
|
2396
|
){ |
|
2397
|
int i = 0; |
|
2398
|
unsigned int col = 0; |
|
2399
|
unsigned char *z = (unsigned char *)zVal; |
|
2400
|
while( i<nVal ){ |
|
2401
|
unsigned char c = z[i]; |
|
2402
|
if( c<' ' ){ |
|
2403
|
int k; |
|
2404
|
sqlite3_str_append(pOut, (const char*)z, i); |
|
2405
|
nVal -= i; |
|
2406
|
z += i; |
|
2407
|
i = 0; |
|
2408
|
if( c=='\033' && (k = qrfIsVt100(z))>0 ){ |
|
2409
|
sqlite3_str_append(pOut, (const char*)z, k); |
|
2410
|
z += k; |
|
2411
|
nVal -= k; |
|
2412
|
}else if( c=='\t' ){ |
|
2413
|
k = 8 - (col&7); |
|
2414
|
sqlite3_str_appendchar(pOut, k, ' '); |
|
2415
|
col += k; |
|
2416
|
z++; |
|
2417
|
nVal--; |
|
2418
|
}else if( c=='\r' && nVal==1 ){ |
|
2419
|
z++; |
|
2420
|
nVal--; |
|
2421
|
}else{ |
|
2422
|
char zCtrlPik[4]; |
|
2423
|
col++; |
|
2424
|
zCtrlPik[0] = 0xe2; |
|
2425
|
zCtrlPik[1] = 0x90; |
|
2426
|
zCtrlPik[2] = 0x80+c; |
|
2427
|
sqlite3_str_append(pOut, zCtrlPik, 3); |
|
2428
|
z++; |
|
2429
|
nVal--; |
|
2430
|
} |
|
2431
|
}else if( (0x80&c)==0 ){ |
|
2432
|
i++; |
|
2433
|
col++; |
|
2434
|
}else{ |
|
2435
|
int u = 0; |
|
2436
|
int len = sqlite3_qrf_decode_utf8(&z[i], &u); |
|
2437
|
i += len; |
|
2438
|
col += sqlite3_qrf_wcwidth(u); |
|
2439
|
} |
|
2440
|
} |
|
2441
|
sqlite3_str_append(pOut, (const char*)z, i); |
|
2442
|
} |
|
2443
|
|
|
2444
|
/* |
|
2445
|
** GCC does not define the offsetof() macro so we'll have to do it |
|
2446
|
** ourselves. |
|
2447
|
*/ |
|
2448
|
#ifndef offsetof |
|
2449
|
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) |
|
2450
|
#endif |
|
2451
|
|
|
2452
|
/* |
|
2453
|
** Data for columnar layout, collected into a single object so |
|
2454
|
** that it can be more easily passed into subroutines. |
|
2455
|
*/ |
|
2456
|
typedef struct qrfColData qrfColData; |
|
2457
|
struct qrfColData { |
|
2458
|
Qrf *p; /* The QRF instance */ |
|
2459
|
int nCol; /* Number of columns in the table */ |
|
2460
|
unsigned char bMultiRow; /* One or more cells will span multiple lines */ |
|
2461
|
unsigned char nMargin; /* Width of column margins */ |
|
2462
|
sqlite3_int64 nRow; /* Number of rows */ |
|
2463
|
sqlite3_int64 nAlloc; /* Number of cells allocated */ |
|
2464
|
sqlite3_int64 n; /* Number of cells. nCol*nRow */ |
|
2465
|
char **az; /* Content of all cells */ |
|
2466
|
int *aiWth; /* Width of each cell */ |
|
2467
|
unsigned char *abNum; /* True for each numeric cell */ |
|
2468
|
struct qrfPerCol { /* Per-column data */ |
|
2469
|
char *z; /* Cache of text for current row */ |
|
2470
|
int w; /* Computed width of this column */ |
|
2471
|
int mxW; /* Maximum natural (unwrapped) width */ |
|
2472
|
unsigned char e; /* Alignment */ |
|
2473
|
unsigned char fx; /* Width is fixed */ |
|
2474
|
unsigned char bNum; /* True if is numeric */ |
|
2475
|
} *a; /* One per column */ |
|
2476
|
}; |
|
2477
|
|
|
2478
|
/* |
|
2479
|
** Output horizontally justified text into pOut. The text is the |
|
2480
|
** first nVal bytes of zVal. Include nWS bytes of whitespace, either |
|
2481
|
** split between both sides, or on the left, or on the right, depending |
|
2482
|
** on eAlign. |
|
2483
|
*/ |
|
2484
|
static void qrfPrintAligned( |
|
2485
|
sqlite3_str *pOut, /* Append text here */ |
|
2486
|
struct qrfPerCol *pCol, /* Information about the text to print */ |
|
2487
|
int nVal, /* Use only the first nVal bytes of zVal[] */ |
|
2488
|
int nWS /* Whitespace for horizonal alignment */ |
|
2489
|
){ |
|
2490
|
unsigned char eAlign = pCol->e & QRF_ALIGN_HMASK; |
|
2491
|
if( eAlign==QRF_Auto && pCol->bNum ) eAlign = QRF_ALIGN_Right; |
|
2492
|
if( eAlign==QRF_ALIGN_Center ){ |
|
2493
|
/* Center the text */ |
|
2494
|
sqlite3_str_appendchar(pOut, nWS/2, ' '); |
|
2495
|
qrfAppendWithTabs(pOut, pCol->z, nVal); |
|
2496
|
sqlite3_str_appendchar(pOut, nWS - nWS/2, ' '); |
|
2497
|
}else if( eAlign==QRF_ALIGN_Right ){ |
|
2498
|
/* Right justify the text */ |
|
2499
|
sqlite3_str_appendchar(pOut, nWS, ' '); |
|
2500
|
qrfAppendWithTabs(pOut, pCol->z, nVal); |
|
2501
|
}else{ |
|
2502
|
/* Left justify the text */ |
|
2503
|
qrfAppendWithTabs(pOut, pCol->z, nVal); |
|
2504
|
sqlite3_str_appendchar(pOut, nWS, ' '); |
|
2505
|
} |
|
2506
|
} |
|
2507
|
|
|
2508
|
/* |
|
2509
|
** Free all the memory allocates in the qrfColData object |
|
2510
|
*/ |
|
2511
|
static void qrfColDataFree(qrfColData *p){ |
|
2512
|
sqlite3_int64 i; |
|
2513
|
for(i=0; i<p->n; i++) sqlite3_free(p->az[i]); |
|
2514
|
sqlite3_free(p->az); |
|
2515
|
sqlite3_free(p->aiWth); |
|
2516
|
sqlite3_free(p->abNum); |
|
2517
|
sqlite3_free(p->a); |
|
2518
|
memset(p, 0, sizeof(*p)); |
|
2519
|
} |
|
2520
|
|
|
2521
|
/* |
|
2522
|
** Allocate space for more cells in the qrfColData object. |
|
2523
|
** Return non-zero if a memory allocation fails. |
|
2524
|
*/ |
|
2525
|
static int qrfColDataEnlarge(qrfColData *p){ |
|
2526
|
char **azData; |
|
2527
|
int *aiWth; |
|
2528
|
unsigned char *abNum; |
|
2529
|
p->nAlloc = 2*p->nAlloc + 10*p->nCol; |
|
2530
|
azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*)); |
|
2531
|
if( azData==0 ){ |
|
2532
|
qrfOom(p->p); |
|
2533
|
qrfColDataFree(p); |
|
2534
|
return 1; |
|
2535
|
} |
|
2536
|
p->az = azData; |
|
2537
|
aiWth = sqlite3_realloc64(p->aiWth, p->nAlloc*sizeof(int)); |
|
2538
|
if( aiWth==0 ){ |
|
2539
|
qrfOom(p->p); |
|
2540
|
qrfColDataFree(p); |
|
2541
|
return 1; |
|
2542
|
} |
|
2543
|
p->aiWth = aiWth; |
|
2544
|
abNum = sqlite3_realloc64(p->abNum, p->nAlloc); |
|
2545
|
if( abNum==0 ){ |
|
2546
|
qrfOom(p->p); |
|
2547
|
qrfColDataFree(p); |
|
2548
|
return 1; |
|
2549
|
} |
|
2550
|
p->abNum = abNum; |
|
2551
|
return 0; |
|
2552
|
} |
|
2553
|
|
|
2554
|
/* |
|
2555
|
** Print a markdown or table-style row separator using ascii-art |
|
2556
|
*/ |
|
2557
|
static void qrfRowSeparator(sqlite3_str *pOut, qrfColData *p, char cSep){ |
|
2558
|
int i; |
|
2559
|
if( p->nCol>0 ){ |
|
2560
|
int useBorder = p->p->spec.bBorder!=QRF_No; |
|
2561
|
if( useBorder ){ |
|
2562
|
sqlite3_str_append(pOut, &cSep, 1); |
|
2563
|
} |
|
2564
|
sqlite3_str_appendchar(pOut, p->a[0].w+p->nMargin, '-'); |
|
2565
|
for(i=1; i<p->nCol; i++){ |
|
2566
|
sqlite3_str_append(pOut, &cSep, 1); |
|
2567
|
sqlite3_str_appendchar(pOut, p->a[i].w+p->nMargin, '-'); |
|
2568
|
} |
|
2569
|
if( useBorder ){ |
|
2570
|
sqlite3_str_append(pOut, &cSep, 1); |
|
2571
|
} |
|
2572
|
} |
|
2573
|
sqlite3_str_append(pOut, "\n", 1); |
|
2574
|
} |
|
2575
|
|
|
2576
|
/* |
|
2577
|
** UTF8 box-drawing characters. Imagine box lines like this: |
|
2578
|
** |
|
2579
|
** 1 |
|
2580
|
** | |
|
2581
|
** 4 --+-- 2 |
|
2582
|
** | |
|
2583
|
** 3 |
|
2584
|
** |
|
2585
|
** Each box characters has between 2 and 4 of the lines leading from |
|
2586
|
** the center. The characters are here identified by the numbers of |
|
2587
|
** their corresponding lines. |
|
2588
|
*/ |
|
2589
|
#define BOX_24 "\342\224\200" /* U+2500 --- */ |
|
2590
|
#define BOX_13 "\342\224\202" /* U+2502 | */ |
|
2591
|
#define BOX_23 "\342\224\214" /* U+250c ,- */ |
|
2592
|
#define BOX_34 "\342\224\220" /* U+2510 -, */ |
|
2593
|
#define BOX_12 "\342\224\224" /* U+2514 '- */ |
|
2594
|
#define BOX_14 "\342\224\230" /* U+2518 -' */ |
|
2595
|
#define BOX_123 "\342\224\234" /* U+251c |- */ |
|
2596
|
#define BOX_134 "\342\224\244" /* U+2524 -| */ |
|
2597
|
#define BOX_234 "\342\224\254" /* U+252c -,- */ |
|
2598
|
#define BOX_124 "\342\224\264" /* U+2534 -'- */ |
|
2599
|
#define BOX_1234 "\342\224\274" /* U+253c -|- */ |
|
2600
|
|
|
2601
|
/* Rounded corners: */ |
|
2602
|
#define BOX_R12 "\342\225\260" /* U+2570 '- */ |
|
2603
|
#define BOX_R23 "\342\225\255" /* U+256d ,- */ |
|
2604
|
#define BOX_R34 "\342\225\256" /* U+256e -, */ |
|
2605
|
#define BOX_R14 "\342\225\257" /* U+256f -' */ |
|
2606
|
|
|
2607
|
/* Doubled horizontal lines: */ |
|
2608
|
#define DBL_24 "\342\225\220" /* U+2550 === */ |
|
2609
|
#define DBL_123 "\342\225\236" /* U+255e |= */ |
|
2610
|
#define DBL_134 "\342\225\241" /* U+2561 =| */ |
|
2611
|
#define DBL_1234 "\342\225\252" /* U+256a =|= */ |
|
2612
|
#define DBL_12 "\342\225\230" /* U+2558 `= */ |
|
2613
|
#define DBL_14 "\342\225\233" /* U+255b =' */ |
|
2614
|
#define DBL_124 "\342\225\247" /* U+2567 ='= */ |
|
2615
|
|
|
2616
|
|
|
2617
|
/* Draw horizontal line N characters long using unicode box |
|
2618
|
** characters |
|
2619
|
*/ |
|
2620
|
static void qrfBoxLine(sqlite3_str *pOut, int N, int bDbl){ |
|
2621
|
const char *azDash[2] = { |
|
2622
|
BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24, |
|
2623
|
DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 |
|
2624
|
};/* 0 1 2 3 4 5 6 7 8 9 */ |
|
2625
|
const int nDash = 30; |
|
2626
|
i64 nn = 3*(i64)N; |
|
2627
|
while( nn>nDash ){ |
|
2628
|
sqlite3_str_append(pOut, azDash[bDbl], nDash); |
|
2629
|
nn -= nDash; |
|
2630
|
} |
|
2631
|
sqlite3_str_append(pOut, azDash[bDbl], (int)nn); |
|
2632
|
} |
|
2633
|
|
|
2634
|
/* |
|
2635
|
** Draw a horizontal separator for a QRF_STYLE_Box table. |
|
2636
|
*/ |
|
2637
|
static void qrfBoxSeparator( |
|
2638
|
sqlite3_str *pOut, /* Output to this sqlite3_str */ |
|
2639
|
qrfColData *p, /* Columnar data */ |
|
2640
|
const char *zSep1, /* Left margin */ |
|
2641
|
const char *zSep2, /* Column separator */ |
|
2642
|
const char *zSep3, /* Right margin */ |
|
2643
|
int bDbl /* True for double-lines */ |
|
2644
|
){ |
|
2645
|
int i; |
|
2646
|
if( p->nCol>0 ){ |
|
2647
|
int useBorder = p->p->spec.bBorder!=QRF_No; |
|
2648
|
if( useBorder ){ |
|
2649
|
sqlite3_str_appendall(pOut, zSep1); |
|
2650
|
} |
|
2651
|
qrfBoxLine(pOut, p->a[0].w+p->nMargin, bDbl); |
|
2652
|
for(i=1; i<p->nCol; i++){ |
|
2653
|
sqlite3_str_appendall(pOut, zSep2); |
|
2654
|
qrfBoxLine(pOut, p->a[i].w+p->nMargin, bDbl); |
|
2655
|
} |
|
2656
|
if( useBorder ){ |
|
2657
|
sqlite3_str_appendall(pOut, zSep3); |
|
2658
|
} |
|
2659
|
} |
|
2660
|
sqlite3_str_append(pOut, "\n", 1); |
|
2661
|
} |
|
2662
|
|
|
2663
|
/* |
|
2664
|
** Draw a horizontal separator for a QRF_STYLE_Column table. |
|
2665
|
** This style of separator is only used for separating the title |
|
2666
|
** from the content. |
|
2667
|
*/ |
|
2668
|
static void qrfColumnSeparator( |
|
2669
|
sqlite3_str *pOut, /* Output to this sqlite3_str */ |
|
2670
|
qrfColData *p, /* Columnar data */ |
|
2671
|
const char *colSep, /* Column separator text */ |
|
2672
|
int szColSep, /* Size of zColSep in bytes */ |
|
2673
|
const char *rowSep, /* Row separator text */ |
|
2674
|
int szRowSep /* Size of zRowSep in bytes */ |
|
2675
|
){ |
|
2676
|
int j; |
|
2677
|
int nColumn = p->nCol; |
|
2678
|
for(j=0; j<nColumn; j++){ |
|
2679
|
sqlite3_str_appendchar(pOut, p->a[j].w, '-'); |
|
2680
|
if( j<nColumn-1 ){ |
|
2681
|
sqlite3_str_append(pOut, colSep, szColSep); |
|
2682
|
}else{ |
|
2683
|
qrfRTrim(pOut); |
|
2684
|
sqlite3_str_append(pOut, rowSep, szRowSep); |
|
2685
|
} |
|
2686
|
} |
|
2687
|
} |
|
2688
|
|
|
2689
|
/* |
|
2690
|
** Load into pData the default alignment for the body of a table. |
|
2691
|
*/ |
|
2692
|
static void qrfLoadAlignment(qrfColData *pData, Qrf *p){ |
|
2693
|
sqlite3_int64 i; |
|
2694
|
for(i=0; i<pData->nCol; i++){ |
|
2695
|
pData->a[i].e = p->spec.eDfltAlign; |
|
2696
|
if( i<p->spec.nAlign ){ |
|
2697
|
unsigned char ax = p->spec.aAlign[i]; |
|
2698
|
if( (ax & QRF_ALIGN_HMASK)!=0 ){ |
|
2699
|
pData->a[i].e = (ax & QRF_ALIGN_HMASK) | |
|
2700
|
(pData->a[i].e & QRF_ALIGN_VMASK); |
|
2701
|
} |
|
2702
|
}else if( i<p->spec.nWidth ){ |
|
2703
|
if( p->spec.aWidth[i]<0 ){ |
|
2704
|
pData->a[i].e = QRF_ALIGN_Right | |
|
2705
|
(pData->a[i].e & QRF_ALIGN_VMASK); |
|
2706
|
} |
|
2707
|
} |
|
2708
|
} |
|
2709
|
} |
|
2710
|
|
|
2711
|
/* |
|
2712
|
** If the single column in pData->a[] with pData->n entries can be |
|
2713
|
** laid out as nCol columns with a 2-space gap between each such |
|
2714
|
** that all columns fit within nSW, then return a pointer to an array |
|
2715
|
** of integers which is the width of each column from left to right. |
|
2716
|
** |
|
2717
|
** If the layout is not possible, return a NULL pointer. |
|
2718
|
** |
|
2719
|
** Space to hold the returned array is from sqlite_malloc64(). |
|
2720
|
*/ |
|
2721
|
static int *qrfValidLayout( |
|
2722
|
qrfColData *pData, /* Collected query results */ |
|
2723
|
Qrf *p, /* On which to report an OOM */ |
|
2724
|
int nCol, /* Attempt this many columns */ |
|
2725
|
int nSW /* Screen width */ |
|
2726
|
){ |
|
2727
|
int i; /* Loop counter */ |
|
2728
|
int nr; /* Number of rows */ |
|
2729
|
int w = 0; /* Width of the current column */ |
|
2730
|
i64 t; /* Total width of all columns */ |
|
2731
|
int *aw; /* Array of individual column widths */ |
|
2732
|
|
|
2733
|
aw = sqlite3_malloc64( sizeof(int)*nCol ); |
|
2734
|
if( aw==0 ){ |
|
2735
|
qrfOom(p); |
|
2736
|
return 0; |
|
2737
|
} |
|
2738
|
nr = (pData->n + nCol - 1)/nCol; |
|
2739
|
for(i=0; i<pData->n; i++){ |
|
2740
|
if( (i%nr)==0 ){ |
|
2741
|
if( i>0 ) aw[i/nr-1] = w; |
|
2742
|
w = pData->aiWth[i]; |
|
2743
|
}else if( pData->aiWth[i]>w ){ |
|
2744
|
w = pData->aiWth[i]; |
|
2745
|
} |
|
2746
|
} |
|
2747
|
aw[nCol-1] = w; |
|
2748
|
for(t=i=0; i<nCol; i++) t += aw[i]; |
|
2749
|
t += 2*(nCol-1); |
|
2750
|
if( t>nSW ){ |
|
2751
|
sqlite3_free(aw); |
|
2752
|
return 0; |
|
2753
|
} |
|
2754
|
return aw; |
|
2755
|
} |
|
2756
|
|
|
2757
|
/* |
|
2758
|
** The output is single-column and the bSplitColumn flag is set. |
|
2759
|
** Check to see if the single-column output can be split into multiple |
|
2760
|
** columns that appear side-by-side. Adjust pData appropriately. |
|
2761
|
*/ |
|
2762
|
static void qrfSplitColumn(qrfColData *pData, Qrf *p){ |
|
2763
|
int nCol = 1; |
|
2764
|
int *aw = 0; |
|
2765
|
char **az = 0; |
|
2766
|
int *aiWth = 0; |
|
2767
|
unsigned char *abNum = 0; |
|
2768
|
int nColNext = 2; |
|
2769
|
int w; |
|
2770
|
struct qrfPerCol *a = 0; |
|
2771
|
sqlite3_int64 nRow = 1; |
|
2772
|
sqlite3_int64 i; |
|
2773
|
while( 1/*exit-by-break*/ ){ |
|
2774
|
int *awNew = qrfValidLayout(pData, p, nColNext, p->spec.nScreenWidth); |
|
2775
|
if( awNew==0 ) break; |
|
2776
|
sqlite3_free(aw); |
|
2777
|
aw = awNew; |
|
2778
|
nCol = nColNext; |
|
2779
|
nRow = (pData->n + nCol - 1)/nCol; |
|
2780
|
if( nRow==1 ) break; |
|
2781
|
nColNext++; |
|
2782
|
while( (pData->n + nColNext - 1)/nColNext == nRow ) nColNext++; |
|
2783
|
} |
|
2784
|
if( nCol==1 ){ |
|
2785
|
sqlite3_free(aw); |
|
2786
|
return; /* Cannot do better than 1 column */ |
|
2787
|
} |
|
2788
|
az = sqlite3_malloc64( nRow*nCol*sizeof(char*) ); |
|
2789
|
if( az==0 ){ |
|
2790
|
qrfOom(p); |
|
2791
|
return; |
|
2792
|
} |
|
2793
|
aiWth = sqlite3_malloc64( nRow*nCol*sizeof(int) ); |
|
2794
|
if( aiWth==0 ){ |
|
2795
|
sqlite3_free(az); |
|
2796
|
qrfOom(p); |
|
2797
|
return; |
|
2798
|
} |
|
2799
|
a = sqlite3_malloc64( nCol*sizeof(struct qrfPerCol) ); |
|
2800
|
if( a==0 ){ |
|
2801
|
sqlite3_free(az); |
|
2802
|
sqlite3_free(aiWth); |
|
2803
|
qrfOom(p); |
|
2804
|
return; |
|
2805
|
} |
|
2806
|
abNum = sqlite3_malloc64( nRow*nCol ); |
|
2807
|
if( abNum==0 ){ |
|
2808
|
sqlite3_free(az); |
|
2809
|
sqlite3_free(aiWth); |
|
2810
|
sqlite3_free(a); |
|
2811
|
qrfOom(p); |
|
2812
|
return; |
|
2813
|
} |
|
2814
|
for(i=0; i<pData->n; i++){ |
|
2815
|
sqlite3_int64 j = (i%nRow)*nCol + (i/nRow); |
|
2816
|
az[j] = pData->az[i]; |
|
2817
|
abNum[j]= pData->abNum[i]; |
|
2818
|
pData->az[i] = 0; |
|
2819
|
aiWth[j] = pData->aiWth[i]; |
|
2820
|
} |
|
2821
|
while( i<nRow*nCol ){ |
|
2822
|
sqlite3_int64 j = (i%nRow)*nCol + (i/nRow); |
|
2823
|
az[j] = sqlite3_mprintf(""); |
|
2824
|
if( az[j]==0 ) qrfOom(p); |
|
2825
|
aiWth[j] = 0; |
|
2826
|
abNum[j] = 0; |
|
2827
|
i++; |
|
2828
|
} |
|
2829
|
for(i=0; i<nCol; i++){ |
|
2830
|
a[i].fx = a[i].mxW = a[i].w = aw[i]; |
|
2831
|
a[i].e = pData->a[0].e; |
|
2832
|
} |
|
2833
|
sqlite3_free(pData->az); |
|
2834
|
sqlite3_free(pData->aiWth); |
|
2835
|
sqlite3_free(pData->a); |
|
2836
|
sqlite3_free(pData->abNum); |
|
2837
|
sqlite3_free(aw); |
|
2838
|
pData->az = az; |
|
2839
|
pData->aiWth = aiWth; |
|
2840
|
pData->a = a; |
|
2841
|
pData->abNum = abNum; |
|
2842
|
pData->nCol = nCol; |
|
2843
|
pData->n = pData->nAlloc = nRow*nCol; |
|
2844
|
for(i=w=0; i<nCol; i++) w += a[i].w; |
|
2845
|
pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1); |
|
2846
|
if( pData->nMargin>5 ) pData->nMargin = 5; |
|
2847
|
} |
|
2848
|
|
|
2849
|
/* |
|
2850
|
** Adjust the layout for the screen width restriction |
|
2851
|
*/ |
|
2852
|
static void qrfRestrictScreenWidth(qrfColData *pData, Qrf *p){ |
|
2853
|
int sepW; /* Width of all box separators and margins */ |
|
2854
|
int sumW; /* Total width of data area over all columns */ |
|
2855
|
int targetW; /* Desired total data area */ |
|
2856
|
int i; /* Loop counters */ |
|
2857
|
int nCol; /* Number of columns */ |
|
2858
|
|
|
2859
|
pData->nMargin = 2; /* Default to normal margins */ |
|
2860
|
if( p->spec.nScreenWidth==0 ) return; |
|
2861
|
if( p->spec.eStyle==QRF_STYLE_Column ){ |
|
2862
|
sepW = pData->nCol*2 - 2; |
|
2863
|
}else{ |
|
2864
|
sepW = pData->nCol*3 + 1; |
|
2865
|
if( p->spec.bBorder==QRF_No ) sepW -= 2; |
|
2866
|
} |
|
2867
|
nCol = pData->nCol; |
|
2868
|
for(i=0, sumW=0; i<nCol; i++){ |
|
2869
|
if( sumW > 2147483647 - pData->a[i].w ) return; |
|
2870
|
sumW += pData->a[i].w; |
|
2871
|
} |
|
2872
|
if( p->spec.nScreenWidth >= (i64)sumW + sepW ) return; |
|
2873
|
|
|
2874
|
/* First thing to do is reduce the separation between columns */ |
|
2875
|
pData->nMargin = 0; |
|
2876
|
if( p->spec.eStyle==QRF_STYLE_Column ){ |
|
2877
|
sepW = pData->nCol - 1; |
|
2878
|
}else{ |
|
2879
|
sepW = pData->nCol + 1; |
|
2880
|
if( p->spec.bBorder==QRF_No ) sepW -= 2; |
|
2881
|
} |
|
2882
|
targetW = p->spec.nScreenWidth - sepW; |
|
2883
|
|
|
2884
|
#define MIN_SQUOZE 8 |
|
2885
|
#define MIN_EX_SQUOZE 16 |
|
2886
|
/* Reduce the width of the widest eligible column. A column is |
|
2887
|
** eligible for narrowing if: |
|
2888
|
** |
|
2889
|
** * It is not a fixed-width column (a[0].fx is false) |
|
2890
|
** * The current width is more than MIN_SQUOZE |
|
2891
|
** * Either: |
|
2892
|
** + The current width is more then MIN_EX_SQUOZE, or |
|
2893
|
** + The current width is more than half the max width (a[].mxW) |
|
2894
|
** |
|
2895
|
** Keep making reductions until either no more reductions are |
|
2896
|
** possible or until the size target is reached. |
|
2897
|
*/ |
|
2898
|
while( sumW > targetW ){ |
|
2899
|
int gain, w; |
|
2900
|
int ix = -1; |
|
2901
|
int mx = 0; |
|
2902
|
for(i=0; i<nCol; i++){ |
|
2903
|
if( pData->a[i].fx==0 |
|
2904
|
&& (w = pData->a[i].w)>mx |
|
2905
|
&& w>MIN_SQUOZE |
|
2906
|
&& (w>MIN_EX_SQUOZE || w*2>pData->a[i].mxW) |
|
2907
|
){ |
|
2908
|
ix = i; |
|
2909
|
mx = w; |
|
2910
|
} |
|
2911
|
} |
|
2912
|
if( ix<0 ) break; |
|
2913
|
if( mx>=MIN_SQUOZE*2 ){ |
|
2914
|
gain = mx/2; |
|
2915
|
}else{ |
|
2916
|
gain = mx - MIN_SQUOZE; |
|
2917
|
} |
|
2918
|
if( sumW - gain < targetW ){ |
|
2919
|
gain = sumW - targetW; |
|
2920
|
} |
|
2921
|
sumW -= gain; |
|
2922
|
pData->a[ix].w -= gain; |
|
2923
|
pData->bMultiRow = 1; |
|
2924
|
} |
|
2925
|
} |
|
2926
|
|
|
2927
|
/* |
|
2928
|
** Columnar modes require that the entire query be evaluated first, with |
|
2929
|
** results written into memory, so that we can compute appropriate column |
|
2930
|
** widths. |
|
2931
|
*/ |
|
2932
|
static void qrfColumnar(Qrf *p){ |
|
2933
|
sqlite3_int64 i, j; /* Loop counters */ |
|
2934
|
const char *colSep = 0; /* Column separator text */ |
|
2935
|
const char *rowSep = 0; /* Row terminator text */ |
|
2936
|
const char *rowStart = 0; /* Row start text */ |
|
2937
|
int szColSep, szRowSep, szRowStart; /* Size in bytes of previous 3 */ |
|
2938
|
int rc; /* Result code */ |
|
2939
|
int nColumn = p->nCol; /* Number of columns */ |
|
2940
|
int bWW; /* True to do word-wrap */ |
|
2941
|
sqlite3_str *pStr; /* Temporary rendering */ |
|
2942
|
qrfColData data; /* Columnar layout data */ |
|
2943
|
int bRTrim; /* Trim trailing space */ |
|
2944
|
|
|
2945
|
rc = sqlite3_step(p->pStmt); |
|
2946
|
if( nColumn==0 ){ |
|
2947
|
return; /* Not a query. No results every shown. */ |
|
2948
|
} |
|
2949
|
if( rc==SQLITE_DONE && nColumn>0 ){ |
|
2950
|
/* Empty query */ |
|
2951
|
if( p->spec.bTitles==QRF_Always ){ |
|
2952
|
/* fall through into the columnar logic below */ |
|
2953
|
}else{ |
|
2954
|
if( p->spec.bRowCount==QRF_Yes ){ |
|
2955
|
sqlite3_str_appendf(p->pOut, "(0 rows)\n"); |
|
2956
|
qrfWrite(p); |
|
2957
|
} |
|
2958
|
return; /* No output, other than the row count */ |
|
2959
|
} |
|
2960
|
}else if( rc!=SQLITE_ROW ){ |
|
2961
|
return; /* No output */ |
|
2962
|
} |
|
2963
|
|
|
2964
|
/* Initialize the data container */ |
|
2965
|
memset(&data, 0, sizeof(data)); |
|
2966
|
data.nCol = p->nCol; |
|
2967
|
data.p = p; |
|
2968
|
data.a = sqlite3_malloc64( nColumn*sizeof(struct qrfPerCol) ); |
|
2969
|
if( data.a==0 ){ |
|
2970
|
qrfOom(p); |
|
2971
|
return; |
|
2972
|
} |
|
2973
|
memset(data.a, 0, nColumn*sizeof(struct qrfPerCol) ); |
|
2974
|
if( qrfColDataEnlarge(&data) ) return; |
|
2975
|
assert( data.az!=0 ); |
|
2976
|
|
|
2977
|
/* Load the column header names into data */ |
|
2978
|
if( p->spec.bTitles>=QRF_Yes ){ |
|
2979
|
unsigned char saved_eText = p->spec.eText; |
|
2980
|
p->spec.eText = p->spec.eTitle; |
|
2981
|
memset(data.abNum, 0, nColumn); |
|
2982
|
for(i=0; i<nColumn; i++){ |
|
2983
|
const char *z = (const char*)sqlite3_column_name(p->pStmt,i); |
|
2984
|
int nNL = 0; |
|
2985
|
int n, w; |
|
2986
|
pStr = sqlite3_str_new(p->db); |
|
2987
|
qrfEncodeText(p, pStr, z ? z : ""); |
|
2988
|
n = sqlite3_str_length(pStr); |
|
2989
|
qrfStrErr(p, pStr); |
|
2990
|
z = data.az[data.n] = sqlite3_str_finish(pStr); |
|
2991
|
if( p->spec.nTitleLimit ){ |
|
2992
|
nNL = 0; |
|
2993
|
data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n], |
|
2994
|
p->spec.nTitleLimit ); |
|
2995
|
}else{ |
|
2996
|
data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL); |
|
2997
|
} |
|
2998
|
data.n++; |
|
2999
|
if( w>data.a[i].mxW ) data.a[i].mxW = w; |
|
3000
|
if( nNL ) data.bMultiRow = 1; |
|
3001
|
} |
|
3002
|
p->spec.eText = saved_eText; |
|
3003
|
} |
|
3004
|
|
|
3005
|
/* Load query results into data */ |
|
3006
|
while( rc==SQLITE_ROW && p->iErr==SQLITE_OK ){ |
|
3007
|
if( data.n+nColumn > data.nAlloc ){ |
|
3008
|
if( qrfColDataEnlarge(&data) ) return; |
|
3009
|
} |
|
3010
|
for(i=0; i<nColumn; i++){ |
|
3011
|
char *z; |
|
3012
|
int nNL = 0; |
|
3013
|
int n, w; |
|
3014
|
int eType = sqlite3_column_type(p->pStmt,i); |
|
3015
|
pStr = sqlite3_str_new(p->db); |
|
3016
|
qrfRenderValue(p, pStr, i); |
|
3017
|
n = sqlite3_str_length(pStr); |
|
3018
|
qrfStrErr(p, pStr); |
|
3019
|
z = data.az[data.n] = sqlite3_str_finish(pStr); |
|
3020
|
data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT; |
|
3021
|
data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL); |
|
3022
|
data.n++; |
|
3023
|
if( w>data.a[i].mxW ) data.a[i].mxW = w; |
|
3024
|
if( nNL ) data.bMultiRow = 1; |
|
3025
|
} |
|
3026
|
p->nRow++; |
|
3027
|
rc = sqlite3_step(p->pStmt); |
|
3028
|
} |
|
3029
|
if( p->iErr ){ |
|
3030
|
qrfColDataFree(&data); |
|
3031
|
return; |
|
3032
|
} |
|
3033
|
|
|
3034
|
/* Compute the width and alignment of every column */ |
|
3035
|
if( p->spec.bTitles==QRF_No ){ |
|
3036
|
qrfLoadAlignment(&data, p); |
|
3037
|
}else{ |
|
3038
|
unsigned char e; |
|
3039
|
if( p->spec.eTitleAlign==QRF_Auto ){ |
|
3040
|
e = QRF_ALIGN_Center; |
|
3041
|
}else{ |
|
3042
|
e = p->spec.eTitleAlign; |
|
3043
|
} |
|
3044
|
for(i=0; i<nColumn; i++) data.a[i].e = e; |
|
3045
|
} |
|
3046
|
|
|
3047
|
for(i=0; i<nColumn; i++){ |
|
3048
|
int w = 0; |
|
3049
|
if( i<p->spec.nWidth ){ |
|
3050
|
w = p->spec.aWidth[i]; |
|
3051
|
if( w==(-32768) ){ |
|
3052
|
w = 0; |
|
3053
|
if( p->spec.nAlign>i && (p->spec.aAlign[i] & QRF_ALIGN_HMASK)==0 ){ |
|
3054
|
data.a[i].e |= QRF_ALIGN_Right; |
|
3055
|
} |
|
3056
|
}else if( w<0 ){ |
|
3057
|
w = -w; |
|
3058
|
if( p->spec.nAlign>i && (p->spec.aAlign[i] & QRF_ALIGN_HMASK)==0 ){ |
|
3059
|
data.a[i].e |= QRF_ALIGN_Right; |
|
3060
|
} |
|
3061
|
} |
|
3062
|
if( w ) data.a[i].fx = 1; |
|
3063
|
} |
|
3064
|
if( w==0 ){ |
|
3065
|
w = data.a[i].mxW; |
|
3066
|
if( p->spec.nWrap>0 && w>p->spec.nWrap ){ |
|
3067
|
w = p->spec.nWrap; |
|
3068
|
data.bMultiRow = 1; |
|
3069
|
} |
|
3070
|
}else if( (data.bMultiRow==0 || w==1) && data.a[i].mxW>w ){ |
|
3071
|
data.bMultiRow = 1; |
|
3072
|
if( w==1 ){ |
|
3073
|
/* If aiWth[j] is 2 or more, then there might be a double-wide |
|
3074
|
** character somewhere. So make the column width at least 2. */ |
|
3075
|
w = 2; |
|
3076
|
} |
|
3077
|
} |
|
3078
|
data.a[i].w = w; |
|
3079
|
} |
|
3080
|
|
|
3081
|
if( nColumn==1 |
|
3082
|
&& data.n>1 |
|
3083
|
&& p->spec.bSplitColumn==QRF_Yes |
|
3084
|
&& p->spec.eStyle==QRF_STYLE_Column |
|
3085
|
&& p->spec.bTitles==QRF_No |
|
3086
|
&& p->spec.nScreenWidth>data.a[0].w+3 |
|
3087
|
){ |
|
3088
|
/* Attempt to convert single-column tables into multi-column by |
|
3089
|
** verticle wrapping, if the screen is wide enough and if the |
|
3090
|
** bSplitColumn flag is set. */ |
|
3091
|
qrfSplitColumn(&data, p); |
|
3092
|
nColumn = data.nCol; |
|
3093
|
}else{ |
|
3094
|
/* Adjust the column widths due to screen width restrictions */ |
|
3095
|
qrfRestrictScreenWidth(&data, p); |
|
3096
|
} |
|
3097
|
|
|
3098
|
/* Draw the line across the top of the table. Also initialize |
|
3099
|
** the row boundary and column separator texts. */ |
|
3100
|
switch( p->spec.eStyle ){ |
|
3101
|
case QRF_STYLE_Box: |
|
3102
|
if( data.nMargin ){ |
|
3103
|
rowStart = BOX_13 " "; |
|
3104
|
colSep = " " BOX_13 " "; |
|
3105
|
rowSep = " " BOX_13 "\n"; |
|
3106
|
}else{ |
|
3107
|
rowStart = BOX_13; |
|
3108
|
colSep = BOX_13; |
|
3109
|
rowSep = BOX_13 "\n"; |
|
3110
|
} |
|
3111
|
if( p->spec.bBorder==QRF_No){ |
|
3112
|
rowStart += 3; |
|
3113
|
rowSep = "\n"; |
|
3114
|
}else{ |
|
3115
|
qrfBoxSeparator(p->pOut, &data, BOX_R23, BOX_234, BOX_R34, 0); |
|
3116
|
} |
|
3117
|
break; |
|
3118
|
case QRF_STYLE_Table: |
|
3119
|
if( data.nMargin ){ |
|
3120
|
rowStart = "| "; |
|
3121
|
colSep = " | "; |
|
3122
|
rowSep = " |\n"; |
|
3123
|
}else{ |
|
3124
|
rowStart = "|"; |
|
3125
|
colSep = "|"; |
|
3126
|
rowSep = "|\n"; |
|
3127
|
} |
|
3128
|
if( p->spec.bBorder==QRF_No ){ |
|
3129
|
rowStart += 1; |
|
3130
|
rowSep = "\n"; |
|
3131
|
}else{ |
|
3132
|
qrfRowSeparator(p->pOut, &data, '+'); |
|
3133
|
} |
|
3134
|
break; |
|
3135
|
case QRF_STYLE_Column: { |
|
3136
|
static const char zSpace[] = " "; |
|
3137
|
rowStart = ""; |
|
3138
|
if( data.nMargin<2 ){ |
|
3139
|
colSep = " "; |
|
3140
|
}else if( data.nMargin<=5 ){ |
|
3141
|
colSep = &zSpace[5-data.nMargin]; |
|
3142
|
}else{ |
|
3143
|
colSep = zSpace; |
|
3144
|
} |
|
3145
|
rowSep = "\n"; |
|
3146
|
break; |
|
3147
|
} |
|
3148
|
default: /*case QRF_STYLE_Markdown:*/ |
|
3149
|
if( data.nMargin ){ |
|
3150
|
rowStart = "| "; |
|
3151
|
colSep = " | "; |
|
3152
|
rowSep = " |\n"; |
|
3153
|
}else{ |
|
3154
|
rowStart = "|"; |
|
3155
|
colSep = "|"; |
|
3156
|
rowSep = "|\n"; |
|
3157
|
} |
|
3158
|
break; |
|
3159
|
} |
|
3160
|
szRowStart = (int)strlen(rowStart); |
|
3161
|
szRowSep = (int)strlen(rowSep); |
|
3162
|
szColSep = (int)strlen(colSep); |
|
3163
|
|
|
3164
|
bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow); |
|
3165
|
if( p->spec.eStyle==QRF_STYLE_Column |
|
3166
|
|| (p->spec.bBorder==QRF_No |
|
3167
|
&& (p->spec.eStyle==QRF_STYLE_Box || p->spec.eStyle==QRF_STYLE_Table) |
|
3168
|
) |
|
3169
|
){ |
|
3170
|
bRTrim = 1; |
|
3171
|
}else{ |
|
3172
|
bRTrim = 0; |
|
3173
|
} |
|
3174
|
for(i=0; i<data.n && sqlite3_str_errcode(p->pOut)==SQLITE_OK; i+=nColumn){ |
|
3175
|
int bMore; |
|
3176
|
int nRow = 0; |
|
3177
|
|
|
3178
|
/* Draw a single row of the table. This might be the title line |
|
3179
|
** (if there is a title line) or a row in the body of the table. |
|
3180
|
** The column number will be j. The row number is i/nColumn. |
|
3181
|
*/ |
|
3182
|
for(j=0; j<nColumn; j++){ |
|
3183
|
data.a[j].z = data.az[i+j]; |
|
3184
|
if( data.a[j].z==0 ) data.a[j].z = ""; |
|
3185
|
data.a[j].bNum = data.abNum[i+j]; |
|
3186
|
} |
|
3187
|
do{ |
|
3188
|
sqlite3_str_append(p->pOut, rowStart, szRowStart); |
|
3189
|
bMore = 0; |
|
3190
|
for(j=0; j<nColumn; j++){ |
|
3191
|
int nThis = 0; |
|
3192
|
int nWide = 0; |
|
3193
|
int iNext = 0; |
|
3194
|
int nWS; |
|
3195
|
qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext); |
|
3196
|
nWS = data.a[j].w - nWide; |
|
3197
|
qrfPrintAligned(p->pOut, &data.a[j], nThis, nWS); |
|
3198
|
data.a[j].z += iNext; |
|
3199
|
if( data.a[j].z[0]!=0 ){ |
|
3200
|
bMore = 1; |
|
3201
|
} |
|
3202
|
if( j<nColumn-1 ){ |
|
3203
|
sqlite3_str_append(p->pOut, colSep, szColSep); |
|
3204
|
}else{ |
|
3205
|
if( bRTrim ) qrfRTrim(p->pOut); |
|
3206
|
sqlite3_str_append(p->pOut, rowSep, szRowSep); |
|
3207
|
} |
|
3208
|
} |
|
3209
|
}while( bMore && ++nRow < p->mxHeight ); |
|
3210
|
if( bMore ){ |
|
3211
|
/* This row was terminated by nLineLimit. Show ellipsis. */ |
|
3212
|
sqlite3_str_append(p->pOut, rowStart, szRowStart); |
|
3213
|
for(j=0; j<nColumn; j++){ |
|
3214
|
if( data.a[j].z[0]==0 ){ |
|
3215
|
sqlite3_str_appendchar(p->pOut, data.a[j].w, ' '); |
|
3216
|
}else{ |
|
3217
|
int nE = 3; |
|
3218
|
if( nE>data.a[j].w ) nE = data.a[j].w; |
|
3219
|
data.a[j].z = "..."; |
|
3220
|
qrfPrintAligned(p->pOut, &data.a[j], nE, data.a[j].w-nE); |
|
3221
|
} |
|
3222
|
if( j<nColumn-1 ){ |
|
3223
|
sqlite3_str_append(p->pOut, colSep, szColSep); |
|
3224
|
}else{ |
|
3225
|
if( bRTrim ) qrfRTrim(p->pOut); |
|
3226
|
sqlite3_str_append(p->pOut, rowSep, szRowSep); |
|
3227
|
} |
|
3228
|
} |
|
3229
|
} |
|
3230
|
|
|
3231
|
/* Draw either (1) the separator between the title line and the body |
|
3232
|
** of the table, or (2) separators between individual rows of the table |
|
3233
|
** body. isTitleDataSeparator will be true if we are doing (1). |
|
3234
|
*/ |
|
3235
|
if( (i==0 || data.bMultiRow) && i+nColumn<data.n ){ |
|
3236
|
int isTitleDataSeparator = (i==0 && p->spec.bTitles>=QRF_Yes); |
|
3237
|
if( isTitleDataSeparator ){ |
|
3238
|
qrfLoadAlignment(&data, p); |
|
3239
|
} |
|
3240
|
switch( p->spec.eStyle ){ |
|
3241
|
case QRF_STYLE_Table: { |
|
3242
|
if( isTitleDataSeparator || data.bMultiRow ){ |
|
3243
|
qrfRowSeparator(p->pOut, &data, '+'); |
|
3244
|
} |
|
3245
|
break; |
|
3246
|
} |
|
3247
|
case QRF_STYLE_Box: { |
|
3248
|
if( isTitleDataSeparator ){ |
|
3249
|
qrfBoxSeparator(p->pOut, &data, DBL_123, DBL_1234, DBL_134, 1); |
|
3250
|
}else if( data.bMultiRow ){ |
|
3251
|
qrfBoxSeparator(p->pOut, &data, BOX_123, BOX_1234, BOX_134, 0); |
|
3252
|
} |
|
3253
|
break; |
|
3254
|
} |
|
3255
|
case QRF_STYLE_Markdown: { |
|
3256
|
if( isTitleDataSeparator ){ |
|
3257
|
qrfRowSeparator(p->pOut, &data, '|'); |
|
3258
|
} |
|
3259
|
break; |
|
3260
|
} |
|
3261
|
case QRF_STYLE_Column: { |
|
3262
|
if( isTitleDataSeparator ){ |
|
3263
|
qrfColumnSeparator(p->pOut, &data, colSep, szColSep, |
|
3264
|
rowSep, szRowSep); |
|
3265
|
}else if( data.bMultiRow ){ |
|
3266
|
qrfRTrim(p->pOut); |
|
3267
|
sqlite3_str_append(p->pOut, "\n", 1); |
|
3268
|
} |
|
3269
|
break; |
|
3270
|
} |
|
3271
|
} |
|
3272
|
} |
|
3273
|
} |
|
3274
|
|
|
3275
|
/* Draw the line across the bottom of the table */ |
|
3276
|
if( p->spec.bBorder!=QRF_No || p->nRow==0 ){ |
|
3277
|
switch( p->spec.eStyle ){ |
|
3278
|
case QRF_STYLE_Box: |
|
3279
|
if( p->nRow>0 ){ |
|
3280
|
qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0); |
|
3281
|
}else{ |
|
3282
|
qrfBoxSeparator(p->pOut, &data, DBL_12, DBL_124, DBL_14, 1); |
|
3283
|
} |
|
3284
|
break; |
|
3285
|
case QRF_STYLE_Table: |
|
3286
|
qrfRowSeparator(p->pOut, &data, '+'); |
|
3287
|
break; |
|
3288
|
case QRF_STYLE_Markdown: |
|
3289
|
if( p->nRow==0 ){ |
|
3290
|
qrfRowSeparator(p->pOut, &data, '|'); |
|
3291
|
} |
|
3292
|
break; |
|
3293
|
case QRF_STYLE_Column: |
|
3294
|
if( p->nRow==0 ){ |
|
3295
|
qrfColumnSeparator(p->pOut, &data, colSep, szColSep, |
|
3296
|
rowSep, szRowSep); |
|
3297
|
} |
|
3298
|
break; |
|
3299
|
} |
|
3300
|
} |
|
3301
|
if( p->spec.bRowCount==QRF_Yes ){ |
|
3302
|
sqlite3_int64 n = p->nRow; |
|
3303
|
sqlite3_str_appendf(p->pOut, "(%lld row%s)\n", n, n==1 ? "" : "s"); |
|
3304
|
} |
|
3305
|
qrfWrite(p); |
|
3306
|
|
|
3307
|
qrfColDataFree(&data); |
|
3308
|
return; |
|
3309
|
} |
|
3310
|
|
|
3311
|
/* |
|
3312
|
** Parameter azArray points to a zero-terminated array of strings. zStr |
|
3313
|
** points to a single nul-terminated string. Return non-zero if zStr |
|
3314
|
** is equal, according to strcmp(), to any of the strings in the array. |
|
3315
|
** Otherwise, return zero. |
|
3316
|
*/ |
|
3317
|
static int qrfStringInArray(const char *zStr, const char **azArray){ |
|
3318
|
int i; |
|
3319
|
if( zStr==0 ) return 0; |
|
3320
|
for(i=0; azArray[i]; i++){ |
|
3321
|
if( 0==strcmp(zStr, azArray[i]) ) return 1; |
|
3322
|
} |
|
3323
|
return 0; |
|
3324
|
} |
|
3325
|
|
|
3326
|
/* |
|
3327
|
** Print out an EXPLAIN with indentation. This is a two-pass algorithm. |
|
3328
|
** |
|
3329
|
** On the first pass, we compute aiIndent[iOp] which is the amount of |
|
3330
|
** indentation to apply to the iOp-th opcode. The output actually occurs |
|
3331
|
** on the second pass. |
|
3332
|
** |
|
3333
|
** The indenting rules are: |
|
3334
|
** |
|
3335
|
** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent |
|
3336
|
** all opcodes that occur between the p2 jump destination and the opcode |
|
3337
|
** itself by 2 spaces. |
|
3338
|
** |
|
3339
|
** * Do the previous for "Return" instructions for when P2 is positive. |
|
3340
|
** See tag-20220407a in wherecode.c and vdbe.c. |
|
3341
|
** |
|
3342
|
** * For each "Goto", if the jump destination is earlier in the program |
|
3343
|
** and ends on one of: |
|
3344
|
** Yield SeekGt SeekLt RowSetRead Rewind |
|
3345
|
** or if the P1 parameter is one instead of zero, |
|
3346
|
** then indent all opcodes between the earlier instruction |
|
3347
|
** and "Goto" by 2 spaces. |
|
3348
|
*/ |
|
3349
|
static void qrfExplain(Qrf *p){ |
|
3350
|
int *abYield = 0; /* abYield[iOp] is rue if opcode iOp is an OP_Yield */ |
|
3351
|
int *aiIndent = 0; /* Indent the iOp-th opcode by aiIndent[iOp] */ |
|
3352
|
i64 nAlloc = 0; /* Allocated size of aiIndent[], abYield */ |
|
3353
|
int nIndent = 0; /* Number of entries in aiIndent[] */ |
|
3354
|
int iOp; /* Opcode number */ |
|
3355
|
int i; /* Column loop counter */ |
|
3356
|
|
|
3357
|
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", |
|
3358
|
"Return", 0 }; |
|
3359
|
const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", |
|
3360
|
"Rewind", 0 }; |
|
3361
|
const char *azGoto[] = { "Goto", 0 }; |
|
3362
|
|
|
3363
|
/* The caller guarantees that the leftmost 4 columns of the statement |
|
3364
|
** passed to this function are equivalent to the leftmost 4 columns |
|
3365
|
** of EXPLAIN statement output. In practice the statement may be |
|
3366
|
** an EXPLAIN, or it may be a query on the bytecode() virtual table. */ |
|
3367
|
assert( sqlite3_column_count(p->pStmt)>=4 ); |
|
3368
|
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) ); |
|
3369
|
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) ); |
|
3370
|
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) ); |
|
3371
|
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) ); |
|
3372
|
|
|
3373
|
for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){ |
|
3374
|
int iAddr = sqlite3_column_int(p->pStmt, 0); |
|
3375
|
const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1); |
|
3376
|
int p1 = sqlite3_column_int(p->pStmt, 2); |
|
3377
|
int p2 = sqlite3_column_int(p->pStmt, 3); |
|
3378
|
|
|
3379
|
/* Assuming that p2 is an instruction address, set variable p2op to the |
|
3380
|
** index of that instruction in the aiIndent[] array. p2 and p2op may be |
|
3381
|
** different if the current instruction is part of a sub-program generated |
|
3382
|
** by an SQL trigger or foreign key. */ |
|
3383
|
int p2op = (p2 + (iOp-iAddr)); |
|
3384
|
|
|
3385
|
/* Grow the aiIndent array as required */ |
|
3386
|
if( iOp>=nAlloc ){ |
|
3387
|
nAlloc += 100; |
|
3388
|
aiIndent = (int*)sqlite3_realloc64(aiIndent, nAlloc*sizeof(int)); |
|
3389
|
abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); |
|
3390
|
if( aiIndent==0 || abYield==0 ){ |
|
3391
|
qrfOom(p); |
|
3392
|
sqlite3_free(aiIndent); |
|
3393
|
sqlite3_free(abYield); |
|
3394
|
return; |
|
3395
|
} |
|
3396
|
} |
|
3397
|
|
|
3398
|
abYield[iOp] = qrfStringInArray(zOp, azYield); |
|
3399
|
aiIndent[iOp] = 0; |
|
3400
|
nIndent = iOp+1; |
|
3401
|
if( qrfStringInArray(zOp, azNext) && p2op>0 ){ |
|
3402
|
for(i=p2op; i<iOp; i++) aiIndent[i] += 2; |
|
3403
|
} |
|
3404
|
if( qrfStringInArray(zOp, azGoto) && p2op<iOp && (abYield[p2op] || p1) ){ |
|
3405
|
for(i=p2op; i<iOp; i++) aiIndent[i] += 2; |
|
3406
|
} |
|
3407
|
} |
|
3408
|
sqlite3_free(abYield); |
|
3409
|
|
|
3410
|
/* Second pass. Actually generate output */ |
|
3411
|
sqlite3_reset(p->pStmt); |
|
3412
|
if( p->iErr==SQLITE_OK ){ |
|
3413
|
static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13}; |
|
3414
|
static const int aExplainMap[] = {0, 1, 2, 3, 4, 5, 6, 7 }; |
|
3415
|
static const int aScanExpWidth[] = {4,15, 6, 13, 4, 4, 4, 13, 2, 13}; |
|
3416
|
static const int aScanExpMap[] = {0, 9, 8, 1, 2, 3, 4, 5, 6, 7 }; |
|
3417
|
const int *aWidth = aExplainWidth; |
|
3418
|
const int *aMap = aExplainMap; |
|
3419
|
int nWidth = sizeof(aExplainWidth)/sizeof(int); |
|
3420
|
int iIndent = 1; |
|
3421
|
int nArg = p->nCol; |
|
3422
|
if( p->spec.eStyle==QRF_STYLE_StatsVm ){ |
|
3423
|
aWidth = aScanExpWidth; |
|
3424
|
aMap = aScanExpMap; |
|
3425
|
nWidth = sizeof(aScanExpWidth)/sizeof(int); |
|
3426
|
iIndent = 3; |
|
3427
|
} |
|
3428
|
if( nArg>nWidth ) nArg = nWidth; |
|
3429
|
|
|
3430
|
for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW && !p->iErr; iOp++){ |
|
3431
|
/* If this is the first row seen, print out the headers */ |
|
3432
|
if( iOp==0 ){ |
|
3433
|
for(i=0; i<nArg; i++){ |
|
3434
|
const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]); |
|
3435
|
qrfWidthPrint(p,p->pOut, aWidth[i], zCol); |
|
3436
|
if( i==nArg-1 ){ |
|
3437
|
sqlite3_str_append(p->pOut, "\n", 1); |
|
3438
|
}else{ |
|
3439
|
sqlite3_str_append(p->pOut, " ", 2); |
|
3440
|
} |
|
3441
|
} |
|
3442
|
for(i=0; i<nArg; i++){ |
|
3443
|
sqlite3_str_appendf(p->pOut, "%.*c", aWidth[i], '-'); |
|
3444
|
if( i==nArg-1 ){ |
|
3445
|
sqlite3_str_append(p->pOut, "\n", 1); |
|
3446
|
}else{ |
|
3447
|
sqlite3_str_append(p->pOut, " ", 2); |
|
3448
|
} |
|
3449
|
} |
|
3450
|
} |
|
3451
|
|
|
3452
|
for(i=0; i<nArg; i++){ |
|
3453
|
const char *zSep = " "; |
|
3454
|
int w = aWidth[i]; |
|
3455
|
const char *zVal = (const char*)sqlite3_column_text(p->pStmt, aMap[i]); |
|
3456
|
int len; |
|
3457
|
if( i==nArg-1 ) w = 0; |
|
3458
|
if( zVal==0 ) zVal = ""; |
|
3459
|
len = (int)sqlite3_qrf_wcswidth(zVal); |
|
3460
|
if( len>w ){ |
|
3461
|
w = len; |
|
3462
|
zSep = " "; |
|
3463
|
} |
|
3464
|
if( i==iIndent && aiIndent && iOp<nIndent ){ |
|
3465
|
sqlite3_str_appendchar(p->pOut, aiIndent[iOp], ' '); |
|
3466
|
} |
|
3467
|
qrfWidthPrint(p, p->pOut, w, zVal); |
|
3468
|
if( i==nArg-1 ){ |
|
3469
|
sqlite3_str_append(p->pOut, "\n", 1); |
|
3470
|
}else{ |
|
3471
|
sqlite3_str_appendall(p->pOut, zSep); |
|
3472
|
} |
|
3473
|
} |
|
3474
|
p->nRow++; |
|
3475
|
} |
|
3476
|
qrfWrite(p); |
|
3477
|
} |
|
3478
|
sqlite3_free(aiIndent); |
|
3479
|
} |
|
3480
|
|
|
3481
|
/* |
|
3482
|
** Do a "scanstatus vm" style EXPLAIN listing on p->pStmt. |
|
3483
|
** |
|
3484
|
** p->pStmt is probably not an EXPLAIN query. Instead, construct a |
|
3485
|
** new query that is a bytecode() rendering of p->pStmt with extra |
|
3486
|
** columns for the "scanstatus vm" outputs, and run the results of |
|
3487
|
** that new query through the normal EXPLAIN formatting. |
|
3488
|
*/ |
|
3489
|
static void qrfScanStatusVm(Qrf *p){ |
|
3490
|
sqlite3_stmt *pOrigStmt = p->pStmt; |
|
3491
|
sqlite3_stmt *pExplain; |
|
3492
|
int rc; |
|
3493
|
static const char *zSql = |
|
3494
|
" SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec," |
|
3495
|
" format('% 6s (%.2f%%)'," |
|
3496
|
" CASE WHEN ncycle<100_000 THEN ncycle || ' '" |
|
3497
|
" WHEN ncycle<100_000_000 THEN (ncycle/1_000) || 'K'" |
|
3498
|
" WHEN ncycle<100_000_000_000 THEN (ncycle/1_000_000) || 'M'" |
|
3499
|
" ELSE (ncycle/1000_000_000) || 'G' END," |
|
3500
|
" ncycle*100.0/(sum(ncycle) OVER ())" |
|
3501
|
" ) AS cycles" |
|
3502
|
" FROM bytecode(?1)"; |
|
3503
|
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pExplain, 0); |
|
3504
|
if( rc ){ |
|
3505
|
qrfError(p, rc, "%s", sqlite3_errmsg(p->db)); |
|
3506
|
sqlite3_finalize(pExplain); |
|
3507
|
return; |
|
3508
|
} |
|
3509
|
sqlite3_bind_pointer(pExplain, 1, pOrigStmt, "stmt-pointer", 0); |
|
3510
|
p->pStmt = pExplain; |
|
3511
|
p->nCol = 10; |
|
3512
|
qrfExplain(p); |
|
3513
|
sqlite3_finalize(pExplain); |
|
3514
|
p->pStmt = pOrigStmt; |
|
3515
|
} |
|
3516
|
|
|
3517
|
/* |
|
3518
|
** Attempt to determine if identifier zName needs to be quoted, either |
|
3519
|
** because it contains non-alphanumeric characters, or because it is an |
|
3520
|
** SQLite keyword. Be conservative in this estimate: When in doubt assume |
|
3521
|
** that quoting is required. |
|
3522
|
** |
|
3523
|
** Return 1 if quoting is required. Return 0 if no quoting is required. |
|
3524
|
*/ |
|
3525
|
|
|
3526
|
static int qrf_need_quote(const char *zName){ |
|
3527
|
int i; |
|
3528
|
const unsigned char *z = (const unsigned char*)zName; |
|
3529
|
if( z==0 ) return 1; |
|
3530
|
if( !qrfAlpha(z[0]) ) return 1; |
|
3531
|
for(i=0; z[i]; i++){ |
|
3532
|
if( !qrfAlnum(z[i]) ) return 1; |
|
3533
|
} |
|
3534
|
return sqlite3_keyword_check(zName, i)!=0; |
|
3535
|
} |
|
3536
|
|
|
3537
|
/* |
|
3538
|
** Helper function for QRF_STYLE_Json and QRF_STYLE_JObject. |
|
3539
|
** The initial "{" for a JSON object that will contain row content |
|
3540
|
** has been output. Now output all the content. |
|
3541
|
*/ |
|
3542
|
static void qrfOneJsonRow(Qrf *p){ |
|
3543
|
int i, nItem; |
|
3544
|
for(nItem=i=0; i<p->nCol; i++){ |
|
3545
|
const char *zCName; |
|
3546
|
zCName = sqlite3_column_name(p->pStmt, i); |
|
3547
|
if( nItem>0 ) sqlite3_str_append(p->pOut, ",", 1); |
|
3548
|
nItem++; |
|
3549
|
qrfEncodeText(p, p->pOut, zCName); |
|
3550
|
sqlite3_str_append(p->pOut, ":", 1); |
|
3551
|
qrfRenderValue(p, p->pOut, i); |
|
3552
|
} |
|
3553
|
qrfWrite(p); |
|
3554
|
} |
|
3555
|
|
|
3556
|
/* |
|
3557
|
** Render a title row (a row containing column names) if the spec |
|
3558
|
** calls for one and if it makes sense for the eStyle. Title rows |
|
3559
|
** do not make sense for some eStyles, such as QRF_STYLE_Off, |
|
3560
|
** QRF_STYLE_Count, QRF_STYLE_Json, and similar. |
|
3561
|
*/ |
|
3562
|
static void qrfSimpleTitle(Qrf *p){ |
|
3563
|
assert( p->nRow==0 ); |
|
3564
|
assert( p->spec.bTitles>=QRF_Yes ); |
|
3565
|
switch( p->spec.eStyle ){ |
|
3566
|
case QRF_STYLE_Html: { |
|
3567
|
int i; |
|
3568
|
sqlite3_str_append(p->pOut, "<tr>", 4); |
|
3569
|
for(i=0; i<p->nCol; i++){ |
|
3570
|
const char *zCName = sqlite3_column_name(p->pStmt, i); |
|
3571
|
sqlite3_str_append(p->pOut, "\n<th>", 5); |
|
3572
|
qrfEncodeText(p, p->pOut, zCName); |
|
3573
|
} |
|
3574
|
sqlite3_str_append(p->pOut, "\n</tr>\n", 7); |
|
3575
|
break; |
|
3576
|
} |
|
3577
|
case QRF_STYLE_Quote: |
|
3578
|
case QRF_STYLE_List: { |
|
3579
|
int i; |
|
3580
|
int saved_eText = p->spec.eText; |
|
3581
|
p->spec.eText = p->spec.eTitle; |
|
3582
|
for(i=0; i<p->nCol; i++){ |
|
3583
|
const char *zCName = sqlite3_column_name(p->pStmt, i); |
|
3584
|
if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); |
|
3585
|
qrfEncodeText(p, p->pOut, zCName); |
|
3586
|
} |
|
3587
|
sqlite3_str_appendall(p->pOut, p->spec.zRowSep); |
|
3588
|
qrfWrite(p); |
|
3589
|
p->spec.eText = saved_eText; |
|
3590
|
break; |
|
3591
|
} |
|
3592
|
} |
|
3593
|
} |
|
3594
|
|
|
3595
|
/* |
|
3596
|
** Render a single row of output for non-columnar styles - any |
|
3597
|
** style that lets us render row by row as the content is received |
|
3598
|
** from the query. |
|
3599
|
*/ |
|
3600
|
static void qrfOneSimpleRow(Qrf *p){ |
|
3601
|
int i; |
|
3602
|
switch( p->spec.eStyle ){ |
|
3603
|
case QRF_STYLE_Off: |
|
3604
|
case QRF_STYLE_Count: { |
|
3605
|
/* No-op */ |
|
3606
|
break; |
|
3607
|
} |
|
3608
|
case QRF_STYLE_Json: { |
|
3609
|
if( p->nRow==0 ){ |
|
3610
|
sqlite3_str_append(p->pOut, "[{", 2); |
|
3611
|
}else{ |
|
3612
|
sqlite3_str_append(p->pOut, "},\n{", 4); |
|
3613
|
} |
|
3614
|
qrfOneJsonRow(p); |
|
3615
|
break; |
|
3616
|
} |
|
3617
|
case QRF_STYLE_JObject: { |
|
3618
|
if( p->nRow==0 ){ |
|
3619
|
sqlite3_str_append(p->pOut, "{", 1); |
|
3620
|
}else{ |
|
3621
|
sqlite3_str_append(p->pOut, "}\n{", 3); |
|
3622
|
} |
|
3623
|
qrfOneJsonRow(p); |
|
3624
|
break; |
|
3625
|
} |
|
3626
|
case QRF_STYLE_Html: { |
|
3627
|
if( p->nRow==0 && p->spec.bTitles>=QRF_Yes ){ |
|
3628
|
qrfSimpleTitle(p); |
|
3629
|
} |
|
3630
|
sqlite3_str_append(p->pOut, "<tr>", 4); |
|
3631
|
for(i=0; i<p->nCol; i++){ |
|
3632
|
sqlite3_str_append(p->pOut, "\n<td>", 5); |
|
3633
|
qrfRenderValue(p, p->pOut, i); |
|
3634
|
} |
|
3635
|
sqlite3_str_append(p->pOut, "\n</tr>\n", 7); |
|
3636
|
qrfWrite(p); |
|
3637
|
break; |
|
3638
|
} |
|
3639
|
case QRF_STYLE_Insert: { |
|
3640
|
unsigned int mxIns = p->spec.nMultiInsert; |
|
3641
|
int szStart = sqlite3_str_length(p->pOut); |
|
3642
|
if( p->u.nIns==0 || p->u.nIns>=mxIns ){ |
|
3643
|
if( p->u.nIns ){ |
|
3644
|
sqlite3_str_append(p->pOut, ";\n", 2); |
|
3645
|
p->u.nIns = 0; |
|
3646
|
} |
|
3647
|
if( qrf_need_quote(p->spec.zTableName) ){ |
|
3648
|
sqlite3_str_appendf(p->pOut,"INSERT INTO \"%w\"",p->spec.zTableName); |
|
3649
|
}else{ |
|
3650
|
sqlite3_str_appendf(p->pOut,"INSERT INTO %s",p->spec.zTableName); |
|
3651
|
} |
|
3652
|
if( p->spec.bTitles>=QRF_Yes ){ |
|
3653
|
for(i=0; i<p->nCol; i++){ |
|
3654
|
const char *zCName = sqlite3_column_name(p->pStmt, i); |
|
3655
|
if( qrf_need_quote(zCName) ){ |
|
3656
|
sqlite3_str_appendf(p->pOut, "%c\"%w\"", |
|
3657
|
i==0 ? '(' : ',', zCName); |
|
3658
|
}else{ |
|
3659
|
sqlite3_str_appendf(p->pOut, "%c%s", |
|
3660
|
i==0 ? '(' : ',', zCName); |
|
3661
|
} |
|
3662
|
} |
|
3663
|
sqlite3_str_append(p->pOut, ")", 1); |
|
3664
|
} |
|
3665
|
sqlite3_str_append(p->pOut," VALUES(", 8); |
|
3666
|
}else{ |
|
3667
|
sqlite3_str_append(p->pOut,",\n (", 5); |
|
3668
|
} |
|
3669
|
for(i=0; i<p->nCol; i++){ |
|
3670
|
if( i>0 ) sqlite3_str_append(p->pOut, ",", 1); |
|
3671
|
qrfRenderValue(p, p->pOut, i); |
|
3672
|
} |
|
3673
|
p->u.nIns += sqlite3_str_length(p->pOut) + 2 - szStart; |
|
3674
|
if( p->u.nIns>=mxIns ){ |
|
3675
|
sqlite3_str_append(p->pOut, ");\n", 3); |
|
3676
|
p->u.nIns = 0; |
|
3677
|
}else{ |
|
3678
|
sqlite3_str_append(p->pOut, ")", 1); |
|
3679
|
} |
|
3680
|
qrfWrite(p); |
|
3681
|
break; |
|
3682
|
} |
|
3683
|
case QRF_STYLE_Line: { |
|
3684
|
sqlite3_str *pVal; |
|
3685
|
int mxW; |
|
3686
|
int bWW; |
|
3687
|
int nSep; |
|
3688
|
if( p->u.sLine.azCol==0 ){ |
|
3689
|
p->u.sLine.azCol = sqlite3_malloc64( p->nCol*sizeof(char*) ); |
|
3690
|
if( p->u.sLine.azCol==0 ){ |
|
3691
|
qrfOom(p); |
|
3692
|
break; |
|
3693
|
} |
|
3694
|
p->u.sLine.mxColWth = 0; |
|
3695
|
for(i=0; i<p->nCol; i++){ |
|
3696
|
int sz; |
|
3697
|
const char *zCName = sqlite3_column_name(p->pStmt, i); |
|
3698
|
if( zCName==0 ) zCName = "unknown"; |
|
3699
|
p->u.sLine.azCol[i] = sqlite3_mprintf("%s", zCName); |
|
3700
|
if( p->spec.nTitleLimit>0 ){ |
|
3701
|
(void)qrfTitleLimit(p->u.sLine.azCol[i], p->spec.nTitleLimit); |
|
3702
|
} |
|
3703
|
sz = (int)sqlite3_qrf_wcswidth(p->u.sLine.azCol[i]); |
|
3704
|
if( sz > p->u.sLine.mxColWth ) p->u.sLine.mxColWth = sz; |
|
3705
|
} |
|
3706
|
} |
|
3707
|
if( p->nRow ) sqlite3_str_append(p->pOut, "\n", 1); |
|
3708
|
pVal = sqlite3_str_new(p->db); |
|
3709
|
nSep = (int)strlen(p->spec.zColumnSep); |
|
3710
|
mxW = p->mxWidth - (nSep + p->u.sLine.mxColWth); |
|
3711
|
bWW = p->spec.bWordWrap==QRF_Yes; |
|
3712
|
for(i=0; i<p->nCol; i++){ |
|
3713
|
const char *zVal; |
|
3714
|
int cnt = 0; |
|
3715
|
qrfWidthPrint(p, p->pOut, -p->u.sLine.mxColWth, p->u.sLine.azCol[i]); |
|
3716
|
sqlite3_str_append(p->pOut, p->spec.zColumnSep, nSep); |
|
3717
|
qrfRenderValue(p, pVal, i); |
|
3718
|
zVal = sqlite3_str_value(pVal); |
|
3719
|
if( zVal==0 ) zVal = ""; |
|
3720
|
do{ |
|
3721
|
int nThis, nWide, iNext; |
|
3722
|
qrfWrapLine(zVal, mxW, bWW, &nThis, &nWide, &iNext); |
|
3723
|
if( cnt ){ |
|
3724
|
sqlite3_str_appendchar(p->pOut,p->u.sLine.mxColWth+nSep,' '); |
|
3725
|
} |
|
3726
|
cnt++; |
|
3727
|
if( cnt>p->mxHeight ){ |
|
3728
|
zVal = "..."; |
|
3729
|
nThis = iNext = 3; |
|
3730
|
} |
|
3731
|
sqlite3_str_append(p->pOut, zVal, nThis); |
|
3732
|
sqlite3_str_append(p->pOut, "\n", 1); |
|
3733
|
zVal += iNext; |
|
3734
|
}while( zVal[0] ); |
|
3735
|
sqlite3_str_reset(pVal); |
|
3736
|
} |
|
3737
|
qrfStrErr(p, pVal); |
|
3738
|
sqlite3_free(sqlite3_str_finish(pVal)); |
|
3739
|
qrfWrite(p); |
|
3740
|
break; |
|
3741
|
} |
|
3742
|
case QRF_STYLE_Eqp: { |
|
3743
|
const char *zEqpLine = (const char*)sqlite3_column_text(p->pStmt,3); |
|
3744
|
int iEqpId = sqlite3_column_int(p->pStmt, 0); |
|
3745
|
int iParentId = sqlite3_column_int(p->pStmt, 1); |
|
3746
|
if( zEqpLine==0 ) zEqpLine = ""; |
|
3747
|
if( zEqpLine[0]=='-' ) qrfEqpRender(p, 0); |
|
3748
|
qrfEqpAppend(p, iEqpId, iParentId, zEqpLine); |
|
3749
|
break; |
|
3750
|
} |
|
3751
|
default: { /* QRF_STYLE_List */ |
|
3752
|
if( p->nRow==0 && p->spec.bTitles>=QRF_Yes ){ |
|
3753
|
qrfSimpleTitle(p); |
|
3754
|
} |
|
3755
|
for(i=0; i<p->nCol; i++){ |
|
3756
|
if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); |
|
3757
|
qrfRenderValue(p, p->pOut, i); |
|
3758
|
} |
|
3759
|
sqlite3_str_appendall(p->pOut, p->spec.zRowSep); |
|
3760
|
qrfWrite(p); |
|
3761
|
break; |
|
3762
|
} |
|
3763
|
} |
|
3764
|
p->nRow++; |
|
3765
|
} |
|
3766
|
|
|
3767
|
/* |
|
3768
|
** Initialize the internal Qrf object. |
|
3769
|
*/ |
|
3770
|
static void qrfInitialize( |
|
3771
|
Qrf *p, /* State object to be initialized */ |
|
3772
|
sqlite3_stmt *pStmt, /* Query whose output to be formatted */ |
|
3773
|
const sqlite3_qrf_spec *pSpec, /* Format specification */ |
|
3774
|
char **pzErr /* Write errors here */ |
|
3775
|
){ |
|
3776
|
size_t sz; /* Size of pSpec[], based on pSpec->iVersion */ |
|
3777
|
memset(p, 0, sizeof(*p)); |
|
3778
|
p->pzErr = pzErr; |
|
3779
|
if( pSpec->iVersion>2 ){ |
|
3780
|
qrfError(p, SQLITE_ERROR, |
|
3781
|
"unusable sqlite3_qrf_spec.iVersion (%d)", |
|
3782
|
pSpec->iVersion); |
|
3783
|
return; |
|
3784
|
} |
|
3785
|
p->pStmt = pStmt; |
|
3786
|
p->db = sqlite3_db_handle(pStmt); |
|
3787
|
p->pOut = sqlite3_str_new(p->db); |
|
3788
|
if( p->pOut==0 ){ |
|
3789
|
qrfOom(p); |
|
3790
|
return; |
|
3791
|
} |
|
3792
|
p->iErr = SQLITE_OK; |
|
3793
|
p->nCol = sqlite3_column_count(p->pStmt); |
|
3794
|
p->nRow = 0; |
|
3795
|
switch( pSpec->iVersion ){ |
|
3796
|
case 0: sz = offsetof(sqlite3_qrf_spec, bRowCount); break; |
|
3797
|
case 1: sz = offsetof(sqlite3_qrf_spec, bRowCount); break; |
|
3798
|
default: sz = sizeof(sqlite3_qrf_spec); break; |
|
3799
|
} |
|
3800
|
memcpy(&p->spec, pSpec, sz); |
|
3801
|
if( p->spec.zNull==0 ) p->spec.zNull = ""; |
|
3802
|
p->mxWidth = p->spec.nScreenWidth; |
|
3803
|
if( p->mxWidth<=0 ) p->mxWidth = 2147483647; |
|
3804
|
p->mxHeight = p->spec.nLineLimit; |
|
3805
|
if( p->mxHeight<=0 ) p->mxHeight = 2147483647; |
|
3806
|
if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto; |
|
3807
|
if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto; |
|
3808
|
if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto; |
|
3809
|
if( p->spec.eTitle>QRF_TEXT_Relaxed ) p->spec.eTitle = QRF_Auto; |
|
3810
|
if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto; |
|
3811
|
qrf_reinit: |
|
3812
|
if( p->spec.zFpFmt && sqlite3_qrf_ckformat(p->spec.zFpFmt)!=2 ){ |
|
3813
|
p->spec.zFpFmt = 0; |
|
3814
|
} |
|
3815
|
switch( p->spec.eStyle ){ |
|
3816
|
case QRF_Auto: { |
|
3817
|
switch( sqlite3_stmt_isexplain(pStmt) ){ |
|
3818
|
case 0: p->spec.eStyle = QRF_STYLE_Box; break; |
|
3819
|
case 1: p->spec.eStyle = QRF_STYLE_Explain; break; |
|
3820
|
default: p->spec.eStyle = QRF_STYLE_Eqp; break; |
|
3821
|
} |
|
3822
|
goto qrf_reinit; |
|
3823
|
} |
|
3824
|
case QRF_STYLE_List: { |
|
3825
|
if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = "|"; |
|
3826
|
if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n"; |
|
3827
|
break; |
|
3828
|
} |
|
3829
|
case QRF_STYLE_JObject: |
|
3830
|
case QRF_STYLE_Json: { |
|
3831
|
p->spec.eText = QRF_TEXT_Json; |
|
3832
|
p->spec.zNull = "null"; |
|
3833
|
if( p->spec.zFpFmt==0 ) p->spec.zFpFmt = "%0.16g"; |
|
3834
|
break; |
|
3835
|
} |
|
3836
|
case QRF_STYLE_Html: { |
|
3837
|
p->spec.eText = QRF_TEXT_Html; |
|
3838
|
p->spec.zNull = "null"; |
|
3839
|
break; |
|
3840
|
} |
|
3841
|
case QRF_STYLE_Insert: { |
|
3842
|
p->spec.eText = QRF_TEXT_Sql; |
|
3843
|
p->spec.zNull = "NULL"; |
|
3844
|
if( p->spec.zTableName==0 || p->spec.zTableName[0]==0 ){ |
|
3845
|
p->spec.zTableName = "tab"; |
|
3846
|
} |
|
3847
|
if( p->spec.zFpFmt==0 ) p->spec.zFpFmt = "%0.16g"; |
|
3848
|
p->u.nIns = 0; |
|
3849
|
break; |
|
3850
|
} |
|
3851
|
case QRF_STYLE_Line: { |
|
3852
|
if( p->spec.zColumnSep==0 ){ |
|
3853
|
p->spec.zColumnSep = ": "; |
|
3854
|
} |
|
3855
|
break; |
|
3856
|
} |
|
3857
|
case QRF_STYLE_Csv: { |
|
3858
|
p->spec.eStyle = QRF_STYLE_List; |
|
3859
|
p->spec.eText = QRF_TEXT_Csv; |
|
3860
|
p->spec.zColumnSep = ","; |
|
3861
|
p->spec.zRowSep = "\r\n"; |
|
3862
|
p->spec.zNull = ""; |
|
3863
|
if( p->spec.eEsc==QRF_Auto ) p->spec.eEsc = QRF_ESC_Off; |
|
3864
|
break; |
|
3865
|
} |
|
3866
|
case QRF_STYLE_Quote: { |
|
3867
|
p->spec.eText = QRF_TEXT_Sql; |
|
3868
|
p->spec.zNull = "NULL"; |
|
3869
|
p->spec.zColumnSep = ","; |
|
3870
|
p->spec.zRowSep = "\n"; |
|
3871
|
break; |
|
3872
|
} |
|
3873
|
case QRF_STYLE_Eqp: { |
|
3874
|
int expMode = sqlite3_stmt_isexplain(p->pStmt); |
|
3875
|
if( expMode!=2 ){ |
|
3876
|
int rc = sqlite3_stmt_explain(p->pStmt, 2); |
|
3877
|
if( rc ){ qrfError(p, SQLITE_ERROR, sqlite3_errstr(rc)); } |
|
3878
|
p->expMode = expMode+1; |
|
3879
|
} |
|
3880
|
break; |
|
3881
|
} |
|
3882
|
case QRF_STYLE_Explain: { |
|
3883
|
int expMode = sqlite3_stmt_isexplain(p->pStmt); |
|
3884
|
if( expMode!=1 ){ |
|
3885
|
int rc = sqlite3_stmt_explain(p->pStmt, 1); |
|
3886
|
if( rc ){ qrfError(p, SQLITE_ERROR, sqlite3_errstr(rc)); } |
|
3887
|
p->expMode = expMode+1; |
|
3888
|
} |
|
3889
|
break; |
|
3890
|
} |
|
3891
|
} |
|
3892
|
if( p->spec.eEsc==QRF_Auto ){ |
|
3893
|
p->spec.eEsc = QRF_ESC_Ascii; |
|
3894
|
} |
|
3895
|
if( p->spec.eText==QRF_Auto ){ |
|
3896
|
p->spec.eText = QRF_TEXT_Plain; |
|
3897
|
} |
|
3898
|
if( p->spec.eTitle==QRF_Auto ){ |
|
3899
|
switch( p->spec.eStyle ){ |
|
3900
|
case QRF_STYLE_Box: |
|
3901
|
case QRF_STYLE_Column: |
|
3902
|
case QRF_STYLE_Table: |
|
3903
|
p->spec.eTitle = QRF_TEXT_Plain; |
|
3904
|
break; |
|
3905
|
default: |
|
3906
|
p->spec.eTitle = p->spec.eText; |
|
3907
|
break; |
|
3908
|
} |
|
3909
|
} |
|
3910
|
if( p->spec.eBlob==QRF_Auto ){ |
|
3911
|
switch( p->spec.eText ){ |
|
3912
|
case QRF_TEXT_Sql: p->spec.eBlob = QRF_BLOB_Sql; break; |
|
3913
|
case QRF_TEXT_Csv: p->spec.eBlob = QRF_BLOB_Tcl; break; |
|
3914
|
case QRF_TEXT_Tcl: p->spec.eBlob = QRF_BLOB_Tcl; break; |
|
3915
|
case QRF_TEXT_Json: p->spec.eBlob = QRF_BLOB_Json; break; |
|
3916
|
default: p->spec.eBlob = QRF_BLOB_Text; break; |
|
3917
|
} |
|
3918
|
} |
|
3919
|
if( p->spec.bTitles==QRF_Auto ){ |
|
3920
|
switch( p->spec.eStyle ){ |
|
3921
|
case QRF_STYLE_Box: |
|
3922
|
case QRF_STYLE_Csv: |
|
3923
|
case QRF_STYLE_Column: |
|
3924
|
case QRF_STYLE_Table: |
|
3925
|
case QRF_STYLE_Markdown: |
|
3926
|
p->spec.bTitles = QRF_Yes; |
|
3927
|
break; |
|
3928
|
default: |
|
3929
|
p->spec.bTitles = QRF_No; |
|
3930
|
break; |
|
3931
|
} |
|
3932
|
} |
|
3933
|
if( p->spec.bWordWrap==QRF_Auto ){ |
|
3934
|
p->spec.bWordWrap = QRF_Yes; |
|
3935
|
} |
|
3936
|
if( p->spec.bTextJsonb==QRF_Auto ){ |
|
3937
|
p->spec.bTextJsonb = QRF_No; |
|
3938
|
} |
|
3939
|
if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = ","; |
|
3940
|
if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n"; |
|
3941
|
if( p->spec.zIFmt==0 || sqlite3_qrf_ckformat(p->spec.zIFmt)!=1 ){ |
|
3942
|
p->spec.zIFmt = "%lld"; |
|
3943
|
}else{ |
|
3944
|
size_t n = strlen(p->spec.zIFmt); |
|
3945
|
memcpy(p->zFmt, p->spec.zIFmt, n-1); |
|
3946
|
p->zFmt[n-1] = 'l'; |
|
3947
|
p->zFmt[n] = 'l'; |
|
3948
|
p->zFmt[n+1] = p->spec.zIFmt[n-1]; |
|
3949
|
p->zFmt[n+2] = 0; |
|
3950
|
p->spec.zIFmt = p->zFmt; |
|
3951
|
} |
|
3952
|
} |
|
3953
|
|
|
3954
|
/* |
|
3955
|
** Finish rendering the results |
|
3956
|
*/ |
|
3957
|
static void qrfFinalize(Qrf *p){ |
|
3958
|
switch( p->spec.eStyle ){ |
|
3959
|
case QRF_STYLE_Count: { |
|
3960
|
sqlite3_str_appendf(p->pOut, "%lld\n", p->nRow); |
|
3961
|
break; |
|
3962
|
} |
|
3963
|
case QRF_STYLE_Json: { |
|
3964
|
if( p->nRow>0 ){ |
|
3965
|
sqlite3_str_append(p->pOut, "}]\n", 3); |
|
3966
|
} |
|
3967
|
break; |
|
3968
|
} |
|
3969
|
case QRF_STYLE_JObject: { |
|
3970
|
if( p->nRow>0 ){ |
|
3971
|
sqlite3_str_append(p->pOut, "}\n", 2); |
|
3972
|
} |
|
3973
|
break; |
|
3974
|
} |
|
3975
|
case QRF_STYLE_Insert: { |
|
3976
|
if( p->u.nIns ){ |
|
3977
|
sqlite3_str_append(p->pOut, ";\n", 2); |
|
3978
|
} |
|
3979
|
break; |
|
3980
|
} |
|
3981
|
case QRF_STYLE_Line: { |
|
3982
|
if( p->u.sLine.azCol ){ |
|
3983
|
int i; |
|
3984
|
for(i=0; i<p->nCol; i++) sqlite3_free(p->u.sLine.azCol[i]); |
|
3985
|
sqlite3_free(p->u.sLine.azCol); |
|
3986
|
} |
|
3987
|
break; |
|
3988
|
} |
|
3989
|
case QRF_STYLE_Stats: |
|
3990
|
case QRF_STYLE_StatsEst: { |
|
3991
|
i64 nCycle = 0; |
|
3992
|
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
|
3993
|
sqlite3_stmt_scanstatus_v2(p->pStmt, -1, SQLITE_SCANSTAT_NCYCLE, |
|
3994
|
SQLITE_SCANSTAT_COMPLEX, (void*)&nCycle); |
|
3995
|
#endif |
|
3996
|
qrfEqpRender(p, nCycle); |
|
3997
|
break; |
|
3998
|
} |
|
3999
|
case QRF_STYLE_Eqp: { |
|
4000
|
qrfEqpRender(p, 0); |
|
4001
|
break; |
|
4002
|
} |
|
4003
|
} |
|
4004
|
qrfWrite(p); |
|
4005
|
qrfStrErr(p, p->pOut); |
|
4006
|
if( p->spec.pzOutput ){ |
|
4007
|
if( p->spec.pzOutput[0] ){ |
|
4008
|
sqlite3_int64 n, sz; |
|
4009
|
char *zCombined; |
|
4010
|
sz = strlen(p->spec.pzOutput[0]); |
|
4011
|
n = sqlite3_str_length(p->pOut); |
|
4012
|
zCombined = sqlite3_realloc64(p->spec.pzOutput[0], sz+n+1); |
|
4013
|
if( zCombined==0 ){ |
|
4014
|
sqlite3_free(p->spec.pzOutput[0]); |
|
4015
|
p->spec.pzOutput[0] = 0; |
|
4016
|
qrfOom(p); |
|
4017
|
}else{ |
|
4018
|
p->spec.pzOutput[0] = zCombined; |
|
4019
|
memcpy(zCombined+sz, sqlite3_str_value(p->pOut), n+1); |
|
4020
|
} |
|
4021
|
sqlite3_free(sqlite3_str_finish(p->pOut)); |
|
4022
|
}else{ |
|
4023
|
p->spec.pzOutput[0] = sqlite3_str_finish(p->pOut); |
|
4024
|
} |
|
4025
|
}else if( p->pOut ){ |
|
4026
|
sqlite3_free(sqlite3_str_finish(p->pOut)); |
|
4027
|
} |
|
4028
|
if( p->expMode>0 ){ |
|
4029
|
sqlite3_stmt_explain(p->pStmt, p->expMode-1); |
|
4030
|
} |
|
4031
|
if( p->actualWidth ){ |
|
4032
|
sqlite3_free(p->actualWidth); |
|
4033
|
} |
|
4034
|
if( p->pJTrans ){ |
|
4035
|
sqlite3 *db = sqlite3_db_handle(p->pJTrans); |
|
4036
|
sqlite3_finalize(p->pJTrans); |
|
4037
|
sqlite3_close(db); |
|
4038
|
} |
|
4039
|
} |
|
4040
|
|
|
4041
|
/* |
|
4042
|
** Run the prepared statement pStmt and format the results according |
|
4043
|
** to the specification provided in pSpec. Return an error code. |
|
4044
|
** If pzErr is not NULL and if an error occurs, write an error message |
|
4045
|
** into *pzErr. |
|
4046
|
*/ |
|
4047
|
int sqlite3_format_query_result( |
|
4048
|
sqlite3_stmt *pStmt, /* Statement to evaluate */ |
|
4049
|
const sqlite3_qrf_spec *pSpec, /* Format specification */ |
|
4050
|
char **pzErr /* Write error message here */ |
|
4051
|
){ |
|
4052
|
Qrf qrf; /* The new Qrf being created */ |
|
4053
|
|
|
4054
|
if( pStmt==0 ) return SQLITE_OK; /* No-op */ |
|
4055
|
if( pSpec==0 ) return SQLITE_MISUSE; |
|
4056
|
if( sqlite3_stmt_busy(pStmt) ) return SQLITE_BUSY; |
|
4057
|
qrfInitialize(&qrf, pStmt, pSpec, pzErr); |
|
4058
|
switch( qrf.spec.eStyle ){ |
|
4059
|
case QRF_STYLE_Box: |
|
4060
|
case QRF_STYLE_Column: |
|
4061
|
case QRF_STYLE_Markdown: |
|
4062
|
case QRF_STYLE_Table: { |
|
4063
|
/* Columnar modes require that the entire query be evaluated and the |
|
4064
|
** results stored in memory, so that we can compute column widths */ |
|
4065
|
qrfColumnar(&qrf); |
|
4066
|
break; |
|
4067
|
} |
|
4068
|
case QRF_STYLE_Explain: { |
|
4069
|
qrfExplain(&qrf); |
|
4070
|
break; |
|
4071
|
} |
|
4072
|
case QRF_STYLE_StatsVm: { |
|
4073
|
qrfScanStatusVm(&qrf); |
|
4074
|
break; |
|
4075
|
} |
|
4076
|
case QRF_STYLE_Stats: |
|
4077
|
case QRF_STYLE_StatsEst: { |
|
4078
|
qrfEqpStats(&qrf); |
|
4079
|
break; |
|
4080
|
} |
|
4081
|
default: { |
|
4082
|
/* Non-columnar modes where the output can occur after each row |
|
4083
|
** of result is received */ |
|
4084
|
while( qrf.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ |
|
4085
|
qrfOneSimpleRow(&qrf); |
|
4086
|
} |
|
4087
|
if( qrf.nCol>0 && qrf.nRow==0 && qrf.spec.bTitles==QRF_Always ){ |
|
4088
|
qrfSimpleTitle(&qrf); |
|
4089
|
} |
|
4090
|
if( qrf.nCol>0 && qrf.spec.bRowCount==QRF_Yes ){ |
|
4091
|
const char *zPlural = qrf.nRow==1 ? "" : "s"; |
|
4092
|
switch( qrf.spec.eStyle ){ |
|
4093
|
case QRF_STYLE_Line: |
|
4094
|
if( qrf.nRow>0 ) sqlite3_str_append(qrf.pOut, "\n", 1); |
|
4095
|
/* Fall through */ |
|
4096
|
case QRF_STYLE_Csv: |
|
4097
|
case QRF_STYLE_List: |
|
4098
|
case QRF_STYLE_Quote: |
|
4099
|
sqlite3_str_appendf(qrf.pOut,"(%lld row%s)\n",qrf.nRow,zPlural); |
|
4100
|
break; |
|
4101
|
case QRF_STYLE_Html: |
|
4102
|
sqlite3_str_appendf(qrf.pOut,"<!-- %lld row%s -->\n", |
|
4103
|
qrf.nRow, zPlural); |
|
4104
|
break; |
|
4105
|
case QRF_STYLE_Insert: |
|
4106
|
sqlite3_str_appendf(qrf.pOut,"/* %lld row%s inserted */\n", |
|
4107
|
qrf.nRow, zPlural); |
|
4108
|
break; |
|
4109
|
} |
|
4110
|
} |
|
4111
|
break; |
|
4112
|
} |
|
4113
|
} |
|
4114
|
qrfResetStmt(&qrf); |
|
4115
|
qrfFinalize(&qrf); |
|
4116
|
return qrf.iErr; |
|
4117
|
} |
|
4118
|
|
|
4119
|
/************************* End ext/qrf/qrf.c ********************/ |
|
4120
|
|
|
4121
|
/* Use console I/O package as a direct INCLUDE. */ |
|
4122
|
#define SQLITE_INTERNAL_LINKAGE static |
|
4123
|
|
|
4124
|
#ifdef SQLITE_SHELL_FIDDLE |
|
4125
|
/* Deselect most features from the console I/O package for Fiddle. */ |
|
4126
|
# define SQLITE_CIO_NO_REDIRECT |
|
4127
|
# define SQLITE_CIO_NO_CLASSIFY |
|
4128
|
# define SQLITE_CIO_NO_TRANSLATE |
|
4129
|
# define SQLITE_CIO_NO_SETMODE |
|
4130
|
# define SQLITE_CIO_NO_FLUSH |
|
4131
|
#endif |
|
4132
|
|
|
4133
|
/* |
|
4134
|
** The source code for several run-time loadable extensions is inserted |
|
4135
|
** below by the ../tool/mkshellc.tcl script. Before processing that included |
|
4136
|
** code, we need to override some macros to make the included program code |
|
4137
|
** work here in the middle of this regular program. |
|
4138
|
*/ |
|
4139
|
#define SQLITE_EXTENSION_INIT1 |
|
4140
|
#define SQLITE_EXTENSION_INIT2(X) (void)(X) |
|
4141
|
|
|
4142
|
/************************* Begin ext/misc/windirent.h ******************/ |
|
4143
|
/* |
|
4144
|
** 2025-06-05 |
|
4145
|
** |
|
4146
|
** The author disclaims copyright to this source code. In place of |
|
4147
|
** a legal notice, here is a blessing: |
|
4148
|
** |
|
4149
|
** May you do good and not evil. |
|
4150
|
** May you find forgiveness for yourself and forgive others. |
|
4151
|
** May you share freely, never taking more than you give. |
|
4152
|
** |
|
4153
|
************************************************************************* |
|
4154
|
** |
|
4155
|
** An implementation of opendir(), readdir(), and closedir() for Windows, |
|
4156
|
** based on the FindFirstFile(), FindNextFile(), and FindClose() APIs |
|
4157
|
** of Win32. |
|
4158
|
** |
|
4159
|
** #include this file inside any C-code module that needs to use |
|
4160
|
** opendir()/readdir()/closedir(). This file is a no-op on non-Windows |
|
4161
|
** machines. On Windows, static functions are defined that implement |
|
4162
|
** those standard interfaces. |
|
4163
|
*/ |
|
4164
|
#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H) |
|
4165
|
#define SQLITE_WINDIRENT_H |
|
4166
|
|
|
4167
|
#ifndef WIN32_LEAN_AND_MEAN |
|
4168
|
#define WIN32_LEAN_AND_MEAN |
|
4169
|
#endif |
|
4170
|
#include <windows.h> |
|
4171
|
#include <io.h> |
|
4172
|
#include <stdio.h> |
|
4173
|
#include <stdlib.h> |
|
4174
|
#include <errno.h> |
|
4175
|
#include <limits.h> |
|
4176
|
#include <sys/types.h> |
|
4177
|
#include <sys/stat.h> |
|
4178
|
#include <string.h> |
|
4179
|
#ifndef FILENAME_MAX |
|
4180
|
# define FILENAME_MAX (260) |
|
4181
|
#endif |
|
4182
|
#ifndef S_ISREG |
|
4183
|
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) |
|
4184
|
#endif |
|
4185
|
#ifndef S_ISDIR |
|
4186
|
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
|
4187
|
#endif |
|
4188
|
#ifndef S_ISLNK |
|
4189
|
#define S_ISLNK(m) (0) |
|
4190
|
#endif |
|
4191
|
typedef unsigned short mode_t; |
|
4192
|
|
|
4193
|
/* The dirent object for Windows is abbreviated. The only field really |
|
4194
|
** usable by applications is d_name[]. |
|
4195
|
*/ |
|
4196
|
struct dirent { |
|
4197
|
int d_ino; /* Inode number (synthesized) */ |
|
4198
|
unsigned d_attributes; /* File attributes */ |
|
4199
|
char d_name[FILENAME_MAX]; /* Null-terminated filename */ |
|
4200
|
}; |
|
4201
|
|
|
4202
|
/* The internals of DIR are opaque according to standards. So it |
|
4203
|
** does not matter what we put here. */ |
|
4204
|
typedef struct DIR DIR; |
|
4205
|
struct DIR { |
|
4206
|
intptr_t d_handle; /* Handle for findfirst()/findnext() */ |
|
4207
|
struct dirent cur; /* Current entry */ |
|
4208
|
}; |
|
4209
|
|
|
4210
|
/* Ignore hidden and system files */ |
|
4211
|
#define WindowsFileToIgnore(a) \ |
|
4212
|
((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) |
|
4213
|
|
|
4214
|
/* |
|
4215
|
** Close a previously opened directory |
|
4216
|
*/ |
|
4217
|
static int closedir(DIR *pDir){ |
|
4218
|
int rc = 0; |
|
4219
|
if( pDir==0 ){ |
|
4220
|
return EINVAL; |
|
4221
|
} |
|
4222
|
if( pDir->d_handle!=0 && pDir->d_handle!=(-1) ){ |
|
4223
|
rc = _findclose(pDir->d_handle); |
|
4224
|
} |
|
4225
|
sqlite3_free(pDir); |
|
4226
|
return rc; |
|
4227
|
} |
|
4228
|
|
|
4229
|
/* |
|
4230
|
** Open a new directory. The directory name should be UTF-8 encoded. |
|
4231
|
** appropriate translations happen automatically. |
|
4232
|
*/ |
|
4233
|
static DIR *opendir(const char *zDirName){ |
|
4234
|
DIR *pDir; |
|
4235
|
wchar_t *b1; |
|
4236
|
sqlite3_int64 sz; |
|
4237
|
struct _wfinddata_t data; |
|
4238
|
|
|
4239
|
pDir = sqlite3_malloc64( sizeof(DIR) ); |
|
4240
|
if( pDir==0 ) return 0; |
|
4241
|
memset(pDir, 0, sizeof(DIR)); |
|
4242
|
memset(&data, 0, sizeof(data)); |
|
4243
|
sz = strlen(zDirName); |
|
4244
|
b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) ); |
|
4245
|
if( b1==0 ){ |
|
4246
|
closedir(pDir); |
|
4247
|
return NULL; |
|
4248
|
} |
|
4249
|
sz = MultiByteToWideChar(CP_UTF8, 0, zDirName, sz, b1, sz); |
|
4250
|
b1[sz++] = '\\'; |
|
4251
|
b1[sz++] = '*'; |
|
4252
|
b1[sz] = 0; |
|
4253
|
if( sz+1>sizeof(data.name)/sizeof(data.name[0]) ){ |
|
4254
|
closedir(pDir); |
|
4255
|
sqlite3_free(b1); |
|
4256
|
return NULL; |
|
4257
|
} |
|
4258
|
memcpy(data.name, b1, (sz+1)*sizeof(b1[0])); |
|
4259
|
sqlite3_free(b1); |
|
4260
|
pDir->d_handle = _wfindfirst(data.name, &data); |
|
4261
|
if( pDir->d_handle<0 ){ |
|
4262
|
closedir(pDir); |
|
4263
|
return NULL; |
|
4264
|
} |
|
4265
|
while( WindowsFileToIgnore(data) ){ |
|
4266
|
memset(&data, 0, sizeof(data)); |
|
4267
|
if( _wfindnext(pDir->d_handle, &data)==-1 ){ |
|
4268
|
closedir(pDir); |
|
4269
|
return NULL; |
|
4270
|
} |
|
4271
|
} |
|
4272
|
pDir->cur.d_ino = 0; |
|
4273
|
pDir->cur.d_attributes = data.attrib; |
|
4274
|
WideCharToMultiByte(CP_UTF8, 0, data.name, -1, |
|
4275
|
pDir->cur.d_name, FILENAME_MAX, 0, 0); |
|
4276
|
return pDir; |
|
4277
|
} |
|
4278
|
|
|
4279
|
/* |
|
4280
|
** Read the next entry from a directory. |
|
4281
|
** |
|
4282
|
** The returned struct-dirent object is managed by DIR. It is only |
|
4283
|
** valid until the next readdir() or closedir() call. Only the |
|
4284
|
** d_name[] field is meaningful. The d_name[] value has been |
|
4285
|
** translated into UTF8. |
|
4286
|
*/ |
|
4287
|
static struct dirent *readdir(DIR *pDir){ |
|
4288
|
struct _wfinddata_t data; |
|
4289
|
if( pDir==0 ) return 0; |
|
4290
|
if( (pDir->cur.d_ino++)==0 ){ |
|
4291
|
return &pDir->cur; |
|
4292
|
} |
|
4293
|
do{ |
|
4294
|
memset(&data, 0, sizeof(data)); |
|
4295
|
if( _wfindnext(pDir->d_handle, &data)==-1 ){ |
|
4296
|
return NULL; |
|
4297
|
} |
|
4298
|
}while( WindowsFileToIgnore(data) ); |
|
4299
|
pDir->cur.d_attributes = data.attrib; |
|
4300
|
WideCharToMultiByte(CP_UTF8, 0, data.name, -1, |
|
4301
|
pDir->cur.d_name, FILENAME_MAX, 0, 0); |
|
4302
|
return &pDir->cur; |
|
4303
|
} |
|
4304
|
|
|
4305
|
#endif /* defined(_WIN32) && defined(_MSC_VER) */ |
|
4306
|
|
|
4307
|
/************************* End ext/misc/windirent.h ********************/ |
|
4308
|
/************************* Begin ext/misc/memtrace.c ******************/ |
|
4309
|
/* |
|
4310
|
** 2019-01-21 |
|
4311
|
** |
|
4312
|
** The author disclaims copyright to this source code. In place of |
|
4313
|
** a legal notice, here is a blessing: |
|
4314
|
** |
|
4315
|
** May you do good and not evil. |
|
4316
|
** May you find forgiveness for yourself and forgive others. |
|
4317
|
** May you share freely, never taking more than you give. |
|
4318
|
** |
|
4319
|
************************************************************************* |
|
4320
|
** |
|
4321
|
** This file implements an extension that uses the SQLITE_CONFIG_MALLOC |
|
4322
|
** mechanism to add a tracing layer on top of SQLite. If this extension |
|
4323
|
** is registered prior to sqlite3_initialize(), it will cause all memory |
|
4324
|
** allocation activities to be logged on standard output, or to some other |
|
4325
|
** FILE specified by the initializer. |
|
4326
|
** |
|
4327
|
** This file needs to be compiled into the application that uses it. |
|
4328
|
** |
|
4329
|
** This extension is used to implement the --memtrace option of the |
|
4330
|
** command-line shell. |
|
4331
|
*/ |
|
4332
|
#include <assert.h> |
|
4333
|
#include <string.h> |
|
4334
|
#include <stdio.h> |
|
4335
|
|
|
4336
|
/* The original memory allocation routines */ |
|
4337
|
static sqlite3_mem_methods memtraceBase; |
|
4338
|
static FILE *memtraceOut; |
|
4339
|
|
|
4340
|
/* Methods that trace memory allocations */ |
|
4341
|
static void *memtraceMalloc(int n){ |
|
4342
|
if( memtraceOut ){ |
|
4343
|
fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", |
|
4344
|
memtraceBase.xRoundup(n)); |
|
4345
|
} |
|
4346
|
return memtraceBase.xMalloc(n); |
|
4347
|
} |
|
4348
|
static void memtraceFree(void *p){ |
|
4349
|
if( p==0 ) return; |
|
4350
|
if( memtraceOut ){ |
|
4351
|
fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p)); |
|
4352
|
} |
|
4353
|
memtraceBase.xFree(p); |
|
4354
|
} |
|
4355
|
static void *memtraceRealloc(void *p, int n){ |
|
4356
|
if( p==0 ) return memtraceMalloc(n); |
|
4357
|
if( n==0 ){ |
|
4358
|
memtraceFree(p); |
|
4359
|
return 0; |
|
4360
|
} |
|
4361
|
if( memtraceOut ){ |
|
4362
|
fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n", |
|
4363
|
memtraceBase.xSize(p), memtraceBase.xRoundup(n)); |
|
4364
|
} |
|
4365
|
return memtraceBase.xRealloc(p, n); |
|
4366
|
} |
|
4367
|
static int memtraceSize(void *p){ |
|
4368
|
return memtraceBase.xSize(p); |
|
4369
|
} |
|
4370
|
static int memtraceRoundup(int n){ |
|
4371
|
return memtraceBase.xRoundup(n); |
|
4372
|
} |
|
4373
|
static int memtraceInit(void *p){ |
|
4374
|
return memtraceBase.xInit(p); |
|
4375
|
} |
|
4376
|
static void memtraceShutdown(void *p){ |
|
4377
|
memtraceBase.xShutdown(p); |
|
4378
|
} |
|
4379
|
|
|
4380
|
/* The substitute memory allocator */ |
|
4381
|
static sqlite3_mem_methods ersaztMethods = { |
|
4382
|
memtraceMalloc, |
|
4383
|
memtraceFree, |
|
4384
|
memtraceRealloc, |
|
4385
|
memtraceSize, |
|
4386
|
memtraceRoundup, |
|
4387
|
memtraceInit, |
|
4388
|
memtraceShutdown, |
|
4389
|
0 |
|
4390
|
}; |
|
4391
|
|
|
4392
|
/* Begin tracing memory allocations to out. */ |
|
4393
|
int sqlite3MemTraceActivate(FILE *out){ |
|
4394
|
int rc = SQLITE_OK; |
|
4395
|
if( memtraceBase.xMalloc==0 ){ |
|
4396
|
rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase); |
|
4397
|
if( rc==SQLITE_OK ){ |
|
4398
|
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods); |
|
4399
|
} |
|
4400
|
} |
|
4401
|
memtraceOut = out; |
|
4402
|
return rc; |
|
4403
|
} |
|
4404
|
|
|
4405
|
/* Deactivate memory tracing */ |
|
4406
|
int sqlite3MemTraceDeactivate(void){ |
|
4407
|
int rc = SQLITE_OK; |
|
4408
|
if( memtraceBase.xMalloc!=0 ){ |
|
4409
|
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase); |
|
4410
|
if( rc==SQLITE_OK ){ |
|
4411
|
memset(&memtraceBase, 0, sizeof(memtraceBase)); |
|
4412
|
} |
|
4413
|
} |
|
4414
|
memtraceOut = 0; |
|
4415
|
return rc; |
|
4416
|
} |
|
4417
|
|
|
4418
|
/************************* End ext/misc/memtrace.c ********************/ |
|
4419
|
/************************* Begin ext/misc/pcachetrace.c ******************/ |
|
4420
|
/* |
|
4421
|
** 2023-06-21 |
|
4422
|
** |
|
4423
|
** The author disclaims copyright to this source code. In place of |
|
4424
|
** a legal notice, here is a blessing: |
|
4425
|
** |
|
4426
|
** May you do good and not evil. |
|
4427
|
** May you find forgiveness for yourself and forgive others. |
|
4428
|
** May you share freely, never taking more than you give. |
|
4429
|
** |
|
4430
|
************************************************************************* |
|
4431
|
** |
|
4432
|
** This file implements an extension that uses the SQLITE_CONFIG_PCACHE2 |
|
4433
|
** mechanism to add a tracing layer on top of pluggable page cache of |
|
4434
|
** SQLite. If this extension is registered prior to sqlite3_initialize(), |
|
4435
|
** it will cause all page cache activities to be logged on standard output, |
|
4436
|
** or to some other FILE specified by the initializer. |
|
4437
|
** |
|
4438
|
** This file needs to be compiled into the application that uses it. |
|
4439
|
** |
|
4440
|
** This extension is used to implement the --pcachetrace option of the |
|
4441
|
** command-line shell. |
|
4442
|
*/ |
|
4443
|
#include <assert.h> |
|
4444
|
#include <string.h> |
|
4445
|
#include <stdio.h> |
|
4446
|
|
|
4447
|
/* The original page cache routines */ |
|
4448
|
static sqlite3_pcache_methods2 pcacheBase; |
|
4449
|
static FILE *pcachetraceOut; |
|
4450
|
|
|
4451
|
/* Methods that trace pcache activity */ |
|
4452
|
static int pcachetraceInit(void *pArg){ |
|
4453
|
int nRes; |
|
4454
|
if( pcachetraceOut ){ |
|
4455
|
fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p)\n", pArg); |
|
4456
|
} |
|
4457
|
nRes = pcacheBase.xInit(pArg); |
|
4458
|
if( pcachetraceOut ){ |
|
4459
|
fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p) -> %d\n", pArg, nRes); |
|
4460
|
} |
|
4461
|
return nRes; |
|
4462
|
} |
|
4463
|
static void pcachetraceShutdown(void *pArg){ |
|
4464
|
if( pcachetraceOut ){ |
|
4465
|
fprintf(pcachetraceOut, "PCACHETRACE: xShutdown(%p)\n", pArg); |
|
4466
|
} |
|
4467
|
pcacheBase.xShutdown(pArg); |
|
4468
|
} |
|
4469
|
static sqlite3_pcache *pcachetraceCreate(int szPage, int szExtra, int bPurge){ |
|
4470
|
sqlite3_pcache *pRes; |
|
4471
|
if( pcachetraceOut ){ |
|
4472
|
fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d)\n", |
|
4473
|
szPage, szExtra, bPurge); |
|
4474
|
} |
|
4475
|
pRes = pcacheBase.xCreate(szPage, szExtra, bPurge); |
|
4476
|
if( pcachetraceOut ){ |
|
4477
|
fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d) -> %p\n", |
|
4478
|
szPage, szExtra, bPurge, pRes); |
|
4479
|
} |
|
4480
|
return pRes; |
|
4481
|
} |
|
4482
|
static void pcachetraceCachesize(sqlite3_pcache *p, int nCachesize){ |
|
4483
|
if( pcachetraceOut ){ |
|
4484
|
fprintf(pcachetraceOut, "PCACHETRACE: xCachesize(%p, %d)\n", p, nCachesize); |
|
4485
|
} |
|
4486
|
pcacheBase.xCachesize(p, nCachesize); |
|
4487
|
} |
|
4488
|
static int pcachetracePagecount(sqlite3_pcache *p){ |
|
4489
|
int nRes; |
|
4490
|
if( pcachetraceOut ){ |
|
4491
|
fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p)\n", p); |
|
4492
|
} |
|
4493
|
nRes = pcacheBase.xPagecount(p); |
|
4494
|
if( pcachetraceOut ){ |
|
4495
|
fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p) -> %d\n", p, nRes); |
|
4496
|
} |
|
4497
|
return nRes; |
|
4498
|
} |
|
4499
|
static sqlite3_pcache_page *pcachetraceFetch( |
|
4500
|
sqlite3_pcache *p, |
|
4501
|
unsigned key, |
|
4502
|
int crFg |
|
4503
|
){ |
|
4504
|
sqlite3_pcache_page *pRes; |
|
4505
|
if( pcachetraceOut ){ |
|
4506
|
fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d)\n", p, key, crFg); |
|
4507
|
} |
|
4508
|
pRes = pcacheBase.xFetch(p, key, crFg); |
|
4509
|
if( pcachetraceOut ){ |
|
4510
|
fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d) -> %p\n", |
|
4511
|
p, key, crFg, pRes); |
|
4512
|
} |
|
4513
|
return pRes; |
|
4514
|
} |
|
4515
|
static void pcachetraceUnpin( |
|
4516
|
sqlite3_pcache *p, |
|
4517
|
sqlite3_pcache_page *pPg, |
|
4518
|
int bDiscard |
|
4519
|
){ |
|
4520
|
if( pcachetraceOut ){ |
|
4521
|
fprintf(pcachetraceOut, "PCACHETRACE: xUnpin(%p, %p, %d)\n", |
|
4522
|
p, pPg, bDiscard); |
|
4523
|
} |
|
4524
|
pcacheBase.xUnpin(p, pPg, bDiscard); |
|
4525
|
} |
|
4526
|
static void pcachetraceRekey( |
|
4527
|
sqlite3_pcache *p, |
|
4528
|
sqlite3_pcache_page *pPg, |
|
4529
|
unsigned oldKey, |
|
4530
|
unsigned newKey |
|
4531
|
){ |
|
4532
|
if( pcachetraceOut ){ |
|
4533
|
fprintf(pcachetraceOut, "PCACHETRACE: xRekey(%p, %p, %u, %u)\n", |
|
4534
|
p, pPg, oldKey, newKey); |
|
4535
|
} |
|
4536
|
pcacheBase.xRekey(p, pPg, oldKey, newKey); |
|
4537
|
} |
|
4538
|
static void pcachetraceTruncate(sqlite3_pcache *p, unsigned n){ |
|
4539
|
if( pcachetraceOut ){ |
|
4540
|
fprintf(pcachetraceOut, "PCACHETRACE: xTruncate(%p, %u)\n", p, n); |
|
4541
|
} |
|
4542
|
pcacheBase.xTruncate(p, n); |
|
4543
|
} |
|
4544
|
static void pcachetraceDestroy(sqlite3_pcache *p){ |
|
4545
|
if( pcachetraceOut ){ |
|
4546
|
fprintf(pcachetraceOut, "PCACHETRACE: xDestroy(%p)\n", p); |
|
4547
|
} |
|
4548
|
pcacheBase.xDestroy(p); |
|
4549
|
} |
|
4550
|
static void pcachetraceShrink(sqlite3_pcache *p){ |
|
4551
|
if( pcachetraceOut ){ |
|
4552
|
fprintf(pcachetraceOut, "PCACHETRACE: xShrink(%p)\n", p); |
|
4553
|
} |
|
4554
|
pcacheBase.xShrink(p); |
|
4555
|
} |
|
4556
|
|
|
4557
|
/* The substitute pcache methods */ |
|
4558
|
static sqlite3_pcache_methods2 ersaztPcacheMethods = { |
|
4559
|
0, |
|
4560
|
0, |
|
4561
|
pcachetraceInit, |
|
4562
|
pcachetraceShutdown, |
|
4563
|
pcachetraceCreate, |
|
4564
|
pcachetraceCachesize, |
|
4565
|
pcachetracePagecount, |
|
4566
|
pcachetraceFetch, |
|
4567
|
pcachetraceUnpin, |
|
4568
|
pcachetraceRekey, |
|
4569
|
pcachetraceTruncate, |
|
4570
|
pcachetraceDestroy, |
|
4571
|
pcachetraceShrink |
|
4572
|
}; |
|
4573
|
|
|
4574
|
/* Begin tracing memory allocations to out. */ |
|
4575
|
int sqlite3PcacheTraceActivate(FILE *out){ |
|
4576
|
int rc = SQLITE_OK; |
|
4577
|
if( pcacheBase.xFetch==0 ){ |
|
4578
|
rc = sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &pcacheBase); |
|
4579
|
if( rc==SQLITE_OK ){ |
|
4580
|
rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &ersaztPcacheMethods); |
|
4581
|
} |
|
4582
|
} |
|
4583
|
pcachetraceOut = out; |
|
4584
|
return rc; |
|
4585
|
} |
|
4586
|
|
|
4587
|
/* Deactivate memory tracing */ |
|
4588
|
int sqlite3PcacheTraceDeactivate(void){ |
|
4589
|
int rc = SQLITE_OK; |
|
4590
|
if( pcacheBase.xFetch!=0 ){ |
|
4591
|
rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcacheBase); |
|
4592
|
if( rc==SQLITE_OK ){ |
|
4593
|
memset(&pcacheBase, 0, sizeof(pcacheBase)); |
|
4594
|
} |
|
4595
|
} |
|
4596
|
pcachetraceOut = 0; |
|
4597
|
return rc; |
|
4598
|
} |
|
4599
|
|
|
4600
|
/************************* End ext/misc/pcachetrace.c ********************/ |
|
4601
|
/************************* Begin ext/misc/shathree.c ******************/ |
|
4602
|
/* |
|
4603
|
** 2017-03-08 |
|
4604
|
** |
|
4605
|
** The author disclaims copyright to this source code. In place of |
|
4606
|
** a legal notice, here is a blessing: |
|
4607
|
** |
|
4608
|
** May you do good and not evil. |
|
4609
|
** May you find forgiveness for yourself and forgive others. |
|
4610
|
** May you share freely, never taking more than you give. |
|
4611
|
** |
|
4612
|
****************************************************************************** |
|
4613
|
** |
|
4614
|
** This SQLite extension implements functions that compute SHA3 hashes |
|
4615
|
** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard. |
|
4616
|
** Three SQL functions are implemented: |
|
4617
|
** |
|
4618
|
** sha3(X,SIZE) |
|
4619
|
** sha3_agg(Y,SIZE) |
|
4620
|
** sha3_query(Z,SIZE) |
|
4621
|
** |
|
4622
|
** The sha3(X) function computes the SHA3 hash of the input X, or NULL if |
|
4623
|
** X is NULL. If inputs X is text, the UTF-8 rendering of that text is |
|
4624
|
** used to compute the hash. If X is a BLOB, then the binary data of the |
|
4625
|
** blob is used to compute the hash. If X is an integer or real number, |
|
4626
|
** then that number if converted into UTF-8 text and the hash is computed |
|
4627
|
** over the text. |
|
4628
|
** |
|
4629
|
** The sha3_agg(Y) function computes the SHA3 hash of all Y inputs. Since |
|
4630
|
** order is important for the hash, it is recommended that the Y expression |
|
4631
|
** by followed by an ORDER BY clause to guarantee that the inputs occur |
|
4632
|
** in the desired order. |
|
4633
|
** |
|
4634
|
** The sha3_query(Y) function evaluates all queries in the SQL statements of Y |
|
4635
|
** and returns a hash of their results. |
|
4636
|
** |
|
4637
|
** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm |
|
4638
|
** is used. If SIZE is included it must be one of the integers 224, 256, |
|
4639
|
** 384, or 512, to determine SHA3 hash variant that is computed. |
|
4640
|
** |
|
4641
|
** Because the sha3_agg() and sha3_query() functions compute a hash over |
|
4642
|
** multiple values, the values are encode to use include type information. |
|
4643
|
** |
|
4644
|
** In sha3_agg(), the sequence of bytes that gets hashed for each input |
|
4645
|
** Y depends on the datatype of Y: |
|
4646
|
** |
|
4647
|
** typeof(Y)='null' A single "N" is hashed. (One byte) |
|
4648
|
** |
|
4649
|
** typeof(Y)='integer' The data hash is the character "I" followed |
|
4650
|
** by an 8-byte big-endian binary of the |
|
4651
|
** 64-bit signed integer. (Nine bytes total.) |
|
4652
|
** |
|
4653
|
** typeof(Y)='real' The character "F" followed by an 8-byte |
|
4654
|
** big-ending binary of the double. (Nine |
|
4655
|
** bytes total.) |
|
4656
|
** |
|
4657
|
** typeof(Y)='text' The hash is over prefix "Tnnn:" followed |
|
4658
|
** by the UTF8 encoding of the text. The "nnn" |
|
4659
|
** in the prefix is the minimum-length decimal |
|
4660
|
** representation of the octet_length of the text. |
|
4661
|
** Notice the ":" at the end of the prefix, which |
|
4662
|
** is needed to separate the prefix from the |
|
4663
|
** content in cases where the content starts |
|
4664
|
** with a digit. |
|
4665
|
** |
|
4666
|
** typeof(Y)='blob' The hash is taken over prefix "Bnnn:" followed |
|
4667
|
** by the binary content of the blob. The "nnn" |
|
4668
|
** in the prefix is the minimum-length decimal |
|
4669
|
** representation of the byte-length of the blob. |
|
4670
|
** |
|
4671
|
** According to the rules above, all of the following SELECT statements |
|
4672
|
** should return TRUE: |
|
4673
|
** |
|
4674
|
** SELECT sha3(1) = sha3('1'); |
|
4675
|
** |
|
4676
|
** SELECT sha3('hello') = sha3(x'68656c6c6f'); |
|
4677
|
** |
|
4678
|
** WITH a(x) AS (VALUES('xyzzy')) |
|
4679
|
** SELECT sha3_agg(x) = sha3('T5:xyzzy') FROM a; |
|
4680
|
** |
|
4681
|
** WITH a(x) AS (VALUES(x'010203')) |
|
4682
|
** SELECT sha3_agg(x) = sha3(x'42333a010203') FROM a; |
|
4683
|
** |
|
4684
|
** WITH a(x) AS (VALUES(0x123456)) |
|
4685
|
** SELECT sha3_agg(x) = sha3(x'490000000000123456') FROM a; |
|
4686
|
** |
|
4687
|
** WITH a(x) AS (VALUES(100.015625)) |
|
4688
|
** SELECT sha3_agg(x) = sha3(x'464059010000000000') FROM a; |
|
4689
|
** |
|
4690
|
** WITH a(x) AS (VALUES(NULL)) |
|
4691
|
** SELECT sha3_agg(x) = sha3('N') FROM a; |
|
4692
|
** |
|
4693
|
** |
|
4694
|
** In sha3_query(), individual column values are encoded as with |
|
4695
|
** sha3_agg(), but with the addition that a single "R" character is |
|
4696
|
** inserted at the start of each row. |
|
4697
|
** |
|
4698
|
** Note that sha3_agg() hashes rows for which Y is NULL. Add a FILTER |
|
4699
|
** clause if NULL rows should be excluded: |
|
4700
|
** |
|
4701
|
** SELECT sha3_agg(x ORDER BY rowid) FILTER(WHERE x NOT NULL) FROM t1; |
|
4702
|
*/ |
|
4703
|
/* #include "sqlite3ext.h" */ |
|
4704
|
SQLITE_EXTENSION_INIT1 |
|
4705
|
#include <assert.h> |
|
4706
|
#include <string.h> |
|
4707
|
#include <stdarg.h> |
|
4708
|
|
|
4709
|
#ifndef SQLITE_AMALGAMATION |
|
4710
|
/* typedef sqlite3_uint64 u64; */ |
|
4711
|
#endif /* SQLITE_AMALGAMATION */ |
|
4712
|
|
|
4713
|
/****************************************************************************** |
|
4714
|
** The Hash Engine |
|
4715
|
*/ |
|
4716
|
/* |
|
4717
|
** Macros to determine whether the machine is big or little endian, |
|
4718
|
** and whether or not that determination is run-time or compile-time. |
|
4719
|
** |
|
4720
|
** For best performance, an attempt is made to guess at the byte-order |
|
4721
|
** using C-preprocessor macros. If that is unsuccessful, or if |
|
4722
|
** -DSHA3_BYTEORDER=0 is set, then byte-order is determined |
|
4723
|
** at run-time. |
|
4724
|
*/ |
|
4725
|
#ifndef SHA3_BYTEORDER |
|
4726
|
# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ |
|
4727
|
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ |
|
4728
|
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ |
|
4729
|
defined(__arm__) |
|
4730
|
# define SHA3_BYTEORDER 1234 |
|
4731
|
# elif defined(sparc) || defined(__ppc__) |
|
4732
|
# define SHA3_BYTEORDER 4321 |
|
4733
|
# else |
|
4734
|
# define SHA3_BYTEORDER 0 |
|
4735
|
# endif |
|
4736
|
#endif |
|
4737
|
|
|
4738
|
|
|
4739
|
/* |
|
4740
|
** State structure for a SHA3 hash in progress |
|
4741
|
*/ |
|
4742
|
typedef struct SHA3Context SHA3Context; |
|
4743
|
struct SHA3Context { |
|
4744
|
union { |
|
4745
|
u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ |
|
4746
|
unsigned char x[1600]; /* ... or 1600 bytes */ |
|
4747
|
} u; |
|
4748
|
unsigned nRate; /* Bytes of input accepted per Keccak iteration */ |
|
4749
|
unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ |
|
4750
|
unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ |
|
4751
|
unsigned iSize; /* 224, 256, 358, or 512 */ |
|
4752
|
}; |
|
4753
|
|
|
4754
|
/* |
|
4755
|
** A single step of the Keccak mixing function for a 1600-bit state |
|
4756
|
*/ |
|
4757
|
static void KeccakF1600Step(SHA3Context *p){ |
|
4758
|
int i; |
|
4759
|
u64 b0, b1, b2, b3, b4; |
|
4760
|
u64 c0, c1, c2, c3, c4; |
|
4761
|
u64 d0, d1, d2, d3, d4; |
|
4762
|
static const u64 RC[] = { |
|
4763
|
0x0000000000000001ULL, 0x0000000000008082ULL, |
|
4764
|
0x800000000000808aULL, 0x8000000080008000ULL, |
|
4765
|
0x000000000000808bULL, 0x0000000080000001ULL, |
|
4766
|
0x8000000080008081ULL, 0x8000000000008009ULL, |
|
4767
|
0x000000000000008aULL, 0x0000000000000088ULL, |
|
4768
|
0x0000000080008009ULL, 0x000000008000000aULL, |
|
4769
|
0x000000008000808bULL, 0x800000000000008bULL, |
|
4770
|
0x8000000000008089ULL, 0x8000000000008003ULL, |
|
4771
|
0x8000000000008002ULL, 0x8000000000000080ULL, |
|
4772
|
0x000000000000800aULL, 0x800000008000000aULL, |
|
4773
|
0x8000000080008081ULL, 0x8000000000008080ULL, |
|
4774
|
0x0000000080000001ULL, 0x8000000080008008ULL |
|
4775
|
}; |
|
4776
|
# define a00 (p->u.s[0]) |
|
4777
|
# define a01 (p->u.s[1]) |
|
4778
|
# define a02 (p->u.s[2]) |
|
4779
|
# define a03 (p->u.s[3]) |
|
4780
|
# define a04 (p->u.s[4]) |
|
4781
|
# define a10 (p->u.s[5]) |
|
4782
|
# define a11 (p->u.s[6]) |
|
4783
|
# define a12 (p->u.s[7]) |
|
4784
|
# define a13 (p->u.s[8]) |
|
4785
|
# define a14 (p->u.s[9]) |
|
4786
|
# define a20 (p->u.s[10]) |
|
4787
|
# define a21 (p->u.s[11]) |
|
4788
|
# define a22 (p->u.s[12]) |
|
4789
|
# define a23 (p->u.s[13]) |
|
4790
|
# define a24 (p->u.s[14]) |
|
4791
|
# define a30 (p->u.s[15]) |
|
4792
|
# define a31 (p->u.s[16]) |
|
4793
|
# define a32 (p->u.s[17]) |
|
4794
|
# define a33 (p->u.s[18]) |
|
4795
|
# define a34 (p->u.s[19]) |
|
4796
|
# define a40 (p->u.s[20]) |
|
4797
|
# define a41 (p->u.s[21]) |
|
4798
|
# define a42 (p->u.s[22]) |
|
4799
|
# define a43 (p->u.s[23]) |
|
4800
|
# define a44 (p->u.s[24]) |
|
4801
|
# define ROL64(a,x) ((a<<x)|(a>>(64-x))) |
|
4802
|
|
|
4803
|
for(i=0; i<24; i+=4){ |
|
4804
|
c0 = a00^a10^a20^a30^a40; |
|
4805
|
c1 = a01^a11^a21^a31^a41; |
|
4806
|
c2 = a02^a12^a22^a32^a42; |
|
4807
|
c3 = a03^a13^a23^a33^a43; |
|
4808
|
c4 = a04^a14^a24^a34^a44; |
|
4809
|
d0 = c4^ROL64(c1, 1); |
|
4810
|
d1 = c0^ROL64(c2, 1); |
|
4811
|
d2 = c1^ROL64(c3, 1); |
|
4812
|
d3 = c2^ROL64(c4, 1); |
|
4813
|
d4 = c3^ROL64(c0, 1); |
|
4814
|
|
|
4815
|
b0 = (a00^d0); |
|
4816
|
b1 = ROL64((a11^d1), 44); |
|
4817
|
b2 = ROL64((a22^d2), 43); |
|
4818
|
b3 = ROL64((a33^d3), 21); |
|
4819
|
b4 = ROL64((a44^d4), 14); |
|
4820
|
a00 = b0 ^((~b1)& b2 ); |
|
4821
|
a00 ^= RC[i]; |
|
4822
|
a11 = b1 ^((~b2)& b3 ); |
|
4823
|
a22 = b2 ^((~b3)& b4 ); |
|
4824
|
a33 = b3 ^((~b4)& b0 ); |
|
4825
|
a44 = b4 ^((~b0)& b1 ); |
|
4826
|
|
|
4827
|
b2 = ROL64((a20^d0), 3); |
|
4828
|
b3 = ROL64((a31^d1), 45); |
|
4829
|
b4 = ROL64((a42^d2), 61); |
|
4830
|
b0 = ROL64((a03^d3), 28); |
|
4831
|
b1 = ROL64((a14^d4), 20); |
|
4832
|
a20 = b0 ^((~b1)& b2 ); |
|
4833
|
a31 = b1 ^((~b2)& b3 ); |
|
4834
|
a42 = b2 ^((~b3)& b4 ); |
|
4835
|
a03 = b3 ^((~b4)& b0 ); |
|
4836
|
a14 = b4 ^((~b0)& b1 ); |
|
4837
|
|
|
4838
|
b4 = ROL64((a40^d0), 18); |
|
4839
|
b0 = ROL64((a01^d1), 1); |
|
4840
|
b1 = ROL64((a12^d2), 6); |
|
4841
|
b2 = ROL64((a23^d3), 25); |
|
4842
|
b3 = ROL64((a34^d4), 8); |
|
4843
|
a40 = b0 ^((~b1)& b2 ); |
|
4844
|
a01 = b1 ^((~b2)& b3 ); |
|
4845
|
a12 = b2 ^((~b3)& b4 ); |
|
4846
|
a23 = b3 ^((~b4)& b0 ); |
|
4847
|
a34 = b4 ^((~b0)& b1 ); |
|
4848
|
|
|
4849
|
b1 = ROL64((a10^d0), 36); |
|
4850
|
b2 = ROL64((a21^d1), 10); |
|
4851
|
b3 = ROL64((a32^d2), 15); |
|
4852
|
b4 = ROL64((a43^d3), 56); |
|
4853
|
b0 = ROL64((a04^d4), 27); |
|
4854
|
a10 = b0 ^((~b1)& b2 ); |
|
4855
|
a21 = b1 ^((~b2)& b3 ); |
|
4856
|
a32 = b2 ^((~b3)& b4 ); |
|
4857
|
a43 = b3 ^((~b4)& b0 ); |
|
4858
|
a04 = b4 ^((~b0)& b1 ); |
|
4859
|
|
|
4860
|
b3 = ROL64((a30^d0), 41); |
|
4861
|
b4 = ROL64((a41^d1), 2); |
|
4862
|
b0 = ROL64((a02^d2), 62); |
|
4863
|
b1 = ROL64((a13^d3), 55); |
|
4864
|
b2 = ROL64((a24^d4), 39); |
|
4865
|
a30 = b0 ^((~b1)& b2 ); |
|
4866
|
a41 = b1 ^((~b2)& b3 ); |
|
4867
|
a02 = b2 ^((~b3)& b4 ); |
|
4868
|
a13 = b3 ^((~b4)& b0 ); |
|
4869
|
a24 = b4 ^((~b0)& b1 ); |
|
4870
|
|
|
4871
|
c0 = a00^a20^a40^a10^a30; |
|
4872
|
c1 = a11^a31^a01^a21^a41; |
|
4873
|
c2 = a22^a42^a12^a32^a02; |
|
4874
|
c3 = a33^a03^a23^a43^a13; |
|
4875
|
c4 = a44^a14^a34^a04^a24; |
|
4876
|
d0 = c4^ROL64(c1, 1); |
|
4877
|
d1 = c0^ROL64(c2, 1); |
|
4878
|
d2 = c1^ROL64(c3, 1); |
|
4879
|
d3 = c2^ROL64(c4, 1); |
|
4880
|
d4 = c3^ROL64(c0, 1); |
|
4881
|
|
|
4882
|
b0 = (a00^d0); |
|
4883
|
b1 = ROL64((a31^d1), 44); |
|
4884
|
b2 = ROL64((a12^d2), 43); |
|
4885
|
b3 = ROL64((a43^d3), 21); |
|
4886
|
b4 = ROL64((a24^d4), 14); |
|
4887
|
a00 = b0 ^((~b1)& b2 ); |
|
4888
|
a00 ^= RC[i+1]; |
|
4889
|
a31 = b1 ^((~b2)& b3 ); |
|
4890
|
a12 = b2 ^((~b3)& b4 ); |
|
4891
|
a43 = b3 ^((~b4)& b0 ); |
|
4892
|
a24 = b4 ^((~b0)& b1 ); |
|
4893
|
|
|
4894
|
b2 = ROL64((a40^d0), 3); |
|
4895
|
b3 = ROL64((a21^d1), 45); |
|
4896
|
b4 = ROL64((a02^d2), 61); |
|
4897
|
b0 = ROL64((a33^d3), 28); |
|
4898
|
b1 = ROL64((a14^d4), 20); |
|
4899
|
a40 = b0 ^((~b1)& b2 ); |
|
4900
|
a21 = b1 ^((~b2)& b3 ); |
|
4901
|
a02 = b2 ^((~b3)& b4 ); |
|
4902
|
a33 = b3 ^((~b4)& b0 ); |
|
4903
|
a14 = b4 ^((~b0)& b1 ); |
|
4904
|
|
|
4905
|
b4 = ROL64((a30^d0), 18); |
|
4906
|
b0 = ROL64((a11^d1), 1); |
|
4907
|
b1 = ROL64((a42^d2), 6); |
|
4908
|
b2 = ROL64((a23^d3), 25); |
|
4909
|
b3 = ROL64((a04^d4), 8); |
|
4910
|
a30 = b0 ^((~b1)& b2 ); |
|
4911
|
a11 = b1 ^((~b2)& b3 ); |
|
4912
|
a42 = b2 ^((~b3)& b4 ); |
|
4913
|
a23 = b3 ^((~b4)& b0 ); |
|
4914
|
a04 = b4 ^((~b0)& b1 ); |
|
4915
|
|
|
4916
|
b1 = ROL64((a20^d0), 36); |
|
4917
|
b2 = ROL64((a01^d1), 10); |
|
4918
|
b3 = ROL64((a32^d2), 15); |
|
4919
|
b4 = ROL64((a13^d3), 56); |
|
4920
|
b0 = ROL64((a44^d4), 27); |
|
4921
|
a20 = b0 ^((~b1)& b2 ); |
|
4922
|
a01 = b1 ^((~b2)& b3 ); |
|
4923
|
a32 = b2 ^((~b3)& b4 ); |
|
4924
|
a13 = b3 ^((~b4)& b0 ); |
|
4925
|
a44 = b4 ^((~b0)& b1 ); |
|
4926
|
|
|
4927
|
b3 = ROL64((a10^d0), 41); |
|
4928
|
b4 = ROL64((a41^d1), 2); |
|
4929
|
b0 = ROL64((a22^d2), 62); |
|
4930
|
b1 = ROL64((a03^d3), 55); |
|
4931
|
b2 = ROL64((a34^d4), 39); |
|
4932
|
a10 = b0 ^((~b1)& b2 ); |
|
4933
|
a41 = b1 ^((~b2)& b3 ); |
|
4934
|
a22 = b2 ^((~b3)& b4 ); |
|
4935
|
a03 = b3 ^((~b4)& b0 ); |
|
4936
|
a34 = b4 ^((~b0)& b1 ); |
|
4937
|
|
|
4938
|
c0 = a00^a40^a30^a20^a10; |
|
4939
|
c1 = a31^a21^a11^a01^a41; |
|
4940
|
c2 = a12^a02^a42^a32^a22; |
|
4941
|
c3 = a43^a33^a23^a13^a03; |
|
4942
|
c4 = a24^a14^a04^a44^a34; |
|
4943
|
d0 = c4^ROL64(c1, 1); |
|
4944
|
d1 = c0^ROL64(c2, 1); |
|
4945
|
d2 = c1^ROL64(c3, 1); |
|
4946
|
d3 = c2^ROL64(c4, 1); |
|
4947
|
d4 = c3^ROL64(c0, 1); |
|
4948
|
|
|
4949
|
b0 = (a00^d0); |
|
4950
|
b1 = ROL64((a21^d1), 44); |
|
4951
|
b2 = ROL64((a42^d2), 43); |
|
4952
|
b3 = ROL64((a13^d3), 21); |
|
4953
|
b4 = ROL64((a34^d4), 14); |
|
4954
|
a00 = b0 ^((~b1)& b2 ); |
|
4955
|
a00 ^= RC[i+2]; |
|
4956
|
a21 = b1 ^((~b2)& b3 ); |
|
4957
|
a42 = b2 ^((~b3)& b4 ); |
|
4958
|
a13 = b3 ^((~b4)& b0 ); |
|
4959
|
a34 = b4 ^((~b0)& b1 ); |
|
4960
|
|
|
4961
|
b2 = ROL64((a30^d0), 3); |
|
4962
|
b3 = ROL64((a01^d1), 45); |
|
4963
|
b4 = ROL64((a22^d2), 61); |
|
4964
|
b0 = ROL64((a43^d3), 28); |
|
4965
|
b1 = ROL64((a14^d4), 20); |
|
4966
|
a30 = b0 ^((~b1)& b2 ); |
|
4967
|
a01 = b1 ^((~b2)& b3 ); |
|
4968
|
a22 = b2 ^((~b3)& b4 ); |
|
4969
|
a43 = b3 ^((~b4)& b0 ); |
|
4970
|
a14 = b4 ^((~b0)& b1 ); |
|
4971
|
|
|
4972
|
b4 = ROL64((a10^d0), 18); |
|
4973
|
b0 = ROL64((a31^d1), 1); |
|
4974
|
b1 = ROL64((a02^d2), 6); |
|
4975
|
b2 = ROL64((a23^d3), 25); |
|
4976
|
b3 = ROL64((a44^d4), 8); |
|
4977
|
a10 = b0 ^((~b1)& b2 ); |
|
4978
|
a31 = b1 ^((~b2)& b3 ); |
|
4979
|
a02 = b2 ^((~b3)& b4 ); |
|
4980
|
a23 = b3 ^((~b4)& b0 ); |
|
4981
|
a44 = b4 ^((~b0)& b1 ); |
|
4982
|
|
|
4983
|
b1 = ROL64((a40^d0), 36); |
|
4984
|
b2 = ROL64((a11^d1), 10); |
|
4985
|
b3 = ROL64((a32^d2), 15); |
|
4986
|
b4 = ROL64((a03^d3), 56); |
|
4987
|
b0 = ROL64((a24^d4), 27); |
|
4988
|
a40 = b0 ^((~b1)& b2 ); |
|
4989
|
a11 = b1 ^((~b2)& b3 ); |
|
4990
|
a32 = b2 ^((~b3)& b4 ); |
|
4991
|
a03 = b3 ^((~b4)& b0 ); |
|
4992
|
a24 = b4 ^((~b0)& b1 ); |
|
4993
|
|
|
4994
|
b3 = ROL64((a20^d0), 41); |
|
4995
|
b4 = ROL64((a41^d1), 2); |
|
4996
|
b0 = ROL64((a12^d2), 62); |
|
4997
|
b1 = ROL64((a33^d3), 55); |
|
4998
|
b2 = ROL64((a04^d4), 39); |
|
4999
|
a20 = b0 ^((~b1)& b2 ); |
|
5000
|
a41 = b1 ^((~b2)& b3 ); |
|
5001
|
a12 = b2 ^((~b3)& b4 ); |
|
5002
|
a33 = b3 ^((~b4)& b0 ); |
|
5003
|
a04 = b4 ^((~b0)& b1 ); |
|
5004
|
|
|
5005
|
c0 = a00^a30^a10^a40^a20; |
|
5006
|
c1 = a21^a01^a31^a11^a41; |
|
5007
|
c2 = a42^a22^a02^a32^a12; |
|
5008
|
c3 = a13^a43^a23^a03^a33; |
|
5009
|
c4 = a34^a14^a44^a24^a04; |
|
5010
|
d0 = c4^ROL64(c1, 1); |
|
5011
|
d1 = c0^ROL64(c2, 1); |
|
5012
|
d2 = c1^ROL64(c3, 1); |
|
5013
|
d3 = c2^ROL64(c4, 1); |
|
5014
|
d4 = c3^ROL64(c0, 1); |
|
5015
|
|
|
5016
|
b0 = (a00^d0); |
|
5017
|
b1 = ROL64((a01^d1), 44); |
|
5018
|
b2 = ROL64((a02^d2), 43); |
|
5019
|
b3 = ROL64((a03^d3), 21); |
|
5020
|
b4 = ROL64((a04^d4), 14); |
|
5021
|
a00 = b0 ^((~b1)& b2 ); |
|
5022
|
a00 ^= RC[i+3]; |
|
5023
|
a01 = b1 ^((~b2)& b3 ); |
|
5024
|
a02 = b2 ^((~b3)& b4 ); |
|
5025
|
a03 = b3 ^((~b4)& b0 ); |
|
5026
|
a04 = b4 ^((~b0)& b1 ); |
|
5027
|
|
|
5028
|
b2 = ROL64((a10^d0), 3); |
|
5029
|
b3 = ROL64((a11^d1), 45); |
|
5030
|
b4 = ROL64((a12^d2), 61); |
|
5031
|
b0 = ROL64((a13^d3), 28); |
|
5032
|
b1 = ROL64((a14^d4), 20); |
|
5033
|
a10 = b0 ^((~b1)& b2 ); |
|
5034
|
a11 = b1 ^((~b2)& b3 ); |
|
5035
|
a12 = b2 ^((~b3)& b4 ); |
|
5036
|
a13 = b3 ^((~b4)& b0 ); |
|
5037
|
a14 = b4 ^((~b0)& b1 ); |
|
5038
|
|
|
5039
|
b4 = ROL64((a20^d0), 18); |
|
5040
|
b0 = ROL64((a21^d1), 1); |
|
5041
|
b1 = ROL64((a22^d2), 6); |
|
5042
|
b2 = ROL64((a23^d3), 25); |
|
5043
|
b3 = ROL64((a24^d4), 8); |
|
5044
|
a20 = b0 ^((~b1)& b2 ); |
|
5045
|
a21 = b1 ^((~b2)& b3 ); |
|
5046
|
a22 = b2 ^((~b3)& b4 ); |
|
5047
|
a23 = b3 ^((~b4)& b0 ); |
|
5048
|
a24 = b4 ^((~b0)& b1 ); |
|
5049
|
|
|
5050
|
b1 = ROL64((a30^d0), 36); |
|
5051
|
b2 = ROL64((a31^d1), 10); |
|
5052
|
b3 = ROL64((a32^d2), 15); |
|
5053
|
b4 = ROL64((a33^d3), 56); |
|
5054
|
b0 = ROL64((a34^d4), 27); |
|
5055
|
a30 = b0 ^((~b1)& b2 ); |
|
5056
|
a31 = b1 ^((~b2)& b3 ); |
|
5057
|
a32 = b2 ^((~b3)& b4 ); |
|
5058
|
a33 = b3 ^((~b4)& b0 ); |
|
5059
|
a34 = b4 ^((~b0)& b1 ); |
|
5060
|
|
|
5061
|
b3 = ROL64((a40^d0), 41); |
|
5062
|
b4 = ROL64((a41^d1), 2); |
|
5063
|
b0 = ROL64((a42^d2), 62); |
|
5064
|
b1 = ROL64((a43^d3), 55); |
|
5065
|
b2 = ROL64((a44^d4), 39); |
|
5066
|
a40 = b0 ^((~b1)& b2 ); |
|
5067
|
a41 = b1 ^((~b2)& b3 ); |
|
5068
|
a42 = b2 ^((~b3)& b4 ); |
|
5069
|
a43 = b3 ^((~b4)& b0 ); |
|
5070
|
a44 = b4 ^((~b0)& b1 ); |
|
5071
|
} |
|
5072
|
} |
|
5073
|
|
|
5074
|
/* |
|
5075
|
** Initialize a new hash. iSize determines the size of the hash |
|
5076
|
** in bits and should be one of 224, 256, 384, or 512. Or iSize |
|
5077
|
** can be zero to use the default hash size of 256 bits. |
|
5078
|
*/ |
|
5079
|
static void SHA3Init(SHA3Context *p, int iSize){ |
|
5080
|
memset(p, 0, sizeof(*p)); |
|
5081
|
p->iSize = iSize; |
|
5082
|
if( iSize>=128 && iSize<=512 ){ |
|
5083
|
p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; |
|
5084
|
}else{ |
|
5085
|
p->nRate = (1600 - 2*256)/8; |
|
5086
|
} |
|
5087
|
#if SHA3_BYTEORDER==1234 |
|
5088
|
/* Known to be little-endian at compile-time. No-op */ |
|
5089
|
#elif SHA3_BYTEORDER==4321 |
|
5090
|
p->ixMask = 7; /* Big-endian */ |
|
5091
|
#else |
|
5092
|
{ |
|
5093
|
static unsigned int one = 1; |
|
5094
|
if( 1==*(unsigned char*)&one ){ |
|
5095
|
/* Little endian. No byte swapping. */ |
|
5096
|
p->ixMask = 0; |
|
5097
|
}else{ |
|
5098
|
/* Big endian. Byte swap. */ |
|
5099
|
p->ixMask = 7; |
|
5100
|
} |
|
5101
|
} |
|
5102
|
#endif |
|
5103
|
} |
|
5104
|
|
|
5105
|
/* |
|
5106
|
** Make consecutive calls to the SHA3Update function to add new content |
|
5107
|
** to the hash |
|
5108
|
*/ |
|
5109
|
static void SHA3Update( |
|
5110
|
SHA3Context *p, |
|
5111
|
const unsigned char *aData, |
|
5112
|
unsigned int nData |
|
5113
|
){ |
|
5114
|
unsigned int i = 0; |
|
5115
|
if( aData==0 ) return; |
|
5116
|
#if SHA3_BYTEORDER==1234 |
|
5117
|
if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ |
|
5118
|
for(; i+7<nData; i+=8){ |
|
5119
|
p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; |
|
5120
|
p->nLoaded += 8; |
|
5121
|
if( p->nLoaded>=p->nRate ){ |
|
5122
|
KeccakF1600Step(p); |
|
5123
|
p->nLoaded = 0; |
|
5124
|
} |
|
5125
|
} |
|
5126
|
} |
|
5127
|
#endif |
|
5128
|
for(; i<nData; i++){ |
|
5129
|
#if SHA3_BYTEORDER==1234 |
|
5130
|
p->u.x[p->nLoaded] ^= aData[i]; |
|
5131
|
#elif SHA3_BYTEORDER==4321 |
|
5132
|
p->u.x[p->nLoaded^0x07] ^= aData[i]; |
|
5133
|
#else |
|
5134
|
p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; |
|
5135
|
#endif |
|
5136
|
p->nLoaded++; |
|
5137
|
if( p->nLoaded==p->nRate ){ |
|
5138
|
KeccakF1600Step(p); |
|
5139
|
p->nLoaded = 0; |
|
5140
|
} |
|
5141
|
} |
|
5142
|
} |
|
5143
|
|
|
5144
|
/* |
|
5145
|
** After all content has been added, invoke SHA3Final() to compute |
|
5146
|
** the final hash. The function returns a pointer to the binary |
|
5147
|
** hash value. |
|
5148
|
*/ |
|
5149
|
static unsigned char *SHA3Final(SHA3Context *p){ |
|
5150
|
unsigned int i; |
|
5151
|
if( p->nLoaded==p->nRate-1 ){ |
|
5152
|
const unsigned char c1 = 0x86; |
|
5153
|
SHA3Update(p, &c1, 1); |
|
5154
|
}else{ |
|
5155
|
const unsigned char c2 = 0x06; |
|
5156
|
const unsigned char c3 = 0x80; |
|
5157
|
SHA3Update(p, &c2, 1); |
|
5158
|
p->nLoaded = p->nRate - 1; |
|
5159
|
SHA3Update(p, &c3, 1); |
|
5160
|
} |
|
5161
|
for(i=0; i<p->nRate; i++){ |
|
5162
|
p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; |
|
5163
|
} |
|
5164
|
return &p->u.x[p->nRate]; |
|
5165
|
} |
|
5166
|
/* End of the hashing logic |
|
5167
|
*****************************************************************************/ |
|
5168
|
|
|
5169
|
/* |
|
5170
|
** Implementation of the sha3(X,SIZE) function. |
|
5171
|
** |
|
5172
|
** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default |
|
5173
|
** size is 256. If X is a BLOB, it is hashed as is. |
|
5174
|
** For all other non-NULL types of input, X is converted into a UTF-8 string |
|
5175
|
** and the string is hashed without the trailing 0x00 terminator. The hash |
|
5176
|
** of a NULL value is NULL. |
|
5177
|
*/ |
|
5178
|
static void sha3Func( |
|
5179
|
sqlite3_context *context, |
|
5180
|
int argc, |
|
5181
|
sqlite3_value **argv |
|
5182
|
){ |
|
5183
|
SHA3Context cx; |
|
5184
|
int eType = sqlite3_value_type(argv[0]); |
|
5185
|
int nByte = sqlite3_value_bytes(argv[0]); |
|
5186
|
int iSize; |
|
5187
|
if( argc==1 ){ |
|
5188
|
iSize = 256; |
|
5189
|
}else{ |
|
5190
|
iSize = sqlite3_value_int(argv[1]); |
|
5191
|
if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ |
|
5192
|
sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " |
|
5193
|
"384 512", -1); |
|
5194
|
return; |
|
5195
|
} |
|
5196
|
} |
|
5197
|
if( eType==SQLITE_NULL ) return; |
|
5198
|
SHA3Init(&cx, iSize); |
|
5199
|
if( eType==SQLITE_BLOB ){ |
|
5200
|
SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte); |
|
5201
|
}else{ |
|
5202
|
SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte); |
|
5203
|
} |
|
5204
|
sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); |
|
5205
|
} |
|
5206
|
|
|
5207
|
/* Compute a string using sqlite3_vsnprintf() with a maximum length |
|
5208
|
** of 50 bytes and add it to the hash. |
|
5209
|
*/ |
|
5210
|
static void sha3_step_vformat( |
|
5211
|
SHA3Context *p, /* Add content to this context */ |
|
5212
|
const char *zFormat, |
|
5213
|
... |
|
5214
|
){ |
|
5215
|
va_list ap; |
|
5216
|
int n; |
|
5217
|
char zBuf[50]; |
|
5218
|
va_start(ap, zFormat); |
|
5219
|
sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); |
|
5220
|
va_end(ap); |
|
5221
|
n = (int)strlen(zBuf); |
|
5222
|
SHA3Update(p, (unsigned char*)zBuf, n); |
|
5223
|
} |
|
5224
|
|
|
5225
|
/* |
|
5226
|
** Update a SHA3Context using a single sqlite3_value. |
|
5227
|
*/ |
|
5228
|
static void sha3UpdateFromValue(SHA3Context *p, sqlite3_value *pVal){ |
|
5229
|
switch( sqlite3_value_type(pVal) ){ |
|
5230
|
case SQLITE_NULL: { |
|
5231
|
SHA3Update(p, (const unsigned char*)"N",1); |
|
5232
|
break; |
|
5233
|
} |
|
5234
|
case SQLITE_INTEGER: { |
|
5235
|
sqlite3_uint64 u; |
|
5236
|
int j; |
|
5237
|
unsigned char x[9]; |
|
5238
|
sqlite3_int64 v = sqlite3_value_int64(pVal); |
|
5239
|
memcpy(&u, &v, 8); |
|
5240
|
for(j=8; j>=1; j--){ |
|
5241
|
x[j] = u & 0xff; |
|
5242
|
u >>= 8; |
|
5243
|
} |
|
5244
|
x[0] = 'I'; |
|
5245
|
SHA3Update(p, x, 9); |
|
5246
|
break; |
|
5247
|
} |
|
5248
|
case SQLITE_FLOAT: { |
|
5249
|
sqlite3_uint64 u; |
|
5250
|
int j; |
|
5251
|
unsigned char x[9]; |
|
5252
|
double r = sqlite3_value_double(pVal); |
|
5253
|
memcpy(&u, &r, 8); |
|
5254
|
for(j=8; j>=1; j--){ |
|
5255
|
x[j] = u & 0xff; |
|
5256
|
u >>= 8; |
|
5257
|
} |
|
5258
|
x[0] = 'F'; |
|
5259
|
SHA3Update(p,x,9); |
|
5260
|
break; |
|
5261
|
} |
|
5262
|
case SQLITE_TEXT: { |
|
5263
|
int n2 = sqlite3_value_bytes(pVal); |
|
5264
|
const unsigned char *z2 = sqlite3_value_text(pVal); |
|
5265
|
sha3_step_vformat(p,"T%d:",n2); |
|
5266
|
SHA3Update(p, z2, n2); |
|
5267
|
break; |
|
5268
|
} |
|
5269
|
case SQLITE_BLOB: { |
|
5270
|
int n2 = sqlite3_value_bytes(pVal); |
|
5271
|
const unsigned char *z2 = sqlite3_value_blob(pVal); |
|
5272
|
sha3_step_vformat(p,"B%d:",n2); |
|
5273
|
SHA3Update(p, z2, n2); |
|
5274
|
break; |
|
5275
|
} |
|
5276
|
} |
|
5277
|
} |
|
5278
|
|
|
5279
|
/* |
|
5280
|
** Implementation of the sha3_query(SQL,SIZE) function. |
|
5281
|
** |
|
5282
|
** This function compiles and runs the SQL statement(s) given in the |
|
5283
|
** argument. The results are hashed using a SIZE-bit SHA3. The default |
|
5284
|
** size is 256. |
|
5285
|
** |
|
5286
|
** The format of the byte stream that is hashed is summarized as follows: |
|
5287
|
** |
|
5288
|
** S<n>:<sql> |
|
5289
|
** R |
|
5290
|
** N |
|
5291
|
** I<int> |
|
5292
|
** F<ieee-float> |
|
5293
|
** B<size>:<bytes> |
|
5294
|
** T<size>:<text> |
|
5295
|
** |
|
5296
|
** <sql> is the original SQL text for each statement run and <n> is |
|
5297
|
** the size of that text. The SQL text is UTF-8. A single R character |
|
5298
|
** occurs before the start of each row. N means a NULL value. |
|
5299
|
** I mean an 8-byte little-endian integer <int>. F is a floating point |
|
5300
|
** number with an 8-byte little-endian IEEE floating point value <ieee-float>. |
|
5301
|
** B means blobs of <size> bytes. T means text rendered as <size> |
|
5302
|
** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII |
|
5303
|
** text integers. |
|
5304
|
** |
|
5305
|
** For each SQL statement in the X input, there is one S segment. Each |
|
5306
|
** S segment is followed by zero or more R segments, one for each row in the |
|
5307
|
** result set. After each R, there are one or more N, I, F, B, or T segments, |
|
5308
|
** one for each column in the result set. Segments are concatentated directly |
|
5309
|
** with no delimiters of any kind. |
|
5310
|
*/ |
|
5311
|
static void sha3QueryFunc( |
|
5312
|
sqlite3_context *context, |
|
5313
|
int argc, |
|
5314
|
sqlite3_value **argv |
|
5315
|
){ |
|
5316
|
sqlite3 *db = sqlite3_context_db_handle(context); |
|
5317
|
const char *zSql = (const char*)sqlite3_value_text(argv[0]); |
|
5318
|
sqlite3_stmt *pStmt = 0; |
|
5319
|
int nCol; /* Number of columns in the result set */ |
|
5320
|
int i; /* Loop counter */ |
|
5321
|
int rc; |
|
5322
|
int n; |
|
5323
|
const char *z; |
|
5324
|
SHA3Context cx; |
|
5325
|
int iSize; |
|
5326
|
int isRecursive = 0; |
|
5327
|
int *pIsRecursive; |
|
5328
|
|
|
5329
|
if( argc==1 ){ |
|
5330
|
iSize = 256; |
|
5331
|
}else{ |
|
5332
|
iSize = sqlite3_value_int(argv[1]); |
|
5333
|
if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ |
|
5334
|
sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " |
|
5335
|
"384 512", -1); |
|
5336
|
return; |
|
5337
|
} |
|
5338
|
} |
|
5339
|
if( zSql==0 ) return; |
|
5340
|
SHA3Init(&cx, iSize); |
|
5341
|
pIsRecursive = (int*)sqlite3_get_clientdata(db,"sha3_query()"); |
|
5342
|
if( pIsRecursive ){ |
|
5343
|
*pIsRecursive = 1; |
|
5344
|
return; |
|
5345
|
} |
|
5346
|
while( zSql[0] ){ |
|
5347
|
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); |
|
5348
|
if( rc ){ |
|
5349
|
char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", |
|
5350
|
zSql, sqlite3_errmsg(db)); |
|
5351
|
sqlite3_finalize(pStmt); |
|
5352
|
sqlite3_result_error(context, zMsg, -1); |
|
5353
|
sqlite3_free(zMsg); |
|
5354
|
return; |
|
5355
|
} |
|
5356
|
if( !sqlite3_stmt_readonly(pStmt) ){ |
|
5357
|
char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); |
|
5358
|
sqlite3_finalize(pStmt); |
|
5359
|
sqlite3_result_error(context, zMsg, -1); |
|
5360
|
sqlite3_free(zMsg); |
|
5361
|
return; |
|
5362
|
} |
|
5363
|
nCol = sqlite3_column_count(pStmt); |
|
5364
|
z = sqlite3_sql(pStmt); |
|
5365
|
if( z ){ |
|
5366
|
n = (int)strlen(z); |
|
5367
|
sha3_step_vformat(&cx,"S%d:",n); |
|
5368
|
SHA3Update(&cx,(unsigned char*)z,n); |
|
5369
|
} |
|
5370
|
|
|
5371
|
/* Compute a hash over the result of the query */ |
|
5372
|
sqlite3_set_clientdata(db, "sha3_query()", &isRecursive, 0); |
|
5373
|
while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
|
5374
|
SHA3Update(&cx,(const unsigned char*)"R",1); |
|
5375
|
for(i=0; i<nCol; i++){ |
|
5376
|
sha3UpdateFromValue(&cx, sqlite3_column_value(pStmt,i)); |
|
5377
|
} |
|
5378
|
} |
|
5379
|
sqlite3_finalize(pStmt); |
|
5380
|
sqlite3_set_clientdata(db, "sha3_query()", 0, 0); |
|
5381
|
} |
|
5382
|
if( isRecursive ){ |
|
5383
|
sqlite3_result_error(context, "recursive use of sha3_query()", -1); |
|
5384
|
}else{ |
|
5385
|
sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); |
|
5386
|
} |
|
5387
|
} |
|
5388
|
|
|
5389
|
/* |
|
5390
|
** xStep function for sha3_agg(). |
|
5391
|
*/ |
|
5392
|
static void sha3AggStep( |
|
5393
|
sqlite3_context *context, |
|
5394
|
int argc, |
|
5395
|
sqlite3_value **argv |
|
5396
|
){ |
|
5397
|
SHA3Context *p; |
|
5398
|
p = (SHA3Context*)sqlite3_aggregate_context(context, sizeof(*p)); |
|
5399
|
if( p==0 ) return; |
|
5400
|
if( p->nRate==0 ){ |
|
5401
|
int sz = 256; |
|
5402
|
if( argc==2 ){ |
|
5403
|
sz = sqlite3_value_int(argv[1]); |
|
5404
|
if( sz!=224 && sz!=384 && sz!=512 ){ |
|
5405
|
sz = 256; |
|
5406
|
} |
|
5407
|
} |
|
5408
|
SHA3Init(p, sz); |
|
5409
|
} |
|
5410
|
sha3UpdateFromValue(p, argv[0]); |
|
5411
|
} |
|
5412
|
|
|
5413
|
|
|
5414
|
/* |
|
5415
|
** xFinal function for sha3_agg(). |
|
5416
|
*/ |
|
5417
|
static void sha3AggFinal(sqlite3_context *context){ |
|
5418
|
SHA3Context *p; |
|
5419
|
p = (SHA3Context*)sqlite3_aggregate_context(context, sizeof(*p)); |
|
5420
|
if( p==0 ) return; |
|
5421
|
if( p->iSize ){ |
|
5422
|
sqlite3_result_blob(context, SHA3Final(p), p->iSize/8, SQLITE_TRANSIENT); |
|
5423
|
} |
|
5424
|
} |
|
5425
|
|
|
5426
|
|
|
5427
|
|
|
5428
|
#ifdef _WIN32 |
|
5429
|
|
|
5430
|
#endif |
|
5431
|
int sqlite3_shathree_init( |
|
5432
|
sqlite3 *db, |
|
5433
|
char **pzErrMsg, |
|
5434
|
const sqlite3_api_routines *pApi |
|
5435
|
){ |
|
5436
|
int rc = SQLITE_OK; |
|
5437
|
SQLITE_EXTENSION_INIT2(pApi); |
|
5438
|
(void)pzErrMsg; /* Unused parameter */ |
|
5439
|
rc = sqlite3_create_function(db, "sha3", 1, |
|
5440
|
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, |
|
5441
|
0, sha3Func, 0, 0); |
|
5442
|
if( rc==SQLITE_OK ){ |
|
5443
|
rc = sqlite3_create_function(db, "sha3", 2, |
|
5444
|
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, |
|
5445
|
0, sha3Func, 0, 0); |
|
5446
|
} |
|
5447
|
if( rc==SQLITE_OK ){ |
|
5448
|
rc = sqlite3_create_function(db, "sha3_agg", 1, |
|
5449
|
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, |
|
5450
|
0, 0, sha3AggStep, sha3AggFinal); |
|
5451
|
} |
|
5452
|
if( rc==SQLITE_OK ){ |
|
5453
|
rc = sqlite3_create_function(db, "sha3_agg", 2, |
|
5454
|
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, |
|
5455
|
0, 0, sha3AggStep, sha3AggFinal); |
|
5456
|
} |
|
5457
|
if( rc==SQLITE_OK ){ |
|
5458
|
rc = sqlite3_create_function(db, "sha3_query", 1, |
|
5459
|
SQLITE_UTF8 | SQLITE_DIRECTONLY, |
|
5460
|
0, sha3QueryFunc, 0, 0); |
|
5461
|
} |
|
5462
|
if( rc==SQLITE_OK ){ |
|
5463
|
rc = sqlite3_create_function(db, "sha3_query", 2, |
|
5464
|
SQLITE_UTF8 | SQLITE_DIRECTONLY, |
|
5465
|
0, sha3QueryFunc, 0, 0); |
|
5466
|
} |
|
5467
|
return rc; |
|
5468
|
} |
|
5469
|
|
|
5470
|
/************************* End ext/misc/shathree.c ********************/ |
|
5471
|
/************************* Begin ext/misc/sha1.c ******************/ |
|
5472
|
/* |
|
5473
|
** 2017-01-27 |
|
5474
|
** |
|
5475
|
** The author disclaims copyright to this source code. In place of |
|
5476
|
** a legal notice, here is a blessing: |
|
5477
|
** |
|
5478
|
** May you do good and not evil. |
|
5479
|
** May you find forgiveness for yourself and forgive others. |
|
5480
|
** May you share freely, never taking more than you give. |
|
5481
|
** |
|
5482
|
****************************************************************************** |
|
5483
|
** |
|
5484
|
** This SQLite extension implements functions that compute SHA1 hashes. |
|
5485
|
** Two SQL functions are implemented: |
|
5486
|
** |
|
5487
|
** sha1(X) |
|
5488
|
** sha1_query(Y) |
|
5489
|
** |
|
5490
|
** The sha1(X) function computes the SHA1 hash of the input X, or NULL if |
|
5491
|
** X is NULL. |
|
5492
|
** |
|
5493
|
** The sha1_query(Y) function evalutes all queries in the SQL statements of Y |
|
5494
|
** and returns a hash of their results. |
|
5495
|
*/ |
|
5496
|
/* #include "sqlite3ext.h" */ |
|
5497
|
SQLITE_EXTENSION_INIT1 |
|
5498
|
#include <assert.h> |
|
5499
|
#include <string.h> |
|
5500
|
#include <stdarg.h> |
|
5501
|
|
|
5502
|
/****************************************************************************** |
|
5503
|
** The Hash Engine |
|
5504
|
*/ |
|
5505
|
#if defined(__GNUC__) && __GNUC__>=11 |
|
5506
|
# pragma GCC diagnostic push |
|
5507
|
# pragma GCC diagnostic ignored "-Wstringop-overread" |
|
5508
|
#endif |
|
5509
|
/* Context for the SHA1 hash */ |
|
5510
|
typedef struct SHA1Context SHA1Context; |
|
5511
|
struct SHA1Context { |
|
5512
|
unsigned int state[5]; |
|
5513
|
unsigned int count[2]; |
|
5514
|
unsigned char buffer[64]; |
|
5515
|
}; |
|
5516
|
|
|
5517
|
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) |
|
5518
|
#define rol(x,k) SHA_ROT(x,k,32-(k)) |
|
5519
|
#define ror(x,k) SHA_ROT(x,32-(k),k) |
|
5520
|
|
|
5521
|
#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ |
|
5522
|
|(rol(block[i],8)&0x00FF00FF)) |
|
5523
|
#define blk0be(i) block[i] |
|
5524
|
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ |
|
5525
|
^block[(i+2)&15]^block[i&15],1)) |
|
5526
|
|
|
5527
|
/* |
|
5528
|
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 |
|
5529
|
* |
|
5530
|
* Rl0() for little-endian and Rb0() for big-endian. Endianness is |
|
5531
|
* determined at run-time. |
|
5532
|
*/ |
|
5533
|
#define Rl0(v,w,x,y,z,i) \ |
|
5534
|
z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2); |
|
5535
|
#define Rb0(v,w,x,y,z,i) \ |
|
5536
|
z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2); |
|
5537
|
#define R1(v,w,x,y,z,i) \ |
|
5538
|
z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2); |
|
5539
|
#define R2(v,w,x,y,z,i) \ |
|
5540
|
z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2); |
|
5541
|
#define R3(v,w,x,y,z,i) \ |
|
5542
|
z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2); |
|
5543
|
#define R4(v,w,x,y,z,i) \ |
|
5544
|
z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2); |
|
5545
|
|
|
5546
|
/* |
|
5547
|
* Hash a single 512-bit block. This is the core of the algorithm. |
|
5548
|
*/ |
|
5549
|
static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){ |
|
5550
|
unsigned int qq[5]; /* a, b, c, d, e; */ |
|
5551
|
static int one = 1; |
|
5552
|
unsigned int block[16]; |
|
5553
|
memcpy(block, buffer, 64); |
|
5554
|
memcpy(qq,state,5*sizeof(unsigned int)); |
|
5555
|
|
|
5556
|
#define a qq[0] |
|
5557
|
#define b qq[1] |
|
5558
|
#define c qq[2] |
|
5559
|
#define d qq[3] |
|
5560
|
#define e qq[4] |
|
5561
|
|
|
5562
|
/* Copy p->state[] to working vars */ |
|
5563
|
/* |
|
5564
|
a = state[0]; |
|
5565
|
b = state[1]; |
|
5566
|
c = state[2]; |
|
5567
|
d = state[3]; |
|
5568
|
e = state[4]; |
|
5569
|
*/ |
|
5570
|
|
|
5571
|
/* 4 rounds of 20 operations each. Loop unrolled. */ |
|
5572
|
if( 1 == *(unsigned char*)&one ){ |
|
5573
|
Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3); |
|
5574
|
Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7); |
|
5575
|
Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11); |
|
5576
|
Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15); |
|
5577
|
}else{ |
|
5578
|
Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3); |
|
5579
|
Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7); |
|
5580
|
Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11); |
|
5581
|
Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15); |
|
5582
|
} |
|
5583
|
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); |
|
5584
|
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); |
|
5585
|
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); |
|
5586
|
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); |
|
5587
|
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); |
|
5588
|
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); |
|
5589
|
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); |
|
5590
|
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); |
|
5591
|
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); |
|
5592
|
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); |
|
5593
|
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); |
|
5594
|
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); |
|
5595
|
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); |
|
5596
|
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); |
|
5597
|
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); |
|
5598
|
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); |
|
5599
|
|
|
5600
|
/* Add the working vars back into context.state[] */ |
|
5601
|
state[0] += a; |
|
5602
|
state[1] += b; |
|
5603
|
state[2] += c; |
|
5604
|
state[3] += d; |
|
5605
|
state[4] += e; |
|
5606
|
|
|
5607
|
#undef a |
|
5608
|
#undef b |
|
5609
|
#undef c |
|
5610
|
#undef d |
|
5611
|
#undef e |
|
5612
|
} |
|
5613
|
|
|
5614
|
|
|
5615
|
/* Initialize a SHA1 context */ |
|
5616
|
static void hash_init(SHA1Context *p){ |
|
5617
|
/* SHA1 initialization constants */ |
|
5618
|
p->state[0] = 0x67452301; |
|
5619
|
p->state[1] = 0xEFCDAB89; |
|
5620
|
p->state[2] = 0x98BADCFE; |
|
5621
|
p->state[3] = 0x10325476; |
|
5622
|
p->state[4] = 0xC3D2E1F0; |
|
5623
|
p->count[0] = p->count[1] = 0; |
|
5624
|
} |
|
5625
|
|
|
5626
|
/* Add new content to the SHA1 hash */ |
|
5627
|
static void hash_step( |
|
5628
|
SHA1Context *p, /* Add content to this context */ |
|
5629
|
const unsigned char *data, /* Data to be added */ |
|
5630
|
unsigned int len /* Number of bytes in data */ |
|
5631
|
){ |
|
5632
|
unsigned int i, j; |
|
5633
|
|
|
5634
|
j = p->count[0]; |
|
5635
|
if( (p->count[0] += len << 3) < j ){ |
|
5636
|
p->count[1] += (len>>29)+1; |
|
5637
|
} |
|
5638
|
j = (j >> 3) & 63; |
|
5639
|
if( (j + len) > 63 ){ |
|
5640
|
(void)memcpy(&p->buffer[j], data, (i = 64-j)); |
|
5641
|
SHA1Transform(p->state, p->buffer); |
|
5642
|
for(; i + 63 < len; i += 64){ |
|
5643
|
SHA1Transform(p->state, &data[i]); |
|
5644
|
} |
|
5645
|
j = 0; |
|
5646
|
}else{ |
|
5647
|
i = 0; |
|
5648
|
} |
|
5649
|
if( len-i>0 ) (void)memcpy(&p->buffer[j], &data[i], len - i); |
|
5650
|
} |
|
5651
|
|
|
5652
|
/* Compute a string using sqlite3_vsnprintf() and hash it */ |
|
5653
|
static void hash_step_vformat( |
|
5654
|
SHA1Context *p, /* Add content to this context */ |
|
5655
|
const char *zFormat, |
|
5656
|
... |
|
5657
|
){ |
|
5658
|
va_list ap; |
|
5659
|
int n; |
|
5660
|
char zBuf[50]; |
|
5661
|
va_start(ap, zFormat); |
|
5662
|
sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); |
|
5663
|
va_end(ap); |
|
5664
|
n = (int)strlen(zBuf); |
|
5665
|
hash_step(p, (unsigned char*)zBuf, n); |
|
5666
|
} |
|
5667
|
|
|
5668
|
|
|
5669
|
/* Add padding and compute the message digest. Render the |
|
5670
|
** message digest as lower-case hexadecimal and put it into |
|
5671
|
** zOut[]. zOut[] must be at least 41 bytes long. */ |
|
5672
|
static void hash_finish( |
|
5673
|
SHA1Context *p, /* The SHA1 context to finish and render */ |
|
5674
|
char *zOut, /* Store hex or binary hash here */ |
|
5675
|
int bAsBinary /* 1 for binary hash, 0 for hex hash */ |
|
5676
|
){ |
|
5677
|
unsigned int i; |
|
5678
|
unsigned char finalcount[8]; |
|
5679
|
unsigned char digest[20]; |
|
5680
|
static const char zEncode[] = "0123456789abcdef"; |
|
5681
|
|
|
5682
|
for (i = 0; i < 8; i++){ |
|
5683
|
finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)] |
|
5684
|
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ |
|
5685
|
} |
|
5686
|
hash_step(p, (const unsigned char *)"\200", 1); |
|
5687
|
while ((p->count[0] & 504) != 448){ |
|
5688
|
hash_step(p, (const unsigned char *)"\0", 1); |
|
5689
|
} |
|
5690
|
hash_step(p, finalcount, 8); /* Should cause a SHA1Transform() */ |
|
5691
|
for (i = 0; i < 20; i++){ |
|
5692
|
digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); |
|
5693
|
} |
|
5694
|
if( bAsBinary ){ |
|
5695
|
memcpy(zOut, digest, 20); |
|
5696
|
}else{ |
|
5697
|
for(i=0; i<20; i++){ |
|
5698
|
zOut[i*2] = zEncode[(digest[i]>>4)&0xf]; |
|
5699
|
zOut[i*2+1] = zEncode[digest[i] & 0xf]; |
|
5700
|
} |
|
5701
|
zOut[i*2]= 0; |
|
5702
|
} |
|
5703
|
} |
|
5704
|
#if defined(__GNUC__) && __GNUC__>=11 |
|
5705
|
# pragma GCC diagnostic pop |
|
5706
|
#endif |
|
5707
|
/* End of the hashing logic |
|
5708
|
*****************************************************************************/ |
|
5709
|
|
|
5710
|
/* |
|
5711
|
** Two SQL functions: sha1(X) and sha1b(X). |
|
5712
|
** |
|
5713
|
** sha1(X) returns a lower-case hexadecimal rendering of the SHA1 hash |
|
5714
|
** of the argument X. If X is a BLOB, it is hashed as is. For all other |
|
5715
|
** types of input, X is converted into a UTF-8 string and the string |
|
5716
|
** is hashed without the trailing 0x00 terminator. The hash of a NULL |
|
5717
|
** value is NULL. |
|
5718
|
** |
|
5719
|
** sha1b(X) is the same except that it returns a 20-byte BLOB containing |
|
5720
|
** the binary hash instead of a hexadecimal string. |
|
5721
|
*/ |
|
5722
|
static void sha1Func( |
|
5723
|
sqlite3_context *context, |
|
5724
|
int argc, |
|
5725
|
sqlite3_value **argv |
|
5726
|
){ |
|
5727
|
SHA1Context cx; |
|
5728
|
int eType = sqlite3_value_type(argv[0]); |
|
5729
|
int nByte = sqlite3_value_bytes(argv[0]); |
|
5730
|
const unsigned char *pData; |
|
5731
|
char zOut[44]; |
|
5732
|
|
|
5733
|
assert( argc==1 ); |
|
5734
|
if( eType==SQLITE_NULL ) return; |
|
5735
|
hash_init(&cx); |
|
5736
|
if( eType==SQLITE_BLOB ){ |
|
5737
|
pData = (const unsigned char*)sqlite3_value_blob(argv[0]); |
|
5738
|
}else{ |
|
5739
|
pData = (const unsigned char*)sqlite3_value_text(argv[0]); |
|
5740
|
} |
|
5741
|
if( pData==0 ){ |
|
5742
|
if( nByte ) return; |
|
5743
|
pData = (const unsigned char*)""; |
|
5744
|
} |
|
5745
|
hash_step(&cx, pData, nByte); |
|
5746
|
if( sqlite3_user_data(context)!=0 ){ |
|
5747
|
/* sha1b() - binary result */ |
|
5748
|
hash_finish(&cx, zOut, 1); |
|
5749
|
sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT); |
|
5750
|
}else{ |
|
5751
|
/* sha1() - hexadecimal text result */ |
|
5752
|
hash_finish(&cx, zOut, 0); |
|
5753
|
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT); |
|
5754
|
} |
|
5755
|
} |
|
5756
|
|
|
5757
|
/* |
|
5758
|
** Implementation of the sha1_query(SQL) function. |
|
5759
|
** |
|
5760
|
** This function compiles and runs the SQL statement(s) given in the |
|
5761
|
** argument. The results are hashed using SHA1 and that hash is returned. |
|
5762
|
** |
|
5763
|
** The original SQL text is included as part of the hash. |
|
5764
|
** |
|
5765
|
** The hash is not just a concatenation of the outputs. Each query |
|
5766
|
** is delimited and each row and value within the query is delimited, |
|
5767
|
** with all values being marked with their datatypes. |
|
5768
|
*/ |
|
5769
|
static void sha1QueryFunc( |
|
5770
|
sqlite3_context *context, |
|
5771
|
int argc, |
|
5772
|
sqlite3_value **argv |
|
5773
|
){ |
|
5774
|
sqlite3 *db = sqlite3_context_db_handle(context); |
|
5775
|
const char *zSql = (const char*)sqlite3_value_text(argv[0]); |
|
5776
|
sqlite3_stmt *pStmt = 0; |
|
5777
|
int nCol; /* Number of columns in the result set */ |
|
5778
|
int i; /* Loop counter */ |
|
5779
|
int rc; |
|
5780
|
int n; |
|
5781
|
const char *z; |
|
5782
|
SHA1Context cx; |
|
5783
|
char zOut[44]; |
|
5784
|
int isRecursive = 0; |
|
5785
|
int *pIsRecursive; |
|
5786
|
|
|
5787
|
assert( argc==1 ); |
|
5788
|
if( zSql==0 ) return; |
|
5789
|
pIsRecursive = sqlite3_get_clientdata(db, "sha1_query()"); |
|
5790
|
if( pIsRecursive ){ |
|
5791
|
*pIsRecursive = 1; |
|
5792
|
return; |
|
5793
|
} |
|
5794
|
hash_init(&cx); |
|
5795
|
while( zSql[0] ){ |
|
5796
|
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); |
|
5797
|
if( rc ){ |
|
5798
|
char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", |
|
5799
|
zSql, sqlite3_errmsg(db)); |
|
5800
|
sqlite3_finalize(pStmt); |
|
5801
|
sqlite3_result_error(context, zMsg, -1); |
|
5802
|
sqlite3_free(zMsg); |
|
5803
|
return; |
|
5804
|
} |
|
5805
|
if( !sqlite3_stmt_readonly(pStmt) ){ |
|
5806
|
char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); |
|
5807
|
sqlite3_finalize(pStmt); |
|
5808
|
sqlite3_result_error(context, zMsg, -1); |
|
5809
|
sqlite3_free(zMsg); |
|
5810
|
return; |
|
5811
|
} |
|
5812
|
nCol = sqlite3_column_count(pStmt); |
|
5813
|
z = sqlite3_sql(pStmt); |
|
5814
|
if( z==0 ) z = ""; |
|
5815
|
n = (int)strlen(z); |
|
5816
|
hash_step_vformat(&cx,"S%d:",n); |
|
5817
|
hash_step(&cx,(unsigned char*)z,n); |
|
5818
|
|
|
5819
|
/* Compute a hash over the result of the query */ |
|
5820
|
sqlite3_set_clientdata(db, "sha1_query()", &isRecursive, 0); |
|
5821
|
while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
|
5822
|
hash_step(&cx,(const unsigned char*)"R",1); |
|
5823
|
for(i=0; i<nCol; i++){ |
|
5824
|
switch( sqlite3_column_type(pStmt,i) ){ |
|
5825
|
case SQLITE_NULL: { |
|
5826
|
hash_step(&cx, (const unsigned char*)"N",1); |
|
5827
|
break; |
|
5828
|
} |
|
5829
|
case SQLITE_INTEGER: { |
|
5830
|
sqlite3_uint64 u; |
|
5831
|
int j; |
|
5832
|
unsigned char x[9]; |
|
5833
|
sqlite3_int64 v = sqlite3_column_int64(pStmt,i); |
|
5834
|
memcpy(&u, &v, 8); |
|
5835
|
for(j=8; j>=1; j--){ |
|
5836
|
x[j] = u & 0xff; |
|
5837
|
u >>= 8; |
|
5838
|
} |
|
5839
|
x[0] = 'I'; |
|
5840
|
hash_step(&cx, x, 9); |
|
5841
|
break; |
|
5842
|
} |
|
5843
|
case SQLITE_FLOAT: { |
|
5844
|
sqlite3_uint64 u; |
|
5845
|
int j; |
|
5846
|
unsigned char x[9]; |
|
5847
|
double r = sqlite3_column_double(pStmt,i); |
|
5848
|
memcpy(&u, &r, 8); |
|
5849
|
for(j=8; j>=1; j--){ |
|
5850
|
x[j] = u & 0xff; |
|
5851
|
u >>= 8; |
|
5852
|
} |
|
5853
|
x[0] = 'F'; |
|
5854
|
hash_step(&cx,x,9); |
|
5855
|
break; |
|
5856
|
} |
|
5857
|
case SQLITE_TEXT: { |
|
5858
|
int n2 = sqlite3_column_bytes(pStmt, i); |
|
5859
|
const unsigned char *z2 = sqlite3_column_text(pStmt, i); |
|
5860
|
hash_step_vformat(&cx,"T%d:",n2); |
|
5861
|
hash_step(&cx, z2, n2); |
|
5862
|
break; |
|
5863
|
} |
|
5864
|
case SQLITE_BLOB: { |
|
5865
|
int n2 = sqlite3_column_bytes(pStmt, i); |
|
5866
|
const unsigned char *z2 = sqlite3_column_blob(pStmt, i); |
|
5867
|
hash_step_vformat(&cx,"B%d:",n2); |
|
5868
|
hash_step(&cx, z2, n2); |
|
5869
|
break; |
|
5870
|
} |
|
5871
|
} |
|
5872
|
} |
|
5873
|
} |
|
5874
|
sqlite3_finalize(pStmt); |
|
5875
|
sqlite3_set_clientdata(db, "sha1_query()", 0, 0); |
|
5876
|
} |
|
5877
|
hash_finish(&cx, zOut, 0); |
|
5878
|
if( isRecursive ){ |
|
5879
|
sqlite3_result_error(context, "recursive use of sha1_query()", -1); |
|
5880
|
}else{ |
|
5881
|
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT); |
|
5882
|
} |
|
5883
|
} |
|
5884
|
|
|
5885
|
|
|
5886
|
#ifdef _WIN32 |
|
5887
|
|
|
5888
|
#endif |
|
5889
|
int sqlite3_sha_init( |
|
5890
|
sqlite3 *db, |
|
5891
|
char **pzErrMsg, |
|
5892
|
const sqlite3_api_routines *pApi |
|
5893
|
){ |
|
5894
|
int rc = SQLITE_OK; |
|
5895
|
static int one = 1; |
|
5896
|
SQLITE_EXTENSION_INIT2(pApi); |
|
5897
|
(void)pzErrMsg; /* Unused parameter */ |
|
5898
|
rc = sqlite3_create_function(db, "sha1", 1, |
|
5899
|
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, |
|
5900
|
0, sha1Func, 0, 0); |
|
5901
|
if( rc==SQLITE_OK ){ |
|
5902
|
rc = sqlite3_create_function(db, "sha1b", 1, |
|
5903
|
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, |
|
5904
|
(void*)&one, sha1Func, 0, 0); |
|
5905
|
} |
|
5906
|
if( rc==SQLITE_OK ){ |
|
5907
|
rc = sqlite3_create_function(db, "sha1_query", 1, |
|
5908
|
SQLITE_UTF8|SQLITE_DIRECTONLY, 0, |
|
5909
|
sha1QueryFunc, 0, 0); |
|
5910
|
} |
|
5911
|
return rc; |
|
5912
|
} |
|
5913
|
|
|
5914
|
/************************* End ext/misc/sha1.c ********************/ |
|
5915
|
/************************* Begin ext/misc/uint.c ******************/ |
|
5916
|
/* |
|
5917
|
** 2020-04-14 |
|
5918
|
** |
|
5919
|
** The author disclaims copyright to this source code. In place of |
|
5920
|
** a legal notice, here is a blessing: |
|
5921
|
** |
|
5922
|
** May you do good and not evil. |
|
5923
|
** May you find forgiveness for yourself and forgive others. |
|
5924
|
** May you share freely, never taking more than you give. |
|
5925
|
** |
|
5926
|
****************************************************************************** |
|
5927
|
** |
|
5928
|
** This SQLite extension implements the UINT collating sequence. |
|
5929
|
** |
|
5930
|
** UINT works like BINARY for text, except that embedded strings |
|
5931
|
** of digits compare in numeric order. |
|
5932
|
** |
|
5933
|
** * Leading zeros are handled properly, in the sense that |
|
5934
|
** they do not mess of the magnitude comparison of embedded |
|
5935
|
** strings of digits. "x00123y" is equal to "x123y". |
|
5936
|
** |
|
5937
|
** * Only unsigned integers are recognized. Plus and minus |
|
5938
|
** signs are ignored. Decimal points and exponential notation |
|
5939
|
** are ignored. |
|
5940
|
** |
|
5941
|
** * Embedded integers can be of arbitrary length. Comparison |
|
5942
|
** is *not* limited integers that can be expressed as a |
|
5943
|
** 64-bit machine integer. |
|
5944
|
*/ |
|
5945
|
/* #include "sqlite3ext.h" */ |
|
5946
|
SQLITE_EXTENSION_INIT1 |
|
5947
|
#include <assert.h> |
|
5948
|
#include <string.h> |
|
5949
|
#include <ctype.h> |
|
5950
|
|
|
5951
|
/* |
|
5952
|
** Compare text in lexicographic order, except strings of digits |
|
5953
|
** compare in numeric order. |
|
5954
|
*/ |
|
5955
|
static int uintCollFunc( |
|
5956
|
void *notUsed, |
|
5957
|
int nKey1, const void *pKey1, |
|
5958
|
int nKey2, const void *pKey2 |
|
5959
|
){ |
|
5960
|
const unsigned char *zA = (const unsigned char*)pKey1; |
|
5961
|
const unsigned char *zB = (const unsigned char*)pKey2; |
|
5962
|
int i=0, j=0, x; |
|
5963
|
(void)notUsed; |
|
5964
|
while( i<nKey1 && j<nKey2 ){ |
|
5965
|
x = zA[i] - zB[j]; |
|
5966
|
if( isdigit(zA[i]) ){ |
|
5967
|
int k; |
|
5968
|
if( !isdigit(zB[j]) ) return x; |
|
5969
|
while( i<nKey1 && zA[i]=='0' ){ i++; } |
|
5970
|
while( j<nKey2 && zB[j]=='0' ){ j++; } |
|
5971
|
k = 0; |
|
5972
|
while( i+k<nKey1 && isdigit(zA[i+k]) |
|
5973
|
&& j+k<nKey2 && isdigit(zB[j+k]) ){ |
|
5974
|
k++; |
|
5975
|
} |
|
5976
|
if( i+k<nKey1 && isdigit(zA[i+k]) ){ |
|
5977
|
return +1; |
|
5978
|
}else if( j+k<nKey2 && isdigit(zB[j+k]) ){ |
|
5979
|
return -1; |
|
5980
|
}else{ |
|
5981
|
x = memcmp(zA+i, zB+j, k); |
|
5982
|
if( x ) return x; |
|
5983
|
i += k; |
|
5984
|
j += k; |
|
5985
|
} |
|
5986
|
}else if( x ){ |
|
5987
|
return x; |
|
5988
|
}else{ |
|
5989
|
i++; |
|
5990
|
j++; |
|
5991
|
} |
|
5992
|
} |
|
5993
|
return (nKey1 - i) - (nKey2 - j); |
|
5994
|
} |
|
5995
|
|
|
5996
|
#ifdef _WIN32 |
|
5997
|
|
|
5998
|
#endif |
|
5999
|
int sqlite3_uint_init( |
|
6000
|
sqlite3 *db, |
|
6001
|
char **pzErrMsg, |
|
6002
|
const sqlite3_api_routines *pApi |
|
6003
|
){ |
|
6004
|
SQLITE_EXTENSION_INIT2(pApi); |
|
6005
|
(void)pzErrMsg; /* Unused parameter */ |
|
6006
|
return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc); |
|
6007
|
} |
|
6008
|
|
|
6009
|
/************************* End ext/misc/uint.c ********************/ |
|
6010
|
/************************* Begin ext/misc/decimal.c ******************/ |
|
6011
|
/* |
|
6012
|
** 2020-06-22 |
|
6013
|
** |
|
6014
|
** The author disclaims copyright to this source code. In place of |
|
6015
|
** a legal notice, here is a blessing: |
|
6016
|
** |
|
6017
|
** May you do good and not evil. |
|
6018
|
** May you find forgiveness for yourself and forgive others. |
|
6019
|
** May you share freely, never taking more than you give. |
|
6020
|
** |
|
6021
|
****************************************************************************** |
|
6022
|
** |
|
6023
|
** Routines to implement arbitrary-precision decimal math. |
|
6024
|
** |
|
6025
|
** The focus here is on simplicity and correctness, not performance. |
|
6026
|
*/ |
|
6027
|
/* #include "sqlite3ext.h" */ |
|
6028
|
SQLITE_EXTENSION_INIT1 |
|
6029
|
#include <assert.h> |
|
6030
|
#include <string.h> |
|
6031
|
#include <ctype.h> |
|
6032
|
#include <stdlib.h> |
|
6033
|
|
|
6034
|
/* Mark a function parameter as unused, to suppress nuisance compiler |
|
6035
|
** warnings. */ |
|
6036
|
#ifndef UNUSED_PARAMETER |
|
6037
|
# define UNUSED_PARAMETER(X) (void)(X) |
|
6038
|
#endif |
|
6039
|
|
|
6040
|
#ifndef IsSpace |
|
6041
|
#define IsSpace(X) isspace((unsigned char)X) |
|
6042
|
#endif |
|
6043
|
|
|
6044
|
#ifndef SQLITE_DECIMAL_MAX_DIGIT |
|
6045
|
# define SQLITE_DECIMAL_MAX_DIGIT 10000000 |
|
6046
|
#endif |
|
6047
|
|
|
6048
|
/* A decimal object */ |
|
6049
|
typedef struct Decimal Decimal; |
|
6050
|
struct Decimal { |
|
6051
|
char sign; /* 0 for positive, 1 for negative */ |
|
6052
|
char oom; /* True if an OOM is encountered */ |
|
6053
|
char isNull; /* True if holds a NULL rather than a number */ |
|
6054
|
char isInit; /* True upon initialization */ |
|
6055
|
int nDigit; /* Total number of digits */ |
|
6056
|
int nFrac; /* Number of digits to the right of the decimal point */ |
|
6057
|
signed char *a; /* Array of digits. Most significant first. */ |
|
6058
|
}; |
|
6059
|
|
|
6060
|
/* |
|
6061
|
** Release memory held by a Decimal, but do not free the object itself. |
|
6062
|
*/ |
|
6063
|
static void decimal_clear(Decimal *p){ |
|
6064
|
sqlite3_free(p->a); |
|
6065
|
} |
|
6066
|
|
|
6067
|
/* |
|
6068
|
** Destroy a Decimal object |
|
6069
|
*/ |
|
6070
|
static void decimal_free(Decimal *p){ |
|
6071
|
if( p ){ |
|
6072
|
decimal_clear(p); |
|
6073
|
sqlite3_free(p); |
|
6074
|
} |
|
6075
|
} |
|
6076
|
|
|
6077
|
/* |
|
6078
|
** Allocate a new Decimal object initialized to the text in zIn[]. |
|
6079
|
** Return NULL if any kind of error occurs. |
|
6080
|
** |
|
6081
|
** Note that zIn[] is not necessarily zero-terminated. Always |
|
6082
|
** respect the boundary imposed by the n argument. |
|
6083
|
*/ |
|
6084
|
static Decimal *decimalNewFromText(const char *zIn, int n){ |
|
6085
|
|