Fossil SCM
Merge the all the latest trunk enhancements into the http1-1-chunked branch.
Commit
a5f61586b7493c3d5298a4a16edf269c2fa09967f483d58b7e924b2c15e0fba4
Parent
4a648d7410ad9d6…
24 files changed
+1
-1
+8
-1
+532
-139
+1369
-689
+73
-11
+12
+1
+3
-3
+6
-2
+99
-8
+16
+3
-3
+61
-21
+19
+8
-2
+255
-61
+10
-1
+4
+40
-13
+3
-5
+58
-10
+2
+9
-1
+1
-1
~
auto.def
~
extsrc/qrf.h
~
extsrc/shell.c
~
extsrc/sqlite3.c
~
extsrc/sqlite3.h
~
src/builtin.c
~
src/configure.c
~
src/delta.c
~
src/forum.c
~
src/fossil.page.forumpost.js
~
src/info.c
~
src/main.c
~
src/merge.c
~
src/path.c
~
src/stash.c
~
src/statrep.c
~
src/style.c
~
src/style.forum.css
~
src/timeline.c
~
src/wiki.c
~
src/wikiformat.c
~
www/changes.wiki
~
www/fileformat.wiki
~
www/wikitheory.wiki
M
auto.def
+1
-1
| --- auto.def | ||
| +++ auto.def | ||
| @@ -36,11 +36,11 @@ | ||
| 36 | 36 | } |
| 37 | 37 | |
| 38 | 38 | # Update the minimum required SQLite version number here, and also |
| 39 | 39 | # in src/main.c near the sqlite3_libversion_number() call. Take care |
| 40 | 40 | # that both places agree! |
| 41 | -define MINIMUM_SQLITE_VERSION "3.49.0" | |
| 41 | +define MINIMUM_SQLITE_VERSION "3.54.0" | |
| 42 | 42 | |
| 43 | 43 | # This is useful for people wanting Fossil to use an external SQLite library |
| 44 | 44 | # to compare the one they have against the minimum required |
| 45 | 45 | if {[opt-bool print-minimum-sqlite-version]} { |
| 46 | 46 | puts [get-define MINIMUM_SQLITE_VERSION] |
| 47 | 47 |
| --- auto.def | |
| +++ auto.def | |
| @@ -36,11 +36,11 @@ | |
| 36 | } |
| 37 | |
| 38 | # Update the minimum required SQLite version number here, and also |
| 39 | # in src/main.c near the sqlite3_libversion_number() call. Take care |
| 40 | # that both places agree! |
| 41 | define MINIMUM_SQLITE_VERSION "3.49.0" |
| 42 | |
| 43 | # This is useful for people wanting Fossil to use an external SQLite library |
| 44 | # to compare the one they have against the minimum required |
| 45 | if {[opt-bool print-minimum-sqlite-version]} { |
| 46 | puts [get-define MINIMUM_SQLITE_VERSION] |
| 47 |
| --- auto.def | |
| +++ auto.def | |
| @@ -36,11 +36,11 @@ | |
| 36 | } |
| 37 | |
| 38 | # Update the minimum required SQLite version number here, and also |
| 39 | # in src/main.c near the sqlite3_libversion_number() call. Take care |
| 40 | # that both places agree! |
| 41 | define MINIMUM_SQLITE_VERSION "3.54.0" |
| 42 | |
| 43 | # This is useful for people wanting Fossil to use an external SQLite library |
| 44 | # to compare the one they have against the minimum required |
| 45 | if {[opt-bool print-minimum-sqlite-version]} { |
| 46 | puts [get-define MINIMUM_SQLITE_VERSION] |
| 47 |
+8
-1
| --- extsrc/qrf.h | ||
| +++ extsrc/qrf.h | ||
| @@ -55,10 +55,12 @@ | ||
| 55 | 55 | char *(*xRender)(void*,sqlite3_value*); /* Render a value */ |
| 56 | 56 | int (*xWrite)(void*,const char*,sqlite3_int64); /* Write output */ |
| 57 | 57 | void *pRenderArg; /* First argument to the xRender callback */ |
| 58 | 58 | void *pWriteArg; /* First argument to the xWrite callback */ |
| 59 | 59 | char **pzOutput; /* Storage location for output string */ |
| 60 | + /* The following are available in iVersion 2 and later */ | |
| 61 | + unsigned char bRowCount; /* Show the number of rows at end of each query */ | |
| 60 | 62 | /* Additional fields may be added in the future */ |
| 61 | 63 | }; |
| 62 | 64 | |
| 63 | 65 | /* |
| 64 | 66 | ** Interfaces |
| @@ -83,11 +85,11 @@ | ||
| 83 | 85 | #define QRF_STYLE_Column 2 /* One record per line in neat columns */ |
| 84 | 86 | #define QRF_STYLE_Count 3 /* Output only a count of the rows of output */ |
| 85 | 87 | #define QRF_STYLE_Csv 4 /* Comma-separated-value */ |
| 86 | 88 | #define QRF_STYLE_Eqp 5 /* Format EXPLAIN QUERY PLAN output */ |
| 87 | 89 | #define QRF_STYLE_Explain 6 /* EXPLAIN output */ |
| 88 | -#define QRF_STYLE_Html 7 /* Generate an XHTML table */ | |
| 90 | +#define QRF_STYLE_Html 7 /* Generate HTML-style <tr><td> output */ | |
| 89 | 91 | #define QRF_STYLE_Insert 8 /* Generate SQL "insert" statements */ |
| 90 | 92 | #define QRF_STYLE_Json 9 /* Output is a list of JSON objects */ |
| 91 | 93 | #define QRF_STYLE_JObject 10 /* Independent JSON objects for each row */ |
| 92 | 94 | #define QRF_STYLE_Line 11 /* One column per line. */ |
| 93 | 95 | #define QRF_STYLE_List 12 /* One record per line with a separator */ |
| @@ -143,10 +145,15 @@ | ||
| 143 | 145 | #define QRF_SW_On 2 /* This setting is forced on */ |
| 144 | 146 | #define QRF_Auto 0 /* Alternate spelling for QRF_*_Auto */ |
| 145 | 147 | #define QRF_No 1 /* Alternate spelling for QRF_SW_Off */ |
| 146 | 148 | #define QRF_Yes 2 /* Alternate spelling for QRF_SW_On */ |
| 147 | 149 | |
| 150 | +/* | |
| 151 | +** Additional value allowed for bTitles | |
| 152 | +*/ | |
| 153 | +#define QRF_Always 3 /* Always show titles, even if no rows */ | |
| 154 | + | |
| 148 | 155 | /* |
| 149 | 156 | ** Possible alignment values alignment settings |
| 150 | 157 | ** |
| 151 | 158 | ** Horizontal Vertial |
| 152 | 159 | ** ---------- -------- */ |
| 153 | 160 |
| --- extsrc/qrf.h | |
| +++ extsrc/qrf.h | |
| @@ -55,10 +55,12 @@ | |
| 55 | char *(*xRender)(void*,sqlite3_value*); /* Render a value */ |
| 56 | int (*xWrite)(void*,const char*,sqlite3_int64); /* Write output */ |
| 57 | void *pRenderArg; /* First argument to the xRender callback */ |
| 58 | void *pWriteArg; /* First argument to the xWrite callback */ |
| 59 | char **pzOutput; /* Storage location for output string */ |
| 60 | /* Additional fields may be added in the future */ |
| 61 | }; |
| 62 | |
| 63 | /* |
| 64 | ** Interfaces |
| @@ -83,11 +85,11 @@ | |
| 83 | #define QRF_STYLE_Column 2 /* One record per line in neat columns */ |
| 84 | #define QRF_STYLE_Count 3 /* Output only a count of the rows of output */ |
| 85 | #define QRF_STYLE_Csv 4 /* Comma-separated-value */ |
| 86 | #define QRF_STYLE_Eqp 5 /* Format EXPLAIN QUERY PLAN output */ |
| 87 | #define QRF_STYLE_Explain 6 /* EXPLAIN output */ |
| 88 | #define QRF_STYLE_Html 7 /* Generate an XHTML table */ |
| 89 | #define QRF_STYLE_Insert 8 /* Generate SQL "insert" statements */ |
| 90 | #define QRF_STYLE_Json 9 /* Output is a list of JSON objects */ |
| 91 | #define QRF_STYLE_JObject 10 /* Independent JSON objects for each row */ |
| 92 | #define QRF_STYLE_Line 11 /* One column per line. */ |
| 93 | #define QRF_STYLE_List 12 /* One record per line with a separator */ |
| @@ -143,10 +145,15 @@ | |
| 143 | #define QRF_SW_On 2 /* This setting is forced on */ |
| 144 | #define QRF_Auto 0 /* Alternate spelling for QRF_*_Auto */ |
| 145 | #define QRF_No 1 /* Alternate spelling for QRF_SW_Off */ |
| 146 | #define QRF_Yes 2 /* Alternate spelling for QRF_SW_On */ |
| 147 | |
| 148 | /* |
| 149 | ** Possible alignment values alignment settings |
| 150 | ** |
| 151 | ** Horizontal Vertial |
| 152 | ** ---------- -------- */ |
| 153 |
| --- extsrc/qrf.h | |
| +++ extsrc/qrf.h | |
| @@ -55,10 +55,12 @@ | |
| 55 | char *(*xRender)(void*,sqlite3_value*); /* Render a value */ |
| 56 | int (*xWrite)(void*,const char*,sqlite3_int64); /* Write output */ |
| 57 | void *pRenderArg; /* First argument to the xRender callback */ |
| 58 | void *pWriteArg; /* First argument to the xWrite callback */ |
| 59 | char **pzOutput; /* Storage location for output string */ |
| 60 | /* The following are available in iVersion 2 and later */ |
| 61 | unsigned char bRowCount; /* Show the number of rows at end of each query */ |
| 62 | /* Additional fields may be added in the future */ |
| 63 | }; |
| 64 | |
| 65 | /* |
| 66 | ** Interfaces |
| @@ -83,11 +85,11 @@ | |
| 85 | #define QRF_STYLE_Column 2 /* One record per line in neat columns */ |
| 86 | #define QRF_STYLE_Count 3 /* Output only a count of the rows of output */ |
| 87 | #define QRF_STYLE_Csv 4 /* Comma-separated-value */ |
| 88 | #define QRF_STYLE_Eqp 5 /* Format EXPLAIN QUERY PLAN output */ |
| 89 | #define QRF_STYLE_Explain 6 /* EXPLAIN output */ |
| 90 | #define QRF_STYLE_Html 7 /* Generate HTML-style <tr><td> output */ |
| 91 | #define QRF_STYLE_Insert 8 /* Generate SQL "insert" statements */ |
| 92 | #define QRF_STYLE_Json 9 /* Output is a list of JSON objects */ |
| 93 | #define QRF_STYLE_JObject 10 /* Independent JSON objects for each row */ |
| 94 | #define QRF_STYLE_Line 11 /* One column per line. */ |
| 95 | #define QRF_STYLE_List 12 /* One record per line with a separator */ |
| @@ -143,10 +145,15 @@ | |
| 145 | #define QRF_SW_On 2 /* This setting is forced on */ |
| 146 | #define QRF_Auto 0 /* Alternate spelling for QRF_*_Auto */ |
| 147 | #define QRF_No 1 /* Alternate spelling for QRF_SW_Off */ |
| 148 | #define QRF_Yes 2 /* Alternate spelling for QRF_SW_On */ |
| 149 | |
| 150 | /* |
| 151 | ** Additional value allowed for bTitles |
| 152 | */ |
| 153 | #define QRF_Always 3 /* Always show titles, even if no rows */ |
| 154 | |
| 155 | /* |
| 156 | ** Possible alignment values alignment settings |
| 157 | ** |
| 158 | ** Horizontal Vertial |
| 159 | ** ---------- -------- */ |
| 160 |
+532
-139
| --- extsrc/shell.c | ||
| +++ extsrc/shell.c | ||
| @@ -23,10 +23,11 @@ | ||
| 23 | 23 | ** ext/misc/shathree.c |
| 24 | 24 | ** ext/misc/sqlar.c |
| 25 | 25 | ** ext/misc/sqlite3_stdio.c |
| 26 | 26 | ** ext/misc/sqlite3_stdio.h |
| 27 | 27 | ** ext/misc/stmtrand.c |
| 28 | +** ext/misc/strdup.c | |
| 28 | 29 | ** ext/misc/uint.c |
| 29 | 30 | ** ext/misc/vfstrace.c |
| 30 | 31 | ** ext/misc/windirent.h |
| 31 | 32 | ** ext/misc/zipfile.c |
| 32 | 33 | ** ext/qrf/qrf.c |
| @@ -205,28 +206,38 @@ | ||
| 205 | 206 | # define shell_add_history(X) add_history(X) |
| 206 | 207 | # define shell_read_history(X) read_history(X) |
| 207 | 208 | # define shell_write_history(X) write_history(X) |
| 208 | 209 | # define shell_stifle_history(X) stifle_history(X) |
| 209 | 210 | # define shell_readline(X) readline(X) |
| 211 | +# define SHELL_CMDLINE_EDIT_AVAILABLE 1 /* command-line editing available */ | |
| 210 | 212 | |
| 211 | 213 | #elif HAVE_LINENOISE |
| 212 | 214 | |
| 213 | 215 | # include "linenoise.h" |
| 214 | 216 | # define shell_add_history(X) linenoiseHistoryAdd(X) |
| 215 | 217 | # define shell_read_history(X) linenoiseHistoryLoad(X) |
| 216 | 218 | # define shell_write_history(X) linenoiseHistorySave(X) |
| 217 | 219 | # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) |
| 218 | 220 | # define shell_readline(X) linenoise(X) |
| 221 | +# define SHELL_CMDLINE_EDIT_AVAILABLE 1 /* command-line editing available */ | |
| 219 | 222 | |
| 220 | 223 | #else |
| 221 | 224 | |
| 222 | 225 | # define shell_read_history(X) |
| 223 | 226 | # define shell_write_history(X) |
| 224 | 227 | # define shell_stifle_history(X) |
| 228 | +# define SHELL_CMDLINE_EDIT_AVAILABLE 0 /* command-line editing not available */ | |
| 229 | +#endif | |
| 225 | 230 | |
| 226 | -# define SHELL_USE_LOCAL_GETLINE 1 | |
| 227 | -#endif | |
| 231 | +/* | |
| 232 | +** Global variable shellCmdLineEdit determines whether or not command-line | |
| 233 | +** editing is enabled. It defaults to 1 if the CLI is linked against a | |
| 234 | +** command-line editing library (linenoise, readline, or editline) and | |
| 235 | +** to 0 if no command-line editing library is available. The | |
| 236 | +** "--cmdline-edit off" command-line option will change this value to 0. | |
| 237 | +*/ | |
| 238 | +static int shellCmdLineEdit = SHELL_CMDLINE_EDIT_AVAILABLE; | |
| 228 | 239 | |
| 229 | 240 | #ifndef deliberate_fall_through |
| 230 | 241 | /* Quiet some compilers about some of our intentional code. */ |
| 231 | 242 | # if defined(GCC_VERSION) && GCC_VERSION>=7000000 |
| 232 | 243 | # define deliberate_fall_through __attribute__((fallthrough)); |
| @@ -733,10 +744,12 @@ | ||
| 733 | 744 | char *(*xRender)(void*,sqlite3_value*); /* Render a value */ |
| 734 | 745 | int (*xWrite)(void*,const char*,sqlite3_int64); /* Write output */ |
| 735 | 746 | void *pRenderArg; /* First argument to the xRender callback */ |
| 736 | 747 | void *pWriteArg; /* First argument to the xWrite callback */ |
| 737 | 748 | char **pzOutput; /* Storage location for output string */ |
| 749 | + /* The following are available in iVersion 2 and later */ | |
| 750 | + unsigned char bRowCount; /* Show the number of rows at end of each query */ | |
| 738 | 751 | /* Additional fields may be added in the future */ |
| 739 | 752 | }; |
| 740 | 753 | |
| 741 | 754 | /* |
| 742 | 755 | ** Interfaces |
| @@ -761,11 +774,11 @@ | ||
| 761 | 774 | #define QRF_STYLE_Column 2 /* One record per line in neat columns */ |
| 762 | 775 | #define QRF_STYLE_Count 3 /* Output only a count of the rows of output */ |
| 763 | 776 | #define QRF_STYLE_Csv 4 /* Comma-separated-value */ |
| 764 | 777 | #define QRF_STYLE_Eqp 5 /* Format EXPLAIN QUERY PLAN output */ |
| 765 | 778 | #define QRF_STYLE_Explain 6 /* EXPLAIN output */ |
| 766 | -#define QRF_STYLE_Html 7 /* Generate an XHTML table */ | |
| 779 | +#define QRF_STYLE_Html 7 /* Generate HTML-style <tr><td> output */ | |
| 767 | 780 | #define QRF_STYLE_Insert 8 /* Generate SQL "insert" statements */ |
| 768 | 781 | #define QRF_STYLE_Json 9 /* Output is a list of JSON objects */ |
| 769 | 782 | #define QRF_STYLE_JObject 10 /* Independent JSON objects for each row */ |
| 770 | 783 | #define QRF_STYLE_Line 11 /* One column per line. */ |
| 771 | 784 | #define QRF_STYLE_List 12 /* One record per line with a separator */ |
| @@ -821,10 +834,15 @@ | ||
| 821 | 834 | #define QRF_SW_On 2 /* This setting is forced on */ |
| 822 | 835 | #define QRF_Auto 0 /* Alternate spelling for QRF_*_Auto */ |
| 823 | 836 | #define QRF_No 1 /* Alternate spelling for QRF_SW_Off */ |
| 824 | 837 | #define QRF_Yes 2 /* Alternate spelling for QRF_SW_On */ |
| 825 | 838 | |
| 839 | +/* | |
| 840 | +** Additional value allowed for bTitles | |
| 841 | +*/ | |
| 842 | +#define QRF_Always 3 /* Always show titles, even if no rows */ | |
| 843 | + | |
| 826 | 844 | /* |
| 827 | 845 | ** Possible alignment values alignment settings |
| 828 | 846 | ** |
| 829 | 847 | ** Horizontal Vertial |
| 830 | 848 | ** ---------- -------- */ |
| @@ -2527,10 +2545,14 @@ | ||
| 2527 | 2545 | /* Doubled horizontal lines: */ |
| 2528 | 2546 | #define DBL_24 "\342\225\220" /* U+2550 === */ |
| 2529 | 2547 | #define DBL_123 "\342\225\236" /* U+255e |= */ |
| 2530 | 2548 | #define DBL_134 "\342\225\241" /* U+2561 =| */ |
| 2531 | 2549 | #define DBL_1234 "\342\225\252" /* U+256a =|= */ |
| 2550 | +#define DBL_12 "\342\225\230" /* U+2558 `= */ | |
| 2551 | +#define DBL_14 "\342\225\233" /* U+255b =' */ | |
| 2552 | +#define DBL_124 "\342\225\247" /* U+2567 ='= */ | |
| 2553 | + | |
| 2532 | 2554 | |
| 2533 | 2555 | /* Draw horizontal line N characters long using unicode box |
| 2534 | 2556 | ** characters |
| 2535 | 2557 | */ |
| 2536 | 2558 | static void qrfBoxLine(sqlite3_str *pOut, int N, int bDbl){ |
| @@ -2549,16 +2571,16 @@ | ||
| 2549 | 2571 | |
| 2550 | 2572 | /* |
| 2551 | 2573 | ** Draw a horizontal separator for a QRF_STYLE_Box table. |
| 2552 | 2574 | */ |
| 2553 | 2575 | static void qrfBoxSeparator( |
| 2554 | - sqlite3_str *pOut, | |
| 2555 | - qrfColData *p, | |
| 2556 | - const char *zSep1, | |
| 2557 | - const char *zSep2, | |
| 2558 | - const char *zSep3, | |
| 2559 | - int bDbl | |
| 2576 | + sqlite3_str *pOut, /* Output to this sqlite3_str */ | |
| 2577 | + qrfColData *p, /* Columnar data */ | |
| 2578 | + const char *zSep1, /* Left margin */ | |
| 2579 | + const char *zSep2, /* Column separator */ | |
| 2580 | + const char *zSep3, /* Right margin */ | |
| 2581 | + int bDbl /* True for double-lines */ | |
| 2560 | 2582 | ){ |
| 2561 | 2583 | int i; |
| 2562 | 2584 | if( p->nCol>0 ){ |
| 2563 | 2585 | int useBorder = p->p->spec.bBorder!=QRF_No; |
| 2564 | 2586 | if( useBorder ){ |
| @@ -2573,10 +2595,36 @@ | ||
| 2573 | 2595 | sqlite3_str_appendall(pOut, zSep3); |
| 2574 | 2596 | } |
| 2575 | 2597 | } |
| 2576 | 2598 | sqlite3_str_append(pOut, "\n", 1); |
| 2577 | 2599 | } |
| 2600 | + | |
| 2601 | +/* | |
| 2602 | +** Draw a horizontal separator for a QRF_STYLE_Column table. | |
| 2603 | +** This style of separator is only used for separating the title | |
| 2604 | +** from the content. | |
| 2605 | +*/ | |
| 2606 | +static void qrfColumnSeparator( | |
| 2607 | + sqlite3_str *pOut, /* Output to this sqlite3_str */ | |
| 2608 | + qrfColData *p, /* Columnar data */ | |
| 2609 | + const char *colSep, /* Column separator text */ | |
| 2610 | + int szColSep, /* Size of zColSep in bytes */ | |
| 2611 | + const char *rowSep, /* Row separator text */ | |
| 2612 | + int szRowSep /* Size of zRowSep in bytes */ | |
| 2613 | +){ | |
| 2614 | + int j; | |
| 2615 | + int nColumn = p->nCol; | |
| 2616 | + for(j=0; j<nColumn; j++){ | |
| 2617 | + sqlite3_str_appendchar(pOut, p->a[j].w, '-'); | |
| 2618 | + if( j<nColumn-1 ){ | |
| 2619 | + sqlite3_str_append(pOut, colSep, szColSep); | |
| 2620 | + }else{ | |
| 2621 | + qrfRTrim(pOut); | |
| 2622 | + sqlite3_str_append(pOut, rowSep, szRowSep); | |
| 2623 | + } | |
| 2624 | + } | |
| 2625 | +} | |
| 2578 | 2626 | |
| 2579 | 2627 | /* |
| 2580 | 2628 | ** Load into pData the default alignment for the body of a table. |
| 2581 | 2629 | */ |
| 2582 | 2630 | static void qrfLoadAlignment(qrfColData *pData, Qrf *p){ |
| @@ -2831,11 +2879,25 @@ | ||
| 2831 | 2879 | sqlite3_str *pStr; /* Temporary rendering */ |
| 2832 | 2880 | qrfColData data; /* Columnar layout data */ |
| 2833 | 2881 | int bRTrim; /* Trim trailing space */ |
| 2834 | 2882 | |
| 2835 | 2883 | rc = sqlite3_step(p->pStmt); |
| 2836 | - if( rc!=SQLITE_ROW || nColumn==0 ){ | |
| 2884 | + if( nColumn==0 ){ | |
| 2885 | + return; /* Not a query. No results every shown. */ | |
| 2886 | + } | |
| 2887 | + if( rc==SQLITE_DONE && nColumn>0 ){ | |
| 2888 | + /* Empty query */ | |
| 2889 | + if( p->spec.bTitles==QRF_Always ){ | |
| 2890 | + /* fall through into the columnar logic below */ | |
| 2891 | + }else{ | |
| 2892 | + if( p->spec.bRowCount==QRF_Yes ){ | |
| 2893 | + sqlite3_str_appendf(p->pOut, "(0 rows)\n"); | |
| 2894 | + qrfWrite(p); | |
| 2895 | + } | |
| 2896 | + return; /* No output, other than the row count */ | |
| 2897 | + } | |
| 2898 | + }else if( rc!=SQLITE_ROW ){ | |
| 2837 | 2899 | return; /* No output */ |
| 2838 | 2900 | } |
| 2839 | 2901 | |
| 2840 | 2902 | /* Initialize the data container */ |
| 2841 | 2903 | memset(&data, 0, sizeof(data)); |
| @@ -2848,12 +2910,12 @@ | ||
| 2848 | 2910 | } |
| 2849 | 2911 | memset(data.a, 0, nColumn*sizeof(struct qrfPerCol) ); |
| 2850 | 2912 | if( qrfColDataEnlarge(&data) ) return; |
| 2851 | 2913 | assert( data.az!=0 ); |
| 2852 | 2914 | |
| 2853 | - /* Load the column header names and all cell content into data */ | |
| 2854 | - if( p->spec.bTitles==QRF_Yes ){ | |
| 2915 | + /* Load the column header names into data */ | |
| 2916 | + if( p->spec.bTitles>=QRF_Yes ){ | |
| 2855 | 2917 | unsigned char saved_eText = p->spec.eText; |
| 2856 | 2918 | p->spec.eText = p->spec.eTitle; |
| 2857 | 2919 | memset(data.abNum, 0, nColumn); |
| 2858 | 2920 | for(i=0; i<nColumn; i++){ |
| 2859 | 2921 | const char *z = (const char*)sqlite3_column_name(p->pStmt,i); |
| @@ -2874,13 +2936,14 @@ | ||
| 2874 | 2936 | data.n++; |
| 2875 | 2937 | if( w>data.a[i].mxW ) data.a[i].mxW = w; |
| 2876 | 2938 | if( nNL ) data.bMultiRow = 1; |
| 2877 | 2939 | } |
| 2878 | 2940 | p->spec.eText = saved_eText; |
| 2879 | - p->nRow++; | |
| 2880 | 2941 | } |
| 2881 | - do{ | |
| 2942 | + | |
| 2943 | + /* Load query results into data */ | |
| 2944 | + while( rc==SQLITE_ROW && p->iErr==SQLITE_OK ){ | |
| 2882 | 2945 | if( data.n+nColumn > data.nAlloc ){ |
| 2883 | 2946 | if( qrfColDataEnlarge(&data) ) return; |
| 2884 | 2947 | } |
| 2885 | 2948 | for(i=0; i<nColumn; i++){ |
| 2886 | 2949 | char *z; |
| @@ -2897,11 +2960,12 @@ | ||
| 2897 | 2960 | data.n++; |
| 2898 | 2961 | if( w>data.a[i].mxW ) data.a[i].mxW = w; |
| 2899 | 2962 | if( nNL ) data.bMultiRow = 1; |
| 2900 | 2963 | } |
| 2901 | 2964 | p->nRow++; |
| 2902 | - }while( sqlite3_step(p->pStmt)==SQLITE_ROW && p->iErr==SQLITE_OK ); | |
| 2965 | + rc = sqlite3_step(p->pStmt); | |
| 2966 | + } | |
| 2903 | 2967 | if( p->iErr ){ |
| 2904 | 2968 | qrfColDataFree(&data); |
| 2905 | 2969 | return; |
| 2906 | 2970 | } |
| 2907 | 2971 | |
| @@ -3105,11 +3169,11 @@ | ||
| 3105 | 3169 | /* Draw either (1) the separator between the title line and the body |
| 3106 | 3170 | ** of the table, or (2) separators between individual rows of the table |
| 3107 | 3171 | ** body. isTitleDataSeparator will be true if we are doing (1). |
| 3108 | 3172 | */ |
| 3109 | 3173 | if( (i==0 || data.bMultiRow) && i+nColumn<data.n ){ |
| 3110 | - int isTitleDataSeparator = (i==0 && p->spec.bTitles==QRF_Yes); | |
| 3174 | + int isTitleDataSeparator = (i==0 && p->spec.bTitles>=QRF_Yes); | |
| 3111 | 3175 | if( isTitleDataSeparator ){ |
| 3112 | 3176 | qrfLoadAlignment(&data, p); |
| 3113 | 3177 | } |
| 3114 | 3178 | switch( p->spec.eStyle ){ |
| 3115 | 3179 | case QRF_STYLE_Table: { |
| @@ -3132,19 +3196,12 @@ | ||
| 3132 | 3196 | } |
| 3133 | 3197 | break; |
| 3134 | 3198 | } |
| 3135 | 3199 | case QRF_STYLE_Column: { |
| 3136 | 3200 | if( isTitleDataSeparator ){ |
| 3137 | - for(j=0; j<nColumn; j++){ | |
| 3138 | - sqlite3_str_appendchar(p->pOut, data.a[j].w, '-'); | |
| 3139 | - if( j<nColumn-1 ){ | |
| 3140 | - sqlite3_str_append(p->pOut, colSep, szColSep); | |
| 3141 | - }else{ | |
| 3142 | - qrfRTrim(p->pOut); | |
| 3143 | - sqlite3_str_append(p->pOut, rowSep, szRowSep); | |
| 3144 | - } | |
| 3145 | - } | |
| 3201 | + qrfColumnSeparator(p->pOut, &data, colSep, szColSep, | |
| 3202 | + rowSep, szRowSep); | |
| 3146 | 3203 | }else if( data.bMultiRow ){ |
| 3147 | 3204 | qrfRTrim(p->pOut); |
| 3148 | 3205 | sqlite3_str_append(p->pOut, "\n", 1); |
| 3149 | 3206 | } |
| 3150 | 3207 | break; |
| @@ -3152,20 +3209,39 @@ | ||
| 3152 | 3209 | } |
| 3153 | 3210 | } |
| 3154 | 3211 | } |
| 3155 | 3212 | |
| 3156 | 3213 | /* Draw the line across the bottom of the table */ |
| 3157 | - if( p->spec.bBorder!=QRF_No ){ | |
| 3214 | + if( p->spec.bBorder!=QRF_No || p->nRow==0 ){ | |
| 3158 | 3215 | switch( p->spec.eStyle ){ |
| 3159 | 3216 | case QRF_STYLE_Box: |
| 3160 | - qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0); | |
| 3217 | + if( p->nRow>0 ){ | |
| 3218 | + qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0); | |
| 3219 | + }else{ | |
| 3220 | + qrfBoxSeparator(p->pOut, &data, DBL_12, DBL_124, DBL_14, 1); | |
| 3221 | + } | |
| 3161 | 3222 | break; |
| 3162 | 3223 | case QRF_STYLE_Table: |
| 3163 | 3224 | qrfRowSeparator(p->pOut, &data, '+'); |
| 3164 | 3225 | break; |
| 3226 | + case QRF_STYLE_Markdown: | |
| 3227 | + if( p->nRow==0 ){ | |
| 3228 | + qrfRowSeparator(p->pOut, &data, '|'); | |
| 3229 | + } | |
| 3230 | + break; | |
| 3231 | + case QRF_STYLE_Column: | |
| 3232 | + if( p->nRow==0 ){ | |
| 3233 | + qrfColumnSeparator(p->pOut, &data, colSep, szColSep, | |
| 3234 | + rowSep, szRowSep); | |
| 3235 | + } | |
| 3236 | + break; | |
| 3165 | 3237 | } |
| 3166 | 3238 | } |
| 3239 | + if( p->spec.bRowCount==QRF_Yes ){ | |
| 3240 | + sqlite3_int64 n = p->nRow; | |
| 3241 | + sqlite3_str_appendf(p->pOut, "(%lld row%s)\n", n, n==1 ? "" : "s"); | |
| 3242 | + } | |
| 3167 | 3243 | qrfWrite(p); |
| 3168 | 3244 | |
| 3169 | 3245 | qrfColDataFree(&data); |
| 3170 | 3246 | return; |
| 3171 | 3247 | } |
| @@ -3412,10 +3488,49 @@ | ||
| 3412 | 3488 | sqlite3_str_append(p->pOut, ":", 1); |
| 3413 | 3489 | qrfRenderValue(p, p->pOut, i); |
| 3414 | 3490 | } |
| 3415 | 3491 | qrfWrite(p); |
| 3416 | 3492 | } |
| 3493 | + | |
| 3494 | +/* | |
| 3495 | +** Render a title row (a row containing column names) if the spec | |
| 3496 | +** calls for one and if it makes sense for the eStyle. Title rows | |
| 3497 | +** do not make sense for some eStyles, such as QRF_STYLE_Off, | |
| 3498 | +** QRF_STYLE_Count, QRF_STYLE_Json, and similar. | |
| 3499 | +*/ | |
| 3500 | +static void qrfSimpleTitle(Qrf *p){ | |
| 3501 | + assert( p->nRow==0 ); | |
| 3502 | + assert( p->spec.bTitles>=QRF_Yes ); | |
| 3503 | + switch( p->spec.eStyle ){ | |
| 3504 | + case QRF_STYLE_Html: { | |
| 3505 | + int i; | |
| 3506 | + sqlite3_str_append(p->pOut, "<tr>", 4); | |
| 3507 | + for(i=0; i<p->nCol; i++){ | |
| 3508 | + const char *zCName = sqlite3_column_name(p->pStmt, i); | |
| 3509 | + sqlite3_str_append(p->pOut, "\n<th>", 5); | |
| 3510 | + qrfEncodeText(p, p->pOut, zCName); | |
| 3511 | + } | |
| 3512 | + sqlite3_str_append(p->pOut, "\n</tr>\n", 7); | |
| 3513 | + break; | |
| 3514 | + } | |
| 3515 | + case QRF_STYLE_Quote: | |
| 3516 | + case QRF_STYLE_List: { | |
| 3517 | + int i; | |
| 3518 | + int saved_eText = p->spec.eText; | |
| 3519 | + p->spec.eText = p->spec.eTitle; | |
| 3520 | + for(i=0; i<p->nCol; i++){ | |
| 3521 | + const char *zCName = sqlite3_column_name(p->pStmt, i); | |
| 3522 | + if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); | |
| 3523 | + qrfEncodeText(p, p->pOut, zCName); | |
| 3524 | + } | |
| 3525 | + sqlite3_str_appendall(p->pOut, p->spec.zRowSep); | |
| 3526 | + qrfWrite(p); | |
| 3527 | + p->spec.eText = saved_eText; | |
| 3528 | + break; | |
| 3529 | + } | |
| 3530 | + } | |
| 3531 | +} | |
| 3417 | 3532 | |
| 3418 | 3533 | /* |
| 3419 | 3534 | ** Render a single row of output for non-columnar styles - any |
| 3420 | 3535 | ** style that lets us render row by row as the content is received |
| 3421 | 3536 | ** from the query. |
| @@ -3445,25 +3560,19 @@ | ||
| 3445 | 3560 | } |
| 3446 | 3561 | qrfOneJsonRow(p); |
| 3447 | 3562 | break; |
| 3448 | 3563 | } |
| 3449 | 3564 | case QRF_STYLE_Html: { |
| 3450 | - if( p->nRow==0 && p->spec.bTitles==QRF_Yes ){ | |
| 3451 | - sqlite3_str_append(p->pOut, "<TR>", 4); | |
| 3452 | - for(i=0; i<p->nCol; i++){ | |
| 3453 | - const char *zCName = sqlite3_column_name(p->pStmt, i); | |
| 3454 | - sqlite3_str_append(p->pOut, "\n<TH>", 5); | |
| 3455 | - qrfEncodeText(p, p->pOut, zCName); | |
| 3456 | - } | |
| 3457 | - sqlite3_str_append(p->pOut, "\n</TR>\n", 7); | |
| 3458 | - } | |
| 3459 | - sqlite3_str_append(p->pOut, "<TR>", 4); | |
| 3460 | - for(i=0; i<p->nCol; i++){ | |
| 3461 | - sqlite3_str_append(p->pOut, "\n<TD>", 5); | |
| 3565 | + if( p->nRow==0 && p->spec.bTitles>=QRF_Yes ){ | |
| 3566 | + qrfSimpleTitle(p); | |
| 3567 | + } | |
| 3568 | + sqlite3_str_append(p->pOut, "<tr>", 4); | |
| 3569 | + for(i=0; i<p->nCol; i++){ | |
| 3570 | + sqlite3_str_append(p->pOut, "\n<td>", 5); | |
| 3462 | 3571 | qrfRenderValue(p, p->pOut, i); |
| 3463 | 3572 | } |
| 3464 | - sqlite3_str_append(p->pOut, "\n</TR>\n", 7); | |
| 3573 | + sqlite3_str_append(p->pOut, "\n</tr>\n", 7); | |
| 3465 | 3574 | qrfWrite(p); |
| 3466 | 3575 | break; |
| 3467 | 3576 | } |
| 3468 | 3577 | case QRF_STYLE_Insert: { |
| 3469 | 3578 | unsigned int mxIns = p->spec.nMultiInsert; |
| @@ -3476,11 +3585,11 @@ | ||
| 3476 | 3585 | if( qrf_need_quote(p->spec.zTableName) ){ |
| 3477 | 3586 | sqlite3_str_appendf(p->pOut,"INSERT INTO \"%w\"",p->spec.zTableName); |
| 3478 | 3587 | }else{ |
| 3479 | 3588 | sqlite3_str_appendf(p->pOut,"INSERT INTO %s",p->spec.zTableName); |
| 3480 | 3589 | } |
| 3481 | - if( p->spec.bTitles==QRF_Yes ){ | |
| 3590 | + if( p->spec.bTitles>=QRF_Yes ){ | |
| 3482 | 3591 | for(i=0; i<p->nCol; i++){ |
| 3483 | 3592 | const char *zCName = sqlite3_column_name(p->pStmt, i); |
| 3484 | 3593 | if( qrf_need_quote(zCName) ){ |
| 3485 | 3594 | sqlite3_str_appendf(p->pOut, "%c\"%w\"", |
| 3486 | 3595 | i==0 ? '(' : ',', zCName); |
| @@ -3576,21 +3685,12 @@ | ||
| 3576 | 3685 | if( zEqpLine[0]=='-' ) qrfEqpRender(p, 0); |
| 3577 | 3686 | qrfEqpAppend(p, iEqpId, iParentId, zEqpLine); |
| 3578 | 3687 | break; |
| 3579 | 3688 | } |
| 3580 | 3689 | default: { /* QRF_STYLE_List */ |
| 3581 | - if( p->nRow==0 && p->spec.bTitles==QRF_Yes ){ | |
| 3582 | - int saved_eText = p->spec.eText; | |
| 3583 | - p->spec.eText = p->spec.eTitle; | |
| 3584 | - for(i=0; i<p->nCol; i++){ | |
| 3585 | - const char *zCName = sqlite3_column_name(p->pStmt, i); | |
| 3586 | - if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); | |
| 3587 | - qrfEncodeText(p, p->pOut, zCName); | |
| 3588 | - } | |
| 3589 | - sqlite3_str_appendall(p->pOut, p->spec.zRowSep); | |
| 3590 | - qrfWrite(p); | |
| 3591 | - p->spec.eText = saved_eText; | |
| 3690 | + if( p->nRow==0 && p->spec.bTitles>=QRF_Yes ){ | |
| 3691 | + qrfSimpleTitle(p); | |
| 3592 | 3692 | } |
| 3593 | 3693 | for(i=0; i<p->nCol; i++){ |
| 3594 | 3694 | if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); |
| 3595 | 3695 | qrfRenderValue(p, p->pOut, i); |
| 3596 | 3696 | } |
| @@ -3612,11 +3712,11 @@ | ||
| 3612 | 3712 | char **pzErr /* Write errors here */ |
| 3613 | 3713 | ){ |
| 3614 | 3714 | size_t sz; /* Size of pSpec[], based on pSpec->iVersion */ |
| 3615 | 3715 | memset(p, 0, sizeof(*p)); |
| 3616 | 3716 | p->pzErr = pzErr; |
| 3617 | - if( pSpec->iVersion>1 ){ | |
| 3717 | + if( pSpec->iVersion>2 ){ | |
| 3618 | 3718 | qrfError(p, SQLITE_ERROR, |
| 3619 | 3719 | "unusable sqlite3_qrf_spec.iVersion (%d)", |
| 3620 | 3720 | pSpec->iVersion); |
| 3621 | 3721 | return; |
| 3622 | 3722 | } |
| @@ -3640,10 +3740,13 @@ | ||
| 3640 | 3740 | if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto; |
| 3641 | 3741 | if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto; |
| 3642 | 3742 | if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto; |
| 3643 | 3743 | if( p->spec.eTitle>QRF_TEXT_Relaxed ) p->spec.eTitle = QRF_Auto; |
| 3644 | 3744 | if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto; |
| 3745 | + if( pSpec->iVersion<=1 ){ | |
| 3746 | + p->spec.bRowCount = 0; | |
| 3747 | + } | |
| 3645 | 3748 | qrf_reinit: |
| 3646 | 3749 | switch( p->spec.eStyle ){ |
| 3647 | 3750 | case QRF_Auto: { |
| 3648 | 3751 | switch( sqlite3_stmt_isexplain(pStmt) ){ |
| 3649 | 3752 | case 0: p->spec.eStyle = QRF_STYLE_Box; break; |
| @@ -3898,10 +4001,34 @@ | ||
| 3898 | 4001 | default: { |
| 3899 | 4002 | /* Non-columnar modes where the output can occur after each row |
| 3900 | 4003 | ** of result is received */ |
| 3901 | 4004 | while( qrf.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 3902 | 4005 | qrfOneSimpleRow(&qrf); |
| 4006 | + } | |
| 4007 | + if( qrf.nCol>0 && qrf.nRow==0 && qrf.spec.bTitles==QRF_Always ){ | |
| 4008 | + qrfSimpleTitle(&qrf); | |
| 4009 | + } | |
| 4010 | + if( qrf.nCol>0 && qrf.spec.bRowCount==QRF_Yes ){ | |
| 4011 | + const char *zPlural = qrf.nRow==1 ? "" : "s"; | |
| 4012 | + switch( qrf.spec.eStyle ){ | |
| 4013 | + case QRF_STYLE_Line: | |
| 4014 | + if( qrf.nRow>0 ) sqlite3_str_append(qrf.pOut, "\n", 1); | |
| 4015 | + /* Fall through */ | |
| 4016 | + case QRF_STYLE_Csv: | |
| 4017 | + case QRF_STYLE_List: | |
| 4018 | + case QRF_STYLE_Quote: | |
| 4019 | + sqlite3_str_appendf(qrf.pOut,"(%lld row%s)\n",qrf.nRow,zPlural); | |
| 4020 | + break; | |
| 4021 | + case QRF_STYLE_Html: | |
| 4022 | + sqlite3_str_appendf(qrf.pOut,"<!-- %lld row%s -->\n", | |
| 4023 | + qrf.nRow, zPlural); | |
| 4024 | + break; | |
| 4025 | + case QRF_STYLE_Insert: | |
| 4026 | + sqlite3_str_appendf(qrf.pOut,"/* %lld row%s inserted */\n", | |
| 4027 | + qrf.nRow, zPlural); | |
| 4028 | + break; | |
| 4029 | + } | |
| 3903 | 4030 | } |
| 3904 | 4031 | break; |
| 3905 | 4032 | } |
| 3906 | 4033 | } |
| 3907 | 4034 | qrfResetStmt(&qrf); |
| @@ -5839,10 +5966,13 @@ | ||
| 5839 | 5966 | } |
| 5840 | 5967 | |
| 5841 | 5968 | /* |
| 5842 | 5969 | ** Allocate a new Decimal object initialized to the text in zIn[]. |
| 5843 | 5970 | ** Return NULL if any kind of error occurs. |
| 5971 | +** | |
| 5972 | +** Note that zIn[] is not necessarily zero-terminated. Always | |
| 5973 | +** respect the boundary imposed by the n argument. | |
| 5844 | 5974 | */ |
| 5845 | 5975 | static Decimal *decimalNewFromText(const char *zIn, int n){ |
| 5846 | 5976 | Decimal *p = 0; |
| 5847 | 5977 | int i; |
| 5848 | 5978 | int iExp = 0; |
| @@ -5856,15 +5986,15 @@ | ||
| 5856 | 5986 | p->isNull = 0; |
| 5857 | 5987 | p->nDigit = 0; |
| 5858 | 5988 | p->nFrac = 0; |
| 5859 | 5989 | p->a = sqlite3_malloc64( n+1 ); |
| 5860 | 5990 | if( p->a==0 ) goto new_from_text_failed; |
| 5861 | - for(i=0; IsSpace(zIn[i]); i++){} | |
| 5862 | - if( zIn[i]=='-' ){ | |
| 5991 | + for(i=0; i<n && IsSpace(zIn[i]); i++){} | |
| 5992 | + if( i<n && zIn[i]=='-' ){ | |
| 5863 | 5993 | p->sign = 1; |
| 5864 | 5994 | i++; |
| 5865 | - }else if( zIn[i]=='+' ){ | |
| 5995 | + }else if( i<n && zIn[i]=='+' ){ | |
| 5866 | 5996 | i++; |
| 5867 | 5997 | } |
| 5868 | 5998 | while( i<n && zIn[i]=='0' ) i++; |
| 5869 | 5999 | while( i<n ){ |
| 5870 | 6000 | char c = zIn[i]; |
| @@ -6091,11 +6221,11 @@ | ||
| 6091 | 6221 | if( p->a[N]>=5 ){ |
| 6092 | 6222 | /* If all leading digits are 9, increase the number of digits |
| 6093 | 6223 | ** by adding a new 0 to the front */ |
| 6094 | 6224 | for(i=0; i<N && p->a[i]==9; i++){} |
| 6095 | 6225 | if( i==N ){ |
| 6096 | - decimal_expand(p, p->nDigit+1, 0); | |
| 6226 | + decimal_expand(p, p->nDigit+1, p->nFrac); | |
| 6097 | 6227 | if( p->oom ) return; |
| 6098 | 6228 | } |
| 6099 | 6229 | |
| 6100 | 6230 | /* Do the rounding */ |
| 6101 | 6231 | p->a[N-1]++; |
| @@ -6249,10 +6379,11 @@ | ||
| 6249 | 6379 | int nAddSig; |
| 6250 | 6380 | int nAddFrac; |
| 6251 | 6381 | signed char *a; |
| 6252 | 6382 | if( p==0 ) return; |
| 6253 | 6383 | nAddFrac = nFrac - p->nFrac; |
| 6384 | + assert( nAddFrac>=0 ); | |
| 6254 | 6385 | nAddSig = (nDigit - p->nDigit) - nAddFrac; |
| 6255 | 6386 | if( nAddFrac==0 && nAddSig==0 ) return; |
| 6256 | 6387 | if( nDigit+1>SQLITE_DECIMAL_MAX_DIGIT ){ p->oom = 1; return; } |
| 6257 | 6388 | a = sqlite3_realloc64(p->a, nDigit+1); |
| 6258 | 6389 | if( a==0 ){ |
| @@ -8256,10 +8387,20 @@ | ||
| 8256 | 8387 | if( r==(double)x ) return r; |
| 8257 | 8388 | if( r<(double)x ) x--; |
| 8258 | 8389 | return (double)x; |
| 8259 | 8390 | } |
| 8260 | 8391 | #endif |
| 8392 | + | |
| 8393 | +/* Convert a floating point value to its closest integer. Do so in | |
| 8394 | +** a way that avoids 'outside the range of representable values' warnings | |
| 8395 | +** from UBSAN. | |
| 8396 | +*/ | |
| 8397 | +static sqlite3_int64 seriesRealToI64(double r){ | |
| 8398 | + if( r<-9223372036854774784.0 ) return SMALLEST_INT64; | |
| 8399 | + if( r>+9223372036854774784.0 ) return LARGEST_INT64; | |
| 8400 | + return (sqlite3_int64)r; | |
| 8401 | +} | |
| 8261 | 8402 | |
| 8262 | 8403 | /* |
| 8263 | 8404 | ** This method is called to "rewind" the series_cursor object back |
| 8264 | 8405 | ** to the first row of output. This method is always called at least |
| 8265 | 8406 | ** once prior to any call to seriesColumn() or seriesRowid() or |
| @@ -8379,11 +8520,11 @@ | ||
| 8379 | 8520 | double r = sqlite3_value_double(argv[iArg++]); |
| 8380 | 8521 | if( r==seriesCeil(r) |
| 8381 | 8522 | && r>=(double)SMALLEST_INT64 |
| 8382 | 8523 | && r<=(double)LARGEST_INT64 |
| 8383 | 8524 | ){ |
| 8384 | - iMin = iMax = (sqlite3_int64)r; | |
| 8525 | + iMin = iMax = seriesRealToI64(r); | |
| 8385 | 8526 | }else{ |
| 8386 | 8527 | goto series_no_rows; |
| 8387 | 8528 | } |
| 8388 | 8529 | }else{ |
| 8389 | 8530 | iMin = iMax = sqlite3_value_int64(argv[iArg++]); |
| @@ -8395,14 +8536,11 @@ | ||
| 8395 | 8536 | if( r<=(double)SMALLEST_INT64 ){ |
| 8396 | 8537 | iMin = SMALLEST_INT64; |
| 8397 | 8538 | }else if( r>(double)LARGEST_INT64 ){ |
| 8398 | 8539 | goto series_no_rows; |
| 8399 | 8540 | }else{ |
| 8400 | - iMin = (sqlite3_int64)seriesCeil(r); | |
| 8401 | - if( iMin<0 && r>0.0 ){ | |
| 8402 | - iMin = LARGEST_INT64; | |
| 8403 | - } | |
| 8541 | + iMin = seriesRealToI64(seriesCeil(r)); | |
| 8404 | 8542 | if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){ |
| 8405 | 8543 | if( iMin==LARGEST_INT64 ) goto series_no_rows; |
| 8406 | 8544 | iMin++; |
| 8407 | 8545 | } |
| 8408 | 8546 | } |
| @@ -8423,14 +8561,12 @@ | ||
| 8423 | 8561 | if( r>=(double)LARGEST_INT64 ){ |
| 8424 | 8562 | iMax = LARGEST_INT64; |
| 8425 | 8563 | }else if( r<=(double)SMALLEST_INT64 ){ |
| 8426 | 8564 | goto series_no_rows; |
| 8427 | 8565 | }else{ |
| 8428 | - iMax = (sqlite3_int64)seriesFloor(r); | |
| 8429 | - if( iMax<0 && r>0.0 ){ | |
| 8430 | - iMax = LARGEST_INT64; | |
| 8431 | - }else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){ | |
| 8566 | + iMax = seriesRealToI64(seriesFloor(r)); | |
| 8567 | + if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){ | |
| 8432 | 8568 | if( iMax==SMALLEST_INT64 ) goto series_no_rows; |
| 8433 | 8569 | iMax--; |
| 8434 | 8570 | } |
| 8435 | 8571 | } |
| 8436 | 8572 | }else{ |
| @@ -10593,11 +10729,15 @@ | ||
| 10593 | 10729 | sqlite3_result_error_nomem(ctx); |
| 10594 | 10730 | return SQLITE_NOMEM; |
| 10595 | 10731 | } |
| 10596 | 10732 | } |
| 10597 | 10733 | |
| 10598 | - sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); | |
| 10734 | + if( n>0 ){ | |
| 10735 | + sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); | |
| 10736 | + }else{ | |
| 10737 | + sqlite3_result_null(ctx); | |
| 10738 | + } | |
| 10599 | 10739 | if( aBuf!=aStatic ) sqlite3_free(aBuf); |
| 10600 | 10740 | #endif |
| 10601 | 10741 | }else{ |
| 10602 | 10742 | readFileContents(ctx, pCur->zPath); |
| 10603 | 10743 | } |
| @@ -14457,11 +14597,11 @@ | ||
| 14457 | 14597 | eocd.nEntry = (u16)p->nEntry; |
| 14458 | 14598 | eocd.nEntryTotal = (u16)p->nEntry; |
| 14459 | 14599 | eocd.nSize = p->cds.n; |
| 14460 | 14600 | eocd.iOffset = p->body.n; |
| 14461 | 14601 | |
| 14462 | - nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ; | |
| 14602 | + nZip = (i64)p->body.n + (i64)p->cds.n + ZIPFILE_EOCD_FIXED_SZ; | |
| 14463 | 14603 | aZip = (u8*)sqlite3_malloc64(nZip); |
| 14464 | 14604 | if( aZip==0 ){ |
| 14465 | 14605 | sqlite3_result_error_nomem(pCtx); |
| 14466 | 14606 | }else{ |
| 14467 | 14607 | memcpy(aZip, p->body.a, p->body.n); |
| @@ -17584,16 +17724,19 @@ | ||
| 17584 | 17724 | } |
| 17585 | 17725 | iRet++; |
| 17586 | 17726 | } |
| 17587 | 17727 | } |
| 17588 | 17728 | else if( c=='[' ){ |
| 17589 | - while( z[iRet++]!=']' && z[iRet] ); | |
| 17729 | + while( z[iRet] && z[iRet++]!=']' ){} | |
| 17590 | 17730 | } |
| 17591 | 17731 | else if( (c>='A' && c<='Z') || (c>='a' && c<='z') ){ |
| 17592 | 17732 | while( (z[iRet]>='A' && z[iRet]<='Z') || (z[iRet]>='a' && z[iRet]<='z') ){ |
| 17593 | 17733 | iRet++; |
| 17594 | 17734 | } |
| 17735 | + } | |
| 17736 | + else if( c==0 ){ | |
| 17737 | + iRet = 0; | |
| 17595 | 17738 | } |
| 17596 | 17739 | |
| 17597 | 17740 | return iRet; |
| 17598 | 17741 | } |
| 17599 | 17742 | |
| @@ -18030,10 +18173,27 @@ | ||
| 18030 | 18173 | intckFinalize(p, pStmt); |
| 18031 | 18174 | |
| 18032 | 18175 | if( bAutoIndex ) intckExec(p, "PRAGMA automatic_index = 1"); |
| 18033 | 18176 | return zRet; |
| 18034 | 18177 | } |
| 18178 | + | |
| 18179 | +/* | |
| 18180 | +** Register or unregister special SQL functions implemented by intck. | |
| 18181 | +** | |
| 18182 | +** Normally the custom SQL functions used by intck are only available | |
| 18183 | +** in between sqlite3_intck_open() and sqlite3_intck_close(). However, | |
| 18184 | +** for testing and debugging, it is sometimes useful to make those | |
| 18185 | +** functions available generally. This routine provides as a separate | |
| 18186 | +** interface in order to provide that capability. | |
| 18187 | +*/ | |
| 18188 | +int sqlite3_intck_register(sqlite3 *db, int bCreate){ | |
| 18189 | + int rc; | |
| 18190 | + rc = sqlite3_create_function(db, "parse_create_index", | |
| 18191 | + 2, SQLITE_UTF8, 0, bCreate ? intckParseCreateIndexFunc : 0, 0, 0 | |
| 18192 | + ); | |
| 18193 | + return rc; | |
| 18194 | +} | |
| 18035 | 18195 | |
| 18036 | 18196 | /* |
| 18037 | 18197 | ** Open a new integrity-check object. |
| 18038 | 18198 | */ |
| 18039 | 18199 | int sqlite3_intck_open( |
| @@ -18052,13 +18212,11 @@ | ||
| 18052 | 18212 | }else{ |
| 18053 | 18213 | memset(pNew, 0, sizeof(*pNew)); |
| 18054 | 18214 | pNew->db = db; |
| 18055 | 18215 | pNew->zDb = (const char*)&pNew[1]; |
| 18056 | 18216 | memcpy(&pNew[1], zDb, nDb+1); |
| 18057 | - rc = sqlite3_create_function(db, "parse_create_index", | |
| 18058 | - 2, SQLITE_UTF8, 0, intckParseCreateIndexFunc, 0, 0 | |
| 18059 | - ); | |
| 18217 | + rc = sqlite3_intck_register(db, 1); | |
| 18060 | 18218 | if( rc!=SQLITE_OK ){ |
| 18061 | 18219 | sqlite3_intck_close(pNew); |
| 18062 | 18220 | pNew = 0; |
| 18063 | 18221 | } |
| 18064 | 18222 | } |
| @@ -18071,13 +18229,11 @@ | ||
| 18071 | 18229 | ** Free the integrity-check object. |
| 18072 | 18230 | */ |
| 18073 | 18231 | void sqlite3_intck_close(sqlite3_intck *p){ |
| 18074 | 18232 | if( p ){ |
| 18075 | 18233 | sqlite3_finalize(p->pCheck); |
| 18076 | - sqlite3_create_function( | |
| 18077 | - p->db, "parse_create_index", 1, SQLITE_UTF8, 0, 0, 0, 0 | |
| 18078 | - ); | |
| 18234 | + sqlite3_intck_register(p->db, 0); | |
| 18079 | 18235 | sqlite3_free(p->zObj); |
| 18080 | 18236 | sqlite3_free(p->zKey); |
| 18081 | 18237 | sqlite3_free(p->zTestSql); |
| 18082 | 18238 | sqlite3_free(p->zErr); |
| 18083 | 18239 | sqlite3_free(p->zMessage); |
| @@ -20355,16 +20511,128 @@ | ||
| 20355 | 20511 | ){ |
| 20356 | 20512 | int rc = SQLITE_OK; |
| 20357 | 20513 | SQLITE_EXTENSION_INIT2(pApi); |
| 20358 | 20514 | (void)pzErrMsg; /* Unused parameter */ |
| 20359 | 20515 | rc = sqlite3_create_function(db, "diskused", 1, |
| 20360 | - SQLITE_UTF8|SQLITE_INNOCUOUS, | |
| 20516 | + SQLITE_UTF8|SQLITE_DIRECTONLY, | |
| 20361 | 20517 | 0, diskusedFunc, 0, 0); |
| 20362 | 20518 | return rc; |
| 20363 | 20519 | } |
| 20364 | 20520 | |
| 20365 | 20521 | /************************* End ext/misc/diskused.c ********************/ |
| 20522 | +/************************* Begin ext/misc/strdup.c ******************/ | |
| 20523 | +/* | |
| 20524 | +** 2026-07-04 | |
| 20525 | +** | |
| 20526 | +** The author disclaims copyright to this source code. In place of | |
| 20527 | +** a legal notice, here is a blessing: | |
| 20528 | +** | |
| 20529 | +** May you do good and not evil. | |
| 20530 | +** May you find forgiveness for yourself and forgive others. | |
| 20531 | +** May you share freely, never taking more than you give. | |
| 20532 | +** | |
| 20533 | +****************************************************************************** | |
| 20534 | +** | |
| 20535 | +** Since this module was written (coincidentally) on the 250th anniversary | |
| 20536 | +** of the signing of the Declaration of Independence of The United States, | |
| 20537 | +** it seems fitting to quote from that document: | |
| 20538 | +** | |
| 20539 | +** We hold these truths to be self-evident, that all men are created | |
| 20540 | +** equal, that they are endowed by their Creator with certain unalienable | |
| 20541 | +** Rights, that among these are Life, Liberty and the pursuit of Happiness | |
| 20542 | +** - That to secure these rights, Governments are instituted among Men, | |
| 20543 | +** deriving their just powers from the consent of the governed,.... | |
| 20544 | +** | |
| 20545 | +** Two core ideas that (1) rights come from God and not from government, | |
| 20546 | +** and that (2) there should not be special privileged classes of people | |
| 20547 | +** were radical thoughts then, and are indeed disputed even today. Many | |
| 20548 | +** people still hold that human rights derive from the beneficence of | |
| 20549 | +** government and that certain classes of people have special rights and | |
| 20550 | +** privileges not available to all. Yet, were it not for the crazy ideas | |
| 20551 | +** espoused in the original Declaration of Independence, this software | |
| 20552 | +** project, and indeed most of modern technology, would not exist. | |
| 20553 | +** | |
| 20554 | +** Therefore let us give thanks for the bold leadership and vision | |
| 20555 | +** demonstrated by the authors of the American Revolution, 250 years ago | |
| 20556 | +** this day. | |
| 20557 | +** | |
| 20558 | +****************************************************************************** | |
| 20559 | +** | |
| 20560 | +** Implementation of the strdup() SQL function. strdup() makes a copy | |
| 20561 | +** of its argument (a string or a BLOB) into memory obtained directly | |
| 20562 | +** from system malloc() (not from sqlite3_malloc()) and sized exactly | |
| 20563 | +** to hold the string or BLOB. This is intended for testing purposes, | |
| 20564 | +** particularly testing with ASAN. This function serves no practical | |
| 20565 | +** purpose beyond testing and not not intended for production use. | |
| 20566 | +** | |
| 20567 | +** NULL, BLOB, and TEXT values come through as NULL, BLOB, and TEXT, | |
| 20568 | +** respectively. Numeric values are rendered as strings and come out | |
| 20569 | +** as text. | |
| 20570 | +*/ | |
| 20571 | +/* #include "sqlite3ext.h" */ | |
| 20572 | +SQLITE_EXTENSION_INIT1 | |
| 20573 | +#include <assert.h> | |
| 20574 | +#include <string.h> | |
| 20575 | +#include <stdlib.h> | |
| 20576 | + | |
| 20577 | +/* | |
| 20578 | +** Make a copy of a string or BLOB in memory obtained from malloc(). | |
| 20579 | +*/ | |
| 20580 | +static void strdupfunc( | |
| 20581 | + sqlite3_context *context, | |
| 20582 | + int argc, | |
| 20583 | + sqlite3_value **argv | |
| 20584 | +){ | |
| 20585 | + const unsigned char *zIn; | |
| 20586 | + int nIn; | |
| 20587 | + unsigned char *zOut; | |
| 20588 | + | |
| 20589 | + assert( argc==1 ); | |
| 20590 | + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; | |
| 20591 | + if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ | |
| 20592 | + zIn = (const unsigned char*)sqlite3_value_blob(argv[0]); | |
| 20593 | + nIn = sqlite3_value_bytes(argv[0]); | |
| 20594 | + zOut = malloc( nIn==0 ? 1 : nIn ); | |
| 20595 | + if( zOut==0 ){ | |
| 20596 | + sqlite3_result_error_nomem(context); | |
| 20597 | + return; | |
| 20598 | + } | |
| 20599 | + if( nIn>0 ) memcpy(zOut, zIn, nIn); | |
| 20600 | + sqlite3_result_blob(context, zOut, nIn, free); | |
| 20601 | + }else{ | |
| 20602 | + zIn = (const unsigned char*)sqlite3_value_text(argv[0]); | |
| 20603 | + if( zIn==0 ) return; | |
| 20604 | + nIn = (int)strlen((char*)zIn); | |
| 20605 | + zOut = malloc( nIn+1 ); | |
| 20606 | + if( zOut==0 ){ | |
| 20607 | + sqlite3_result_error_nomem(context); | |
| 20608 | + return; | |
| 20609 | + } | |
| 20610 | + memcpy(zOut, zIn, nIn); | |
| 20611 | + zOut[nIn] = 0; | |
| 20612 | + sqlite3_result_text64(context, (char*)zOut, nIn, free, | |
| 20613 | + SQLITE_UTF8_ZT); | |
| 20614 | + } | |
| 20615 | +} | |
| 20616 | + | |
| 20617 | +#ifdef _WIN32 | |
| 20618 | + | |
| 20619 | +#endif | |
| 20620 | +int sqlite3_strdup_init( | |
| 20621 | + sqlite3 *db, | |
| 20622 | + char **pzErrMsg, | |
| 20623 | + const sqlite3_api_routines *pApi | |
| 20624 | +){ | |
| 20625 | + int rc = SQLITE_OK; | |
| 20626 | + SQLITE_EXTENSION_INIT2(pApi); | |
| 20627 | + (void)pzErrMsg; /* Unused parameter */ | |
| 20628 | + rc = sqlite3_create_function(db, "strdup", 1, SQLITE_UTF8, | |
| 20629 | + 0, strdupfunc, 0, 0); | |
| 20630 | + return rc; | |
| 20631 | +} | |
| 20632 | + | |
| 20633 | +/************************* End ext/misc/strdup.c ********************/ | |
| 20366 | 20634 | |
| 20367 | 20635 | #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) |
| 20368 | 20636 | #define SQLITE_SHELL_HAVE_RECOVER 1 |
| 20369 | 20637 | #else |
| 20370 | 20638 | #define SQLITE_SHELL_HAVE_RECOVER 0 |
| @@ -24581,10 +24849,20 @@ | ||
| 24581 | 24849 | #endif |
| 24582 | 24850 | #ifdef SQLITE_SHELL_EXTSRC |
| 24583 | 24851 | # include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC) |
| 24584 | 24852 | #endif |
| 24585 | 24853 | |
| 24854 | +/* | |
| 24855 | +** Set the SQLITE_SHELL_EDITION to a YYYYMMDD date string and the | |
| 24856 | +** code will attempt to use defaults for the prompt and for the | |
| 24857 | +** initial output mode (and maybe other feature) that were for | |
| 24858 | +** the most recent version not newer than the specified date. | |
| 24859 | +*/ | |
| 24860 | +#ifndef SQLITE_SHELL_EDITION | |
| 24861 | +# define SQLITE_SHELL_EDITION 99991231 /* Use the latest if unspecified */ | |
| 24862 | +#endif | |
| 24863 | + | |
| 24586 | 24864 | #if defined(SQLITE_ENABLE_SESSION) |
| 24587 | 24865 | /* |
| 24588 | 24866 | ** State information for a single open session |
| 24589 | 24867 | */ |
| 24590 | 24868 | typedef struct OpenSession OpenSession; |
| @@ -24828,11 +25106,11 @@ | ||
| 24828 | 25106 | unsigned char eHdr; /* Default header encoding. */ |
| 24829 | 25107 | unsigned char eBlob; /* Default blob encoding. */ |
| 24830 | 25108 | unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */ |
| 24831 | 25109 | unsigned char eStyle; /* Underlying QRF style */ |
| 24832 | 25110 | unsigned char eCx; /* 0: other, 1: line, 2: columnar */ |
| 24833 | - unsigned char mFlg; /* Flags. 1=border-off 2=split-column */ | |
| 25111 | + unsigned char mFlg; /* Flags. 1=border-off 2=split-column 4=rowcount */ | |
| 24834 | 25112 | }; |
| 24835 | 25113 | |
| 24836 | 25114 | /* String constants used by built-in modes */ |
| 24837 | 25115 | static const char *aModeStr[] = |
| 24838 | 25116 | /* 0 1 2 3 4 5 6 7 8 */ |
| @@ -24841,45 +25119,45 @@ | ||
| 24841 | 25119 | /* 9 10 11 12 13 */ |
| 24842 | 25120 | |
| 24843 | 25121 | static const ModeInfo aModeInfo[] = { |
| 24844 | 25122 | /* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */ |
| 24845 | 25123 | { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0, 0 }, |
| 24846 | - { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2, 0 }, | |
| 25124 | + { "box", 0, 0, 9, 1, 1, 0, 3, 1, 2, 0 }, | |
| 24847 | 25125 | { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0, 0 }, |
| 24848 | - { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2, 0 }, | |
| 25126 | + { "column", 0, 0, 9, 1, 1, 0, 3, 2, 2, 0 }, | |
| 24849 | 25127 | { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, |
| 24850 | 25128 | { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0, 0 }, |
| 24851 | - { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 }, | |
| 25129 | + { "html", 0, 0, 9, 4, 4, 0, 3, 7, 0, 0 }, | |
| 24852 | 25130 | { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0, 0 }, |
| 24853 | 25131 | { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0, 0 }, |
| 24854 | 25132 | { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0, 0 }, |
| 24855 | 25133 | { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0, 0 }, |
| 24856 | 25134 | { "line", 13, 1, 9, 1, 1, 0, 0, 11, 1, 0 }, |
| 24857 | 25135 | { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0, 0 }, |
| 24858 | - { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2, 0 }, | |
| 25136 | + { "markdown", 0, 0, 9, 1, 1, 0, 3, 13, 2, 0 }, | |
| 24859 | 25137 | { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0, 0 }, |
| 24860 | - { "psql", 0, 0, 9, 1, 1, 0, 2, 19, 2, 1 }, | |
| 24861 | - { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2, 0 }, | |
| 25138 | + { "psql", 0, 0, 9, 1, 1, 0, 3, 19, 2, 5 }, | |
| 25139 | + { "qbox", 0, 0, 10, 2, 1, 0, 3, 1, 2, 0 }, | |
| 24862 | 25140 | { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0, 0 }, |
| 24863 | 25141 | { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2, 2 }, |
| 24864 | - { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2, 0 }, | |
| 25142 | + { "table", 0, 0, 9, 1, 1, 0, 3, 19, 2, 0 }, | |
| 24865 | 25143 | { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0, 0 }, |
| 24866 | 25144 | { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0, 0 }, |
| 24867 | - { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 } | |
| 24868 | -}; /* | / / | / / | | \ | |
| 24869 | - ** | / / | / / | | \_ 2: columnar | |
| 24870 | - ** Index into aModeStr[] | / / | | 1: line | |
| 24871 | - ** | / / | | 0: other | |
| 24872 | - ** | / / | \ | |
| 24873 | - ** text encoding |/ | show | \ | |
| 24874 | - ** v-------------------' | hdrs? | The QRF style | |
| 24875 | - ** 0: n/a blob | v-----' | |
| 24876 | - ** 1: plain v----------' 0: n/a | |
| 24877 | - ** 2: sql 0: auto 1: no | |
| 24878 | - ** 3: csv 1: as-text 2: yes | |
| 24879 | - ** 4: html 2: sql | |
| 24880 | - ** 5: c 3: hex | |
| 25145 | + { "www", 0, 0, 9, 4, 4, 0, 3, 7, 0, 0 } | |
| 25146 | +}; /* | / / | / / | | / \____ | |
| 25147 | + ** | / / | / / | | / | | |
| 25148 | + ** Index into aModeStr[] | / / | | 2: columnar | | |
| 25149 | + ** | / / | | 1: line | | |
| 25150 | + ** | / / | | 0: other | | |
| 25151 | + ** text encoding |/ | show | | | | |
| 25152 | + ** v-------------------' | hdrs? | The QRF style | | |
| 25153 | + ** 0: n/a blob | v-----' / | |
| 25154 | + ** 1: plain v----------' 0: n/a _________/ | |
| 25155 | + ** 2: sql 0: auto 1: no | | |
| 25156 | + ** 3: csv 1: as-text 2: yes 1: border-off | |
| 25157 | + ** 4: html 2: sql 3: always 2: split-column | |
| 25158 | + ** 5: c 3: hex 4: rowcount | |
| 24881 | 25159 | ** 6: json 4: c |
| 24882 | 25160 | ** 5: json |
| 24883 | 25161 | ** 6: size |
| 24884 | 25162 | ******************************************************************/ |
| 24885 | 25163 | |
| @@ -25162,11 +25440,11 @@ | ||
| 25162 | 25440 | */ |
| 25163 | 25441 | static char *local_getline(char *zLine, FILE *in){ |
| 25164 | 25442 | int nLine = zLine==0 ? 0 : 100; |
| 25165 | 25443 | int n = 0; |
| 25166 | 25444 | |
| 25167 | - while( 1 ){ | |
| 25445 | + while( seenInterrupt<2 ){ | |
| 25168 | 25446 | if( n+100>nLine ){ |
| 25169 | 25447 | if( nLine>=1073741773 ){ |
| 25170 | 25448 | free(zLine); |
| 25171 | 25449 | return 0; |
| 25172 | 25450 | } |
| @@ -25226,11 +25504,13 @@ | ||
| 25226 | 25504 | # define SQLITE_PS_APPDEF shellPromptAppDef |
| 25227 | 25505 | static const char *shellPromptAppDef(int c){ |
| 25228 | 25506 | switch( c ){ |
| 25229 | 25507 | /* The default main prompt string */ |
| 25230 | 25508 | case 1: |
| 25231 | -#if defined(SQLITE_PS1) | |
| 25509 | +#if SQLITE_SHELL_EDITION<20260423 | |
| 25510 | + return "sqlite> "; /* Legacy prompt for backwards compatibility */ | |
| 25511 | +#elif defined(SQLITE_PS1) | |
| 25232 | 25512 | return SQLITE_PS1; |
| 25233 | 25513 | #else |
| 25234 | 25514 | if( shellNoColor() ){ |
| 25235 | 25515 | return "/A-/v /f-> "; |
| 25236 | 25516 | }else{ |
| @@ -25238,11 +25518,13 @@ | ||
| 25238 | 25518 | } |
| 25239 | 25519 | #endif |
| 25240 | 25520 | |
| 25241 | 25521 | /* The default continuation prompt string */ |
| 25242 | 25522 | case 2: |
| 25243 | -#if defined(SQLITE_PS2) | |
| 25523 | +#if SQLITE_SHELL_EDITION<20260423 | |
| 25524 | + return " ...> "; /* Legacy continuation prompt */ | |
| 25525 | +#elif defined(SQLITE_PS2) | |
| 25244 | 25526 | return SQLITE_PS2; |
| 25245 | 25527 | #else |
| 25246 | 25528 | if( shellNoColor() ){ |
| 25247 | 25529 | return "/B/C-> "; |
| 25248 | 25530 | }else{ |
| @@ -25711,30 +25993,33 @@ | ||
| 25711 | 25993 | zResult = local_getline(zPrior, in); |
| 25712 | 25994 | }else{ |
| 25713 | 25995 | const char *zBase = prompt_string(p, bContinue!=0); |
| 25714 | 25996 | char *zPrompt = expand_prompt(p, zAll, zBase); |
| 25715 | 25997 | shell_check_oom(zPrompt); |
| 25716 | -#if SHELL_USE_LOCAL_GETLINE | |
| 25717 | - sputz(stdout, zPrompt); | |
| 25718 | - fflush(stdout); | |
| 25719 | - do{ | |
| 25720 | - zResult = local_getline(zPrior, stdin); | |
| 25721 | - zPrior = 0; | |
| 25722 | - /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ | |
| 25723 | - if( zResult==0 ) sqlite3_sleep(50); | |
| 25724 | - }while( zResult==0 && seenInterrupt>0 ); | |
| 25725 | -#else | |
| 25726 | - free(zPrior); | |
| 25727 | - zResult = shell_readline(zPrompt); | |
| 25728 | - while( zResult==0 ){ | |
| 25729 | - /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ | |
| 25730 | - sqlite3_sleep(50); | |
| 25731 | - if( seenInterrupt==0 ) break; | |
| 25732 | - zResult = shell_readline(""); | |
| 25733 | - } | |
| 25734 | - if( zResult && *zResult ) shell_add_history(zResult); | |
| 25735 | -#endif | |
| 25998 | +#if SHELL_CMDLINE_EDIT_AVAILABLE | |
| 25999 | + if( shellCmdLineEdit ){ | |
| 26000 | + free(zPrior); | |
| 26001 | + zResult = shell_readline(zPrompt); | |
| 26002 | + while( zResult==0 ){ | |
| 26003 | + /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ | |
| 26004 | + sqlite3_sleep(50); | |
| 26005 | + if( seenInterrupt==0 ) break; | |
| 26006 | + zResult = shell_readline(""); | |
| 26007 | + } | |
| 26008 | + if( zResult && *zResult ) shell_add_history(zResult); | |
| 26009 | + }else | |
| 26010 | +#endif | |
| 26011 | + { | |
| 26012 | + sputz(stdout, zPrompt); | |
| 26013 | + fflush(stdout); | |
| 26014 | + do{ | |
| 26015 | + zResult = local_getline(zPrior, stdin); | |
| 26016 | + zPrior = 0; | |
| 26017 | + /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ | |
| 26018 | + if( zResult==0 ) sqlite3_sleep(50); | |
| 26019 | + }while( zResult==0 && seenInterrupt>0 ); | |
| 26020 | + } | |
| 25736 | 26021 | sqlite3_free(zPrompt); |
| 25737 | 26022 | } |
| 25738 | 26023 | return zResult; |
| 25739 | 26024 | } |
| 25740 | 26025 | #endif /* !SQLITE_SHELL_FIDDLE */ |
| @@ -26307,11 +26592,11 @@ | ||
| 26307 | 26592 | free(p->spec.zColumnSep); |
| 26308 | 26593 | free(p->spec.zRowSep); |
| 26309 | 26594 | free(p->spec.zTableName); |
| 26310 | 26595 | free(p->spec.zNull); |
| 26311 | 26596 | memset(p, 0, sizeof(*p)); |
| 26312 | - p->spec.iVersion = 1; | |
| 26597 | + p->spec.iVersion = 2; | |
| 26313 | 26598 | p->autoExplain = autoExplain; |
| 26314 | 26599 | } |
| 26315 | 26600 | |
| 26316 | 26601 | /* |
| 26317 | 26602 | ** Duplicate Mode pSrc into pDest. pDest is assumed to be |
| @@ -26432,10 +26717,15 @@ | ||
| 26432 | 26717 | pM->spec.bSplitColumn = QRF_Yes; |
| 26433 | 26718 | pM->bAutoScreenWidth = 1; |
| 26434 | 26719 | }else{ |
| 26435 | 26720 | pM->spec.bSplitColumn = QRF_No; |
| 26436 | 26721 | } |
| 26722 | + if( pI->mFlg & 0x04 ){ | |
| 26723 | + pM->spec.bRowCount = QRF_Yes; | |
| 26724 | + }else{ | |
| 26725 | + pM->spec.bRowCount = QRF_No; | |
| 26726 | + } | |
| 26437 | 26727 | }else if( eMode>=MODE_USER && eMode-MODE_USER<p->nSavedModes ){ |
| 26438 | 26728 | modeFree(&p->mode); |
| 26439 | 26729 | modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode); |
| 26440 | 26730 | }else if( eMode==MODE_BATCH ){ |
| 26441 | 26731 | u8 mFlags = p->mode.mFlags; |
| @@ -26461,13 +26751,15 @@ | ||
| 26461 | 26751 | /* |
| 26462 | 26752 | ** Set the mode to the default. It assumed that the mode has |
| 26463 | 26753 | ** already been freed and zeroed prior to calling this routine. |
| 26464 | 26754 | */ |
| 26465 | 26755 | static void modeDefault(ShellState *p){ |
| 26466 | - p->mode.spec.iVersion = 1; | |
| 26756 | + p->mode.spec.iVersion = 2; | |
| 26467 | 26757 | p->mode.autoExplain = 1; |
| 26468 | - if( stdin_is_interactive || stdout_is_console ){ | |
| 26758 | + if( (stdin_is_interactive || stdout_is_console) | |
| 26759 | + && SQLITE_SHELL_EDITION>=20260409 | |
| 26760 | + ){ | |
| 26469 | 26761 | modeChange(p, MODE_TTY); |
| 26470 | 26762 | }else{ |
| 26471 | 26763 | modeChange(p, MODE_BATCH); |
| 26472 | 26764 | } |
| 26473 | 26765 | } |
| @@ -28827,10 +29119,11 @@ | ||
| 28827 | 29119 | " --quote ARG Enable/disable quoting of text. ARG can be\n" |
| 28828 | 29120 | " \"off\", \"on\", \"sql\", \"relaxed\", \"csv\", \"html\",\n" |
| 28829 | 29121 | " \"tcl\", or \"json\". \"off\" means show the text as-is.\n" |
| 28830 | 29122 | " \"on\" is an alias for \"sql\".\n" |
| 28831 | 29123 | " --reset Changes all mode settings back to their default.\n" |
| 29124 | +" --rowcount BOOLEAN Show \"(N rows)\" at the end of query results.\n" | |
| 28832 | 29125 | " --rowsep STRING Use STRING as the row separator\n" |
| 28833 | 29126 | " --sw|--screenwidth N Declare the screen width of the output device\n" |
| 28834 | 29127 | " to be N characters. An attempt may be made to\n" |
| 28835 | 29128 | " wrap output text to fit within this limit. Zero\n" |
| 28836 | 29129 | " means \"no limit\". Or N can be \"auto\" to set the\n" |
| @@ -28838,11 +29131,11 @@ | ||
| 28838 | 29131 | " --tablename NAME Set the name of the table for \"insert\" mode.\n" |
| 28839 | 29132 | " --tag NAME Save mode to the left as NAME.\n" |
| 28840 | 29133 | " --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON.\n" |
| 28841 | 29134 | " --title ARG Whether or not to show column headers, and if so\n" |
| 28842 | 29135 | " how to encode them. ARG can be \"off\", \"on\",\n" |
| 28843 | -" \"sql\", \"csv\", \"html\", \"tcl\", or \"json\".\n" | |
| 29136 | +" \"always\", \"sql\", \"csv\", \"html\", \"tcl\", or \"json\".\n" | |
| 28844 | 29137 | " --titlelimit N Limit the length of column titles to N characters.\n" |
| 28845 | 29138 | " -v|--verbose Verbose output\n" |
| 28846 | 29139 | " --widths LIST Set the columns widths for columnar modes. The\n" |
| 28847 | 29140 | " argument is a list of integers, one for each\n" |
| 28848 | 29141 | " column. A \"0\" width means use a dynamic width\n" |
| @@ -29544,10 +29837,11 @@ | ||
| 29544 | 29837 | sqlite3_base85_init(p->db, 0, 0); |
| 29545 | 29838 | sqlite3_regexp_init(p->db, 0, 0); |
| 29546 | 29839 | sqlite3_ieee_init(p->db, 0, 0); |
| 29547 | 29840 | sqlite3_series_init(p->db, 0, 0); |
| 29548 | 29841 | sqlite3_diskused_init(p->db, 0, 0); |
| 29842 | + sqlite3_strdup_init(p->db, 0, 0); | |
| 29549 | 29843 | #ifndef SQLITE_SHELL_FIDDLE |
| 29550 | 29844 | sqlite3_fileio_init(p->db, 0, 0); |
| 29551 | 29845 | sqlite3_completion_init(p->db, 0, 0); |
| 29552 | 29846 | #endif |
| 29553 | 29847 | #ifdef SQLITE_HAVE_ZLIB |
| @@ -32998,14 +33292,16 @@ | ||
| 32998 | 33292 | /* |
| 32999 | 33293 | ** This function computes what to show the user about the configured |
| 33000 | 33294 | ** titles (or column-names). Output is an integer between 0 and 3: |
| 33001 | 33295 | ** |
| 33002 | 33296 | ** 0: The titles do not matter. Never show anything. |
| 33003 | -** 1: Show "--titles off" | |
| 33004 | -** 2: Show "--titles on" | |
| 33005 | -** 3: Show "--title VALUE" where VALUE is an encoding method | |
| 33297 | +** 1: Show "--title off" | |
| 33298 | +** 2: Show "--title on" | |
| 33299 | +** 3: Show "--title always" | |
| 33300 | +** 4: Show "--title VALUE" where VALUE is an encoding method | |
| 33006 | 33301 | ** to use, one of: plain sql csv html tcl json |
| 33302 | +** 5: Show "--title VALUE" as in 3, followed by "--title always" | |
| 33007 | 33303 | ** |
| 33008 | 33304 | ** Inputs are: |
| 33009 | 33305 | ** |
| 33010 | 33306 | ** spec.bTitles (bT) Whether or not to show the titles |
| 33011 | 33307 | ** spec.eTitle (eT) The actual encoding to be used for titles |
| @@ -33038,11 +33334,27 @@ | ||
| 33038 | 33334 | if( eT!=eH ) v >>= 32; /* Encoding disagree in upper 4-bytes */ |
| 33039 | 33335 | if( bT!=bH ) v >>= 16; /* ON/OFF disagree in upper 2-byte pairs */ |
| 33040 | 33336 | if( bT<2 ) v >>= 8; /* ON in even bytes, OFF in odd bytes (1st byte 0) */ |
| 33041 | 33337 | if( !bAll ) v >>= 4; /* bAll values are in the lower half-byte */ |
| 33042 | 33338 | |
| 33043 | - return v & 3; /* Return the selected truth-table entry */ | |
| 33339 | + v &= 3; | |
| 33340 | + /* At this point v means: | |
| 33341 | + ** 0: The titles do not matter. Never show anything. | |
| 33342 | + ** 1: Show "--title off" | |
| 33343 | + ** 2: Show "--title on" | |
| 33344 | + ** 3: Show "--title VALUE" where VALUE is an encoding method | |
| 33345 | + ** to use, one of: plain sql csv html tcl json | |
| 33346 | + ** If bTitles is QRF_Always, convert 2->3, 3->5. If bTitles is not | |
| 33347 | + ** QRF_Always, convert 3->4. | |
| 33348 | + */ | |
| 33349 | + if( p->mode.spec.bTitles==QRF_Always ){ | |
| 33350 | + if( v==3 ) v = 5; | |
| 33351 | + if( v==2 ) v = 3; | |
| 33352 | + }else{ | |
| 33353 | + if( v==3 ) v = 4; | |
| 33354 | + } | |
| 33355 | + return v; | |
| 33044 | 33356 | } |
| 33045 | 33357 | |
| 33046 | 33358 | /* |
| 33047 | 33359 | ** DOT-COMMAND: .mode |
| 33048 | 33360 | ** |
| @@ -33086,10 +33398,11 @@ | ||
| 33086 | 33398 | ** --quote ARG Enable/disable quoting of text. ARG can be |
| 33087 | 33399 | ** "off", "on", "sql", "relaxed", "csv", "html", |
| 33088 | 33400 | ** "tcl", or "json". "off" means show the text as-is. |
| 33089 | 33401 | ** "on" is an alias for "sql". |
| 33090 | 33402 | ** --reset Changes all mode settings back to their default. |
| 33403 | +** --rowcount BOOLEAN Show "(N rows)" at the end of query results. | |
| 33091 | 33404 | ** --rowsep STRING Use STRING as the row separator |
| 33092 | 33405 | ** --sw|--screenwidth N Declare the screen width of the output device |
| 33093 | 33406 | ** to be N characters. An attempt may be made to |
| 33094 | 33407 | ** wrap output text to fit within this limit. Zero |
| 33095 | 33408 | ** means "no limit". Or N can be "auto" to set the |
| @@ -33097,11 +33410,11 @@ | ||
| 33097 | 33410 | ** --tablename NAME Set the name of the table for "insert" mode. |
| 33098 | 33411 | ** --tag NAME Save mode to the left as NAME. |
| 33099 | 33412 | ** --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON. |
| 33100 | 33413 | ** --title ARG Whether or not to show column headers, and if so |
| 33101 | 33414 | ** how to encode them. ARG can be "off", "on", |
| 33102 | -** "sql", "csv", "html", "tcl", or "json". | |
| 33415 | +** "always", "sql", "csv", "html", "tcl", or "json". | |
| 33103 | 33416 | ** --titlelimit N Limit the length of column titles to N characters. |
| 33104 | 33417 | ** -v|--verbose Verbose output |
| 33105 | 33418 | ** --widths LIST Set the columns widths for columnar modes. The |
| 33106 | 33419 | ** argument is a list of integers, one for each |
| 33107 | 33420 | ** column. A "0" width means use a dynamic width |
| @@ -33325,10 +33638,17 @@ | ||
| 33325 | 33638 | chng = 1; |
| 33326 | 33639 | }else if( optionMatch(z,"reset") ){ |
| 33327 | 33640 | int saved_eMode = p->mode.eMode; |
| 33328 | 33641 | modeFree(&p->mode); |
| 33329 | 33642 | modeChange(p, saved_eMode); |
| 33643 | + }else if( optionMatch(z,"rowcount") ){ | |
| 33644 | + if( i+1>=nArg ){ | |
| 33645 | + dotCmdError(p, i, "missing argument", 0); | |
| 33646 | + return 1; | |
| 33647 | + } | |
| 33648 | + p->mode.spec.bRowCount = booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; | |
| 33649 | + chng = 1; | |
| 33330 | 33650 | }else if( optionMatch(z,"screenwidth") || optionMatch(z,"sw") ){ |
| 33331 | 33651 | if( (++i)>=nArg ){ |
| 33332 | 33652 | dotCmdError(p, i-1, "missing argument", 0); |
| 33333 | 33653 | return 1; |
| 33334 | 33654 | } |
| @@ -33378,25 +33698,63 @@ | ||
| 33378 | 33698 | return 1; |
| 33379 | 33699 | } |
| 33380 | 33700 | p->mode.spec.bTextJsonb = booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; |
| 33381 | 33701 | chng = 1; |
| 33382 | 33702 | }else if( optionMatch(z,"titles") || optionMatch(z,"title") ){ |
| 33703 | + /* The --titles option controls two fields of the | |
| 33704 | + ** sqlite3_qrf_spec object: eTitle and bTitles. | |
| 33705 | + ** | |
| 33706 | + ** --titles eTitle bTitles | |
| 33707 | + ** -------- --------------- --------------------- | |
| 33708 | + ** "off" (unchanged) QRF_Off | |
| 33709 | + ** "on" (unchanged) QRF_On | |
| 33710 | + ** "always" (unchanged) QRF_Always | |
| 33711 | + ** "auto", (default) (default) | |
| 33712 | + ** "plain" QRF_TEXT_Plain QRF_Always or QRF_On | |
| 33713 | + ** "sql" QRF_TEXT_Sql QRF_Always or QRF_On | |
| 33714 | + ** "csv" QRF_TEXT_Csv QRF_Always or QRF_On | |
| 33715 | + ** "html" QRF_TEXT_Html QRF_Always or QRF_On | |
| 33716 | + ** "tcl" QRF_TEXT_Tcl QRF_Always or QRF_On | |
| 33717 | + ** "json" QRF_TEXT_Json QRF_Always or QRF_On | |
| 33718 | + ** | |
| 33719 | + ** This mapping is different from the -title option to the "format" | |
| 33720 | + ** method of the TCL interface. In this mapping: | |
| 33721 | + ** | |
| 33722 | + ** * "off", "on", and "always" affect only bTitles and leave | |
| 33723 | + ** eTitle unchanged | |
| 33724 | + ** | |
| 33725 | + ** * "auto" sets both bTitles and eTitle to the default value | |
| 33726 | + ** in aModeInfo[] according to the current --style. | |
| 33727 | + ** | |
| 33728 | + ** * "plain" through "json" set eTitle but leave bTitles | |
| 33729 | + ** unchanged if it is not QRF_Off. If bTitles is QRF_Off, | |
| 33730 | + ** then it is changed QRF_Always. | |
| 33731 | + */ | |
| 33383 | 33732 | char *zErr = 0; |
| 33384 | 33733 | if( i+1>=nArg ){ |
| 33385 | 33734 | dotCmdError(p, i, "missing argument", 0); |
| 33386 | 33735 | return 1; |
| 33387 | 33736 | } |
| 33388 | 33737 | k = pickStr(azArg[++i],&zErr, |
| 33389 | - "off","on","plain","sql","csv","html","tcl","json",""); | |
| 33390 | - /* 0 1 2 3 4 5 6 7 */ | |
| 33738 | + "off","on","always","auto","plain","sql","csv","html","tcl","json",""); | |
| 33739 | + /* 0 1 2 3 4 5 6 7 8 9 */ | |
| 33391 | 33740 | if( k<0 ){ |
| 33392 | 33741 | dotCmdError(p, i, "bad --titles value","%z", zErr); |
| 33393 | 33742 | return 1; |
| 33394 | 33743 | } |
| 33395 | - p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No; | |
| 33396 | 33744 | p->mode.mFlags &= ~MFLG_HDR; |
| 33397 | - p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr; | |
| 33745 | + if( k<=2 ){ | |
| 33746 | + p->mode.spec.bTitles = QRF_No+k; | |
| 33747 | + }else if( k==3 ){ | |
| 33748 | + p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr; | |
| 33749 | + p->mode.spec.bTitles = aModeInfo[p->mode.eMode].bHdr; | |
| 33750 | + }else{ | |
| 33751 | + p->mode.spec.eTitle = (k-4)+QRF_TEXT_Plain; | |
| 33752 | + if( p->mode.spec.bTitles==QRF_No ){ | |
| 33753 | + p->mode.spec.bTitles = QRF_Always; | |
| 33754 | + } | |
| 33755 | + } | |
| 33398 | 33756 | chng = 1; |
| 33399 | 33757 | }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){ |
| 33400 | 33758 | int nWidth = 0; |
| 33401 | 33759 | short int *aWidth; |
| 33402 | 33760 | const char *zW; |
| @@ -33547,10 +33905,16 @@ | ||
| 33547 | 33905 | if( bAll |
| 33548 | 33906 | || (pI->eText!=p->mode.spec.eText && (pI->eText>1 || p->mode.spec.eText>1)) |
| 33549 | 33907 | ){ |
| 33550 | 33908 | sqlite3_str_appendf(pDesc," --quote %s",qrfQuoteNames[p->mode.spec.eText]); |
| 33551 | 33909 | } |
| 33910 | + if( bAll | |
| 33911 | + || ((p->mode.spec.bRowCount==QRF_Yes) != ((pI->mFlg&4)!=0)) | |
| 33912 | + ){ | |
| 33913 | + sqlite3_str_appendf(pDesc," --rowcount %s", | |
| 33914 | + p->mode.spec.bRowCount==QRF_Yes ? "on" : "off"); | |
| 33915 | + } | |
| 33552 | 33916 | zSetting = aModeStr[pI->eRSep]; |
| 33553 | 33917 | if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zRowSep)!=0) ){ |
| 33554 | 33918 | sqlite3_str_appendf(pDesc, " --rowsep "); |
| 33555 | 33919 | append_c_string(pDesc, p->mode.spec.zRowSep); |
| 33556 | 33920 | } |
| @@ -33576,14 +33940,19 @@ | ||
| 33576 | 33940 | if( k==1 ){ |
| 33577 | 33941 | sqlite3_str_appendall(pDesc, " --titles off"); |
| 33578 | 33942 | }else if( k==2 ){ |
| 33579 | 33943 | sqlite3_str_appendall(pDesc, " --titles on"); |
| 33580 | 33944 | }else if( k==3 ){ |
| 33945 | + sqlite3_str_appendall(pDesc, " --titles always"); | |
| 33946 | + }else if( k>=4 ){ | |
| 33581 | 33947 | static const char *azTitle[] = |
| 33582 | 33948 | { "plain", "sql", "csv", "html", "tcl", "json"}; |
| 33583 | 33949 | sqlite3_str_appendf(pDesc, " --titles %s", |
| 33584 | 33950 | azTitle[p->mode.spec.eTitle-1]); |
| 33951 | + if( k==5 ){ | |
| 33952 | + sqlite3_str_appendf(pDesc, " --titles always"); | |
| 33953 | + } | |
| 33585 | 33954 | } |
| 33586 | 33955 | if( p->mode.spec.nWidth>0 && (bAll || pI->eCx==2) ){ |
| 33587 | 33956 | int ii; |
| 33588 | 33957 | const char *zSep = " --widths "; |
| 33589 | 33958 | for(ii=0; ii<p->mode.spec.nWidth; ii++){ |
| @@ -34901,15 +35270,19 @@ | ||
| 34901 | 35270 | } |
| 34902 | 35271 | }else |
| 34903 | 35272 | |
| 34904 | 35273 | if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){ |
| 34905 | 35274 | if( nArg==2 ){ |
| 34906 | - p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No; | |
| 35275 | + if( cli_strcmp(azArg[1],"always")==0 ){ | |
| 35276 | + p->mode.spec.bTitles = QRF_Always; | |
| 35277 | + }else{ | |
| 35278 | + p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No; | |
| 35279 | + } | |
| 34907 | 35280 | p->mode.mFlags |= MFLG_HDR; |
| 34908 | 35281 | p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr; |
| 34909 | 35282 | }else{ |
| 34910 | - eputz("Usage: .headers on|off\n"); | |
| 35283 | + eputz("Usage: .headers off|on|always\n"); | |
| 34911 | 35284 | rc = 1; |
| 34912 | 35285 | } |
| 34913 | 35286 | }else |
| 34914 | 35287 | |
| 34915 | 35288 | if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){ |
| @@ -35113,13 +35486,21 @@ | ||
| 35113 | 35486 | sqlite3_str_free(pSql); |
| 35114 | 35487 | }else |
| 35115 | 35488 | |
| 35116 | 35489 | if( c=='i' && cli_strncmp(azArg[0], "intck", n)==0 ){ |
| 35117 | 35490 | i64 iArg = 0; |
| 35491 | + open_db(p, 0); | |
| 35118 | 35492 | if( nArg==2 ){ |
| 35119 | 35493 | iArg = integerValue(azArg[1]); |
| 35120 | - if( iArg==0 ) iArg = -1; | |
| 35494 | + if( iArg==0 ){ | |
| 35495 | + if( cli_strcmp(azArg[1],"register")==0 ){ | |
| 35496 | + sqlite3_intck_register(p->db, 1); | |
| 35497 | + rc = 0; | |
| 35498 | + goto meta_command_exit; | |
| 35499 | + } | |
| 35500 | + iArg = -1; | |
| 35501 | + } | |
| 35121 | 35502 | } |
| 35122 | 35503 | if( (nArg!=1 && nArg!=2) || iArg<0 ){ |
| 35123 | 35504 | cli_printf(stderr,"%s","Usage: .intck STEPS_PER_UNLOCK\n"); |
| 35124 | 35505 | rc = 1; |
| 35125 | 35506 | goto meta_command_exit; |
| @@ -35167,10 +35548,11 @@ | ||
| 35167 | 35548 | { "attached", SQLITE_LIMIT_ATTACHED }, |
| 35168 | 35549 | { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, |
| 35169 | 35550 | { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, |
| 35170 | 35551 | { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, |
| 35171 | 35552 | { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, |
| 35553 | + { "schema", SQLITE_LIMIT_SCHEMA }, | |
| 35172 | 35554 | }; |
| 35173 | 35555 | int i, n2; |
| 35174 | 35556 | open_db(p, 0); |
| 35175 | 35557 | if( nArg==1 ){ |
| 35176 | 35558 | for(i=0; i<ArraySize(aLimit); i++){ |
| @@ -36493,11 +36875,12 @@ | ||
| 36493 | 36875 | azBool[(p->mode.mFlags & MFLG_ECHO)!=0]); |
| 36494 | 36876 | cli_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->mode.autoEQP&3]); |
| 36495 | 36877 | cli_printf(p->out, "%12.12s: %s\n","explain", |
| 36496 | 36878 | p->mode.autoExplain ? "auto" : "off"); |
| 36497 | 36879 | cli_printf(p->out, "%12.12s: %s\n","headers", |
| 36498 | - azBool[p->mode.spec.bTitles==QRF_Yes]); | |
| 36880 | + p->mode.spec.bTitles==QRF_Always ? "always" : | |
| 36881 | + azBool[p->mode.spec.bTitles==QRF_Yes]); | |
| 36499 | 36882 | if( p->mode.spec.eStyle==QRF_STYLE_Column |
| 36500 | 36883 | || p->mode.spec.eStyle==QRF_STYLE_Box |
| 36501 | 36884 | || p->mode.spec.eStyle==QRF_STYLE_Table |
| 36502 | 36885 | || p->mode.spec.eStyle==QRF_STYLE_Markdown |
| 36503 | 36886 | ){ |
| @@ -37860,10 +38243,11 @@ | ||
| 37860 | 38243 | " -ascii set '.mode ascii'\n" |
| 37861 | 38244 | " -bail stop after hitting an error\n" |
| 37862 | 38245 | " -batch force batch I/O\n" |
| 37863 | 38246 | " -box set '.mode box'\n" |
| 37864 | 38247 | " -cmd COMMAND run \"COMMAND\" before reading stdin\n" |
| 38248 | + " -cmdline-edit BOOL enable or disable command-line editing\n" | |
| 37865 | 38249 | " -column set '.mode column'\n" |
| 37866 | 38250 | " -csv set '.mode csv -limits off'\n" |
| 37867 | 38251 | #if !defined(SQLITE_OMIT_DESERIALIZE) |
| 37868 | 38252 | " -deserialize open the database using sqlite3_deserialize()\n" |
| 37869 | 38253 | #endif |
| @@ -38130,10 +38514,13 @@ | ||
| 38130 | 38514 | stdout_is_console = 1; |
| 38131 | 38515 | data.wasm.zDefaultDbName = "/fiddle.sqlite3"; |
| 38132 | 38516 | #else |
| 38133 | 38517 | stdin_is_interactive = isatty(0); |
| 38134 | 38518 | stdout_is_console = isatty(1); |
| 38519 | + if( !stdin_is_interactive || !stdout_is_console ){ | |
| 38520 | + shellCmdLineEdit = 0; | |
| 38521 | + } | |
| 38135 | 38522 | #endif |
| 38136 | 38523 | atexit(abnormalExit); |
| 38137 | 38524 | #ifdef SQLITE_DEBUG |
| 38138 | 38525 | mem_main_enter = sqlite3_memory_used(); |
| 38139 | 38526 | #endif |
| @@ -38377,10 +38764,12 @@ | ||
| 38377 | 38764 | }else if( cli_strcmp(z,"-safe")==0 ){ |
| 38378 | 38765 | /* no-op - catch this on the second pass */ |
| 38379 | 38766 | }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ |
| 38380 | 38767 | /* skip over the argument */ |
| 38381 | 38768 | i++; |
| 38769 | + }else if( cli_strcmp(z,"-cmdline-edit")==0 ){ | |
| 38770 | + shellCmdLineEdit = booleanValue(cmdline_option_value(argc,argv,++i)); | |
| 38382 | 38771 | }else if( cli_strcmp(z,"-test-argv")==0 ){ |
| 38383 | 38772 | /* Undocumented test option. Print the values in argv[] and exit. |
| 38384 | 38773 | ** Use this to verify that any translation of the argv[], for example |
| 38385 | 38774 | ** on Windows that receives wargv[] from the OS and must convert |
| 38386 | 38775 | ** to UTF8 prior to calling this routine. */ |
| @@ -38567,11 +38956,11 @@ | ||
| 38567 | 38956 | cmdline_option_value(argc,argv,++i)); |
| 38568 | 38957 | }else if( cli_strcmp(z,"-nullvalue")==0 ){ |
| 38569 | 38958 | modeSetStr(&data.mode.spec.zNull, |
| 38570 | 38959 | cmdline_option_value(argc,argv,++i)); |
| 38571 | 38960 | }else if( cli_strcmp(z,"-header")==0 ){ |
| 38572 | - data.mode.spec.bTitles = QRF_Yes; | |
| 38961 | + data.mode.spec.bTitles = QRF_Always; | |
| 38573 | 38962 | data.mode.mFlags |= MFLG_HDR; |
| 38574 | 38963 | }else if( cli_strcmp(z,"-noheader")==0 ){ |
| 38575 | 38964 | data.mode.spec.bTitles = QRF_No; |
| 38576 | 38965 | data.mode.mFlags |= MFLG_HDR; |
| 38577 | 38966 | }else if( cli_strcmp(z,"-echo")==0 ){ |
| @@ -38639,10 +39028,12 @@ | ||
| 38639 | 39028 | i++; |
| 38640 | 39029 | #ifdef SQLITE_ENABLE_MULTIPLEX |
| 38641 | 39030 | }else if( cli_strcmp(z,"-multiplex")==0 ){ |
| 38642 | 39031 | i++; |
| 38643 | 39032 | #endif |
| 39033 | + }else if( cli_strcmp(z,"-cmdline-edit")==0 ){ | |
| 39034 | + i+=2; | |
| 38644 | 39035 | }else if( cli_strcmp(z,"-help")==0 ){ |
| 38645 | 39036 | usage(1); |
| 38646 | 39037 | }else if( cli_strcmp(z,"-cmd")==0 ){ |
| 38647 | 39038 | /* Run commands that follow -cmd first and separately from commands |
| 38648 | 39039 | ** that simply appear on the command-line. This seems goofy. It would |
| @@ -38668,12 +39059,14 @@ | ||
| 38668 | 39059 | rc = 1; |
| 38669 | 39060 | goto shell_main_exit; |
| 38670 | 39061 | } |
| 38671 | 39062 | open_db(&data, OPEN_DB_ZIPFILE); |
| 38672 | 39063 | if( z[2] ){ |
| 39064 | + char *zSaved = argv[i]; | |
| 38673 | 39065 | argv[i] = &z[2]; |
| 38674 | 39066 | arDotCommand(&data, 1, argv+(i-1), argc-(i-1)); |
| 39067 | + argv[i] = zSaved; | |
| 38675 | 39068 | }else{ |
| 38676 | 39069 | arDotCommand(&data, 1, argv+i, argc-i); |
| 38677 | 39070 | } |
| 38678 | 39071 | readStdin = 0; |
| 38679 | 39072 | stdin_is_interactive = 0; |
| 38680 | 39073 |
| --- extsrc/shell.c | |
| +++ extsrc/shell.c | |
| @@ -23,10 +23,11 @@ | |
| 23 | ** ext/misc/shathree.c |
| 24 | ** ext/misc/sqlar.c |
| 25 | ** ext/misc/sqlite3_stdio.c |
| 26 | ** ext/misc/sqlite3_stdio.h |
| 27 | ** ext/misc/stmtrand.c |
| 28 | ** ext/misc/uint.c |
| 29 | ** ext/misc/vfstrace.c |
| 30 | ** ext/misc/windirent.h |
| 31 | ** ext/misc/zipfile.c |
| 32 | ** ext/qrf/qrf.c |
| @@ -205,28 +206,38 @@ | |
| 205 | # define shell_add_history(X) add_history(X) |
| 206 | # define shell_read_history(X) read_history(X) |
| 207 | # define shell_write_history(X) write_history(X) |
| 208 | # define shell_stifle_history(X) stifle_history(X) |
| 209 | # define shell_readline(X) readline(X) |
| 210 | |
| 211 | #elif HAVE_LINENOISE |
| 212 | |
| 213 | # include "linenoise.h" |
| 214 | # define shell_add_history(X) linenoiseHistoryAdd(X) |
| 215 | # define shell_read_history(X) linenoiseHistoryLoad(X) |
| 216 | # define shell_write_history(X) linenoiseHistorySave(X) |
| 217 | # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) |
| 218 | # define shell_readline(X) linenoise(X) |
| 219 | |
| 220 | #else |
| 221 | |
| 222 | # define shell_read_history(X) |
| 223 | # define shell_write_history(X) |
| 224 | # define shell_stifle_history(X) |
| 225 | |
| 226 | # define SHELL_USE_LOCAL_GETLINE 1 |
| 227 | #endif |
| 228 | |
| 229 | #ifndef deliberate_fall_through |
| 230 | /* Quiet some compilers about some of our intentional code. */ |
| 231 | # if defined(GCC_VERSION) && GCC_VERSION>=7000000 |
| 232 | # define deliberate_fall_through __attribute__((fallthrough)); |
| @@ -733,10 +744,12 @@ | |
| 733 | char *(*xRender)(void*,sqlite3_value*); /* Render a value */ |
| 734 | int (*xWrite)(void*,const char*,sqlite3_int64); /* Write output */ |
| 735 | void *pRenderArg; /* First argument to the xRender callback */ |
| 736 | void *pWriteArg; /* First argument to the xWrite callback */ |
| 737 | char **pzOutput; /* Storage location for output string */ |
| 738 | /* Additional fields may be added in the future */ |
| 739 | }; |
| 740 | |
| 741 | /* |
| 742 | ** Interfaces |
| @@ -761,11 +774,11 @@ | |
| 761 | #define QRF_STYLE_Column 2 /* One record per line in neat columns */ |
| 762 | #define QRF_STYLE_Count 3 /* Output only a count of the rows of output */ |
| 763 | #define QRF_STYLE_Csv 4 /* Comma-separated-value */ |
| 764 | #define QRF_STYLE_Eqp 5 /* Format EXPLAIN QUERY PLAN output */ |
| 765 | #define QRF_STYLE_Explain 6 /* EXPLAIN output */ |
| 766 | #define QRF_STYLE_Html 7 /* Generate an XHTML table */ |
| 767 | #define QRF_STYLE_Insert 8 /* Generate SQL "insert" statements */ |
| 768 | #define QRF_STYLE_Json 9 /* Output is a list of JSON objects */ |
| 769 | #define QRF_STYLE_JObject 10 /* Independent JSON objects for each row */ |
| 770 | #define QRF_STYLE_Line 11 /* One column per line. */ |
| 771 | #define QRF_STYLE_List 12 /* One record per line with a separator */ |
| @@ -821,10 +834,15 @@ | |
| 821 | #define QRF_SW_On 2 /* This setting is forced on */ |
| 822 | #define QRF_Auto 0 /* Alternate spelling for QRF_*_Auto */ |
| 823 | #define QRF_No 1 /* Alternate spelling for QRF_SW_Off */ |
| 824 | #define QRF_Yes 2 /* Alternate spelling for QRF_SW_On */ |
| 825 | |
| 826 | /* |
| 827 | ** Possible alignment values alignment settings |
| 828 | ** |
| 829 | ** Horizontal Vertial |
| 830 | ** ---------- -------- */ |
| @@ -2527,10 +2545,14 @@ | |
| 2527 | /* Doubled horizontal lines: */ |
| 2528 | #define DBL_24 "\342\225\220" /* U+2550 === */ |
| 2529 | #define DBL_123 "\342\225\236" /* U+255e |= */ |
| 2530 | #define DBL_134 "\342\225\241" /* U+2561 =| */ |
| 2531 | #define DBL_1234 "\342\225\252" /* U+256a =|= */ |
| 2532 | |
| 2533 | /* Draw horizontal line N characters long using unicode box |
| 2534 | ** characters |
| 2535 | */ |
| 2536 | static void qrfBoxLine(sqlite3_str *pOut, int N, int bDbl){ |
| @@ -2549,16 +2571,16 @@ | |
| 2549 | |
| 2550 | /* |
| 2551 | ** Draw a horizontal separator for a QRF_STYLE_Box table. |
| 2552 | */ |
| 2553 | static void qrfBoxSeparator( |
| 2554 | sqlite3_str *pOut, |
| 2555 | qrfColData *p, |
| 2556 | const char *zSep1, |
| 2557 | const char *zSep2, |
| 2558 | const char *zSep3, |
| 2559 | int bDbl |
| 2560 | ){ |
| 2561 | int i; |
| 2562 | if( p->nCol>0 ){ |
| 2563 | int useBorder = p->p->spec.bBorder!=QRF_No; |
| 2564 | if( useBorder ){ |
| @@ -2573,10 +2595,36 @@ | |
| 2573 | sqlite3_str_appendall(pOut, zSep3); |
| 2574 | } |
| 2575 | } |
| 2576 | sqlite3_str_append(pOut, "\n", 1); |
| 2577 | } |
| 2578 | |
| 2579 | /* |
| 2580 | ** Load into pData the default alignment for the body of a table. |
| 2581 | */ |
| 2582 | static void qrfLoadAlignment(qrfColData *pData, Qrf *p){ |
| @@ -2831,11 +2879,25 @@ | |
| 2831 | sqlite3_str *pStr; /* Temporary rendering */ |
| 2832 | qrfColData data; /* Columnar layout data */ |
| 2833 | int bRTrim; /* Trim trailing space */ |
| 2834 | |
| 2835 | rc = sqlite3_step(p->pStmt); |
| 2836 | if( rc!=SQLITE_ROW || nColumn==0 ){ |
| 2837 | return; /* No output */ |
| 2838 | } |
| 2839 | |
| 2840 | /* Initialize the data container */ |
| 2841 | memset(&data, 0, sizeof(data)); |
| @@ -2848,12 +2910,12 @@ | |
| 2848 | } |
| 2849 | memset(data.a, 0, nColumn*sizeof(struct qrfPerCol) ); |
| 2850 | if( qrfColDataEnlarge(&data) ) return; |
| 2851 | assert( data.az!=0 ); |
| 2852 | |
| 2853 | /* Load the column header names and all cell content into data */ |
| 2854 | if( p->spec.bTitles==QRF_Yes ){ |
| 2855 | unsigned char saved_eText = p->spec.eText; |
| 2856 | p->spec.eText = p->spec.eTitle; |
| 2857 | memset(data.abNum, 0, nColumn); |
| 2858 | for(i=0; i<nColumn; i++){ |
| 2859 | const char *z = (const char*)sqlite3_column_name(p->pStmt,i); |
| @@ -2874,13 +2936,14 @@ | |
| 2874 | data.n++; |
| 2875 | if( w>data.a[i].mxW ) data.a[i].mxW = w; |
| 2876 | if( nNL ) data.bMultiRow = 1; |
| 2877 | } |
| 2878 | p->spec.eText = saved_eText; |
| 2879 | p->nRow++; |
| 2880 | } |
| 2881 | do{ |
| 2882 | if( data.n+nColumn > data.nAlloc ){ |
| 2883 | if( qrfColDataEnlarge(&data) ) return; |
| 2884 | } |
| 2885 | for(i=0; i<nColumn; i++){ |
| 2886 | char *z; |
| @@ -2897,11 +2960,12 @@ | |
| 2897 | data.n++; |
| 2898 | if( w>data.a[i].mxW ) data.a[i].mxW = w; |
| 2899 | if( nNL ) data.bMultiRow = 1; |
| 2900 | } |
| 2901 | p->nRow++; |
| 2902 | }while( sqlite3_step(p->pStmt)==SQLITE_ROW && p->iErr==SQLITE_OK ); |
| 2903 | if( p->iErr ){ |
| 2904 | qrfColDataFree(&data); |
| 2905 | return; |
| 2906 | } |
| 2907 | |
| @@ -3105,11 +3169,11 @@ | |
| 3105 | /* Draw either (1) the separator between the title line and the body |
| 3106 | ** of the table, or (2) separators between individual rows of the table |
| 3107 | ** body. isTitleDataSeparator will be true if we are doing (1). |
| 3108 | */ |
| 3109 | if( (i==0 || data.bMultiRow) && i+nColumn<data.n ){ |
| 3110 | int isTitleDataSeparator = (i==0 && p->spec.bTitles==QRF_Yes); |
| 3111 | if( isTitleDataSeparator ){ |
| 3112 | qrfLoadAlignment(&data, p); |
| 3113 | } |
| 3114 | switch( p->spec.eStyle ){ |
| 3115 | case QRF_STYLE_Table: { |
| @@ -3132,19 +3196,12 @@ | |
| 3132 | } |
| 3133 | break; |
| 3134 | } |
| 3135 | case QRF_STYLE_Column: { |
| 3136 | if( isTitleDataSeparator ){ |
| 3137 | for(j=0; j<nColumn; j++){ |
| 3138 | sqlite3_str_appendchar(p->pOut, data.a[j].w, '-'); |
| 3139 | if( j<nColumn-1 ){ |
| 3140 | sqlite3_str_append(p->pOut, colSep, szColSep); |
| 3141 | }else{ |
| 3142 | qrfRTrim(p->pOut); |
| 3143 | sqlite3_str_append(p->pOut, rowSep, szRowSep); |
| 3144 | } |
| 3145 | } |
| 3146 | }else if( data.bMultiRow ){ |
| 3147 | qrfRTrim(p->pOut); |
| 3148 | sqlite3_str_append(p->pOut, "\n", 1); |
| 3149 | } |
| 3150 | break; |
| @@ -3152,20 +3209,39 @@ | |
| 3152 | } |
| 3153 | } |
| 3154 | } |
| 3155 | |
| 3156 | /* Draw the line across the bottom of the table */ |
| 3157 | if( p->spec.bBorder!=QRF_No ){ |
| 3158 | switch( p->spec.eStyle ){ |
| 3159 | case QRF_STYLE_Box: |
| 3160 | qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0); |
| 3161 | break; |
| 3162 | case QRF_STYLE_Table: |
| 3163 | qrfRowSeparator(p->pOut, &data, '+'); |
| 3164 | break; |
| 3165 | } |
| 3166 | } |
| 3167 | qrfWrite(p); |
| 3168 | |
| 3169 | qrfColDataFree(&data); |
| 3170 | return; |
| 3171 | } |
| @@ -3412,10 +3488,49 @@ | |
| 3412 | sqlite3_str_append(p->pOut, ":", 1); |
| 3413 | qrfRenderValue(p, p->pOut, i); |
| 3414 | } |
| 3415 | qrfWrite(p); |
| 3416 | } |
| 3417 | |
| 3418 | /* |
| 3419 | ** Render a single row of output for non-columnar styles - any |
| 3420 | ** style that lets us render row by row as the content is received |
| 3421 | ** from the query. |
| @@ -3445,25 +3560,19 @@ | |
| 3445 | } |
| 3446 | qrfOneJsonRow(p); |
| 3447 | break; |
| 3448 | } |
| 3449 | case QRF_STYLE_Html: { |
| 3450 | if( p->nRow==0 && p->spec.bTitles==QRF_Yes ){ |
| 3451 | sqlite3_str_append(p->pOut, "<TR>", 4); |
| 3452 | for(i=0; i<p->nCol; i++){ |
| 3453 | const char *zCName = sqlite3_column_name(p->pStmt, i); |
| 3454 | sqlite3_str_append(p->pOut, "\n<TH>", 5); |
| 3455 | qrfEncodeText(p, p->pOut, zCName); |
| 3456 | } |
| 3457 | sqlite3_str_append(p->pOut, "\n</TR>\n", 7); |
| 3458 | } |
| 3459 | sqlite3_str_append(p->pOut, "<TR>", 4); |
| 3460 | for(i=0; i<p->nCol; i++){ |
| 3461 | sqlite3_str_append(p->pOut, "\n<TD>", 5); |
| 3462 | qrfRenderValue(p, p->pOut, i); |
| 3463 | } |
| 3464 | sqlite3_str_append(p->pOut, "\n</TR>\n", 7); |
| 3465 | qrfWrite(p); |
| 3466 | break; |
| 3467 | } |
| 3468 | case QRF_STYLE_Insert: { |
| 3469 | unsigned int mxIns = p->spec.nMultiInsert; |
| @@ -3476,11 +3585,11 @@ | |
| 3476 | if( qrf_need_quote(p->spec.zTableName) ){ |
| 3477 | sqlite3_str_appendf(p->pOut,"INSERT INTO \"%w\"",p->spec.zTableName); |
| 3478 | }else{ |
| 3479 | sqlite3_str_appendf(p->pOut,"INSERT INTO %s",p->spec.zTableName); |
| 3480 | } |
| 3481 | if( p->spec.bTitles==QRF_Yes ){ |
| 3482 | for(i=0; i<p->nCol; i++){ |
| 3483 | const char *zCName = sqlite3_column_name(p->pStmt, i); |
| 3484 | if( qrf_need_quote(zCName) ){ |
| 3485 | sqlite3_str_appendf(p->pOut, "%c\"%w\"", |
| 3486 | i==0 ? '(' : ',', zCName); |
| @@ -3576,21 +3685,12 @@ | |
| 3576 | if( zEqpLine[0]=='-' ) qrfEqpRender(p, 0); |
| 3577 | qrfEqpAppend(p, iEqpId, iParentId, zEqpLine); |
| 3578 | break; |
| 3579 | } |
| 3580 | default: { /* QRF_STYLE_List */ |
| 3581 | if( p->nRow==0 && p->spec.bTitles==QRF_Yes ){ |
| 3582 | int saved_eText = p->spec.eText; |
| 3583 | p->spec.eText = p->spec.eTitle; |
| 3584 | for(i=0; i<p->nCol; i++){ |
| 3585 | const char *zCName = sqlite3_column_name(p->pStmt, i); |
| 3586 | if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); |
| 3587 | qrfEncodeText(p, p->pOut, zCName); |
| 3588 | } |
| 3589 | sqlite3_str_appendall(p->pOut, p->spec.zRowSep); |
| 3590 | qrfWrite(p); |
| 3591 | p->spec.eText = saved_eText; |
| 3592 | } |
| 3593 | for(i=0; i<p->nCol; i++){ |
| 3594 | if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); |
| 3595 | qrfRenderValue(p, p->pOut, i); |
| 3596 | } |
| @@ -3612,11 +3712,11 @@ | |
| 3612 | char **pzErr /* Write errors here */ |
| 3613 | ){ |
| 3614 | size_t sz; /* Size of pSpec[], based on pSpec->iVersion */ |
| 3615 | memset(p, 0, sizeof(*p)); |
| 3616 | p->pzErr = pzErr; |
| 3617 | if( pSpec->iVersion>1 ){ |
| 3618 | qrfError(p, SQLITE_ERROR, |
| 3619 | "unusable sqlite3_qrf_spec.iVersion (%d)", |
| 3620 | pSpec->iVersion); |
| 3621 | return; |
| 3622 | } |
| @@ -3640,10 +3740,13 @@ | |
| 3640 | if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto; |
| 3641 | if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto; |
| 3642 | if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto; |
| 3643 | if( p->spec.eTitle>QRF_TEXT_Relaxed ) p->spec.eTitle = QRF_Auto; |
| 3644 | if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto; |
| 3645 | qrf_reinit: |
| 3646 | switch( p->spec.eStyle ){ |
| 3647 | case QRF_Auto: { |
| 3648 | switch( sqlite3_stmt_isexplain(pStmt) ){ |
| 3649 | case 0: p->spec.eStyle = QRF_STYLE_Box; break; |
| @@ -3898,10 +4001,34 @@ | |
| 3898 | default: { |
| 3899 | /* Non-columnar modes where the output can occur after each row |
| 3900 | ** of result is received */ |
| 3901 | while( qrf.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 3902 | qrfOneSimpleRow(&qrf); |
| 3903 | } |
| 3904 | break; |
| 3905 | } |
| 3906 | } |
| 3907 | qrfResetStmt(&qrf); |
| @@ -5839,10 +5966,13 @@ | |
| 5839 | } |
| 5840 | |
| 5841 | /* |
| 5842 | ** Allocate a new Decimal object initialized to the text in zIn[]. |
| 5843 | ** Return NULL if any kind of error occurs. |
| 5844 | */ |
| 5845 | static Decimal *decimalNewFromText(const char *zIn, int n){ |
| 5846 | Decimal *p = 0; |
| 5847 | int i; |
| 5848 | int iExp = 0; |
| @@ -5856,15 +5986,15 @@ | |
| 5856 | p->isNull = 0; |
| 5857 | p->nDigit = 0; |
| 5858 | p->nFrac = 0; |
| 5859 | p->a = sqlite3_malloc64( n+1 ); |
| 5860 | if( p->a==0 ) goto new_from_text_failed; |
| 5861 | for(i=0; IsSpace(zIn[i]); i++){} |
| 5862 | if( zIn[i]=='-' ){ |
| 5863 | p->sign = 1; |
| 5864 | i++; |
| 5865 | }else if( zIn[i]=='+' ){ |
| 5866 | i++; |
| 5867 | } |
| 5868 | while( i<n && zIn[i]=='0' ) i++; |
| 5869 | while( i<n ){ |
| 5870 | char c = zIn[i]; |
| @@ -6091,11 +6221,11 @@ | |
| 6091 | if( p->a[N]>=5 ){ |
| 6092 | /* If all leading digits are 9, increase the number of digits |
| 6093 | ** by adding a new 0 to the front */ |
| 6094 | for(i=0; i<N && p->a[i]==9; i++){} |
| 6095 | if( i==N ){ |
| 6096 | decimal_expand(p, p->nDigit+1, 0); |
| 6097 | if( p->oom ) return; |
| 6098 | } |
| 6099 | |
| 6100 | /* Do the rounding */ |
| 6101 | p->a[N-1]++; |
| @@ -6249,10 +6379,11 @@ | |
| 6249 | int nAddSig; |
| 6250 | int nAddFrac; |
| 6251 | signed char *a; |
| 6252 | if( p==0 ) return; |
| 6253 | nAddFrac = nFrac - p->nFrac; |
| 6254 | nAddSig = (nDigit - p->nDigit) - nAddFrac; |
| 6255 | if( nAddFrac==0 && nAddSig==0 ) return; |
| 6256 | if( nDigit+1>SQLITE_DECIMAL_MAX_DIGIT ){ p->oom = 1; return; } |
| 6257 | a = sqlite3_realloc64(p->a, nDigit+1); |
| 6258 | if( a==0 ){ |
| @@ -8256,10 +8387,20 @@ | |
| 8256 | if( r==(double)x ) return r; |
| 8257 | if( r<(double)x ) x--; |
| 8258 | return (double)x; |
| 8259 | } |
| 8260 | #endif |
| 8261 | |
| 8262 | /* |
| 8263 | ** This method is called to "rewind" the series_cursor object back |
| 8264 | ** to the first row of output. This method is always called at least |
| 8265 | ** once prior to any call to seriesColumn() or seriesRowid() or |
| @@ -8379,11 +8520,11 @@ | |
| 8379 | double r = sqlite3_value_double(argv[iArg++]); |
| 8380 | if( r==seriesCeil(r) |
| 8381 | && r>=(double)SMALLEST_INT64 |
| 8382 | && r<=(double)LARGEST_INT64 |
| 8383 | ){ |
| 8384 | iMin = iMax = (sqlite3_int64)r; |
| 8385 | }else{ |
| 8386 | goto series_no_rows; |
| 8387 | } |
| 8388 | }else{ |
| 8389 | iMin = iMax = sqlite3_value_int64(argv[iArg++]); |
| @@ -8395,14 +8536,11 @@ | |
| 8395 | if( r<=(double)SMALLEST_INT64 ){ |
| 8396 | iMin = SMALLEST_INT64; |
| 8397 | }else if( r>(double)LARGEST_INT64 ){ |
| 8398 | goto series_no_rows; |
| 8399 | }else{ |
| 8400 | iMin = (sqlite3_int64)seriesCeil(r); |
| 8401 | if( iMin<0 && r>0.0 ){ |
| 8402 | iMin = LARGEST_INT64; |
| 8403 | } |
| 8404 | if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){ |
| 8405 | if( iMin==LARGEST_INT64 ) goto series_no_rows; |
| 8406 | iMin++; |
| 8407 | } |
| 8408 | } |
| @@ -8423,14 +8561,12 @@ | |
| 8423 | if( r>=(double)LARGEST_INT64 ){ |
| 8424 | iMax = LARGEST_INT64; |
| 8425 | }else if( r<=(double)SMALLEST_INT64 ){ |
| 8426 | goto series_no_rows; |
| 8427 | }else{ |
| 8428 | iMax = (sqlite3_int64)seriesFloor(r); |
| 8429 | if( iMax<0 && r>0.0 ){ |
| 8430 | iMax = LARGEST_INT64; |
| 8431 | }else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){ |
| 8432 | if( iMax==SMALLEST_INT64 ) goto series_no_rows; |
| 8433 | iMax--; |
| 8434 | } |
| 8435 | } |
| 8436 | }else{ |
| @@ -10593,11 +10729,15 @@ | |
| 10593 | sqlite3_result_error_nomem(ctx); |
| 10594 | return SQLITE_NOMEM; |
| 10595 | } |
| 10596 | } |
| 10597 | |
| 10598 | sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); |
| 10599 | if( aBuf!=aStatic ) sqlite3_free(aBuf); |
| 10600 | #endif |
| 10601 | }else{ |
| 10602 | readFileContents(ctx, pCur->zPath); |
| 10603 | } |
| @@ -14457,11 +14597,11 @@ | |
| 14457 | eocd.nEntry = (u16)p->nEntry; |
| 14458 | eocd.nEntryTotal = (u16)p->nEntry; |
| 14459 | eocd.nSize = p->cds.n; |
| 14460 | eocd.iOffset = p->body.n; |
| 14461 | |
| 14462 | nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ; |
| 14463 | aZip = (u8*)sqlite3_malloc64(nZip); |
| 14464 | if( aZip==0 ){ |
| 14465 | sqlite3_result_error_nomem(pCtx); |
| 14466 | }else{ |
| 14467 | memcpy(aZip, p->body.a, p->body.n); |
| @@ -17584,16 +17724,19 @@ | |
| 17584 | } |
| 17585 | iRet++; |
| 17586 | } |
| 17587 | } |
| 17588 | else if( c=='[' ){ |
| 17589 | while( z[iRet++]!=']' && z[iRet] ); |
| 17590 | } |
| 17591 | else if( (c>='A' && c<='Z') || (c>='a' && c<='z') ){ |
| 17592 | while( (z[iRet]>='A' && z[iRet]<='Z') || (z[iRet]>='a' && z[iRet]<='z') ){ |
| 17593 | iRet++; |
| 17594 | } |
| 17595 | } |
| 17596 | |
| 17597 | return iRet; |
| 17598 | } |
| 17599 | |
| @@ -18030,10 +18173,27 @@ | |
| 18030 | intckFinalize(p, pStmt); |
| 18031 | |
| 18032 | if( bAutoIndex ) intckExec(p, "PRAGMA automatic_index = 1"); |
| 18033 | return zRet; |
| 18034 | } |
| 18035 | |
| 18036 | /* |
| 18037 | ** Open a new integrity-check object. |
| 18038 | */ |
| 18039 | int sqlite3_intck_open( |
| @@ -18052,13 +18212,11 @@ | |
| 18052 | }else{ |
| 18053 | memset(pNew, 0, sizeof(*pNew)); |
| 18054 | pNew->db = db; |
| 18055 | pNew->zDb = (const char*)&pNew[1]; |
| 18056 | memcpy(&pNew[1], zDb, nDb+1); |
| 18057 | rc = sqlite3_create_function(db, "parse_create_index", |
| 18058 | 2, SQLITE_UTF8, 0, intckParseCreateIndexFunc, 0, 0 |
| 18059 | ); |
| 18060 | if( rc!=SQLITE_OK ){ |
| 18061 | sqlite3_intck_close(pNew); |
| 18062 | pNew = 0; |
| 18063 | } |
| 18064 | } |
| @@ -18071,13 +18229,11 @@ | |
| 18071 | ** Free the integrity-check object. |
| 18072 | */ |
| 18073 | void sqlite3_intck_close(sqlite3_intck *p){ |
| 18074 | if( p ){ |
| 18075 | sqlite3_finalize(p->pCheck); |
| 18076 | sqlite3_create_function( |
| 18077 | p->db, "parse_create_index", 1, SQLITE_UTF8, 0, 0, 0, 0 |
| 18078 | ); |
| 18079 | sqlite3_free(p->zObj); |
| 18080 | sqlite3_free(p->zKey); |
| 18081 | sqlite3_free(p->zTestSql); |
| 18082 | sqlite3_free(p->zErr); |
| 18083 | sqlite3_free(p->zMessage); |
| @@ -20355,16 +20511,128 @@ | |
| 20355 | ){ |
| 20356 | int rc = SQLITE_OK; |
| 20357 | SQLITE_EXTENSION_INIT2(pApi); |
| 20358 | (void)pzErrMsg; /* Unused parameter */ |
| 20359 | rc = sqlite3_create_function(db, "diskused", 1, |
| 20360 | SQLITE_UTF8|SQLITE_INNOCUOUS, |
| 20361 | 0, diskusedFunc, 0, 0); |
| 20362 | return rc; |
| 20363 | } |
| 20364 | |
| 20365 | /************************* End ext/misc/diskused.c ********************/ |
| 20366 | |
| 20367 | #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) |
| 20368 | #define SQLITE_SHELL_HAVE_RECOVER 1 |
| 20369 | #else |
| 20370 | #define SQLITE_SHELL_HAVE_RECOVER 0 |
| @@ -24581,10 +24849,20 @@ | |
| 24581 | #endif |
| 24582 | #ifdef SQLITE_SHELL_EXTSRC |
| 24583 | # include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC) |
| 24584 | #endif |
| 24585 | |
| 24586 | #if defined(SQLITE_ENABLE_SESSION) |
| 24587 | /* |
| 24588 | ** State information for a single open session |
| 24589 | */ |
| 24590 | typedef struct OpenSession OpenSession; |
| @@ -24828,11 +25106,11 @@ | |
| 24828 | unsigned char eHdr; /* Default header encoding. */ |
| 24829 | unsigned char eBlob; /* Default blob encoding. */ |
| 24830 | unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */ |
| 24831 | unsigned char eStyle; /* Underlying QRF style */ |
| 24832 | unsigned char eCx; /* 0: other, 1: line, 2: columnar */ |
| 24833 | unsigned char mFlg; /* Flags. 1=border-off 2=split-column */ |
| 24834 | }; |
| 24835 | |
| 24836 | /* String constants used by built-in modes */ |
| 24837 | static const char *aModeStr[] = |
| 24838 | /* 0 1 2 3 4 5 6 7 8 */ |
| @@ -24841,45 +25119,45 @@ | |
| 24841 | /* 9 10 11 12 13 */ |
| 24842 | |
| 24843 | static const ModeInfo aModeInfo[] = { |
| 24844 | /* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */ |
| 24845 | { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0, 0 }, |
| 24846 | { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2, 0 }, |
| 24847 | { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0, 0 }, |
| 24848 | { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2, 0 }, |
| 24849 | { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, |
| 24850 | { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0, 0 }, |
| 24851 | { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 }, |
| 24852 | { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0, 0 }, |
| 24853 | { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0, 0 }, |
| 24854 | { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0, 0 }, |
| 24855 | { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0, 0 }, |
| 24856 | { "line", 13, 1, 9, 1, 1, 0, 0, 11, 1, 0 }, |
| 24857 | { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0, 0 }, |
| 24858 | { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2, 0 }, |
| 24859 | { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0, 0 }, |
| 24860 | { "psql", 0, 0, 9, 1, 1, 0, 2, 19, 2, 1 }, |
| 24861 | { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2, 0 }, |
| 24862 | { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0, 0 }, |
| 24863 | { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2, 2 }, |
| 24864 | { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2, 0 }, |
| 24865 | { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0, 0 }, |
| 24866 | { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0, 0 }, |
| 24867 | { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 } |
| 24868 | }; /* | / / | / / | | \ |
| 24869 | ** | / / | / / | | \_ 2: columnar |
| 24870 | ** Index into aModeStr[] | / / | | 1: line |
| 24871 | ** | / / | | 0: other |
| 24872 | ** | / / | \ |
| 24873 | ** text encoding |/ | show | \ |
| 24874 | ** v-------------------' | hdrs? | The QRF style |
| 24875 | ** 0: n/a blob | v-----' |
| 24876 | ** 1: plain v----------' 0: n/a |
| 24877 | ** 2: sql 0: auto 1: no |
| 24878 | ** 3: csv 1: as-text 2: yes |
| 24879 | ** 4: html 2: sql |
| 24880 | ** 5: c 3: hex |
| 24881 | ** 6: json 4: c |
| 24882 | ** 5: json |
| 24883 | ** 6: size |
| 24884 | ******************************************************************/ |
| 24885 | |
| @@ -25162,11 +25440,11 @@ | |
| 25162 | */ |
| 25163 | static char *local_getline(char *zLine, FILE *in){ |
| 25164 | int nLine = zLine==0 ? 0 : 100; |
| 25165 | int n = 0; |
| 25166 | |
| 25167 | while( 1 ){ |
| 25168 | if( n+100>nLine ){ |
| 25169 | if( nLine>=1073741773 ){ |
| 25170 | free(zLine); |
| 25171 | return 0; |
| 25172 | } |
| @@ -25226,11 +25504,13 @@ | |
| 25226 | # define SQLITE_PS_APPDEF shellPromptAppDef |
| 25227 | static const char *shellPromptAppDef(int c){ |
| 25228 | switch( c ){ |
| 25229 | /* The default main prompt string */ |
| 25230 | case 1: |
| 25231 | #if defined(SQLITE_PS1) |
| 25232 | return SQLITE_PS1; |
| 25233 | #else |
| 25234 | if( shellNoColor() ){ |
| 25235 | return "/A-/v /f-> "; |
| 25236 | }else{ |
| @@ -25238,11 +25518,13 @@ | |
| 25238 | } |
| 25239 | #endif |
| 25240 | |
| 25241 | /* The default continuation prompt string */ |
| 25242 | case 2: |
| 25243 | #if defined(SQLITE_PS2) |
| 25244 | return SQLITE_PS2; |
| 25245 | #else |
| 25246 | if( shellNoColor() ){ |
| 25247 | return "/B/C-> "; |
| 25248 | }else{ |
| @@ -25711,30 +25993,33 @@ | |
| 25711 | zResult = local_getline(zPrior, in); |
| 25712 | }else{ |
| 25713 | const char *zBase = prompt_string(p, bContinue!=0); |
| 25714 | char *zPrompt = expand_prompt(p, zAll, zBase); |
| 25715 | shell_check_oom(zPrompt); |
| 25716 | #if SHELL_USE_LOCAL_GETLINE |
| 25717 | sputz(stdout, zPrompt); |
| 25718 | fflush(stdout); |
| 25719 | do{ |
| 25720 | zResult = local_getline(zPrior, stdin); |
| 25721 | zPrior = 0; |
| 25722 | /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ |
| 25723 | if( zResult==0 ) sqlite3_sleep(50); |
| 25724 | }while( zResult==0 && seenInterrupt>0 ); |
| 25725 | #else |
| 25726 | free(zPrior); |
| 25727 | zResult = shell_readline(zPrompt); |
| 25728 | while( zResult==0 ){ |
| 25729 | /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ |
| 25730 | sqlite3_sleep(50); |
| 25731 | if( seenInterrupt==0 ) break; |
| 25732 | zResult = shell_readline(""); |
| 25733 | } |
| 25734 | if( zResult && *zResult ) shell_add_history(zResult); |
| 25735 | #endif |
| 25736 | sqlite3_free(zPrompt); |
| 25737 | } |
| 25738 | return zResult; |
| 25739 | } |
| 25740 | #endif /* !SQLITE_SHELL_FIDDLE */ |
| @@ -26307,11 +26592,11 @@ | |
| 26307 | free(p->spec.zColumnSep); |
| 26308 | free(p->spec.zRowSep); |
| 26309 | free(p->spec.zTableName); |
| 26310 | free(p->spec.zNull); |
| 26311 | memset(p, 0, sizeof(*p)); |
| 26312 | p->spec.iVersion = 1; |
| 26313 | p->autoExplain = autoExplain; |
| 26314 | } |
| 26315 | |
| 26316 | /* |
| 26317 | ** Duplicate Mode pSrc into pDest. pDest is assumed to be |
| @@ -26432,10 +26717,15 @@ | |
| 26432 | pM->spec.bSplitColumn = QRF_Yes; |
| 26433 | pM->bAutoScreenWidth = 1; |
| 26434 | }else{ |
| 26435 | pM->spec.bSplitColumn = QRF_No; |
| 26436 | } |
| 26437 | }else if( eMode>=MODE_USER && eMode-MODE_USER<p->nSavedModes ){ |
| 26438 | modeFree(&p->mode); |
| 26439 | modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode); |
| 26440 | }else if( eMode==MODE_BATCH ){ |
| 26441 | u8 mFlags = p->mode.mFlags; |
| @@ -26461,13 +26751,15 @@ | |
| 26461 | /* |
| 26462 | ** Set the mode to the default. It assumed that the mode has |
| 26463 | ** already been freed and zeroed prior to calling this routine. |
| 26464 | */ |
| 26465 | static void modeDefault(ShellState *p){ |
| 26466 | p->mode.spec.iVersion = 1; |
| 26467 | p->mode.autoExplain = 1; |
| 26468 | if( stdin_is_interactive || stdout_is_console ){ |
| 26469 | modeChange(p, MODE_TTY); |
| 26470 | }else{ |
| 26471 | modeChange(p, MODE_BATCH); |
| 26472 | } |
| 26473 | } |
| @@ -28827,10 +29119,11 @@ | |
| 28827 | " --quote ARG Enable/disable quoting of text. ARG can be\n" |
| 28828 | " \"off\", \"on\", \"sql\", \"relaxed\", \"csv\", \"html\",\n" |
| 28829 | " \"tcl\", or \"json\". \"off\" means show the text as-is.\n" |
| 28830 | " \"on\" is an alias for \"sql\".\n" |
| 28831 | " --reset Changes all mode settings back to their default.\n" |
| 28832 | " --rowsep STRING Use STRING as the row separator\n" |
| 28833 | " --sw|--screenwidth N Declare the screen width of the output device\n" |
| 28834 | " to be N characters. An attempt may be made to\n" |
| 28835 | " wrap output text to fit within this limit. Zero\n" |
| 28836 | " means \"no limit\". Or N can be \"auto\" to set the\n" |
| @@ -28838,11 +29131,11 @@ | |
| 28838 | " --tablename NAME Set the name of the table for \"insert\" mode.\n" |
| 28839 | " --tag NAME Save mode to the left as NAME.\n" |
| 28840 | " --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON.\n" |
| 28841 | " --title ARG Whether or not to show column headers, and if so\n" |
| 28842 | " how to encode them. ARG can be \"off\", \"on\",\n" |
| 28843 | " \"sql\", \"csv\", \"html\", \"tcl\", or \"json\".\n" |
| 28844 | " --titlelimit N Limit the length of column titles to N characters.\n" |
| 28845 | " -v|--verbose Verbose output\n" |
| 28846 | " --widths LIST Set the columns widths for columnar modes. The\n" |
| 28847 | " argument is a list of integers, one for each\n" |
| 28848 | " column. A \"0\" width means use a dynamic width\n" |
| @@ -29544,10 +29837,11 @@ | |
| 29544 | sqlite3_base85_init(p->db, 0, 0); |
| 29545 | sqlite3_regexp_init(p->db, 0, 0); |
| 29546 | sqlite3_ieee_init(p->db, 0, 0); |
| 29547 | sqlite3_series_init(p->db, 0, 0); |
| 29548 | sqlite3_diskused_init(p->db, 0, 0); |
| 29549 | #ifndef SQLITE_SHELL_FIDDLE |
| 29550 | sqlite3_fileio_init(p->db, 0, 0); |
| 29551 | sqlite3_completion_init(p->db, 0, 0); |
| 29552 | #endif |
| 29553 | #ifdef SQLITE_HAVE_ZLIB |
| @@ -32998,14 +33292,16 @@ | |
| 32998 | /* |
| 32999 | ** This function computes what to show the user about the configured |
| 33000 | ** titles (or column-names). Output is an integer between 0 and 3: |
| 33001 | ** |
| 33002 | ** 0: The titles do not matter. Never show anything. |
| 33003 | ** 1: Show "--titles off" |
| 33004 | ** 2: Show "--titles on" |
| 33005 | ** 3: Show "--title VALUE" where VALUE is an encoding method |
| 33006 | ** to use, one of: plain sql csv html tcl json |
| 33007 | ** |
| 33008 | ** Inputs are: |
| 33009 | ** |
| 33010 | ** spec.bTitles (bT) Whether or not to show the titles |
| 33011 | ** spec.eTitle (eT) The actual encoding to be used for titles |
| @@ -33038,11 +33334,27 @@ | |
| 33038 | if( eT!=eH ) v >>= 32; /* Encoding disagree in upper 4-bytes */ |
| 33039 | if( bT!=bH ) v >>= 16; /* ON/OFF disagree in upper 2-byte pairs */ |
| 33040 | if( bT<2 ) v >>= 8; /* ON in even bytes, OFF in odd bytes (1st byte 0) */ |
| 33041 | if( !bAll ) v >>= 4; /* bAll values are in the lower half-byte */ |
| 33042 | |
| 33043 | return v & 3; /* Return the selected truth-table entry */ |
| 33044 | } |
| 33045 | |
| 33046 | /* |
| 33047 | ** DOT-COMMAND: .mode |
| 33048 | ** |
| @@ -33086,10 +33398,11 @@ | |
| 33086 | ** --quote ARG Enable/disable quoting of text. ARG can be |
| 33087 | ** "off", "on", "sql", "relaxed", "csv", "html", |
| 33088 | ** "tcl", or "json". "off" means show the text as-is. |
| 33089 | ** "on" is an alias for "sql". |
| 33090 | ** --reset Changes all mode settings back to their default. |
| 33091 | ** --rowsep STRING Use STRING as the row separator |
| 33092 | ** --sw|--screenwidth N Declare the screen width of the output device |
| 33093 | ** to be N characters. An attempt may be made to |
| 33094 | ** wrap output text to fit within this limit. Zero |
| 33095 | ** means "no limit". Or N can be "auto" to set the |
| @@ -33097,11 +33410,11 @@ | |
| 33097 | ** --tablename NAME Set the name of the table for "insert" mode. |
| 33098 | ** --tag NAME Save mode to the left as NAME. |
| 33099 | ** --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON. |
| 33100 | ** --title ARG Whether or not to show column headers, and if so |
| 33101 | ** how to encode them. ARG can be "off", "on", |
| 33102 | ** "sql", "csv", "html", "tcl", or "json". |
| 33103 | ** --titlelimit N Limit the length of column titles to N characters. |
| 33104 | ** -v|--verbose Verbose output |
| 33105 | ** --widths LIST Set the columns widths for columnar modes. The |
| 33106 | ** argument is a list of integers, one for each |
| 33107 | ** column. A "0" width means use a dynamic width |
| @@ -33325,10 +33638,17 @@ | |
| 33325 | chng = 1; |
| 33326 | }else if( optionMatch(z,"reset") ){ |
| 33327 | int saved_eMode = p->mode.eMode; |
| 33328 | modeFree(&p->mode); |
| 33329 | modeChange(p, saved_eMode); |
| 33330 | }else if( optionMatch(z,"screenwidth") || optionMatch(z,"sw") ){ |
| 33331 | if( (++i)>=nArg ){ |
| 33332 | dotCmdError(p, i-1, "missing argument", 0); |
| 33333 | return 1; |
| 33334 | } |
| @@ -33378,25 +33698,63 @@ | |
| 33378 | return 1; |
| 33379 | } |
| 33380 | p->mode.spec.bTextJsonb = booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; |
| 33381 | chng = 1; |
| 33382 | }else if( optionMatch(z,"titles") || optionMatch(z,"title") ){ |
| 33383 | char *zErr = 0; |
| 33384 | if( i+1>=nArg ){ |
| 33385 | dotCmdError(p, i, "missing argument", 0); |
| 33386 | return 1; |
| 33387 | } |
| 33388 | k = pickStr(azArg[++i],&zErr, |
| 33389 | "off","on","plain","sql","csv","html","tcl","json",""); |
| 33390 | /* 0 1 2 3 4 5 6 7 */ |
| 33391 | if( k<0 ){ |
| 33392 | dotCmdError(p, i, "bad --titles value","%z", zErr); |
| 33393 | return 1; |
| 33394 | } |
| 33395 | p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No; |
| 33396 | p->mode.mFlags &= ~MFLG_HDR; |
| 33397 | p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr; |
| 33398 | chng = 1; |
| 33399 | }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){ |
| 33400 | int nWidth = 0; |
| 33401 | short int *aWidth; |
| 33402 | const char *zW; |
| @@ -33547,10 +33905,16 @@ | |
| 33547 | if( bAll |
| 33548 | || (pI->eText!=p->mode.spec.eText && (pI->eText>1 || p->mode.spec.eText>1)) |
| 33549 | ){ |
| 33550 | sqlite3_str_appendf(pDesc," --quote %s",qrfQuoteNames[p->mode.spec.eText]); |
| 33551 | } |
| 33552 | zSetting = aModeStr[pI->eRSep]; |
| 33553 | if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zRowSep)!=0) ){ |
| 33554 | sqlite3_str_appendf(pDesc, " --rowsep "); |
| 33555 | append_c_string(pDesc, p->mode.spec.zRowSep); |
| 33556 | } |
| @@ -33576,14 +33940,19 @@ | |
| 33576 | if( k==1 ){ |
| 33577 | sqlite3_str_appendall(pDesc, " --titles off"); |
| 33578 | }else if( k==2 ){ |
| 33579 | sqlite3_str_appendall(pDesc, " --titles on"); |
| 33580 | }else if( k==3 ){ |
| 33581 | static const char *azTitle[] = |
| 33582 | { "plain", "sql", "csv", "html", "tcl", "json"}; |
| 33583 | sqlite3_str_appendf(pDesc, " --titles %s", |
| 33584 | azTitle[p->mode.spec.eTitle-1]); |
| 33585 | } |
| 33586 | if( p->mode.spec.nWidth>0 && (bAll || pI->eCx==2) ){ |
| 33587 | int ii; |
| 33588 | const char *zSep = " --widths "; |
| 33589 | for(ii=0; ii<p->mode.spec.nWidth; ii++){ |
| @@ -34901,15 +35270,19 @@ | |
| 34901 | } |
| 34902 | }else |
| 34903 | |
| 34904 | if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){ |
| 34905 | if( nArg==2 ){ |
| 34906 | p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No; |
| 34907 | p->mode.mFlags |= MFLG_HDR; |
| 34908 | p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr; |
| 34909 | }else{ |
| 34910 | eputz("Usage: .headers on|off\n"); |
| 34911 | rc = 1; |
| 34912 | } |
| 34913 | }else |
| 34914 | |
| 34915 | if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){ |
| @@ -35113,13 +35486,21 @@ | |
| 35113 | sqlite3_str_free(pSql); |
| 35114 | }else |
| 35115 | |
| 35116 | if( c=='i' && cli_strncmp(azArg[0], "intck", n)==0 ){ |
| 35117 | i64 iArg = 0; |
| 35118 | if( nArg==2 ){ |
| 35119 | iArg = integerValue(azArg[1]); |
| 35120 | if( iArg==0 ) iArg = -1; |
| 35121 | } |
| 35122 | if( (nArg!=1 && nArg!=2) || iArg<0 ){ |
| 35123 | cli_printf(stderr,"%s","Usage: .intck STEPS_PER_UNLOCK\n"); |
| 35124 | rc = 1; |
| 35125 | goto meta_command_exit; |
| @@ -35167,10 +35548,11 @@ | |
| 35167 | { "attached", SQLITE_LIMIT_ATTACHED }, |
| 35168 | { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, |
| 35169 | { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, |
| 35170 | { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, |
| 35171 | { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, |
| 35172 | }; |
| 35173 | int i, n2; |
| 35174 | open_db(p, 0); |
| 35175 | if( nArg==1 ){ |
| 35176 | for(i=0; i<ArraySize(aLimit); i++){ |
| @@ -36493,11 +36875,12 @@ | |
| 36493 | azBool[(p->mode.mFlags & MFLG_ECHO)!=0]); |
| 36494 | cli_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->mode.autoEQP&3]); |
| 36495 | cli_printf(p->out, "%12.12s: %s\n","explain", |
| 36496 | p->mode.autoExplain ? "auto" : "off"); |
| 36497 | cli_printf(p->out, "%12.12s: %s\n","headers", |
| 36498 | azBool[p->mode.spec.bTitles==QRF_Yes]); |
| 36499 | if( p->mode.spec.eStyle==QRF_STYLE_Column |
| 36500 | || p->mode.spec.eStyle==QRF_STYLE_Box |
| 36501 | || p->mode.spec.eStyle==QRF_STYLE_Table |
| 36502 | || p->mode.spec.eStyle==QRF_STYLE_Markdown |
| 36503 | ){ |
| @@ -37860,10 +38243,11 @@ | |
| 37860 | " -ascii set '.mode ascii'\n" |
| 37861 | " -bail stop after hitting an error\n" |
| 37862 | " -batch force batch I/O\n" |
| 37863 | " -box set '.mode box'\n" |
| 37864 | " -cmd COMMAND run \"COMMAND\" before reading stdin\n" |
| 37865 | " -column set '.mode column'\n" |
| 37866 | " -csv set '.mode csv -limits off'\n" |
| 37867 | #if !defined(SQLITE_OMIT_DESERIALIZE) |
| 37868 | " -deserialize open the database using sqlite3_deserialize()\n" |
| 37869 | #endif |
| @@ -38130,10 +38514,13 @@ | |
| 38130 | stdout_is_console = 1; |
| 38131 | data.wasm.zDefaultDbName = "/fiddle.sqlite3"; |
| 38132 | #else |
| 38133 | stdin_is_interactive = isatty(0); |
| 38134 | stdout_is_console = isatty(1); |
| 38135 | #endif |
| 38136 | atexit(abnormalExit); |
| 38137 | #ifdef SQLITE_DEBUG |
| 38138 | mem_main_enter = sqlite3_memory_used(); |
| 38139 | #endif |
| @@ -38377,10 +38764,12 @@ | |
| 38377 | }else if( cli_strcmp(z,"-safe")==0 ){ |
| 38378 | /* no-op - catch this on the second pass */ |
| 38379 | }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ |
| 38380 | /* skip over the argument */ |
| 38381 | i++; |
| 38382 | }else if( cli_strcmp(z,"-test-argv")==0 ){ |
| 38383 | /* Undocumented test option. Print the values in argv[] and exit. |
| 38384 | ** Use this to verify that any translation of the argv[], for example |
| 38385 | ** on Windows that receives wargv[] from the OS and must convert |
| 38386 | ** to UTF8 prior to calling this routine. */ |
| @@ -38567,11 +38956,11 @@ | |
| 38567 | cmdline_option_value(argc,argv,++i)); |
| 38568 | }else if( cli_strcmp(z,"-nullvalue")==0 ){ |
| 38569 | modeSetStr(&data.mode.spec.zNull, |
| 38570 | cmdline_option_value(argc,argv,++i)); |
| 38571 | }else if( cli_strcmp(z,"-header")==0 ){ |
| 38572 | data.mode.spec.bTitles = QRF_Yes; |
| 38573 | data.mode.mFlags |= MFLG_HDR; |
| 38574 | }else if( cli_strcmp(z,"-noheader")==0 ){ |
| 38575 | data.mode.spec.bTitles = QRF_No; |
| 38576 | data.mode.mFlags |= MFLG_HDR; |
| 38577 | }else if( cli_strcmp(z,"-echo")==0 ){ |
| @@ -38639,10 +39028,12 @@ | |
| 38639 | i++; |
| 38640 | #ifdef SQLITE_ENABLE_MULTIPLEX |
| 38641 | }else if( cli_strcmp(z,"-multiplex")==0 ){ |
| 38642 | i++; |
| 38643 | #endif |
| 38644 | }else if( cli_strcmp(z,"-help")==0 ){ |
| 38645 | usage(1); |
| 38646 | }else if( cli_strcmp(z,"-cmd")==0 ){ |
| 38647 | /* Run commands that follow -cmd first and separately from commands |
| 38648 | ** that simply appear on the command-line. This seems goofy. It would |
| @@ -38668,12 +39059,14 @@ | |
| 38668 | rc = 1; |
| 38669 | goto shell_main_exit; |
| 38670 | } |
| 38671 | open_db(&data, OPEN_DB_ZIPFILE); |
| 38672 | if( z[2] ){ |
| 38673 | argv[i] = &z[2]; |
| 38674 | arDotCommand(&data, 1, argv+(i-1), argc-(i-1)); |
| 38675 | }else{ |
| 38676 | arDotCommand(&data, 1, argv+i, argc-i); |
| 38677 | } |
| 38678 | readStdin = 0; |
| 38679 | stdin_is_interactive = 0; |
| 38680 |
| --- extsrc/shell.c | |
| +++ extsrc/shell.c | |
| @@ -23,10 +23,11 @@ | |
| 23 | ** ext/misc/shathree.c |
| 24 | ** ext/misc/sqlar.c |
| 25 | ** ext/misc/sqlite3_stdio.c |
| 26 | ** ext/misc/sqlite3_stdio.h |
| 27 | ** ext/misc/stmtrand.c |
| 28 | ** ext/misc/strdup.c |
| 29 | ** ext/misc/uint.c |
| 30 | ** ext/misc/vfstrace.c |
| 31 | ** ext/misc/windirent.h |
| 32 | ** ext/misc/zipfile.c |
| 33 | ** ext/qrf/qrf.c |
| @@ -205,28 +206,38 @@ | |
| 206 | # define shell_add_history(X) add_history(X) |
| 207 | # define shell_read_history(X) read_history(X) |
| 208 | # define shell_write_history(X) write_history(X) |
| 209 | # define shell_stifle_history(X) stifle_history(X) |
| 210 | # define shell_readline(X) readline(X) |
| 211 | # define SHELL_CMDLINE_EDIT_AVAILABLE 1 /* command-line editing available */ |
| 212 | |
| 213 | #elif HAVE_LINENOISE |
| 214 | |
| 215 | # include "linenoise.h" |
| 216 | # define shell_add_history(X) linenoiseHistoryAdd(X) |
| 217 | # define shell_read_history(X) linenoiseHistoryLoad(X) |
| 218 | # define shell_write_history(X) linenoiseHistorySave(X) |
| 219 | # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) |
| 220 | # define shell_readline(X) linenoise(X) |
| 221 | # define SHELL_CMDLINE_EDIT_AVAILABLE 1 /* command-line editing available */ |
| 222 | |
| 223 | #else |
| 224 | |
| 225 | # define shell_read_history(X) |
| 226 | # define shell_write_history(X) |
| 227 | # define shell_stifle_history(X) |
| 228 | # define SHELL_CMDLINE_EDIT_AVAILABLE 0 /* command-line editing not available */ |
| 229 | #endif |
| 230 | |
| 231 | /* |
| 232 | ** Global variable shellCmdLineEdit determines whether or not command-line |
| 233 | ** editing is enabled. It defaults to 1 if the CLI is linked against a |
| 234 | ** command-line editing library (linenoise, readline, or editline) and |
| 235 | ** to 0 if no command-line editing library is available. The |
| 236 | ** "--cmdline-edit off" command-line option will change this value to 0. |
| 237 | */ |
| 238 | static int shellCmdLineEdit = SHELL_CMDLINE_EDIT_AVAILABLE; |
| 239 | |
| 240 | #ifndef deliberate_fall_through |
| 241 | /* Quiet some compilers about some of our intentional code. */ |
| 242 | # if defined(GCC_VERSION) && GCC_VERSION>=7000000 |
| 243 | # define deliberate_fall_through __attribute__((fallthrough)); |
| @@ -733,10 +744,12 @@ | |
| 744 | char *(*xRender)(void*,sqlite3_value*); /* Render a value */ |
| 745 | int (*xWrite)(void*,const char*,sqlite3_int64); /* Write output */ |
| 746 | void *pRenderArg; /* First argument to the xRender callback */ |
| 747 | void *pWriteArg; /* First argument to the xWrite callback */ |
| 748 | char **pzOutput; /* Storage location for output string */ |
| 749 | /* The following are available in iVersion 2 and later */ |
| 750 | unsigned char bRowCount; /* Show the number of rows at end of each query */ |
| 751 | /* Additional fields may be added in the future */ |
| 752 | }; |
| 753 | |
| 754 | /* |
| 755 | ** Interfaces |
| @@ -761,11 +774,11 @@ | |
| 774 | #define QRF_STYLE_Column 2 /* One record per line in neat columns */ |
| 775 | #define QRF_STYLE_Count 3 /* Output only a count of the rows of output */ |
| 776 | #define QRF_STYLE_Csv 4 /* Comma-separated-value */ |
| 777 | #define QRF_STYLE_Eqp 5 /* Format EXPLAIN QUERY PLAN output */ |
| 778 | #define QRF_STYLE_Explain 6 /* EXPLAIN output */ |
| 779 | #define QRF_STYLE_Html 7 /* Generate HTML-style <tr><td> output */ |
| 780 | #define QRF_STYLE_Insert 8 /* Generate SQL "insert" statements */ |
| 781 | #define QRF_STYLE_Json 9 /* Output is a list of JSON objects */ |
| 782 | #define QRF_STYLE_JObject 10 /* Independent JSON objects for each row */ |
| 783 | #define QRF_STYLE_Line 11 /* One column per line. */ |
| 784 | #define QRF_STYLE_List 12 /* One record per line with a separator */ |
| @@ -821,10 +834,15 @@ | |
| 834 | #define QRF_SW_On 2 /* This setting is forced on */ |
| 835 | #define QRF_Auto 0 /* Alternate spelling for QRF_*_Auto */ |
| 836 | #define QRF_No 1 /* Alternate spelling for QRF_SW_Off */ |
| 837 | #define QRF_Yes 2 /* Alternate spelling for QRF_SW_On */ |
| 838 | |
| 839 | /* |
| 840 | ** Additional value allowed for bTitles |
| 841 | */ |
| 842 | #define QRF_Always 3 /* Always show titles, even if no rows */ |
| 843 | |
| 844 | /* |
| 845 | ** Possible alignment values alignment settings |
| 846 | ** |
| 847 | ** Horizontal Vertial |
| 848 | ** ---------- -------- */ |
| @@ -2527,10 +2545,14 @@ | |
| 2545 | /* Doubled horizontal lines: */ |
| 2546 | #define DBL_24 "\342\225\220" /* U+2550 === */ |
| 2547 | #define DBL_123 "\342\225\236" /* U+255e |= */ |
| 2548 | #define DBL_134 "\342\225\241" /* U+2561 =| */ |
| 2549 | #define DBL_1234 "\342\225\252" /* U+256a =|= */ |
| 2550 | #define DBL_12 "\342\225\230" /* U+2558 `= */ |
| 2551 | #define DBL_14 "\342\225\233" /* U+255b =' */ |
| 2552 | #define DBL_124 "\342\225\247" /* U+2567 ='= */ |
| 2553 | |
| 2554 | |
| 2555 | /* Draw horizontal line N characters long using unicode box |
| 2556 | ** characters |
| 2557 | */ |
| 2558 | static void qrfBoxLine(sqlite3_str *pOut, int N, int bDbl){ |
| @@ -2549,16 +2571,16 @@ | |
| 2571 | |
| 2572 | /* |
| 2573 | ** Draw a horizontal separator for a QRF_STYLE_Box table. |
| 2574 | */ |
| 2575 | static void qrfBoxSeparator( |
| 2576 | sqlite3_str *pOut, /* Output to this sqlite3_str */ |
| 2577 | qrfColData *p, /* Columnar data */ |
| 2578 | const char *zSep1, /* Left margin */ |
| 2579 | const char *zSep2, /* Column separator */ |
| 2580 | const char *zSep3, /* Right margin */ |
| 2581 | int bDbl /* True for double-lines */ |
| 2582 | ){ |
| 2583 | int i; |
| 2584 | if( p->nCol>0 ){ |
| 2585 | int useBorder = p->p->spec.bBorder!=QRF_No; |
| 2586 | if( useBorder ){ |
| @@ -2573,10 +2595,36 @@ | |
| 2595 | sqlite3_str_appendall(pOut, zSep3); |
| 2596 | } |
| 2597 | } |
| 2598 | sqlite3_str_append(pOut, "\n", 1); |
| 2599 | } |
| 2600 | |
| 2601 | /* |
| 2602 | ** Draw a horizontal separator for a QRF_STYLE_Column table. |
| 2603 | ** This style of separator is only used for separating the title |
| 2604 | ** from the content. |
| 2605 | */ |
| 2606 | static void qrfColumnSeparator( |
| 2607 | sqlite3_str *pOut, /* Output to this sqlite3_str */ |
| 2608 | qrfColData *p, /* Columnar data */ |
| 2609 | const char *colSep, /* Column separator text */ |
| 2610 | int szColSep, /* Size of zColSep in bytes */ |
| 2611 | const char *rowSep, /* Row separator text */ |
| 2612 | int szRowSep /* Size of zRowSep in bytes */ |
| 2613 | ){ |
| 2614 | int j; |
| 2615 | int nColumn = p->nCol; |
| 2616 | for(j=0; j<nColumn; j++){ |
| 2617 | sqlite3_str_appendchar(pOut, p->a[j].w, '-'); |
| 2618 | if( j<nColumn-1 ){ |
| 2619 | sqlite3_str_append(pOut, colSep, szColSep); |
| 2620 | }else{ |
| 2621 | qrfRTrim(pOut); |
| 2622 | sqlite3_str_append(pOut, rowSep, szRowSep); |
| 2623 | } |
| 2624 | } |
| 2625 | } |
| 2626 | |
| 2627 | /* |
| 2628 | ** Load into pData the default alignment for the body of a table. |
| 2629 | */ |
| 2630 | static void qrfLoadAlignment(qrfColData *pData, Qrf *p){ |
| @@ -2831,11 +2879,25 @@ | |
| 2879 | sqlite3_str *pStr; /* Temporary rendering */ |
| 2880 | qrfColData data; /* Columnar layout data */ |
| 2881 | int bRTrim; /* Trim trailing space */ |
| 2882 | |
| 2883 | rc = sqlite3_step(p->pStmt); |
| 2884 | if( nColumn==0 ){ |
| 2885 | return; /* Not a query. No results every shown. */ |
| 2886 | } |
| 2887 | if( rc==SQLITE_DONE && nColumn>0 ){ |
| 2888 | /* Empty query */ |
| 2889 | if( p->spec.bTitles==QRF_Always ){ |
| 2890 | /* fall through into the columnar logic below */ |
| 2891 | }else{ |
| 2892 | if( p->spec.bRowCount==QRF_Yes ){ |
| 2893 | sqlite3_str_appendf(p->pOut, "(0 rows)\n"); |
| 2894 | qrfWrite(p); |
| 2895 | } |
| 2896 | return; /* No output, other than the row count */ |
| 2897 | } |
| 2898 | }else if( rc!=SQLITE_ROW ){ |
| 2899 | return; /* No output */ |
| 2900 | } |
| 2901 | |
| 2902 | /* Initialize the data container */ |
| 2903 | memset(&data, 0, sizeof(data)); |
| @@ -2848,12 +2910,12 @@ | |
| 2910 | } |
| 2911 | memset(data.a, 0, nColumn*sizeof(struct qrfPerCol) ); |
| 2912 | if( qrfColDataEnlarge(&data) ) return; |
| 2913 | assert( data.az!=0 ); |
| 2914 | |
| 2915 | /* Load the column header names into data */ |
| 2916 | if( p->spec.bTitles>=QRF_Yes ){ |
| 2917 | unsigned char saved_eText = p->spec.eText; |
| 2918 | p->spec.eText = p->spec.eTitle; |
| 2919 | memset(data.abNum, 0, nColumn); |
| 2920 | for(i=0; i<nColumn; i++){ |
| 2921 | const char *z = (const char*)sqlite3_column_name(p->pStmt,i); |
| @@ -2874,13 +2936,14 @@ | |
| 2936 | data.n++; |
| 2937 | if( w>data.a[i].mxW ) data.a[i].mxW = w; |
| 2938 | if( nNL ) data.bMultiRow = 1; |
| 2939 | } |
| 2940 | p->spec.eText = saved_eText; |
| 2941 | } |
| 2942 | |
| 2943 | /* Load query results into data */ |
| 2944 | while( rc==SQLITE_ROW && p->iErr==SQLITE_OK ){ |
| 2945 | if( data.n+nColumn > data.nAlloc ){ |
| 2946 | if( qrfColDataEnlarge(&data) ) return; |
| 2947 | } |
| 2948 | for(i=0; i<nColumn; i++){ |
| 2949 | char *z; |
| @@ -2897,11 +2960,12 @@ | |
| 2960 | data.n++; |
| 2961 | if( w>data.a[i].mxW ) data.a[i].mxW = w; |
| 2962 | if( nNL ) data.bMultiRow = 1; |
| 2963 | } |
| 2964 | p->nRow++; |
| 2965 | rc = sqlite3_step(p->pStmt); |
| 2966 | } |
| 2967 | if( p->iErr ){ |
| 2968 | qrfColDataFree(&data); |
| 2969 | return; |
| 2970 | } |
| 2971 | |
| @@ -3105,11 +3169,11 @@ | |
| 3169 | /* Draw either (1) the separator between the title line and the body |
| 3170 | ** of the table, or (2) separators between individual rows of the table |
| 3171 | ** body. isTitleDataSeparator will be true if we are doing (1). |
| 3172 | */ |
| 3173 | if( (i==0 || data.bMultiRow) && i+nColumn<data.n ){ |
| 3174 | int isTitleDataSeparator = (i==0 && p->spec.bTitles>=QRF_Yes); |
| 3175 | if( isTitleDataSeparator ){ |
| 3176 | qrfLoadAlignment(&data, p); |
| 3177 | } |
| 3178 | switch( p->spec.eStyle ){ |
| 3179 | case QRF_STYLE_Table: { |
| @@ -3132,19 +3196,12 @@ | |
| 3196 | } |
| 3197 | break; |
| 3198 | } |
| 3199 | case QRF_STYLE_Column: { |
| 3200 | if( isTitleDataSeparator ){ |
| 3201 | qrfColumnSeparator(p->pOut, &data, colSep, szColSep, |
| 3202 | rowSep, szRowSep); |
| 3203 | }else if( data.bMultiRow ){ |
| 3204 | qrfRTrim(p->pOut); |
| 3205 | sqlite3_str_append(p->pOut, "\n", 1); |
| 3206 | } |
| 3207 | break; |
| @@ -3152,20 +3209,39 @@ | |
| 3209 | } |
| 3210 | } |
| 3211 | } |
| 3212 | |
| 3213 | /* Draw the line across the bottom of the table */ |
| 3214 | if( p->spec.bBorder!=QRF_No || p->nRow==0 ){ |
| 3215 | switch( p->spec.eStyle ){ |
| 3216 | case QRF_STYLE_Box: |
| 3217 | if( p->nRow>0 ){ |
| 3218 | qrfBoxSeparator(p->pOut, &data, BOX_R12, BOX_124, BOX_R14, 0); |
| 3219 | }else{ |
| 3220 | qrfBoxSeparator(p->pOut, &data, DBL_12, DBL_124, DBL_14, 1); |
| 3221 | } |
| 3222 | break; |
| 3223 | case QRF_STYLE_Table: |
| 3224 | qrfRowSeparator(p->pOut, &data, '+'); |
| 3225 | break; |
| 3226 | case QRF_STYLE_Markdown: |
| 3227 | if( p->nRow==0 ){ |
| 3228 | qrfRowSeparator(p->pOut, &data, '|'); |
| 3229 | } |
| 3230 | break; |
| 3231 | case QRF_STYLE_Column: |
| 3232 | if( p->nRow==0 ){ |
| 3233 | qrfColumnSeparator(p->pOut, &data, colSep, szColSep, |
| 3234 | rowSep, szRowSep); |
| 3235 | } |
| 3236 | break; |
| 3237 | } |
| 3238 | } |
| 3239 | if( p->spec.bRowCount==QRF_Yes ){ |
| 3240 | sqlite3_int64 n = p->nRow; |
| 3241 | sqlite3_str_appendf(p->pOut, "(%lld row%s)\n", n, n==1 ? "" : "s"); |
| 3242 | } |
| 3243 | qrfWrite(p); |
| 3244 | |
| 3245 | qrfColDataFree(&data); |
| 3246 | return; |
| 3247 | } |
| @@ -3412,10 +3488,49 @@ | |
| 3488 | sqlite3_str_append(p->pOut, ":", 1); |
| 3489 | qrfRenderValue(p, p->pOut, i); |
| 3490 | } |
| 3491 | qrfWrite(p); |
| 3492 | } |
| 3493 | |
| 3494 | /* |
| 3495 | ** Render a title row (a row containing column names) if the spec |
| 3496 | ** calls for one and if it makes sense for the eStyle. Title rows |
| 3497 | ** do not make sense for some eStyles, such as QRF_STYLE_Off, |
| 3498 | ** QRF_STYLE_Count, QRF_STYLE_Json, and similar. |
| 3499 | */ |
| 3500 | static void qrfSimpleTitle(Qrf *p){ |
| 3501 | assert( p->nRow==0 ); |
| 3502 | assert( p->spec.bTitles>=QRF_Yes ); |
| 3503 | switch( p->spec.eStyle ){ |
| 3504 | case QRF_STYLE_Html: { |
| 3505 | int i; |
| 3506 | sqlite3_str_append(p->pOut, "<tr>", 4); |
| 3507 | for(i=0; i<p->nCol; i++){ |
| 3508 | const char *zCName = sqlite3_column_name(p->pStmt, i); |
| 3509 | sqlite3_str_append(p->pOut, "\n<th>", 5); |
| 3510 | qrfEncodeText(p, p->pOut, zCName); |
| 3511 | } |
| 3512 | sqlite3_str_append(p->pOut, "\n</tr>\n", 7); |
| 3513 | break; |
| 3514 | } |
| 3515 | case QRF_STYLE_Quote: |
| 3516 | case QRF_STYLE_List: { |
| 3517 | int i; |
| 3518 | int saved_eText = p->spec.eText; |
| 3519 | p->spec.eText = p->spec.eTitle; |
| 3520 | for(i=0; i<p->nCol; i++){ |
| 3521 | const char *zCName = sqlite3_column_name(p->pStmt, i); |
| 3522 | if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); |
| 3523 | qrfEncodeText(p, p->pOut, zCName); |
| 3524 | } |
| 3525 | sqlite3_str_appendall(p->pOut, p->spec.zRowSep); |
| 3526 | qrfWrite(p); |
| 3527 | p->spec.eText = saved_eText; |
| 3528 | break; |
| 3529 | } |
| 3530 | } |
| 3531 | } |
| 3532 | |
| 3533 | /* |
| 3534 | ** Render a single row of output for non-columnar styles - any |
| 3535 | ** style that lets us render row by row as the content is received |
| 3536 | ** from the query. |
| @@ -3445,25 +3560,19 @@ | |
| 3560 | } |
| 3561 | qrfOneJsonRow(p); |
| 3562 | break; |
| 3563 | } |
| 3564 | case QRF_STYLE_Html: { |
| 3565 | if( p->nRow==0 && p->spec.bTitles>=QRF_Yes ){ |
| 3566 | qrfSimpleTitle(p); |
| 3567 | } |
| 3568 | sqlite3_str_append(p->pOut, "<tr>", 4); |
| 3569 | for(i=0; i<p->nCol; i++){ |
| 3570 | sqlite3_str_append(p->pOut, "\n<td>", 5); |
| 3571 | qrfRenderValue(p, p->pOut, i); |
| 3572 | } |
| 3573 | sqlite3_str_append(p->pOut, "\n</tr>\n", 7); |
| 3574 | qrfWrite(p); |
| 3575 | break; |
| 3576 | } |
| 3577 | case QRF_STYLE_Insert: { |
| 3578 | unsigned int mxIns = p->spec.nMultiInsert; |
| @@ -3476,11 +3585,11 @@ | |
| 3585 | if( qrf_need_quote(p->spec.zTableName) ){ |
| 3586 | sqlite3_str_appendf(p->pOut,"INSERT INTO \"%w\"",p->spec.zTableName); |
| 3587 | }else{ |
| 3588 | sqlite3_str_appendf(p->pOut,"INSERT INTO %s",p->spec.zTableName); |
| 3589 | } |
| 3590 | if( p->spec.bTitles>=QRF_Yes ){ |
| 3591 | for(i=0; i<p->nCol; i++){ |
| 3592 | const char *zCName = sqlite3_column_name(p->pStmt, i); |
| 3593 | if( qrf_need_quote(zCName) ){ |
| 3594 | sqlite3_str_appendf(p->pOut, "%c\"%w\"", |
| 3595 | i==0 ? '(' : ',', zCName); |
| @@ -3576,21 +3685,12 @@ | |
| 3685 | if( zEqpLine[0]=='-' ) qrfEqpRender(p, 0); |
| 3686 | qrfEqpAppend(p, iEqpId, iParentId, zEqpLine); |
| 3687 | break; |
| 3688 | } |
| 3689 | default: { /* QRF_STYLE_List */ |
| 3690 | if( p->nRow==0 && p->spec.bTitles>=QRF_Yes ){ |
| 3691 | qrfSimpleTitle(p); |
| 3692 | } |
| 3693 | for(i=0; i<p->nCol; i++){ |
| 3694 | if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); |
| 3695 | qrfRenderValue(p, p->pOut, i); |
| 3696 | } |
| @@ -3612,11 +3712,11 @@ | |
| 3712 | char **pzErr /* Write errors here */ |
| 3713 | ){ |
| 3714 | size_t sz; /* Size of pSpec[], based on pSpec->iVersion */ |
| 3715 | memset(p, 0, sizeof(*p)); |
| 3716 | p->pzErr = pzErr; |
| 3717 | if( pSpec->iVersion>2 ){ |
| 3718 | qrfError(p, SQLITE_ERROR, |
| 3719 | "unusable sqlite3_qrf_spec.iVersion (%d)", |
| 3720 | pSpec->iVersion); |
| 3721 | return; |
| 3722 | } |
| @@ -3640,10 +3740,13 @@ | |
| 3740 | if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto; |
| 3741 | if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto; |
| 3742 | if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto; |
| 3743 | if( p->spec.eTitle>QRF_TEXT_Relaxed ) p->spec.eTitle = QRF_Auto; |
| 3744 | if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto; |
| 3745 | if( pSpec->iVersion<=1 ){ |
| 3746 | p->spec.bRowCount = 0; |
| 3747 | } |
| 3748 | qrf_reinit: |
| 3749 | switch( p->spec.eStyle ){ |
| 3750 | case QRF_Auto: { |
| 3751 | switch( sqlite3_stmt_isexplain(pStmt) ){ |
| 3752 | case 0: p->spec.eStyle = QRF_STYLE_Box; break; |
| @@ -3898,10 +4001,34 @@ | |
| 4001 | default: { |
| 4002 | /* Non-columnar modes where the output can occur after each row |
| 4003 | ** of result is received */ |
| 4004 | while( qrf.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 4005 | qrfOneSimpleRow(&qrf); |
| 4006 | } |
| 4007 | if( qrf.nCol>0 && qrf.nRow==0 && qrf.spec.bTitles==QRF_Always ){ |
| 4008 | qrfSimpleTitle(&qrf); |
| 4009 | } |
| 4010 | if( qrf.nCol>0 && qrf.spec.bRowCount==QRF_Yes ){ |
| 4011 | const char *zPlural = qrf.nRow==1 ? "" : "s"; |
| 4012 | switch( qrf.spec.eStyle ){ |
| 4013 | case QRF_STYLE_Line: |
| 4014 | if( qrf.nRow>0 ) sqlite3_str_append(qrf.pOut, "\n", 1); |
| 4015 | /* Fall through */ |
| 4016 | case QRF_STYLE_Csv: |
| 4017 | case QRF_STYLE_List: |
| 4018 | case QRF_STYLE_Quote: |
| 4019 | sqlite3_str_appendf(qrf.pOut,"(%lld row%s)\n",qrf.nRow,zPlural); |
| 4020 | break; |
| 4021 | case QRF_STYLE_Html: |
| 4022 | sqlite3_str_appendf(qrf.pOut,"<!-- %lld row%s -->\n", |
| 4023 | qrf.nRow, zPlural); |
| 4024 | break; |
| 4025 | case QRF_STYLE_Insert: |
| 4026 | sqlite3_str_appendf(qrf.pOut,"/* %lld row%s inserted */\n", |
| 4027 | qrf.nRow, zPlural); |
| 4028 | break; |
| 4029 | } |
| 4030 | } |
| 4031 | break; |
| 4032 | } |
| 4033 | } |
| 4034 | qrfResetStmt(&qrf); |
| @@ -5839,10 +5966,13 @@ | |
| 5966 | } |
| 5967 | |
| 5968 | /* |
| 5969 | ** Allocate a new Decimal object initialized to the text in zIn[]. |
| 5970 | ** Return NULL if any kind of error occurs. |
| 5971 | ** |
| 5972 | ** Note that zIn[] is not necessarily zero-terminated. Always |
| 5973 | ** respect the boundary imposed by the n argument. |
| 5974 | */ |
| 5975 | static Decimal *decimalNewFromText(const char *zIn, int n){ |
| 5976 | Decimal *p = 0; |
| 5977 | int i; |
| 5978 | int iExp = 0; |
| @@ -5856,15 +5986,15 @@ | |
| 5986 | p->isNull = 0; |
| 5987 | p->nDigit = 0; |
| 5988 | p->nFrac = 0; |
| 5989 | p->a = sqlite3_malloc64( n+1 ); |
| 5990 | if( p->a==0 ) goto new_from_text_failed; |
| 5991 | for(i=0; i<n && IsSpace(zIn[i]); i++){} |
| 5992 | if( i<n && zIn[i]=='-' ){ |
| 5993 | p->sign = 1; |
| 5994 | i++; |
| 5995 | }else if( i<n && zIn[i]=='+' ){ |
| 5996 | i++; |
| 5997 | } |
| 5998 | while( i<n && zIn[i]=='0' ) i++; |
| 5999 | while( i<n ){ |
| 6000 | char c = zIn[i]; |
| @@ -6091,11 +6221,11 @@ | |
| 6221 | if( p->a[N]>=5 ){ |
| 6222 | /* If all leading digits are 9, increase the number of digits |
| 6223 | ** by adding a new 0 to the front */ |
| 6224 | for(i=0; i<N && p->a[i]==9; i++){} |
| 6225 | if( i==N ){ |
| 6226 | decimal_expand(p, p->nDigit+1, p->nFrac); |
| 6227 | if( p->oom ) return; |
| 6228 | } |
| 6229 | |
| 6230 | /* Do the rounding */ |
| 6231 | p->a[N-1]++; |
| @@ -6249,10 +6379,11 @@ | |
| 6379 | int nAddSig; |
| 6380 | int nAddFrac; |
| 6381 | signed char *a; |
| 6382 | if( p==0 ) return; |
| 6383 | nAddFrac = nFrac - p->nFrac; |
| 6384 | assert( nAddFrac>=0 ); |
| 6385 | nAddSig = (nDigit - p->nDigit) - nAddFrac; |
| 6386 | if( nAddFrac==0 && nAddSig==0 ) return; |
| 6387 | if( nDigit+1>SQLITE_DECIMAL_MAX_DIGIT ){ p->oom = 1; return; } |
| 6388 | a = sqlite3_realloc64(p->a, nDigit+1); |
| 6389 | if( a==0 ){ |
| @@ -8256,10 +8387,20 @@ | |
| 8387 | if( r==(double)x ) return r; |
| 8388 | if( r<(double)x ) x--; |
| 8389 | return (double)x; |
| 8390 | } |
| 8391 | #endif |
| 8392 | |
| 8393 | /* Convert a floating point value to its closest integer. Do so in |
| 8394 | ** a way that avoids 'outside the range of representable values' warnings |
| 8395 | ** from UBSAN. |
| 8396 | */ |
| 8397 | static sqlite3_int64 seriesRealToI64(double r){ |
| 8398 | if( r<-9223372036854774784.0 ) return SMALLEST_INT64; |
| 8399 | if( r>+9223372036854774784.0 ) return LARGEST_INT64; |
| 8400 | return (sqlite3_int64)r; |
| 8401 | } |
| 8402 | |
| 8403 | /* |
| 8404 | ** This method is called to "rewind" the series_cursor object back |
| 8405 | ** to the first row of output. This method is always called at least |
| 8406 | ** once prior to any call to seriesColumn() or seriesRowid() or |
| @@ -8379,11 +8520,11 @@ | |
| 8520 | double r = sqlite3_value_double(argv[iArg++]); |
| 8521 | if( r==seriesCeil(r) |
| 8522 | && r>=(double)SMALLEST_INT64 |
| 8523 | && r<=(double)LARGEST_INT64 |
| 8524 | ){ |
| 8525 | iMin = iMax = seriesRealToI64(r); |
| 8526 | }else{ |
| 8527 | goto series_no_rows; |
| 8528 | } |
| 8529 | }else{ |
| 8530 | iMin = iMax = sqlite3_value_int64(argv[iArg++]); |
| @@ -8395,14 +8536,11 @@ | |
| 8536 | if( r<=(double)SMALLEST_INT64 ){ |
| 8537 | iMin = SMALLEST_INT64; |
| 8538 | }else if( r>(double)LARGEST_INT64 ){ |
| 8539 | goto series_no_rows; |
| 8540 | }else{ |
| 8541 | iMin = seriesRealToI64(seriesCeil(r)); |
| 8542 | if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){ |
| 8543 | if( iMin==LARGEST_INT64 ) goto series_no_rows; |
| 8544 | iMin++; |
| 8545 | } |
| 8546 | } |
| @@ -8423,14 +8561,12 @@ | |
| 8561 | if( r>=(double)LARGEST_INT64 ){ |
| 8562 | iMax = LARGEST_INT64; |
| 8563 | }else if( r<=(double)SMALLEST_INT64 ){ |
| 8564 | goto series_no_rows; |
| 8565 | }else{ |
| 8566 | iMax = seriesRealToI64(seriesFloor(r)); |
| 8567 | if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){ |
| 8568 | if( iMax==SMALLEST_INT64 ) goto series_no_rows; |
| 8569 | iMax--; |
| 8570 | } |
| 8571 | } |
| 8572 | }else{ |
| @@ -10593,11 +10729,15 @@ | |
| 10729 | sqlite3_result_error_nomem(ctx); |
| 10730 | return SQLITE_NOMEM; |
| 10731 | } |
| 10732 | } |
| 10733 | |
| 10734 | if( n>0 ){ |
| 10735 | sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); |
| 10736 | }else{ |
| 10737 | sqlite3_result_null(ctx); |
| 10738 | } |
| 10739 | if( aBuf!=aStatic ) sqlite3_free(aBuf); |
| 10740 | #endif |
| 10741 | }else{ |
| 10742 | readFileContents(ctx, pCur->zPath); |
| 10743 | } |
| @@ -14457,11 +14597,11 @@ | |
| 14597 | eocd.nEntry = (u16)p->nEntry; |
| 14598 | eocd.nEntryTotal = (u16)p->nEntry; |
| 14599 | eocd.nSize = p->cds.n; |
| 14600 | eocd.iOffset = p->body.n; |
| 14601 | |
| 14602 | nZip = (i64)p->body.n + (i64)p->cds.n + ZIPFILE_EOCD_FIXED_SZ; |
| 14603 | aZip = (u8*)sqlite3_malloc64(nZip); |
| 14604 | if( aZip==0 ){ |
| 14605 | sqlite3_result_error_nomem(pCtx); |
| 14606 | }else{ |
| 14607 | memcpy(aZip, p->body.a, p->body.n); |
| @@ -17584,16 +17724,19 @@ | |
| 17724 | } |
| 17725 | iRet++; |
| 17726 | } |
| 17727 | } |
| 17728 | else if( c=='[' ){ |
| 17729 | while( z[iRet] && z[iRet++]!=']' ){} |
| 17730 | } |
| 17731 | else if( (c>='A' && c<='Z') || (c>='a' && c<='z') ){ |
| 17732 | while( (z[iRet]>='A' && z[iRet]<='Z') || (z[iRet]>='a' && z[iRet]<='z') ){ |
| 17733 | iRet++; |
| 17734 | } |
| 17735 | } |
| 17736 | else if( c==0 ){ |
| 17737 | iRet = 0; |
| 17738 | } |
| 17739 | |
| 17740 | return iRet; |
| 17741 | } |
| 17742 | |
| @@ -18030,10 +18173,27 @@ | |
| 18173 | intckFinalize(p, pStmt); |
| 18174 | |
| 18175 | if( bAutoIndex ) intckExec(p, "PRAGMA automatic_index = 1"); |
| 18176 | return zRet; |
| 18177 | } |
| 18178 | |
| 18179 | /* |
| 18180 | ** Register or unregister special SQL functions implemented by intck. |
| 18181 | ** |
| 18182 | ** Normally the custom SQL functions used by intck are only available |
| 18183 | ** in between sqlite3_intck_open() and sqlite3_intck_close(). However, |
| 18184 | ** for testing and debugging, it is sometimes useful to make those |
| 18185 | ** functions available generally. This routine provides as a separate |
| 18186 | ** interface in order to provide that capability. |
| 18187 | */ |
| 18188 | int sqlite3_intck_register(sqlite3 *db, int bCreate){ |
| 18189 | int rc; |
| 18190 | rc = sqlite3_create_function(db, "parse_create_index", |
| 18191 | 2, SQLITE_UTF8, 0, bCreate ? intckParseCreateIndexFunc : 0, 0, 0 |
| 18192 | ); |
| 18193 | return rc; |
| 18194 | } |
| 18195 | |
| 18196 | /* |
| 18197 | ** Open a new integrity-check object. |
| 18198 | */ |
| 18199 | int sqlite3_intck_open( |
| @@ -18052,13 +18212,11 @@ | |
| 18212 | }else{ |
| 18213 | memset(pNew, 0, sizeof(*pNew)); |
| 18214 | pNew->db = db; |
| 18215 | pNew->zDb = (const char*)&pNew[1]; |
| 18216 | memcpy(&pNew[1], zDb, nDb+1); |
| 18217 | rc = sqlite3_intck_register(db, 1); |
| 18218 | if( rc!=SQLITE_OK ){ |
| 18219 | sqlite3_intck_close(pNew); |
| 18220 | pNew = 0; |
| 18221 | } |
| 18222 | } |
| @@ -18071,13 +18229,11 @@ | |
| 18229 | ** Free the integrity-check object. |
| 18230 | */ |
| 18231 | void sqlite3_intck_close(sqlite3_intck *p){ |
| 18232 | if( p ){ |
| 18233 | sqlite3_finalize(p->pCheck); |
| 18234 | sqlite3_intck_register(p->db, 0); |
| 18235 | sqlite3_free(p->zObj); |
| 18236 | sqlite3_free(p->zKey); |
| 18237 | sqlite3_free(p->zTestSql); |
| 18238 | sqlite3_free(p->zErr); |
| 18239 | sqlite3_free(p->zMessage); |
| @@ -20355,16 +20511,128 @@ | |
| 20511 | ){ |
| 20512 | int rc = SQLITE_OK; |
| 20513 | SQLITE_EXTENSION_INIT2(pApi); |
| 20514 | (void)pzErrMsg; /* Unused parameter */ |
| 20515 | rc = sqlite3_create_function(db, "diskused", 1, |
| 20516 | SQLITE_UTF8|SQLITE_DIRECTONLY, |
| 20517 | 0, diskusedFunc, 0, 0); |
| 20518 | return rc; |
| 20519 | } |
| 20520 | |
| 20521 | /************************* End ext/misc/diskused.c ********************/ |
| 20522 | /************************* Begin ext/misc/strdup.c ******************/ |
| 20523 | /* |
| 20524 | ** 2026-07-04 |
| 20525 | ** |
| 20526 | ** The author disclaims copyright to this source code. In place of |
| 20527 | ** a legal notice, here is a blessing: |
| 20528 | ** |
| 20529 | ** May you do good and not evil. |
| 20530 | ** May you find forgiveness for yourself and forgive others. |
| 20531 | ** May you share freely, never taking more than you give. |
| 20532 | ** |
| 20533 | ****************************************************************************** |
| 20534 | ** |
| 20535 | ** Since this module was written (coincidentally) on the 250th anniversary |
| 20536 | ** of the signing of the Declaration of Independence of The United States, |
| 20537 | ** it seems fitting to quote from that document: |
| 20538 | ** |
| 20539 | ** We hold these truths to be self-evident, that all men are created |
| 20540 | ** equal, that they are endowed by their Creator with certain unalienable |
| 20541 | ** Rights, that among these are Life, Liberty and the pursuit of Happiness |
| 20542 | ** - That to secure these rights, Governments are instituted among Men, |
| 20543 | ** deriving their just powers from the consent of the governed,.... |
| 20544 | ** |
| 20545 | ** Two core ideas that (1) rights come from God and not from government, |
| 20546 | ** and that (2) there should not be special privileged classes of people |
| 20547 | ** were radical thoughts then, and are indeed disputed even today. Many |
| 20548 | ** people still hold that human rights derive from the beneficence of |
| 20549 | ** government and that certain classes of people have special rights and |
| 20550 | ** privileges not available to all. Yet, were it not for the crazy ideas |
| 20551 | ** espoused in the original Declaration of Independence, this software |
| 20552 | ** project, and indeed most of modern technology, would not exist. |
| 20553 | ** |
| 20554 | ** Therefore let us give thanks for the bold leadership and vision |
| 20555 | ** demonstrated by the authors of the American Revolution, 250 years ago |
| 20556 | ** this day. |
| 20557 | ** |
| 20558 | ****************************************************************************** |
| 20559 | ** |
| 20560 | ** Implementation of the strdup() SQL function. strdup() makes a copy |
| 20561 | ** of its argument (a string or a BLOB) into memory obtained directly |
| 20562 | ** from system malloc() (not from sqlite3_malloc()) and sized exactly |
| 20563 | ** to hold the string or BLOB. This is intended for testing purposes, |
| 20564 | ** particularly testing with ASAN. This function serves no practical |
| 20565 | ** purpose beyond testing and not not intended for production use. |
| 20566 | ** |
| 20567 | ** NULL, BLOB, and TEXT values come through as NULL, BLOB, and TEXT, |
| 20568 | ** respectively. Numeric values are rendered as strings and come out |
| 20569 | ** as text. |
| 20570 | */ |
| 20571 | /* #include "sqlite3ext.h" */ |
| 20572 | SQLITE_EXTENSION_INIT1 |
| 20573 | #include <assert.h> |
| 20574 | #include <string.h> |
| 20575 | #include <stdlib.h> |
| 20576 | |
| 20577 | /* |
| 20578 | ** Make a copy of a string or BLOB in memory obtained from malloc(). |
| 20579 | */ |
| 20580 | static void strdupfunc( |
| 20581 | sqlite3_context *context, |
| 20582 | int argc, |
| 20583 | sqlite3_value **argv |
| 20584 | ){ |
| 20585 | const unsigned char *zIn; |
| 20586 | int nIn; |
| 20587 | unsigned char *zOut; |
| 20588 | |
| 20589 | assert( argc==1 ); |
| 20590 | if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
| 20591 | if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ |
| 20592 | zIn = (const unsigned char*)sqlite3_value_blob(argv[0]); |
| 20593 | nIn = sqlite3_value_bytes(argv[0]); |
| 20594 | zOut = malloc( nIn==0 ? 1 : nIn ); |
| 20595 | if( zOut==0 ){ |
| 20596 | sqlite3_result_error_nomem(context); |
| 20597 | return; |
| 20598 | } |
| 20599 | if( nIn>0 ) memcpy(zOut, zIn, nIn); |
| 20600 | sqlite3_result_blob(context, zOut, nIn, free); |
| 20601 | }else{ |
| 20602 | zIn = (const unsigned char*)sqlite3_value_text(argv[0]); |
| 20603 | if( zIn==0 ) return; |
| 20604 | nIn = (int)strlen((char*)zIn); |
| 20605 | zOut = malloc( nIn+1 ); |
| 20606 | if( zOut==0 ){ |
| 20607 | sqlite3_result_error_nomem(context); |
| 20608 | return; |
| 20609 | } |
| 20610 | memcpy(zOut, zIn, nIn); |
| 20611 | zOut[nIn] = 0; |
| 20612 | sqlite3_result_text64(context, (char*)zOut, nIn, free, |
| 20613 | SQLITE_UTF8_ZT); |
| 20614 | } |
| 20615 | } |
| 20616 | |
| 20617 | #ifdef _WIN32 |
| 20618 | |
| 20619 | #endif |
| 20620 | int sqlite3_strdup_init( |
| 20621 | sqlite3 *db, |
| 20622 | char **pzErrMsg, |
| 20623 | const sqlite3_api_routines *pApi |
| 20624 | ){ |
| 20625 | int rc = SQLITE_OK; |
| 20626 | SQLITE_EXTENSION_INIT2(pApi); |
| 20627 | (void)pzErrMsg; /* Unused parameter */ |
| 20628 | rc = sqlite3_create_function(db, "strdup", 1, SQLITE_UTF8, |
| 20629 | 0, strdupfunc, 0, 0); |
| 20630 | return rc; |
| 20631 | } |
| 20632 | |
| 20633 | /************************* End ext/misc/strdup.c ********************/ |
| 20634 | |
| 20635 | #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) |
| 20636 | #define SQLITE_SHELL_HAVE_RECOVER 1 |
| 20637 | #else |
| 20638 | #define SQLITE_SHELL_HAVE_RECOVER 0 |
| @@ -24581,10 +24849,20 @@ | |
| 24849 | #endif |
| 24850 | #ifdef SQLITE_SHELL_EXTSRC |
| 24851 | # include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC) |
| 24852 | #endif |
| 24853 | |
| 24854 | /* |
| 24855 | ** Set the SQLITE_SHELL_EDITION to a YYYYMMDD date string and the |
| 24856 | ** code will attempt to use defaults for the prompt and for the |
| 24857 | ** initial output mode (and maybe other feature) that were for |
| 24858 | ** the most recent version not newer than the specified date. |
| 24859 | */ |
| 24860 | #ifndef SQLITE_SHELL_EDITION |
| 24861 | # define SQLITE_SHELL_EDITION 99991231 /* Use the latest if unspecified */ |
| 24862 | #endif |
| 24863 | |
| 24864 | #if defined(SQLITE_ENABLE_SESSION) |
| 24865 | /* |
| 24866 | ** State information for a single open session |
| 24867 | */ |
| 24868 | typedef struct OpenSession OpenSession; |
| @@ -24828,11 +25106,11 @@ | |
| 25106 | unsigned char eHdr; /* Default header encoding. */ |
| 25107 | unsigned char eBlob; /* Default blob encoding. */ |
| 25108 | unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */ |
| 25109 | unsigned char eStyle; /* Underlying QRF style */ |
| 25110 | unsigned char eCx; /* 0: other, 1: line, 2: columnar */ |
| 25111 | unsigned char mFlg; /* Flags. 1=border-off 2=split-column 4=rowcount */ |
| 25112 | }; |
| 25113 | |
| 25114 | /* String constants used by built-in modes */ |
| 25115 | static const char *aModeStr[] = |
| 25116 | /* 0 1 2 3 4 5 6 7 8 */ |
| @@ -24841,45 +25119,45 @@ | |
| 25119 | /* 9 10 11 12 13 */ |
| 25120 | |
| 25121 | static const ModeInfo aModeInfo[] = { |
| 25122 | /* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */ |
| 25123 | { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0, 0 }, |
| 25124 | { "box", 0, 0, 9, 1, 1, 0, 3, 1, 2, 0 }, |
| 25125 | { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0, 0 }, |
| 25126 | { "column", 0, 0, 9, 1, 1, 0, 3, 2, 2, 0 }, |
| 25127 | { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, |
| 25128 | { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0, 0 }, |
| 25129 | { "html", 0, 0, 9, 4, 4, 0, 3, 7, 0, 0 }, |
| 25130 | { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0, 0 }, |
| 25131 | { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0, 0 }, |
| 25132 | { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0, 0 }, |
| 25133 | { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0, 0 }, |
| 25134 | { "line", 13, 1, 9, 1, 1, 0, 0, 11, 1, 0 }, |
| 25135 | { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0, 0 }, |
| 25136 | { "markdown", 0, 0, 9, 1, 1, 0, 3, 13, 2, 0 }, |
| 25137 | { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0, 0 }, |
| 25138 | { "psql", 0, 0, 9, 1, 1, 0, 3, 19, 2, 5 }, |
| 25139 | { "qbox", 0, 0, 10, 2, 1, 0, 3, 1, 2, 0 }, |
| 25140 | { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0, 0 }, |
| 25141 | { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2, 2 }, |
| 25142 | { "table", 0, 0, 9, 1, 1, 0, 3, 19, 2, 0 }, |
| 25143 | { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0, 0 }, |
| 25144 | { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0, 0 }, |
| 25145 | { "www", 0, 0, 9, 4, 4, 0, 3, 7, 0, 0 } |
| 25146 | }; /* | / / | / / | | / \____ |
| 25147 | ** | / / | / / | | / | |
| 25148 | ** Index into aModeStr[] | / / | | 2: columnar | |
| 25149 | ** | / / | | 1: line | |
| 25150 | ** | / / | | 0: other | |
| 25151 | ** text encoding |/ | show | | | |
| 25152 | ** v-------------------' | hdrs? | The QRF style | |
| 25153 | ** 0: n/a blob | v-----' / |
| 25154 | ** 1: plain v----------' 0: n/a _________/ |
| 25155 | ** 2: sql 0: auto 1: no | |
| 25156 | ** 3: csv 1: as-text 2: yes 1: border-off |
| 25157 | ** 4: html 2: sql 3: always 2: split-column |
| 25158 | ** 5: c 3: hex 4: rowcount |
| 25159 | ** 6: json 4: c |
| 25160 | ** 5: json |
| 25161 | ** 6: size |
| 25162 | ******************************************************************/ |
| 25163 | |
| @@ -25162,11 +25440,11 @@ | |
| 25440 | */ |
| 25441 | static char *local_getline(char *zLine, FILE *in){ |
| 25442 | int nLine = zLine==0 ? 0 : 100; |
| 25443 | int n = 0; |
| 25444 | |
| 25445 | while( seenInterrupt<2 ){ |
| 25446 | if( n+100>nLine ){ |
| 25447 | if( nLine>=1073741773 ){ |
| 25448 | free(zLine); |
| 25449 | return 0; |
| 25450 | } |
| @@ -25226,11 +25504,13 @@ | |
| 25504 | # define SQLITE_PS_APPDEF shellPromptAppDef |
| 25505 | static const char *shellPromptAppDef(int c){ |
| 25506 | switch( c ){ |
| 25507 | /* The default main prompt string */ |
| 25508 | case 1: |
| 25509 | #if SQLITE_SHELL_EDITION<20260423 |
| 25510 | return "sqlite> "; /* Legacy prompt for backwards compatibility */ |
| 25511 | #elif defined(SQLITE_PS1) |
| 25512 | return SQLITE_PS1; |
| 25513 | #else |
| 25514 | if( shellNoColor() ){ |
| 25515 | return "/A-/v /f-> "; |
| 25516 | }else{ |
| @@ -25238,11 +25518,13 @@ | |
| 25518 | } |
| 25519 | #endif |
| 25520 | |
| 25521 | /* The default continuation prompt string */ |
| 25522 | case 2: |
| 25523 | #if SQLITE_SHELL_EDITION<20260423 |
| 25524 | return " ...> "; /* Legacy continuation prompt */ |
| 25525 | #elif defined(SQLITE_PS2) |
| 25526 | return SQLITE_PS2; |
| 25527 | #else |
| 25528 | if( shellNoColor() ){ |
| 25529 | return "/B/C-> "; |
| 25530 | }else{ |
| @@ -25711,30 +25993,33 @@ | |
| 25993 | zResult = local_getline(zPrior, in); |
| 25994 | }else{ |
| 25995 | const char *zBase = prompt_string(p, bContinue!=0); |
| 25996 | char *zPrompt = expand_prompt(p, zAll, zBase); |
| 25997 | shell_check_oom(zPrompt); |
| 25998 | #if SHELL_CMDLINE_EDIT_AVAILABLE |
| 25999 | if( shellCmdLineEdit ){ |
| 26000 | free(zPrior); |
| 26001 | zResult = shell_readline(zPrompt); |
| 26002 | while( zResult==0 ){ |
| 26003 | /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ |
| 26004 | sqlite3_sleep(50); |
| 26005 | if( seenInterrupt==0 ) break; |
| 26006 | zResult = shell_readline(""); |
| 26007 | } |
| 26008 | if( zResult && *zResult ) shell_add_history(zResult); |
| 26009 | }else |
| 26010 | #endif |
| 26011 | { |
| 26012 | sputz(stdout, zPrompt); |
| 26013 | fflush(stdout); |
| 26014 | do{ |
| 26015 | zResult = local_getline(zPrior, stdin); |
| 26016 | zPrior = 0; |
| 26017 | /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ |
| 26018 | if( zResult==0 ) sqlite3_sleep(50); |
| 26019 | }while( zResult==0 && seenInterrupt>0 ); |
| 26020 | } |
| 26021 | sqlite3_free(zPrompt); |
| 26022 | } |
| 26023 | return zResult; |
| 26024 | } |
| 26025 | #endif /* !SQLITE_SHELL_FIDDLE */ |
| @@ -26307,11 +26592,11 @@ | |
| 26592 | free(p->spec.zColumnSep); |
| 26593 | free(p->spec.zRowSep); |
| 26594 | free(p->spec.zTableName); |
| 26595 | free(p->spec.zNull); |
| 26596 | memset(p, 0, sizeof(*p)); |
| 26597 | p->spec.iVersion = 2; |
| 26598 | p->autoExplain = autoExplain; |
| 26599 | } |
| 26600 | |
| 26601 | /* |
| 26602 | ** Duplicate Mode pSrc into pDest. pDest is assumed to be |
| @@ -26432,10 +26717,15 @@ | |
| 26717 | pM->spec.bSplitColumn = QRF_Yes; |
| 26718 | pM->bAutoScreenWidth = 1; |
| 26719 | }else{ |
| 26720 | pM->spec.bSplitColumn = QRF_No; |
| 26721 | } |
| 26722 | if( pI->mFlg & 0x04 ){ |
| 26723 | pM->spec.bRowCount = QRF_Yes; |
| 26724 | }else{ |
| 26725 | pM->spec.bRowCount = QRF_No; |
| 26726 | } |
| 26727 | }else if( eMode>=MODE_USER && eMode-MODE_USER<p->nSavedModes ){ |
| 26728 | modeFree(&p->mode); |
| 26729 | modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode); |
| 26730 | }else if( eMode==MODE_BATCH ){ |
| 26731 | u8 mFlags = p->mode.mFlags; |
| @@ -26461,13 +26751,15 @@ | |
| 26751 | /* |
| 26752 | ** Set the mode to the default. It assumed that the mode has |
| 26753 | ** already been freed and zeroed prior to calling this routine. |
| 26754 | */ |
| 26755 | static void modeDefault(ShellState *p){ |
| 26756 | p->mode.spec.iVersion = 2; |
| 26757 | p->mode.autoExplain = 1; |
| 26758 | if( (stdin_is_interactive || stdout_is_console) |
| 26759 | && SQLITE_SHELL_EDITION>=20260409 |
| 26760 | ){ |
| 26761 | modeChange(p, MODE_TTY); |
| 26762 | }else{ |
| 26763 | modeChange(p, MODE_BATCH); |
| 26764 | } |
| 26765 | } |
| @@ -28827,10 +29119,11 @@ | |
| 29119 | " --quote ARG Enable/disable quoting of text. ARG can be\n" |
| 29120 | " \"off\", \"on\", \"sql\", \"relaxed\", \"csv\", \"html\",\n" |
| 29121 | " \"tcl\", or \"json\". \"off\" means show the text as-is.\n" |
| 29122 | " \"on\" is an alias for \"sql\".\n" |
| 29123 | " --reset Changes all mode settings back to their default.\n" |
| 29124 | " --rowcount BOOLEAN Show \"(N rows)\" at the end of query results.\n" |
| 29125 | " --rowsep STRING Use STRING as the row separator\n" |
| 29126 | " --sw|--screenwidth N Declare the screen width of the output device\n" |
| 29127 | " to be N characters. An attempt may be made to\n" |
| 29128 | " wrap output text to fit within this limit. Zero\n" |
| 29129 | " means \"no limit\". Or N can be \"auto\" to set the\n" |
| @@ -28838,11 +29131,11 @@ | |
| 29131 | " --tablename NAME Set the name of the table for \"insert\" mode.\n" |
| 29132 | " --tag NAME Save mode to the left as NAME.\n" |
| 29133 | " --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON.\n" |
| 29134 | " --title ARG Whether or not to show column headers, and if so\n" |
| 29135 | " how to encode them. ARG can be \"off\", \"on\",\n" |
| 29136 | " \"always\", \"sql\", \"csv\", \"html\", \"tcl\", or \"json\".\n" |
| 29137 | " --titlelimit N Limit the length of column titles to N characters.\n" |
| 29138 | " -v|--verbose Verbose output\n" |
| 29139 | " --widths LIST Set the columns widths for columnar modes. The\n" |
| 29140 | " argument is a list of integers, one for each\n" |
| 29141 | " column. A \"0\" width means use a dynamic width\n" |
| @@ -29544,10 +29837,11 @@ | |
| 29837 | sqlite3_base85_init(p->db, 0, 0); |
| 29838 | sqlite3_regexp_init(p->db, 0, 0); |
| 29839 | sqlite3_ieee_init(p->db, 0, 0); |
| 29840 | sqlite3_series_init(p->db, 0, 0); |
| 29841 | sqlite3_diskused_init(p->db, 0, 0); |
| 29842 | sqlite3_strdup_init(p->db, 0, 0); |
| 29843 | #ifndef SQLITE_SHELL_FIDDLE |
| 29844 | sqlite3_fileio_init(p->db, 0, 0); |
| 29845 | sqlite3_completion_init(p->db, 0, 0); |
| 29846 | #endif |
| 29847 | #ifdef SQLITE_HAVE_ZLIB |
| @@ -32998,14 +33292,16 @@ | |
| 33292 | /* |
| 33293 | ** This function computes what to show the user about the configured |
| 33294 | ** titles (or column-names). Output is an integer between 0 and 3: |
| 33295 | ** |
| 33296 | ** 0: The titles do not matter. Never show anything. |
| 33297 | ** 1: Show "--title off" |
| 33298 | ** 2: Show "--title on" |
| 33299 | ** 3: Show "--title always" |
| 33300 | ** 4: Show "--title VALUE" where VALUE is an encoding method |
| 33301 | ** to use, one of: plain sql csv html tcl json |
| 33302 | ** 5: Show "--title VALUE" as in 3, followed by "--title always" |
| 33303 | ** |
| 33304 | ** Inputs are: |
| 33305 | ** |
| 33306 | ** spec.bTitles (bT) Whether or not to show the titles |
| 33307 | ** spec.eTitle (eT) The actual encoding to be used for titles |
| @@ -33038,11 +33334,27 @@ | |
| 33334 | if( eT!=eH ) v >>= 32; /* Encoding disagree in upper 4-bytes */ |
| 33335 | if( bT!=bH ) v >>= 16; /* ON/OFF disagree in upper 2-byte pairs */ |
| 33336 | if( bT<2 ) v >>= 8; /* ON in even bytes, OFF in odd bytes (1st byte 0) */ |
| 33337 | if( !bAll ) v >>= 4; /* bAll values are in the lower half-byte */ |
| 33338 | |
| 33339 | v &= 3; |
| 33340 | /* At this point v means: |
| 33341 | ** 0: The titles do not matter. Never show anything. |
| 33342 | ** 1: Show "--title off" |
| 33343 | ** 2: Show "--title on" |
| 33344 | ** 3: Show "--title VALUE" where VALUE is an encoding method |
| 33345 | ** to use, one of: plain sql csv html tcl json |
| 33346 | ** If bTitles is QRF_Always, convert 2->3, 3->5. If bTitles is not |
| 33347 | ** QRF_Always, convert 3->4. |
| 33348 | */ |
| 33349 | if( p->mode.spec.bTitles==QRF_Always ){ |
| 33350 | if( v==3 ) v = 5; |
| 33351 | if( v==2 ) v = 3; |
| 33352 | }else{ |
| 33353 | if( v==3 ) v = 4; |
| 33354 | } |
| 33355 | return v; |
| 33356 | } |
| 33357 | |
| 33358 | /* |
| 33359 | ** DOT-COMMAND: .mode |
| 33360 | ** |
| @@ -33086,10 +33398,11 @@ | |
| 33398 | ** --quote ARG Enable/disable quoting of text. ARG can be |
| 33399 | ** "off", "on", "sql", "relaxed", "csv", "html", |
| 33400 | ** "tcl", or "json". "off" means show the text as-is. |
| 33401 | ** "on" is an alias for "sql". |
| 33402 | ** --reset Changes all mode settings back to their default. |
| 33403 | ** --rowcount BOOLEAN Show "(N rows)" at the end of query results. |
| 33404 | ** --rowsep STRING Use STRING as the row separator |
| 33405 | ** --sw|--screenwidth N Declare the screen width of the output device |
| 33406 | ** to be N characters. An attempt may be made to |
| 33407 | ** wrap output text to fit within this limit. Zero |
| 33408 | ** means "no limit". Or N can be "auto" to set the |
| @@ -33097,11 +33410,11 @@ | |
| 33410 | ** --tablename NAME Set the name of the table for "insert" mode. |
| 33411 | ** --tag NAME Save mode to the left as NAME. |
| 33412 | ** --textjsonb BOOLEAN If enabled, JSONB text is displayed as text JSON. |
| 33413 | ** --title ARG Whether or not to show column headers, and if so |
| 33414 | ** how to encode them. ARG can be "off", "on", |
| 33415 | ** "always", "sql", "csv", "html", "tcl", or "json". |
| 33416 | ** --titlelimit N Limit the length of column titles to N characters. |
| 33417 | ** -v|--verbose Verbose output |
| 33418 | ** --widths LIST Set the columns widths for columnar modes. The |
| 33419 | ** argument is a list of integers, one for each |
| 33420 | ** column. A "0" width means use a dynamic width |
| @@ -33325,10 +33638,17 @@ | |
| 33638 | chng = 1; |
| 33639 | }else if( optionMatch(z,"reset") ){ |
| 33640 | int saved_eMode = p->mode.eMode; |
| 33641 | modeFree(&p->mode); |
| 33642 | modeChange(p, saved_eMode); |
| 33643 | }else if( optionMatch(z,"rowcount") ){ |
| 33644 | if( i+1>=nArg ){ |
| 33645 | dotCmdError(p, i, "missing argument", 0); |
| 33646 | return 1; |
| 33647 | } |
| 33648 | p->mode.spec.bRowCount = booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; |
| 33649 | chng = 1; |
| 33650 | }else if( optionMatch(z,"screenwidth") || optionMatch(z,"sw") ){ |
| 33651 | if( (++i)>=nArg ){ |
| 33652 | dotCmdError(p, i-1, "missing argument", 0); |
| 33653 | return 1; |
| 33654 | } |
| @@ -33378,25 +33698,63 @@ | |
| 33698 | return 1; |
| 33699 | } |
| 33700 | p->mode.spec.bTextJsonb = booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; |
| 33701 | chng = 1; |
| 33702 | }else if( optionMatch(z,"titles") || optionMatch(z,"title") ){ |
| 33703 | /* The --titles option controls two fields of the |
| 33704 | ** sqlite3_qrf_spec object: eTitle and bTitles. |
| 33705 | ** |
| 33706 | ** --titles eTitle bTitles |
| 33707 | ** -------- --------------- --------------------- |
| 33708 | ** "off" (unchanged) QRF_Off |
| 33709 | ** "on" (unchanged) QRF_On |
| 33710 | ** "always" (unchanged) QRF_Always |
| 33711 | ** "auto", (default) (default) |
| 33712 | ** "plain" QRF_TEXT_Plain QRF_Always or QRF_On |
| 33713 | ** "sql" QRF_TEXT_Sql QRF_Always or QRF_On |
| 33714 | ** "csv" QRF_TEXT_Csv QRF_Always or QRF_On |
| 33715 | ** "html" QRF_TEXT_Html QRF_Always or QRF_On |
| 33716 | ** "tcl" QRF_TEXT_Tcl QRF_Always or QRF_On |
| 33717 | ** "json" QRF_TEXT_Json QRF_Always or QRF_On |
| 33718 | ** |
| 33719 | ** This mapping is different from the -title option to the "format" |
| 33720 | ** method of the TCL interface. In this mapping: |
| 33721 | ** |
| 33722 | ** * "off", "on", and "always" affect only bTitles and leave |
| 33723 | ** eTitle unchanged |
| 33724 | ** |
| 33725 | ** * "auto" sets both bTitles and eTitle to the default value |
| 33726 | ** in aModeInfo[] according to the current --style. |
| 33727 | ** |
| 33728 | ** * "plain" through "json" set eTitle but leave bTitles |
| 33729 | ** unchanged if it is not QRF_Off. If bTitles is QRF_Off, |
| 33730 | ** then it is changed QRF_Always. |
| 33731 | */ |
| 33732 | char *zErr = 0; |
| 33733 | if( i+1>=nArg ){ |
| 33734 | dotCmdError(p, i, "missing argument", 0); |
| 33735 | return 1; |
| 33736 | } |
| 33737 | k = pickStr(azArg[++i],&zErr, |
| 33738 | "off","on","always","auto","plain","sql","csv","html","tcl","json",""); |
| 33739 | /* 0 1 2 3 4 5 6 7 8 9 */ |
| 33740 | if( k<0 ){ |
| 33741 | dotCmdError(p, i, "bad --titles value","%z", zErr); |
| 33742 | return 1; |
| 33743 | } |
| 33744 | p->mode.mFlags &= ~MFLG_HDR; |
| 33745 | if( k<=2 ){ |
| 33746 | p->mode.spec.bTitles = QRF_No+k; |
| 33747 | }else if( k==3 ){ |
| 33748 | p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr; |
| 33749 | p->mode.spec.bTitles = aModeInfo[p->mode.eMode].bHdr; |
| 33750 | }else{ |
| 33751 | p->mode.spec.eTitle = (k-4)+QRF_TEXT_Plain; |
| 33752 | if( p->mode.spec.bTitles==QRF_No ){ |
| 33753 | p->mode.spec.bTitles = QRF_Always; |
| 33754 | } |
| 33755 | } |
| 33756 | chng = 1; |
| 33757 | }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){ |
| 33758 | int nWidth = 0; |
| 33759 | short int *aWidth; |
| 33760 | const char *zW; |
| @@ -33547,10 +33905,16 @@ | |
| 33905 | if( bAll |
| 33906 | || (pI->eText!=p->mode.spec.eText && (pI->eText>1 || p->mode.spec.eText>1)) |
| 33907 | ){ |
| 33908 | sqlite3_str_appendf(pDesc," --quote %s",qrfQuoteNames[p->mode.spec.eText]); |
| 33909 | } |
| 33910 | if( bAll |
| 33911 | || ((p->mode.spec.bRowCount==QRF_Yes) != ((pI->mFlg&4)!=0)) |
| 33912 | ){ |
| 33913 | sqlite3_str_appendf(pDesc," --rowcount %s", |
| 33914 | p->mode.spec.bRowCount==QRF_Yes ? "on" : "off"); |
| 33915 | } |
| 33916 | zSetting = aModeStr[pI->eRSep]; |
| 33917 | if( bAll || (zSetting && cli_strcmp(zSetting,p->mode.spec.zRowSep)!=0) ){ |
| 33918 | sqlite3_str_appendf(pDesc, " --rowsep "); |
| 33919 | append_c_string(pDesc, p->mode.spec.zRowSep); |
| 33920 | } |
| @@ -33576,14 +33940,19 @@ | |
| 33940 | if( k==1 ){ |
| 33941 | sqlite3_str_appendall(pDesc, " --titles off"); |
| 33942 | }else if( k==2 ){ |
| 33943 | sqlite3_str_appendall(pDesc, " --titles on"); |
| 33944 | }else if( k==3 ){ |
| 33945 | sqlite3_str_appendall(pDesc, " --titles always"); |
| 33946 | }else if( k>=4 ){ |
| 33947 | static const char *azTitle[] = |
| 33948 | { "plain", "sql", "csv", "html", "tcl", "json"}; |
| 33949 | sqlite3_str_appendf(pDesc, " --titles %s", |
| 33950 | azTitle[p->mode.spec.eTitle-1]); |
| 33951 | if( k==5 ){ |
| 33952 | sqlite3_str_appendf(pDesc, " --titles always"); |
| 33953 | } |
| 33954 | } |
| 33955 | if( p->mode.spec.nWidth>0 && (bAll || pI->eCx==2) ){ |
| 33956 | int ii; |
| 33957 | const char *zSep = " --widths "; |
| 33958 | for(ii=0; ii<p->mode.spec.nWidth; ii++){ |
| @@ -34901,15 +35270,19 @@ | |
| 35270 | } |
| 35271 | }else |
| 35272 | |
| 35273 | if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){ |
| 35274 | if( nArg==2 ){ |
| 35275 | if( cli_strcmp(azArg[1],"always")==0 ){ |
| 35276 | p->mode.spec.bTitles = QRF_Always; |
| 35277 | }else{ |
| 35278 | p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No; |
| 35279 | } |
| 35280 | p->mode.mFlags |= MFLG_HDR; |
| 35281 | p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr; |
| 35282 | }else{ |
| 35283 | eputz("Usage: .headers off|on|always\n"); |
| 35284 | rc = 1; |
| 35285 | } |
| 35286 | }else |
| 35287 | |
| 35288 | if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){ |
| @@ -35113,13 +35486,21 @@ | |
| 35486 | sqlite3_str_free(pSql); |
| 35487 | }else |
| 35488 | |
| 35489 | if( c=='i' && cli_strncmp(azArg[0], "intck", n)==0 ){ |
| 35490 | i64 iArg = 0; |
| 35491 | open_db(p, 0); |
| 35492 | if( nArg==2 ){ |
| 35493 | iArg = integerValue(azArg[1]); |
| 35494 | if( iArg==0 ){ |
| 35495 | if( cli_strcmp(azArg[1],"register")==0 ){ |
| 35496 | sqlite3_intck_register(p->db, 1); |
| 35497 | rc = 0; |
| 35498 | goto meta_command_exit; |
| 35499 | } |
| 35500 | iArg = -1; |
| 35501 | } |
| 35502 | } |
| 35503 | if( (nArg!=1 && nArg!=2) || iArg<0 ){ |
| 35504 | cli_printf(stderr,"%s","Usage: .intck STEPS_PER_UNLOCK\n"); |
| 35505 | rc = 1; |
| 35506 | goto meta_command_exit; |
| @@ -35167,10 +35548,11 @@ | |
| 35548 | { "attached", SQLITE_LIMIT_ATTACHED }, |
| 35549 | { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, |
| 35550 | { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, |
| 35551 | { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, |
| 35552 | { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, |
| 35553 | { "schema", SQLITE_LIMIT_SCHEMA }, |
| 35554 | }; |
| 35555 | int i, n2; |
| 35556 | open_db(p, 0); |
| 35557 | if( nArg==1 ){ |
| 35558 | for(i=0; i<ArraySize(aLimit); i++){ |
| @@ -36493,11 +36875,12 @@ | |
| 36875 | azBool[(p->mode.mFlags & MFLG_ECHO)!=0]); |
| 36876 | cli_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->mode.autoEQP&3]); |
| 36877 | cli_printf(p->out, "%12.12s: %s\n","explain", |
| 36878 | p->mode.autoExplain ? "auto" : "off"); |
| 36879 | cli_printf(p->out, "%12.12s: %s\n","headers", |
| 36880 | p->mode.spec.bTitles==QRF_Always ? "always" : |
| 36881 | azBool[p->mode.spec.bTitles==QRF_Yes]); |
| 36882 | if( p->mode.spec.eStyle==QRF_STYLE_Column |
| 36883 | || p->mode.spec.eStyle==QRF_STYLE_Box |
| 36884 | || p->mode.spec.eStyle==QRF_STYLE_Table |
| 36885 | || p->mode.spec.eStyle==QRF_STYLE_Markdown |
| 36886 | ){ |
| @@ -37860,10 +38243,11 @@ | |
| 38243 | " -ascii set '.mode ascii'\n" |
| 38244 | " -bail stop after hitting an error\n" |
| 38245 | " -batch force batch I/O\n" |
| 38246 | " -box set '.mode box'\n" |
| 38247 | " -cmd COMMAND run \"COMMAND\" before reading stdin\n" |
| 38248 | " -cmdline-edit BOOL enable or disable command-line editing\n" |
| 38249 | " -column set '.mode column'\n" |
| 38250 | " -csv set '.mode csv -limits off'\n" |
| 38251 | #if !defined(SQLITE_OMIT_DESERIALIZE) |
| 38252 | " -deserialize open the database using sqlite3_deserialize()\n" |
| 38253 | #endif |
| @@ -38130,10 +38514,13 @@ | |
| 38514 | stdout_is_console = 1; |
| 38515 | data.wasm.zDefaultDbName = "/fiddle.sqlite3"; |
| 38516 | #else |
| 38517 | stdin_is_interactive = isatty(0); |
| 38518 | stdout_is_console = isatty(1); |
| 38519 | if( !stdin_is_interactive || !stdout_is_console ){ |
| 38520 | shellCmdLineEdit = 0; |
| 38521 | } |
| 38522 | #endif |
| 38523 | atexit(abnormalExit); |
| 38524 | #ifdef SQLITE_DEBUG |
| 38525 | mem_main_enter = sqlite3_memory_used(); |
| 38526 | #endif |
| @@ -38377,10 +38764,12 @@ | |
| 38764 | }else if( cli_strcmp(z,"-safe")==0 ){ |
| 38765 | /* no-op - catch this on the second pass */ |
| 38766 | }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ |
| 38767 | /* skip over the argument */ |
| 38768 | i++; |
| 38769 | }else if( cli_strcmp(z,"-cmdline-edit")==0 ){ |
| 38770 | shellCmdLineEdit = booleanValue(cmdline_option_value(argc,argv,++i)); |
| 38771 | }else if( cli_strcmp(z,"-test-argv")==0 ){ |
| 38772 | /* Undocumented test option. Print the values in argv[] and exit. |
| 38773 | ** Use this to verify that any translation of the argv[], for example |
| 38774 | ** on Windows that receives wargv[] from the OS and must convert |
| 38775 | ** to UTF8 prior to calling this routine. */ |
| @@ -38567,11 +38956,11 @@ | |
| 38956 | cmdline_option_value(argc,argv,++i)); |
| 38957 | }else if( cli_strcmp(z,"-nullvalue")==0 ){ |
| 38958 | modeSetStr(&data.mode.spec.zNull, |
| 38959 | cmdline_option_value(argc,argv,++i)); |
| 38960 | }else if( cli_strcmp(z,"-header")==0 ){ |
| 38961 | data.mode.spec.bTitles = QRF_Always; |
| 38962 | data.mode.mFlags |= MFLG_HDR; |
| 38963 | }else if( cli_strcmp(z,"-noheader")==0 ){ |
| 38964 | data.mode.spec.bTitles = QRF_No; |
| 38965 | data.mode.mFlags |= MFLG_HDR; |
| 38966 | }else if( cli_strcmp(z,"-echo")==0 ){ |
| @@ -38639,10 +39028,12 @@ | |
| 39028 | i++; |
| 39029 | #ifdef SQLITE_ENABLE_MULTIPLEX |
| 39030 | }else if( cli_strcmp(z,"-multiplex")==0 ){ |
| 39031 | i++; |
| 39032 | #endif |
| 39033 | }else if( cli_strcmp(z,"-cmdline-edit")==0 ){ |
| 39034 | i+=2; |
| 39035 | }else if( cli_strcmp(z,"-help")==0 ){ |
| 39036 | usage(1); |
| 39037 | }else if( cli_strcmp(z,"-cmd")==0 ){ |
| 39038 | /* Run commands that follow -cmd first and separately from commands |
| 39039 | ** that simply appear on the command-line. This seems goofy. It would |
| @@ -38668,12 +39059,14 @@ | |
| 39059 | rc = 1; |
| 39060 | goto shell_main_exit; |
| 39061 | } |
| 39062 | open_db(&data, OPEN_DB_ZIPFILE); |
| 39063 | if( z[2] ){ |
| 39064 | char *zSaved = argv[i]; |
| 39065 | argv[i] = &z[2]; |
| 39066 | arDotCommand(&data, 1, argv+(i-1), argc-(i-1)); |
| 39067 | argv[i] = zSaved; |
| 39068 | }else{ |
| 39069 | arDotCommand(&data, 1, argv+i, argc-i); |
| 39070 | } |
| 39071 | readStdin = 0; |
| 39072 | stdin_is_interactive = 0; |
| 39073 |
+1369
-689
| --- extsrc/sqlite3.c | ||
| +++ extsrc/sqlite3.c | ||
| @@ -16,11 +16,11 @@ | ||
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | -** 3f3fb9b638f59ad982beafb7c117f24ddd3d with changes in files: | |
| 21 | +** 2f1f4f73535386549c12694dc57cfe555eec with changes in files: | |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| @@ -467,14 +467,14 @@ | ||
| 467 | 467 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 468 | 468 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 469 | 469 | */ |
| 470 | 470 | #define SQLITE_VERSION "3.54.0" |
| 471 | 471 | #define SQLITE_VERSION_NUMBER 3054000 |
| 472 | -#define SQLITE_SOURCE_ID "2026-06-16 13:43:08 3f3fb9b638f59ad982beafb7c117f24ddd3da612e62c862510805fa672ffae06" | |
| 472 | +#define SQLITE_SOURCE_ID "2026-07-24 16:28:47 2f1f4f73535386549c12694dc57cfe555eec689ae6824c6241aaf8d5befcd74d" | |
| 473 | 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 474 | 474 | #define SQLITE_SCM_TAGS "" |
| 475 | -#define SQLITE_SCM_DATETIME "2026-06-16T13:43:08.110Z" | |
| 475 | +#define SQLITE_SCM_DATETIME "2026-07-24T16:28:47.830Z" | |
| 476 | 476 | |
| 477 | 477 | /* |
| 478 | 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 479 | 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 480 | 480 | ** |
| @@ -3732,11 +3732,11 @@ | ||
| 3732 | 3732 | ** authorizer will fail with an error message explaining that |
| 3733 | 3733 | ** access is denied. |
| 3734 | 3734 | ** |
| 3735 | 3735 | ** ^The first parameter to the authorizer callback is a copy of the third |
| 3736 | 3736 | ** parameter to the sqlite3_set_authorizer() interface. ^The second parameter |
| 3737 | -** to the callback is an integer [SQLITE_COPY | action code] that specifies | |
| 3737 | +** to the callback is an integer [SQLITE_READ | action code] that specifies | |
| 3738 | 3738 | ** the particular action to be authorized. ^The third through sixth parameters |
| 3739 | 3739 | ** to the callback are either NULL pointers or zero-terminated strings |
| 3740 | 3740 | ** that contain additional details about the action to be authorized. |
| 3741 | 3741 | ** Applications must always be prepared to encounter a NULL pointer in any |
| 3742 | 3742 | ** of the third through the sixth parameters of the authorization callback. |
| @@ -3775,25 +3775,37 @@ | ||
| 3775 | 3775 | ** ^(Only a single authorizer can be in place on a database connection |
| 3776 | 3776 | ** at a time. Each call to sqlite3_set_authorizer overrides the |
| 3777 | 3777 | ** previous call.)^ ^Disable the authorizer by installing a NULL callback. |
| 3778 | 3778 | ** The authorizer is disabled by default. |
| 3779 | 3779 | ** |
| 3780 | -** The authorizer callback must not do anything that will modify | |
| 3780 | +** <h3>Limitations And Caveats</h3><ul> | |
| 3781 | +** | |
| 3782 | +** <li>The authorizer callback must not do anything that will modify | |
| 3781 | 3783 | ** the database connection that invoked the authorizer callback. |
| 3782 | 3784 | ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their |
| 3783 | 3785 | ** database connections for the meaning of "modify" in this paragraph. |
| 3784 | 3786 | ** |
| 3785 | -** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the | |
| 3787 | +** <li>^When [sqlite3_prepare_v2()] is used to prepare a statement, the | |
| 3786 | 3788 | ** statement might be re-prepared during [sqlite3_step()] due to a |
| 3787 | 3789 | ** schema change. Hence, the application should ensure that the |
| 3788 | 3790 | ** correct authorizer callback remains in place during the [sqlite3_step()]. |
| 3789 | 3791 | ** |
| 3790 | -** ^Note that the authorizer callback is invoked only during | |
| 3792 | +** <li>^The authorizer callback is invoked only during | |
| 3791 | 3793 | ** [sqlite3_prepare()] or its variants. Authorization is not |
| 3792 | 3794 | ** performed during statement evaluation in [sqlite3_step()], unless |
| 3793 | 3795 | ** as stated in the previous paragraph, sqlite3_step() invokes |
| 3794 | 3796 | ** sqlite3_prepare_v2() to reprepare a statement after a schema change. |
| 3797 | +** | |
| 3798 | +** <li>Authorizer callbacks for the expressions of a | |
| 3799 | +** [generated column] are invoked when the schema is parsed (and specifically | |
| 3800 | +** when the [CREATE TABLE] statement that contains the generated column is | |
| 3801 | +** parsed) not when the generated column is used in a DML statement. | |
| 3802 | +** This is deliberate, as one of the purposes of generated columns | |
| 3803 | +** is to give schema designers the ability to provide gated access | |
| 3804 | +** to privileged columns and/or functions. | |
| 3805 | +** | |
| 3806 | +** </ul> | |
| 3795 | 3807 | */ |
| 3796 | 3808 | SQLITE_API int sqlite3_set_authorizer( |
| 3797 | 3809 | sqlite3*, |
| 3798 | 3810 | int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), |
| 3799 | 3811 | void *pUserData |
| @@ -3864,12 +3876,17 @@ | ||
| 3864 | 3876 | #define SQLITE_ANALYZE 28 /* Table Name NULL */ |
| 3865 | 3877 | #define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ |
| 3866 | 3878 | #define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ |
| 3867 | 3879 | #define SQLITE_FUNCTION 31 /* NULL Function Name */ |
| 3868 | 3880 | #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ |
| 3869 | -#define SQLITE_COPY 0 /* No longer used */ | |
| 3870 | 3881 | #define SQLITE_RECURSIVE 33 /* NULL NULL */ |
| 3882 | + | |
| 3883 | +/* | |
| 3884 | +** Note: The SQLITE_COPY macro (with value 0) used to be one of the | |
| 3885 | +** action codes above. That macro has now been repurposed as a possible | |
| 3886 | +** value to the 3rd argument to sqlite3_result_str(). | |
| 3887 | +*/ | |
| 3871 | 3888 | |
| 3872 | 3889 | /* |
| 3873 | 3890 | ** CAPI3REF: Deprecated Tracing And Profiling Functions |
| 3874 | 3891 | ** DEPRECATED |
| 3875 | 3892 | ** |
| @@ -4734,10 +4751,14 @@ | ||
| 4734 | 4751 | ** nesting depth for separate triggers.</dd>)^ |
| 4735 | 4752 | ** |
| 4736 | 4753 | ** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt> |
| 4737 | 4754 | ** <dd>The maximum number of auxiliary worker threads that a single |
| 4738 | 4755 | ** [prepared statement] may start.</dd>)^ |
| 4756 | +** | |
| 4757 | +** [[SQLITE_LIMIT_SCHEMA]] ^(<dt>SQLITE_LIMIT_SCHEMA</dt> | |
| 4758 | +** <dd>The maximum number of objects (tables, indexes, triggers, and views) | |
| 4759 | +** defined by the database schema.</dd>)^ | |
| 4739 | 4760 | ** </dl> |
| 4740 | 4761 | */ |
| 4741 | 4762 | #define SQLITE_LIMIT_LENGTH 0 |
| 4742 | 4763 | #define SQLITE_LIMIT_SQL_LENGTH 1 |
| 4743 | 4764 | #define SQLITE_LIMIT_COLUMN 2 |
| @@ -4749,10 +4770,11 @@ | ||
| 4749 | 4770 | #define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 |
| 4750 | 4771 | #define SQLITE_LIMIT_VARIABLE_NUMBER 9 |
| 4751 | 4772 | #define SQLITE_LIMIT_TRIGGER_DEPTH 10 |
| 4752 | 4773 | #define SQLITE_LIMIT_WORKER_THREADS 11 |
| 4753 | 4774 | #define SQLITE_LIMIT_PARSER_DEPTH 12 |
| 4775 | +#define SQLITE_LIMIT_SCHEMA 13 | |
| 4754 | 4776 | |
| 4755 | 4777 | /* |
| 4756 | 4778 | ** CAPI3REF: Prepare Flags |
| 4757 | 4779 | ** |
| 4758 | 4780 | ** These constants define various flags that can be passed into the |
| @@ -4860,10 +4882,12 @@ | ||
| 4860 | 4882 | ** there is a small performance advantage to passing an nByte parameter that |
| 4861 | 4883 | ** is the number of bytes in the input string <i>including</i> |
| 4862 | 4884 | ** the nul-terminator. |
| 4863 | 4885 | ** Note that nByte measures the length of the input in bytes, not |
| 4864 | 4886 | ** characters, even for the UTF-16 interfaces. |
| 4887 | +** For the sqlite3_prepare16() and sqlite3_prepare16_v2() interfaces, | |
| 4888 | +** the nByte value must be even or undefined behavior can result. | |
| 4865 | 4889 | ** |
| 4866 | 4890 | ** ^If pzTail is not NULL then *pzTail is made to point to the first byte |
| 4867 | 4891 | ** past the end of the first SQL statement in zSql. These routines only |
| 4868 | 4892 | ** compile the first statement in zSql, so *pzTail is left pointing to |
| 4869 | 4893 | ** what remains uncompiled. |
| @@ -5606,11 +5630,11 @@ | ||
| 5606 | 5630 | ** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) |
| 5607 | 5631 | ** can be obtained by calling [sqlite3_reset()] on the |
| 5608 | 5632 | ** [prepared statement]. ^In the "v2" interface, |
| 5609 | 5633 | ** the more specific error code is returned directly by sqlite3_step(). |
| 5610 | 5634 | ** |
| 5611 | -** [SQLITE_MISUSE] means that the this routine was called inappropriately. | |
| 5635 | +** [SQLITE_MISUSE] means that this routine was called inappropriately. | |
| 5612 | 5636 | ** Perhaps it was called on a [prepared statement] that has |
| 5613 | 5637 | ** already been [sqlite3_finalize | finalized] or on one that had |
| 5614 | 5638 | ** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could |
| 5615 | 5639 | ** be the case that the same database connection is being used by two or |
| 5616 | 5640 | ** more threads at the same moment in time. |
| @@ -6779,11 +6803,15 @@ | ||
| 6779 | 6803 | ** to by the second parameter and which is N bytes long where N is the |
| 6780 | 6804 | ** third parameter. |
| 6781 | 6805 | ** |
| 6782 | 6806 | ** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N) |
| 6783 | 6807 | ** interfaces set the result of the application-defined function to be |
| 6784 | -** a BLOB containing all zero bytes and N bytes in size. | |
| 6808 | +** a BLOB containing all zero bytes and N bytes in size. The | |
| 6809 | +** zeroblob64(C,N) interface returns a [result code], which is normally | |
| 6810 | +** [SQLITE_OK] but might be some other value if the requested operation | |
| 6811 | +** could not be complete, for example if insufficient memory is available | |
| 6812 | +** or if the value of N is out of range. | |
| 6785 | 6813 | ** |
| 6786 | 6814 | ** ^The sqlite3_result_double() interface sets the result from |
| 6787 | 6815 | ** an application-defined function to be a floating point value specified |
| 6788 | 6816 | ** by its 2nd argument. |
| 6789 | 6817 | ** |
| @@ -9117,12 +9145,12 @@ | ||
| 9117 | 9145 | ** The lifecycle of an sqlite3_str object is as follows: |
| 9118 | 9146 | ** <ol> |
| 9119 | 9147 | ** <li> ^The sqlite3_str object is created using [sqlite3_str_new()]. |
| 9120 | 9148 | ** <li> ^Text is appended to the sqlite3_str object using various |
| 9121 | 9149 | ** methods, such as [sqlite3_str_appendf()]. |
| 9122 | -** <li> ^The sqlite3_str object is destroyed and the string it created | |
| 9123 | -** is returned using the [sqlite3_str_finish()] interface. | |
| 9150 | +** <li> The sqlite3_str object is destroyed and the string it created | |
| 9151 | +** is returned using [sqlite3_str_finish()] or [sqlite3_result_str()]. | |
| 9124 | 9152 | ** </ol> |
| 9125 | 9153 | */ |
| 9126 | 9154 | typedef struct sqlite3_str sqlite3_str; |
| 9127 | 9155 | |
| 9128 | 9156 | /* |
| @@ -9170,10 +9198,44 @@ | ||
| 9170 | 9198 | ** the equivalent of calling [sqlite3_free](sqlite3_str_finish(X)). |
| 9171 | 9199 | */ |
| 9172 | 9200 | SQLITE_API char *sqlite3_str_finish(sqlite3_str*); |
| 9173 | 9201 | SQLITE_API void sqlite3_str_free(sqlite3_str*); |
| 9174 | 9202 | |
| 9203 | +/* | |
| 9204 | +** CAPI3REF: Return A Dynamic String From an SQL Function | |
| 9205 | +** | |
| 9206 | +** The [sqlite3_result_str(C,S,F)] interface causes the | |
| 9207 | +** [sqlite3_str|dynamic string] S to become the return value for the | |
| 9208 | +** application-defined function or virtual table that uses | |
| 9209 | +** [sqlite3_context] C. The F flag can be one of [SQLITE_COPY] | |
| 9210 | +** or [SQLITE_XFER] or [SQLITE_FINISH]. | |
| 9211 | +** | |
| 9212 | +** If the dynamic string is invalid or incomplete due to an out-of-memory | |
| 9213 | +** or string-too-large error, then this routine transfers that error | |
| 9214 | +** over to the SQL function. | |
| 9215 | +** | |
| 9216 | +** If the F argument is SQLITE_COPY, then a copy of the dynamic string | |
| 9217 | +** content is made and the dynamic string object is unchanged. | |
| 9218 | +** If the F argument is SQLITE_XFER, then ownership of the content | |
| 9219 | +** in the dynamic is transferred to the SQL function (via a pointer copy | |
| 9220 | +** rather than a string copy) and the dynamic string is reset to an | |
| 9221 | +** empty string. The SQLITE_FINISH value for F works like SQLITE_RESET | |
| 9222 | +** except that it also invokes the [sqlite3_str_free(S)] destructor | |
| 9223 | +** on the dynamic string object. | |
| 9224 | +*/ | |
| 9225 | +SQLITE_API void sqlite3_result_str(sqlite3_context*, sqlite3_str*, int); | |
| 9226 | + | |
| 9227 | +/* | |
| 9228 | +** CAPI3REF: Control Flags For sqlite3_result_str() | |
| 9229 | +** | |
| 9230 | +** The following integers can be used as the third "F" argument | |
| 9231 | +** to [sqlite3_result_str(C,S,F)]. | |
| 9232 | +*/ | |
| 9233 | +#define SQLITE_COPY 0 /* Results copied. Dynamic string unchanged */ | |
| 9234 | +#define SQLITE_XFER 1 /* Results transfered. Dynamic string reset */ | |
| 9235 | +#define SQLITE_FINISH 2 /* Like SQLITE_XFER, plus dynamic string freed */ | |
| 9236 | + | |
| 9175 | 9237 | /* |
| 9176 | 9238 | ** CAPI3REF: Add Content To A Dynamic String |
| 9177 | 9239 | ** METHOD: sqlite3_str |
| 9178 | 9240 | ** |
| 9179 | 9241 | ** These interfaces add or remove content to an sqlite3_str object |
| @@ -14978,10 +15040,37 @@ | ||
| 14978 | 15040 | */ |
| 14979 | 15041 | #ifndef SQLITE_MAX_TRIGGER_DEPTH |
| 14980 | 15042 | # define SQLITE_MAX_TRIGGER_DEPTH 1000 |
| 14981 | 15043 | #endif |
| 14982 | 15044 | |
| 15045 | +/* | |
| 15046 | +** Maximum number of objects defined by a single database schema. | |
| 15047 | +** Objects include: | |
| 15048 | +** | |
| 15049 | +** * tables (including the sqlite_schema table) | |
| 15050 | +** * virtual tables | |
| 15051 | +** * named indexes | |
| 15052 | +** * indexes created automatically by UNIQUE and PRIMARY KEY constraints | |
| 15053 | +** * triggers | |
| 15054 | +** * views | |
| 15055 | +** | |
| 15056 | +** The total of all of the above is the number of objects in the schema, | |
| 15057 | +** and that number may not exceed this value. | |
| 15058 | +** | |
| 15059 | +** The maximum number of objects is restricted to forestall theoretical | |
| 15060 | +** signed integer overflow attacks using databases with billions of | |
| 15061 | +** schema objects. Such attacks are "theoretical" because memory and | |
| 15062 | +** disk space constraints would be reached long before billions of schema | |
| 15063 | +** objects could be created. Even so, it seems good to have a well defined | |
| 15064 | +** upper limit on the complexity of the schema, for defense in depth. | |
| 15065 | +** No real-world application should ever get anywhere close to hitting | |
| 15066 | +** this limit. | |
| 15067 | +*/ | |
| 15068 | +#ifndef SQLITE_MAX_SCHEMA | |
| 15069 | +# define SQLITE_MAX_SCHEMA 10000000 | |
| 15070 | +#endif | |
| 15071 | + | |
| 14983 | 15072 | /************** End of sqliteLimit.h *****************************************/ |
| 14984 | 15073 | /************** Continuing where we left off in sqliteInt.h ******************/ |
| 14985 | 15074 | |
| 14986 | 15075 | /* Disable nuisance warnings on Borland compilers */ |
| 14987 | 15076 | #if defined(__BORLANDC__) |
| @@ -15236,11 +15325,13 @@ | ||
| 15236 | 15325 | ** bitmask tests, testcase() can be used to make sure each bit |
| 15237 | 15326 | ** is significant and used at least once. On switch statements |
| 15238 | 15327 | ** where multiple cases go to the same block of code, testcase() |
| 15239 | 15328 | ** can insure that all cases are evaluated. |
| 15240 | 15329 | */ |
| 15241 | -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) | |
| 15330 | +#if defined(SQLITE_MUTATION_TEST) | |
| 15331 | +# define testcase(X) | |
| 15332 | +#elif defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) | |
| 15242 | 15333 | # ifndef SQLITE_AMALGAMATION |
| 15243 | 15334 | extern unsigned int sqlite3CoverageCounter; |
| 15244 | 15335 | # endif |
| 15245 | 15336 | # define testcase(X) if( X ){ sqlite3CoverageCounter += (unsigned)__LINE__; } |
| 15246 | 15337 | #else |
| @@ -17190,11 +17281,11 @@ | ||
| 17190 | 17281 | SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); |
| 17191 | 17282 | #endif |
| 17192 | 17283 | |
| 17193 | 17284 | SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); |
| 17194 | 17285 | SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); |
| 17195 | -SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); | |
| 17286 | +SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree*, Btree*); | |
| 17196 | 17287 | |
| 17197 | 17288 | SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); |
| 17198 | 17289 | |
| 17199 | 17290 | /* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR |
| 17200 | 17291 | ** of the flags shown below. |
| @@ -17267,16 +17358,23 @@ | ||
| 17267 | 17358 | ** The design of the _RANGE hint is aid b-tree implementations that try |
| 17268 | 17359 | ** to prefetch content from remote machines - to provide those |
| 17269 | 17360 | ** implementations with limits on what needs to be prefetched and thereby |
| 17270 | 17361 | ** reduce network bandwidth. |
| 17271 | 17362 | ** |
| 17363 | +** BTREE_HINT_TABLECURSOR (arguments: BtCursor*) | |
| 17364 | +** | |
| 17365 | +** This hint is invoked on a non-covering index cursor soon after it | |
| 17366 | +** is opened. The only argument is a pointer to the table cursor used to | |
| 17367 | +** obtain non-covered fields from the database. | |
| 17368 | +** | |
| 17272 | 17369 | ** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by |
| 17273 | 17370 | ** standard SQLite. The other hints are provided for extensions that use |
| 17274 | 17371 | ** the SQLite parser and code generator but substitute their own storage |
| 17275 | 17372 | ** engine. |
| 17276 | 17373 | */ |
| 17277 | 17374 | #define BTREE_HINT_RANGE 0 /* Range constraints on queries */ |
| 17375 | +#define BTREE_HINT_TABLECURSOR 1 /* Table csr associated with this index csr */ | |
| 17278 | 17376 | |
| 17279 | 17377 | /* |
| 17280 | 17378 | ** Values that may be OR'd together to form the argument to the |
| 17281 | 17379 | ** BTREE_HINT_FLAGS hint for sqlite3BtreeCursorHint(): |
| 17282 | 17380 | ** |
| @@ -17332,10 +17430,13 @@ | ||
| 17332 | 17430 | #endif |
| 17333 | 17431 | SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); |
| 17334 | 17432 | SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned); |
| 17335 | 17433 | #ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 17336 | 17434 | SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...); |
| 17435 | + #ifdef SQLITE_DEBUG | |
| 17436 | +SQLITE_PRIVATE BtCursor *sqlite3BtreeCursorHintTblCsr(BtCursor*); | |
| 17437 | + #endif | |
| 17337 | 17438 | #endif |
| 17338 | 17439 | |
| 17339 | 17440 | SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); |
| 17340 | 17441 | SQLITE_PRIVATE int sqlite3BtreeTableMoveto( |
| 17341 | 17442 | BtCursor*, |
| @@ -18573,11 +18674,11 @@ | ||
| 18573 | 18674 | |
| 18574 | 18675 | /* |
| 18575 | 18676 | ** The number of different kinds of things that can be limited |
| 18576 | 18677 | ** using the sqlite3_limit() interface. |
| 18577 | 18678 | */ |
| 18578 | -#define SQLITE_N_LIMIT (SQLITE_LIMIT_PARSER_DEPTH+1) | |
| 18679 | +#define SQLITE_N_LIMIT (SQLITE_LIMIT_SCHEMA+1) | |
| 18579 | 18680 | |
| 18580 | 18681 | /* |
| 18581 | 18682 | ** Lookaside malloc is a set of fixed-size buffers that can be used |
| 18582 | 18683 | ** to satisfy small transient memory allocation requests for objects |
| 18583 | 18684 | ** associated with a particular database connection. The use of |
| @@ -20940,16 +21041,16 @@ | ||
| 20940 | 21041 | bft bHasExists :1; /* Has a correlated "EXISTS (SELECT ....)" expression */ |
| 20941 | 21042 | bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */ |
| 20942 | 21043 | bft bHasWith :1; /* True if statement contains WITH */ |
| 20943 | 21044 | bft okConstFactor:1; /* OK to factor out constants */ |
| 20944 | 21045 | bft checkSchema :1; /* Causes schema cookie check after an error */ |
| 21046 | + bft usesAinc :1; /* True if pAinc is valid */ | |
| 20945 | 21047 | int nRangeReg; /* Size of the temporary register block */ |
| 20946 | 21048 | int iRangeReg; /* First register in temporary register block */ |
| 20947 | 21049 | int nErr; /* Number of errors seen */ |
| 20948 | 21050 | int nTab; /* Number of previously allocated VDBE cursors */ |
| 20949 | 21051 | int nMem; /* Number of memory cells used so far */ |
| 20950 | - int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ | |
| 20951 | 21052 | int iSelfTab; /* Table associated with an index on expr, or negative |
| 20952 | 21053 | ** of the base register during check-constraint eval */ |
| 20953 | 21054 | int nNestSel; /* Number of nested SELECT statements and/or VIEWs */ |
| 20954 | 21055 | int nLabel; /* The *negative* of the number of labels used */ |
| 20955 | 21056 | int nLabelAlloc; /* Number of slots in aLabel */ |
| @@ -20964,13 +21065,11 @@ | ||
| 20964 | 21065 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 20965 | 21066 | u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ |
| 20966 | 21067 | #endif |
| 20967 | 21068 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 20968 | 21069 | int nTableLock; /* Number of locks in aTableLock */ |
| 20969 | - TableLock *aTableLock; /* Required table locks for shared-cache mode */ | |
| 20970 | 21070 | #endif |
| 20971 | - AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ | |
| 20972 | 21071 | Parse *pToplevel; /* Parse structure for main program (or NULL) */ |
| 20973 | 21072 | Table *pTriggerTab; /* Table triggers are being coded for */ |
| 20974 | 21073 | TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ |
| 20975 | 21074 | ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ |
| 20976 | 21075 | |
| @@ -20995,10 +21094,17 @@ | ||
| 20995 | 21094 | } cr; |
| 20996 | 21095 | struct { /* These fields available to all other statements */ |
| 20997 | 21096 | Returning *pReturning; /* The RETURNING clause */ |
| 20998 | 21097 | } d; |
| 20999 | 21098 | } u1; |
| 21099 | + AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters. Only | |
| 21100 | + ** valid if Parse.usesAinc is true */ | |
| 21101 | +#ifndef SQLITE_OMIT_SHARED_CACHE | |
| 21102 | + TableLock *aTableLock; /* Required table locks for shared-cache mode. Only | |
| 21103 | + ** valid if Parse.nTableLock>0 */ | |
| 21104 | +#endif | |
| 21105 | + | |
| 21000 | 21106 | |
| 21001 | 21107 | /************************************************************************ |
| 21002 | 21108 | ** Above is constant between recursions. Below is reset before and after |
| 21003 | 21109 | ** each recursion. The boundary between these two regions is determined |
| 21004 | 21110 | ** using offsetof(Parse,sLastToken) so the sLastToken field must be the |
| @@ -21942,10 +22048,11 @@ | ||
| 21942 | 22048 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 21943 | 22049 | SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); |
| 21944 | 22050 | #endif |
| 21945 | 22051 | #if defined(SQLITE_TEST) |
| 21946 | 22052 | SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); |
| 22053 | +SQLITE_PRIVATE const char *sqlite3TestPtrToText(void*); | |
| 21947 | 22054 | #endif |
| 21948 | 22055 | |
| 21949 | 22056 | #if defined(SQLITE_DEBUG) |
| 21950 | 22057 | SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView*, const char *zFormat, ...); |
| 21951 | 22058 | SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); |
| @@ -22166,10 +22273,11 @@ | ||
| 22166 | 22273 | SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*); |
| 22167 | 22274 | SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); |
| 22168 | 22275 | SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*); |
| 22169 | 22276 | SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); |
| 22170 | 22277 | SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**); |
| 22278 | +SQLITE_PRIVATE int sqlite3IndexBloomable(const Index*,int); | |
| 22171 | 22279 | SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, |
| 22172 | 22280 | Expr*, int, int, u8); |
| 22173 | 22281 | SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); |
| 22174 | 22282 | SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); |
| 22175 | 22283 | SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, |
| @@ -22528,10 +22636,11 @@ | ||
| 22528 | 22636 | SQLITE_PRIVATE const unsigned char *sqlite3aEQb; |
| 22529 | 22637 | SQLITE_PRIVATE const unsigned char *sqlite3aGTb; |
| 22530 | 22638 | SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; |
| 22531 | 22639 | SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config; |
| 22532 | 22640 | SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; |
| 22641 | +SQLITE_PRIVATE const sqlite3_str sqlite3OomStr; | |
| 22533 | 22642 | #ifndef SQLITE_OMIT_WSD |
| 22534 | 22643 | SQLITE_PRIVATE int sqlite3PendingByte; |
| 22535 | 22644 | #endif |
| 22536 | 22645 | #endif /* SQLITE_AMALGAMATION */ |
| 22537 | 22646 | #ifdef VDBE_PROFILE |
| @@ -22630,11 +22739,10 @@ | ||
| 22630 | 22739 | SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); |
| 22631 | 22740 | SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, i64); |
| 22632 | 22741 | SQLITE_PRIVATE int sqlite3StrAccumEnlargeIfNeeded(StrAccum*, i64); |
| 22633 | 22742 | SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); |
| 22634 | 22743 | SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum*, u8); |
| 22635 | -SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*); | |
| 22636 | 22744 | SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); |
| 22637 | 22745 | SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); |
| 22638 | 22746 | SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3*,const char*); |
| 22639 | 22747 | SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3*,const Expr*); |
| 22640 | 22748 | |
| @@ -23578,10 +23686,13 @@ | ||
| 23578 | 23686 | "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT), |
| 23579 | 23687 | #endif |
| 23580 | 23688 | #ifdef SQLITE_MAX_PAGE_SIZE |
| 23581 | 23689 | "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE), |
| 23582 | 23690 | #endif |
| 23691 | +#ifdef SQLITE_MAX_SCHEMA | |
| 23692 | + "MAX_SCHEMA=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA), | |
| 23693 | +#endif | |
| 23583 | 23694 | #ifdef SQLITE_MAX_SCHEMA_RETRY |
| 23584 | 23695 | "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY), |
| 23585 | 23696 | #endif |
| 23586 | 23697 | #ifdef SQLITE_MAX_SQL_LENGTH |
| 23587 | 23698 | "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH), |
| @@ -24228,10 +24339,20 @@ | ||
| 24228 | 24339 | ** Hash table for global functions - functions common to all |
| 24229 | 24340 | ** database connections. After initialization, this table is |
| 24230 | 24341 | ** read-only. |
| 24231 | 24342 | */ |
| 24232 | 24343 | SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; |
| 24344 | + | |
| 24345 | +/* | |
| 24346 | +** This singleton is an sqlite3_str object that is returned if | |
| 24347 | +** sqlite3_malloc() fails to provide space for a real one. This | |
| 24348 | +** sqlite3_str object accepts no new text and always returns | |
| 24349 | +** an SQLITE_NOMEM error. | |
| 24350 | +*/ | |
| 24351 | +SQLITE_PRIVATE const sqlite3_str sqlite3OomStr = { | |
| 24352 | + 0, 0, 0, 0, 0, SQLITE_NOMEM, 0 | |
| 24353 | +}; | |
| 24233 | 24354 | |
| 24234 | 24355 | #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) |
| 24235 | 24356 | /* |
| 24236 | 24357 | ** Counter used for coverage testing. Does not come into play for |
| 24237 | 24358 | ** release builds. |
| @@ -26297,10 +26418,53 @@ | ||
| 26297 | 26418 | clearYMD_HMS_TZ(p); |
| 26298 | 26419 | rc = 0; |
| 26299 | 26420 | p->nFloor = 0; |
| 26300 | 26421 | } |
| 26301 | 26422 | break; |
| 26423 | + } | |
| 26424 | + case 'e': { | |
| 26425 | + /* | |
| 26426 | + ** end of day | |
| 26427 | + ** end of month | |
| 26428 | + ** end of year | |
| 26429 | + ** | |
| 26430 | + ** Move the date forwards to the last millisecond of the current | |
| 26431 | + ** day, month or year. | |
| 26432 | + */ | |
| 26433 | + if( sqlite3_strnicmp(z, "end of ", 7)!=0 ){ | |
| 26434 | + break; | |
| 26435 | + } | |
| 26436 | + if( !p->validJD && !p->validYMD && !p->validHMS ) break; | |
| 26437 | + z += 7; | |
| 26438 | + computeYMD(p); | |
| 26439 | + p->validHMS = 1; | |
| 26440 | + p->h = 23; | |
| 26441 | + p->m = 59; | |
| 26442 | + p->s = 59.999; | |
| 26443 | + p->rawS = 0; | |
| 26444 | + p->tz = 0; | |
| 26445 | + p->validJD = 0; | |
| 26446 | + if( sqlite3_stricmp(z,"month")==0 ){ | |
| 26447 | + p->D = 1; | |
| 26448 | + p->M++; | |
| 26449 | + if( p->M>12 ){ | |
| 26450 | + p->Y++; | |
| 26451 | + p->M = 1; | |
| 26452 | + } | |
| 26453 | + computeFloor(p); | |
| 26454 | + computeJD(p); | |
| 26455 | + p->iJD -= (p->nFloor+1)*86400000; | |
| 26456 | + clearYMD_HMS_TZ(p); | |
| 26457 | + rc = 0; | |
| 26458 | + }else if( sqlite3_stricmp(z,"year")==0 ){ | |
| 26459 | + p->M = 12; | |
| 26460 | + p->D = 31; | |
| 26461 | + rc = 0; | |
| 26462 | + }else if( sqlite3_stricmp(z,"day")==0 ){ | |
| 26463 | + rc = 0; | |
| 26464 | + } | |
| 26465 | + break; | |
| 26302 | 26466 | } |
| 26303 | 26467 | case 'f': { |
| 26304 | 26468 | /* |
| 26305 | 26469 | ** floor |
| 26306 | 26470 | ** |
| @@ -26400,34 +26564,44 @@ | ||
| 26400 | 26564 | break; |
| 26401 | 26565 | } |
| 26402 | 26566 | case 'w': { |
| 26403 | 26567 | /* |
| 26404 | 26568 | ** weekday N |
| 26569 | + ** weekday -N | |
| 26405 | 26570 | ** |
| 26406 | - ** Move the date to the same time on the next occurrence of | |
| 26407 | - ** weekday N where 0==Sunday, 1==Monday, and so forth. If the | |
| 26408 | - ** date is already on the appropriate weekday, this is a no-op. | |
| 26571 | + ** Move the date forward (for N>=0) or backward (for N<=-0) to the | |
| 26572 | + ** same time on the next/previous occurrence of weekday abs(N) | |
| 26573 | + ** where 0==Sunday, 1==Monday, and so forth. If the date is already | |
| 26574 | + ** on the appropriate weekday, this is a no-op. | |
| 26409 | 26575 | */ |
| 26410 | 26576 | if( sqlite3_strnicmp(z, "weekday ", 8)==0 |
| 26411 | - && sqlite3AtoF(&z[8], &r)>0 | |
| 26412 | - && r>=0.0 && r<7.0 && (n=(int)r)==r ){ | |
| 26577 | + && sqlite3AtoF(&z[8], &r)>0 | |
| 26578 | + && r>=-6.0 && r<=6.0 | |
| 26579 | + && sqlite3RealSameAsInt(r,(i64)(n=(int)r)) | |
| 26580 | + ){ | |
| 26413 | 26581 | sqlite3_int64 Z; |
| 26414 | 26582 | computeYMD_HMS(p); |
| 26415 | 26583 | p->tz = 0; |
| 26416 | 26584 | p->validJD = 0; |
| 26417 | 26585 | computeJD(p); |
| 26418 | 26586 | Z = ((p->iJD + 129600000)/86400000) % 7; |
| 26419 | - if( Z>n ) Z -= 7; | |
| 26420 | - p->iJD += (n - Z)*86400000; | |
| 26587 | + if( n<0 ) n = -n; | |
| 26588 | + if( Z!=n ){ | |
| 26589 | + if( Z>n ) Z -= 7; | |
| 26590 | + p->iJD += (n - Z)*86400000; | |
| 26591 | + if( strchr(z+8,'-')!=0 ) p->iJD -= 7*86400000; | |
| 26592 | + } | |
| 26421 | 26593 | clearYMD_HMS_TZ(p); |
| 26422 | 26594 | rc = 0; |
| 26423 | 26595 | } |
| 26424 | 26596 | break; |
| 26425 | 26597 | } |
| 26426 | 26598 | case 's': { |
| 26427 | 26599 | /* |
| 26428 | - ** start of TTTTT | |
| 26600 | + ** start of day | |
| 26601 | + ** start of month | |
| 26602 | + ** start of year | |
| 26429 | 26603 | ** |
| 26430 | 26604 | ** Move the date backwards to the beginning of the current day, |
| 26431 | 26605 | ** or month or year. |
| 26432 | 26606 | ** |
| 26433 | 26607 | ** subsecond |
| @@ -26947,42 +27121,42 @@ | ||
| 26947 | 27121 | ){ |
| 26948 | 27122 | DateTime x; |
| 26949 | 27123 | size_t i,j; |
| 26950 | 27124 | sqlite3 *db; |
| 26951 | 27125 | const char *zFmt; |
| 26952 | - sqlite3_str sRes; | |
| 27126 | + sqlite3_str *pRes; | |
| 26953 | 27127 | |
| 26954 | 27128 | |
| 26955 | 27129 | if( argc==0 ) return; |
| 26956 | 27130 | zFmt = (const char*)sqlite3_value_text(argv[0]); |
| 26957 | 27131 | if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return; |
| 26958 | 27132 | db = sqlite3_context_db_handle(context); |
| 26959 | - sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); | |
| 27133 | + pRes = sqlite3_str_new(db); | |
| 26960 | 27134 | |
| 26961 | 27135 | computeJD(&x); |
| 26962 | 27136 | computeYMD_HMS(&x); |
| 26963 | 27137 | for(i=j=0; zFmt[i]; i++){ |
| 26964 | 27138 | char cf; |
| 26965 | 27139 | if( zFmt[i]!='%' ) continue; |
| 26966 | - if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j)); | |
| 27140 | + if( j<i ) sqlite3_str_append(pRes, zFmt+j, (int)(i-j)); | |
| 26967 | 27141 | i++; |
| 26968 | 27142 | j = i + 1; |
| 26969 | 27143 | cf = zFmt[i]; |
| 26970 | 27144 | switch( cf ){ |
| 26971 | 27145 | case 'd': /* Fall thru */ |
| 26972 | 27146 | case 'e': { |
| 26973 | - sqlite3_str_appendf(&sRes, cf=='d' ? "%02d" : "%2d", x.D); | |
| 27147 | + sqlite3_str_appendf(pRes, cf=='d' ? "%02d" : "%2d", x.D); | |
| 26974 | 27148 | break; |
| 26975 | 27149 | } |
| 26976 | 27150 | case 'f': { /* Fractional seconds. (Non-standard) */ |
| 26977 | 27151 | double s = x.s; |
| 26978 | 27152 | if( NEVER(s>59.999) ) s = 59.999; |
| 26979 | - sqlite3_str_appendf(&sRes, "%06.3f", s); | |
| 27153 | + sqlite3_str_appendf(pRes, "%06.3f", s); | |
| 26980 | 27154 | break; |
| 26981 | 27155 | } |
| 26982 | 27156 | case 'F': { |
| 26983 | - sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D); | |
| 27157 | + sqlite3_str_appendf(pRes, "%04d-%02d-%02d", x.Y, x.M, x.D); | |
| 26984 | 27158 | break; |
| 26985 | 27159 | } |
| 26986 | 27160 | case 'G': /* Fall thru */ |
| 26987 | 27161 | case 'g': { |
| 26988 | 27162 | DateTime y = x; |
| @@ -26990,85 +27164,85 @@ | ||
| 26990 | 27164 | /* Move y so that it is the Thursday in the same week as x */ |
| 26991 | 27165 | y.iJD += (3 - daysAfterMonday(&x))*86400000; |
| 26992 | 27166 | y.validYMD = 0; |
| 26993 | 27167 | computeYMD(&y); |
| 26994 | 27168 | if( cf=='g' ){ |
| 26995 | - sqlite3_str_appendf(&sRes, "%02d", y.Y%100); | |
| 27169 | + sqlite3_str_appendf(pRes, "%02d", y.Y%100); | |
| 26996 | 27170 | }else{ |
| 26997 | - sqlite3_str_appendf(&sRes, "%04d", y.Y); | |
| 27171 | + sqlite3_str_appendf(pRes, "%04d", y.Y); | |
| 26998 | 27172 | } |
| 26999 | 27173 | break; |
| 27000 | 27174 | } |
| 27001 | 27175 | case 'H': |
| 27002 | 27176 | case 'k': { |
| 27003 | - sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h); | |
| 27177 | + sqlite3_str_appendf(pRes, cf=='H' ? "%02d" : "%2d", x.h); | |
| 27004 | 27178 | break; |
| 27005 | 27179 | } |
| 27006 | 27180 | case 'I': /* Fall thru */ |
| 27007 | 27181 | case 'l': { |
| 27008 | 27182 | int h = x.h; |
| 27009 | 27183 | if( h>12 ) h -= 12; |
| 27010 | 27184 | if( h==0 ) h = 12; |
| 27011 | - sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h); | |
| 27185 | + sqlite3_str_appendf(pRes, cf=='I' ? "%02d" : "%2d", h); | |
| 27012 | 27186 | break; |
| 27013 | 27187 | } |
| 27014 | 27188 | case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */ |
| 27015 | - sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1); | |
| 27189 | + sqlite3_str_appendf(pRes,"%03d",daysAfterJan01(&x)+1); | |
| 27016 | 27190 | break; |
| 27017 | 27191 | } |
| 27018 | 27192 | case 'J': { /* Julian day number. (Non-standard) */ |
| 27019 | - sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0); | |
| 27193 | + sqlite3_str_appendf(pRes,"%.16g",x.iJD/86400000.0); | |
| 27020 | 27194 | break; |
| 27021 | 27195 | } |
| 27022 | 27196 | case 'm': { |
| 27023 | - sqlite3_str_appendf(&sRes,"%02d",x.M); | |
| 27197 | + sqlite3_str_appendf(pRes,"%02d",x.M); | |
| 27024 | 27198 | break; |
| 27025 | 27199 | } |
| 27026 | 27200 | case 'M': { |
| 27027 | - sqlite3_str_appendf(&sRes,"%02d",x.m); | |
| 27201 | + sqlite3_str_appendf(pRes,"%02d",x.m); | |
| 27028 | 27202 | break; |
| 27029 | 27203 | } |
| 27030 | 27204 | case 'p': /* Fall thru */ |
| 27031 | 27205 | case 'P': { |
| 27032 | 27206 | if( x.h>=12 ){ |
| 27033 | - sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2); | |
| 27207 | + sqlite3_str_append(pRes, cf=='p' ? "PM" : "pm", 2); | |
| 27034 | 27208 | }else{ |
| 27035 | - sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2); | |
| 27209 | + sqlite3_str_append(pRes, cf=='p' ? "AM" : "am", 2); | |
| 27036 | 27210 | } |
| 27037 | 27211 | break; |
| 27038 | 27212 | } |
| 27039 | 27213 | case 'R': { |
| 27040 | - sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m); | |
| 27214 | + sqlite3_str_appendf(pRes, "%02d:%02d", x.h, x.m); | |
| 27041 | 27215 | break; |
| 27042 | 27216 | } |
| 27043 | 27217 | case 's': { |
| 27044 | 27218 | if( x.useSubsec ){ |
| 27045 | - sqlite3_str_appendf(&sRes,"%.3f", | |
| 27219 | + sqlite3_str_appendf(pRes,"%.3f", | |
| 27046 | 27220 | (x.iJD - 21086676*(i64)10000000)/1000.0); |
| 27047 | 27221 | }else{ |
| 27048 | 27222 | i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000); |
| 27049 | - sqlite3_str_appendf(&sRes,"%lld",iS); | |
| 27223 | + sqlite3_str_appendf(pRes,"%lld",iS); | |
| 27050 | 27224 | } |
| 27051 | 27225 | break; |
| 27052 | 27226 | } |
| 27053 | 27227 | case 'S': { |
| 27054 | - sqlite3_str_appendf(&sRes,"%02d",(int)x.s); | |
| 27228 | + sqlite3_str_appendf(pRes,"%02d",(int)x.s); | |
| 27055 | 27229 | break; |
| 27056 | 27230 | } |
| 27057 | 27231 | case 'T': { |
| 27058 | - sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s); | |
| 27232 | + sqlite3_str_appendf(pRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s); | |
| 27059 | 27233 | break; |
| 27060 | 27234 | } |
| 27061 | 27235 | case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */ |
| 27062 | 27236 | case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */ |
| 27063 | 27237 | char c = (char)daysAfterSunday(&x) + '0'; |
| 27064 | 27238 | if( c=='0' && cf=='u' ) c = '7'; |
| 27065 | - sqlite3_str_appendchar(&sRes, 1, c); | |
| 27239 | + sqlite3_str_appendchar(pRes, 1, c); | |
| 27066 | 27240 | break; |
| 27067 | 27241 | } |
| 27068 | 27242 | case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */ |
| 27069 | - sqlite3_str_appendf(&sRes,"%02d", | |
| 27243 | + sqlite3_str_appendf(pRes,"%02d", | |
| 27070 | 27244 | (daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7); |
| 27071 | 27245 | break; |
| 27072 | 27246 | } |
| 27073 | 27247 | case 'V': { /* Week num. 01-53. First week with a Thur is week 01 */ |
| 27074 | 27248 | DateTime y = x; |
| @@ -27075,34 +27249,34 @@ | ||
| 27075 | 27249 | /* Adjust y so that is the Thursday in the same week as x */ |
| 27076 | 27250 | assert( y.validJD ); |
| 27077 | 27251 | y.iJD += (3 - daysAfterMonday(&x))*86400000; |
| 27078 | 27252 | y.validYMD = 0; |
| 27079 | 27253 | computeYMD(&y); |
| 27080 | - sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1); | |
| 27254 | + sqlite3_str_appendf(pRes,"%02d", daysAfterJan01(&y)/7+1); | |
| 27081 | 27255 | break; |
| 27082 | 27256 | } |
| 27083 | 27257 | case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */ |
| 27084 | - sqlite3_str_appendf(&sRes,"%02d", | |
| 27258 | + sqlite3_str_appendf(pRes,"%02d", | |
| 27085 | 27259 | (daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7); |
| 27086 | 27260 | break; |
| 27087 | 27261 | } |
| 27088 | 27262 | case 'Y': { |
| 27089 | - sqlite3_str_appendf(&sRes,"%04d",x.Y); | |
| 27263 | + sqlite3_str_appendf(pRes,"%04d",x.Y); | |
| 27090 | 27264 | break; |
| 27091 | 27265 | } |
| 27092 | 27266 | case '%': { |
| 27093 | - sqlite3_str_appendchar(&sRes, 1, '%'); | |
| 27267 | + sqlite3_str_appendchar(pRes, 1, '%'); | |
| 27094 | 27268 | break; |
| 27095 | 27269 | } |
| 27096 | 27270 | default: { |
| 27097 | - sqlite3_str_reset(&sRes); | |
| 27271 | + sqlite3_str_free(pRes); | |
| 27098 | 27272 | return; |
| 27099 | 27273 | } |
| 27100 | 27274 | } |
| 27101 | 27275 | } |
| 27102 | - if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j)); | |
| 27103 | - sqlite3ResultStrAccum(context, &sRes); | |
| 27276 | + if( j<i ) sqlite3_str_append(pRes, zFmt+j, (int)(i-j)); | |
| 27277 | + sqlite3_result_str(context, pRes, SQLITE_FINISH); | |
| 27104 | 27278 | } |
| 27105 | 27279 | |
| 27106 | 27280 | /* |
| 27107 | 27281 | ** current_time() |
| 27108 | 27282 | ** |
| @@ -27234,11 +27408,11 @@ | ||
| 27234 | 27408 | clearYMD_HMS_TZ(&d1); |
| 27235 | 27409 | computeYMD_HMS(&d1); |
| 27236 | 27410 | sqlite3StrAccumInit(&sRes, 0, 0, 0, 100); |
| 27237 | 27411 | sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f", |
| 27238 | 27412 | sign, Y, M, d1.D-1, d1.h, d1.m, d1.s); |
| 27239 | - sqlite3ResultStrAccum(context, &sRes); | |
| 27413 | + sqlite3_result_str(context, &sRes, SQLITE_XFER); | |
| 27240 | 27414 | } |
| 27241 | 27415 | |
| 27242 | 27416 | |
| 27243 | 27417 | /* |
| 27244 | 27418 | ** current_timestamp() |
| @@ -27662,11 +27836,11 @@ | ||
| 27662 | 27836 | if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ |
| 27663 | 27837 | rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut); |
| 27664 | 27838 | }else{ |
| 27665 | 27839 | double r; |
| 27666 | 27840 | rc = pVfs->xCurrentTime(pVfs, &r); |
| 27667 | - *pTimeOut = (sqlite3_int64)(r*86400000.0); | |
| 27841 | + *pTimeOut = sqlite3RealToI64(r*86400000.0); | |
| 27668 | 27842 | } |
| 27669 | 27843 | return rc; |
| 27670 | 27844 | } |
| 27671 | 27845 | |
| 27672 | 27846 | SQLITE_PRIVATE int sqlite3OsOpenMalloc( |
| @@ -32612,10 +32786,14 @@ | ||
| 32612 | 32786 | */ |
| 32613 | 32787 | #ifndef SQLITE_PRINTF_PRECISION_LIMIT |
| 32614 | 32788 | # define SQLITE_FP_PRECISION_LIMIT 100000000 |
| 32615 | 32789 | #endif |
| 32616 | 32790 | |
| 32791 | +/* Forward reference */ | |
| 32792 | +static void sqlite3StrAppend64(sqlite3_str *p, const char *z, i64 N); | |
| 32793 | +static void sqlite3StrAppendchar64(sqlite3_str *p, i64 N, char c); | |
| 32794 | + | |
| 32617 | 32795 | /* |
| 32618 | 32796 | ** Render a string given by "fmt" into the StrAccum object. |
| 32619 | 32797 | */ |
| 32620 | 32798 | SQLITE_API void sqlite3_str_vappendf( |
| 32621 | 32799 | sqlite3_str *pAccum, /* Accumulate results here */ |
| @@ -32622,14 +32800,14 @@ | ||
| 32622 | 32800 | const char *fmt, /* Format string */ |
| 32623 | 32801 | va_list ap /* arguments */ |
| 32624 | 32802 | ){ |
| 32625 | 32803 | int c; /* Next character in the format string */ |
| 32626 | 32804 | char *bufpt; /* Pointer to the conversion buffer */ |
| 32627 | - int precision; /* Precision of the current field */ | |
| 32628 | - int length; /* Length of the field */ | |
| 32805 | + i64 precision; /* Precision of the current field */ | |
| 32806 | + i64 length; /* Length of the field */ | |
| 32629 | 32807 | int idx; /* A general purpose loop counter */ |
| 32630 | - int width; /* Width of the current field */ | |
| 32808 | + i64 width; /* Width of the current field */ | |
| 32631 | 32809 | etByte flag_leftjustify; /* True if "-" flag is present */ |
| 32632 | 32810 | etByte flag_prefix; /* '+' or ' ' or 0 for prefix */ |
| 32633 | 32811 | etByte flag_alternateform; /* True if "#" flag is present */ |
| 32634 | 32812 | etByte flag_altform2; /* True if "!" flag is present */ |
| 32635 | 32813 | etByte flag_zeropad; /* True if field width constant starts with zero */ |
| @@ -32673,11 +32851,11 @@ | ||
| 32673 | 32851 | fmt = strchr(fmt, '%'); |
| 32674 | 32852 | if( fmt==0 ){ |
| 32675 | 32853 | fmt = bufpt + strlen(bufpt); |
| 32676 | 32854 | } |
| 32677 | 32855 | #endif |
| 32678 | - sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt)); | |
| 32856 | + sqlite3StrAppend64(pAccum, bufpt, fmt - bufpt); | |
| 32679 | 32857 | if( *fmt==0 ) break; |
| 32680 | 32858 | } |
| 32681 | 32859 | if( (c=(*++fmt))==0 ){ |
| 32682 | 32860 | sqlite3_str_append(pAccum, "%", 1); |
| 32683 | 32861 | break; |
| @@ -32919,26 +33097,27 @@ | ||
| 32919 | 33097 | do{ /* Convert to ascii */ |
| 32920 | 33098 | *(--bufpt) = cset[longvalue%base]; |
| 32921 | 33099 | longvalue = longvalue/base; |
| 32922 | 33100 | }while( longvalue>0 ); |
| 32923 | 33101 | } |
| 32924 | - length = (int)(&zOut[nOut-1]-bufpt); | |
| 33102 | + length = &zOut[nOut-1] - bufpt; | |
| 32925 | 33103 | if( precision>length ){ /* zero pad */ |
| 32926 | - int nn = precision-length; | |
| 33104 | + i64 nn = precision-length; | |
| 32927 | 33105 | bufpt -= nn; |
| 32928 | 33106 | memset(bufpt,'0',nn); |
| 32929 | 33107 | length = precision; |
| 32930 | 33108 | } |
| 32931 | 33109 | if( cThousand ){ |
| 32932 | - int nn = (length - 1)/3; /* Number of "," to insert */ | |
| 32933 | - int ix = (length - 1)%3 + 1; | |
| 33110 | + i64 nn = (length - 1)/3; /* Number of "," to insert */ | |
| 33111 | + i64 ix = (length - 1)%3 + 1; | |
| 33112 | + int ii; | |
| 32934 | 33113 | bufpt -= nn; |
| 32935 | - for(idx=0; nn>0; idx++){ | |
| 32936 | - bufpt[idx] = bufpt[idx+nn]; | |
| 33114 | + for(ii=0; nn>0; ii++){ | |
| 33115 | + bufpt[ii] = bufpt[ii+nn]; | |
| 32937 | 33116 | ix--; |
| 32938 | 33117 | if( ix==0 ){ |
| 32939 | - bufpt[++idx] = cThousand; | |
| 33118 | + bufpt[++ii] = cThousand; | |
| 32940 | 33119 | nn--; |
| 32941 | 33120 | ix = 3; |
| 32942 | 33121 | } |
| 32943 | 33122 | } |
| 32944 | 33123 | } |
| @@ -32947,11 +33126,11 @@ | ||
| 32947 | 33126 | const char *pre; |
| 32948 | 33127 | char x; |
| 32949 | 33128 | pre = &aPrefix[infop->prefix]; |
| 32950 | 33129 | for(; (x=(*pre))!=0; pre++) *(--bufpt) = x; |
| 32951 | 33130 | } |
| 32952 | - length = (int)(&zOut[nOut-1]-bufpt); | |
| 33131 | + length = &zOut[nOut-1] - bufpt; | |
| 32953 | 33132 | break; |
| 32954 | 33133 | case etFLOAT: |
| 32955 | 33134 | case etEXP: |
| 32956 | 33135 | case etGENERIC: { |
| 32957 | 33136 | FpDecode s; |
| @@ -32979,12 +33158,17 @@ | ||
| 32979 | 33158 | iRound = precision+1; |
| 32980 | 33159 | } |
| 32981 | 33160 | sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 20 : 16); |
| 32982 | 33161 | if( s.isSpecial ){ |
| 32983 | 33162 | if( s.isSpecial==2 ){ |
| 32984 | - bufpt = flag_zeropad ? "null" : "NaN"; | |
| 32985 | - length = sqlite3Strlen30(bufpt); | |
| 33163 | + if( flag_zeropad ){ | |
| 33164 | + bufpt = "null"; | |
| 33165 | + length = 4; | |
| 33166 | + }else{ | |
| 33167 | + bufpt = "NaN"; | |
| 33168 | + length = 3; | |
| 33169 | + } | |
| 32986 | 33170 | break; |
| 32987 | 33171 | }else if( flag_zeropad ){ |
| 32988 | 33172 | s.z[0] = '9'; |
| 32989 | 33173 | s.iDP = 1000; |
| 32990 | 33174 | s.n = 1; |
| @@ -32996,11 +33180,11 @@ | ||
| 32996 | 33180 | }else if( flag_prefix ){ |
| 32997 | 33181 | buf[0] = flag_prefix; |
| 32998 | 33182 | }else{ |
| 32999 | 33183 | bufpt++; |
| 33000 | 33184 | } |
| 33001 | - length = sqlite3Strlen30(bufpt); | |
| 33185 | + length = strlen(bufpt); | |
| 33002 | 33186 | break; |
| 33003 | 33187 | } |
| 33004 | 33188 | } |
| 33005 | 33189 | if( s.sign=='-' ){ |
| 33006 | 33190 | if( flag_alternateform |
| @@ -33152,11 +33336,11 @@ | ||
| 33152 | 33336 | } |
| 33153 | 33337 | *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */ |
| 33154 | 33338 | *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */ |
| 33155 | 33339 | } |
| 33156 | 33340 | |
| 33157 | - length = (int)(bufpt-zOut); | |
| 33341 | + length = bufpt - zOut; | |
| 33158 | 33342 | assert( length <= szBufNeeded ); |
| 33159 | 33343 | if( length<width ){ |
| 33160 | 33344 | i64 nPad = width - length; |
| 33161 | 33345 | if( flag_leftjustify ){ |
| 33162 | 33346 | memset(bufpt, ' ', nPad); |
| @@ -33172,10 +33356,11 @@ | ||
| 33172 | 33356 | } |
| 33173 | 33357 | |
| 33174 | 33358 | if( zExtra==0 ){ |
| 33175 | 33359 | /* The result is being rendered directory into pAccum. This |
| 33176 | 33360 | ** is the common and fast case */ |
| 33361 | + assert( pAccum->nChar + length < SMXV(pAccum->nChar) ); | |
| 33177 | 33362 | pAccum->nChar += length; |
| 33178 | 33363 | zOut[length] = 0; |
| 33179 | 33364 | continue; |
| 33180 | 33365 | }else{ |
| 33181 | 33366 | /* We were unable to render directly into pAccum because we |
| @@ -33218,14 +33403,14 @@ | ||
| 33218 | 33403 | } |
| 33219 | 33404 | if( precision>1 ){ |
| 33220 | 33405 | i64 nPrior = 1; |
| 33221 | 33406 | width -= precision-1; |
| 33222 | 33407 | if( width>1 && !flag_leftjustify ){ |
| 33223 | - sqlite3_str_appendchar(pAccum, width-1, ' '); | |
| 33408 | + sqlite3StrAppendchar64(pAccum, width-1, ' '); | |
| 33224 | 33409 | width = 0; |
| 33225 | 33410 | } |
| 33226 | - sqlite3_str_append(pAccum, buf, length); | |
| 33411 | + sqlite3StrAppend64(pAccum, buf, length); | |
| 33227 | 33412 | precision--; |
| 33228 | 33413 | while( precision > 1 ){ |
| 33229 | 33414 | i64 nCopyBytes; |
| 33230 | 33415 | if( nPrior > precision-1 ) nPrior = precision - 1; |
| 33231 | 33416 | nCopyBytes = length*nPrior; |
| @@ -33277,21 +33462,21 @@ | ||
| 33277 | 33462 | ** precision characters */ |
| 33278 | 33463 | unsigned char *z = (unsigned char*)bufpt; |
| 33279 | 33464 | while( precision-- > 0 && z[0] ){ |
| 33280 | 33465 | SQLITE_SKIP_UTF8(z); |
| 33281 | 33466 | } |
| 33282 | - length = (int)(z - (unsigned char*)bufpt); | |
| 33467 | + length = z - (unsigned char*)bufpt; | |
| 33283 | 33468 | }else{ |
| 33284 | 33469 | for(length=0; length<precision && bufpt[length]; length++){} |
| 33285 | 33470 | } |
| 33286 | 33471 | }else{ |
| 33287 | - length = 0x7fffffff & (int)strlen(bufpt); | |
| 33472 | + length = strlen(bufpt); | |
| 33288 | 33473 | } |
| 33289 | 33474 | adjust_width_for_utf8: |
| 33290 | 33475 | if( flag_altform2 && width>0 ){ |
| 33291 | 33476 | /* Adjust width to account for extra bytes in UTF-8 characters */ |
| 33292 | - int ii = length - 1; | |
| 33477 | + i64 ii = length - 1; | |
| 33293 | 33478 | while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++; |
| 33294 | 33479 | } |
| 33295 | 33480 | break; |
| 33296 | 33481 | case etESCAPE_j: /* %j: JSON string literal w/o "..." */ |
| 33297 | 33482 | case etESCAPE_J: { /* %J: Generate a JSON string literal */ |
| @@ -33322,11 +33507,11 @@ | ||
| 33322 | 33507 | while( (escarg[px]&0xc0)==0x80 ) px++; |
| 33323 | 33508 | } |
| 33324 | 33509 | } |
| 33325 | 33510 | for(i=j=0; i<px; i++){ |
| 33326 | 33511 | if( (ch = ((u8*)escarg)[i])<=0x1f || ch=='"' || ch=='\\' ){ |
| 33327 | - if( j<i ) sqlite3_str_append(pAccum, &escarg[j], i-j); | |
| 33512 | + if( j<i ) sqlite3StrAppend64(pAccum, &escarg[j], i-j); | |
| 33328 | 33513 | j = i+1; |
| 33329 | 33514 | if( ch==0 ) break; |
| 33330 | 33515 | sqlite3_str_appendchar(pAccum, 1, '\\'); |
| 33331 | 33516 | if( ch>0x1f ){ |
| 33332 | 33517 | sqlite3_str_appendchar(pAccum, 1, ch); |
| @@ -33338,11 +33523,11 @@ | ||
| 33338 | 33523 | sqlite3_str_appendchar(pAccum, 1, aHex[ch>>4]); |
| 33339 | 33524 | sqlite3_str_appendchar(pAccum, 1, aHex[ch&0xf]); |
| 33340 | 33525 | } |
| 33341 | 33526 | } |
| 33342 | 33527 | } |
| 33343 | - if( j<i ) sqlite3_str_append(pAccum, &escarg[j], i-j); | |
| 33528 | + if( j<i ) sqlite3StrAppend64(pAccum, &escarg[j], i-j); | |
| 33344 | 33529 | if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "\"", 1); |
| 33345 | 33530 | } |
| 33346 | 33531 | if( width>0 && sqlite3_str_errcode(pAccum)==SQLITE_OK ){ |
| 33347 | 33532 | sqlite3_int64 n = sqlite3_str_length(pAccum) - iStart; |
| 33348 | 33533 | sqlite3_int64 len = n; |
| @@ -33354,11 +33539,11 @@ | ||
| 33354 | 33539 | } |
| 33355 | 33540 | } |
| 33356 | 33541 | if( width>len ){ |
| 33357 | 33542 | sqlite3_int64 sp = width-len; |
| 33358 | 33543 | assert( sp>0 && sp<0x7fffffff ); |
| 33359 | - sqlite3_str_appendchar(pAccum, (int)sp, ' '); | |
| 33544 | + sqlite3StrAppendchar64(pAccum, (int)sp, ' '); | |
| 33360 | 33545 | if( !flag_leftjustify |
| 33361 | 33546 | && n>0 |
| 33362 | 33547 | && sqlite3_str_errcode(pAccum)==0 |
| 33363 | 33548 | ){ |
| 33364 | 33549 | zz = sqlite3_str_value(pAccum); |
| @@ -33546,15 +33731,15 @@ | ||
| 33546 | 33731 | ** indicating that width and precision should be expressed in characters, |
| 33547 | 33732 | ** then the values have been translated prior to reaching this point. |
| 33548 | 33733 | */ |
| 33549 | 33734 | width -= length; |
| 33550 | 33735 | if( width>0 ){ |
| 33551 | - if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); | |
| 33552 | - sqlite3_str_append(pAccum, bufpt, length); | |
| 33553 | - if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); | |
| 33736 | + if( !flag_leftjustify ) sqlite3StrAppendchar64(pAccum, width, ' '); | |
| 33737 | + sqlite3StrAppend64(pAccum, bufpt, length); | |
| 33738 | + if( flag_leftjustify ) sqlite3StrAppendchar64(pAccum, width, ' '); | |
| 33554 | 33739 | }else{ |
| 33555 | - sqlite3_str_append(pAccum, bufpt, length); | |
| 33740 | + sqlite3StrAppend64(pAccum, bufpt, length); | |
| 33556 | 33741 | } |
| 33557 | 33742 | |
| 33558 | 33743 | if( zExtra ){ |
| 33559 | 33744 | sqlite3DbFree(pAccum->db, zExtra); |
| 33560 | 33745 | zExtra = 0; |
| @@ -33670,10 +33855,17 @@ | ||
| 33670 | 33855 | if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ |
| 33671 | 33856 | return; |
| 33672 | 33857 | } |
| 33673 | 33858 | while( (N--)>0 ) p->zText[p->nChar++] = c; |
| 33674 | 33859 | } |
| 33860 | +static void sqlite3StrAppendchar64(sqlite3_str *p, i64 N, char c){ | |
| 33861 | + testcase( p->nChar + N > 0x7fffffff ); | |
| 33862 | + if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ | |
| 33863 | + return; | |
| 33864 | + } | |
| 33865 | + while( (N--)>0 ) p->zText[p->nChar++] = c; | |
| 33866 | +} | |
| 33675 | 33867 | |
| 33676 | 33868 | /* |
| 33677 | 33869 | ** The StrAccum "p" is not large enough to accept N new bytes of z[]. |
| 33678 | 33870 | ** So enlarge if first, then do the append. |
| 33679 | 33871 | ** |
| @@ -33681,10 +33873,11 @@ | ||
| 33681 | 33873 | ** work (enlarging the buffer) using tail recursion, so that the |
| 33682 | 33874 | ** sqlite3_str_append() routine can use fast calling semantics. |
| 33683 | 33875 | */ |
| 33684 | 33876 | static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ |
| 33685 | 33877 | N = sqlite3StrAccumEnlarge(p, N); |
| 33878 | + assert( z!=0 || N==0 ); | |
| 33686 | 33879 | if( N>0 ){ |
| 33687 | 33880 | memcpy(&p->zText[p->nChar], z, N); |
| 33688 | 33881 | p->nChar += N; |
| 33689 | 33882 | } |
| 33690 | 33883 | } |
| @@ -33704,10 +33897,24 @@ | ||
| 33704 | 33897 | assert( p->zText ); |
| 33705 | 33898 | p->nChar += N; |
| 33706 | 33899 | memcpy(&p->zText[p->nChar-N], z, N); |
| 33707 | 33900 | } |
| 33708 | 33901 | } |
| 33902 | +static void sqlite3StrAppend64(sqlite3_str *p, const char *z, i64 N){ | |
| 33903 | + assert( z!=0 || N==0 ); | |
| 33904 | + assert( p->zText!=0 || p->nChar==0 || p->accError ); | |
| 33905 | + assert( N>=0 ); | |
| 33906 | + assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 ); | |
| 33907 | + if( p->nChar+N >= (i64)p->nAlloc ){ | |
| 33908 | + enlargeAndAppend(p,z,N); | |
| 33909 | + }else if( N ){ | |
| 33910 | + assert( p->zText ); | |
| 33911 | + p->nChar += N; | |
| 33912 | + memcpy(&p->zText[p->nChar-N], z, N); | |
| 33913 | + } | |
| 33914 | +} | |
| 33915 | + | |
| 33709 | 33916 | |
| 33710 | 33917 | /* |
| 33711 | 33918 | ** Append the complete text of zero-terminated string z[] to the p string. |
| 33712 | 33919 | */ |
| 33713 | 33920 | SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){ |
| @@ -33741,41 +33948,15 @@ | ||
| 33741 | 33948 | } |
| 33742 | 33949 | } |
| 33743 | 33950 | return p->zText; |
| 33744 | 33951 | } |
| 33745 | 33952 | |
| 33746 | -/* | |
| 33747 | -** Use the content of the StrAccum passed as the second argument | |
| 33748 | -** as the result of an SQL function. | |
| 33749 | -*/ | |
| 33750 | -SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){ | |
| 33751 | - if( p->accError ){ | |
| 33752 | - sqlite3_result_error_code(pCtx, p->accError); | |
| 33753 | - sqlite3_str_reset(p); | |
| 33754 | - }else if( isMalloced(p) ){ | |
| 33755 | - sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC); | |
| 33756 | - }else{ | |
| 33757 | - sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); | |
| 33758 | - sqlite3_str_reset(p); | |
| 33759 | - } | |
| 33760 | -} | |
| 33761 | - | |
| 33762 | -/* | |
| 33763 | -** This singleton is an sqlite3_str object that is returned if | |
| 33764 | -** sqlite3_malloc() fails to provide space for a real one. This | |
| 33765 | -** sqlite3_str object accepts no new text and always returns | |
| 33766 | -** an SQLITE_NOMEM error. | |
| 33767 | -*/ | |
| 33768 | -static sqlite3_str sqlite3OomStr = { | |
| 33769 | - 0, 0, 0, 0, 0, SQLITE_NOMEM, 0 | |
| 33770 | -}; | |
| 33771 | - | |
| 33772 | 33953 | /* Finalize a string created using sqlite3_str_new(). |
| 33773 | 33954 | */ |
| 33774 | 33955 | SQLITE_API char *sqlite3_str_finish(sqlite3_str *p){ |
| 33775 | 33956 | char *z; |
| 33776 | - if( p!=0 && p!=&sqlite3OomStr ){ | |
| 33957 | + if( p!=0 && p!=(sqlite3_str*)&sqlite3OomStr ){ | |
| 33777 | 33958 | z = sqlite3StrAccumFinish(p); |
| 33778 | 33959 | sqlite3_free(p); |
| 33779 | 33960 | }else{ |
| 33780 | 33961 | z = 0; |
| 33781 | 33962 | } |
| @@ -33812,10 +33993,12 @@ | ||
| 33812 | 33993 | */ |
| 33813 | 33994 | SQLITE_API void sqlite3_str_reset(StrAccum *p){ |
| 33814 | 33995 | if( isMalloced(p) ){ |
| 33815 | 33996 | sqlite3DbFree(p->db, p->zText); |
| 33816 | 33997 | p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; |
| 33998 | + }else if( p==(sqlite3_str*)&sqlite3OomStr ){ | |
| 33999 | + return; | |
| 33817 | 34000 | } |
| 33818 | 34001 | p->nAlloc = 0; |
| 33819 | 34002 | p->nChar = 0; |
| 33820 | 34003 | p->zText = 0; |
| 33821 | 34004 | } |
| @@ -33823,11 +34006,11 @@ | ||
| 33823 | 34006 | /* |
| 33824 | 34007 | ** Destroy a dynamically allocate sqlite3_str object and all |
| 33825 | 34008 | ** of its content, all in one call. |
| 33826 | 34009 | */ |
| 33827 | 34010 | SQLITE_API void sqlite3_str_free(sqlite3_str *p){ |
| 33828 | - if( p!=0 && p!=&sqlite3OomStr ){ | |
| 34011 | + if( p!=0 && p!=(sqlite3_str*)&sqlite3OomStr ){ | |
| 33829 | 34012 | sqlite3_str_reset(p); |
| 33830 | 34013 | sqlite3_free(p); |
| 33831 | 34014 | } |
| 33832 | 34015 | } |
| 33833 | 34016 | |
| @@ -33860,11 +34043,11 @@ | ||
| 33860 | 34043 | sqlite3_str *p = sqlite3_malloc64(sizeof(*p)); |
| 33861 | 34044 | if( p ){ |
| 33862 | 34045 | sqlite3StrAccumInit(p, 0, 0, 0, |
| 33863 | 34046 | db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH); |
| 33864 | 34047 | }else{ |
| 33865 | - p = &sqlite3OomStr; | |
| 34048 | + p = (sqlite3_str*)&sqlite3OomStr; | |
| 33866 | 34049 | } |
| 33867 | 34050 | return p; |
| 33868 | 34051 | } |
| 33869 | 34052 | |
| 33870 | 34053 | /* |
| @@ -37500,11 +37683,11 @@ | ||
| 37500 | 37683 | return mState; |
| 37501 | 37684 | } |
| 37502 | 37685 | } |
| 37503 | 37686 | return 0xfffffff0 | mState; |
| 37504 | 37687 | #else |
| 37505 | - return sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8)==0; | |
| 37688 | + return sqlite3Atoi64(zIn, pResult, strlen(zIn), SQLITE_UTF8)==0; | |
| 37506 | 37689 | #endif /* SQLITE_OMIT_FLOATING_POINT */ |
| 37507 | 37690 | } |
| 37508 | 37691 | |
| 37509 | 37692 | /* |
| 37510 | 37693 | ** Digit pairs used to convert a U64 or I64 into text, two digits |
| @@ -39731,20 +39914,21 @@ | ||
| 39731 | 39914 | i = 0; |
| 39732 | 39915 | j = 0; |
| 39733 | 39916 | while( 1 ){ |
| 39734 | 39917 | c = kvvfsHexValue[aIn[i]]; |
| 39735 | 39918 | if( c<0 ){ |
| 39736 | - int n = 0; | |
| 39737 | - int mult = 1; | |
| 39919 | + sqlite3_int64 n = 0; | |
| 39920 | + sqlite3_int64 mult = 1; | |
| 39738 | 39921 | c = aIn[i]; |
| 39739 | 39922 | if( c==0 ) break; |
| 39740 | 39923 | while( c>='a' && c<='z' ){ |
| 39741 | 39924 | n += (c - 'a')*mult; |
| 39925 | + if( n>nOut ) return -1 /* oversized/malformed input */; | |
| 39742 | 39926 | mult *= 26; |
| 39743 | 39927 | c = aIn[++i]; |
| 39744 | 39928 | } |
| 39745 | - if( j+n>nOut ) return -1; | |
| 39929 | + if( j+n>nOut ) return -1 /* oversized/malformed input */; | |
| 39746 | 39930 | memset(&aOut[j], 0, n); |
| 39747 | 39931 | j += n; |
| 39748 | 39932 | if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */ |
| 39749 | 39933 | }else if( j<nOut ){ |
| 39750 | 39934 | aOut[j] = c<<4; |
| @@ -39773,22 +39957,28 @@ | ||
| 39773 | 39957 | static void kvvfsDecodeJournal( |
| 39774 | 39958 | KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */ |
| 39775 | 39959 | const char *zTxt, /* Text encoding. Zero-terminated */ |
| 39776 | 39960 | int nTxt /* Bytes in zTxt, excluding zero terminator */ |
| 39777 | 39961 | ){ |
| 39778 | - unsigned int n = 0; | |
| 39779 | - int c, i, mult; | |
| 39962 | + unsigned int n = 0, mult; | |
| 39963 | + int c, i; | |
| 39780 | 39964 | i = 0; |
| 39781 | 39965 | mult = 1; |
| 39782 | - while( (c = zTxt[i++])>='a' && c<='z' ){ | |
| 39783 | - n += (zTxt[i] - 'a')*mult; | |
| 39966 | + sqlite3_free(pFile->aJrnl); | |
| 39967 | + pFile->aJrnl = 0; | |
| 39968 | + pFile->nJrnl = 0; | |
| 39969 | + while( (c = zTxt[i])>='a' && c<='z' ){ | |
| 39970 | + n += (c - 'a')*mult; | |
| 39784 | 39971 | mult *= 26; |
| 39972 | + ++i; | |
| 39785 | 39973 | } |
| 39786 | - sqlite3_free(pFile->aJrnl); | |
| 39974 | + if( ' '!=zTxt[i++] ){ | |
| 39975 | + /* Malformed input */ | |
| 39976 | + return; | |
| 39977 | + } | |
| 39787 | 39978 | pFile->aJrnl = sqlite3_malloc64( n ); |
| 39788 | 39979 | if( pFile->aJrnl==0 ){ |
| 39789 | - pFile->nJrnl = 0; | |
| 39790 | 39980 | return; |
| 39791 | 39981 | } |
| 39792 | 39982 | pFile->nJrnl = n; |
| 39793 | 39983 | n = kvvfsDecode(zTxt+i, pFile->aJrnl, pFile->nJrnl); |
| 39794 | 39984 | if( n<pFile->nJrnl ){ |
| @@ -39824,13 +40014,11 @@ | ||
| 39824 | 40014 | |
| 39825 | 40015 | SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass, |
| 39826 | 40016 | pFile->isJournal ? "journal" : "db")); |
| 39827 | 40017 | sqlite3_free(pFile->aJrnl); |
| 39828 | 40018 | sqlite3_free(pFile->aData); |
| 39829 | -#ifdef SQLITE_WASM | |
| 39830 | 40019 | memset(pFile, 0, sizeof(*pFile)); |
| 39831 | -#endif | |
| 39832 | 40020 | return SQLITE_OK; |
| 39833 | 40021 | } |
| 39834 | 40022 | |
| 39835 | 40023 | /* |
| 39836 | 40024 | ** Read from the -journal file. |
| @@ -39856,10 +40044,11 @@ | ||
| 39856 | 40044 | if( aTxt==0 ) return SQLITE_NOMEM; |
| 39857 | 40045 | rc = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl", |
| 39858 | 40046 | aTxt, szTxt+1); |
| 39859 | 40047 | if( rc>=0 ){ |
| 39860 | 40048 | kvvfsDecodeJournal(pFile, aTxt, szTxt); |
| 40049 | + rc = 0; | |
| 39861 | 40050 | } |
| 39862 | 40051 | sqlite3_free(aTxt); |
| 39863 | 40052 | if( rc ) return rc; |
| 39864 | 40053 | if( pFile->aJrnl==0 ) return SQLITE_IOERR; |
| 39865 | 40054 | } |
| @@ -40180,11 +40369,11 @@ | ||
| 40180 | 40369 | } |
| 40181 | 40370 | if( !pFile->zClass ){ |
| 40182 | 40371 | #ifdef SQLITE_WASM |
| 40183 | 40372 | if( strlen(zName) >= (KVRECORD_KEY_SZ |
| 40184 | 40373 | - 6 /* "kvvfs-" */ |
| 40185 | - - 11 /* "-##########" */) ){ | |
| 40374 | + - 11 /* "-NNNNNNNNNNN" */) ){ | |
| 40186 | 40375 | return SQLITE_CANTOPEN; |
| 40187 | 40376 | } |
| 40188 | 40377 | #else |
| 40189 | 40378 | if( 0!=strcmp(zName, "local") && 0!=strcmp(zName, "session") ){ |
| 40190 | 40379 | /* Historical naming restriction which journaling depends on. */ |
| @@ -45946,11 +46135,10 @@ | ||
| 45946 | 46135 | i64 nNew /* Required mapping size */ |
| 45947 | 46136 | ){ |
| 45948 | 46137 | const char *zErr = "mmap"; |
| 45949 | 46138 | int h = pFd->h; /* File descriptor open on db file */ |
| 45950 | 46139 | u8 *pOrig = (u8 *)pFd->pMapRegion; /* Pointer to current file mapping */ |
| 45951 | - i64 nOrig = pFd->mmapSizeActual; /* Size of pOrig region in bytes */ | |
| 45952 | 46140 | u8 *pNew = 0; /* Location of new mapping */ |
| 45953 | 46141 | int flags = PROT_READ; /* Flags to pass to mmap() */ |
| 45954 | 46142 | |
| 45955 | 46143 | assert( pFd->nFetchOut==0 ); |
| 45956 | 46144 | assert( nNew>pFd->mmapSize ); |
| @@ -45964,25 +46152,16 @@ | ||
| 45964 | 46152 | #endif |
| 45965 | 46153 | |
| 45966 | 46154 | if( pOrig ){ |
| 45967 | 46155 | #if HAVE_MREMAP |
| 45968 | 46156 | i64 nReuse = pFd->mmapSize; |
| 46157 | + pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE); | |
| 46158 | + zErr = "mremap"; | |
| 45969 | 46159 | #else |
| 45970 | 46160 | const int szSyspage = osGetpagesize(); |
| 45971 | 46161 | i64 nReuse = (pFd->mmapSize & ~(szSyspage-1)); |
| 45972 | -#endif | |
| 45973 | 46162 | u8 *pReq = &pOrig[nReuse]; |
| 45974 | - | |
| 45975 | - /* Unmap any pages of the existing mapping that cannot be reused. */ | |
| 45976 | - if( nReuse!=nOrig ){ | |
| 45977 | - osMunmap(pReq, nOrig-nReuse); | |
| 45978 | - } | |
| 45979 | - | |
| 45980 | -#if HAVE_MREMAP | |
| 45981 | - pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE); | |
| 45982 | - zErr = "mremap"; | |
| 45983 | -#else | |
| 45984 | 46163 | pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse); |
| 45985 | 46164 | if( pNew!=MAP_FAILED ){ |
| 45986 | 46165 | if( pNew!=pReq ){ |
| 45987 | 46166 | osMunmap(pNew, nNew - nReuse); |
| 45988 | 46167 | pNew = 0; |
| @@ -46613,40 +46792,33 @@ | ||
| 46613 | 46792 | verifyDbFile(pNew); |
| 46614 | 46793 | } |
| 46615 | 46794 | return rc; |
| 46616 | 46795 | } |
| 46617 | 46796 | |
| 46618 | -/* | |
| 46619 | -** Directories to consider for temp files. | |
| 46620 | -*/ | |
| 46621 | -static const char *azTempDirs[] = { | |
| 46622 | - 0, | |
| 46623 | - 0, | |
| 46624 | - "/var/tmp", | |
| 46625 | - "/usr/tmp", | |
| 46626 | - "/tmp", | |
| 46627 | - "." | |
| 46628 | -}; | |
| 46629 | - | |
| 46630 | -/* | |
| 46631 | -** Initialize first two members of azTempDirs[] array. | |
| 46632 | -*/ | |
| 46633 | -static void unixTempFileInit(void){ | |
| 46634 | - azTempDirs[0] = getenv("SQLITE_TMPDIR"); | |
| 46635 | - azTempDirs[1] = getenv("TMPDIR"); | |
| 46636 | -} | |
| 46637 | - | |
| 46638 | 46797 | /* |
| 46639 | 46798 | ** Return the name of a directory in which to put temporary files. |
| 46640 | 46799 | ** If no suitable temporary file directory can be found, return NULL. |
| 46800 | +** | |
| 46801 | +** The return value might be a string obtained from getenv() and so | |
| 46802 | +** the return value should not be used after any call to setenv() or | |
| 46803 | +** putenv() as that value might have been freed. | |
| 46641 | 46804 | */ |
| 46642 | 46805 | static const char *unixTempFileDir(void){ |
| 46643 | - unsigned int i = 0; | |
| 46806 | + unsigned int i; | |
| 46644 | 46807 | struct stat buf; |
| 46645 | - const char *zDir = sqlite3_temp_directory; | |
| 46808 | + const char *zDir; | |
| 46646 | 46809 | |
| 46647 | - while(1){ | |
| 46810 | + for(i=0; i<7; i++){ | |
| 46811 | + switch( i ){ | |
| 46812 | + case 0: zDir = sqlite3_temp_directory; break; | |
| 46813 | + case 1: zDir = getenv("SQLITE_TMPDIR"); break; | |
| 46814 | + case 2: zDir = getenv("TMPDIR"); break; | |
| 46815 | + case 3: zDir = "/var/tmp"; break; | |
| 46816 | + case 4: zDir = "/usr/tmp"; break; | |
| 46817 | + case 5: zDir = "/tmp"; break; | |
| 46818 | + default: zDir = "."; break; | |
| 46819 | + } | |
| 46648 | 46820 | if( zDir!=0 |
| 46649 | 46821 | #if OS_VXWORKS |
| 46650 | 46822 | && zDir[0]=='/' |
| 46651 | 46823 | #endif |
| 46652 | 46824 | && osStat(zDir, &buf)==0 |
| @@ -46653,12 +46825,10 @@ | ||
| 46653 | 46825 | && S_ISDIR(buf.st_mode) |
| 46654 | 46826 | && osAccess(zDir, 03)==0 |
| 46655 | 46827 | ){ |
| 46656 | 46828 | return zDir; |
| 46657 | 46829 | } |
| 46658 | - if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break; | |
| 46659 | - zDir = azTempDirs[i++]; | |
| 46660 | 46830 | } |
| 46661 | 46831 | return 0; |
| 46662 | 46832 | } |
| 46663 | 46833 | |
| 46664 | 46834 | /* |
| @@ -48937,13 +49107,10 @@ | ||
| 48937 | 49107 | ** DMS UNIX_SHM_BASE+8 128 |
| 48938 | 49108 | */ |
| 48939 | 49109 | assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */ |
| 48940 | 49110 | #endif |
| 48941 | 49111 | |
| 48942 | - /* Initialize temp file dir array. */ | |
| 48943 | - unixTempFileInit(); | |
| 48944 | - | |
| 48945 | 49112 | return SQLITE_OK; |
| 48946 | 49113 | } |
| 48947 | 49114 | |
| 48948 | 49115 | /* |
| 48949 | 49116 | ** Shutdown the operating system interface. |
| @@ -52221,11 +52388,11 @@ | ||
| 52221 | 52388 | # define sqlite3_win_test_unc_locking 0 |
| 52222 | 52389 | #endif |
| 52223 | 52390 | |
| 52224 | 52391 | /* |
| 52225 | 52392 | ** Return true if the string passed as the only argument is likely |
| 52226 | -** to be a UNC path. Return false if note. | |
| 52393 | +** to be a UNC path. Return false if not. | |
| 52227 | 52394 | ** |
| 52228 | 52395 | ** Return true if: |
| 52229 | 52396 | ** |
| 52230 | 52397 | ** (1) The name begins with "\\" |
| 52231 | 52398 | ** (2) But does not begin with "\\?\C:\" where C can be any alphabetic |
| @@ -55070,26 +55237,27 @@ | ||
| 55070 | 55237 | int iDb; |
| 55071 | 55238 | Btree *pBt; |
| 55072 | 55239 | sqlite3_int64 sz; |
| 55073 | 55240 | int szPage = 0; |
| 55074 | 55241 | sqlite3_stmt *pStmt = 0; |
| 55075 | - unsigned char *pOut; | |
| 55242 | + unsigned char *pOut = 0; | |
| 55076 | 55243 | char *zSql; |
| 55077 | 55244 | int rc; |
| 55078 | 55245 | |
| 55079 | 55246 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 55080 | 55247 | if( !sqlite3SafetyCheckOk(db) ){ |
| 55081 | 55248 | (void)SQLITE_MISUSE_BKPT; |
| 55082 | 55249 | return 0; |
| 55083 | 55250 | } |
| 55084 | 55251 | #endif |
| 55252 | + sqlite3_mutex_enter(db->mutex); | |
| 55085 | 55253 | |
| 55086 | 55254 | if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; |
| 55087 | 55255 | p = memdbFromDbSchema(db, zSchema); |
| 55088 | 55256 | iDb = sqlite3FindDbName(db, zSchema); |
| 55089 | 55257 | if( piSize ) *piSize = -1; |
| 55090 | - if( iDb<0 ) return 0; | |
| 55258 | + if( iDb<0 ) goto serialize_out; | |
| 55091 | 55259 | if( p ){ |
| 55092 | 55260 | MemStore *pStore = p->pStore; |
| 55093 | 55261 | assert( pStore->pMutex==0 ); |
| 55094 | 55262 | if( piSize ) *piSize = pStore->sz; |
| 55095 | 55263 | if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ |
| @@ -55096,23 +55264,21 @@ | ||
| 55096 | 55264 | pOut = pStore->aData; |
| 55097 | 55265 | }else{ |
| 55098 | 55266 | pOut = sqlite3_malloc64( pStore->sz ); |
| 55099 | 55267 | if( pOut ) memcpy(pOut, pStore->aData, pStore->sz); |
| 55100 | 55268 | } |
| 55101 | - return pOut; | |
| 55269 | + goto serialize_out; | |
| 55102 | 55270 | } |
| 55103 | 55271 | pBt = db->aDb[iDb].pBt; |
| 55104 | - if( pBt==0 ) return 0; | |
| 55272 | + if( pBt==0 ) goto serialize_out; | |
| 55105 | 55273 | szPage = sqlite3BtreeGetPageSize(pBt); |
| 55106 | 55274 | zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema); |
| 55107 | 55275 | rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM; |
| 55108 | 55276 | sqlite3_free(zSql); |
| 55109 | - if( rc ) return 0; | |
| 55277 | + if( rc ) goto serialize_out; | |
| 55110 | 55278 | rc = sqlite3_step(pStmt); |
| 55111 | - if( rc!=SQLITE_ROW ){ | |
| 55112 | - pOut = 0; | |
| 55113 | - }else{ | |
| 55279 | + if( rc==SQLITE_ROW ){ | |
| 55114 | 55280 | sz = sqlite3_column_int64(pStmt, 0)*szPage; |
| 55115 | 55281 | if( sz==0 ){ |
| 55116 | 55282 | sqlite3_reset(pStmt); |
| 55117 | 55283 | sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0); |
| 55118 | 55284 | rc = sqlite3_step(pStmt); |
| @@ -55142,10 +55308,13 @@ | ||
| 55142 | 55308 | } |
| 55143 | 55309 | } |
| 55144 | 55310 | } |
| 55145 | 55311 | } |
| 55146 | 55312 | sqlite3_finalize(pStmt); |
| 55313 | + | |
| 55314 | + serialize_out: | |
| 55315 | + sqlite3_mutex_leave(db->mutex); | |
| 55147 | 55316 | return pOut; |
| 55148 | 55317 | } |
| 55149 | 55318 | |
| 55150 | 55319 | /* Convert zSchema to a MemDB and initialize its content. |
| 55151 | 55320 | */ |
| @@ -59917,10 +60086,45 @@ | ||
| 59917 | 60086 | static void freeSuperJournal(char *zSuper){ |
| 59918 | 60087 | if( zSuper ){ |
| 59919 | 60088 | sqlite3_free(&zSuper[-4]); |
| 59920 | 60089 | } |
| 59921 | 60090 | } |
| 60091 | + | |
| 60092 | +/* | |
| 60093 | +** Check if zSuper is a valid super-journal name. There are two valid | |
| 60094 | +** formats: | |
| 60095 | +** | |
| 60096 | +** + The 3rd and 4th last bytes of the filename are ".9", and the | |
| 60097 | +** following 2 bytes are hex digits. This is a file created in 8.3 | |
| 60098 | +** filenames mode. | |
| 60099 | +** | |
| 60100 | +** + The 3rd last byte of the filename is "9" and the filename | |
| 60101 | +** contains the string "-mj" starting at the 12th last byte. | |
| 60102 | +** All bytes following the "-mj" are hex digits. | |
| 60103 | +** | |
| 60104 | +** If the filename matches either of these patterns, return non-zero. | |
| 60105 | +** Otherwise, return zero. | |
| 60106 | +*/ | |
| 60107 | +static int pagerIsSuperJrnlName(const char *zSuper){ | |
| 60108 | + const int nSuper = sqlite3Strlen30(zSuper); | |
| 60109 | + int ii; | |
| 60110 | + | |
| 60111 | +#ifdef SQLITE_ENABLE_8_3_NAMES | |
| 60112 | + if( nSuper<4 ) return 0; | |
| 60113 | + if( zSuper[nSuper-3]!='9' ) return 0; | |
| 60114 | + if( sqlite3Isxdigit(zSuper[nSuper-2])==0 ) return 0; | |
| 60115 | + if( sqlite3Isxdigit(zSuper[nSuper-1])==0 ) return 0; | |
| 60116 | + if( zSuper[nSuper-4]=='.' ) return 1; | |
| 60117 | +#endif | |
| 60118 | + if( nSuper<12 ) return 0; | |
| 60119 | + if( memcmp(&zSuper[nSuper-12], "-mj", 3) ) return 0; | |
| 60120 | + if( zSuper[nSuper-3]!='9' ) return 0; | |
| 60121 | + for(ii=nSuper-9; ii<nSuper; ii++){ | |
| 60122 | + if( sqlite3Isxdigit(zSuper[ii])==0 ) return 0; | |
| 60123 | + } | |
| 60124 | + return 1; | |
| 60125 | +} | |
| 59922 | 60126 | |
| 59923 | 60127 | /* |
| 59924 | 60128 | ** Parameter pJrnl is a file-handle open on a journal file. This function |
| 59925 | 60129 | ** attempts to read a super-journal file name from the end of the journal |
| 59926 | 60130 | ** file. If successful, it sets output parameter (*pzSuper) to point to a |
| @@ -59955,32 +60159,34 @@ | ||
| 59955 | 60159 | || len>=nSuper |
| 59956 | 60160 | || len>szJ-16 |
| 59957 | 60161 | || len==0 |
| 59958 | 60162 | || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) |
| 59959 | 60163 | || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) |
| 59960 | - || memcmp(aMagic, aJournalMagic, 8) | |
| 59961 | 60164 | ){ |
| 59962 | 60165 | return rc; |
| 59963 | 60166 | } |
| 59964 | 60167 | |
| 59965 | 60168 | zOut = (char*)sqlite3MallocZero(4 + len + 2); |
| 59966 | 60169 | if( !zOut ){ |
| 59967 | - rc = SQLITE_NOMEM_BKPT; | |
| 60170 | + rc = memcmp(aMagic,aJournalMagic,8) ? SQLITE_OK : SQLITE_NOMEM_BKPT; | |
| 59968 | 60171 | }else{ |
| 59969 | 60172 | zOut = &zOut[4]; |
| 59970 | 60173 | if( SQLITE_OK==(rc = sqlite3OsRead(pJrnl, zOut, len, szJ-16-len)) ){ |
| 59971 | 60174 | u32 u; /* Unsigned loop counter */ |
| 59972 | 60175 | /* See if the checksum matches the super-journal name */ |
| 59973 | 60176 | for(u=0; u<len; u++){ |
| 59974 | 60177 | cksum -= zOut[u]; |
| 59975 | 60178 | } |
| 59976 | 60179 | } |
| 59977 | - if( rc!=SQLITE_OK || cksum ){ | |
| 59978 | - /* If the checksum doesn't add up, then one or more of the disk sectors | |
| 59979 | - ** containing the super-journal filename is corrupted. This means | |
| 59980 | - ** definitely roll back, so just return SQLITE_OK and report a (nul) | |
| 59981 | - ** super-journal filename. */ | |
| 60180 | + if( rc!=SQLITE_OK /* Couldn't read the name */ | |
| 60181 | + || !pagerIsSuperJrnlName(zOut) /* Name is not valid */ | |
| 60182 | + || cksum /* checksum is incorrect */ | |
| 60183 | + || memcmp(aMagic, aJournalMagic, 8)!=0 /* Bad magic number */ | |
| 60184 | + ){ | |
| 60185 | + /* If any validity checks fail, that means the super-journal filename | |
| 60186 | + ** is corrupted, so rollback. Return SQLITE_K and a NULL super-journal | |
| 60187 | + ** name */ | |
| 59982 | 60188 | freeSuperJournal(zOut); |
| 59983 | 60189 | zOut = 0; |
| 59984 | 60190 | } |
| 59985 | 60191 | } |
| 59986 | 60192 | |
| @@ -60359,10 +60565,11 @@ | ||
| 60359 | 60565 | i64 jrnlSize; /* Size of journal file on disk */ |
| 60360 | 60566 | u32 cksum = 0; /* Checksum of string zSuper */ |
| 60361 | 60567 | |
| 60362 | 60568 | assert( pPager->setSuper==0 ); |
| 60363 | 60569 | assert( !pagerUseWal(pPager) ); |
| 60570 | + assert( zSuper==0 || pagerIsSuperJrnlName(zSuper) ); | |
| 60364 | 60571 | |
| 60365 | 60572 | if( !zSuper |
| 60366 | 60573 | || pPager->journalMode==PAGER_JOURNALMODE_MEMORY |
| 60367 | 60574 | || !isOpen(pPager->jfd) |
| 60368 | 60575 | ){ |
| @@ -61189,10 +61396,23 @@ | ||
| 61189 | 61396 | sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */ |
| 61190 | 61397 | char *zSuperJournal = 0; /* Contents of super-journal file */ |
| 61191 | 61398 | i64 nSuperJournal; /* Size of super-journal file */ |
| 61192 | 61399 | char *zJournal; /* Pointer to one journal within MJ file */ |
| 61193 | 61400 | char *zFree = 0; /* Free this buffer */ |
| 61401 | + int bSeen = 0; /* If super-journal contains pPager->zJournal */ | |
| 61402 | + | |
| 61403 | + /* Check if this looks like a real super-journal name. If it does not, | |
| 61404 | + ** return SQLITE_OK without attempting to delete it. This is to limit | |
| 61405 | + ** the degree to which a crafted journal file can be used to cause | |
| 61406 | + ** SQLite to delete arbitrary files. | |
| 61407 | + ** | |
| 61408 | + ** This test never fails, becaue the super journal name is checked | |
| 61409 | + ** by readSuperJournal(). | |
| 61410 | + */ | |
| 61411 | + if( NEVER(pagerIsSuperJrnlName(zSuper)==0) ){ | |
| 61412 | + return SQLITE_OK; | |
| 61413 | + } | |
| 61194 | 61414 | |
| 61195 | 61415 | /* Allocate space for both the pJournal and pSuper file descriptors. |
| 61196 | 61416 | ** If successful, open the super-journal file for reading. |
| 61197 | 61417 | */ |
| 61198 | 61418 | pSuper = (sqlite3_file *)sqlite3MallocZero(2 * (i64)pVfs->szOsFile); |
| @@ -61228,51 +61448,60 @@ | ||
| 61228 | 61448 | zSuperJournal[nSuperJournal] = 0; |
| 61229 | 61449 | zSuperJournal[nSuperJournal+1] = 0; |
| 61230 | 61450 | |
| 61231 | 61451 | zJournal = zSuperJournal; |
| 61232 | 61452 | while( (zJournal-zSuperJournal)<nSuperJournal ){ |
| 61233 | - int exists; | |
| 61234 | - rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists); | |
| 61235 | - if( rc!=SQLITE_OK ){ | |
| 61236 | - goto delsuper_out; | |
| 61237 | - } | |
| 61238 | - if( exists ){ | |
| 61239 | - char *zSuperPtr = 0; | |
| 61240 | - | |
| 61241 | - /* One of the journals pointed to by the super-journal exists. | |
| 61242 | - ** Open it and check if it points at the super-journal. If | |
| 61243 | - ** so, return without deleting the super-journal file. | |
| 61244 | - ** NB: zJournal is really a MAIN_JOURNAL. But call it a | |
| 61245 | - ** SUPER_JOURNAL here so that the VFS will not send the zJournal | |
| 61246 | - ** name into sqlite3_database_file_object(). | |
| 61247 | - */ | |
| 61248 | - int c; | |
| 61249 | - int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL); | |
| 61250 | - rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0); | |
| 61251 | - if( rc!=SQLITE_OK ){ | |
| 61252 | - goto delsuper_out; | |
| 61253 | - } | |
| 61254 | - | |
| 61255 | - rc = readSuperJournal(pJournal, 1+(u64)pVfs->mxPathname, &zSuperPtr); | |
| 61256 | - sqlite3OsClose(pJournal); | |
| 61257 | - if( rc!=SQLITE_OK ){ | |
| 61258 | - assert( zSuperPtr==0 ); | |
| 61259 | - goto delsuper_out; | |
| 61260 | - } | |
| 61261 | - | |
| 61262 | - c = zSuperPtr!=0 && strcmp(zSuperPtr, zSuper)==0; | |
| 61263 | - freeSuperJournal(zSuperPtr); | |
| 61264 | - if( c ){ | |
| 61265 | - /* We have a match. Do not delete the super-journal file. */ | |
| 61266 | - goto delsuper_out; | |
| 61453 | + if( strcmp(zJournal, pPager->zJournal)==0 ){ | |
| 61454 | + bSeen = 1; | |
| 61455 | + }else{ | |
| 61456 | + int exists; | |
| 61457 | + rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists); | |
| 61458 | + if( rc!=SQLITE_OK ){ | |
| 61459 | + goto delsuper_out; | |
| 61460 | + } | |
| 61461 | + if( exists ){ | |
| 61462 | + char *zSuperPtr = 0; | |
| 61463 | + | |
| 61464 | + /* One of the journals pointed to by the super-journal exists. | |
| 61465 | + ** Open it and check if it points at the super-journal. If | |
| 61466 | + ** so, return without deleting the super-journal file. | |
| 61467 | + ** NB: zJournal is really a MAIN_JOURNAL. But call it a | |
| 61468 | + ** SUPER_JOURNAL here so that the VFS will not send the zJournal | |
| 61469 | + ** name into sqlite3_database_file_object(). | |
| 61470 | + */ | |
| 61471 | + int c; | |
| 61472 | + int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL); | |
| 61473 | + rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0); | |
| 61474 | + if( rc!=SQLITE_OK ){ | |
| 61475 | + goto delsuper_out; | |
| 61476 | + } | |
| 61477 | + | |
| 61478 | + rc = readSuperJournal(pJournal, 1+(u64)pVfs->mxPathname, &zSuperPtr); | |
| 61479 | + sqlite3OsClose(pJournal); | |
| 61480 | + if( rc!=SQLITE_OK ){ | |
| 61481 | + assert( zSuperPtr==0 ); | |
| 61482 | + goto delsuper_out; | |
| 61483 | + } | |
| 61484 | + | |
| 61485 | + c = zSuperPtr!=0 && strcmp(zSuperPtr, zSuper)==0; | |
| 61486 | + freeSuperJournal(zSuperPtr); | |
| 61487 | + if( c ){ | |
| 61488 | + /* We have a match. Do not delete the super-journal file. */ | |
| 61489 | + goto delsuper_out; | |
| 61490 | + } | |
| 61267 | 61491 | } |
| 61268 | 61492 | } |
| 61269 | 61493 | zJournal += (sqlite3Strlen30(zJournal)+1); |
| 61270 | 61494 | } |
| 61271 | 61495 | |
| 61272 | 61496 | sqlite3OsClose(pSuper); |
| 61273 | - rc = sqlite3OsDelete(pVfs, zSuper, 0); | |
| 61497 | + if( bSeen ){ | |
| 61498 | + /* Only delete the super-journal if bSeen is true - indicating that | |
| 61499 | + ** the super-journal contained a pointer to this database's journal | |
| 61500 | + ** file. */ | |
| 61501 | + rc = sqlite3OsDelete(pVfs, zSuper, 0); | |
| 61502 | + } | |
| 61274 | 61503 | |
| 61275 | 61504 | delsuper_out: |
| 61276 | 61505 | sqlite3_free(zFree); |
| 61277 | 61506 | if( pSuper ){ |
| 61278 | 61507 | sqlite3OsClose(pSuper); |
| @@ -71674,10 +71903,13 @@ | ||
| 71674 | 71903 | int skipNext; /* Prev() is noop if negative. Next() is noop if positive. |
| 71675 | 71904 | ** Error code if eState==CURSOR_FAULT */ |
| 71676 | 71905 | Btree *pBtree; /* The Btree to which this cursor belongs */ |
| 71677 | 71906 | Pgno *aOverflow; /* Cache of overflow page locations */ |
| 71678 | 71907 | void *pKey; /* Saved key that was cursor last known position */ |
| 71908 | +#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG) | |
| 71909 | + BtCursor *pCursorHintTableCursor; | |
| 71910 | +#endif | |
| 71679 | 71911 | /* All fields above are zeroed when the cursor is allocated. See |
| 71680 | 71912 | ** sqlite3BtreeCursorZero(). Fields that follow must be manually |
| 71681 | 71913 | ** initialized. */ |
| 71682 | 71914 | #define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */ |
| 71683 | 71915 | BtShared *pBt; /* The BtShared this cursor points to */ |
| @@ -71850,10 +72082,13 @@ | ||
| 71850 | 72082 | int v2; /* Value for third %d substitution in zPfx */ |
| 71851 | 72083 | StrAccum errMsg; /* Accumulate the error message text here */ |
| 71852 | 72084 | u32 *heap; /* Min-heap used for analyzing cell coverage */ |
| 71853 | 72085 | sqlite3 *db; /* Database connection running the check */ |
| 71854 | 72086 | i64 nRow; /* Number of rows visited in current tree */ |
| 72087 | +#ifdef SQLITE_DEBUG | |
| 72088 | + u32 mxHeap; /* Maximum number of entries in the Min-heap */ | |
| 72089 | +#endif | |
| 71855 | 72090 | }; |
| 71856 | 72091 | |
| 71857 | 72092 | /* |
| 71858 | 72093 | ** Routines to read or write a two- and four-byte big-endian integer values. |
| 71859 | 72094 | */ |
| @@ -73178,28 +73413,45 @@ | ||
| 73178 | 73413 | ** parameter. See the definitions of the BTREE_HINT_* macros for details. |
| 73179 | 73414 | */ |
| 73180 | 73415 | SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){ |
| 73181 | 73416 | /* Used only by system that substitute their own storage engine */ |
| 73182 | 73417 | #ifdef SQLITE_DEBUG |
| 73183 | - if( ALWAYS(eHintType==BTREE_HINT_RANGE) ){ | |
| 73184 | - va_list ap; | |
| 73418 | + va_list ap; | |
| 73419 | + va_start(ap, eHintType); | |
| 73420 | + if( eHintType==BTREE_HINT_RANGE ){ | |
| 73185 | 73421 | Expr *pExpr; |
| 73186 | 73422 | Walker w; |
| 73187 | 73423 | memset(&w, 0, sizeof(w)); |
| 73188 | 73424 | w.xExprCallback = sqlite3CursorRangeHintExprCheck; |
| 73189 | - va_start(ap, eHintType); | |
| 73190 | 73425 | pExpr = va_arg(ap, Expr*); |
| 73191 | 73426 | w.u.aMem = va_arg(ap, Mem*); |
| 73192 | - va_end(ap); | |
| 73193 | 73427 | assert( pExpr!=0 ); |
| 73194 | 73428 | assert( w.u.aMem!=0 ); |
| 73195 | 73429 | sqlite3WalkExpr(&w, pExpr); |
| 73430 | + }else if( ALWAYS(eHintType==BTREE_HINT_TABLECURSOR) ){ | |
| 73431 | + BtCursor *pCsr = va_arg(ap, BtCursor*); | |
| 73432 | + assert( pCur->pCursorHintTableCursor==0 | |
| 73433 | + || pCur->pCursorHintTableCursor==pCsr | |
| 73434 | + ); | |
| 73435 | + assert( pCsr->pKeyInfo==0 || CORRUPT_DB ); | |
| 73436 | + pCur->pCursorHintTableCursor = pCsr; | |
| 73196 | 73437 | } |
| 73438 | + va_end(ap); | |
| 73197 | 73439 | #endif /* SQLITE_DEBUG */ |
| 73198 | 73440 | } |
| 73199 | 73441 | #endif /* SQLITE_ENABLE_CURSOR_HINTS */ |
| 73200 | 73442 | |
| 73443 | +#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG) | |
| 73444 | +/* | |
| 73445 | +** Return the pointer configured via the BTREE_HINT_TABLECURSOR hint on | |
| 73446 | +** cursor pCsr. This is used from OP_DeferredSeek to assert() that the | |
| 73447 | +** index cursor has been correctly configured with the table cursor. | |
| 73448 | +*/ | |
| 73449 | +SQLITE_PRIVATE BtCursor *sqlite3BtreeCursorHintTblCsr(BtCursor *pCsr){ | |
| 73450 | + return pCsr->pCursorHintTableCursor; | |
| 73451 | +} | |
| 73452 | +#endif | |
| 73201 | 73453 | |
| 73202 | 73454 | /* |
| 73203 | 73455 | ** Provide flag hints to the cursor. |
| 73204 | 73456 | */ |
| 73205 | 73457 | SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){ |
| @@ -74321,12 +74573,19 @@ | ||
| 74321 | 74573 | /* Freeblock off the end of the page */ |
| 74322 | 74574 | return SQLITE_CORRUPT_PAGE(pPage); |
| 74323 | 74575 | } |
| 74324 | 74576 | next = get2byte(&data[pc]); |
| 74325 | 74577 | size = get2byte(&data[pc+2]); |
| 74578 | + if( size<4 && sqlite3FaultSim(422)==SQLITE_OK ){ | |
| 74579 | + /* Minimum freeblock size is 4. Enable fault-sim 422 to disable this | |
| 74580 | + ** check to reach interesting error stats. However, disabling this | |
| 74581 | + ** check can cause assertion faults due to min-heap overflow. All | |
| 74582 | + ** fault-sims are for testing use only, but this one especially so. */ | |
| 74583 | + return SQLITE_CORRUPT_PAGE(pPage); | |
| 74584 | + } | |
| 74326 | 74585 | nFree = nFree + size; |
| 74327 | - if( next<=pc+size+3 ) break; | |
| 74586 | + if( next<pc+size+4 ) break; | |
| 74328 | 74587 | pc = next; |
| 74329 | 74588 | } |
| 74330 | 74589 | if( next>0 ){ |
| 74331 | 74590 | /* Freeblock not in ascending order */ |
| 74332 | 74591 | return SQLITE_CORRUPT_PAGE(pPage); |
| @@ -78157,18 +78416,18 @@ | ||
| 78157 | 78416 | nCell = pCell[0]; |
| 78158 | 78417 | if( nCell<=pPage->max1bytePayload ){ |
| 78159 | 78418 | /* This branch runs if the record-size field of the cell is a |
| 78160 | 78419 | ** single byte varint and the record fits entirely on the main |
| 78161 | 78420 | ** b-tree page. */ |
| 78162 | - testcase( pCell+nCell+1==pPage->aDataEnd ); | |
| 78421 | + if( pCell + nCell >= pPage->aDataEnd ) return 99; | |
| 78163 | 78422 | c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); |
| 78164 | 78423 | }else if( !(pCell[1] & 0x80) |
| 78165 | 78424 | && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal |
| 78166 | 78425 | ){ |
| 78167 | 78426 | /* The record-size field is a 2 byte varint and the record |
| 78168 | 78427 | ** fits entirely on the main b-tree page. */ |
| 78169 | - testcase( pCell+nCell+2==pPage->aDataEnd ); | |
| 78428 | + if( pCell + nCell >= pPage->aDataEnd ) return 99; | |
| 78170 | 78429 | c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); |
| 78171 | 78430 | }else{ |
| 78172 | 78431 | /* If the record extends into overflow pages, do not attempt |
| 78173 | 78432 | ** the optimization. */ |
| 78174 | 78433 | c = 99; |
| @@ -78326,18 +78585,21 @@ | ||
| 78326 | 78585 | nCell = pCell[0]; |
| 78327 | 78586 | if( nCell<=pPage->max1bytePayload ){ |
| 78328 | 78587 | /* This branch runs if the record-size field of the cell is a |
| 78329 | 78588 | ** single byte varint and the record fits entirely on the main |
| 78330 | 78589 | ** b-tree page. */ |
| 78331 | - testcase( pCell+nCell+1==pPage->aDataEnd ); | |
| 78590 | + if( pCell + nCell >= pPage->aDataEnd ){ | |
| 78591 | + rc = SQLITE_CORRUPT_PAGE(pPage); | |
| 78592 | + goto moveto_index_finish; | |
| 78593 | + } | |
| 78332 | 78594 | c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); |
| 78333 | 78595 | }else if( !(pCell[1] & 0x80) |
| 78334 | 78596 | && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal |
| 78597 | + && pCell + nCell < pPage->aDataEnd | |
| 78335 | 78598 | ){ |
| 78336 | 78599 | /* The record-size field is a 2 byte varint and the record |
| 78337 | 78600 | ** fits entirely on the main b-tree page. */ |
| 78338 | - testcase( pCell+nCell+2==pPage->aDataEnd ); | |
| 78339 | 78601 | c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); |
| 78340 | 78602 | }else{ |
| 78341 | 78603 | /* The record flows over onto one or more overflow pages. In |
| 78342 | 78604 | ** this case the whole cell needs to be parsed, a buffer allocated |
| 78343 | 78605 | ** and accessPayload() used to retrieve the record into the |
| @@ -83203,10 +83465,11 @@ | ||
| 83203 | 83465 | checkAppendMsg(pCheck, "Child page depth differs"); |
| 83204 | 83466 | depth = d2; |
| 83205 | 83467 | } |
| 83206 | 83468 | }else{ |
| 83207 | 83469 | /* Populate the coverage-checking heap for leaf pages */ |
| 83470 | + assert( heap!=0 && heap[0] < pCheck->mxHeap ); | |
| 83208 | 83471 | btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1)); |
| 83209 | 83472 | } |
| 83210 | 83473 | } |
| 83211 | 83474 | *piMinKey = maxKey; |
| 83212 | 83475 | |
| @@ -83222,10 +83485,11 @@ | ||
| 83222 | 83485 | heap[0] = 0; |
| 83223 | 83486 | for(i=nCell-1; i>=0; i--){ |
| 83224 | 83487 | u32 size; |
| 83225 | 83488 | pc = get2byteAligned(&data[cellStart+i*2]); |
| 83226 | 83489 | size = pPage->xCellSize(pPage, &data[pc]); |
| 83490 | + assert( heap!=0 && heap[0] < pCheck->mxHeap ); | |
| 83227 | 83491 | btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); |
| 83228 | 83492 | } |
| 83229 | 83493 | } |
| 83230 | 83494 | assert( heap!=0 ); |
| 83231 | 83495 | /* Add the freeblocks to the min-heap |
| @@ -83238,10 +83502,11 @@ | ||
| 83238 | 83502 | while( i>0 ){ |
| 83239 | 83503 | int size, j; |
| 83240 | 83504 | assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */ |
| 83241 | 83505 | size = get2byte(&data[i+2]); |
| 83242 | 83506 | assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */ |
| 83507 | + assert( heap!=0 && heap[0] < pCheck->mxHeap ); | |
| 83243 | 83508 | btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1)); |
| 83244 | 83509 | /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a |
| 83245 | 83510 | ** big-endian integer which is the offset in the b-tree page of the next |
| 83246 | 83511 | ** freeblock in the chain, or zero if the freeblock is the last on the |
| 83247 | 83512 | ** chain. */ |
| @@ -83372,10 +83637,13 @@ | ||
| 83372 | 83637 | if( !sCheck.aPgRef ){ |
| 83373 | 83638 | checkOom(&sCheck); |
| 83374 | 83639 | goto integrity_ck_cleanup; |
| 83375 | 83640 | } |
| 83376 | 83641 | sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); |
| 83642 | +#ifdef SQLITE_DEBUG | |
| 83643 | + sCheck.mxHeap = pBt->pageSize/4 - 1; | |
| 83644 | +#endif | |
| 83377 | 83645 | if( sCheck.heap==0 ){ |
| 83378 | 83646 | checkOom(&sCheck); |
| 83379 | 83647 | goto integrity_ck_cleanup; |
| 83380 | 83648 | } |
| 83381 | 83649 | |
| @@ -83796,17 +84064,18 @@ | ||
| 83796 | 84064 | /* |
| 83797 | 84065 | ** Structure allocated for each backup operation. |
| 83798 | 84066 | */ |
| 83799 | 84067 | struct sqlite3_backup { |
| 83800 | 84068 | sqlite3* pDestDb; /* Destination database handle */ |
| 83801 | - Db *pDest; /* Destination db file */ | |
| 84069 | + char *zDestDb; | |
| 84070 | + Btree *pDest; /* Destination b-tree file */ | |
| 83802 | 84071 | u32 iDestSchema; /* Original schema cookie in destination */ |
| 83803 | 84072 | int bDestLocked; /* True once a write-transaction is open on pDest */ |
| 83804 | 84073 | |
| 83805 | 84074 | Pgno iNext; /* Page number of the next source page to copy */ |
| 83806 | 84075 | sqlite3* pSrcDb; /* Source database handle */ |
| 83807 | - Db *pSrc; /* Source db file */ | |
| 84076 | + Btree *pSrc; /* Source b-tree file */ | |
| 83808 | 84077 | |
| 83809 | 84078 | int rc; /* Backup process error code */ |
| 83810 | 84079 | |
| 83811 | 84080 | /* These two variables are set by every call to backup_step(). They are |
| 83812 | 84081 | ** read by calls to backup_remaining() and backup_pagecount(). |
| @@ -83855,13 +84124,15 @@ | ||
| 83855 | 84124 | ** |
| 83856 | 84125 | ** If the "temp" database is requested, it may need to be opened by this |
| 83857 | 84126 | ** function. If an error occurs while doing so, return 0 and write an |
| 83858 | 84127 | ** error message to pErrorDb. |
| 83859 | 84128 | */ |
| 83860 | -static Db *findDatabase(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ | |
| 83861 | - int i = sqlite3FindDbName(pDb, zDb); | |
| 84129 | +static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ | |
| 84130 | + int i; | |
| 83862 | 84131 | |
| 84132 | + assert( pDb!=0 ); | |
| 84133 | + i = sqlite3FindDbName(pDb, zDb); | |
| 83863 | 84134 | if( i==1 ){ |
| 83864 | 84135 | Parse sParse; |
| 83865 | 84136 | int rc = 0; |
| 83866 | 84137 | sqlite3ParseObjectInit(&sParse,pDb); |
| 83867 | 84138 | if( sqlite3OpenTempDatabase(&sParse) ){ |
| @@ -83878,21 +84149,19 @@ | ||
| 83878 | 84149 | if( i<0 ){ |
| 83879 | 84150 | sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); |
| 83880 | 84151 | return 0; |
| 83881 | 84152 | } |
| 83882 | 84153 | |
| 83883 | - return &pDb->aDb[i]; | |
| 84154 | + return pDb->aDb[i].pBt; | |
| 83884 | 84155 | } |
| 83885 | 84156 | |
| 83886 | 84157 | /* |
| 83887 | 84158 | ** Attempt to set the page size of the destination to match the page size |
| 83888 | 84159 | ** of the source. |
| 83889 | 84160 | */ |
| 83890 | -static int setDestPgsz(sqlite3_backup *p){ | |
| 83891 | - return sqlite3BtreeSetPageSize(p->pDest->pBt, | |
| 83892 | - sqlite3BtreeGetPageSize(p->pSrc->pBt), 0, 0 | |
| 83893 | - ); | |
| 84161 | +static int setDestPgsz(Btree *pDest, Btree *pSrc){ | |
| 84162 | + return sqlite3BtreeSetPageSize(pDest, sqlite3BtreeGetPageSize(pSrc), 0, 0); | |
| 83894 | 84163 | } |
| 83895 | 84164 | |
| 83896 | 84165 | /* |
| 83897 | 84166 | ** Check that there is no open read-transaction on the b-tree passed as the |
| 83898 | 84167 | ** second argument. If there is not, return SQLITE_OK. Otherwise, if there |
| @@ -83945,31 +84214,41 @@ | ||
| 83945 | 84214 | sqlite3ErrorWithMsg( |
| 83946 | 84215 | pDestDb, SQLITE_ERROR, "source and destination must be distinct" |
| 83947 | 84216 | ); |
| 83948 | 84217 | p = 0; |
| 83949 | 84218 | }else { |
| 84219 | + int nDest = sqlite3Strlen30(zDestDb); | |
| 84220 | + | |
| 83950 | 84221 | /* Allocate space for a new sqlite3_backup object... |
| 83951 | 84222 | ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a |
| 83952 | 84223 | ** call to sqlite3_backup_init() and is destroyed by a call to |
| 83953 | 84224 | ** sqlite3_backup_finish(). */ |
| 83954 | - p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); | |
| 84225 | + p = (sqlite3_backup*)sqlite3MallocZero(sizeof(sqlite3_backup)+nDest+1); | |
| 83955 | 84226 | if( !p ){ |
| 83956 | 84227 | sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT); |
| 84228 | + }else{ | |
| 84229 | + p->zDestDb = (char*)&p[1]; | |
| 84230 | + memcpy(p->zDestDb, zDestDb, nDest); | |
| 83957 | 84231 | } |
| 83958 | 84232 | } |
| 83959 | 84233 | |
| 83960 | 84234 | /* If the allocation succeeded, populate the new object. */ |
| 83961 | 84235 | if( p ){ |
| 83962 | - p->pSrc = findDatabase(pDestDb, pSrcDb, zSrcDb); | |
| 83963 | - p->pDest = findDatabase(pDestDb, pDestDb, zDestDb); | |
| 84236 | + /* Do not store the pointer to the destination b-tree at this point. | |
| 84237 | + ** This is because there is nothing preventing it from being detached | |
| 84238 | + ** or otherwise freed before the first call to sqlite3_backup_step() | |
| 84239 | + ** on this object. The source b-tree does not have this problem, as | |
| 84240 | + ** incrementing Btree.nBackup (see below) effectively locks the object. */ | |
| 84241 | + Btree *pDest = findBtree(pDestDb, pDestDb, zDestDb); | |
| 84242 | + p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); | |
| 83964 | 84243 | p->pDestDb = pDestDb; |
| 83965 | 84244 | p->pSrcDb = pSrcDb; |
| 83966 | 84245 | p->iNext = 1; |
| 83967 | 84246 | p->isAttached = 0; |
| 83968 | 84247 | |
| 83969 | - if( 0==p->pSrc || 0==p->pDest | |
| 83970 | - || checkReadTransaction(pDestDb, p->pDest->pBt)!=SQLITE_OK | |
| 84248 | + if( 0==p->pSrc || 0==pDest | |
| 84249 | + || checkReadTransaction(pDestDb, pDest)!=SQLITE_OK | |
| 83971 | 84250 | ){ |
| 83972 | 84251 | /* One (or both) of the named databases did not exist or an OOM |
| 83973 | 84252 | ** error was hit. Or there is a transaction open on the destination |
| 83974 | 84253 | ** database. The error has already been written into the pDestDb |
| 83975 | 84254 | ** handle. All that is left to do here is free the sqlite3_backup |
| @@ -83977,11 +84256,11 @@ | ||
| 83977 | 84256 | sqlite3_free(p); |
| 83978 | 84257 | p = 0; |
| 83979 | 84258 | } |
| 83980 | 84259 | } |
| 83981 | 84260 | if( p ){ |
| 83982 | - p->pSrc->pBt->nBackup++; | |
| 84261 | + p->pSrc->nBackup++; | |
| 83983 | 84262 | } |
| 83984 | 84263 | |
| 83985 | 84264 | sqlite3_mutex_leave(pDestDb->mutex); |
| 83986 | 84265 | sqlite3_mutex_leave(pSrcDb->mutex); |
| 83987 | 84266 | return p; |
| @@ -84005,22 +84284,22 @@ | ||
| 84005 | 84284 | sqlite3_backup *p, /* Backup handle */ |
| 84006 | 84285 | Pgno iSrcPg, /* Source database page to backup */ |
| 84007 | 84286 | const u8 *zSrcData, /* Source database page data */ |
| 84008 | 84287 | int bUpdate /* True for an update, false otherwise */ |
| 84009 | 84288 | ){ |
| 84010 | - Pager * const pDestPager = sqlite3BtreePager(p->pDest->pBt); | |
| 84011 | - const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc->pBt); | |
| 84012 | - int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest->pBt); | |
| 84289 | + Pager * const pDestPager = sqlite3BtreePager(p->pDest); | |
| 84290 | + const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); | |
| 84291 | + int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); | |
| 84013 | 84292 | const int nCopy = MIN(nSrcPgsz, nDestPgsz); |
| 84014 | 84293 | const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; |
| 84015 | 84294 | int rc = SQLITE_OK; |
| 84016 | 84295 | i64 iOff; |
| 84017 | 84296 | |
| 84018 | - assert( sqlite3BtreeGetReserveNoMutex(p->pSrc->pBt)>=0 ); | |
| 84297 | + assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 ); | |
| 84019 | 84298 | assert( p->bDestLocked ); |
| 84020 | 84299 | assert( !isFatalError(p->rc) ); |
| 84021 | - assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt->pBt) ); | |
| 84300 | + assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); | |
| 84022 | 84301 | assert( zSrcData ); |
| 84023 | 84302 | assert( nSrcPgsz==nDestPgsz || sqlite3PagerIsMemdb(pDestPager)==0 ); |
| 84024 | 84303 | |
| 84025 | 84304 | /* This loop runs once for each destination page spanned by the source |
| 84026 | 84305 | ** page. For each iteration, variable iOff is set to the byte offset |
| @@ -84027,11 +84306,11 @@ | ||
| 84027 | 84306 | ** of the destination page. |
| 84028 | 84307 | */ |
| 84029 | 84308 | for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){ |
| 84030 | 84309 | DbPage *pDestPg = 0; |
| 84031 | 84310 | Pgno iDest = (Pgno)(iOff/nDestPgsz)+1; |
| 84032 | - if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt->pBt) ) continue; | |
| 84311 | + if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue; | |
| 84033 | 84312 | if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0)) |
| 84034 | 84313 | && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg)) |
| 84035 | 84314 | ){ |
| 84036 | 84315 | const u8 *zIn = &zSrcData[iOff%nSrcPgsz]; |
| 84037 | 84316 | u8 *zDestData = sqlite3PagerGetData(pDestPg); |
| @@ -84045,11 +84324,11 @@ | ||
| 84045 | 84324 | ** "MUST BE FIRST" for this purpose. |
| 84046 | 84325 | */ |
| 84047 | 84326 | memcpy(zOut, zIn, nCopy); |
| 84048 | 84327 | ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; |
| 84049 | 84328 | if( iOff==0 && bUpdate==0 ){ |
| 84050 | - sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc->pBt)); | |
| 84329 | + sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); | |
| 84051 | 84330 | } |
| 84052 | 84331 | } |
| 84053 | 84332 | sqlite3PagerUnref(pDestPg); |
| 84054 | 84333 | } |
| 84055 | 84334 | |
| @@ -84077,12 +84356,12 @@ | ||
| 84077 | 84356 | ** Register this backup object with the associated source pager for |
| 84078 | 84357 | ** callbacks when pages are changed or the cache invalidated. |
| 84079 | 84358 | */ |
| 84080 | 84359 | static void attachBackupObject(sqlite3_backup *p){ |
| 84081 | 84360 | sqlite3_backup **pp; |
| 84082 | - assert( sqlite3BtreeHoldsMutex(p->pSrc->pBt) ); | |
| 84083 | - pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc->pBt)); | |
| 84361 | + assert( sqlite3BtreeHoldsMutex(p->pSrc) ); | |
| 84362 | + pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); | |
| 84084 | 84363 | p->pNext = *pp; |
| 84085 | 84364 | *pp = p; |
| 84086 | 84365 | p->isAttached = 1; |
| 84087 | 84366 | } |
| 84088 | 84367 | |
| @@ -84089,93 +84368,103 @@ | ||
| 84089 | 84368 | /* |
| 84090 | 84369 | ** Copy nPage pages from the source b-tree to the destination. |
| 84091 | 84370 | */ |
| 84092 | 84371 | SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ |
| 84093 | 84372 | int rc; |
| 84094 | - int destMode; /* Destination journal mode */ | |
| 84373 | + int destMode = 0; /* Destination journal mode */ | |
| 84095 | 84374 | int pgszSrc = 0; /* Source page size */ |
| 84096 | 84375 | int pgszDest = 0; /* Destination page size */ |
| 84097 | - Btree *pDest; | |
| 84098 | - Btree *pSrc; | |
| 84099 | 84376 | |
| 84100 | 84377 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 84101 | 84378 | if( p==0 ) return SQLITE_MISUSE_BKPT; |
| 84102 | 84379 | #endif |
| 84103 | - assert( p->pDest ); | |
| 84104 | - assert( p->pSrc ); | |
| 84105 | - pDest = p->pDest->pBt; | |
| 84106 | - pSrc = p->pSrc->pBt; | |
| 84107 | 84380 | sqlite3_mutex_enter(p->pSrcDb->mutex); |
| 84108 | - sqlite3BtreeEnter(pSrc); | |
| 84381 | + sqlite3BtreeEnter(p->pSrc); | |
| 84109 | 84382 | if( p->pDestDb ){ |
| 84110 | 84383 | sqlite3_mutex_enter(p->pDestDb->mutex); |
| 84111 | 84384 | } |
| 84112 | 84385 | |
| 84113 | 84386 | rc = p->rc; |
| 84114 | 84387 | if( !isFatalError(rc) ){ |
| 84115 | - Pager * const pSrcPager = sqlite3BtreePager(pSrc); /* Source pager */ | |
| 84116 | - Pager * const pDestPager = sqlite3BtreePager(pDest); /* Dest pager */ | |
| 84388 | + Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */ | |
| 84389 | + Btree * pDest = 0; /* Dest btree */ | |
| 84390 | + Pager * pDestPager = 0; /* Dest pager */ | |
| 84117 | 84391 | int ii; /* Iterator variable */ |
| 84118 | 84392 | int nSrcPage = -1; /* Size of source db in pages */ |
| 84119 | 84393 | int bCloseTrans = 0; /* True if src db requires unlocking */ |
| 84120 | 84394 | |
| 84121 | 84395 | /* If the source pager is currently in a write-transaction, return |
| 84122 | 84396 | ** SQLITE_BUSY immediately. |
| 84123 | 84397 | */ |
| 84124 | - if( p->pDestDb && pSrc->pBt->inTransaction==TRANS_WRITE ){ | |
| 84398 | + if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){ | |
| 84125 | 84399 | rc = SQLITE_BUSY; |
| 84126 | 84400 | }else{ |
| 84127 | 84401 | rc = SQLITE_OK; |
| 84128 | 84402 | } |
| 84403 | + | |
| 84129 | 84404 | |
| 84130 | 84405 | /* If there is no open read-transaction on the source database, open |
| 84131 | 84406 | ** one now. If a transaction is opened here, then it will be closed |
| 84132 | 84407 | ** before this function exits. |
| 84133 | 84408 | */ |
| 84134 | - if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(pSrc) ){ | |
| 84135 | - rc = sqlite3BtreeBeginTrans(pSrc, 0, 0); | |
| 84409 | + if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){ | |
| 84410 | + rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0); | |
| 84136 | 84411 | bCloseTrans = 1; |
| 84137 | 84412 | } |
| 84413 | + | |
| 84414 | + /* Locate the destination btree and pager. */ | |
| 84415 | + if( (pDest = p->pDest)==0 ){ | |
| 84416 | + pDest = findBtree(p->pDestDb, p->pDestDb, p->zDestDb); | |
| 84417 | + } | |
| 84418 | + if( pDest==0 ){ | |
| 84419 | + rc = SQLITE_ERROR; | |
| 84420 | + }else{ | |
| 84421 | + pDestPager = sqlite3BtreePager(pDest); | |
| 84422 | + } | |
| 84138 | 84423 | |
| 84139 | 84424 | /* If the destination database has not yet been locked (i.e. if this |
| 84140 | 84425 | ** is the first call to backup_step() for the current backup operation), |
| 84141 | 84426 | ** try to set its page size to the same as the source database. This |
| 84142 | 84427 | ** is especially important on ZipVFS systems, as in that case it is |
| 84143 | 84428 | ** not possible to create a database file that uses one page size by |
| 84144 | 84429 | ** writing to it with another. */ |
| 84145 | - if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){ | |
| 84430 | + if( p->bDestLocked==0 && rc==SQLITE_OK | |
| 84431 | + && setDestPgsz(pDest, p->pSrc)==SQLITE_NOMEM | |
| 84432 | + ){ | |
| 84146 | 84433 | rc = SQLITE_NOMEM; |
| 84147 | 84434 | } |
| 84148 | 84435 | |
| 84149 | 84436 | /* Lock the destination database, if it is not locked already. */ |
| 84150 | 84437 | if( SQLITE_OK==rc && p->bDestLocked==0 |
| 84151 | 84438 | && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(pDest, 2, |
| 84152 | 84439 | (int*)&p->iDestSchema)) |
| 84153 | 84440 | ){ |
| 84154 | 84441 | p->bDestLocked = 1; |
| 84442 | + p->pDest = pDest; | |
| 84155 | 84443 | } |
| 84156 | 84444 | |
| 84157 | 84445 | /* Do not allow backup if the destination database is in WAL mode |
| 84158 | 84446 | ** and the page sizes are different between source and destination */ |
| 84159 | - pgszSrc = sqlite3BtreeGetPageSize(pSrc); | |
| 84160 | - pgszDest = sqlite3BtreeGetPageSize(pDest); | |
| 84161 | - destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(pDest)); | |
| 84162 | - if( SQLITE_OK==rc | |
| 84163 | - && (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager)) | |
| 84164 | - && pgszSrc!=pgszDest | |
| 84165 | - ){ | |
| 84166 | - rc = SQLITE_READONLY; | |
| 84447 | + if( rc==SQLITE_OK ){ | |
| 84448 | + pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); | |
| 84449 | + pgszDest = sqlite3BtreeGetPageSize(p->pDest); | |
| 84450 | + destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); | |
| 84451 | + if( (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager)) | |
| 84452 | + && pgszSrc!=pgszDest | |
| 84453 | + ){ | |
| 84454 | + rc = SQLITE_READONLY; | |
| 84455 | + } | |
| 84167 | 84456 | } |
| 84168 | 84457 | |
| 84169 | 84458 | /* Now that there is a read-lock on the source database, query the |
| 84170 | 84459 | ** source pager for the number of pages in the database. |
| 84171 | 84460 | */ |
| 84172 | - nSrcPage = (int)sqlite3BtreeLastPage(pSrc); | |
| 84461 | + nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); | |
| 84173 | 84462 | assert( nSrcPage>=0 ); |
| 84174 | 84463 | for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){ |
| 84175 | 84464 | const Pgno iSrcPg = p->iNext; /* Source page number */ |
| 84176 | - if( iSrcPg!=PENDING_BYTE_PAGE(pSrc->pBt) ){ | |
| 84465 | + if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ | |
| 84177 | 84466 | DbPage *pSrcPg; /* Source page object */ |
| 84178 | 84467 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY); |
| 84179 | 84468 | if( rc==SQLITE_OK ){ |
| 84180 | 84469 | rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); |
| 84181 | 84470 | sqlite3PagerUnref(pSrcPg); |
| @@ -84198,22 +84487,22 @@ | ||
| 84198 | 84487 | ** the case where the source and destination databases have the |
| 84199 | 84488 | ** same schema version. |
| 84200 | 84489 | */ |
| 84201 | 84490 | if( rc==SQLITE_DONE ){ |
| 84202 | 84491 | if( nSrcPage==0 ){ |
| 84203 | - rc = sqlite3BtreeNewDb(pDest); | |
| 84492 | + rc = sqlite3BtreeNewDb(p->pDest); | |
| 84204 | 84493 | nSrcPage = 1; |
| 84205 | 84494 | } |
| 84206 | 84495 | if( rc==SQLITE_OK || rc==SQLITE_DONE ){ |
| 84207 | - rc = sqlite3BtreeUpdateMeta(pDest,1,p->iDestSchema+1); | |
| 84496 | + rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); | |
| 84208 | 84497 | } |
| 84209 | 84498 | if( rc==SQLITE_OK ){ |
| 84210 | 84499 | if( p->pDestDb ){ |
| 84211 | 84500 | sqlite3ResetAllSchemasOfConnection(p->pDestDb); |
| 84212 | 84501 | } |
| 84213 | 84502 | if( destMode==PAGER_JOURNALMODE_WAL ){ |
| 84214 | - rc = sqlite3BtreeSetVersion(pDest, 2); | |
| 84503 | + rc = sqlite3BtreeSetVersion(p->pDest, 2); | |
| 84215 | 84504 | } |
| 84216 | 84505 | } |
| 84217 | 84506 | if( rc==SQLITE_OK ){ |
| 84218 | 84507 | int nDestTruncate; |
| 84219 | 84508 | /* Set nDestTruncate to the final number of pages in the destination |
| @@ -84226,16 +84515,16 @@ | ||
| 84226 | 84515 | ** sqlite3PagerTruncateImage() here so that any pages in the |
| 84227 | 84516 | ** destination file that lie beyond the nDestTruncate page mark are |
| 84228 | 84517 | ** journalled by PagerCommitPhaseOne() before they are destroyed |
| 84229 | 84518 | ** by the file truncation. |
| 84230 | 84519 | */ |
| 84231 | - assert( pgszSrc==sqlite3BtreeGetPageSize(pSrc) ); | |
| 84232 | - assert( pgszDest==sqlite3BtreeGetPageSize(pDest) ); | |
| 84520 | + assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) ); | |
| 84521 | + assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) ); | |
| 84233 | 84522 | if( pgszSrc<pgszDest ){ |
| 84234 | 84523 | int ratio = pgszDest/pgszSrc; |
| 84235 | 84524 | nDestTruncate = (nSrcPage+ratio-1)/ratio; |
| 84236 | - if( nDestTruncate==(int)PENDING_BYTE_PAGE(pDest->pBt) ){ | |
| 84525 | + if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){ | |
| 84237 | 84526 | nDestTruncate--; |
| 84238 | 84527 | } |
| 84239 | 84528 | }else{ |
| 84240 | 84529 | nDestTruncate = nSrcPage * (pgszSrc/pgszDest); |
| 84241 | 84530 | } |
| @@ -84259,11 +84548,11 @@ | ||
| 84259 | 84548 | i64 iEnd; |
| 84260 | 84549 | |
| 84261 | 84550 | assert( pFile ); |
| 84262 | 84551 | assert( nDestTruncate==0 |
| 84263 | 84552 | || (i64)nDestTruncate*(i64)pgszDest >= iSize || ( |
| 84264 | - nDestTruncate==(int)(PENDING_BYTE_PAGE(pDest->pBt)-1) | |
| 84553 | + nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) | |
| 84265 | 84554 | && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest |
| 84266 | 84555 | )); |
| 84267 | 84556 | |
| 84268 | 84557 | /* This block ensures that all data required to recreate the original |
| 84269 | 84558 | ** database has been stored in the journal for pDestPager and the |
| @@ -84271,11 +84560,11 @@ | ||
| 84271 | 84560 | ** the database file in any way, knowing that if a power failure |
| 84272 | 84561 | ** occurs, the original database will be reconstructed from the |
| 84273 | 84562 | ** journal file. */ |
| 84274 | 84563 | sqlite3PagerPagecount(pDestPager, &nDstPage); |
| 84275 | 84564 | for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ |
| 84276 | - if( iPg!=PENDING_BYTE_PAGE(pDest->pBt) ){ | |
| 84565 | + if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ | |
| 84277 | 84566 | DbPage *pPg; |
| 84278 | 84567 | rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0); |
| 84279 | 84568 | if( rc==SQLITE_OK ){ |
| 84280 | 84569 | rc = sqlite3PagerWrite(pPg); |
| 84281 | 84570 | sqlite3PagerUnref(pPg); |
| @@ -84315,11 +84604,11 @@ | ||
| 84315 | 84604 | rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); |
| 84316 | 84605 | } |
| 84317 | 84606 | |
| 84318 | 84607 | /* Finish committing the transaction to the destination database. */ |
| 84319 | 84608 | if( SQLITE_OK==rc |
| 84320 | - && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(pDest, 0)) | |
| 84609 | + && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0)) | |
| 84321 | 84610 | ){ |
| 84322 | 84611 | rc = SQLITE_DONE; |
| 84323 | 84612 | } |
| 84324 | 84613 | } |
| 84325 | 84614 | } |
| @@ -84329,12 +84618,12 @@ | ||
| 84329 | 84618 | ** no need to check the return values of the btree methods here, as |
| 84330 | 84619 | ** "committing" a read-only transaction cannot fail. |
| 84331 | 84620 | */ |
| 84332 | 84621 | if( bCloseTrans ){ |
| 84333 | 84622 | TESTONLY( int rc2 ); |
| 84334 | - TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(pSrc, 0); | |
| 84335 | - TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(pSrc, 0); | |
| 84623 | + TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); | |
| 84624 | + TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0); | |
| 84336 | 84625 | assert( rc2==SQLITE_OK ); |
| 84337 | 84626 | } |
| 84338 | 84627 | |
| 84339 | 84628 | if( rc==SQLITE_IOERR_NOMEM ){ |
| 84340 | 84629 | rc = SQLITE_NOMEM_BKPT; |
| @@ -84342,11 +84631,11 @@ | ||
| 84342 | 84631 | p->rc = rc; |
| 84343 | 84632 | } |
| 84344 | 84633 | if( p->pDestDb ){ |
| 84345 | 84634 | sqlite3_mutex_leave(p->pDestDb->mutex); |
| 84346 | 84635 | } |
| 84347 | - sqlite3BtreeLeave(pSrc); | |
| 84636 | + sqlite3BtreeLeave(p->pSrc); | |
| 84348 | 84637 | sqlite3_mutex_leave(p->pSrcDb->mutex); |
| 84349 | 84638 | return rc; |
| 84350 | 84639 | } |
| 84351 | 84640 | |
| 84352 | 84641 | /* |
| @@ -84359,41 +84648,43 @@ | ||
| 84359 | 84648 | |
| 84360 | 84649 | /* Enter the mutexes */ |
| 84361 | 84650 | if( p==0 ) return SQLITE_OK; |
| 84362 | 84651 | pSrcDb = p->pSrcDb; |
| 84363 | 84652 | sqlite3_mutex_enter(pSrcDb->mutex); |
| 84364 | - sqlite3BtreeEnter(p->pSrc->pBt); | |
| 84653 | + sqlite3BtreeEnter(p->pSrc); | |
| 84365 | 84654 | if( p->pDestDb ){ |
| 84366 | 84655 | sqlite3_mutex_enter(p->pDestDb->mutex); |
| 84367 | 84656 | } |
| 84368 | 84657 | |
| 84369 | 84658 | /* Detach this backup from the source pager. */ |
| 84370 | 84659 | if( p->pDestDb ){ |
| 84371 | - p->pSrc->pBt->nBackup--; | |
| 84660 | + p->pSrc->nBackup--; | |
| 84372 | 84661 | } |
| 84373 | 84662 | if( p->isAttached ){ |
| 84374 | - pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc->pBt)); | |
| 84663 | + pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); | |
| 84375 | 84664 | assert( pp!=0 ); |
| 84376 | 84665 | while( *pp!=p ){ |
| 84377 | 84666 | pp = &(*pp)->pNext; |
| 84378 | 84667 | assert( pp!=0 ); |
| 84379 | 84668 | } |
| 84380 | 84669 | *pp = p->pNext; |
| 84381 | 84670 | } |
| 84382 | 84671 | |
| 84383 | 84672 | /* If a transaction is still open on the Btree, roll it back. */ |
| 84384 | - sqlite3BtreeRollback(p->pDest->pBt, SQLITE_OK, 0); | |
| 84673 | + if( p->pDest ){ | |
| 84674 | + sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0); | |
| 84675 | + } | |
| 84385 | 84676 | |
| 84386 | 84677 | /* Set the error code of the destination database handle. */ |
| 84387 | 84678 | rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; |
| 84388 | 84679 | if( p->pDestDb ){ |
| 84389 | 84680 | sqlite3Error(p->pDestDb, rc); |
| 84390 | 84681 | |
| 84391 | 84682 | /* Exit the mutexes and free the backup context structure. */ |
| 84392 | 84683 | sqlite3LeaveMutexAndCloseZombie(p->pDestDb); |
| 84393 | 84684 | } |
| 84394 | - sqlite3BtreeLeave(p->pSrc->pBt); | |
| 84685 | + sqlite3BtreeLeave(p->pSrc); | |
| 84395 | 84686 | if( p->pDestDb ){ |
| 84396 | 84687 | /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a |
| 84397 | 84688 | ** call to sqlite3_backup_init() and is destroyed by a call to |
| 84398 | 84689 | ** sqlite3_backup_finish(). */ |
| 84399 | 84690 | sqlite3_free(p); |
| @@ -84447,11 +84738,11 @@ | ||
| 84447 | 84738 | Pgno iPage, |
| 84448 | 84739 | const u8 *aData |
| 84449 | 84740 | ){ |
| 84450 | 84741 | assert( p!=0 ); |
| 84451 | 84742 | do{ |
| 84452 | - assert( sqlite3_mutex_held(p->pSrc->pBt->pBt->mutex) ); | |
| 84743 | + assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); | |
| 84453 | 84744 | if( !isFatalError(p->rc) && iPage<p->iNext ){ |
| 84454 | 84745 | /* The backup process p has already copied page iPage. But now it |
| 84455 | 84746 | ** has been modified by a transaction on the source pager. Copy |
| 84456 | 84747 | ** the new data into the backup. |
| 84457 | 84748 | */ |
| @@ -84483,11 +84774,11 @@ | ||
| 84483 | 84774 | ** called. |
| 84484 | 84775 | */ |
| 84485 | 84776 | SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *pBackup){ |
| 84486 | 84777 | sqlite3_backup *p; /* Iterator variable */ |
| 84487 | 84778 | for(p=pBackup; p; p=p->pNext){ |
| 84488 | - assert( sqlite3_mutex_held(p->pSrc->pBt->pBt->mutex) ); | |
| 84779 | + assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); | |
| 84489 | 84780 | p->iNext = 1; |
| 84490 | 84781 | } |
| 84491 | 84782 | } |
| 84492 | 84783 | |
| 84493 | 84784 | #ifndef SQLITE_OMIT_VACUUM |
| @@ -84501,12 +84792,10 @@ | ||
| 84501 | 84792 | */ |
| 84502 | 84793 | SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ |
| 84503 | 84794 | int rc; |
| 84504 | 84795 | sqlite3_file *pFd; /* File descriptor for database pTo */ |
| 84505 | 84796 | sqlite3_backup b; |
| 84506 | - Db dbDest; | |
| 84507 | - Db dbSrc; | |
| 84508 | 84797 | sqlite3BtreeEnter(pTo); |
| 84509 | 84798 | sqlite3BtreeEnter(pFrom); |
| 84510 | 84799 | |
| 84511 | 84800 | assert( sqlite3BtreeTxnState(pTo)==SQLITE_TXN_WRITE ); |
| 84512 | 84801 | pFd = sqlite3PagerFile(sqlite3BtreePager(pTo)); |
| @@ -84521,17 +84810,13 @@ | ||
| 84521 | 84810 | ** to 0. This is used by the implementations of sqlite3_backup_step() |
| 84522 | 84811 | ** and sqlite3_backup_finish() to detect that they are being called |
| 84523 | 84812 | ** from this function, not directly by the user. |
| 84524 | 84813 | */ |
| 84525 | 84814 | memset(&b, 0, sizeof(b)); |
| 84526 | - memset(&dbDest, 0, sizeof(dbDest)); | |
| 84527 | - memset(&dbSrc, 0, sizeof(dbSrc)); | |
| 84528 | - dbDest.pBt = pTo; | |
| 84529 | - dbSrc.pBt = pFrom; | |
| 84530 | 84815 | b.pSrcDb = pFrom->db; |
| 84531 | - b.pSrc = &dbSrc; | |
| 84532 | - b.pDest = &dbDest; | |
| 84816 | + b.pSrc = pFrom; | |
| 84817 | + b.pDest = pTo; | |
| 84533 | 84818 | b.iNext = 1; |
| 84534 | 84819 | |
| 84535 | 84820 | /* 0x7FFFFFFF is the hard limit for the number of pages in a database |
| 84536 | 84821 | ** file. By passing this as the number of pages to copy to |
| 84537 | 84822 | ** sqlite3_backup_step(), we can guarantee that the copy finishes |
| @@ -84543,11 +84828,11 @@ | ||
| 84543 | 84828 | |
| 84544 | 84829 | rc = sqlite3_backup_finish(&b); |
| 84545 | 84830 | if( rc==SQLITE_OK ){ |
| 84546 | 84831 | pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; |
| 84547 | 84832 | }else{ |
| 84548 | - sqlite3PagerClearCache(sqlite3BtreePager(pTo)); | |
| 84833 | + sqlite3PagerClearCache(sqlite3BtreePager(b.pDest)); | |
| 84549 | 84834 | } |
| 84550 | 84835 | |
| 84551 | 84836 | assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE ); |
| 84552 | 84837 | copy_finished: |
| 84553 | 84838 | sqlite3BtreeLeave(pFrom); |
| @@ -86859,11 +87144,10 @@ | ||
| 86859 | 87144 | p->pParse = pParse; |
| 86860 | 87145 | pParse->pVdbe = p; |
| 86861 | 87146 | assert( pParse->aLabel==0 ); |
| 86862 | 87147 | assert( pParse->nLabel==0 ); |
| 86863 | 87148 | assert( p->nOpAlloc==0 ); |
| 86864 | - assert( pParse->szOpAlloc==0 ); | |
| 86865 | 87149 | sqlite3VdbeAddOp2(p, OP_Init, 0, 1); |
| 86866 | 87150 | return p; |
| 86867 | 87151 | } |
| 86868 | 87152 | |
| 86869 | 87153 | /* |
| @@ -87009,12 +87293,11 @@ | ||
| 87009 | 87293 | |
| 87010 | 87294 | assert( nOp<=(int)(1024/sizeof(Op)) ); |
| 87011 | 87295 | assert( nNew>=(v->nOpAlloc+nOp) ); |
| 87012 | 87296 | pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op)); |
| 87013 | 87297 | if( pNew ){ |
| 87014 | - p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew); | |
| 87015 | - v->nOpAlloc = p->szOpAlloc/sizeof(Op); | |
| 87298 | + v->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op); | |
| 87016 | 87299 | v->aOp = pNew; |
| 87017 | 87300 | } |
| 87018 | 87301 | return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT); |
| 87019 | 87302 | } |
| 87020 | 87303 | |
| @@ -87445,11 +87728,11 @@ | ||
| 87445 | 87728 | ** Resolve label "x" to be the address of the next instruction to |
| 87446 | 87729 | ** be inserted. The parameter "x" must have been obtained from |
| 87447 | 87730 | ** a prior call to sqlite3VdbeMakeLabel(). |
| 87448 | 87731 | */ |
| 87449 | 87732 | static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){ |
| 87450 | - int nNewSize = 10 - p->nLabel; | |
| 87733 | + int nNewSize = 25 - p->nLabel; | |
| 87451 | 87734 | p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, |
| 87452 | 87735 | nNewSize*sizeof(p->aLabel[0])); |
| 87453 | 87736 | if( p->aLabel==0 ){ |
| 87454 | 87737 | p->nLabelAlloc = 0; |
| 87455 | 87738 | }else{ |
| @@ -89513,11 +89796,11 @@ | ||
| 89513 | 89796 | ** of the prepared statement. |
| 89514 | 89797 | */ |
| 89515 | 89798 | n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ |
| 89516 | 89799 | x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ |
| 89517 | 89800 | assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); |
| 89518 | - x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ | |
| 89801 | + x.nFree = ROUNDDOWN8((p->nOpAlloc-p->nOp)*sizeof(Op)); /* Bytes unused mem */ | |
| 89519 | 89802 | assert( x.nFree>=0 ); |
| 89520 | 89803 | assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); |
| 89521 | 89804 | |
| 89522 | 89805 | resolveP2Values(p, &nArg); |
| 89523 | 89806 | p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); |
| @@ -92662,12 +92945,18 @@ | ||
| 92662 | 92945 | ** that sqlite3_prepare() generates. For example, if new functions or |
| 92663 | 92946 | ** collating sequences are registered or if an authorizer function is |
| 92664 | 92947 | ** added or changed. |
| 92665 | 92948 | */ |
| 92666 | 92949 | SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ |
| 92667 | - Vdbe *p = (Vdbe*)pStmt; | |
| 92668 | - return p==0 || p->expired; | |
| 92950 | + int iRet = 1; | |
| 92951 | + if( pStmt ){ | |
| 92952 | + Vdbe *p = (Vdbe*)pStmt; | |
| 92953 | + sqlite3_mutex_enter(p->db->mutex); | |
| 92954 | + iRet = p->expired; | |
| 92955 | + sqlite3_mutex_leave(p->db->mutex); | |
| 92956 | + } | |
| 92957 | + return iRet; | |
| 92669 | 92958 | } |
| 92670 | 92959 | #endif |
| 92671 | 92960 | |
| 92672 | 92961 | /* |
| 92673 | 92962 | ** Check on a Vdbe to make sure it has not been finalized. Log |
| @@ -93009,19 +93298,22 @@ | ||
| 93009 | 93298 | sqlite3ValueFree(pOld); |
| 93010 | 93299 | } |
| 93011 | 93300 | |
| 93012 | 93301 | |
| 93013 | 93302 | /**************************** sqlite3_result_ ******************************* |
| 93014 | -** The following routines are used by user-defined functions to specify | |
| 93015 | -** the function result. | |
| 93016 | -** | |
| 93017 | -** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the | |
| 93018 | -** result as a string or blob. Appropriate errors are set if the string/blob | |
| 93019 | -** is too big or if an OOM occurs. | |
| 93020 | -** | |
| 93021 | -** The invokeValueDestructor(P,X) routine invokes destructor function X() | |
| 93022 | -** on value P if P is not going to be used and need to be destroyed. | |
| 93303 | +** The following routines are used by application-defined SQL functions to | |
| 93304 | +** specify the function return value. There are many variations on | |
| 93305 | +** sqlite3_result_xxxx() for different types of return values. | |
| 93306 | +** | |
| 93307 | +** The setStrOrError() function is a helper function that invokes | |
| 93308 | +** sqlite3VdbeMemSetStr() to store the result as a string or blob. | |
| 93309 | +** Appropriate errors are set if the string/blob is too big or if | |
| 93310 | +** an OOM occurs. | |
| 93311 | +** | |
| 93312 | +** The invokeValueDestructor(P,X) helper function invokes the destructor | |
| 93313 | +** function X() on value P if P is not going to be used and need to | |
| 93314 | +** be destroyed. | |
| 93023 | 93315 | */ |
| 93024 | 93316 | static void setResultStrOrError( |
| 93025 | 93317 | sqlite3_context *pCtx, /* Function context */ |
| 93026 | 93318 | const char *z, /* String pointer */ |
| 93027 | 93319 | int n, /* Bytes in string, or negative */ |
| @@ -93330,11 +93622,11 @@ | ||
| 93330 | 93622 | setResultStrOrError(pCtx, sqlite3ErrStr(errCode), -1, SQLITE_UTF8, |
| 93331 | 93623 | SQLITE_STATIC); |
| 93332 | 93624 | } |
| 93333 | 93625 | } |
| 93334 | 93626 | |
| 93335 | -/* Force an SQLITE_TOOBIG error. */ | |
| 93627 | +/* Cause the SQL function to raise an SQLITE_TOOBIG error. */ | |
| 93336 | 93628 | SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ |
| 93337 | 93629 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 93338 | 93630 | if( pCtx==0 ) return; |
| 93339 | 93631 | #endif |
| 93340 | 93632 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| @@ -93341,20 +93633,78 @@ | ||
| 93341 | 93633 | pCtx->isError = SQLITE_TOOBIG; |
| 93342 | 93634 | sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, |
| 93343 | 93635 | SQLITE_UTF8, SQLITE_STATIC); |
| 93344 | 93636 | } |
| 93345 | 93637 | |
| 93346 | -/* An SQLITE_NOMEM error. */ | |
| 93638 | +/* Cause the SQL function to raise an SQLITE_NOMEM error. */ | |
| 93347 | 93639 | SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ |
| 93348 | 93640 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 93349 | 93641 | if( pCtx==0 ) return; |
| 93350 | 93642 | #endif |
| 93351 | 93643 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 93352 | 93644 | sqlite3VdbeMemSetNull(pCtx->pOut); |
| 93353 | 93645 | pCtx->isError = SQLITE_NOMEM_BKPT; |
| 93354 | 93646 | sqlite3OomFault(pCtx->pOut->db); |
| 93355 | 93647 | } |
| 93648 | + | |
| 93649 | +/* Make the return value of the SQL function or virtual table pCtx | |
| 93650 | +** be the content of the sqlite3_str object pStr. The eOwn flag | |
| 93651 | +** determines ownership of the sqlite3_str object and its content. | |
| 93652 | +** | |
| 93653 | +** eOwn Ownership transfer | |
| 93654 | +** ------------- ------------------------------------------------ | |
| 93655 | +** | |
| 93656 | +** SQLITE_COPY The SQL function returns a copy the sqlite3_str | |
| 93657 | +** content and leaves the sqlite3_str object itself | |
| 93658 | +** unchanged. | |
| 93659 | +** | |
| 93660 | +** SQLITE_XFER The content of the sqlite3_str is transferred to | |
| 93661 | +** the SQL function and the SQL function takes | |
| 93662 | +** responsibility for freeing that content when it is | |
| 93663 | +** no longer needed. The sqlite3_str object is reset | |
| 93664 | +** to an empty string. | |
| 93665 | +** | |
| 93666 | +** SQLITE_FINISH Like SQLITE_XFER except that the pStr is also | |
| 93667 | +** freed using sqlite3_str_free(). | |
| 93668 | +*/ | |
| 93669 | +SQLITE_API void sqlite3_result_str(sqlite3_context *pCtx, sqlite3_str *pStr, int eOwn){ | |
| 93670 | +#ifdef SQLITE_ENABLE_API_ARMOR | |
| 93671 | + if( pCtx==0 ) return; | |
| 93672 | + if( pStr==0 ) return; | |
| 93673 | +#endif | |
| 93674 | + testcase( pStr==(sqlite3_str*)&sqlite3OomStr ); | |
| 93675 | + if( pStr->accError==0 ){ | |
| 93676 | + if( pStr->nChar==0 ){ | |
| 93677 | + setResultStrOrError(pCtx, "", 0, SQLITE_UTF8_ZT, SQLITE_STATIC); | |
| 93678 | + sqlite3_str_reset(pStr); | |
| 93679 | + }else{ | |
| 93680 | + const char *zText = sqlite3_str_value(pStr); | |
| 93681 | + /* Only internal code has the ability to capture a pointer to | |
| 93682 | + ** an sqlite3_str object that uses static buffer. And none of | |
| 93683 | + ** those internal use cases every invoke the sqlite3_result_str() | |
| 93684 | + ** interface on a static-buffer sqlite3_str. Should this change | |
| 93685 | + ** in the future, the following assert() will let us know. */ | |
| 93686 | + assert( isMalloced(pStr) ); | |
| 93687 | + if( eOwn==SQLITE_COPY ){ | |
| 93688 | + setResultStrOrError(pCtx, zText, pStr->nChar, | |
| 93689 | + SQLITE_UTF8, SQLITE_TRANSIENT); | |
| 93690 | + }else{ | |
| 93691 | + setResultStrOrError(pCtx, zText, pStr->nChar, | |
| 93692 | + SQLITE_UTF8_ZT, SQLITE_DYNAMIC); | |
| 93693 | + sqlite3StrAccumInit(pStr, pStr->db, 0, 0, pStr->mxAlloc); | |
| 93694 | + } | |
| 93695 | + } | |
| 93696 | + }else if( pStr->accError==SQLITE_NOMEM ){ | |
| 93697 | + sqlite3_result_error_nomem(pCtx); | |
| 93698 | + }else{ | |
| 93699 | + assert( pStr->accError==SQLITE_TOOBIG ); | |
| 93700 | + sqlite3_result_error_toobig(pCtx); | |
| 93701 | + } | |
| 93702 | + if( eOwn==SQLITE_FINISH ){ | |
| 93703 | + sqlite3_str_free(pStr); | |
| 93704 | + } | |
| 93705 | +} | |
| 93356 | 93706 | |
| 93357 | 93707 | #ifndef SQLITE_UNTESTABLE |
| 93358 | 93708 | /* Force the INT64 value currently stored as the result to be |
| 93359 | 93709 | ** a MEM_IntReal value. See the SQLITE_TESTCTRL_RESULT_INTREAL |
| 93360 | 93710 | ** test-control. |
| @@ -96241,10 +96591,14 @@ | ||
| 96241 | 96591 | } |
| 96242 | 96592 | |
| 96243 | 96593 | /* |
| 96244 | 96594 | ** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning |
| 96245 | 96595 | ** with pOp->p3. Return the hash. |
| 96596 | +** | |
| 96597 | +** IMPORTANT RESTRICTION (tag-202607231411): This hash is only valid if the | |
| 96598 | +** collating sequence for TEXT is BINARY. Hence, Bloom filters that use this | |
| 96599 | +** hash will not work for look-ups that use any other collating sequence. | |
| 96246 | 96600 | */ |
| 96247 | 96601 | static u64 filterHash(const Mem *aMem, const Op *pOp){ |
| 96248 | 96602 | int i, mx; |
| 96249 | 96603 | u64 h = 0; |
| 96250 | 96604 | |
| @@ -96253,15 +96607,32 @@ | ||
| 96253 | 96607 | const Mem *p = &aMem[i]; |
| 96254 | 96608 | if( p->flags & (MEM_Int|MEM_IntReal) ){ |
| 96255 | 96609 | h += p->u.i; |
| 96256 | 96610 | }else if( p->flags & MEM_Real ){ |
| 96257 | 96611 | h += sqlite3VdbeIntValue(p); |
| 96258 | - }else if( p->flags & (MEM_Str|MEM_Blob) ){ | |
| 96259 | - /* All strings have the same hash and all blobs have the same hash, | |
| 96260 | - ** though, at least, those hashes are different from each other and | |
| 96261 | - ** from NULL. */ | |
| 96262 | - h += 4093 + (p->flags & (MEM_Str|MEM_Blob)); | |
| 96612 | + }else if( p->flags & MEM_Str ){ | |
| 96613 | + u64 x; | |
| 96614 | + h += p->n; | |
| 96615 | + if( p->n >= sizeof(x) ){ | |
| 96616 | + memcpy(&x, p->z, sizeof(x)); | |
| 96617 | + h += x; | |
| 96618 | + memcpy(&x, p->z + p->n - sizeof(x), sizeof(x)); | |
| 96619 | + h += x; | |
| 96620 | + }else{ | |
| 96621 | + x = 0; | |
| 96622 | + memcpy(&x, p->z, p->n); | |
| 96623 | + h += x; | |
| 96624 | + } | |
| 96625 | + }else if( p->flags & MEM_Blob ){ | |
| 96626 | + int n = p->n; | |
| 96627 | + u64 x = 0; | |
| 96628 | + if( n ){ | |
| 96629 | + memcpy(&x, p->z, MIN(n, sizeof(x))); | |
| 96630 | + h += x; | |
| 96631 | + } | |
| 96632 | + h += n; | |
| 96633 | + if( p->flags & MEM_Zero ) h += p->u.nZero; | |
| 96263 | 96634 | } |
| 96264 | 96635 | } |
| 96265 | 96636 | return h; |
| 96266 | 96637 | } |
| 96267 | 96638 | |
| @@ -101084,11 +101455,11 @@ | ||
| 101084 | 101455 | */ |
| 101085 | 101456 | case OP_SeekRowid: { /* jump0, in3, ncycle */ |
| 101086 | 101457 | VdbeCursor *pC; |
| 101087 | 101458 | BtCursor *pCrsr; |
| 101088 | 101459 | int res; |
| 101089 | - u64 iKey; | |
| 101460 | + i64 iKey; | |
| 101090 | 101461 | |
| 101091 | 101462 | pIn3 = &aMem[pOp->p3]; |
| 101092 | 101463 | testcase( pIn3->flags & MEM_Int ); |
| 101093 | 101464 | testcase( pIn3->flags & MEM_IntReal ); |
| 101094 | 101465 | testcase( pIn3->flags & MEM_Real ); |
| @@ -101098,13 +101469,23 @@ | ||
| 101098 | 101469 | ** integer value of pIn3. Jump to P2 if pIn3 cannot be converted |
| 101099 | 101470 | ** into an integer without loss of information. Take care to avoid |
| 101100 | 101471 | ** changing the datatype of pIn3, however, as it is used by other |
| 101101 | 101472 | ** parts of the prepared statement. */ |
| 101102 | 101473 | Mem x = pIn3[0]; |
| 101103 | - applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding); | |
| 101104 | - if( (x.flags & MEM_Int)==0 ) goto jump_to_p2; | |
| 101105 | - iKey = x.u.i; | |
| 101474 | + if( x.flags & MEM_Str ){ | |
| 101475 | + applyNumericAffinity(&x, 1); | |
| 101476 | + } | |
| 101477 | + if( x.flags & MEM_Int ){ | |
| 101478 | + iKey = x.u.i; | |
| 101479 | + }else | |
| 101480 | + if( (x.flags & MEM_Real)==0 | |
| 101481 | + || x.u.r < -9223372036854775808.0 | |
| 101482 | + || x.u.r > 9223372036854775807.0 | |
| 101483 | + || (double)(iKey = sqlite3RealToI64(x.u.r))!=x.u.r | |
| 101484 | + ){ | |
| 101485 | + goto jump_to_p2; | |
| 101486 | + } | |
| 101106 | 101487 | goto notExistsWithKey; |
| 101107 | 101488 | } |
| 101108 | 101489 | /* Fall through into OP_NotExists */ |
| 101109 | 101490 | /* no break */ deliberate_fall_through |
| 101110 | 101491 | case OP_NotExists: /* jump, in3, ncycle */ |
| @@ -102342,10 +102723,15 @@ | ||
| 102342 | 102723 | pTabCur = p->apCsr[pOp->p3]; |
| 102343 | 102724 | assert( pTabCur!=0 ); |
| 102344 | 102725 | assert( pTabCur->eCurType==CURTYPE_BTREE ); |
| 102345 | 102726 | assert( pTabCur->uc.pCursor!=0 ); |
| 102346 | 102727 | assert( pTabCur->isTable ); |
| 102728 | +#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG) | |
| 102729 | + assert( | |
| 102730 | + sqlite3BtreeCursorHintTblCsr(pC->uc.pCursor)==pTabCur->uc.pCursor | |
| 102731 | + ); | |
| 102732 | +#endif | |
| 102347 | 102733 | pTabCur->nullRow = 0; |
| 102348 | 102734 | pTabCur->movetoTarget = rowid; |
| 102349 | 102735 | pTabCur->deferredMoveto = 1; |
| 102350 | 102736 | pTabCur->cacheStatus = CACHE_STALE; |
| 102351 | 102737 | assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); |
| @@ -104724,27 +105110,41 @@ | ||
| 104724 | 105110 | p->aCounter[SQLITE_STMTSTATUS_RUN]++; |
| 104725 | 105111 | goto jump_to_p2; |
| 104726 | 105112 | } |
| 104727 | 105113 | |
| 104728 | 105114 | #ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 104729 | -/* Opcode: CursorHint P1 * * P4 * | |
| 105115 | +/* Opcode: CursorHint P1 * P3 P4 * | |
| 104730 | 105116 | ** |
| 104731 | -** Provide a hint to cursor P1 that it only needs to return rows that | |
| 104732 | -** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer | |
| 104733 | -** to values currently held in registers. TK_COLUMN terms in the P4 | |
| 105117 | +** Provide a hint to cursor P1. | |
| 105118 | +** | |
| 105119 | +** If P4 is of type P4_EXPR, then the hint is that the cursor need only return | |
| 105120 | +** rows that satisfy the Expr in P4. TK_REGISTER terms in the P4 expression | |
| 105121 | +** refer to values currently held in registers. TK_COLUMN terms in the P4 | |
| 104734 | 105122 | ** expression refer to columns in the b-tree to which cursor P1 is pointing. |
| 105123 | +** P3 is ignore in this case. | |
| 105124 | +** | |
| 105125 | +** Or, if P4 is P4_NOTUSED, then the hint is that cursor P1 is an index cursor | |
| 105126 | +** used to drive table cursor P3. In other words, that this VM may execute | |
| 105127 | +** OP_DeferredSeek instructions to lazily position P3 based on current | |
| 105128 | +** position of P1. | |
| 104735 | 105129 | */ |
| 104736 | 105130 | case OP_CursorHint: { |
| 104737 | 105131 | VdbeCursor *pC; |
| 105132 | + pC = p->apCsr[pOp->p1]; | |
| 104738 | 105133 | |
| 104739 | 105134 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 104740 | - assert( pOp->p4type==P4_EXPR ); | |
| 104741 | - pC = p->apCsr[pOp->p1]; | |
| 105135 | + | |
| 104742 | 105136 | if( pC ){ |
| 104743 | 105137 | assert( pC->eCurType==CURTYPE_BTREE ); |
| 104744 | - sqlite3BtreeCursorHint(pC->uc.pCursor, BTREE_HINT_RANGE, | |
| 104745 | - pOp->p4.pExpr, aMem); | |
| 105138 | + if( pOp->p4type==P4_EXPR ){ | |
| 105139 | + sqlite3BtreeCursorHint(pC->uc.pCursor, BTREE_HINT_RANGE, | |
| 105140 | + pOp->p4.pExpr, aMem); | |
| 105141 | + }else if( p->apCsr[pOp->p3] ){ | |
| 105142 | + sqlite3BtreeCursorHint( | |
| 105143 | + pC->uc.pCursor, BTREE_HINT_TABLECURSOR, p->apCsr[pOp->p3]->uc.pCursor | |
| 105144 | + ); | |
| 105145 | + } | |
| 104746 | 105146 | } |
| 104747 | 105147 | break; |
| 104748 | 105148 | } |
| 104749 | 105149 | #endif /* SQLITE_ENABLE_CURSOR_HINTS */ |
| 104750 | 105150 | |
| @@ -110329,13 +110729,15 @@ | ||
| 110329 | 110729 | if( pFJMatch ){ |
| 110330 | 110730 | assert( pExpr->op==TK_FUNCTION ); |
| 110331 | 110731 | assert( sqlite3_stricmp(pExpr->u.zToken,"coalesce")==0 ); |
| 110332 | 110732 | assert( pExpr->x.pList==pFJMatch ); |
| 110333 | 110733 | assert( pFJMatch->nExpr>0 ); |
| 110334 | - pExpr = pFJMatch->a[0].pExpr; | |
| 110335 | - } | |
| 110336 | - if( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ){ | |
| 110734 | + for(i=0; i<pFJMatch->nExpr; i++){ | |
| 110735 | + assert( pFJMatch->a[i].pExpr->op==TK_COLUMN ); | |
| 110736 | + sqlite3AuthRead(pParse,pFJMatch->a[i].pExpr,pSchema,pNC->pSrcList); | |
| 110737 | + } | |
| 110738 | + }else if( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ){ | |
| 110337 | 110739 | sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); |
| 110338 | 110740 | } |
| 110339 | 110741 | } |
| 110340 | 110742 | #endif |
| 110341 | 110743 | /* Increment the nRef value on all name contexts from TopNC up to |
| @@ -110447,15 +110849,24 @@ | ||
| 110447 | 110849 | static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){ |
| 110448 | 110850 | int nn, ii; |
| 110449 | 110851 | nn = pList ? pList->nExpr : 0; |
| 110450 | 110852 | for(ii=0; ii<nn; ii++){ |
| 110451 | 110853 | Expr *pExpr = pList->a[ii].pExpr; |
| 110452 | - ExprSetProperty(pExpr, EP_SubtArg); | |
| 110453 | - if( pExpr->op==TK_SELECT ){ | |
| 110454 | - assert( ExprUseXSelect(pExpr) ); | |
| 110455 | - assert( pExpr->x.pSelect!=0 ); | |
| 110456 | - resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList); | |
| 110854 | + while( 1 /*exit-by-break*/ ){ | |
| 110855 | + ExprSetProperty(pExpr, EP_SubtArg); | |
| 110856 | + if( pExpr->op==TK_SELECT ){ | |
| 110857 | + assert( ExprUseXSelect(pExpr) ); | |
| 110858 | + assert( pExpr->x.pSelect!=0 ); | |
| 110859 | + resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList); | |
| 110860 | + break; | |
| 110861 | + } | |
| 110862 | + if( pExpr->op==TK_UPLUS ){ | |
| 110863 | + pExpr = pExpr->pLeft; | |
| 110864 | + assert( pExpr!=0 ); | |
| 110865 | + }else{ | |
| 110866 | + break; | |
| 110867 | + } | |
| 110457 | 110868 | } |
| 110458 | 110869 | } |
| 110459 | 110870 | } |
| 110460 | 110871 | |
| 110461 | 110872 | /* |
| @@ -115538,10 +115949,12 @@ | ||
| 115538 | 115949 | }else{ |
| 115539 | 115950 | VdbeComment((v, "RHS of IN operator")); |
| 115540 | 115951 | } |
| 115541 | 115952 | #endif |
| 115542 | 115953 | pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1); |
| 115954 | + assert( pKeyInfo!=0 || pParse->nErr ); | |
| 115955 | + if( pKeyInfo==0 ) return; | |
| 115543 | 115956 | |
| 115544 | 115957 | if( ExprUseXSelect(pExpr) ){ |
| 115545 | 115958 | /* Case 1: expr IN (SELECT ...) |
| 115546 | 115959 | ** |
| 115547 | 115960 | ** Generate code to write the results of the select into the temporary |
| @@ -115562,21 +115975,35 @@ | ||
| 115562 | 115975 | int rc; |
| 115563 | 115976 | int addrBloom = 0; |
| 115564 | 115977 | sqlite3SelectDestInit(&dest, SRT_Set, iTab); |
| 115565 | 115978 | dest.zAffSdst = exprINAffinity(pParse, pExpr); |
| 115566 | 115979 | pSelect->iLimit = 0; |
| 115980 | + assert( pEList!=0 ); | |
| 115981 | + assert( pEList->nExpr>0 ); | |
| 115982 | + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); | |
| 115983 | + for(i=0; i<nVal; i++){ | |
| 115984 | + Expr *p = sqlite3VectorFieldSubexpr(pLeft, i); | |
| 115985 | + CollSeq *pColl; | |
| 115986 | + pKeyInfo->aColl[i] = pColl = sqlite3BinaryCompareCollSeq( | |
| 115987 | + pParse, p, pEList->a[i].pExpr | |
| 115988 | + ); | |
| 115989 | + if( !sqlite3IsBinary(pColl) ){ | |
| 115990 | + allowBloom = 0; /* tag-202607231411 */ | |
| 115991 | + } | |
| 115992 | + } | |
| 115567 | 115993 | if( addrOnce |
| 115568 | 115994 | && allowBloom |
| 115569 | 115995 | && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) |
| 115570 | 115996 | ){ |
| 115571 | 115997 | int regBloom = ++pParse->nMem; |
| 115572 | 115998 | addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom); |
| 115573 | 115999 | VdbeComment((v, "Bloom filter")); |
| 115574 | 116000 | dest.iSDParm2 = regBloom; |
| 116001 | + sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO); | |
| 116002 | + pKeyInfo = 0; | |
| 115575 | 116003 | } |
| 115576 | 116004 | testcase( pSelect->selFlags & SF_Distinct ); |
| 115577 | - testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ | |
| 115578 | 116005 | pCopy = sqlite3SelectDup(pParse->db, pSelect, 0); |
| 115579 | 116006 | rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest); |
| 115580 | 116007 | sqlite3SelectDelete(pParse->db, pCopy); |
| 115581 | 116008 | sqlite3DbFree(pParse->db, dest.zAffSdst); |
| 115582 | 116009 | if( addrBloom ){ |
| @@ -115590,20 +116017,10 @@ | ||
| 115590 | 116017 | } |
| 115591 | 116018 | if( rc ){ |
| 115592 | 116019 | sqlite3KeyInfoUnref(pKeyInfo); |
| 115593 | 116020 | return; |
| 115594 | 116021 | } |
| 115595 | - assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ | |
| 115596 | - assert( pEList!=0 ); | |
| 115597 | - assert( pEList->nExpr>0 ); | |
| 115598 | - assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); | |
| 115599 | - for(i=0; i<nVal; i++){ | |
| 115600 | - Expr *p = sqlite3VectorFieldSubexpr(pLeft, i); | |
| 115601 | - pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq( | |
| 115602 | - pParse, p, pEList->a[i].pExpr | |
| 115603 | - ); | |
| 115604 | - } | |
| 115605 | 116022 | } |
| 115606 | 116023 | }else if( ALWAYS(pExpr->x.pList!=0) ){ |
| 115607 | 116024 | /* Case 2: expr IN (exprlist) |
| 115608 | 116025 | ** |
| 115609 | 116026 | ** For each expression, build an index key from the evaluation and |
| @@ -115620,14 +116037,13 @@ | ||
| 115620 | 116037 | if( affinity<=SQLITE_AFF_NONE ){ |
| 115621 | 116038 | affinity = SQLITE_AFF_BLOB; |
| 115622 | 116039 | }else if( affinity==SQLITE_AFF_REAL ){ |
| 115623 | 116040 | affinity = SQLITE_AFF_NUMERIC; |
| 115624 | 116041 | } |
| 115625 | - if( pKeyInfo ){ | |
| 115626 | - assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); | |
| 115627 | - pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); | |
| 115628 | - } | |
| 116042 | + assert( pKeyInfo!=0 ); | |
| 116043 | + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); | |
| 116044 | + pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); | |
| 115629 | 116045 | |
| 115630 | 116046 | /* Loop through each expression in <exprlist>. */ |
| 115631 | 116047 | r1 = sqlite3GetTempReg(pParse); |
| 115632 | 116048 | r2 = sqlite3GetTempReg(pParse); |
| 115633 | 116049 | for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ |
| @@ -116580,11 +116996,11 @@ | ||
| 116580 | 116996 | if( pExpr->op!=TK_FUNCTION ){ |
| 116581 | 116997 | return WRC_Prune; |
| 116582 | 116998 | } |
| 116583 | 116999 | assert( ExprUseXList(pExpr) ); |
| 116584 | 117000 | db = pWalker->pParse->db; |
| 116585 | - n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0; | |
| 117001 | + n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; | |
| 116586 | 117002 | pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); |
| 116587 | 117003 | if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){ |
| 116588 | 117004 | pWalker->eCode = 1; |
| 116589 | 117005 | return WRC_Abort; |
| 116590 | 117006 | } |
| @@ -117229,11 +117645,16 @@ | ||
| 117229 | 117645 | #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION |
| 117230 | 117646 | if( pDef==0 && pParse->explain ){ |
| 117231 | 117647 | pDef = sqlite3FindFunction(db, "unknown", nFarg, enc, 0); |
| 117232 | 117648 | } |
| 117233 | 117649 | #endif |
| 117234 | - if( pDef==0 || pDef->xFinalize!=0 ){ | |
| 117650 | + if( pDef==0 | |
| 117651 | + || pDef->xFinalize!=0 | |
| 117652 | + || ((pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 && | |
| 117653 | + !pParse->nested && | |
| 117654 | + (db->mDbFlags & DBFLAG_InternalFunc)==0) | |
| 117655 | + ){ | |
| 117235 | 117656 | sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr); |
| 117236 | 117657 | break; |
| 117237 | 117658 | } |
| 117238 | 117659 | if( (pDef->funcFlags & SQLITE_FUNC_INLINE)!=0 && ALWAYS(pFarg!=0) ){ |
| 117239 | 117660 | assert( (pDef->funcFlags & SQLITE_FUNC_UNSAFE)==0 ); |
| @@ -121984,19 +122405,41 @@ | ||
| 121984 | 122405 | |
| 121985 | 122406 | |
| 121986 | 122407 | /* |
| 121987 | 122408 | ** Argument z points into the body of a constraint - specifically the |
| 121988 | 122409 | ** second token of the constraint definition. For a named constraint, |
| 121989 | -** z points to the first token past the CONSTRAINT keyword. For an | |
| 122410 | +** z points to the second token of the constraint definition. For an | |
| 121990 | 122411 | ** unnamed NOT NULL constraint, z points to the first byte past the NOT |
| 121991 | 122412 | ** keyword. |
| 122413 | +** | |
| 122414 | +** Argument eTok may be the token value of the first token of the constraint | |
| 122415 | +** (e.g. TK_CHECK or TK_REFERENCES) or zero. If it is either TK_REFERENCES | |
| 122416 | +** or TK_FOREIGN, special parsing is enabled to find the end of the foreign-key | |
| 122417 | +** constraint definition. | |
| 121992 | 122418 | ** |
| 121993 | 122419 | ** Return the number of bytes until the end of the constraint. |
| 121994 | 122420 | */ |
| 121995 | -static int getConstraint(const u8 *z){ | |
| 122421 | +static int getConstraint(const u8 *z, int eTok){ | |
| 121996 | 122422 | int iOff = 0; |
| 121997 | 122423 | int t = 0; |
| 122424 | + | |
| 122425 | +#ifndef SQLITE_OMIT_FOREIGN_KEY | |
| 122426 | + if( eTok==TK_FOREIGN ){ | |
| 122427 | + /* For a FOREIGN KEY constraint, use getConstraint() to parse everything | |
| 122428 | + ** up to the REFERENCES keyword. Then getConstraintToken() to consume | |
| 122429 | + ** the TK_REFERENCES token itself. Then fall through to the special | |
| 122430 | + ** handling for TK_REFERENCES below. */ | |
| 122431 | + iOff = getConstraint(z, 0); | |
| 122432 | + iOff += getConstraintToken(&z[iOff], &eTok); | |
| 122433 | + } | |
| 122434 | + | |
| 122435 | + if( eTok==TK_REFERENCES ){ | |
| 122436 | + /* REFERENCES is followed by a table name. Gobble this up here in | |
| 122437 | + ** case the table name is a fallback token like TK_GENERATED. */ | |
| 122438 | + iOff += getConstraintToken(&z[iOff], &t); | |
| 122439 | + } | |
| 122440 | +#endif | |
| 121998 | 122441 | |
| 121999 | 122442 | /* Now, the current constraint proceeds until the next occurence of one |
| 122000 | 122443 | ** of the following tokens: |
| 122001 | 122444 | ** |
| 122002 | 122445 | ** CONSTRAINT, PRIMARY, NOT, UNIQUE, CHECK, DEFAULT, |
| @@ -122165,24 +122608,24 @@ | ||
| 122165 | 122608 | || t==TK_COMMA || t==TK_RP || t==TK_GENERATED || t==TK_AS |
| 122166 | 122609 | ){ |
| 122167 | 122610 | t = TK_CHECK; |
| 122168 | 122611 | }else{ |
| 122169 | 122612 | iOff += nTok; |
| 122170 | - iOff += getConstraint(&zSql[iOff]); | |
| 122613 | + iOff += getConstraint(&zSql[iOff], t); | |
| 122171 | 122614 | } |
| 122172 | 122615 | |
| 122173 | 122616 | if( cmp==0 || (iNotNull>=0 && t==TK_NOT) ){ |
| 122174 | - if( t!=TK_NOT && t!=TK_CHECK ){ | |
| 122617 | + if( t!=TK_NOT && t!=TK_CHECK && t!=TK_REFERENCES && t!=TK_FOREIGN ){ | |
| 122175 | 122618 | errorMPrintf(ctx, "constraint may not be dropped: %s", zCons); |
| 122176 | 122619 | return; |
| 122177 | 122620 | } |
| 122178 | 122621 | iEnd = iOff; |
| 122179 | 122622 | break; |
| 122180 | 122623 | } |
| 122181 | 122624 | |
| 122182 | 122625 | }else if( t==TK_NOT && iNotNull==ii ){ |
| 122183 | - iEnd = iOff + getConstraint(&zSql[iOff]); | |
| 122626 | + iEnd = iOff + getConstraint(&zSql[iOff], 0); | |
| 122184 | 122627 | break; |
| 122185 | 122628 | }else if( t==TK_RP || t==TK_ILLEGAL ){ |
| 122186 | 122629 | iEnd = -1; |
| 122187 | 122630 | break; |
| 122188 | 122631 | }else if( t==TK_COMMA ){ |
| @@ -122236,13 +122679,12 @@ | ||
| 122236 | 122679 | const u8 *zSql = sqlite3_value_text(argv[0]); |
| 122237 | 122680 | const char *zCons = (const char*)sqlite3_value_text(argv[1]); |
| 122238 | 122681 | int iCol = sqlite3_value_int(argv[2]); |
| 122239 | 122682 | int iOff = 0; |
| 122240 | 122683 | int ii; |
| 122241 | - char *zNew = 0; | |
| 122684 | + sqlite3_str *pNew; | |
| 122242 | 122685 | int t = 0; |
| 122243 | - sqlite3 *db; | |
| 122244 | 122686 | UNUSED_PARAMETER(NotUsed); |
| 122245 | 122687 | |
| 122246 | 122688 | if( skipCreateTable(ctx, zSql, &iOff) ) return; |
| 122247 | 122689 | |
| 122248 | 122690 | for(ii=0; ii<=iCol || (iCol<0 && t!=TK_RP); ii++){ |
| @@ -122258,17 +122700,15 @@ | ||
| 122258 | 122700 | } |
| 122259 | 122701 | } |
| 122260 | 122702 | |
| 122261 | 122703 | iOff += getWhitespace(&zSql[iOff]); |
| 122262 | 122704 | |
| 122263 | - db = sqlite3_context_db_handle(ctx); | |
| 122264 | - if( iCol<0 ){ | |
| 122265 | - zNew = sqlite3MPrintf(db, "%.*s, %s%s", iOff, zSql, zCons, &zSql[iOff]); | |
| 122266 | - }else{ | |
| 122267 | - zNew = sqlite3MPrintf(db, "%.*s %s%s", iOff, zSql, zCons, &zSql[iOff]); | |
| 122268 | - } | |
| 122269 | - sqlite3_result_text(ctx, zNew, -1, SQLITE_DYNAMIC); | |
| 122705 | + pNew = sqlite3_str_new(sqlite3_context_db_handle(ctx)); | |
| 122706 | + sqlite3_str_append(pNew, (const char*)zSql, iOff); | |
| 122707 | + if( iCol<0 ) sqlite3_str_append(pNew, ",", 1); | |
| 122708 | + sqlite3_str_appendf(pNew, " %s%s", zCons, &zSql[iOff]); | |
| 122709 | + sqlite3_result_str(ctx, pNew, SQLITE_FINISH); | |
| 122270 | 122710 | } |
| 122271 | 122711 | |
| 122272 | 122712 | /* |
| 122273 | 122713 | ** Find a column named pCol in table pTab. If successful, set output |
| 122274 | 122714 | ** parameter *piCol to the index of the column in the table and return |
| @@ -123524,11 +123964,11 @@ | ||
| 123524 | 123964 | sqlite3_str_appendf(&sStat, " %llu", iVal); |
| 123525 | 123965 | #ifdef SQLITE_ENABLE_STAT4 |
| 123526 | 123966 | assert( p->current.anEq[i] || p->nRow==0 ); |
| 123527 | 123967 | #endif |
| 123528 | 123968 | } |
| 123529 | - sqlite3ResultStrAccum(context, &sStat); | |
| 123969 | + sqlite3_result_str(context, &sStat, SQLITE_XFER); | |
| 123530 | 123970 | } |
| 123531 | 123971 | #ifdef SQLITE_ENABLE_STAT4 |
| 123532 | 123972 | else if( eCall==STAT_GET_ROWID ){ |
| 123533 | 123973 | if( p->iGet<0 ){ |
| 123534 | 123974 | samplePushPrevious(p, 0); |
| @@ -123561,11 +124001,11 @@ | ||
| 123561 | 124001 | sqlite3StrAccumInit(&sStat, 0, 0, 0, p->nCol*100); |
| 123562 | 124002 | for(i=0; i<p->nCol; i++){ |
| 123563 | 124003 | sqlite3_str_appendf(&sStat, "%llu ", (u64)aCnt[i]); |
| 123564 | 124004 | } |
| 123565 | 124005 | if( sStat.nChar ) sStat.nChar--; |
| 123566 | - sqlite3ResultStrAccum(context, &sStat); | |
| 124006 | + sqlite3_result_str(context, &sStat, SQLITE_XFER); | |
| 123567 | 124007 | } |
| 123568 | 124008 | #endif /* SQLITE_ENABLE_STAT4 */ |
| 123569 | 124009 | #ifndef SQLITE_DEBUG |
| 123570 | 124010 | UNUSED_PARAMETER( argc ); |
| 123571 | 124011 | #endif |
| @@ -125649,10 +126089,11 @@ | ||
| 125649 | 126089 | } |
| 125650 | 126090 | } |
| 125651 | 126091 | |
| 125652 | 126092 | assert( pToplevel->nTableLock < 0x7fff0000 ); |
| 125653 | 126093 | nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1); |
| 126094 | + if( pToplevel->nTableLock==0 ) pToplevel->aTableLock = 0; | |
| 125654 | 126095 | pToplevel->aTableLock = |
| 125655 | 126096 | sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes); |
| 125656 | 126097 | if( pToplevel->aTableLock ){ |
| 125657 | 126098 | p = &pToplevel->aTableLock[pToplevel->nTableLock++]; |
| 125658 | 126099 | p->iDb = iDb; |
| @@ -125815,11 +126256,11 @@ | ||
| 125815 | 126256 | if( pParse->nTableLock ) codeTableLocks(pParse); |
| 125816 | 126257 | #endif |
| 125817 | 126258 | |
| 125818 | 126259 | /* Initialize any AUTOINCREMENT data structures required. |
| 125819 | 126260 | */ |
| 125820 | - if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse); | |
| 126261 | + if( pParse->usesAinc ) sqlite3AutoincrementBegin(pParse); | |
| 125821 | 126262 | |
| 125822 | 126263 | /* Code constant expressions that were factored out of inner loops. |
| 125823 | 126264 | */ |
| 125824 | 126265 | if( pParse->pConstExpr ){ |
| 125825 | 126266 | ExprList *pEL = pParse->pConstExpr; |
| @@ -125848,11 +126289,11 @@ | ||
| 125848 | 126289 | assert( v!=0 || pParse->nErr ); |
| 125849 | 126290 | assert( db->mallocFailed==0 || pParse->nErr ); |
| 125850 | 126291 | if( pParse->nErr==0 ){ |
| 125851 | 126292 | /* A minimum of one cursor is required if autoincrement is used |
| 125852 | 126293 | * See ticket [a696379c1f08866] */ |
| 125853 | - assert( pParse->pAinc==0 || pParse->nTab>0 ); | |
| 126294 | + assert( pParse->usesAinc==0 || pParse->nTab>0 ); | |
| 125854 | 126295 | sqlite3VdbeMakeReady(v, pParse); |
| 125855 | 126296 | pParse->rc = SQLITE_DONE; |
| 125856 | 126297 | }else{ |
| 125857 | 126298 | pParse->rc = SQLITE_ERROR; |
| 125858 | 126299 | } |
| @@ -127812,10 +128253,27 @@ | ||
| 127812 | 128253 | pIdx->aSortOrder = (u8*)zExtra; |
| 127813 | 128254 | pIdx->nColumn = (u16)N; /* See tag-20250221-1 above for proof of safety */ |
| 127814 | 128255 | pIdx->isResized = 1; |
| 127815 | 128256 | return SQLITE_OK; |
| 127816 | 128257 | } |
| 128258 | + | |
| 128259 | +/* | |
| 128260 | +** Return true if the index pIdx can support a Bloom filter on its | |
| 128261 | +** first N columns. Specifically, return true if all of the first N | |
| 128262 | +** columns have the BINARY collating sequence or no collating sequence | |
| 128263 | +** at all, and return false if there are any non-BINARY collating | |
| 128264 | +** seqeuences on any of the first N columns. tag-202607231411 | |
| 128265 | +*/ | |
| 128266 | +SQLITE_PRIVATE int sqlite3IndexBloomable(const Index *pIdx, int N){ | |
| 128267 | + int i; | |
| 128268 | + assert( pIdx!=0 ); | |
| 128269 | + assert( N <= pIdx->nColumn ); | |
| 128270 | + for(i=0; i<N; i++){ | |
| 128271 | + if( sqlite3StrICmp(pIdx->azColl[i],"BINARY")!=0 ) return 0; | |
| 128272 | + } | |
| 128273 | + return 1; | |
| 128274 | +} | |
| 127817 | 128275 | |
| 127818 | 128276 | /* |
| 127819 | 128277 | ** Estimate the total row width for a table. |
| 127820 | 128278 | */ |
| 127821 | 128279 | static void estimateTableWidth(Table *pTab){ |
| @@ -128164,18 +128622,15 @@ | ||
| 128164 | 128622 | |
| 128165 | 128623 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 128166 | 128624 | /* |
| 128167 | 128625 | ** Return true if zName is a shadow table name in the current database |
| 128168 | 128626 | ** connection. |
| 128169 | -** | |
| 128170 | -** zName is temporarily modified while this routine is running, but is | |
| 128171 | -** restored to its original value prior to this routine returning. | |
| 128172 | 128627 | */ |
| 128173 | 128628 | SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){ |
| 128174 | 128629 | const char *zTail; /* Pointer to the last "_" in zName */ |
| 128175 | 128630 | Table *pTab; /* Table that zName is a shadow of */ |
| 128176 | - char *zCopy; | |
| 128631 | + char *zCopy; /* Transient copy of zName after last "_" */ | |
| 128177 | 128632 | zTail = strrchr(zName, '_'); |
| 128178 | 128633 | if( zTail==0 ) return 0; |
| 128179 | 128634 | zCopy = sqlite3DbStrNDup(db, zName, (int)(zTail-zName)); |
| 128180 | 128635 | pTab = zCopy ? sqlite3FindTable(db, zCopy, 0) : 0; |
| 128181 | 128636 | sqlite3DbFree(db, zCopy); |
| @@ -129683,12 +130138,13 @@ | ||
| 129683 | 130138 | } |
| 129684 | 130139 | } |
| 129685 | 130140 | if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ |
| 129686 | 130141 | if( !ifNotExist ){ |
| 129687 | 130142 | sqlite3ErrorMsg(pParse, "index %s already exists", zName); |
| 130143 | + }else if( db->init.busy ){ | |
| 130144 | + sqlite3ErrorMsg(pParse,""); /* corruptSchema() will do the error */ | |
| 129688 | 130145 | }else{ |
| 129689 | - assert( !db->init.busy ); | |
| 129690 | 130146 | sqlite3CodeVerifySchema(pParse, iDb); |
| 129691 | 130147 | sqlite3ForceNotReadOnly(pParse); |
| 129692 | 130148 | } |
| 129693 | 130149 | goto exit_create_index; |
| 129694 | 130150 | } |
| @@ -133318,32 +133774,20 @@ | ||
| 133318 | 133774 | sqlite3_value **argv |
| 133319 | 133775 | ){ |
| 133320 | 133776 | PrintfArguments x; |
| 133321 | 133777 | StrAccum str; |
| 133322 | 133778 | const char *zFormat; |
| 133323 | - int n; | |
| 133324 | 133779 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 133325 | 133780 | |
| 133326 | 133781 | if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ |
| 133327 | 133782 | x.nArg = argc-1; |
| 133328 | 133783 | x.nUsed = 0; |
| 133329 | 133784 | x.apArg = argv+1; |
| 133330 | 133785 | sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 133331 | 133786 | str.printfFlags = SQLITE_PRINTF_SQLFUNC; |
| 133332 | 133787 | sqlite3_str_appendf(&str, zFormat, &x); |
| 133333 | - if( str.accError==SQLITE_OK ){ | |
| 133334 | - n = str.nChar; | |
| 133335 | - sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, | |
| 133336 | - SQLITE_DYNAMIC); | |
| 133337 | - }else{ | |
| 133338 | - if( str.accError==SQLITE_NOMEM ){ | |
| 133339 | - sqlite3_result_error_nomem(context); | |
| 133340 | - }else{ | |
| 133341 | - sqlite3_result_error_toobig(context); | |
| 133342 | - } | |
| 133343 | - sqlite3_str_reset(&str); | |
| 133344 | - } | |
| 133788 | + sqlite3_result_str(context, &str, SQLITE_XFER); | |
| 133345 | 133789 | } |
| 133346 | 133790 | } |
| 133347 | 133791 | |
| 133348 | 133792 | /* |
| 133349 | 133793 | ** Implementation of the substr() function. |
| @@ -134286,16 +134730,11 @@ | ||
| 134286 | 134730 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 134287 | 134731 | assert( argc==1 ); |
| 134288 | 134732 | UNUSED_PARAMETER(argc); |
| 134289 | 134733 | sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 134290 | 134734 | sqlite3QuoteValue(&str,argv[0],SQLITE_PTR_TO_INT(sqlite3_user_data(context))); |
| 134291 | - sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar, | |
| 134292 | - SQLITE_DYNAMIC); | |
| 134293 | - if( str.accError!=SQLITE_OK ){ | |
| 134294 | - sqlite3_result_null(context); | |
| 134295 | - sqlite3_result_error_code(context, str.accError); | |
| 134296 | - } | |
| 134735 | + sqlite3_result_str(context, &str, SQLITE_XFER); | |
| 134297 | 134736 | } |
| 134298 | 134737 | |
| 134299 | 134738 | /* |
| 134300 | 134739 | ** The unicode() function. Return the integer unicode code-point value |
| 134301 | 134740 | ** for the first character of the input string. |
| @@ -135324,32 +135763,22 @@ | ||
| 135324 | 135763 | #endif /* SQLITE_OMIT_WINDOWFUNC */ |
| 135325 | 135764 | static void groupConcatFinalize(sqlite3_context *context){ |
| 135326 | 135765 | GroupConcatCtx *pGCC |
| 135327 | 135766 | = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0); |
| 135328 | 135767 | if( pGCC ){ |
| 135329 | - sqlite3ResultStrAccum(context, &pGCC->str); | |
| 135768 | + sqlite3_result_str(context, &pGCC->str, SQLITE_XFER); | |
| 135330 | 135769 | #ifndef SQLITE_OMIT_WINDOWFUNC |
| 135331 | 135770 | sqlite3_free(pGCC->pnSepLengths); |
| 135332 | 135771 | #endif |
| 135333 | 135772 | } |
| 135334 | 135773 | } |
| 135335 | 135774 | #ifndef SQLITE_OMIT_WINDOWFUNC |
| 135336 | 135775 | static void groupConcatValue(sqlite3_context *context){ |
| 135337 | 135776 | GroupConcatCtx *pGCC |
| 135338 | 135777 | = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0); |
| 135339 | - if( pGCC ){ | |
| 135340 | - StrAccum *pAccum = &pGCC->str; | |
| 135341 | - if( pAccum->accError==SQLITE_TOOBIG ){ | |
| 135342 | - sqlite3_result_error_toobig(context); | |
| 135343 | - }else if( pAccum->accError==SQLITE_NOMEM ){ | |
| 135344 | - sqlite3_result_error_nomem(context); | |
| 135345 | - }else if( pGCC->nAccum>0 && pAccum->nChar==0 ){ | |
| 135346 | - sqlite3_result_text(context, "", 1, SQLITE_STATIC); | |
| 135347 | - }else{ | |
| 135348 | - const char *zText = sqlite3_str_value(pAccum); | |
| 135349 | - sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT); | |
| 135350 | - } | |
| 135778 | + if( pGCC && pGCC->nAccum>0 ){ | |
| 135779 | + sqlite3_result_str(context, &pGCC->str, SQLITE_COPY); | |
| 135351 | 135780 | } |
| 135352 | 135781 | } |
| 135353 | 135782 | #else |
| 135354 | 135783 | # define groupConcatValue 0 |
| 135355 | 135784 | #endif /* SQLITE_OMIT_WINDOWFUNC */ |
| @@ -135976,17 +136405,21 @@ | ||
| 135976 | 136405 | static void percentSort( |
| 135977 | 136406 | double *a, /* Array to sort */ |
| 135978 | 136407 | unsigned int n, /* Number of elements in array a[] */ |
| 135979 | 136408 | int iReq /* Element caller cares about (or -ve) */ |
| 135980 | 136409 | ){ |
| 135981 | - int iLt; /* Entries before a[iLt] are less than rPivot */ | |
| 135982 | - int iGt; /* Entries at or after a[iGt] are greater than rPivot */ | |
| 136410 | + int iLt; /* Entries before a[iLt] are less than or equal to rPivot */ | |
| 136411 | + int iGt; /* Entries a[iGt] and after are greater or equal to rPivot */ | |
| 135983 | 136412 | int i; /* Loop counter */ |
| 135984 | 136413 | double rPivot; /* The pivot value */ |
| 135985 | 136414 | |
| 135986 | 136415 | assert( n>=2 ); |
| 135987 | 136416 | do{ |
| 136417 | + /* Put the first, middle, and last elements in sorted order. | |
| 136418 | + ** After doing so, return immediately if the array contains | |
| 136419 | + ** three or fewer elements as there is nothing more to do. | |
| 136420 | + */ | |
| 135988 | 136421 | if( a[0]>a[n-1] ){ |
| 135989 | 136422 | SWAP_DOUBLE(a[0],a[n-1]) |
| 135990 | 136423 | } |
| 135991 | 136424 | if( n==2 ) return; |
| 135992 | 136425 | iGt = n-1; |
| @@ -135995,10 +136428,15 @@ | ||
| 135995 | 136428 | SWAP_DOUBLE(a[0],a[i]) |
| 135996 | 136429 | }else if( a[i]>a[iGt] ){ |
| 135997 | 136430 | SWAP_DOUBLE(a[i],a[iGt]) |
| 135998 | 136431 | } |
| 135999 | 136432 | if( n==3 ) return; |
| 136433 | + | |
| 136434 | + /* Take the value of the middle element as the pivot. Shuffle | |
| 136435 | + ** values around so that all elements less than the pivot come | |
| 136436 | + ** before all elements greater than the pivot. | |
| 136437 | + */ | |
| 136000 | 136438 | rPivot = a[i]; |
| 136001 | 136439 | iLt = i = 1; |
| 136002 | 136440 | do{ |
| 136003 | 136441 | if( a[i]<rPivot ){ |
| 136004 | 136442 | if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt]) |
| @@ -136012,12 +136450,16 @@ | ||
| 136012 | 136450 | }else{ |
| 136013 | 136451 | i++; |
| 136014 | 136452 | } |
| 136015 | 136453 | }while( i<iGt ); |
| 136016 | 136454 | |
| 136455 | + assert( iLt>0 && iLt<iGt && iGt<n ); | |
| 136456 | + testcase( iGt>iLt+1 ); | |
| 136017 | 136457 | assert( a[iLt]==rPivot ); |
| 136018 | - assert( iGt>iLt ); | |
| 136458 | + assert( a[iLt-1]<=rPivot ); | |
| 136459 | + assert( a[iGt]>=rPivot ); | |
| 136460 | + assert( a[iLt+1]>=rPivot ); | |
| 136019 | 136461 | |
| 136020 | 136462 | if( iReq>=0 ){ |
| 136021 | 136463 | /* In this case, the only elements that the caller requires sorted into |
| 136022 | 136464 | ** the correct positions are elements a[iReq] and a[iReq+1]. At this |
| 136023 | 136465 | ** point we know that element a[iLt] is in the correct position and |
| @@ -136190,12 +136632,11 @@ | ||
| 136190 | 136632 | sqlite3_str_appendall(pStr, ",\"journal\":"); |
| 136191 | 136633 | rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr); |
| 136192 | 136634 | if( rc ) sqlite3_str_append(pStr, "null", 4); |
| 136193 | 136635 | } |
| 136194 | 136636 | sqlite3_str_append(pStr, "}", 1); |
| 136195 | - sqlite3_result_text(context, sqlite3_str_finish(pStr), -1, | |
| 136196 | - sqlite3_free); | |
| 136637 | + sqlite3_result_str(context, pStr, SQLITE_FINISH); | |
| 136197 | 136638 | } |
| 136198 | 136639 | sqlite3BtreeLeave(pBtree); |
| 136199 | 136640 | }else{ |
| 136200 | 136641 | sqlite3_result_text(context, "{}", 2, SQLITE_STATIC); |
| 136201 | 136642 | } |
| @@ -136307,12 +136748,12 @@ | ||
| 136307 | 136748 | }else{ |
| 136308 | 136749 | sqlite3_str_appendf(pResult, ", NULL"); |
| 136309 | 136750 | } |
| 136310 | 136751 | } |
| 136311 | 136752 | } |
| 136312 | - sqlite3_result_text(ctx, sqlite3_str_finish(pResult), -1, sqlite3_free); | |
| 136313 | 136753 | } |
| 136754 | + sqlite3_result_str(ctx, pResult, SQLITE_FINISH); | |
| 136314 | 136755 | sqlite3_free_filename(zFile); |
| 136315 | 136756 | sqlite3_free(zErr); |
| 136316 | 136757 | } |
| 136317 | 136758 | #endif /* SQLITE_DEBUG */ |
| 136318 | 136759 | |
| @@ -136405,11 +136846,11 @@ | ||
| 136405 | 136846 | VFUNCTION(random, 0, 0, 0, randomFunc ), |
| 136406 | 136847 | VFUNCTION(randomblob, 1, 0, 0, randomBlob ), |
| 136407 | 136848 | FUNCTION(nullif, 2, 0, 1, nullifFunc ), |
| 136408 | 136849 | DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), |
| 136409 | 136850 | DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), |
| 136410 | - FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), | |
| 136851 | + SFUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), | |
| 136411 | 136852 | FUNCTION(unistr, 1, 0, 0, unistrFunc ), |
| 136412 | 136853 | FUNCTION(quote, 1, 0, 0, quoteFunc ), |
| 136413 | 136854 | FUNCTION(unistr_quote, 1, 1, 0, quoteFunc ), |
| 136414 | 136855 | VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), |
| 136415 | 136856 | VFUNCTION(changes, 0, 0, 0, changes ), |
| @@ -138454,19 +138895,23 @@ | ||
| 138454 | 138895 | pParse->nErr++; |
| 138455 | 138896 | pParse->rc = SQLITE_CORRUPT_SEQUENCE; |
| 138456 | 138897 | return 0; |
| 138457 | 138898 | } |
| 138458 | 138899 | |
| 138900 | + if( pToplevel->usesAinc==0 ){ | |
| 138901 | + pToplevel->pAinc = 0; | |
| 138902 | + } | |
| 138459 | 138903 | pInfo = pToplevel->pAinc; |
| 138460 | 138904 | while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } |
| 138461 | 138905 | if( pInfo==0 ){ |
| 138462 | 138906 | pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); |
| 138463 | 138907 | sqlite3ParserAddCleanup(pToplevel, sqlite3DbFree, pInfo); |
| 138464 | 138908 | testcase( pParse->earlyCleanup ); |
| 138465 | 138909 | if( pParse->db->mallocFailed ) return 0; |
| 138466 | 138910 | pInfo->pNext = pToplevel->pAinc; |
| 138467 | 138911 | pToplevel->pAinc = pInfo; |
| 138912 | + pToplevel->usesAinc = 1; | |
| 138468 | 138913 | pInfo->pTab = pTab; |
| 138469 | 138914 | pInfo->iDb = iDb; |
| 138470 | 138915 | pToplevel->nMem++; /* Register to hold name of table */ |
| 138471 | 138916 | pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */ |
| 138472 | 138917 | pToplevel->nMem +=2; /* Rowid in sqlite_sequence + orig max val */ |
| @@ -138491,10 +138936,11 @@ | ||
| 138491 | 138936 | ** only called from the top-level */ |
| 138492 | 138937 | assert( pParse->pTriggerTab==0 ); |
| 138493 | 138938 | assert( sqlite3IsToplevel(pParse) ); |
| 138494 | 138939 | |
| 138495 | 138940 | assert( v ); /* We failed long ago if this is not so */ |
| 138941 | + assert( pParse->usesAinc ); | |
| 138496 | 138942 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 138497 | 138943 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 138498 | 138944 | static const VdbeOpList autoInc[] = { |
| 138499 | 138945 | /* 0 */ {OP_Null, 0, 0, 0}, |
| 138500 | 138946 | /* 1 */ {OP_Rewind, 0, 10, 0}, |
| @@ -138558,10 +139004,11 @@ | ||
| 138558 | 139004 | AutoincInfo *p; |
| 138559 | 139005 | Vdbe *v = pParse->pVdbe; |
| 138560 | 139006 | sqlite3 *db = pParse->db; |
| 138561 | 139007 | |
| 138562 | 139008 | assert( v ); |
| 139009 | + assert( pParse->usesAinc ); | |
| 138563 | 139010 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 138564 | 139011 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 138565 | 139012 | static const VdbeOpList autoIncEnd[] = { |
| 138566 | 139013 | /* 0 */ {OP_NotNull, 0, 2, 0}, |
| 138567 | 139014 | /* 1 */ {OP_NewRowid, 0, 0, 0}, |
| @@ -138590,11 +139037,11 @@ | ||
| 138590 | 139037 | aOp[3].p5 = OPFLAG_APPEND; |
| 138591 | 139038 | sqlite3ReleaseTempReg(pParse, iRec); |
| 138592 | 139039 | } |
| 138593 | 139040 | } |
| 138594 | 139041 | SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ |
| 138595 | - if( pParse->pAinc ) autoIncrementEnd(pParse); | |
| 139042 | + if( pParse->usesAinc ) autoIncrementEnd(pParse); | |
| 138596 | 139043 | } |
| 138597 | 139044 | #else |
| 138598 | 139045 | /* |
| 138599 | 139046 | ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines |
| 138600 | 139047 | ** above are all no-ops |
| @@ -140244,10 +140691,26 @@ | ||
| 140244 | 140691 | pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
| 140245 | 140692 | regTrigCnt = pTrigger!=0 || sqlite3FkRequired(pParse, pTab, 0, 0); |
| 140246 | 140693 | }else{ |
| 140247 | 140694 | pTrigger = 0; |
| 140248 | 140695 | regTrigCnt = sqlite3FkRequired(pParse, pTab, 0, 0); |
| 140696 | + } | |
| 140697 | + if( regTrigCnt ){ | |
| 140698 | + /* At this point regTrigCnt is non-zero if there are DELETE triggers | |
| 140699 | + ** or FK triggers. But we only care about these things if there is | |
| 140700 | + ** a chance that a row will be deleted by an ON CONFLICT REPLACE | |
| 140701 | + ** constraint. So zero regTrigCnt if no such constraint can be found. */ | |
| 140702 | + if( overrideError!=OE_Replace ){ | |
| 140703 | + if( overrideError!=OE_Default ){ | |
| 140704 | + regTrigCnt = 0; | |
| 140705 | + }else if( pkChng==0 || pPk || pTab->keyConf!=OE_Replace ){ | |
| 140706 | + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | |
| 140707 | + if( pIdx->onError==OE_Replace ) break; | |
| 140708 | + } | |
| 140709 | + if( pIdx==0 ) regTrigCnt = 0; | |
| 140710 | + } | |
| 140711 | + } | |
| 140249 | 140712 | } |
| 140250 | 140713 | if( regTrigCnt ){ |
| 140251 | 140714 | /* Replace triggers might exist. Allocate the counter and |
| 140252 | 140715 | ** initialize it to zero. */ |
| 140253 | 140716 | regTrigCnt = ++pParse->nMem; |
| @@ -140296,13 +140759,17 @@ | ||
| 140296 | 140759 | ** the UNIQUE constraints have run. |
| 140297 | 140760 | */ |
| 140298 | 140761 | if( onError==OE_Replace /* IPK rule is REPLACE */ |
| 140299 | 140762 | && onError!=overrideError /* Rules for other constraints are different */ |
| 140300 | 140763 | && pTab->pIndex /* There exist other constraints */ |
| 140301 | - && !upsertIpkDelay /* IPK check already deferred by UPSERT */ | |
| 140302 | 140764 | ){ |
| 140303 | - ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; | |
| 140765 | + if( upsertIpkDelay ){ | |
| 140766 | + ipkTop = upsertIpkDelay + 1; | |
| 140767 | + upsertIpkDelay = 0; | |
| 140768 | + }else{ | |
| 140769 | + ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; | |
| 140770 | + } | |
| 140304 | 140771 | VdbeComment((v, "defer IPK REPLACE until last")); |
| 140305 | 140772 | } |
| 140306 | 140773 | |
| 140307 | 140774 | if( isUpdate ){ |
| 140308 | 140775 | /* pkChng!=0 does not mean that the rowid has changed, only that |
| @@ -140392,15 +140859,15 @@ | ||
| 140392 | 140859 | sqlite3VdbeGoto(v, ignoreDest); |
| 140393 | 140860 | break; |
| 140394 | 140861 | } |
| 140395 | 140862 | } |
| 140396 | 140863 | sqlite3VdbeResolveLabel(v, addrRowidOk); |
| 140397 | - if( pUpsert && pUpsertClause!=pUpsert ){ | |
| 140398 | - upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto); | |
| 140399 | - }else if( ipkTop ){ | |
| 140864 | + if( ipkTop ){ | |
| 140400 | 140865 | ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto); |
| 140401 | 140866 | sqlite3VdbeJumpHere(v, ipkTop-1); |
| 140867 | + }else if( pUpsert && pUpsertClause!=pUpsert ){ | |
| 140868 | + upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto); | |
| 140402 | 140869 | } |
| 140403 | 140870 | } |
| 140404 | 140871 | |
| 140405 | 140872 | /* Test all UNIQUE constraints by creating entries for each UNIQUE |
| 140406 | 140873 | ** index and making sure that duplicate entries do not already exist. |
| @@ -140416,10 +140883,11 @@ | ||
| 140416 | 140883 | int regIdx; /* Range of registers holding content for pIdx */ |
| 140417 | 140884 | int regR; /* Range of registers holding conflicting PK */ |
| 140418 | 140885 | int iThisCur; /* Cursor for this UNIQUE index */ |
| 140419 | 140886 | int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ |
| 140420 | 140887 | int addrConflictCk; /* First opcode in the conflict check logic */ |
| 140888 | + int nConflictCk; /* Number of opcodes in conflict check logic */ | |
| 140421 | 140889 | |
| 140422 | 140890 | if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ |
| 140423 | 140891 | if( pUpsert ){ |
| 140424 | 140892 | pUpsertClause = sqlite3UpsertOfIndex(pUpsert, pIdx); |
| 140425 | 140893 | if( upsertIpkDelay && pUpsertClause==pUpsert ){ |
| @@ -140591,10 +141059,15 @@ | ||
| 140591 | 141059 | VdbeCoverageIf(v, op==OP_Ne); |
| 140592 | 141060 | } |
| 140593 | 141061 | } |
| 140594 | 141062 | } |
| 140595 | 141063 | } |
| 141064 | + | |
| 141065 | + nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk; | |
| 141066 | + assert( nConflictCk>0 || db->mallocFailed ); | |
| 141067 | + testcase( nConflictCk<=0 ); | |
| 141068 | + testcase( nConflictCk>1 ); | |
| 140596 | 141069 | |
| 140597 | 141070 | /* Generate code that executes if the new index entry is not unique */ |
| 140598 | 141071 | assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail |
| 140599 | 141072 | || onError==OE_Ignore || onError==OE_Replace || onError==OE_Update ); |
| 140600 | 141073 | switch( onError ){ |
| @@ -140617,17 +141090,11 @@ | ||
| 140617 | 141090 | testcase( onError==OE_Ignore ); |
| 140618 | 141091 | sqlite3VdbeGoto(v, ignoreDest); |
| 140619 | 141092 | break; |
| 140620 | 141093 | } |
| 140621 | 141094 | default: { |
| 140622 | - int nConflictCk; /* Number of opcodes in conflict check logic */ | |
| 140623 | - | |
| 140624 | 141095 | assert( onError==OE_Replace ); |
| 140625 | - nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk; | |
| 140626 | - assert( nConflictCk>0 || db->mallocFailed ); | |
| 140627 | - testcase( nConflictCk<=0 ); | |
| 140628 | - testcase( nConflictCk>1 ); | |
| 140629 | 141096 | if( regTrigCnt ){ |
| 140630 | 141097 | sqlite3MultiWrite(pParse); |
| 140631 | 141098 | nReplaceTrig++; |
| 140632 | 141099 | } |
| 140633 | 141100 | if( pTrigger && isUpdate ){ |
| @@ -140637,62 +141104,62 @@ | ||
| 140637 | 141104 | regR, nPkField, 0, OE_Replace, |
| 140638 | 141105 | (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); |
| 140639 | 141106 | if( pTrigger && isUpdate ){ |
| 140640 | 141107 | sqlite3VdbeAddOp1(v, OP_CursorUnlock, iDataCur); |
| 140641 | 141108 | } |
| 140642 | - if( regTrigCnt ){ | |
| 140643 | - int addrBypass; /* Jump destination to bypass recheck logic */ | |
| 140644 | - | |
| 140645 | - sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */ | |
| 140646 | - addrBypass = sqlite3VdbeAddOp0(v, OP_Goto); /* Bypass recheck */ | |
| 140647 | - VdbeComment((v, "bypass recheck")); | |
| 140648 | - | |
| 140649 | - /* Here we insert code that will be invoked after all constraint | |
| 140650 | - ** checks have run, if and only if one or more replace triggers | |
| 140651 | - ** fired. */ | |
| 140652 | - sqlite3VdbeResolveLabel(v, lblRecheckOk); | |
| 140653 | - lblRecheckOk = sqlite3VdbeMakeLabel(pParse); | |
| 140654 | - if( pIdx->pPartIdxWhere ){ | |
| 140655 | - /* Bypass the recheck if this partial index is not defined | |
| 140656 | - ** for the current row */ | |
| 140657 | - sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk); | |
| 140658 | - VdbeCoverage(v); | |
| 140659 | - } | |
| 140660 | - /* Copy the constraint check code from above, except change | |
| 140661 | - ** the constraint-ok jump destination to be the address of | |
| 140662 | - ** the next retest block */ | |
| 140663 | - while( nConflictCk>0 ){ | |
| 140664 | - VdbeOp x; /* Conflict check opcode to copy */ | |
| 140665 | - /* The sqlite3VdbeAddOp4() call might reallocate the opcode array. | |
| 140666 | - ** Hence, make a complete copy of the opcode, rather than using | |
| 140667 | - ** a pointer to the opcode. */ | |
| 140668 | - x = *sqlite3VdbeGetOp(v, addrConflictCk); | |
| 140669 | - if( x.opcode!=OP_IdxRowid ){ | |
| 140670 | - int p2; /* New P2 value for copied conflict check opcode */ | |
| 140671 | - const char *zP4; | |
| 140672 | - if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){ | |
| 140673 | - p2 = lblRecheckOk; | |
| 140674 | - }else{ | |
| 140675 | - p2 = x.p2; | |
| 140676 | - } | |
| 140677 | - zP4 = x.p4type==P4_INT32 ? SQLITE_INT_TO_PTR(x.p4.i) : x.p4.z; | |
| 140678 | - sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, zP4, x.p4type); | |
| 140679 | - sqlite3VdbeChangeP5(v, x.p5); | |
| 140680 | - VdbeCoverageIf(v, p2!=x.p2); | |
| 140681 | - } | |
| 140682 | - nConflictCk--; | |
| 140683 | - addrConflictCk++; | |
| 140684 | - } | |
| 140685 | - /* If the retest fails, issue an abort */ | |
| 140686 | - sqlite3UniqueConstraint(pParse, OE_Abort, pIdx); | |
| 140687 | - | |
| 140688 | - sqlite3VdbeJumpHere(v, addrBypass); /* Terminate the recheck bypass */ | |
| 140689 | - } | |
| 140690 | 141109 | seenReplace = 1; |
| 140691 | 141110 | break; |
| 140692 | 141111 | } |
| 140693 | 141112 | } |
| 141113 | + if( regTrigCnt ){ | |
| 141114 | + int addrBypass; /* Jump destination to bypass recheck logic */ | |
| 141115 | + | |
| 141116 | + sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */ | |
| 141117 | + addrBypass = sqlite3VdbeAddOp0(v, OP_Goto); /* Bypass recheck */ | |
| 141118 | + VdbeComment((v, "bypass recheck")); | |
| 141119 | + | |
| 141120 | + /* Here we insert code that will be invoked after all constraint | |
| 141121 | + ** checks have run, if and only if one or more replace triggers | |
| 141122 | + ** fired. */ | |
| 141123 | + sqlite3VdbeResolveLabel(v, lblRecheckOk); | |
| 141124 | + lblRecheckOk = sqlite3VdbeMakeLabel(pParse); | |
| 141125 | + if( pIdx->pPartIdxWhere ){ | |
| 141126 | + /* Bypass the recheck if this partial index is not defined | |
| 141127 | + ** for the current row */ | |
| 141128 | + sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk); | |
| 141129 | + VdbeCoverage(v); | |
| 141130 | + } | |
| 141131 | + /* Copy the constraint check code from above, except change | |
| 141132 | + ** the constraint-ok jump destination to be the address of | |
| 141133 | + ** the next retest block */ | |
| 141134 | + while( nConflictCk>0 ){ | |
| 141135 | + VdbeOp x; /* Conflict check opcode to copy */ | |
| 141136 | + /* The sqlite3VdbeAddOp4() call might reallocate the opcode array. | |
| 141137 | + ** Hence, make a complete copy of the opcode, rather than using | |
| 141138 | + ** a pointer to the opcode. */ | |
| 141139 | + x = *sqlite3VdbeGetOp(v, addrConflictCk); | |
| 141140 | + if( x.opcode!=OP_IdxRowid ){ | |
| 141141 | + int p2; /* New P2 value for copied conflict check opcode */ | |
| 141142 | + const char *zP4; | |
| 141143 | + if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){ | |
| 141144 | + p2 = lblRecheckOk; | |
| 141145 | + }else{ | |
| 141146 | + p2 = x.p2; | |
| 141147 | + } | |
| 141148 | + zP4 = x.p4type==P4_INT32 ? SQLITE_INT_TO_PTR(x.p4.i) : x.p4.z; | |
| 141149 | + sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, zP4, x.p4type); | |
| 141150 | + sqlite3VdbeChangeP5(v, x.p5); | |
| 141151 | + VdbeCoverageIf(v, p2!=x.p2); | |
| 141152 | + } | |
| 141153 | + nConflictCk--; | |
| 141154 | + addrConflictCk++; | |
| 141155 | + } | |
| 141156 | + /* If the retest fails, issue an abort */ | |
| 141157 | + sqlite3UniqueConstraint(pParse, OE_Abort, pIdx); | |
| 141158 | + | |
| 141159 | + sqlite3VdbeJumpHere(v, addrBypass); /* Terminate the recheck bypass */ | |
| 141160 | + } | |
| 140694 | 141161 | sqlite3VdbeResolveLabel(v, addrUniqueOk); |
| 140695 | 141162 | if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); |
| 140696 | 141163 | if( pUpsertClause |
| 140697 | 141164 | && upsertIpkReturn |
| 140698 | 141165 | && sqlite3UpsertNextIsIPK(pUpsertClause) |
| @@ -140726,12 +141193,12 @@ | ||
| 140726 | 141193 | VdbeCoverage(v); |
| 140727 | 141194 | sqlite3RowidConstraint(pParse, OE_Abort, pTab); |
| 140728 | 141195 | }else{ |
| 140729 | 141196 | sqlite3VdbeGoto(v, addrRecheck); |
| 140730 | 141197 | } |
| 140731 | - sqlite3VdbeResolveLabel(v, lblRecheckOk); | |
| 140732 | 141198 | } |
| 141199 | + if( regTrigCnt ) sqlite3VdbeResolveLabel(v, lblRecheckOk); | |
| 140733 | 141200 | |
| 140734 | 141201 | /* Generate the table record */ |
| 140735 | 141202 | if( HasRowid(pTab) ){ |
| 140736 | 141203 | int regRec = aRegIdx[ix]; |
| 140737 | 141204 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nNVCol, regRec); |
| @@ -142023,10 +142490,11 @@ | ||
| 142023 | 142490 | void (*str_free)(sqlite3_str*); |
| 142024 | 142491 | int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*)); |
| 142025 | 142492 | int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*); |
| 142026 | 142493 | /* Version 3.54.0 and later */ |
| 142027 | 142494 | sqlite3_int64 (*incomplete)(const char*); |
| 142495 | + void (*result_str)(sqlite3_context*,sqlite3_str*,int); | |
| 142028 | 142496 | }; |
| 142029 | 142497 | |
| 142030 | 142498 | /* |
| 142031 | 142499 | ** This is the function signature used for all extension entry points. It |
| 142032 | 142500 | ** is also defined in the file "loadext.c". |
| @@ -142368,10 +142836,11 @@ | ||
| 142368 | 142836 | #define sqlite3_str_free sqlite3_api->str_free |
| 142369 | 142837 | #define sqlite3_carray_bind sqlite3_api->carray_bind |
| 142370 | 142838 | #define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2 |
| 142371 | 142839 | /* Version 3.54.0 and later */ |
| 142372 | 142840 | #define sqlite3_incomplete sqlite3_api->incomplete |
| 142841 | +#define sqlite3_result_str sqlite3_api->result_str | |
| 142373 | 142842 | #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
| 142374 | 142843 | |
| 142375 | 142844 | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| 142376 | 142845 | /* This case when the file really is being compiled as a loadable |
| 142377 | 142846 | ** extension */ |
| @@ -142905,11 +143374,13 @@ | ||
| 142905 | 143374 | sqlite3_carray_bind_v2, |
| 142906 | 143375 | #else |
| 142907 | 143376 | 0, |
| 142908 | 143377 | 0, |
| 142909 | 143378 | #endif |
| 142910 | - sqlite3_incomplete | |
| 143379 | + /* Version 3.54.0 and later */ | |
| 143380 | + sqlite3_incomplete, | |
| 143381 | + sqlite3_result_str | |
| 142911 | 143382 | }; |
| 142912 | 143383 | |
| 142913 | 143384 | /* True if x is the directory separator character |
| 142914 | 143385 | */ |
| 142915 | 143386 | #if SQLITE_OS_WIN |
| @@ -147203,10 +147674,11 @@ | ||
| 147203 | 147674 | corruptSchema(pData, argv, 0); |
| 147204 | 147675 | return 1; |
| 147205 | 147676 | } |
| 147206 | 147677 | |
| 147207 | 147678 | assert( iDb>=0 && iDb<db->nDb ); |
| 147679 | + assert( db->aDb[iDb].pSchema!=0 ); | |
| 147208 | 147680 | if( argv[3]==0 ){ |
| 147209 | 147681 | corruptSchema(pData, argv, 0); |
| 147210 | 147682 | }else if( argv[4] |
| 147211 | 147683 | && 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]] |
| 147212 | 147684 | && 'r'==sqlite3UpperToLower[(unsigned char)argv[4][1]] ){ |
| @@ -147277,10 +147749,20 @@ | ||
| 147277 | 147749 | ){ |
| 147278 | 147750 | if( sqlite3Config.bExtraSchemaChecks ){ |
| 147279 | 147751 | corruptSchema(pData, argv, "invalid rootpage"); |
| 147280 | 147752 | } |
| 147281 | 147753 | } |
| 147754 | + } | |
| 147755 | + if( pData->pzErrMsg[0]==0 ){ | |
| 147756 | + Schema *pX = db->aDb[iDb].pSchema; | |
| 147757 | + if( pX->tblHash.count + pX->idxHash.count + pX->trigHash.count | |
| 147758 | + > (u32)db->aLimit[SQLITE_LIMIT_SCHEMA] | |
| 147759 | + ){ | |
| 147760 | + *pData->pzErrMsg = sqlite3MPrintf(db, "too many schema objects"); | |
| 147761 | + pData->rc = SQLITE_ERROR; | |
| 147762 | + return 1; | |
| 147763 | + } | |
| 147282 | 147764 | } |
| 147283 | 147765 | return 0; |
| 147284 | 147766 | } |
| 147285 | 147767 | |
| 147286 | 147768 | /* |
| @@ -147674,11 +148156,11 @@ | ||
| 147674 | 148156 | sqlite3 *db = pParse->db; |
| 147675 | 148157 | assert( db!=0 ); |
| 147676 | 148158 | assert( db->pParse==pParse ); |
| 147677 | 148159 | assert( pParse->nested==0 ); |
| 147678 | 148160 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 147679 | - if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock); | |
| 148161 | + if( pParse->nTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock); | |
| 147680 | 148162 | #endif |
| 147681 | 148163 | while( pParse->pCleanup ){ |
| 147682 | 148164 | ParseCleanup *pCleanup = pParse->pCleanup; |
| 147683 | 148165 | pParse->pCleanup = pCleanup->pNext; |
| 147684 | 148166 | pCleanup->xCleanup(db, pCleanup->pPtr); |
| @@ -147758,10 +148240,11 @@ | ||
| 147758 | 148240 | ** |
| 147759 | 148241 | ** Caution: Do not confuse this routine with sqlite3ParseObjectInit() which |
| 147760 | 148242 | ** is generated by Lemon. |
| 147761 | 148243 | */ |
| 147762 | 148244 | SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){ |
| 148245 | + assert( db!=0 ); | |
| 147763 | 148246 | memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ); |
| 147764 | 148247 | memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); |
| 147765 | 148248 | assert( db->pParse!=pParse ); |
| 147766 | 148249 | pParse->pOuterParse = db->pParse; |
| 147767 | 148250 | db->pParse = pParse; |
| @@ -148157,11 +148640,11 @@ | ||
| 148157 | 148640 | int nBytes, /* Length of zSql in bytes. */ |
| 148158 | 148641 | sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ |
| 148159 | 148642 | const void **pzTail /* OUT: End of parsed string */ |
| 148160 | 148643 | ){ |
| 148161 | 148644 | int rc; |
| 148162 | - rc = sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail); | |
| 148645 | + rc = sqlite3Prepare16(db,zSql,nBytes&~1,0,ppStmt,pzTail); | |
| 148163 | 148646 | assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ |
| 148164 | 148647 | return rc; |
| 148165 | 148648 | } |
| 148166 | 148649 | SQLITE_API int sqlite3_prepare16_v2( |
| 148167 | 148650 | sqlite3 *db, /* Database handle. */ |
| @@ -148169,11 +148652,11 @@ | ||
| 148169 | 148652 | int nBytes, /* Length of zSql in bytes. */ |
| 148170 | 148653 | sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ |
| 148171 | 148654 | const void **pzTail /* OUT: End of parsed string */ |
| 148172 | 148655 | ){ |
| 148173 | 148656 | int rc; |
| 148174 | - rc = sqlite3Prepare16(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,ppStmt,pzTail); | |
| 148657 | + rc = sqlite3Prepare16(db,zSql,nBytes&~1,SQLITE_PREPARE_SAVESQL,ppStmt,pzTail); | |
| 148175 | 148658 | assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ |
| 148176 | 148659 | return rc; |
| 148177 | 148660 | } |
| 148178 | 148661 | SQLITE_API int sqlite3_prepare16_v3( |
| 148179 | 148662 | sqlite3 *db, /* Database handle. */ |
| @@ -148182,11 +148665,11 @@ | ||
| 148182 | 148665 | unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ |
| 148183 | 148666 | sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ |
| 148184 | 148667 | const void **pzTail /* OUT: End of parsed string */ |
| 148185 | 148668 | ){ |
| 148186 | 148669 | int rc; |
| 148187 | - rc = sqlite3Prepare16(db,zSql,nBytes, | |
| 148670 | + rc = sqlite3Prepare16(db,zSql,nBytes&~1, | |
| 148188 | 148671 | SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK), |
| 148189 | 148672 | ppStmt,pzTail); |
| 148190 | 148673 | assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ |
| 148191 | 148674 | return rc; |
| 148192 | 148675 | } |
| @@ -148855,11 +149338,11 @@ | ||
| 148855 | 149338 | pRight->u3.pOn = 0; |
| 148856 | 149339 | pRight->fg.isOn = 1; |
| 148857 | 149340 | p->selFlags |= SF_OnToWhere; |
| 148858 | 149341 | } |
| 148859 | 149342 | |
| 148860 | - if( IsVirtual(pRightTab) && joinType==EP_OuterON && pRight->u1.pFuncArg ){ | |
| 149343 | + if( pRight->fg.isTabFunc && joinType==EP_OuterON && pRight->u1.pFuncArg ){ | |
| 148861 | 149344 | p->selFlags |= SF_OnToWhere; |
| 148862 | 149345 | } |
| 148863 | 149346 | } |
| 148864 | 149347 | return 0; |
| 148865 | 149348 | } |
| @@ -149321,10 +149804,52 @@ | ||
| 149321 | 149804 | } |
| 149322 | 149805 | pSort->nDefer = (u8)nDefer; |
| 149323 | 149806 | *ppExtra = pExtra; |
| 149324 | 149807 | } |
| 149325 | 149808 | #endif |
| 149809 | + | |
| 149810 | +#ifdef SQLITE_DEBUG | |
| 149811 | +/* | |
| 149812 | +** This is a byte-code validation check that only runs when SQLITE_DEBUG | |
| 149813 | +** is defined. This routine looks backwards through the bytecode | |
| 149814 | +** for the definition of cursor with index iCur. It extracts the KeyInfo from | |
| 149815 | +** that cursor (it must be an index cursor) and verifies that the cursor | |
| 149816 | +** does not use any collating seqeuences other than BINARY for its first | |
| 149817 | +** nCol columns. | |
| 149818 | +** | |
| 149819 | +** This routine is used inside of an assert(). So it should return true | |
| 149820 | +** on success and false if the invariant is not satisfied. | |
| 149821 | +** | |
| 149822 | +** tag-202607231411 | |
| 149823 | +*/ | |
| 149824 | +static int sqlite3CursorBloomable(Parse *pParse, int iCur, int nCol){ | |
| 149825 | + int i,k; | |
| 149826 | + Vdbe *v = pParse->pVdbe; | |
| 149827 | + if( pParse->nErr ) return 1; | |
| 149828 | + assert( v ); | |
| 149829 | + for(k=sqlite3VdbeCurrentAddr(v)-1; k>0; k--){ | |
| 149830 | + const VdbeOp *pOp = sqlite3VdbeGetOp(v, k); | |
| 149831 | + const KeyInfo *pKeyInfo; | |
| 149832 | + if( pOp->p1!=iCur ) continue; | |
| 149833 | + if( pOp->opcode!=OP_OpenRead | |
| 149834 | + && pOp->opcode!=OP_OpenWrite | |
| 149835 | + && pOp->opcode!=OP_OpenEphemeral | |
| 149836 | + ){ | |
| 149837 | + continue; | |
| 149838 | + } | |
| 149839 | + assert( pOp->p4type==P4_KEYINFO ); | |
| 149840 | + pKeyInfo = (const KeyInfo*)pOp->p4.pKeyInfo; | |
| 149841 | + assert( pKeyInfo!=0 ); | |
| 149842 | + for(i=0; i<nCol; i++){ | |
| 149843 | + assert( sqlite3IsBinary(pKeyInfo->aColl[i]) ); | |
| 149844 | + } | |
| 149845 | + return 1; | |
| 149846 | + } | |
| 149847 | + return 0; | |
| 149848 | +} | |
| 149849 | +#endif /* SQLITE_DEBUG */ | |
| 149850 | + | |
| 149326 | 149851 | |
| 149327 | 149852 | /* |
| 149328 | 149853 | ** This routine generates the code for the inside of the inner loop |
| 149329 | 149854 | ** of a SELECT. |
| 149330 | 149855 | ** |
| @@ -149592,10 +150117,11 @@ | ||
| 149592 | 150117 | assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); |
| 149593 | 150118 | sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, |
| 149594 | 150119 | r1, pDest->zAffSdst, nResultCol); |
| 149595 | 150120 | sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); |
| 149596 | 150121 | if( pDest->iSDParm2 ){ |
| 150122 | + assert( sqlite3CursorBloomable(pParse,iParm,nResultCol) ); | |
| 149597 | 150123 | sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0, |
| 149598 | 150124 | regResult, nResultCol); |
| 149599 | 150125 | ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER")); |
| 149600 | 150126 | } |
| 149601 | 150127 | sqlite3ReleaseTempReg(pParse, r1); |
| @@ -151401,10 +151927,11 @@ | ||
| 151401 | 151927 | sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, |
| 151402 | 151928 | r1, pDest->zAffSdst, pIn->nSdst); |
| 151403 | 151929 | sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, |
| 151404 | 151930 | pIn->iSdst, pIn->nSdst); |
| 151405 | 151931 | if( pDest->iSDParm2>0 ){ |
| 151932 | + assert( sqlite3CursorBloomable(pParse, pDest->iSDParm, pIn->nSdst) ); | |
| 151406 | 151933 | sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0, |
| 151407 | 151934 | pIn->iSdst, pIn->nSdst); |
| 151408 | 151935 | ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER")); |
| 151409 | 151936 | } |
| 151410 | 151937 | sqlite3ReleaseTempReg(pParse, r1); |
| @@ -155350,11 +155877,12 @@ | ||
| 155350 | 155877 | assert( ExprUseXList(pExpr) ); |
| 155351 | 155878 | if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */ |
| 155352 | 155879 | if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */ |
| 155353 | 155880 | if( ExprHasProperty(pExpr, EP_WinFunc) ) return 0;/* Not a window function */ |
| 155354 | 155881 | pFrom = p->pSrc->a; |
| 155355 | - if( pFrom->fg.isSubquery==0 ) return 0; /* FROM is a subquery */ | |
| 155882 | + if( pFrom->fg.isSubquery==0 ) return 0; /* FROM is a subquery */ | |
| 155883 | + if( (p->selFlags & SF_Correlated)!=0 ) return 0; /* Not a correlated subq */ | |
| 155356 | 155884 | pSub = pFrom->u4.pSubq->pSelect; |
| 155357 | 155885 | if( pSub->pPrior==0 ) return 0; /* Must be a compound */ |
| 155358 | 155886 | if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */ |
| 155359 | 155887 | do{ |
| 155360 | 155888 | if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */ |
| @@ -157581,12 +158109,13 @@ | ||
| 157581 | 158109 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 157582 | 158110 | if( !IN_RENAME_OBJECT ){ |
| 157583 | 158111 | if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ |
| 157584 | 158112 | if( !noErr ){ |
| 157585 | 158113 | sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); |
| 158114 | + }else if( db->init.busy ){ | |
| 158115 | + sqlite3ErrorMsg(pParse,""); /* Err msg generated by corruptSchema() */ | |
| 157586 | 158116 | }else{ |
| 157587 | - assert( !db->init.busy ); | |
| 157588 | 158117 | sqlite3CodeVerifySchema(pParse, iDb); |
| 157589 | 158118 | VVA_ONLY( pParse->ifNotExists = 1; ) |
| 157590 | 158119 | } |
| 157591 | 158120 | goto trigger_cleanup; |
| 157592 | 158121 | } |
| @@ -161225,10 +161754,11 @@ | ||
| 161225 | 161754 | SQLITE_API int sqlite3_drop_modules(sqlite3 *db, const char** azNames){ |
| 161226 | 161755 | HashElem *pThis, *pNext; |
| 161227 | 161756 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 161228 | 161757 | if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
| 161229 | 161758 | #endif |
| 161759 | + sqlite3_mutex_enter(db->mutex); | |
| 161230 | 161760 | for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){ |
| 161231 | 161761 | Module *pMod = (Module*)sqliteHashData(pThis); |
| 161232 | 161762 | pNext = sqliteHashNext(pThis); |
| 161233 | 161763 | if( azNames ){ |
| 161234 | 161764 | int ii; |
| @@ -161235,10 +161765,11 @@ | ||
| 161235 | 161765 | for(ii=0; azNames[ii]!=0 && strcmp(azNames[ii],pMod->zName)!=0; ii++){} |
| 161236 | 161766 | if( azNames[ii]!=0 ) continue; |
| 161237 | 161767 | } |
| 161238 | 161768 | createModule(db, pMod->zName, 0, 0, 0); |
| 161239 | 161769 | } |
| 161770 | + sqlite3_mutex_leave(db->mutex); | |
| 161240 | 161771 | return SQLITE_OK; |
| 161241 | 161772 | } |
| 161242 | 161773 | |
| 161243 | 161774 | /* |
| 161244 | 161775 | ** Decrement the reference count on a Module object. Destroy the |
| @@ -161803,10 +162334,12 @@ | ||
| 161803 | 162334 | char *zErr = 0; |
| 161804 | 162335 | rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); |
| 161805 | 162336 | if( rc!=SQLITE_OK ){ |
| 161806 | 162337 | sqlite3ErrorMsg(pParse, "%s", zErr); |
| 161807 | 162338 | pParse->rc = rc; |
| 162339 | + }else{ | |
| 162340 | + sqlite3MarkAllShadowTablesOf(db, pTab); | |
| 161808 | 162341 | } |
| 161809 | 162342 | sqlite3DbFree(db, zErr); |
| 161810 | 162343 | } |
| 161811 | 162344 | |
| 161812 | 162345 | return rc; |
| @@ -163082,14 +163615,11 @@ | ||
| 163082 | 163615 | SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); |
| 163083 | 163616 | SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*); |
| 163084 | 163617 | SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); |
| 163085 | 163618 | SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*); |
| 163086 | 163619 | SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); |
| 163087 | - | |
| 163088 | - | |
| 163089 | - | |
| 163090 | - | |
| 163620 | +SQLITE_PRIVATE int sqlite3WhereLoopBloomable(const WhereLoop*); | |
| 163091 | 163621 | |
| 163092 | 163622 | /* |
| 163093 | 163623 | ** Bitmasks for the operators on WhereTerm objects. These are all |
| 163094 | 163624 | ** operators that are of interest to the query planner. An |
| 163095 | 163625 | ** OR-ed combination of these values can be used when searching for |
| @@ -164554,10 +165084,11 @@ | ||
| 164554 | 165084 | testcase( pTerm->wtFlags & TERM_VIRTUAL ); |
| 164555 | 165085 | regRowid = sqlite3GetTempReg(pParse); |
| 164556 | 165086 | regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid); |
| 164557 | 165087 | sqlite3VdbeAddOp2(pParse->pVdbe, OP_MustBeInt, regRowid, addrNxt); |
| 164558 | 165088 | VdbeCoverage(pParse->pVdbe); |
| 165089 | + assert( sqlite3WhereLoopBloomable(pLoop) ); | |
| 164559 | 165090 | sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, |
| 164560 | 165091 | addrNxt, regRowid, 1); |
| 164561 | 165092 | VdbeCoverage(pParse->pVdbe); |
| 164562 | 165093 | }else{ |
| 164563 | 165094 | u16 nEq = pLoop->u.btree.nEq; |
| @@ -164567,10 +165098,11 @@ | ||
| 164567 | 165098 | assert( pLoop->wsFlags & WHERE_INDEXED ); |
| 164568 | 165099 | assert( (pLoop->wsFlags & WHERE_COLUMN_IN)==0 ); |
| 164569 | 165100 | r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff); |
| 164570 | 165101 | codeApplyAffinity(pParse, r1, nEq, zStartAff); |
| 164571 | 165102 | sqlite3DbFree(pParse->db, zStartAff); |
| 165103 | + assert( sqlite3WhereLoopBloomable(pLoop) ); | |
| 164572 | 165104 | sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, |
| 164573 | 165105 | addrNxt, r1, nEq); |
| 164574 | 165106 | VdbeCoverage(pParse->pVdbe); |
| 164575 | 165107 | } |
| 164576 | 165108 | pLevel->regFilter = 0; |
| @@ -165170,10 +165702,11 @@ | ||
| 165170 | 165702 | if( regBignull ){ |
| 165171 | 165703 | sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull); |
| 165172 | 165704 | VdbeComment((v, "NULL-scan pass ctr")); |
| 165173 | 165705 | } |
| 165174 | 165706 | if( pLevel->regFilter ){ |
| 165707 | + assert( sqlite3WhereLoopBloomable(pLoop) ); | |
| 165175 | 165708 | sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, |
| 165176 | 165709 | regBase, nEq); |
| 165177 | 165710 | VdbeCoverage(v); |
| 165178 | 165711 | filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); |
| 165179 | 165712 | } |
| @@ -165907,12 +166440,14 @@ | ||
| 165907 | 166440 | jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, 0, r+1, nPk); |
| 165908 | 166441 | VdbeCoverage(v); |
| 165909 | 166442 | VdbeComment((v, "match against %s", pTab->zName)); |
| 165910 | 166443 | sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r); |
| 165911 | 166444 | sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk); |
| 165912 | - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk); | |
| 165913 | - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); | |
| 166445 | + if( pRJ->regBloom ){ | |
| 166446 | + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk); | |
| 166447 | + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); | |
| 166448 | + } | |
| 165914 | 166449 | sqlite3VdbeJumpHere(v, jmp1); |
| 165915 | 166450 | sqlite3ReleaseTempRange(pParse, r, nPk+1); |
| 165916 | 166451 | } |
| 165917 | 166452 | |
| 165918 | 166453 | /* For a LEFT OUTER JOIN, generate code that will record the fact that |
| @@ -166060,11 +166595,11 @@ | ||
| 166060 | 166595 | WHERE_RIGHT_JOIN, 0); |
| 166061 | 166596 | if( pSubWInfo ){ |
| 166062 | 166597 | int iCur = pLevel->iTabCur; |
| 166063 | 166598 | int r = ++pParse->nMem; |
| 166064 | 166599 | int nPk; |
| 166065 | - int jmp; | |
| 166600 | + int jmp = 0; | |
| 166066 | 166601 | int addrCont = sqlite3WhereContinueLabel(pSubWInfo); |
| 166067 | 166602 | Table *pTab = pTabItem->pSTab; |
| 166068 | 166603 | if( HasRowid(pTab) ){ |
| 166069 | 166604 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r); |
| 166070 | 166605 | nPk = 1; |
| @@ -166076,15 +166611,17 @@ | ||
| 166076 | 166611 | for(iPk=0; iPk<nPk; iPk++){ |
| 166077 | 166612 | int iCol = pPk->aiColumn[iPk]; |
| 166078 | 166613 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk); |
| 166079 | 166614 | } |
| 166080 | 166615 | } |
| 166081 | - jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk); | |
| 166082 | - VdbeCoverage(v); | |
| 166616 | + if( pRJ->regBloom ){ | |
| 166617 | + jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk); | |
| 166618 | + VdbeCoverage(v); | |
| 166619 | + } | |
| 166083 | 166620 | sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk); |
| 166084 | 166621 | VdbeCoverage(v); |
| 166085 | - sqlite3VdbeJumpHere(v, jmp); | |
| 166622 | + if( jmp ) sqlite3VdbeJumpHere(v, jmp); | |
| 166086 | 166623 | sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn); |
| 166087 | 166624 | sqlite3WhereEnd(pSubWInfo); |
| 166088 | 166625 | } |
| 166089 | 166626 | sqlite3ExprDelete(pParse->db, pSubWhere); |
| 166090 | 166627 | ExplainQueryPlanPop(pParse); |
| @@ -167001,33 +167538,62 @@ | ||
| 167001 | 167538 | } |
| 167002 | 167539 | } |
| 167003 | 167540 | } |
| 167004 | 167541 | } |
| 167005 | 167542 | |
| 167006 | - /* At this point, okToChngToIN is true if original pTerm satisfies | |
| 167007 | - ** case 1. In that case, construct a new virtual term that is | |
| 167008 | - ** pTerm converted into an IN operator. | |
| 167543 | + /* At this point, okToChngToIN is true if original pTerm is a | |
| 167544 | + ** candidate to satisfy case 1, though we are not yet certain that | |
| 167545 | + ** the collating sequences are all compatible. Try to construct a | |
| 167546 | + ** new virtual term that is pTerm converted from an OR operator | |
| 167547 | + ** into an IN operator. | |
| 167548 | + ** | |
| 167549 | + ** During construction, verify that the collating sequences on all | |
| 167550 | + ** subterms of the OR are compatible. Omit the construction of the | |
| 167551 | + ** new IN operator if there are any collating sequence mismatches. | |
| 167009 | 167552 | */ |
| 167010 | 167553 | if( okToChngToIN ){ |
| 167011 | 167554 | Expr *pDup; /* A transient duplicate expression */ |
| 167012 | 167555 | ExprList *pList = 0; /* The RHS of the IN operator */ |
| 167013 | 167556 | Expr *pLeft = 0; /* The LHS of the IN operator */ |
| 167557 | + CollSeq *pCollSeq = 0; /* Collating sequence to use */ | |
| 167014 | 167558 | Expr *pNew; /* The complete IN operator */ |
| 167015 | 167559 | |
| 167016 | 167560 | for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ |
| 167561 | + Expr *pThis; | |
| 167017 | 167562 | if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue; |
| 167018 | 167563 | assert( pOrTerm->eOperator & WO_EQ ); |
| 167019 | 167564 | assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 ); |
| 167020 | 167565 | assert( pOrTerm->leftCursor==iCursor ); |
| 167021 | 167566 | assert( pOrTerm->u.x.leftColumn==iColumn ); |
| 167022 | - pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); | |
| 167567 | + pThis = pOrTerm->pExpr; | |
| 167568 | + pDup = sqlite3ExprDup(db, pThis->pRight, 0); | |
| 167023 | 167569 | pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup); |
| 167024 | - pLeft = pOrTerm->pExpr->pLeft; | |
| 167570 | + if( pLeft==0 ){ | |
| 167571 | + pLeft = pThis->pLeft; | |
| 167572 | + pCollSeq = sqlite3ExprCompareCollSeq(pParse, pThis); | |
| 167573 | + }else{ | |
| 167574 | + assert( 0==sqlite3ExprCompare(pParse, | |
| 167575 | + sqlite3ExprSkipCollate(pThis->pLeft), | |
| 167576 | + sqlite3ExprSkipCollate(pLeft), -1) ); | |
| 167577 | + if( pCollSeq!=sqlite3ExprCompareCollSeq(pParse, pThis) ){ | |
| 167578 | + pLeft = 0; /* Collating sequence mismatch */ | |
| 167579 | + break; | |
| 167580 | + } | |
| 167581 | + } | |
| 167025 | 167582 | } |
| 167026 | - assert( pLeft!=0 ); | |
| 167027 | - pDup = sqlite3ExprDup(db, pLeft, 0); | |
| 167028 | - pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0); | |
| 167583 | + if( pLeft==0 ){ | |
| 167584 | + pNew = 0; /* Collating sequence mismatch */ | |
| 167585 | + }else{ | |
| 167586 | + pDup = sqlite3ExprDup(db, pLeft, 0); | |
| 167587 | + if( sqlite3ExprCollSeq(pParse, pDup)!=pCollSeq | |
| 167588 | + && ALWAYS(pCollSeq!=0) | |
| 167589 | + ){ | |
| 167590 | + assert( pCollSeq->zName!=0 ); | |
| 167591 | + pDup = sqlite3ExprAddCollateString(pParse, pDup, pCollSeq->zName); | |
| 167592 | + } | |
| 167593 | + pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0); | |
| 167594 | + } | |
| 167029 | 167595 | if( pNew ){ |
| 167030 | 167596 | int idxNew; |
| 167031 | 167597 | transferJoinMarkings(pNew, pExpr); |
| 167032 | 167598 | assert( ExprUseXList(pNew) ); |
| 167033 | 167599 | pNew->x.pList = pList; |
| @@ -168006,10 +168572,14 @@ | ||
| 168006 | 168572 | Expr *pColRef; |
| 168007 | 168573 | Expr *pTerm; |
| 168008 | 168574 | if( pItem->fg.isTabFunc==0 ) return; |
| 168009 | 168575 | pTab = pItem->pSTab; |
| 168010 | 168576 | assert( pTab!=0 ); |
| 168577 | + if( !IsVirtual(pTab) ){ | |
| 168578 | + sqlite3ErrorMsg(pParse, "'%s' is not a function", pItem->zName); | |
| 168579 | + return; | |
| 168580 | + } | |
| 168011 | 168581 | pArgs = pItem->u1.pFuncArg; |
| 168012 | 168582 | if( pArgs==0 ) return; |
| 168013 | 168583 | for(j=k=0; j<pArgs->nExpr; j++){ |
| 168014 | 168584 | Expr *pRhs; |
| 168015 | 168585 | u32 joinType; |
| @@ -168039,10 +168609,20 @@ | ||
| 168039 | 168609 | } |
| 168040 | 168610 | sqlite3SetJoinExpr(pTerm, pItem->iCursor, joinType); |
| 168041 | 168611 | whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); |
| 168042 | 168612 | } |
| 168043 | 168613 | } |
| 168614 | + | |
| 168615 | +/* | |
| 168616 | +** Return true if the WhereLoop pLoop can be use a Bloom filter. | |
| 168617 | +** tag-202607231411 | |
| 168618 | +*/ | |
| 168619 | +SQLITE_PRIVATE int sqlite3WhereLoopBloomable(const WhereLoop *pLoop){ | |
| 168620 | + if( pLoop->wsFlags & WHERE_IPK ) return 1; | |
| 168621 | + if( NEVER((pLoop->wsFlags & WHERE_INDEXED)==0) ) return 0; | |
| 168622 | + return sqlite3IndexBloomable(pLoop->u.btree.pIndex, pLoop->u.btree.nEq); | |
| 168623 | +} | |
| 168044 | 168624 | |
| 168045 | 168625 | /************** End of whereexpr.c *******************************************/ |
| 168046 | 168626 | /************** Begin file where.c *******************************************/ |
| 168047 | 168627 | /* |
| 168048 | 168628 | ** 2001 September 15 |
| @@ -169051,11 +169631,11 @@ | ||
| 169051 | 169631 | WhereLoop *pLoop; /* The Loop object */ |
| 169052 | 169632 | char *zNotUsed; /* Extra space on the end of pIdx */ |
| 169053 | 169633 | Bitmask idxCols; /* Bitmap of columns used for indexing */ |
| 169054 | 169634 | Bitmask extraCols; /* Bitmap of additional columns */ |
| 169055 | 169635 | u8 sentWarning = 0; /* True if a warning has been issued */ |
| 169056 | - u8 useBloomFilter = 0; /* True to also add a Bloom filter */ | |
| 169636 | + u8 useBloomFilter = 1; /* True to also add a Bloom filter */ | |
| 169057 | 169637 | Expr *pPartial = 0; /* Partial Index Expression */ |
| 169058 | 169638 | int iContinue = 0; /* Jump here to skip excluded rows */ |
| 169059 | 169639 | SrcList *pTabList; /* The complete FROM clause */ |
| 169060 | 169640 | SrcItem *pSrc; /* The FROM clause term to get the next index */ |
| 169061 | 169641 | int addrCounter = 0; /* Address where integer counter is initialized */ |
| @@ -169178,22 +169758,17 @@ | ||
| 169178 | 169758 | Expr *pX = pTerm->pExpr; |
| 169179 | 169759 | idxCols |= cMask; |
| 169180 | 169760 | pIdx->aiColumn[n] = pTerm->u.x.leftColumn; |
| 169181 | 169761 | pColl = sqlite3ExprCompareCollSeq(pParse, pX); |
| 169182 | 169762 | assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */ |
| 169763 | + if( !sqlite3IsBinary(pColl) ){ | |
| 169764 | + /* Disallow the use of a Bloom filter if any non-BINARY collating | |
| 169765 | + ** sequence is involved. tag-202607231411 */ | |
| 169766 | + useBloomFilter = 0; | |
| 169767 | + } | |
| 169183 | 169768 | pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY; |
| 169184 | 169769 | n++; |
| 169185 | - if( ALWAYS(pX->pLeft!=0) | |
| 169186 | - && sqlite3ExprAffinity(pX->pLeft)!=SQLITE_AFF_TEXT | |
| 169187 | - ){ | |
| 169188 | - /* TUNING: only use a Bloom filter on an automatic index | |
| 169189 | - ** if one or more key columns has the ability to hold numeric | |
| 169190 | - ** values, since strings all have the same hash in the Bloom | |
| 169191 | - ** filter implementation and hence a Bloom filter on a text column | |
| 169192 | - ** is not usually helpful. */ | |
| 169193 | - useBloomFilter = 1; | |
| 169194 | - } | |
| 169195 | 169770 | } |
| 169196 | 169771 | } |
| 169197 | 169772 | } |
| 169198 | 169773 | assert( (u32)n==pLoop->u.btree.nEq ); |
| 169199 | 169774 | |
| @@ -169259,10 +169834,11 @@ | ||
| 169259 | 169834 | regRecord = sqlite3GetTempReg(pParse); |
| 169260 | 169835 | regBase = sqlite3GenerateIndexKey( |
| 169261 | 169836 | pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0 |
| 169262 | 169837 | ); |
| 169263 | 169838 | if( pLevel->regFilter ){ |
| 169839 | + assert( sqlite3WhereLoopBloomable(pLoop) ); | |
| 169264 | 169840 | sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, |
| 169265 | 169841 | regBase, pLoop->u.btree.nEq); |
| 169266 | 169842 | } |
| 169267 | 169843 | sqlite3VdbeScanStatusCounters(v, addrExp, addrExp, sqlite3VdbeCurrentAddr(v)); |
| 169268 | 169844 | sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); |
| @@ -169374,10 +169950,11 @@ | ||
| 169374 | 169950 | if( sz<10000 ){ |
| 169375 | 169951 | sz = 10000; |
| 169376 | 169952 | }else if( sz>10000000 ){ |
| 169377 | 169953 | sz = 10000000; |
| 169378 | 169954 | } |
| 169955 | + assert( sqlite3WhereLoopBloomable(pLoop) ); | |
| 169379 | 169956 | sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter); |
| 169380 | 169957 | |
| 169381 | 169958 | addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); |
| 169382 | 169959 | pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; |
| 169383 | 169960 | for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){ |
| @@ -169396,10 +169973,11 @@ | ||
| 169396 | 169973 | }else{ |
| 169397 | 169974 | Index *pIdx = pLoop->u.btree.pIndex; |
| 169398 | 169975 | int n = pLoop->u.btree.nEq; |
| 169399 | 169976 | int r1 = sqlite3GetTempRange(pParse, n); |
| 169400 | 169977 | int jj; |
| 169978 | + assert( pIdx!=0 ); | |
| 169401 | 169979 | for(jj=0; jj<n; jj++){ |
| 169402 | 169980 | assert( pIdx->pTable==pItem->pSTab ); |
| 169403 | 169981 | sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iCur, jj, r1+jj); |
| 169404 | 169982 | } |
| 169405 | 169983 | sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); |
| @@ -173052,11 +173630,11 @@ | ||
| 173052 | 173630 | } |
| 173053 | 173631 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 173054 | 173632 | if( IsVirtual(pItem->pSTab) ){ |
| 173055 | 173633 | SrcItem *p; |
| 173056 | 173634 | for(p=&pItem[1]; p<pEnd; p++){ |
| 173057 | - if( mUnusable || (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){ | |
| 173635 | + if( (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){ | |
| 173058 | 173636 | mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor); |
| 173059 | 173637 | } |
| 173060 | 173638 | } |
| 173061 | 173639 | rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable); |
| 173062 | 173640 | }else |
| @@ -174682,23 +175260,21 @@ | ||
| 174682 | 175260 | Table *pTab = pItem->pSTab; |
| 174683 | 175261 | if( (pTab->tabFlags & TF_HasStat1)==0 ) break; |
| 174684 | 175262 | pTab->tabFlags |= TF_MaybeReanalyze; |
| 174685 | 175263 | if( i>=1 |
| 174686 | 175264 | && (pLoop->wsFlags & reqFlags)==reqFlags |
| 174687 | - /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */ | |
| 174688 | - && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0) | |
| 175265 | + && sqlite3WhereLoopBloomable(pLoop) | |
| 175266 | + && nSearch > pTab->nRowLogEst | |
| 174689 | 175267 | ){ |
| 174690 | - if( nSearch > pTab->nRowLogEst ){ | |
| 174691 | - testcase( pItem->fg.jointype & JT_LEFT ); | |
| 174692 | - pLoop->wsFlags |= WHERE_BLOOMFILTER; | |
| 174693 | - pLoop->wsFlags &= ~WHERE_IDX_ONLY; | |
| 174694 | - WHERETRACE(0xffffffff, ( | |
| 174695 | - "-> use Bloom-filter on loop %c because there are ~%.1e " | |
| 174696 | - "lookups into %s which has only ~%.1e rows\n", | |
| 174697 | - pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName, | |
| 174698 | - (double)sqlite3LogEstToInt(pTab->nRowLogEst))); | |
| 174699 | - } | |
| 175268 | + testcase( pItem->fg.jointype & JT_LEFT ); | |
| 175269 | + pLoop->wsFlags |= WHERE_BLOOMFILTER; | |
| 175270 | + pLoop->wsFlags &= ~WHERE_IDX_ONLY; | |
| 175271 | + WHERETRACE(0xffffffff, ( | |
| 175272 | + "-> use Bloom-filter on loop %c because there are ~%.1e " | |
| 175273 | + "lookups into %s which has only ~%.1e rows\n", | |
| 175274 | + pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName, | |
| 175275 | + (double)sqlite3LogEstToInt(pTab->nRowLogEst))); | |
| 174700 | 175276 | } |
| 174701 | 175277 | nSearch += pLoop->nOut; |
| 174702 | 175278 | } |
| 174703 | 175279 | } |
| 174704 | 175280 | |
| @@ -175432,26 +176008,31 @@ | ||
| 175432 | 176008 | } |
| 175433 | 176009 | sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0, |
| 175434 | 176010 | (u8*)&colUsed, P4_INT64); |
| 175435 | 176011 | } |
| 175436 | 176012 | #endif /* SQLITE_ENABLE_COLUMN_USED_MASK */ |
| 176013 | +#ifdef SQLITE_ENABLE_CURSOR_HINTS | |
| 176014 | + if( HasRowid(pTab) ){ | |
| 176015 | + sqlite3VdbeAddOp3(v, OP_CursorHint, iIndexCur, 0, pTabItem->iCursor); | |
| 176016 | + } | |
| 176017 | +#endif | |
| 175437 | 176018 | } |
| 175438 | 176019 | } |
| 175439 | 176020 | if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb); |
| 175440 | 176021 | if( (pTabItem->fg.jointype & JT_RIGHT)!=0 |
| 175441 | 176022 | && (pLevel->pRJ = sqlite3WhereMalloc(pWInfo, sizeof(WhereRightJoin)))!=0 |
| 175442 | 176023 | ){ |
| 175443 | 176024 | WhereRightJoin *pRJ = pLevel->pRJ; |
| 176025 | + int bBloomable = 0; | |
| 175444 | 176026 | pRJ->iMatch = pParse->nTab++; |
| 175445 | - pRJ->regBloom = ++pParse->nMem; | |
| 175446 | - sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom); | |
| 175447 | 176027 | pRJ->regReturn = ++pParse->nMem; |
| 175448 | 176028 | sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn); |
| 175449 | 176029 | assert( pTab==pTabItem->pSTab ); |
| 175450 | 176030 | if( HasRowid(pTab) ){ |
| 175451 | 176031 | KeyInfo *pInfo; |
| 175452 | 176032 | sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1); |
| 176033 | + bBloomable = 1; | |
| 175453 | 176034 | pInfo = sqlite3KeyInfoAlloc(pParse->db, 1, 0); |
| 175454 | 176035 | if( pInfo ){ |
| 175455 | 176036 | pInfo->aColl[0] = 0; |
| 175456 | 176037 | pInfo->aSortFlags[0] = 0; |
| 175457 | 176038 | sqlite3VdbeAppendP4(v, pInfo, P4_KEYINFO); |
| @@ -175458,10 +176039,17 @@ | ||
| 175458 | 176039 | } |
| 175459 | 176040 | }else{ |
| 175460 | 176041 | Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 175461 | 176042 | sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, pPk->nKeyCol); |
| 175462 | 176043 | sqlite3VdbeSetP4KeyInfo(pParse, pPk); |
| 176044 | + bBloomable = sqlite3IndexBloomable(pPk,pPk->nKeyCol); | |
| 176045 | + } | |
| 176046 | + if( bBloomable ){ | |
| 176047 | + pRJ->regBloom = ++pParse->nMem; | |
| 176048 | + sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom); | |
| 176049 | + }else{ | |
| 176050 | + pRJ->regBloom = 0; | |
| 175463 | 176051 | } |
| 175464 | 176052 | pLoop->wsFlags &= ~WHERE_IDX_ONLY; |
| 175465 | 176053 | /* The nature of RIGHT JOIN processing is such that it messes up |
| 175466 | 176054 | ** the output order. So omit any ORDER BY/GROUP BY elimination |
| 175467 | 176055 | ** optimizations. We need to do an actual sort for RIGHT JOIN. */ |
| @@ -176155,11 +176743,11 @@ | ||
| 176155 | 176743 | case SQLITE_INTEGER: |
| 176156 | 176744 | iVal = sqlite3_value_int64(apArg[1]); |
| 176157 | 176745 | break; |
| 176158 | 176746 | case SQLITE_FLOAT: { |
| 176159 | 176747 | double fVal = sqlite3_value_double(apArg[1]); |
| 176160 | - if( ((i64)fVal)!=fVal ) goto error_out; | |
| 176748 | + if( sqlite3RealToI64(fVal)!=fVal ) goto error_out; | |
| 176161 | 176749 | iVal = (i64)fVal; |
| 176162 | 176750 | break; |
| 176163 | 176751 | } |
| 176164 | 176752 | default: |
| 176165 | 176753 | goto error_out; |
| @@ -186803,67 +187391,64 @@ | ||
| 186803 | 187391 | SQLITE_API char *sqlite3_data_directory = 0; |
| 186804 | 187392 | |
| 186805 | 187393 | /* |
| 186806 | 187394 | ** Initialize SQLite. |
| 186807 | 187395 | ** |
| 186808 | -** This routine must be called to initialize the memory allocation, | |
| 186809 | -** VFS, and mutex subsystems prior to doing any serious work with | |
| 186810 | -** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT | |
| 187396 | +** The sqlite3_initialize() routine must be called to initialize the | |
| 187397 | +** memory allocation, VFS, and mutex subsystems prior to doing any | |
| 187398 | +** serious work. As long as you do not compile with SQLITE_OMIT_AUTOINIT | |
| 186811 | 187399 | ** this routine will be called automatically by key routines such as |
| 186812 | 187400 | ** sqlite3_open(). |
| 186813 | 187401 | ** |
| 186814 | 187402 | ** This routine is a no-op except on its very first call for the process, |
| 186815 | -** or for the first call after a call to sqlite3_shutdown. | |
| 187403 | +** or for the first call after a call to sqlite3_shutdown. Most calls | |
| 187404 | +** to sqlite3_initialize() are, in fact, no-ops. For that reason, the | |
| 187405 | +** routine is broken into two pieces: | |
| 186816 | 187406 | ** |
| 186817 | -** The first thread to call this routine runs the initialization to | |
| 186818 | -** completion. If subsequent threads call this routine before the first | |
| 187407 | +** sqlite3Initialize() Does the actual work of initialization | |
| 187408 | +** | |
| 187409 | +** sqlite3_initialize() Checks to see if initialization is needed | |
| 187410 | +** and invokes sqlite3Initialize() if it is. | |
| 187411 | +** | |
| 187412 | +** The sqlite3_initialize() interface is called frequently, but | |
| 187413 | +** sqlite3Initialize() runs rarely. The function is broken up this way | |
| 187414 | +** to avoid wasting CPU cycles with unnecessary stack setup for local | |
| 187415 | +** variables in cases where it is not needed. | |
| 187416 | +** | |
| 187417 | +** The first thread to call sqlite3_initialize() runs the initialization to | |
| 187418 | +** completion. If subsequent threads call sqlite3_initialize() before the first | |
| 186819 | 187419 | ** thread has finished the initialization process, then the subsequent |
| 186820 | 187420 | ** threads must block until the first thread finishes with the initialization. |
| 186821 | 187421 | ** |
| 186822 | 187422 | ** The first thread might call this routine recursively. Recursive |
| 186823 | 187423 | ** calls to this routine should not block, of course. Otherwise the |
| 186824 | 187424 | ** initialization process would never complete. |
| 186825 | 187425 | ** |
| 186826 | -** Let X be the first thread to enter this routine. Let Y be some other | |
| 186827 | -** thread. Then while the initial invocation of this routine by X is | |
| 186828 | -** incomplete, it is required that: | |
| 187426 | +** Let X be the first thread to enter sqlite3_initialize(). Let Y be some | |
| 187427 | +** other thread. While the initial invocation of sqlite3_initialize() by X | |
| 187428 | +** is incomplete, it is required that: | |
| 186829 | 187429 | ** |
| 186830 | -** * Calls to this routine from Y must block until the outer-most | |
| 187430 | +** * Calls to sqlite3_initialize() from Y must block until the outer-most | |
| 186831 | 187431 | ** call by X completes. |
| 186832 | 187432 | ** |
| 186833 | -** * Recursive calls to this routine from thread X return immediately | |
| 186834 | -** without blocking. | |
| 187433 | +** * Recursive calls to sqlite3_initialize() from thread X return | |
| 187434 | +** immediately without blocking. | |
| 186835 | 187435 | */ |
| 186836 | -SQLITE_API int sqlite3_initialize(void){ | |
| 186837 | - MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */ | |
| 186838 | - int rc; /* Result code */ | |
| 187436 | +static SQLITE_NOINLINE int sqlite3Initialize(void){ | |
| 187437 | + MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */ | |
| 187438 | + int rc; /* Result code */ | |
| 186839 | 187439 | #ifdef SQLITE_EXTRA_INIT |
| 186840 | - int bRunExtraInit = 0; /* Extra initialization needed */ | |
| 186841 | -#endif | |
| 186842 | - | |
| 186843 | -#ifdef SQLITE_OMIT_WSD | |
| 186844 | - rc = sqlite3_wsd_init(4096, 24); | |
| 186845 | - if( rc!=SQLITE_OK ){ | |
| 186846 | - return rc; | |
| 186847 | - } | |
| 187440 | + int bRunExtraInit = 0; /* Extra initialization needed */ | |
| 186848 | 187441 | #endif |
| 186849 | 187442 | |
| 186850 | 187443 | /* If the following assert() fails on some obscure processor/compiler |
| 186851 | - ** combination, the work-around is to set the correct pointer | |
| 186852 | - ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */ | |
| 187444 | + ** combination to warn that SQLite has been mis-compiled. If you hit | |
| 187445 | + ** this assert(), that means you need to recompile with the | |
| 187446 | + ** -DSQLITE_PTRSIZE=n compile-time option to set the correct pointer size. | |
| 187447 | + */ | |
| 186853 | 187448 | assert( SQLITE_PTRSIZE==sizeof(char*) ); |
| 186854 | 187449 | |
| 186855 | - /* If SQLite is already completely initialized, then this call | |
| 186856 | - ** to sqlite3_initialize() should be a no-op. But the initialization | |
| 186857 | - ** must be complete. So isInit must not be set until the very end | |
| 186858 | - ** of this routine. | |
| 186859 | - */ | |
| 186860 | - if( sqlite3GlobalConfig.isInit ){ | |
| 186861 | - sqlite3MemoryBarrier(); | |
| 186862 | - return SQLITE_OK; | |
| 186863 | - } | |
| 186864 | - | |
| 186865 | 187450 | /* Make sure the mutex subsystem is initialized. If unable to |
| 186866 | 187451 | ** initialize the mutex subsystem, return early with the error. |
| 186867 | 187452 | ** If the system is so sick that we are unable to allocate a mutex, |
| 186868 | 187453 | ** there is not much SQLite is going to be able to do. |
| 186869 | 187454 | ** |
| @@ -187003,10 +187588,30 @@ | ||
| 187003 | 187588 | int SQLITE_EXTRA_INIT(const char*); |
| 187004 | 187589 | rc = SQLITE_EXTRA_INIT(0); |
| 187005 | 187590 | } |
| 187006 | 187591 | #endif |
| 187007 | 187592 | return rc; |
| 187593 | +} | |
| 187594 | +SQLITE_API int sqlite3_initialize(void){ | |
| 187595 | + /* If this build does not support writable static data (WSD) natively | |
| 187596 | + ** then we have to invoke the (application-supplied) WSD initialization | |
| 187597 | + ** routine before doing anything else. */ | |
| 187598 | +#ifdef SQLITE_OMIT_WSD | |
| 187599 | + rc = sqlite3_wsd_init(4096, 24); | |
| 187600 | + if( rc!=SQLITE_OK ){ | |
| 187601 | + return rc; | |
| 187602 | + } | |
| 187603 | +#endif | |
| 187604 | + | |
| 187605 | + if( sqlite3GlobalConfig.isInit ){ | |
| 187606 | + /* SQLite has already been initialized. Fast early-out. */ | |
| 187607 | + sqlite3MemoryBarrier(); | |
| 187608 | + return SQLITE_OK; | |
| 187609 | + }else{ | |
| 187610 | + /* Invoke sqlite3Initialize() to do the actual work. */ | |
| 187611 | + return sqlite3Initialize(); | |
| 187612 | + } | |
| 187008 | 187613 | } |
| 187009 | 187614 | |
| 187010 | 187615 | /* |
| 187011 | 187616 | ** Undo the effects of sqlite3_initialize(). Must not be called while |
| 187012 | 187617 | ** there are outstanding database connections or memory allocations or |
| @@ -187755,17 +188360,21 @@ | ||
| 187755 | 188360 | |
| 187756 | 188361 | /* |
| 187757 | 188362 | ** Return the ROWID of the most recent insert |
| 187758 | 188363 | */ |
| 187759 | 188364 | SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){ |
| 188365 | + i64 iRet; | |
| 187760 | 188366 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 187761 | 188367 | if( !sqlite3SafetyCheckOk(db) ){ |
| 187762 | 188368 | (void)SQLITE_MISUSE_BKPT; |
| 187763 | 188369 | return 0; |
| 187764 | 188370 | } |
| 187765 | 188371 | #endif |
| 187766 | - return db->lastRowid; | |
| 188372 | + sqlite3_mutex_enter(db->mutex); | |
| 188373 | + iRet = db->lastRowid; | |
| 188374 | + sqlite3_mutex_leave(db->mutex); | |
| 188375 | + return iRet; | |
| 187767 | 188376 | } |
| 187768 | 188377 | |
| 187769 | 188378 | /* |
| 187770 | 188379 | ** Set the value returned by the sqlite3_last_insert_rowid() API function. |
| 187771 | 188380 | */ |
| @@ -187784,33 +188393,41 @@ | ||
| 187784 | 188393 | /* |
| 187785 | 188394 | ** Return the number of changes in the most recently executed DML |
| 187786 | 188395 | ** statement. |
| 187787 | 188396 | */ |
| 187788 | 188397 | SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){ |
| 188398 | + i64 iRet; | |
| 187789 | 188399 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 187790 | 188400 | if( !sqlite3SafetyCheckOk(db) ){ |
| 187791 | 188401 | (void)SQLITE_MISUSE_BKPT; |
| 187792 | 188402 | return 0; |
| 187793 | 188403 | } |
| 187794 | 188404 | #endif |
| 187795 | - return db->nChange; | |
| 188405 | + sqlite3_mutex_enter(db->mutex); | |
| 188406 | + iRet = db->nChange; | |
| 188407 | + sqlite3_mutex_leave(db->mutex); | |
| 188408 | + return iRet; | |
| 187796 | 188409 | } |
| 187797 | 188410 | SQLITE_API int sqlite3_changes(sqlite3 *db){ |
| 187798 | 188411 | return (int)sqlite3_changes64(db); |
| 187799 | 188412 | } |
| 187800 | 188413 | |
| 187801 | 188414 | /* |
| 187802 | 188415 | ** Return the number of changes since the database handle was opened. |
| 187803 | 188416 | */ |
| 187804 | 188417 | SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){ |
| 188418 | + i64 iRet; | |
| 187805 | 188419 |