Fossil SCM
Latest merge from trunk.
Commit
d03791648f6bc0237d8a7464c213899b7632c5e89d812d04665f096075372b99
Parent
6759efcc813e66c…
108 files changed
+1027
-523
+1112
-736
+133
-35
+23
+2
-2
+1
-1
+7
-7
+18
-5
+1
-1
+1
-1
+18
-7
+7
-7
+1
-1
+2
-2
+3
-3
+7
-7
+1
-1
+32
-9
+19
-21
+1
-1
+1
-1
+1
-1
+1
-1
+8
-8
+9
-9
+19
-1
+3
-3
+1
-1
+22
-2
+5
-5
+115
-73
+1
-1
+4
-3
+2
-2
+3
-3
+1
-1
+1
-1
+4
-4
+1
-1
+1
-1
+3
-3
+1
-1
+1
-1
+1
-1
+2
-2
+1
-1
+2
-2
+1
-1
+1
-1
+1
-1
+33
-14
+7
+21
-100
+4
-4
+1
-1
+1
-1
+15
-9
+16
-8
+3
-4
+4
-4
+42
-1
+1
-1
+3
-3
+2
-2
+17
-5
+1
-1
+7
-7
+3
-3
+1
-1
+1
-1
+3
-1
+3
-3
+2
-2
+2
-2
+1
-1
+1
-1
+1
-1
+1
-1
+1
-1
+16
-12
+1
-1
+10
-5
+17
-5
+1
-1
+3
-3
+1
-1
+1
-1
+5
-5
+19
-18
+7
-7
+1
-1
+2
-2
+1
-1
+3
-3
+8
-5
+1
-1
+1
-1
+5
-5
+1
-1
+18
-6
+81
-3
+3
-3
+1
-1
+61
-23
+1
-1
+4
+18
-3
+1
-1
~
extsrc/shell.c
~
extsrc/sqlite3.c
~
extsrc/sqlite3.h
~
src/accordion.js
~
src/add.c
~
src/ajax.c
~
src/alerts.c
~
src/allrepo.c
~
src/backlink.c
~
src/bisect.c
~
src/blob.c
~
src/branch.c
~
src/builtin.c
~
src/cache.c
~
src/captcha.c
~
src/cgi.c
~
src/chat.c
~
src/checkin.c
~
src/checkout.c
~
src/color.c
~
src/comformat.c
~
src/config.h
~
src/configure.c
~
src/content.c
~
src/db.c
~
src/default.css
~
src/delta.c
~
src/descendants.c
~
src/diff.c
~
src/diffcmd.c
~
src/dispatch.c
~
src/event.c
~
src/export.c
~
src/file.c
~
src/fileedit.c
~
src/forum.c
~
src/fossil.confirmer.js
~
src/fossil.diff.js
~
src/fossil.dom.js
~
src/fossil.fetch.js
~
src/fossil.page.chat.js
~
src/fossil.page.fileedit.js
~
src/fossil.page.wikiedit.js
~
src/fossil.pikchr.js
~
src/fossil.wikiedit-wysiwyg.js
~
src/fshell.c
~
src/glob.c
~
src/graph.c
~
src/hname.c
~
src/hook.c
~
src/http.c
~
src/http_socket.c
~
src/http_ssl.c
~
src/json.c
~
src/json_report.c
~
src/json_status.c
~
src/login.c
~
src/main.c
~
src/manifest.c
~
src/markdown.c
~
src/markdown_html.c
~
src/match.c
~
src/merge.c
~
src/merge3.c
~
src/name.c
~
src/piechart.c
~
src/printf.c
~
src/purge.c
~
src/regexp.c
~
src/report.c
~
src/robot.c
~
src/schema.c
~
src/search.c
~
src/security_audit.c
~
src/setup.c
~
src/setupuser.c
~
src/sha1.c
~
src/skins.c
~
src/smtp.c
~
src/sqlcmd.c
~
src/stat.c
~
src/style.c
~
src/sync.c
~
src/tag.c
~
src/tar.c
~
src/terminal.c
~
src/th.c
~
src/th_main.c
~
src/timeline.c
~
src/tkt.c
~
src/tktsetup.c
~
src/undo.c
~
src/unicode.c
~
src/update.c
~
src/util.c
~
src/vfile.c
~
src/wiki.c
~
src/wikiformat.c
~
src/winhttp.c
~
src/xfer.c
~
src/xsystem.c
~
src/zip.c
~
tools/codecheck1.c
~
tools/mkindex.c
~
www/antibot.wiki
~
www/changes.wiki
~
www/customskin.md
~
www/serverext.wiki
+1027
-523
| --- extsrc/shell.c | ||
| +++ extsrc/shell.c | ||
| @@ -35,11 +35,11 @@ | ||
| 35 | 35 | ** ext/recover/sqlite3recover.h |
| 36 | 36 | ** src/shell.c.in |
| 37 | 37 | ** |
| 38 | 38 | ** To modify this program, get a copy of the canonical SQLite source tree, |
| 39 | 39 | ** edit the src/shell.c.in file and/or some of the other files that are |
| 40 | -** listed above, then rerun the rerun "make shell.c". | |
| 40 | +** listed above, then rerun the command "make shell.c". | |
| 41 | 41 | */ |
| 42 | 42 | /************************* Begin src/shell.c.in ******************/ |
| 43 | 43 | /* |
| 44 | 44 | ** 2001 September 15 |
| 45 | 45 | ** |
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | ** May you do good and not evil. |
| 50 | 50 | ** May you find forgiveness for yourself and forgive others. |
| 51 | 51 | ** May you share freely, never taking more than you give. |
| 52 | 52 | ** |
| 53 | 53 | ************************************************************************* |
| 54 | -** This file contains code to implement the "sqlite" command line | |
| 54 | +** This file contains code to implement the "sqlite3" command line | |
| 55 | 55 | ** utility for accessing SQLite databases. |
| 56 | 56 | */ |
| 57 | 57 | #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) |
| 58 | 58 | /* This needs to come before any includes for MSVC compiler */ |
| 59 | 59 | #define _CRT_SECURE_NO_WARNINGS |
| @@ -79,10 +79,14 @@ | ||
| 79 | 79 | ** should only be used when building the "fiddle" web application, as |
| 80 | 80 | ** the browser-mode build has much different user input requirements |
| 81 | 81 | ** and this build mode rewires the user input subsystem to account for |
| 82 | 82 | ** that. |
| 83 | 83 | */ |
| 84 | +#if defined(SQLITE_SHELL_FIDDLE) | |
| 85 | +# undef SQLITE_OMIT_LOAD_EXTENSION | |
| 86 | +# define SQLITE_OMIT_LOAD_EXTENSION 1 | |
| 87 | +#endif | |
| 84 | 88 | |
| 85 | 89 | /* |
| 86 | 90 | ** Warning pragmas copied from msvc.h in the core. |
| 87 | 91 | */ |
| 88 | 92 | #if defined(_MSC_VER) |
| @@ -872,10 +876,11 @@ | ||
| 872 | 876 | #ifndef SQLITE_QRF_H |
| 873 | 877 | #include "qrf.h" |
| 874 | 878 | #endif |
| 875 | 879 | #include <string.h> |
| 876 | 880 | #include <assert.h> |
| 881 | +#include <stdint.h> | |
| 877 | 882 | |
| 878 | 883 | /* typedef sqlite3_int64 i64; */ |
| 879 | 884 | |
| 880 | 885 | /* A single line in the EQP output */ |
| 881 | 886 | typedef struct qrfEQPGraphRow qrfEQPGraphRow; |
| @@ -889,11 +894,12 @@ | ||
| 889 | 894 | /* All EQP output is collected into an instance of the following */ |
| 890 | 895 | typedef struct qrfEQPGraph qrfEQPGraph; |
| 891 | 896 | struct qrfEQPGraph { |
| 892 | 897 | qrfEQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ |
| 893 | 898 | qrfEQPGraphRow *pLast; /* Last element of the pRow list */ |
| 894 | - char zPrefix[100]; /* Graph prefix */ | |
| 899 | + int nWidth; /* Width of the graph */ | |
| 900 | + char zPrefix[400]; /* Graph prefix */ | |
| 895 | 901 | }; |
| 896 | 902 | |
| 897 | 903 | /* |
| 898 | 904 | ** Private state information. Subject to change from one release to the |
| 899 | 905 | ** next. |
| @@ -995,10 +1001,19 @@ | ||
| 995 | 1001 | */ |
| 996 | 1002 | static void qrfOom(Qrf *p){ |
| 997 | 1003 | qrfError(p, SQLITE_NOMEM, "out of memory"); |
| 998 | 1004 | } |
| 999 | 1005 | |
| 1006 | +/* | |
| 1007 | +** Transfer any error in pStr over into p. | |
| 1008 | +*/ | |
| 1009 | +static void qrfStrErr(Qrf *p, sqlite3_str *pStr){ | |
| 1010 | + int rc = pStr ? sqlite3_str_errcode(pStr) : 0; | |
| 1011 | + if( rc ){ | |
| 1012 | + qrfError(p, rc, sqlite3_errstr(rc)); | |
| 1013 | + } | |
| 1014 | +} | |
| 1000 | 1015 | |
| 1001 | 1016 | |
| 1002 | 1017 | /* |
| 1003 | 1018 | ** Add a new entry to the EXPLAIN QUERY PLAN data |
| 1004 | 1019 | */ |
| @@ -1074,10 +1089,49 @@ | ||
| 1074 | 1089 | qrfEqpRenderLevel(p, pRow->iEqpId); |
| 1075 | 1090 | p->u.pGraph->zPrefix[n] = 0; |
| 1076 | 1091 | } |
| 1077 | 1092 | } |
| 1078 | 1093 | } |
| 1094 | + | |
| 1095 | +/* | |
| 1096 | +** Render the 64-bit value N in a more human-readable format into | |
| 1097 | +** pOut. | |
| 1098 | +** | |
| 1099 | +** + Only show the first three significant digits. | |
| 1100 | +** + Append suffixes K, M, G, T, P, and E for 1e3, 1e6, ... 1e18 | |
| 1101 | +*/ | |
| 1102 | +static void qrfApproxInt64(sqlite3_str *pOut, i64 N){ | |
| 1103 | + static const char aSuffix[] = { 'K', 'M', 'G', 'T', 'P', 'E' }; | |
| 1104 | + int i; | |
| 1105 | + if( N<0 ){ | |
| 1106 | + N = N==INT64_MIN ? INT64_MAX : -N; | |
| 1107 | + sqlite3_str_append(pOut, "-", 1); | |
| 1108 | + } | |
| 1109 | + if( N<10000 ){ | |
| 1110 | + sqlite3_str_appendf(pOut, "%4lld ", N); | |
| 1111 | + return; | |
| 1112 | + } | |
| 1113 | + for(i=1; i<=18; i++){ | |
| 1114 | + N = (N+5)/10; | |
| 1115 | + if( N<10000 ){ | |
| 1116 | + int n = (int)N; | |
| 1117 | + switch( i%3 ){ | |
| 1118 | + case 0: | |
| 1119 | + sqlite3_str_appendf(pOut, "%d.%02d", n/1000, (n%1000)/10); | |
| 1120 | + break; | |
| 1121 | + case 1: | |
| 1122 | + sqlite3_str_appendf(pOut, "%2d.%d", n/100, (n%100)/10); | |
| 1123 | + break; | |
| 1124 | + case 2: | |
| 1125 | + sqlite3_str_appendf(pOut, "%4d", n/10); | |
| 1126 | + break; | |
| 1127 | + } | |
| 1128 | + sqlite3_str_append(pOut, &aSuffix[i/3], 1); | |
| 1129 | + break; | |
| 1130 | + } | |
| 1131 | + } | |
| 1132 | +} | |
| 1079 | 1133 | |
| 1080 | 1134 | /* |
| 1081 | 1135 | ** Display and reset the EXPLAIN QUERY PLAN data |
| 1082 | 1136 | */ |
| 1083 | 1137 | static void qrfEqpRender(Qrf *p, i64 nCycle){ |
| @@ -1090,11 +1144,30 @@ | ||
| 1090 | 1144 | } |
| 1091 | 1145 | sqlite3_str_appendf(p->pOut, "%s\n", pRow->zText+3); |
| 1092 | 1146 | p->u.pGraph->pRow = pRow->pNext; |
| 1093 | 1147 | sqlite3_free(pRow); |
| 1094 | 1148 | }else if( nCycle>0 ){ |
| 1095 | - sqlite3_str_appendf(p->pOut, "QUERY PLAN (cycles=%lld [100%%])\n",nCycle); | |
| 1149 | + int nSp = p->u.pGraph->nWidth - 2; | |
| 1150 | + if( p->spec.eStyle==QRF_STYLE_StatsEst ){ | |
| 1151 | + sqlite3_str_appendchar(p->pOut, nSp, ' '); | |
| 1152 | + sqlite3_str_appendall(p->pOut, | |
| 1153 | + "Cycles Loops (est) Rows (est)\n"); | |
| 1154 | + sqlite3_str_appendchar(p->pOut, nSp, ' '); | |
| 1155 | + sqlite3_str_appendall(p->pOut, | |
| 1156 | + "---------- ------------ ------------\n"); | |
| 1157 | + }else{ | |
| 1158 | + sqlite3_str_appendchar(p->pOut, nSp, ' '); | |
| 1159 | + sqlite3_str_appendall(p->pOut, | |
| 1160 | + "Cycles Loops Rows \n"); | |
| 1161 | + sqlite3_str_appendchar(p->pOut, nSp, ' '); | |
| 1162 | + sqlite3_str_appendall(p->pOut, | |
| 1163 | + "---------- ----- -----\n"); | |
| 1164 | + } | |
| 1165 | + sqlite3_str_appendall(p->pOut, "QUERY PLAN"); | |
| 1166 | + sqlite3_str_appendchar(p->pOut, nSp - 10, ' '); | |
| 1167 | + qrfApproxInt64(p->pOut, nCycle); | |
| 1168 | + sqlite3_str_appendall(p->pOut, " 100%\n"); | |
| 1096 | 1169 | }else{ |
| 1097 | 1170 | sqlite3_str_appendall(p->pOut, "QUERY PLAN\n"); |
| 1098 | 1171 | } |
| 1099 | 1172 | p->u.pGraph->zPrefix[0] = 0; |
| 1100 | 1173 | qrfEqpRenderLevel(p, 0); |
| @@ -1145,10 +1218,12 @@ | ||
| 1145 | 1218 | static const int f = SQLITE_SCANSTAT_COMPLEX; |
| 1146 | 1219 | sqlite3_stmt *pS = p->pStmt; |
| 1147 | 1220 | int i = 0; |
| 1148 | 1221 | i64 nTotal = 0; |
| 1149 | 1222 | int nWidth = 0; |
| 1223 | + int prevPid = -1; /* Previous iPid */ | |
| 1224 | + double rEstCum = 1.0; /* Cumulative row estimate */ | |
| 1150 | 1225 | sqlite3_str *pLine = sqlite3_str_new(p->db); |
| 1151 | 1226 | sqlite3_str *pStats = sqlite3_str_new(p->db); |
| 1152 | 1227 | qrfEqpReset(p); |
| 1153 | 1228 | |
| 1154 | 1229 | for(i=0; 1; i++){ |
| @@ -1158,11 +1233,11 @@ | ||
| 1158 | 1233 | break; |
| 1159 | 1234 | } |
| 1160 | 1235 | n = (int)strlen(z) + qrfStatsHeight(pS,i)*3; |
| 1161 | 1236 | if( n>nWidth ) nWidth = n; |
| 1162 | 1237 | } |
| 1163 | - nWidth += 4; | |
| 1238 | + nWidth += 2; | |
| 1164 | 1239 | |
| 1165 | 1240 | sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal); |
| 1166 | 1241 | for(i=0; 1; i++){ |
| 1167 | 1242 | i64 nLoop = 0; |
| 1168 | 1243 | i64 nRow = 0; |
| @@ -1173,55 +1248,67 @@ | ||
| 1173 | 1248 | const char *zName = 0; |
| 1174 | 1249 | double rEst = 0.0; |
| 1175 | 1250 | |
| 1176 | 1251 | if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){ |
| 1177 | 1252 | break; |
| 1253 | + } | |
| 1254 | + sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid); | |
| 1255 | + if( iPid!=prevPid ){ | |
| 1256 | + prevPid = iPid; | |
| 1257 | + rEstCum = 1.0; | |
| 1178 | 1258 | } |
| 1179 | 1259 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst); |
| 1260 | + rEstCum *= rEst; | |
| 1180 | 1261 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop); |
| 1181 | 1262 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow); |
| 1182 | 1263 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle); |
| 1183 | 1264 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId); |
| 1184 | - sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid); | |
| 1185 | 1265 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName); |
| 1186 | 1266 | |
| 1187 | 1267 | if( nCycle>=0 || nLoop>=0 || nRow>=0 ){ |
| 1188 | - const char *zSp = ""; | |
| 1189 | - double rpl; | |
| 1268 | + int nSp = 0; | |
| 1190 | 1269 | sqlite3_str_reset(pStats); |
| 1191 | 1270 | if( nCycle>=0 && nTotal>0 ){ |
| 1192 | - sqlite3_str_appendf(pStats, "cycles=%lld [%d%%]", | |
| 1193 | - nCycle, ((nCycle*100)+nTotal/2) / nTotal | |
| 1271 | + qrfApproxInt64(pStats, nCycle); | |
| 1272 | + sqlite3_str_appendf(pStats, " %3d%%", | |
| 1273 | + ((nCycle*100)+nTotal/2) / nTotal | |
| 1194 | 1274 | ); |
| 1195 | - zSp = " "; | |
| 1275 | + nSp = 2; | |
| 1196 | 1276 | } |
| 1197 | 1277 | if( nLoop>=0 ){ |
| 1198 | - sqlite3_str_appendf(pStats, "%sloops=%lld", zSp, nLoop); | |
| 1199 | - zSp = " "; | |
| 1278 | + if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' '); | |
| 1279 | + qrfApproxInt64(pStats, nLoop); | |
| 1280 | + nSp = 2; | |
| 1281 | + if( p->spec.eStyle==QRF_STYLE_StatsEst ){ | |
| 1282 | + sqlite3_str_appendf(pStats, " "); | |
| 1283 | + qrfApproxInt64(pStats, (i64)(rEstCum/rEst)); | |
| 1284 | + } | |
| 1200 | 1285 | } |
| 1201 | 1286 | if( nRow>=0 ){ |
| 1202 | - sqlite3_str_appendf(pStats, "%srows=%lld", zSp, nRow); | |
| 1203 | - zSp = " "; | |
| 1204 | - } | |
| 1205 | - | |
| 1206 | - if( p->spec.eStyle==QRF_STYLE_StatsEst ){ | |
| 1207 | - rpl = (double)nRow / (double)nLoop; | |
| 1208 | - sqlite3_str_appendf(pStats, "%srpl=%.1f est=%.1f", zSp, rpl, rEst); | |
| 1209 | - } | |
| 1210 | - | |
| 1287 | + if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' '); | |
| 1288 | + qrfApproxInt64(pStats, nRow); | |
| 1289 | + nSp = 2; | |
| 1290 | + if( p->spec.eStyle==QRF_STYLE_StatsEst ){ | |
| 1291 | + sqlite3_str_appendf(pStats, " "); | |
| 1292 | + qrfApproxInt64(pStats, (i64)rEstCum); | |
| 1293 | + } | |
| 1294 | + } | |
| 1211 | 1295 | sqlite3_str_appendf(pLine, |
| 1212 | - "% *s (%s)", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo, | |
| 1296 | + "% *s %s", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo, | |
| 1213 | 1297 | sqlite3_str_value(pStats) |
| 1214 | 1298 | ); |
| 1215 | 1299 | sqlite3_str_reset(pStats); |
| 1216 | 1300 | qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine)); |
| 1217 | 1301 | sqlite3_str_reset(pLine); |
| 1218 | 1302 | }else{ |
| 1219 | 1303 | qrfEqpAppend(p, iId, iPid, zo); |
| 1220 | 1304 | } |
| 1221 | 1305 | } |
| 1306 | + if( p->u.pGraph ) p->u.pGraph->nWidth = nWidth; | |
| 1307 | + qrfStrErr(p, pLine); | |
| 1222 | 1308 | sqlite3_free(sqlite3_str_finish(pLine)); |
| 1309 | + qrfStrErr(p, pStats); | |
| 1223 | 1310 | sqlite3_free(sqlite3_str_finish(pStats)); |
| 1224 | 1311 | #endif |
| 1225 | 1312 | } |
| 1226 | 1313 | |
| 1227 | 1314 | |
| @@ -1581,13 +1668,15 @@ | ||
| 1581 | 1668 | ** (3) z[] does not looks like a numeric literal |
| 1582 | 1669 | */ |
| 1583 | 1670 | static int qrfRelaxable(Qrf *p, const char *z){ |
| 1584 | 1671 | size_t i, n; |
| 1585 | 1672 | if( z[0]=='\'' || qrfSpace(z[0]) ) return 0; |
| 1586 | - if( z[0]==0 && (p->spec.zNull==0 || p->spec.zNull[0]==0) ) return 0; | |
| 1673 | + if( z[0]==0 ){ | |
| 1674 | + return (p->spec.zNull!=0 && p->spec.zNull[0]!=0); | |
| 1675 | + } | |
| 1587 | 1676 | n = strlen(z); |
| 1588 | - if( z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0; | |
| 1677 | + if( n==0 || z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0; | |
| 1589 | 1678 | if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0; |
| 1590 | 1679 | i = (z[0]=='-' || z[0]=='+'); |
| 1591 | 1680 | if( strcmp(z+i,"Inf")==0 ) return 0; |
| 1592 | 1681 | if( !qrfDigit(z[i]) ) return 1; |
| 1593 | 1682 | i++; |
| @@ -2729,10 +2818,11 @@ | ||
| 2729 | 2818 | int nNL = 0; |
| 2730 | 2819 | int n, w; |
| 2731 | 2820 | pStr = sqlite3_str_new(p->db); |
| 2732 | 2821 | qrfEncodeText(p, pStr, z ? z : ""); |
| 2733 | 2822 | n = sqlite3_str_length(pStr); |
| 2823 | + qrfStrErr(p, pStr); | |
| 2734 | 2824 | z = data.az[data.n] = sqlite3_str_finish(pStr); |
| 2735 | 2825 | if( p->spec.nTitleLimit ){ |
| 2736 | 2826 | nNL = 0; |
| 2737 | 2827 | data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n], |
| 2738 | 2828 | p->spec.nTitleLimit ); |
| @@ -2756,10 +2846,11 @@ | ||
| 2756 | 2846 | int n, w; |
| 2757 | 2847 | int eType = sqlite3_column_type(p->pStmt,i); |
| 2758 | 2848 | pStr = sqlite3_str_new(p->db); |
| 2759 | 2849 | qrfRenderValue(p, pStr, i); |
| 2760 | 2850 | n = sqlite3_str_length(pStr); |
| 2851 | + qrfStrErr(p, pStr); | |
| 2761 | 2852 | z = data.az[data.n] = sqlite3_str_finish(pStr); |
| 2762 | 2853 | data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT; |
| 2763 | 2854 | data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL); |
| 2764 | 2855 | data.n++; |
| 2765 | 2856 | if( w>data.a[i].mxW ) data.a[i].mxW = w; |
| @@ -2910,11 +3001,11 @@ | ||
| 2910 | 3001 | ){ |
| 2911 | 3002 | bRTrim = 1; |
| 2912 | 3003 | }else{ |
| 2913 | 3004 | bRTrim = 0; |
| 2914 | 3005 | } |
| 2915 | - for(i=0; i<data.n; i+=nColumn){ | |
| 3006 | + for(i=0; i<data.n && sqlite3_str_errcode(p->pOut)==SQLITE_OK; i+=nColumn){ | |
| 2916 | 3007 | int bMore; |
| 2917 | 3008 | int nRow = 0; |
| 2918 | 3009 | |
| 2919 | 3010 | /* Draw a single row of the table. This might be the title line |
| 2920 | 3011 | ** (if there is a title line) or a row in the body of the table. |
| @@ -3097,11 +3188,11 @@ | ||
| 3097 | 3188 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) ); |
| 3098 | 3189 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) ); |
| 3099 | 3190 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) ); |
| 3100 | 3191 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) ); |
| 3101 | 3192 | |
| 3102 | - for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt); iOp++){ | |
| 3193 | + for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){ | |
| 3103 | 3194 | int iAddr = sqlite3_column_int(p->pStmt, 0); |
| 3104 | 3195 | const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1); |
| 3105 | 3196 | int p1 = sqlite3_column_int(p->pStmt, 2); |
| 3106 | 3197 | int p2 = sqlite3_column_int(p->pStmt, 3); |
| 3107 | 3198 | |
| @@ -3154,11 +3245,11 @@ | ||
| 3154 | 3245 | nWidth = sizeof(aScanExpWidth)/sizeof(int); |
| 3155 | 3246 | iIndent = 3; |
| 3156 | 3247 | } |
| 3157 | 3248 | if( nArg>nWidth ) nArg = nWidth; |
| 3158 | 3249 | |
| 3159 | - for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW; iOp++){ | |
| 3250 | + for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW && !p->iErr; iOp++){ | |
| 3160 | 3251 | /* If this is the first row seen, print out the headers */ |
| 3161 | 3252 | if( iOp==0 ){ |
| 3162 | 3253 | for(i=0; i<nArg; i++){ |
| 3163 | 3254 | const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]); |
| 3164 | 3255 | qrfWidthPrint(p,p->pOut, aWidth[i], zCol); |
| @@ -3410,10 +3501,11 @@ | ||
| 3410 | 3501 | sqlite3_str_append(p->pOut, "\n", 1); |
| 3411 | 3502 | zVal += iNext; |
| 3412 | 3503 | }while( zVal[0] ); |
| 3413 | 3504 | sqlite3_str_reset(pVal); |
| 3414 | 3505 | } |
| 3506 | + qrfStrErr(p, pVal); | |
| 3415 | 3507 | sqlite3_free(sqlite3_str_finish(pVal)); |
| 3416 | 3508 | qrfWrite(p); |
| 3417 | 3509 | break; |
| 3418 | 3510 | } |
| 3419 | 3511 | case QRF_STYLE_Eqp: { |
| @@ -3473,11 +3565,11 @@ | ||
| 3473 | 3565 | p->pOut = sqlite3_str_new(p->db); |
| 3474 | 3566 | if( p->pOut==0 ){ |
| 3475 | 3567 | qrfOom(p); |
| 3476 | 3568 | return; |
| 3477 | 3569 | } |
| 3478 | - p->iErr = 0; | |
| 3570 | + p->iErr = SQLITE_OK; | |
| 3479 | 3571 | p->nCol = sqlite3_column_count(p->pStmt); |
| 3480 | 3572 | p->nRow = 0; |
| 3481 | 3573 | sz = sizeof(sqlite3_qrf_spec); |
| 3482 | 3574 | memcpy(&p->spec, pSpec, sz); |
| 3483 | 3575 | if( p->spec.zNull==0 ) p->spec.zNull = ""; |
| @@ -3644,17 +3736,27 @@ | ||
| 3644 | 3736 | sqlite3_free(p->u.sLine.azCol); |
| 3645 | 3737 | } |
| 3646 | 3738 | break; |
| 3647 | 3739 | } |
| 3648 | 3740 | case QRF_STYLE_Stats: |
| 3649 | - case QRF_STYLE_StatsEst: | |
| 3741 | + case QRF_STYLE_StatsEst: { | |
| 3742 | + i64 nCycle = 0; | |
| 3743 | +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS | |
| 3744 | + sqlite3_stmt_scanstatus_v2(p->pStmt, -1, SQLITE_SCANSTAT_NCYCLE, | |
| 3745 | + SQLITE_SCANSTAT_COMPLEX, (void*)&nCycle); | |
| 3746 | +#endif | |
| 3747 | + qrfEqpRender(p, nCycle); | |
| 3748 | + qrfWrite(p); | |
| 3749 | + break; | |
| 3750 | + } | |
| 3650 | 3751 | case QRF_STYLE_Eqp: { |
| 3651 | 3752 | qrfEqpRender(p, 0); |
| 3652 | 3753 | qrfWrite(p); |
| 3653 | 3754 | break; |
| 3654 | 3755 | } |
| 3655 | 3756 | } |
| 3757 | + qrfStrErr(p, p->pOut); | |
| 3656 | 3758 | if( p->spec.pzOutput ){ |
| 3657 | 3759 | if( p->spec.pzOutput[0] ){ |
| 3658 | 3760 | sqlite3_int64 n, sz; |
| 3659 | 3761 | char *zCombined; |
| 3660 | 3762 | sz = strlen(p->spec.pzOutput[0]); |
| @@ -3815,13 +3917,10 @@ | ||
| 3815 | 3917 | |
| 3816 | 3918 | |
| 3817 | 3919 | #define eputz(z) cli_puts(z,stderr) |
| 3818 | 3920 | #define sputz(fp,z) cli_puts(z,fp) |
| 3819 | 3921 | |
| 3820 | -/* True if the timer is enabled */ | |
| 3821 | -static int enableTimer = 0; | |
| 3822 | - | |
| 3823 | 3922 | /* A version of strcmp() that works with NULL values */ |
| 3824 | 3923 | static int cli_strcmp(const char *a, const char *b){ |
| 3825 | 3924 | if( a==0 ) a = ""; |
| 3826 | 3925 | if( b==0 ) b = ""; |
| 3827 | 3926 | return strcmp(a,b); |
| @@ -3834,11 +3933,11 @@ | ||
| 3834 | 3933 | |
| 3835 | 3934 | /* Return the current wall-clock time in microseconds since the |
| 3836 | 3935 | ** Unix epoch (1970-01-01T00:00:00Z) |
| 3837 | 3936 | */ |
| 3838 | 3937 | static sqlite3_int64 timeOfDay(void){ |
| 3839 | -#if defined(_WIN64) | |
| 3938 | +#if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8 | |
| 3840 | 3939 | sqlite3_uint64 t; |
| 3841 | 3940 | FILETIME tm; |
| 3842 | 3941 | GetSystemTimePreciseAsFileTime(&tm); |
| 3843 | 3942 | t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime; |
| 3844 | 3943 | t += 116444736000000000LL; |
| @@ -3862,154 +3961,10 @@ | ||
| 3862 | 3961 | (void)gettimeofday(&sNow,0); |
| 3863 | 3962 | return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec; |
| 3864 | 3963 | #endif |
| 3865 | 3964 | } |
| 3866 | 3965 | |
| 3867 | -#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) | |
| 3868 | -#include <sys/time.h> | |
| 3869 | -#include <sys/resource.h> | |
| 3870 | - | |
| 3871 | -/* VxWorks does not support getrusage() as far as we can determine */ | |
| 3872 | -#if defined(_WRS_KERNEL) || defined(__RTP__) | |
| 3873 | -struct rusage { | |
| 3874 | - struct timeval ru_utime; /* user CPU time used */ | |
| 3875 | - struct timeval ru_stime; /* system CPU time used */ | |
| 3876 | -}; | |
| 3877 | -#define getrusage(A,B) memset(B,0,sizeof(*B)) | |
| 3878 | -#endif | |
| 3879 | - | |
| 3880 | - | |
| 3881 | -/* Saved resource information for the beginning of an operation */ | |
| 3882 | -static struct rusage sBegin; /* CPU time at start */ | |
| 3883 | -static sqlite3_int64 iBegin; /* Wall-clock time at start */ | |
| 3884 | - | |
| 3885 | -/* | |
| 3886 | -** Begin timing an operation | |
| 3887 | -*/ | |
| 3888 | -static void beginTimer(void){ | |
| 3889 | - if( enableTimer ){ | |
| 3890 | - getrusage(RUSAGE_SELF, &sBegin); | |
| 3891 | - iBegin = timeOfDay(); | |
| 3892 | - } | |
| 3893 | -} | |
| 3894 | - | |
| 3895 | -/* Return the difference of two time_structs in seconds */ | |
| 3896 | -static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ | |
| 3897 | - return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + | |
| 3898 | - (double)(pEnd->tv_sec - pStart->tv_sec); | |
| 3899 | -} | |
| 3900 | - | |
| 3901 | -/* | |
| 3902 | -** Print the timing results. | |
| 3903 | -*/ | |
| 3904 | -static void endTimer(FILE *out){ | |
| 3905 | - if( enableTimer ){ | |
| 3906 | - sqlite3_int64 iEnd = timeOfDay(); | |
| 3907 | - struct rusage sEnd; | |
| 3908 | - getrusage(RUSAGE_SELF, &sEnd); | |
| 3909 | - cli_printf(out, "Run Time: real %.6f user %.6f sys %.6f\n", | |
| 3910 | - (iEnd - iBegin)*0.000001, | |
| 3911 | - timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), | |
| 3912 | - timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); | |
| 3913 | - } | |
| 3914 | -} | |
| 3915 | - | |
| 3916 | -#define BEGIN_TIMER beginTimer() | |
| 3917 | -#define END_TIMER(X) endTimer(X) | |
| 3918 | -#define HAS_TIMER 1 | |
| 3919 | - | |
| 3920 | -#elif (defined(_WIN32) || defined(WIN32)) | |
| 3921 | - | |
| 3922 | -/* Saved resource information for the beginning of an operation */ | |
| 3923 | -static HANDLE hProcess; | |
| 3924 | -static FILETIME ftKernelBegin; | |
| 3925 | -static FILETIME ftUserBegin; | |
| 3926 | -static sqlite3_int64 ftWallBegin; | |
| 3927 | -typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, | |
| 3928 | - LPFILETIME, LPFILETIME); | |
| 3929 | -static GETPROCTIMES getProcessTimesAddr = NULL; | |
| 3930 | - | |
| 3931 | -/* | |
| 3932 | -** Check to see if we have timer support. Return 1 if necessary | |
| 3933 | -** support found (or found previously). | |
| 3934 | -*/ | |
| 3935 | -static int hasTimer(void){ | |
| 3936 | - if( getProcessTimesAddr ){ | |
| 3937 | - return 1; | |
| 3938 | - } else { | |
| 3939 | - /* GetProcessTimes() isn't supported in WIN95 and some other Windows | |
| 3940 | - ** versions. See if the version we are running on has it, and if it | |
| 3941 | - ** does, save off a pointer to it and the current process handle. | |
| 3942 | - */ | |
| 3943 | - hProcess = GetCurrentProcess(); | |
| 3944 | - if( hProcess ){ | |
| 3945 | - HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); | |
| 3946 | - if( NULL != hinstLib ){ | |
| 3947 | - getProcessTimesAddr = | |
| 3948 | - (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); | |
| 3949 | - if( NULL != getProcessTimesAddr ){ | |
| 3950 | - return 1; | |
| 3951 | - } | |
| 3952 | - FreeLibrary(hinstLib); | |
| 3953 | - } | |
| 3954 | - } | |
| 3955 | - } | |
| 3956 | - return 0; | |
| 3957 | -} | |
| 3958 | - | |
| 3959 | -/* | |
| 3960 | -** Begin timing an operation | |
| 3961 | -*/ | |
| 3962 | -static void beginTimer(void){ | |
| 3963 | - if( enableTimer && getProcessTimesAddr ){ | |
| 3964 | - FILETIME ftCreation, ftExit; | |
| 3965 | - getProcessTimesAddr(hProcess,&ftCreation,&ftExit, | |
| 3966 | - &ftKernelBegin,&ftUserBegin); | |
| 3967 | - ftWallBegin = timeOfDay(); | |
| 3968 | - } | |
| 3969 | -} | |
| 3970 | - | |
| 3971 | -/* Return the difference of two FILETIME structs in seconds */ | |
| 3972 | -static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ | |
| 3973 | - sqlite_int64 i64Start = *((sqlite_int64 *) pStart); | |
| 3974 | - sqlite_int64 i64End = *((sqlite_int64 *) pEnd); | |
| 3975 | - return (double) ((i64End - i64Start) / 10000000.0); | |
| 3976 | -} | |
| 3977 | - | |
| 3978 | -/* | |
| 3979 | -** Print the timing results. | |
| 3980 | -*/ | |
| 3981 | -static void endTimer(FILE *out){ | |
| 3982 | - if( enableTimer && getProcessTimesAddr){ | |
| 3983 | - FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; | |
| 3984 | - sqlite3_int64 ftWallEnd = timeOfDay(); | |
| 3985 | - getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); | |
| 3986 | -#ifdef _WIN64 | |
| 3987 | - /* microsecond precision on 64-bit windows */ | |
| 3988 | - cli_printf(out, "Run Time: real %.6f user %f sys %f\n", | |
| 3989 | - (ftWallEnd - ftWallBegin)*0.000001, | |
| 3990 | - timeDiff(&ftUserBegin, &ftUserEnd), | |
| 3991 | - timeDiff(&ftKernelBegin, &ftKernelEnd)); | |
| 3992 | -#else | |
| 3993 | - /* millisecond precisino on 32-bit windows */ | |
| 3994 | - cli_printf(out, "Run Time: real %.3f user %.3f sys %.3f\n", | |
| 3995 | - (ftWallEnd - ftWallBegin)*0.000001, | |
| 3996 | - timeDiff(&ftUserBegin, &ftUserEnd), | |
| 3997 | - timeDiff(&ftKernelBegin, &ftKernelEnd)); | |
| 3998 | -#endif | |
| 3999 | - } | |
| 4000 | -} | |
| 4001 | - | |
| 4002 | -#define BEGIN_TIMER beginTimer() | |
| 4003 | -#define END_TIMER(X) endTimer(X) | |
| 4004 | -#define HAS_TIMER hasTimer() | |
| 4005 | - | |
| 4006 | -#else | |
| 4007 | -#define BEGIN_TIMER | |
| 4008 | -#define END_TIMER(X) /*no-op*/ | |
| 4009 | -#define HAS_TIMER 0 | |
| 4010 | -#endif | |
| 4011 | 3966 | |
| 4012 | 3967 | /* |
| 4013 | 3968 | ** Used to prevent warnings about unused parameters |
| 4014 | 3969 | */ |
| 4015 | 3970 | #define UNUSED_PARAMETER(x) (void)(x) |
| @@ -4068,10 +4023,18 @@ | ||
| 4068 | 4023 | #define PROMPT_LEN_MAX 128 |
| 4069 | 4024 | /* First line prompt. default: "sqlite> " */ |
| 4070 | 4025 | static char mainPrompt[PROMPT_LEN_MAX]; |
| 4071 | 4026 | /* Continuation prompt. default: " ...> " */ |
| 4072 | 4027 | static char continuePrompt[PROMPT_LEN_MAX]; |
| 4028 | + | |
| 4029 | +/* | |
| 4030 | +** Write I/O traces to the following stream. | |
| 4031 | +*/ | |
| 4032 | +#ifdef SQLITE_ENABLE_IOTRACE | |
| 4033 | +static FILE *iotrace = 0; | |
| 4034 | +#endif | |
| 4035 | + | |
| 4073 | 4036 | |
| 4074 | 4037 | /* This is variant of the standard-library strncpy() routine with the |
| 4075 | 4038 | ** one change that the destination string is always zero-terminated, even |
| 4076 | 4039 | ** if there is no zero-terminator in the first n-1 characters of the source |
| 4077 | 4040 | ** string. |
| @@ -4188,17 +4151,10 @@ | ||
| 4188 | 4151 | */ |
| 4189 | 4152 | static void shell_check_oom(const void *p){ |
| 4190 | 4153 | if( p==0 ) shell_out_of_memory(); |
| 4191 | 4154 | } |
| 4192 | 4155 | |
| 4193 | -/* | |
| 4194 | -** Write I/O traces to the following stream. | |
| 4195 | -*/ | |
| 4196 | -#ifdef SQLITE_ENABLE_IOTRACE | |
| 4197 | -static FILE *iotrace = 0; | |
| 4198 | -#endif | |
| 4199 | - | |
| 4200 | 4156 | /* |
| 4201 | 4157 | ** This routine works like printf in that its first argument is a |
| 4202 | 4158 | ** format string and subsequent arguments are values to be substituted |
| 4203 | 4159 | ** in place of % fields. The result of formatting this string |
| 4204 | 4160 | ** is written to iotrace. |
| @@ -8349,13 +8305,13 @@ | ||
| 8349 | 8305 | }else if( e<-10000 ){ |
| 8350 | 8306 | e = -10000; |
| 8351 | 8307 | } |
| 8352 | 8308 | |
| 8353 | 8309 | if( m<0 ){ |
| 8310 | + if( m<(-9223372036854775807LL) ) return; | |
| 8354 | 8311 | isNeg = 1; |
| 8355 | 8312 | m = -m; |
| 8356 | - if( m<0 ) return; | |
| 8357 | 8313 | }else if( m==0 && e>-1000 && e<1000 ){ |
| 8358 | 8314 | sqlite3_result_double(context, 0.0); |
| 8359 | 8315 | return; |
| 8360 | 8316 | } |
| 8361 | 8317 | while( (m>>32)&0xffe00000 ){ |
| @@ -9472,11 +9428,11 @@ | ||
| 9472 | 9428 | ** (X) match X |
| 9473 | 9429 | ** X|Y X or Y |
| 9474 | 9430 | ** ^X X occurring at the beginning of the string |
| 9475 | 9431 | ** X$ X occurring at the end of the string |
| 9476 | 9432 | ** . Match any single character |
| 9477 | -** \c Character c where c is one of \{}()[]|*+?. | |
| 9433 | +** \c Character c where c is one of \{}()[]|*+?-. | |
| 9478 | 9434 | ** \c C-language escapes for c in afnrtv. ex: \t or \n |
| 9479 | 9435 | ** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX |
| 9480 | 9436 | ** \xXX Where XX is exactly 2 hex digits, unicode value XX |
| 9481 | 9437 | ** [abc] Any single character from the set abc |
| 9482 | 9438 | ** [^abc] Any single character not in the set abc |
| @@ -9857,11 +9813,11 @@ | ||
| 9857 | 9813 | |
| 9858 | 9814 | /* A backslash character has been seen, read the next character and |
| 9859 | 9815 | ** return its interpretation. |
| 9860 | 9816 | */ |
| 9861 | 9817 | static unsigned re_esc_char(ReCompiled *p){ |
| 9862 | - static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]"; | |
| 9818 | + static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]-"; | |
| 9863 | 9819 | static const char zTrans[] = "\a\f\n\r\t\v"; |
| 9864 | 9820 | int i, v = 0; |
| 9865 | 9821 | char c; |
| 9866 | 9822 | if( p->sIn.i>=p->sIn.mx ) return 0; |
| 9867 | 9823 | c = p->sIn.z[p->sIn.i]; |
| @@ -10180,15 +10136,22 @@ | ||
| 10180 | 10136 | } |
| 10181 | 10137 | return pRe->zErr; |
| 10182 | 10138 | } |
| 10183 | 10139 | |
| 10184 | 10140 | /* |
| 10185 | -** Compute a reasonable limit on the length of the REGEXP NFA. | |
| 10141 | +** The value of LIMIT_MAX_PATTERN_LENGTH. | |
| 10186 | 10142 | */ |
| 10187 | 10143 | static int re_maxlen(sqlite3_context *context){ |
| 10188 | 10144 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 10189 | - return 75 + sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1)/2; | |
| 10145 | + return sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1); | |
| 10146 | +} | |
| 10147 | + | |
| 10148 | +/* | |
| 10149 | +** Maximum NFA size given a maximum pattern length. | |
| 10150 | +*/ | |
| 10151 | +static int re_maxnfa(int mxlen){ | |
| 10152 | + return 75+mxlen/2; | |
| 10190 | 10153 | } |
| 10191 | 10154 | |
| 10192 | 10155 | /* |
| 10193 | 10156 | ** Implementation of the regexp() SQL function. This function implements |
| 10194 | 10157 | ** the build-in REGEXP operator. The first argument to the function is the |
| @@ -10210,14 +10173,21 @@ | ||
| 10210 | 10173 | int setAux = 0; /* True to invoke sqlite3_set_auxdata() */ |
| 10211 | 10174 | |
| 10212 | 10175 | (void)argc; /* Unused */ |
| 10213 | 10176 | pRe = sqlite3_get_auxdata(context, 0); |
| 10214 | 10177 | if( pRe==0 ){ |
| 10178 | + int mxLen = re_maxlen(context); | |
| 10179 | + int nPattern; | |
| 10215 | 10180 | zPattern = (const char*)sqlite3_value_text(argv[0]); |
| 10216 | 10181 | if( zPattern==0 ) return; |
| 10217 | - zErr = re_compile(&pRe, zPattern, re_maxlen(context), | |
| 10218 | - sqlite3_user_data(context)!=0); | |
| 10182 | + nPattern = sqlite3_value_bytes(argv[0]); | |
| 10183 | + if( nPattern>mxLen ){ | |
| 10184 | + zErr = "REGEXP pattern too big"; | |
| 10185 | + }else{ | |
| 10186 | + zErr = re_compile(&pRe, zPattern, re_maxnfa(mxLen), | |
| 10187 | + sqlite3_user_data(context)!=0); | |
| 10188 | + } | |
| 10219 | 10189 | if( zErr ){ |
| 10220 | 10190 | re_free(pRe); |
| 10221 | 10191 | sqlite3_result_error(context, zErr, -1); |
| 10222 | 10192 | return; |
| 10223 | 10193 | } |
| @@ -10279,11 +10249,11 @@ | ||
| 10279 | 10249 | "ATSTART", |
| 10280 | 10250 | }; |
| 10281 | 10251 | |
| 10282 | 10252 | zPattern = (const char*)sqlite3_value_text(argv[0]); |
| 10283 | 10253 | if( zPattern==0 ) return; |
| 10284 | - zErr = re_compile(&pRe, zPattern, re_maxlen(context), | |
| 10254 | + zErr = re_compile(&pRe, zPattern, re_maxnfa(re_maxlen(context)), | |
| 10285 | 10255 | sqlite3_user_data(context)!=0); |
| 10286 | 10256 | if( zErr ){ |
| 10287 | 10257 | re_free(pRe); |
| 10288 | 10258 | sqlite3_result_error(context, zErr, -1); |
| 10289 | 10259 | return; |
| @@ -13067,11 +13037,11 @@ | ||
| 13067 | 13037 | nFile = (int)strlen(zFile)+1; |
| 13068 | 13038 | } |
| 13069 | 13039 | |
| 13070 | 13040 | rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA); |
| 13071 | 13041 | if( rc==SQLITE_OK ){ |
| 13072 | - pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile); | |
| 13042 | + pNew = (ZipfileTab*)sqlite3_malloc64((i64)nByte+nFile); | |
| 13073 | 13043 | if( pNew==0 ) return SQLITE_NOMEM; |
| 13074 | 13044 | memset(pNew, 0, nByte+nFile); |
| 13075 | 13045 | pNew->db = db; |
| 13076 | 13046 | pNew->aBuffer = (u8*)&pNew[1]; |
| 13077 | 13047 | if( zFile ){ |
| @@ -13213,18 +13183,19 @@ | ||
| 13213 | 13183 | ** sqlite3_free(). |
| 13214 | 13184 | */ |
| 13215 | 13185 | static int zipfileReadData( |
| 13216 | 13186 | FILE *pFile, /* Read from this file */ |
| 13217 | 13187 | u8 *aRead, /* Read into this buffer */ |
| 13218 | - int nRead, /* Number of bytes to read */ | |
| 13188 | + i64 nRead, /* Number of bytes to read */ | |
| 13219 | 13189 | i64 iOff, /* Offset to read from */ |
| 13220 | 13190 | char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */ |
| 13221 | 13191 | ){ |
| 13222 | 13192 | size_t n; |
| 13223 | 13193 | fseek(pFile, (long)iOff, SEEK_SET); |
| 13224 | - n = fread(aRead, 1, nRead, pFile); | |
| 13225 | - if( (int)n!=nRead ){ | |
| 13194 | + n = fread(aRead, 1, (long)nRead, pFile); | |
| 13195 | + if( n!=(size_t)nRead ){ | |
| 13196 | + sqlite3_free(*pzErrmsg); | |
| 13226 | 13197 | *pzErrmsg = sqlite3_mprintf("error in fread()"); |
| 13227 | 13198 | return SQLITE_ERROR; |
| 13228 | 13199 | } |
| 13229 | 13200 | return SQLITE_OK; |
| 13230 | 13201 | } |
| @@ -13237,11 +13208,11 @@ | ||
| 13237 | 13208 | if( nWrite>0 ){ |
| 13238 | 13209 | size_t n = nWrite; |
| 13239 | 13210 | fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET); |
| 13240 | 13211 | n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd); |
| 13241 | 13212 | if( (int)n!=nWrite ){ |
| 13242 | - pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()"); | |
| 13213 | + zipfileTableErr(pTab,"error in fwrite()"); | |
| 13243 | 13214 | return SQLITE_ERROR; |
| 13244 | 13215 | } |
| 13245 | 13216 | pTab->szCurrent += nWrite; |
| 13246 | 13217 | } |
| 13247 | 13218 | return SQLITE_OK; |
| @@ -13484,10 +13455,11 @@ | ||
| 13484 | 13455 | /* |
| 13485 | 13456 | ** Set (*pzErr) to point to a buffer from sqlite3_malloc() containing a |
| 13486 | 13457 | ** generic corruption message and return SQLITE_CORRUPT; |
| 13487 | 13458 | */ |
| 13488 | 13459 | static int zipfileCorrupt(char **pzErr){ |
| 13460 | + sqlite3_free(*pzErr); | |
| 13489 | 13461 | *pzErr = sqlite3_mprintf("zip archive is corrupt"); |
| 13490 | 13462 | return SQLITE_CORRUPT; |
| 13491 | 13463 | } |
| 13492 | 13464 | |
| 13493 | 13465 | /* |
| @@ -13502,11 +13474,11 @@ | ||
| 13502 | 13474 | ** final value of (*ppEntry) undefined. |
| 13503 | 13475 | */ |
| 13504 | 13476 | static int zipfileGetEntry( |
| 13505 | 13477 | ZipfileTab *pTab, /* Store any error message here */ |
| 13506 | 13478 | const u8 *aBlob, /* Pointer to in-memory file image */ |
| 13507 | - int nBlob, /* Size of aBlob[] in bytes */ | |
| 13479 | + i64 nBlob, /* Size of aBlob[] in bytes */ | |
| 13508 | 13480 | FILE *pFile, /* If aBlob==0, read from this file */ |
| 13509 | 13481 | i64 iOff, /* Offset of CDS record */ |
| 13510 | 13482 | ZipfileEntry **ppEntry /* OUT: Pointer to new object */ |
| 13511 | 13483 | ){ |
| 13512 | 13484 | u8 *aRead; |
| @@ -13542,18 +13514,18 @@ | ||
| 13542 | 13514 | rc = SQLITE_NOMEM; |
| 13543 | 13515 | }else{ |
| 13544 | 13516 | memset(pNew, 0, sizeof(ZipfileEntry)); |
| 13545 | 13517 | rc = zipfileReadCDS(aRead, &pNew->cds); |
| 13546 | 13518 | if( rc!=SQLITE_OK ){ |
| 13547 | - *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff); | |
| 13519 | + zipfileTableErr(pTab, "failed to read CDS at offset %lld", iOff); | |
| 13548 | 13520 | }else if( aBlob==0 ){ |
| 13549 | 13521 | rc = zipfileReadData( |
| 13550 | 13522 | pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr |
| 13551 | 13523 | ); |
| 13552 | 13524 | }else{ |
| 13553 | 13525 | aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ]; |
| 13554 | - if( (iOff + ZIPFILE_LFH_FIXED_SZ + nFile + nExtra)>nBlob ){ | |
| 13526 | + if( (iOff + ZIPFILE_CDS_FIXED_SZ + nFile + nExtra)>nBlob ){ | |
| 13555 | 13527 | rc = zipfileCorrupt(pzErr); |
| 13556 | 13528 | } |
| 13557 | 13529 | } |
| 13558 | 13530 | } |
| 13559 | 13531 | |
| @@ -13574,19 +13546,19 @@ | ||
| 13574 | 13546 | ZipfileLFH lfh; |
| 13575 | 13547 | if( pFile ){ |
| 13576 | 13548 | rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr); |
| 13577 | 13549 | }else{ |
| 13578 | 13550 | aRead = (u8*)&aBlob[pNew->cds.iOffset]; |
| 13579 | - if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>(unsigned)nBlob ){ | |
| 13551 | + if( ((i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){ | |
| 13580 | 13552 | rc = zipfileCorrupt(pzErr); |
| 13581 | 13553 | } |
| 13582 | 13554 | } |
| 13583 | 13555 | |
| 13584 | 13556 | memset(&lfh, 0, sizeof(lfh)); |
| 13585 | 13557 | if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh); |
| 13586 | 13558 | if( rc==SQLITE_OK ){ |
| 13587 | - pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; | |
| 13559 | + pNew->iDataOff = (i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; | |
| 13588 | 13560 | pNew->iDataOff += lfh.nFile + lfh.nExtra; |
| 13589 | 13561 | if( aBlob && pNew->cds.szCompressed ){ |
| 13590 | 13562 | if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){ |
| 13591 | 13563 | rc = zipfileCorrupt(pzErr); |
| 13592 | 13564 | }else{ |
| @@ -13593,11 +13565,11 @@ | ||
| 13593 | 13565 | pNew->aData = &pNew->aExtra[nExtra]; |
| 13594 | 13566 | memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed); |
| 13595 | 13567 | } |
| 13596 | 13568 | } |
| 13597 | 13569 | }else{ |
| 13598 | - *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", | |
| 13570 | + zipfileTableErr(pTab, "failed to read LFH at offset %d", | |
| 13599 | 13571 | (int)pNew->cds.iOffset |
| 13600 | 13572 | ); |
| 13601 | 13573 | } |
| 13602 | 13574 | } |
| 13603 | 13575 | |
| @@ -13617,11 +13589,11 @@ | ||
| 13617 | 13589 | static int zipfileNext(sqlite3_vtab_cursor *cur){ |
| 13618 | 13590 | ZipfileCsr *pCsr = (ZipfileCsr*)cur; |
| 13619 | 13591 | int rc = SQLITE_OK; |
| 13620 | 13592 | |
| 13621 | 13593 | if( pCsr->pFile ){ |
| 13622 | - i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize; | |
| 13594 | + i64 iEof = (i64)pCsr->eocd.iOffset + (i64)pCsr->eocd.nSize; | |
| 13623 | 13595 | zipfileEntryFree(pCsr->pCurrent); |
| 13624 | 13596 | pCsr->pCurrent = 0; |
| 13625 | 13597 | if( pCsr->iNextOff>=iEof ){ |
| 13626 | 13598 | pCsr->bEof = 1; |
| 13627 | 13599 | }else{ |
| @@ -13855,16 +13827,16 @@ | ||
| 13855 | 13827 | ** an English language error message may be left in virtual-table pTab. |
| 13856 | 13828 | */ |
| 13857 | 13829 | static int zipfileReadEOCD( |
| 13858 | 13830 | ZipfileTab *pTab, /* Return errors here */ |
| 13859 | 13831 | const u8 *aBlob, /* Pointer to in-memory file image */ |
| 13860 | - int nBlob, /* Size of aBlob[] in bytes */ | |
| 13832 | + i64 nBlob, /* Size of aBlob[] in bytes */ | |
| 13861 | 13833 | FILE *pFile, /* Read from this file if aBlob==0 */ |
| 13862 | 13834 | ZipfileEOCD *pEOCD /* Object to populate */ |
| 13863 | 13835 | ){ |
| 13864 | 13836 | u8 *aRead = pTab->aBuffer; /* Temporary buffer */ |
| 13865 | - int nRead; /* Bytes to read from file */ | |
| 13837 | + i64 nRead; /* Bytes to read from file */ | |
| 13866 | 13838 | int rc = SQLITE_OK; |
| 13867 | 13839 | |
| 13868 | 13840 | memset(pEOCD, 0, sizeof(ZipfileEOCD)); |
| 13869 | 13841 | if( aBlob==0 ){ |
| 13870 | 13842 | i64 iOff; /* Offset to read from */ |
| @@ -13881,11 +13853,11 @@ | ||
| 13881 | 13853 | nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE)); |
| 13882 | 13854 | aRead = (u8*)&aBlob[nBlob-nRead]; |
| 13883 | 13855 | } |
| 13884 | 13856 | |
| 13885 | 13857 | if( rc==SQLITE_OK ){ |
| 13886 | - int i; | |
| 13858 | + i64 i; | |
| 13887 | 13859 | |
| 13888 | 13860 | /* Scan backwards looking for the signature bytes */ |
| 13889 | 13861 | for(i=nRead-20; i>=0; i--){ |
| 13890 | 13862 | if( aRead[i]==0x50 && aRead[i+1]==0x4b |
| 13891 | 13863 | && aRead[i+2]==0x05 && aRead[i+3]==0x06 |
| @@ -13892,13 +13864,11 @@ | ||
| 13892 | 13864 | ){ |
| 13893 | 13865 | break; |
| 13894 | 13866 | } |
| 13895 | 13867 | } |
| 13896 | 13868 | if( i<0 ){ |
| 13897 | - pTab->base.zErrMsg = sqlite3_mprintf( | |
| 13898 | - "cannot find end of central directory record" | |
| 13899 | - ); | |
| 13869 | + zipfileTableErr(pTab, "cannot find end of central directory record"); | |
| 13900 | 13870 | return SQLITE_ERROR; |
| 13901 | 13871 | } |
| 13902 | 13872 | |
| 13903 | 13873 | aRead += i+4; |
| 13904 | 13874 | pEOCD->iDisk = zipfileRead16(aRead); |
| @@ -13939,11 +13909,11 @@ | ||
| 13939 | 13909 | pNew->pNext = pBefore; |
| 13940 | 13910 | *pp = pNew; |
| 13941 | 13911 | } |
| 13942 | 13912 | } |
| 13943 | 13913 | |
| 13944 | -static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){ | |
| 13914 | +static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, i64 nBlob){ | |
| 13945 | 13915 | ZipfileEOCD eocd; |
| 13946 | 13916 | int rc; |
| 13947 | 13917 | int i; |
| 13948 | 13918 | i64 iOff; |
| 13949 | 13919 | |
| @@ -13987,11 +13957,11 @@ | ||
| 13987 | 13957 | zipfileCursorErr(pCsr, "zipfile() function requires an argument"); |
| 13988 | 13958 | return SQLITE_ERROR; |
| 13989 | 13959 | }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ |
| 13990 | 13960 | static const u8 aEmptyBlob = 0; |
| 13991 | 13961 | const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]); |
| 13992 | - int nBlob = sqlite3_value_bytes(argv[0]); | |
| 13962 | + i64 nBlob = sqlite3_value_bytes(argv[0]); | |
| 13993 | 13963 | assert( pTab->pFirstEntry==0 ); |
| 13994 | 13964 | if( aBlob==0 ){ |
| 13995 | 13965 | aBlob = &aEmptyBlob; |
| 13996 | 13966 | nBlob = 0; |
| 13997 | 13967 | } |
| @@ -14185,23 +14155,23 @@ | ||
| 14185 | 14155 | ZipfileTab *pTab = (ZipfileTab*)pVtab; |
| 14186 | 14156 | int rc = SQLITE_OK; |
| 14187 | 14157 | |
| 14188 | 14158 | assert( pTab->pWriteFd==0 ); |
| 14189 | 14159 | if( pTab->zFile==0 || pTab->zFile[0]==0 ){ |
| 14190 | - pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename"); | |
| 14160 | + zipfileTableErr(pTab, "zipfile: missing filename"); | |
| 14191 | 14161 | return SQLITE_ERROR; |
| 14192 | 14162 | } |
| 14193 | 14163 | |
| 14194 | 14164 | /* Open a write fd on the file. Also load the entire central directory |
| 14195 | 14165 | ** structure into memory. During the transaction any new file data is |
| 14196 | 14166 | ** appended to the archive file, but the central directory is accumulated |
| 14197 | 14167 | ** in main-memory until the transaction is committed. */ |
| 14198 | 14168 | pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+"); |
| 14199 | 14169 | if( pTab->pWriteFd==0 ){ |
| 14200 | - pTab->base.zErrMsg = sqlite3_mprintf( | |
| 14201 | - "zipfile: failed to open file %s for writing", pTab->zFile | |
| 14202 | - ); | |
| 14170 | + zipfileTableErr(pTab, | |
| 14171 | + "zipfile: failed to open file %s for writing", pTab->zFile | |
| 14172 | + ); | |
| 14203 | 14173 | rc = SQLITE_ERROR; |
| 14204 | 14174 | }else{ |
| 14205 | 14175 | fseek(pTab->pWriteFd, 0, SEEK_END); |
| 14206 | 14176 | pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd); |
| 14207 | 14177 | rc = zipfileLoadDirectory(pTab, 0, 0); |
| @@ -14662,11 +14632,11 @@ | ||
| 14662 | 14632 | int nEntry; |
| 14663 | 14633 | ZipfileBuffer body; |
| 14664 | 14634 | ZipfileBuffer cds; |
| 14665 | 14635 | }; |
| 14666 | 14636 | |
| 14667 | -static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){ | |
| 14637 | +static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){ | |
| 14668 | 14638 | if( pBuf->n+nByte>pBuf->nAlloc ){ |
| 14669 | 14639 | u8 *aNew; |
| 14670 | 14640 | sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512; |
| 14671 | 14641 | int nReq = pBuf->n + nByte; |
| 14672 | 14642 | |
| @@ -14711,11 +14681,11 @@ | ||
| 14711 | 14681 | u32 iCrc32 = 0; /* crc32 of uncompressed data */ |
| 14712 | 14682 | |
| 14713 | 14683 | char *zName = 0; /* Path (name) of new entry */ |
| 14714 | 14684 | int nName = 0; /* Size of zName in bytes */ |
| 14715 | 14685 | char *zFree = 0; /* Free this before returning */ |
| 14716 | - int nByte; | |
| 14686 | + i64 nByte; | |
| 14717 | 14687 | |
| 14718 | 14688 | memset(&e, 0, sizeof(e)); |
| 14719 | 14689 | p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); |
| 14720 | 14690 | if( p==0 ) return; |
| 14721 | 14691 | |
| @@ -24161,28 +24131,28 @@ | ||
| 24161 | 24131 | u8 autoExplain; /* Automatically turn on .explain mode */ |
| 24162 | 24132 | u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */ |
| 24163 | 24133 | u8 autoEQPtrace; /* autoEQP is in trace mode */ |
| 24164 | 24134 | u8 scanstatsOn; /* True to display scan stats before each finalize */ |
| 24165 | 24135 | u8 bAutoScreenWidth; /* Using the TTY to determine screen width */ |
| 24166 | - u8 mFlags; /* MFLG_ECHO and/or MFLG_CRLF */ | |
| 24136 | + u8 mFlags; /* MFLG_ECHO, MFLG_CRLF, etc. */ | |
| 24167 | 24137 | u8 eMode; /* One of the MODE_ values */ |
| 24168 | 24138 | sqlite3_qrf_spec spec; /* Spec to be passed into QRF */ |
| 24169 | 24139 | } Mode; |
| 24170 | 24140 | |
| 24171 | 24141 | /* Flags for Mode.mFlags */ |
| 24172 | 24142 | #define MFLG_ECHO 0x01 /* Echo inputs to output */ |
| 24173 | 24143 | #define MFLG_CRLF 0x02 /* Use CR/LF output line endings */ |
| 24144 | +#define MFLG_HDR 0x04 /* .header used to change headers on/off */ | |
| 24174 | 24145 | |
| 24175 | 24146 | |
| 24176 | 24147 | /* |
| 24177 | 24148 | ** State information about the database connection is contained in an |
| 24178 | 24149 | ** instance of the following structure. |
| 24179 | 24150 | */ |
| 24180 | 24151 | typedef struct ShellState ShellState; |
| 24181 | 24152 | struct ShellState { |
| 24182 | 24153 | sqlite3 *db; /* The database */ |
| 24183 | - int iCompat; /* Compatibility date YYYYMMDD */ | |
| 24184 | 24154 | u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ |
| 24185 | 24155 | u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ |
| 24186 | 24156 | u8 nEqpLevel; /* Depth of the EQP output graph */ |
| 24187 | 24157 | u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ |
| 24188 | 24158 | u8 bSafeMode; /* True to prohibit unsafe operations */ |
| @@ -24190,11 +24160,14 @@ | ||
| 24190 | 24160 | u8 eRestoreState; /* See comments above doAutoDetectRestore() */ |
| 24191 | 24161 | unsigned statsOn; /* True to display memory stats before each finalize */ |
| 24192 | 24162 | unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */ |
| 24193 | 24163 | u8 nPopOutput; /* Revert .output settings when reaching zero */ |
| 24194 | 24164 | u8 nPopMode; /* Revert .mode settings when reaching zero */ |
| 24165 | + u8 enableTimer; /* Enable the timer. 2: permanently 1: only once */ | |
| 24195 | 24166 | int inputNesting; /* Track nesting level of .read and other redirects */ |
| 24167 | + double prevTimer; /* Last reported timer value */ | |
| 24168 | + double tmProgress; /* --timeout option for .progress */ | |
| 24196 | 24169 | i64 lineno; /* Line number of last line read from in */ |
| 24197 | 24170 | const char *zInFile; /* Name of the input file */ |
| 24198 | 24171 | int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ |
| 24199 | 24172 | FILE *in; /* Read commands from this stream */ |
| 24200 | 24173 | FILE *out; /* Write results here */ |
| @@ -24286,10 +24259,11 @@ | ||
| 24286 | 24259 | #define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */ |
| 24287 | 24260 | #define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progress |
| 24288 | 24261 | ** callback limit is reached, and for each |
| 24289 | 24262 | ** top-level SQL statement */ |
| 24290 | 24263 | #define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */ |
| 24264 | +#define SHELL_PROGRESS_TMOUT 0x08 /* Stop after tmProgress seconds */ | |
| 24291 | 24265 | |
| 24292 | 24266 | /* Names of values for Mode.spec.eEsc and Mode.spec.eText |
| 24293 | 24267 | */ |
| 24294 | 24268 | static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" }; |
| 24295 | 24269 | static const char *qrfQuoteNames[] = |
| @@ -24447,10 +24421,181 @@ | ||
| 24447 | 24421 | ** Limit input nesting via .read or any other input redirect. |
| 24448 | 24422 | ** It's not too expensive, so a generous allowance can be made. |
| 24449 | 24423 | */ |
| 24450 | 24424 | #define MAX_INPUT_NESTING 25 |
| 24451 | 24425 | |
| 24426 | +/************************* BEGIN PERFORMANCE TIMER *****************************/ | |
| 24427 | +#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) | |
| 24428 | +#include <sys/time.h> | |
| 24429 | +#include <sys/resource.h> | |
| 24430 | +/* VxWorks does not support getrusage() as far as we can determine */ | |
| 24431 | +#if defined(_WRS_KERNEL) || defined(__RTP__) | |
| 24432 | +struct rusage { | |
| 24433 | + struct timeval ru_utime; /* user CPU time used */ | |
| 24434 | + struct timeval ru_stime; /* system CPU time used */ | |
| 24435 | +}; | |
| 24436 | +#define getrusage(A,B) memset(B,0,sizeof(*B)) | |
| 24437 | +#endif | |
| 24438 | + | |
| 24439 | +/* Saved resource information for the beginning of an operation */ | |
| 24440 | +static struct rusage sBegin; /* CPU time at start */ | |
| 24441 | +static sqlite3_int64 iBegin; /* Wall-clock time at start */ | |
| 24442 | + | |
| 24443 | +/* | |
| 24444 | +** Begin timing an operation | |
| 24445 | +*/ | |
| 24446 | +static void beginTimer(ShellState *p){ | |
| 24447 | + if( p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0 ){ | |
| 24448 | + getrusage(RUSAGE_SELF, &sBegin); | |
| 24449 | + iBegin = timeOfDay(); | |
| 24450 | + } | |
| 24451 | +} | |
| 24452 | + | |
| 24453 | +/* Return the difference of two time_structs in seconds */ | |
| 24454 | +static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ | |
| 24455 | + return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + | |
| 24456 | + (double)(pEnd->tv_sec - pStart->tv_sec); | |
| 24457 | +} | |
| 24458 | + | |
| 24459 | +/* Return the time since the start of the timer in | |
| 24460 | +** seconds. */ | |
| 24461 | +static double elapseTime(ShellState *NotUsed){ | |
| 24462 | + (void)NotUsed; | |
| 24463 | + if( iBegin==0 ) return 0.0; | |
| 24464 | + return (timeOfDay() - iBegin)*0.000001; | |
| 24465 | +} | |
| 24466 | + | |
| 24467 | +/* | |
| 24468 | +** Print the timing results. | |
| 24469 | +*/ | |
| 24470 | +static void endTimer(ShellState *p){ | |
| 24471 | + if( p->enableTimer ){ | |
| 24472 | + sqlite3_int64 iEnd = timeOfDay(); | |
| 24473 | + struct rusage sEnd; | |
| 24474 | + getrusage(RUSAGE_SELF, &sEnd); | |
| 24475 | + p->prevTimer = (iEnd - iBegin)*0.000001; | |
| 24476 | + cli_printf(p->out, "Run Time: real %.6f user %.6f sys %.6f\n", | |
| 24477 | + p->prevTimer, | |
| 24478 | + timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), | |
| 24479 | + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); | |
| 24480 | + if( p->enableTimer==1 ) p->enableTimer = 0; | |
| 24481 | + iBegin = 0; | |
| 24482 | + } | |
| 24483 | +} | |
| 24484 | + | |
| 24485 | +#define BEGIN_TIMER(X) beginTimer(X) | |
| 24486 | +#define END_TIMER(X) endTimer(X) | |
| 24487 | +#define ELAPSE_TIME(X) elapseTime(X) | |
| 24488 | +#define HAS_TIMER 1 | |
| 24489 | + | |
| 24490 | +#elif (defined(_WIN32) || defined(WIN32)) | |
| 24491 | + | |
| 24492 | +/* Saved resource information for the beginning of an operation */ | |
| 24493 | +static HANDLE hProcess; | |
| 24494 | +static FILETIME ftKernelBegin; | |
| 24495 | +static FILETIME ftUserBegin; | |
| 24496 | +static sqlite3_int64 ftWallBegin; | |
| 24497 | +typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, | |
| 24498 | + LPFILETIME, LPFILETIME); | |
| 24499 | +static GETPROCTIMES getProcessTimesAddr = NULL; | |
| 24500 | + | |
| 24501 | +/* | |
| 24502 | +** Check to see if we have timer support. Return 1 if necessary | |
| 24503 | +** support found (or found previously). | |
| 24504 | +*/ | |
| 24505 | +static int hasTimer(void){ | |
| 24506 | + if( getProcessTimesAddr ){ | |
| 24507 | + return 1; | |
| 24508 | + } else { | |
| 24509 | + /* GetProcessTimes() isn't supported in WIN95 and some other Windows | |
| 24510 | + ** versions. See if the version we are running on has it, and if it | |
| 24511 | + ** does, save off a pointer to it and the current process handle. | |
| 24512 | + */ | |
| 24513 | + hProcess = GetCurrentProcess(); | |
| 24514 | + if( hProcess ){ | |
| 24515 | + HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); | |
| 24516 | + if( NULL != hinstLib ){ | |
| 24517 | + getProcessTimesAddr = | |
| 24518 | + (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); | |
| 24519 | + if( NULL != getProcessTimesAddr ){ | |
| 24520 | + return 1; | |
| 24521 | + } | |
| 24522 | + FreeLibrary(hinstLib); | |
| 24523 | + } | |
| 24524 | + } | |
| 24525 | + } | |
| 24526 | + return 0; | |
| 24527 | +} | |
| 24528 | + | |
| 24529 | +/* | |
| 24530 | +** Begin timing an operation | |
| 24531 | +*/ | |
| 24532 | +static void beginTimer(ShellState *p){ | |
| 24533 | + if( (p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0) | |
| 24534 | + && getProcessTimesAddr | |
| 24535 | + ){ | |
| 24536 | + FILETIME ftCreation, ftExit; | |
| 24537 | + getProcessTimesAddr(hProcess,&ftCreation,&ftExit, | |
| 24538 | + &ftKernelBegin,&ftUserBegin); | |
| 24539 | + ftWallBegin = timeOfDay(); | |
| 24540 | + } | |
| 24541 | +} | |
| 24542 | + | |
| 24543 | +/* Return the difference of two FILETIME structs in seconds */ | |
| 24544 | +static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ | |
| 24545 | + sqlite_int64 i64Start = *((sqlite_int64 *) pStart); | |
| 24546 | + sqlite_int64 i64End = *((sqlite_int64 *) pEnd); | |
| 24547 | + return (double) ((i64End - i64Start) / 10000000.0); | |
| 24548 | +} | |
| 24549 | + | |
| 24550 | +/* Return the time since the start of the timer in | |
| 24551 | +** seconds. */ | |
| 24552 | +static double elapseTime(ShellState *NotUsed){ | |
| 24553 | + (void)NotUsed; | |
| 24554 | + if( ftWallBegin==0 ) return 0.0; | |
| 24555 | + return (timeOfDay() - ftWallBegin)*0.000001; | |
| 24556 | +} | |
| 24557 | + | |
| 24558 | +/* | |
| 24559 | +** Print the timing results. | |
| 24560 | +*/ | |
| 24561 | +static void endTimer(ShellState *p){ | |
| 24562 | + if( p->enableTimer && getProcessTimesAddr){ | |
| 24563 | + FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; | |
| 24564 | + sqlite3_int64 ftWallEnd = timeOfDay(); | |
| 24565 | + getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); | |
| 24566 | + p->prevTimer = (ftWallEnd - ftWallBegin)*0.000001; | |
| 24567 | +#ifdef _WIN64 | |
| 24568 | + /* microsecond precision on 64-bit windows */ | |
| 24569 | + cli_printf(p->out, "Run Time: real %.6f user %f sys %f\n", | |
| 24570 | + p->prevTimer, | |
| 24571 | + timeDiff(&ftUserBegin, &ftUserEnd), | |
| 24572 | + timeDiff(&ftKernelBegin, &ftKernelEnd)); | |
| 24573 | +#else | |
| 24574 | + /* millisecond precisino on 32-bit windows */ | |
| 24575 | + cli_printf(p->out, "Run Time: real %.3f user %.3f sys %.3f\n", | |
| 24576 | + p->prevTimer, | |
| 24577 | + timeDiff(&ftUserBegin, &ftUserEnd), | |
| 24578 | + timeDiff(&ftKernelBegin, &ftKernelEnd)); | |
| 24579 | +#endif | |
| 24580 | + if( p->enableTimer==1 ) p->enableTimer = 0; | |
| 24581 | + ftWallBegin = 0; | |
| 24582 | + } | |
| 24583 | +} | |
| 24584 | + | |
| 24585 | +#define BEGIN_TIMER(X) beginTimer(X) | |
| 24586 | +#define ELAPSE_TIME(X) elapseTime(X) | |
| 24587 | +#define END_TIMER(X) endTimer(X) | |
| 24588 | +#define HAS_TIMER hasTimer() | |
| 24589 | + | |
| 24590 | +#else | |
| 24591 | +#define BEGIN_TIMER(X) /* no-op */ | |
| 24592 | +#define ELAPSE_TIME(X) 0.0 | |
| 24593 | +#define END_TIMER(X) /*no-op*/ | |
| 24594 | +#define HAS_TIMER 0 | |
| 24595 | +#endif | |
| 24596 | +/************************* END PERFORMANCE TIMER ******************************/ | |
| 24452 | 24597 | |
| 24453 | 24598 | /* |
| 24454 | 24599 | ** Clear a display mode, freeing any allocated memory that it |
| 24455 | 24600 | ** contains. |
| 24456 | 24601 | */ |
| @@ -24534,11 +24679,13 @@ | ||
| 24534 | 24679 | if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]); |
| 24535 | 24680 | if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]); |
| 24536 | 24681 | if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]); |
| 24537 | 24682 | pM->spec.eText = pI->eText; |
| 24538 | 24683 | pM->spec.eBlob = pI->eBlob; |
| 24539 | - pM->spec.bTitles = pI->bHdr; | |
| 24684 | + if( (pM->mFlags & MFLG_HDR)==0 ){ | |
| 24685 | + pM->spec.bTitles = pI->bHdr; | |
| 24686 | + } | |
| 24540 | 24687 | pM->spec.eTitle = pI->eHdr; |
| 24541 | 24688 | if( pI->mFlg & 0x01 ){ |
| 24542 | 24689 | pM->spec.bBorder = QRF_No; |
| 24543 | 24690 | }else{ |
| 24544 | 24691 | pM->spec.bBorder = QRF_Auto; |
| @@ -24570,18 +24717,17 @@ | ||
| 24570 | 24717 | p->mode.mFlags = mFlags; |
| 24571 | 24718 | } |
| 24572 | 24719 | } |
| 24573 | 24720 | |
| 24574 | 24721 | /* |
| 24575 | -** Set the mode to the default according to p->iCompat. It assumed | |
| 24576 | -** that the mode has already been freed and zeroed prior to calling | |
| 24577 | -** this routine. | |
| 24722 | +** Set the mode to the default. It assumed that the mode has | |
| 24723 | +** already been freed and zeroed prior to calling this routine. | |
| 24578 | 24724 | */ |
| 24579 | 24725 | static void modeDefault(ShellState *p){ |
| 24580 | 24726 | p->mode.spec.iVersion = 1; |
| 24581 | 24727 | p->mode.autoExplain = 1; |
| 24582 | - if( p->iCompat>=20251115 && (stdin_is_interactive || stdout_is_console) ){ | |
| 24728 | + if( stdin_is_interactive || stdout_is_console ){ | |
| 24583 | 24729 | modeChange(p, MODE_TTY); |
| 24584 | 24730 | }else{ |
| 24585 | 24731 | modeChange(p, MODE_BATCH); |
| 24586 | 24732 | } |
| 24587 | 24733 | } |
| @@ -25371,10 +25517,17 @@ | ||
| 25371 | 25517 | ** Progress handler callback. |
| 25372 | 25518 | */ |
| 25373 | 25519 | static int progress_handler(void *pClientData) { |
| 25374 | 25520 | ShellState *p = (ShellState*)pClientData; |
| 25375 | 25521 | p->nProgress++; |
| 25522 | + if( (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0 | |
| 25523 | + && ELAPSE_TIME(p)>=p->tmProgress | |
| 25524 | + ){ | |
| 25525 | + cli_printf(p->out, "Progress timeout after %.6f seconds\n", | |
| 25526 | + ELAPSE_TIME(p)); | |
| 25527 | + return 1; | |
| 25528 | + } | |
| 25376 | 25529 | if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){ |
| 25377 | 25530 | cli_printf(p->out, "Progress limit reached (%u)\n", p->nProgress); |
| 25378 | 25531 | if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; |
| 25379 | 25532 | if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0; |
| 25380 | 25533 | return 1; |
| @@ -25908,10 +26061,12 @@ | ||
| 25908 | 26061 | char *zBuf = sqlite3_malloc64( szVar-5 ); |
| 25909 | 26062 | if( zBuf ){ |
| 25910 | 26063 | memcpy(zBuf, &zVar[6], szVar-5); |
| 25911 | 26064 | sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8); |
| 25912 | 26065 | } |
| 26066 | + }else if( strcmp(zVar, "$TIMER")==0 ){ | |
| 26067 | + sqlite3_bind_double(pStmt, i, pArg->prevTimer); | |
| 25913 | 26068 | #ifdef SQLITE_ENABLE_CARRAY |
| 25914 | 26069 | }else if( strncmp(zVar, "$carray_", 8)==0 ){ |
| 25915 | 26070 | static char *azColorNames[] = { |
| 25916 | 26071 | "azure", "black", "blue", "brown", "cyan", "fuchsia", "gold", |
| 25917 | 26072 | "gray", "green", "indigo", "khaki", "lime", "magenta", "maroon", |
| @@ -26167,27 +26322,36 @@ | ||
| 26167 | 26322 | pArg->pStmt = pStmt; |
| 26168 | 26323 | } |
| 26169 | 26324 | |
| 26170 | 26325 | /* Show the EXPLAIN QUERY PLAN if .eqp is on */ |
| 26171 | 26326 | isExplain = sqlite3_stmt_isexplain(pStmt); |
| 26172 | - if( pArg && pArg->mode.autoEQP && isExplain==0 ){ | |
| 26327 | + if( pArg && pArg->mode.autoEQP && isExplain==0 && pArg->dot.nArg==0 ){ | |
| 26173 | 26328 | int triggerEQP = 0; |
| 26329 | + u8 savedEnableTimer = pArg->enableTimer; | |
| 26330 | + pArg->enableTimer = 0; | |
| 26174 | 26331 | disable_debug_trace_modes(); |
| 26175 | 26332 | sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP); |
| 26176 | 26333 | if( pArg->mode.autoEQP>=AUTOEQP_trigger ){ |
| 26177 | 26334 | sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0); |
| 26178 | 26335 | } |
| 26179 | 26336 | sqlite3_reset(pStmt); |
| 26180 | 26337 | spec.eStyle = QRF_STYLE_Auto; |
| 26181 | - sqlite3_stmt_explain(pStmt, 2-(pArg->mode.autoEQP>=AUTOEQP_full)); | |
| 26338 | + sqlite3_stmt_explain(pStmt, 2); | |
| 26182 | 26339 | sqlite3_format_query_result(pStmt, &spec, 0); |
| 26340 | + if( pArg->mode.autoEQP>=AUTOEQP_full ){ | |
| 26341 | + sqlite3_reset(pStmt); | |
| 26342 | + sqlite3_stmt_explain(pStmt, 1); | |
| 26343 | + sqlite3_format_query_result(pStmt, &spec, 0); | |
| 26344 | + } | |
| 26345 | + | |
| 26183 | 26346 | if( pArg->mode.autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){ |
| 26184 | 26347 | sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0); |
| 26185 | 26348 | } |
| 26186 | 26349 | sqlite3_reset(pStmt); |
| 26187 | 26350 | sqlite3_stmt_explain(pStmt, 0); |
| 26188 | 26351 | restore_debug_trace_modes(); |
| 26352 | + pArg->enableTimer = savedEnableTimer; | |
| 26189 | 26353 | } |
| 26190 | 26354 | |
| 26191 | 26355 | bind_prepared_stmt(pArg, pStmt); |
| 26192 | 26356 | if( isExplain && pArg->mode.autoExplain ){ |
| 26193 | 26357 | spec.eStyle = isExplain==1 ? QRF_STYLE_Explain : QRF_STYLE_Eqp; |
| @@ -26604,12 +26768,12 @@ | ||
| 26604 | 26768 | ".bail on|off Stop after hitting an error. Default OFF", |
| 26605 | 26769 | #ifndef SQLITE_SHELL_FIDDLE |
| 26606 | 26770 | ".cd DIRECTORY Change the working directory to DIRECTORY", |
| 26607 | 26771 | #endif |
| 26608 | 26772 | ".changes on|off Show number of rows changed by SQL", |
| 26773 | + ".check OPTIONS ... Verify the results of a .testcase", | |
| 26609 | 26774 | #ifndef SQLITE_SHELL_FIDDLE |
| 26610 | - ".check GLOB Fail if output since .testcase does not match", | |
| 26611 | 26775 | ".clone NEWDB Clone data into NEWDB from the existing database", |
| 26612 | 26776 | #endif |
| 26613 | 26777 | ".connection [close] [#] Open or close an auxiliary database connection", |
| 26614 | 26778 | ".crlf ?on|off? Whether or not to use \\r\\n line endings", |
| 26615 | 26779 | ".databases List names and files of attached databases", |
| @@ -26721,10 +26885,11 @@ | ||
| 26721 | 26885 | ".progress N Invoke progress handler after every N opcodes", |
| 26722 | 26886 | " --limit N Interrupt after N progress callbacks", |
| 26723 | 26887 | " --once Do no more than one progress interrupt", |
| 26724 | 26888 | " --quiet|-q No output except at interrupts", |
| 26725 | 26889 | " --reset Reset the count for each input and interrupt", |
| 26890 | + " --timeout S Halt after running for S seconds", | |
| 26726 | 26891 | #endif |
| 26727 | 26892 | ".prompt MAIN CONTINUE Replace the standard prompts", |
| 26728 | 26893 | #ifndef SQLITE_SHELL_FIDDLE |
| 26729 | 26894 | ".quit Stop interpreting input stream, exit if primary.", |
| 26730 | 26895 | ".read FILE Read input from FILE or command output", |
| @@ -26785,17 +26950,15 @@ | ||
| 26785 | 26950 | " vmstep Show the virtual machine step count only", |
| 26786 | 26951 | #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) |
| 26787 | 26952 | ".system CMD ARGS... Run CMD ARGS... in a system shell", |
| 26788 | 26953 | #endif |
| 26789 | 26954 | ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", |
| 26790 | -#ifndef SQLITE_SHELL_FIDDLE | |
| 26791 | - ",testcase NAME Begin redirecting output to 'testcase-out.txt'", | |
| 26792 | -#endif | |
| 26955 | + ".testcase NAME Begin a test case.", | |
| 26793 | 26956 | ",testctrl CMD ... Run various sqlite3_test_control() operations", |
| 26794 | 26957 | " Run \".testctrl\" with no arguments for details", |
| 26795 | 26958 | ".timeout MS Try opening locked tables for MS milliseconds", |
| 26796 | - ".timer on|off Turn SQL timer on or off", | |
| 26959 | + ".timer on|off|once Turn SQL timer on or off.", | |
| 26797 | 26960 | #ifndef SQLITE_OMIT_TRACE |
| 26798 | 26961 | ".trace ?OPTIONS? Output each SQL statement as it is run", |
| 26799 | 26962 | " FILE Send output to FILE", |
| 26800 | 26963 | " stdout Send output to stdout", |
| 26801 | 26964 | " stderr Send output to stderr", |
| @@ -26836,19 +26999,33 @@ | ||
| 26836 | 26999 | "USAGE: .import [OPTIONS] FILE TABLE\n" |
| 26837 | 27000 | "\n" |
| 26838 | 27001 | "Import CSV or similar text from FILE into TABLE. If TABLE does\n" |
| 26839 | 27002 | "not exist, it is created using the first row of FILE as the column\n" |
| 26840 | 27003 | "names. If FILE begins with \"|\" then it is a command that is run\n" |
| 26841 | -"and the output from the command is used as the input data.\n" | |
| 27004 | +"and the output from the command is used as the input data. If\n" | |
| 27005 | +"FILE begins with \"<<\" followed by a label, then content is read from\n" | |
| 27006 | +"the script until the first line that matches the label.\n" | |
| 27007 | +"\n" | |
| 27008 | +"The content of FILE is interpreted using RFC-4180 (\"CSV\") quoting\n" | |
| 27009 | +"rules unless the current mode is \"ascii\" or \"tabs\" or unless one\n" | |
| 27010 | +"the --ascii option is used.\n" | |
| 26842 | 27011 | "\n" |
| 26843 | -"FILE is assumed to be in a CSV format, unless the current mode\n" | |
| 26844 | -"is \"ascii\" or \"tabs\" or unless one of the options below specify\n" | |
| 26845 | -"an alternative.\n" | |
| 27012 | +"The column and row separators must be single ASCII characters. If\n" | |
| 27013 | +"multiple characters or a Unicode character are specified for the\n" | |
| 27014 | +"separators, then only the first byte of the separator is used. Except,\n" | |
| 27015 | +"if the row separator is \\n and the mode is not --ascii, then \\r\\n is\n" | |
| 27016 | +"understood as a row separator too.\n" | |
| 26846 | 27017 | "\n" |
| 26847 | 27018 | "Options:\n" |
| 26848 | -" --ascii Use \\037 and \\036 as column and row separators on input\n" | |
| 27019 | +" --ascii Do not use RFC-4180 quoting. Use \\037 and \\036\n" | |
| 27020 | +" as column and row separators on input, unless other\n" | |
| 27021 | +" delimiters are specified using --colsep and/or --rowsep\n" | |
| 27022 | +" --colsep CHAR Use CHAR as the column separator.\n" | |
| 26849 | 27023 | " --csv Input is standard RFC-4180 CSV.\n" |
| 27024 | +" --esc CHAR Use CHAR as an escape character in unquoted CSV inputs.\n" | |
| 27025 | +" --qesc CHAR Use CHAR as an escape character in quoted CSV inputs.\n" | |
| 27026 | +" --rowsep CHAR Use CHAR as the row separator.\n" | |
| 26850 | 27027 | " --schema S When creating TABLE, put it in schema S\n" |
| 26851 | 27028 | " --skip N Ignore the first N rows of input\n" |
| 26852 | 27029 | " -v Verbose mode\n" |
| 26853 | 27030 | }, |
| 26854 | 27031 | { ".mode", |
| @@ -26930,23 +27107,17 @@ | ||
| 26930 | 27107 | " --bom Prepend a byte-order mark to the output\n" |
| 26931 | 27108 | " -e Accumulate output in a temporary text file then\n" |
| 26932 | 27109 | " launch a text editor when the redirection ends.\n" |
| 26933 | 27110 | " --error-prefix X Use X as the left-margin prefix for error messages.\n" |
| 26934 | 27111 | " Set to an empty string to restore the default.\n" |
| 26935 | -" --glob GLOB Raise an error if the memory buffer does not match\n" | |
| 26936 | -" the GLOB pattern.\n" | |
| 26937 | -" --keep Continue using the same \"memory\" buffer. Do not\n" | |
| 26938 | -" reset it or delete it. Useful in combination with\n" | |
| 26939 | -" --glob, --not-glob, and/or --verify.\n" | |
| 26940 | -" ---notglob GLOB Raise an error if the memory buffer does not match\n" | |
| 26941 | -" the GLOB pattern.\n" | |
| 27112 | +" --keep Keep redirecting output to its current destination.\n" | |
| 27113 | +" Use this option in combination with --show or\n" | |
| 27114 | +" with --error-prefix when you do not want to stop\n" | |
| 27115 | +" a current redirection.\n" | |
| 26942 | 27116 | " --plain Use plain text rather than HTML tables with -w\n" |
| 26943 | -" --show Write the memory buffer to the screen, for debugging.\n" | |
| 26944 | -" --verify ENDMARK Read subsequent lines of text until the first line\n" | |
| 26945 | -" that matches ENDMARK. Discard the ENDMARK. Compare\n" | |
| 26946 | -" the text against the accumulated output in memory and\n" | |
| 26947 | -" raise an error if there are any differences.\n" | |
| 27117 | +" --show Show output text captured by .testcase or by\n" | |
| 27118 | +" redirecting to \"memory\".\n" | |
| 26948 | 27119 | " -w Show the output in a web browser. Output is\n" |
| 26949 | 27120 | " written into a temporary HTML file until the\n" |
| 26950 | 27121 | " redirect ends, then the web browser is launched.\n" |
| 26951 | 27122 | " Query results are shown as HTML tables, unless\n" |
| 26952 | 27123 | " the --plain is used too.\n" |
| @@ -26970,10 +27141,39 @@ | ||
| 26970 | 27141 | " file in a web browser\n" |
| 26971 | 27142 | " -x Show the output in a spreadsheet. Output is\n" |
| 26972 | 27143 | " written to a temp file as CSV then the spreadsheet\n" |
| 26973 | 27144 | " is launched when\n" |
| 26974 | 27145 | }, |
| 27146 | + { ".check", | |
| 27147 | +"USAGE: .check [OPTIONS] PATTERN\n" | |
| 27148 | +"\n" | |
| 27149 | +"Verify results of commands since the most recent .testcase command.\n" | |
| 27150 | +"Restore output to the console, unless --keep is used.\n" | |
| 27151 | +"\n" | |
| 27152 | +"If PATTERN starts with \"<<ENDMARK\" then the actual pattern is taken from\n" | |
| 27153 | +"subsequent lines of text up to the first line that begins with ENDMARK.\n" | |
| 27154 | +"All pattern lines and the ENDMARK are discarded.\n" | |
| 27155 | +"\n" | |
| 27156 | +"Options:\n" | |
| 27157 | +" --exact Do an exact comparison including leading and\n" | |
| 27158 | +" trailing whitespace.\n" | |
| 27159 | +" --glob Treat PATTERN as a GLOB\n" | |
| 27160 | +" --keep Do not reset the testcase. More .check commands\n" | |
| 27161 | +" will follow.\n" | |
| 27162 | +" --notglob Output should not match PATTERN\n" | |
| 27163 | +" --show Write testcase output to the screen, for debugging.\n" | |
| 27164 | + }, | |
| 27165 | + { ".testcase", | |
| 27166 | +"USAGE: .testcase [OPTIONS] NAME\n" | |
| 27167 | +"\n" | |
| 27168 | +"Start a new test case identified by NAME. All output\n" | |
| 27169 | +"through the next \".check\" command is captured for comparison. See the\n" | |
| 27170 | +"\".check\" commandn for additional informatioon.\n" | |
| 27171 | +"\n" | |
| 27172 | +"Options:\n" | |
| 27173 | +" --error-prefix TEXT Change error message prefix text to TEXT\n" | |
| 27174 | + }, | |
| 26975 | 27175 | }; |
| 26976 | 27176 | |
| 26977 | 27177 | /* |
| 26978 | 27178 | ** Return a pointer to usage text for zCmd, or NULL if none exists. |
| 26979 | 27179 | */ |
| @@ -27193,10 +27393,56 @@ | ||
| 27193 | 27393 | if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0; |
| 27194 | 27394 | } |
| 27195 | 27395 | return 1; |
| 27196 | 27396 | } |
| 27197 | 27397 | #endif |
| 27398 | + | |
| 27399 | +/* | |
| 27400 | +** Return the size of the named file in bytes. Or return a negative | |
| 27401 | +** number if the file does not exist. | |
| 27402 | +*/ | |
| 27403 | +static sqlite3_int64 fileSize(const char *zFile){ | |
| 27404 | +#if defined(_WIN32) || defined(WIN32) | |
| 27405 | + struct _stat64 x; | |
| 27406 | + if( _stat64(zFile, &x)!=0 ) return -1; | |
| 27407 | + return (sqlite3_int64)x.st_size; | |
| 27408 | +#else | |
| 27409 | + struct stat x; | |
| 27410 | + if( stat(zFile, &x)!=0 ) return -1; | |
| 27411 | + return (sqlite3_int64)x.st_size; | |
| 27412 | +#endif | |
| 27413 | +} | |
| 27414 | + | |
| 27415 | +/* | |
| 27416 | +** Return true if zFile is an SQLite database. | |
| 27417 | +** | |
| 27418 | +** Algorithm: | |
| 27419 | +** * If the file does not exist -> return false | |
| 27420 | +** * If the size of the file is not a multiple of 512 -> return false | |
| 27421 | +** * If sqlite3_open() fails -> return false | |
| 27422 | +** * if sqlite3_prepare() or sqlite3_step() fails -> return false | |
| 27423 | +** * Otherwise -> return true | |
| 27424 | +*/ | |
| 27425 | +static int isDatabaseFile(const char *zFile, int openFlags){ | |
| 27426 | + sqlite3 *db = 0; | |
| 27427 | + sqlite3_stmt *pStmt = 0; | |
| 27428 | + int rc; | |
| 27429 | + sqlite3_int64 sz = fileSize(zFile); | |
| 27430 | + if( sz<512 || (sz%512)!=0 ) return 0; | |
| 27431 | + if( sqlite3_open_v2(zFile, &db, openFlags, 0)==SQLITE_OK | |
| 27432 | + && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0) | |
| 27433 | + ==SQLITE_OK | |
| 27434 | + && sqlite3_step(pStmt)==SQLITE_ROW | |
| 27435 | + ){ | |
| 27436 | + rc = 1; | |
| 27437 | + }else{ | |
| 27438 | + rc = 0; | |
| 27439 | + } | |
| 27440 | + sqlite3_finalize(pStmt); | |
| 27441 | + sqlite3_close(db); | |
| 27442 | + return rc; | |
| 27443 | +} | |
| 27198 | 27444 | |
| 27199 | 27445 | /* |
| 27200 | 27446 | ** Try to deduce the type of file for zName based on its content. Return |
| 27201 | 27447 | ** one of the SHELL_OPEN_* constants. |
| 27202 | 27448 | ** |
| @@ -27206,24 +27452,16 @@ | ||
| 27206 | 27452 | ** the type cannot be determined from content. |
| 27207 | 27453 | */ |
| 27208 | 27454 | int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){ |
| 27209 | 27455 | FILE *f; |
| 27210 | 27456 | size_t n; |
| 27211 | - sqlite3 *db = 0; | |
| 27212 | - sqlite3_stmt *pStmt = 0; | |
| 27213 | 27457 | int rc = SHELL_OPEN_UNSPEC; |
| 27214 | 27458 | char zBuf[100]; |
| 27215 | 27459 | if( access(zName,0)!=0 ) goto database_type_by_name; |
| 27216 | - if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK | |
| 27217 | - && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0) | |
| 27218 | - ==SQLITE_OK | |
| 27219 | - && sqlite3_step(pStmt)==SQLITE_ROW | |
| 27220 | - ){ | |
| 27460 | + if( isDatabaseFile(zName, openFlags) ){ | |
| 27221 | 27461 | rc = SHELL_OPEN_NORMAL; |
| 27222 | 27462 | } |
| 27223 | - sqlite3_finalize(pStmt); | |
| 27224 | - sqlite3_close(db); | |
| 27225 | 27463 | if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL; |
| 27226 | 27464 | f = sqlite3_fopen(zName, "rb"); |
| 27227 | 27465 | if( f==0 ) goto database_type_by_name; |
| 27228 | 27466 | n = fread(zBuf, 16, 1, f); |
| 27229 | 27467 | if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ |
| @@ -27253,10 +27491,39 @@ | ||
| 27253 | 27491 | }else{ |
| 27254 | 27492 | rc = SHELL_OPEN_NORMAL; |
| 27255 | 27493 | } |
| 27256 | 27494 | return rc; |
| 27257 | 27495 | } |
| 27496 | + | |
| 27497 | +/* | |
| 27498 | +** If the text in z[] is the name of a readable file and that file appears | |
| 27499 | +** to contain SQL text and/or dot-commands, then return true. If z[] is | |
| 27500 | +** not a file, or if the file is unreadable, or if the file is a database | |
| 27501 | +** or anything else that is not SQL text and dot-commands, then return false. | |
| 27502 | +** | |
| 27503 | +** If the bLeaveUninit flag is set, then be sure to leave SQLite in an | |
| 27504 | +** uninitialized state. This means invoking sqlite3_shutdown() after any | |
| 27505 | +** SQLite API is used. | |
| 27506 | +** | |
| 27507 | +** Some amount of guesswork is involved in this decision. | |
| 27508 | +*/ | |
| 27509 | +static int isScriptFile(const char *z, int bLeaveUninit){ | |
| 27510 | + sqlite3_int64 sz = fileSize(z); | |
| 27511 | + if( sz<=0 ) return 0; | |
| 27512 | + if( (sz%512)==0 ){ | |
| 27513 | + int rc; | |
| 27514 | + sqlite3_initialize(); | |
| 27515 | + rc = isDatabaseFile(z, SQLITE_OPEN_READONLY); | |
| 27516 | + if( bLeaveUninit ){ | |
| 27517 | + sqlite3_shutdown(); | |
| 27518 | + } | |
| 27519 | + if( rc ) return 0; /* Is a database */ | |
| 27520 | + } | |
| 27521 | + if( sqlite3_strlike("%.sql",z,0)==0 ) return 1; | |
| 27522 | + if( sqlite3_strlike("%.txt",z,0)==0 ) return 1; | |
| 27523 | + return 0; | |
| 27524 | +} | |
| 27258 | 27525 | |
| 27259 | 27526 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 27260 | 27527 | /* |
| 27261 | 27528 | ** Reconstruct an in-memory database using the output from the "dbtotxt" |
| 27262 | 27529 | ** program. Read content from the file in p->aAuxDb[].zDbFilename. |
| @@ -27899,20 +28166,24 @@ | ||
| 27899 | 28166 | typedef struct ImportCtx ImportCtx; |
| 27900 | 28167 | struct ImportCtx { |
| 27901 | 28168 | const char *zFile; /* Name of the input file */ |
| 27902 | 28169 | FILE *in; /* Read the CSV text from this input stream */ |
| 27903 | 28170 | int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */ |
| 28171 | + char *zIn; /* Input text */ | |
| 27904 | 28172 | char *z; /* Accumulated text for a field */ |
| 28173 | + i64 nUsed; /* Bytes of zIn[] used so far */ | |
| 27905 | 28174 | i64 n; /* Number of bytes in z */ |
| 27906 | 28175 | i64 nAlloc; /* Space allocated for z[] */ |
| 27907 | 28176 | int nLine; /* Current line number */ |
| 27908 | 28177 | int nRow; /* Number of rows imported */ |
| 27909 | 28178 | int nErr; /* Number of errors encountered */ |
| 27910 | 28179 | int bNotFirst; /* True if one or more bytes already read */ |
| 27911 | 28180 | int cTerm; /* Character that terminated the most recent field */ |
| 27912 | 28181 | int cColSep; /* The column separator character. (Usually ",") */ |
| 27913 | 28182 | int cRowSep; /* The row separator character. (Usually "\n") */ |
| 28183 | + int cQEscape; /* Escape character with "...". 0 for none */ | |
| 28184 | + int cUQEscape; /* Escape character not with "...". 0 for none */ | |
| 27914 | 28185 | }; |
| 27915 | 28186 | |
| 27916 | 28187 | /* Clean up resourced used by an ImportCtx */ |
| 27917 | 28188 | static void import_cleanup(ImportCtx *p){ |
| 27918 | 28189 | if( p->in!=0 && p->xCloser!=0 ){ |
| @@ -27919,13 +28190,32 @@ | ||
| 27919 | 28190 | p->xCloser(p->in); |
| 27920 | 28191 | p->in = 0; |
| 27921 | 28192 | } |
| 27922 | 28193 | sqlite3_free(p->z); |
| 27923 | 28194 | p->z = 0; |
| 28195 | + if( p->zIn ){ | |
| 28196 | + sqlite3_free(p->zIn); | |
| 28197 | + p->zIn = 0; | |
| 28198 | + } | |
| 27924 | 28199 | } |
| 27925 | 28200 | |
| 27926 | -/* Append a single byte to z[] */ | |
| 28201 | +/* Read a single character of the .import input text. Return EOF | |
| 28202 | +** at end-of-file. | |
| 28203 | +*/ | |
| 28204 | +static int import_getc(ImportCtx *p){ | |
| 28205 | + if( p->in ){ | |
| 28206 | + return fgetc(p->in); | |
| 28207 | + }else if( p->zIn && p->zIn[p->nUsed]!=0 ){ | |
| 28208 | + return p->zIn[p->nUsed++]; | |
| 28209 | + }else{ | |
| 28210 | + return EOF; | |
| 28211 | + } | |
| 28212 | +} | |
| 28213 | + | |
| 28214 | +/* Append a single byte to the field value begin constructed | |
| 28215 | +** in the p->z[] buffer | |
| 28216 | +*/ | |
| 27927 | 28217 | static void import_append_char(ImportCtx *p, int c){ |
| 27928 | 28218 | if( p->n+1>=p->nAlloc ){ |
| 27929 | 28219 | p->nAlloc += p->nAlloc + 100; |
| 27930 | 28220 | p->z = sqlite3_realloc64(p->z, p->nAlloc); |
| 27931 | 28221 | shell_check_oom(p->z); |
| @@ -27937,12 +28227,12 @@ | ||
| 27937 | 28227 | ** with the option of having a separator other than ",". |
| 27938 | 28228 | ** |
| 27939 | 28229 | ** + Input comes from p->in. |
| 27940 | 28230 | ** + Store results in p->z of length p->n. Space to hold p->z comes |
| 27941 | 28231 | ** from sqlite3_malloc64(). |
| 27942 | -** + Use p->cSep as the column separator. The default is ",". | |
| 27943 | -** + Use p->rSep as the row separator. The default is "\n". | |
| 28232 | +** + Use p->cColSep as the column separator. The default is ",". | |
| 28233 | +** + Use p->cRowSep as the row separator. The default is "\n". | |
| 27944 | 28234 | ** + Keep track of the line number in p->nLine. |
| 27945 | 28235 | ** + Store the character that terminates the field in p->cTerm. Store |
| 27946 | 28236 | ** EOF on end-of-file. |
| 27947 | 28237 | ** + Report syntax errors on stderr |
| 27948 | 28238 | */ |
| @@ -27949,23 +28239,30 @@ | ||
| 27949 | 28239 | static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ |
| 27950 | 28240 | int c; |
| 27951 | 28241 | int cSep = (u8)p->cColSep; |
| 27952 | 28242 | int rSep = (u8)p->cRowSep; |
| 27953 | 28243 | p->n = 0; |
| 27954 | - c = fgetc(p->in); | |
| 28244 | + c = import_getc(p); | |
| 27955 | 28245 | if( c==EOF || seenInterrupt ){ |
| 27956 | 28246 | p->cTerm = EOF; |
| 27957 | 28247 | return 0; |
| 27958 | 28248 | } |
| 27959 | 28249 | if( c=='"' ){ |
| 27960 | 28250 | int pc, ppc; |
| 27961 | 28251 | int startLine = p->nLine; |
| 27962 | 28252 | int cQuote = c; |
| 28253 | + int cEsc = (u8)p->cQEscape; | |
| 27963 | 28254 | pc = ppc = 0; |
| 27964 | 28255 | while( 1 ){ |
| 27965 | - c = fgetc(p->in); | |
| 28256 | + c = import_getc(p); | |
| 27966 | 28257 | if( c==rSep ) p->nLine++; |
| 28258 | + if( c==cEsc && cEsc!=0 ){ | |
| 28259 | + c = import_getc(p); | |
| 28260 | + import_append_char(p, c); | |
| 28261 | + ppc = pc = 0; | |
| 28262 | + continue; | |
| 28263 | + } | |
| 27967 | 28264 | if( c==cQuote ){ |
| 27968 | 28265 | if( pc==cQuote ){ |
| 27969 | 28266 | pc = 0; |
| 27970 | 28267 | continue; |
| 27971 | 28268 | } |
| @@ -27979,11 +28276,11 @@ | ||
| 27979 | 28276 | p->cTerm = c; |
| 27980 | 28277 | break; |
| 27981 | 28278 | } |
| 27982 | 28279 | if( pc==cQuote && c!='\r' ){ |
| 27983 | 28280 | cli_printf(stderr,"%s:%d: unescaped %c character\n", |
| 27984 | - p->zFile, p->nLine, cQuote); | |
| 28281 | + p->zFile, p->nLine, cQuote); | |
| 27985 | 28282 | } |
| 27986 | 28283 | if( c==EOF ){ |
| 27987 | 28284 | cli_printf(stderr,"%s:%d: unterminated %c-quoted field\n", |
| 27988 | 28285 | p->zFile, startLine, cQuote); |
| 27989 | 28286 | p->cTerm = c; |
| @@ -27994,26 +28291,28 @@ | ||
| 27994 | 28291 | pc = c; |
| 27995 | 28292 | } |
| 27996 | 28293 | }else{ |
| 27997 | 28294 | /* If this is the first field being parsed and it begins with the |
| 27998 | 28295 | ** UTF-8 BOM (0xEF BB BF) then skip the BOM */ |
| 28296 | + int cEsc = p->cUQEscape; | |
| 27999 | 28297 | if( (c&0xff)==0xef && p->bNotFirst==0 ){ |
| 28000 | 28298 | import_append_char(p, c); |
| 28001 | - c = fgetc(p->in); | |
| 28299 | + c = import_getc(p); | |
| 28002 | 28300 | if( (c&0xff)==0xbb ){ |
| 28003 | 28301 | import_append_char(p, c); |
| 28004 | - c = fgetc(p->in); | |
| 28302 | + c = import_getc(p); | |
| 28005 | 28303 | if( (c&0xff)==0xbf ){ |
| 28006 | 28304 | p->bNotFirst = 1; |
| 28007 | 28305 | p->n = 0; |
| 28008 | 28306 | return csv_read_one_field(p); |
| 28009 | 28307 | } |
| 28010 | 28308 | } |
| 28011 | 28309 | } |
| 28012 | 28310 | while( c!=EOF && c!=cSep && c!=rSep ){ |
| 28311 | + if( c==cEsc && cEsc!=0 ) c = import_getc(p); | |
| 28013 | 28312 | import_append_char(p, c); |
| 28014 | - c = fgetc(p->in); | |
| 28313 | + c = import_getc(p); | |
| 28015 | 28314 | } |
| 28016 | 28315 | if( c==rSep ){ |
| 28017 | 28316 | p->nLine++; |
| 28018 | 28317 | if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; |
| 28019 | 28318 | } |
| @@ -28027,12 +28326,12 @@ | ||
| 28027 | 28326 | /* Read a single field of ASCII delimited text. |
| 28028 | 28327 | ** |
| 28029 | 28328 | ** + Input comes from p->in. |
| 28030 | 28329 | ** + Store results in p->z of length p->n. Space to hold p->z comes |
| 28031 | 28330 | ** from sqlite3_malloc64(). |
| 28032 | -** + Use p->cSep as the column separator. The default is "\x1F". | |
| 28033 | -** + Use p->rSep as the row separator. The default is "\x1E". | |
| 28331 | +** + Use p->cColSep as the column separator. The default is "\x1F". | |
| 28332 | +** + Use p->cRowSep as the row separator. The default is "\x1E". | |
| 28034 | 28333 | ** + Keep track of the row number in p->nLine. |
| 28035 | 28334 | ** + Store the character that terminates the field in p->cTerm. Store |
| 28036 | 28335 | ** EOF on end-of-file. |
| 28037 | 28336 | ** + Report syntax errors on stderr |
| 28038 | 28337 | */ |
| @@ -28039,18 +28338,18 @@ | ||
| 28039 | 28338 | static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ |
| 28040 | 28339 | int c; |
| 28041 | 28340 | int cSep = (u8)p->cColSep; |
| 28042 | 28341 | int rSep = (u8)p->cRowSep; |
| 28043 | 28342 | p->n = 0; |
| 28044 | - c = fgetc(p->in); | |
| 28343 | + c = import_getc(p); | |
| 28045 | 28344 | if( c==EOF || seenInterrupt ){ |
| 28046 | 28345 | p->cTerm = EOF; |
| 28047 | 28346 | return 0; |
| 28048 | 28347 | } |
| 28049 | 28348 | while( c!=EOF && c!=cSep && c!=rSep ){ |
| 28050 | 28349 | import_append_char(p, c); |
| 28051 | - c = fgetc(p->in); | |
| 28350 | + c = import_getc(p); | |
| 28052 | 28351 | } |
| 28053 | 28352 | if( c==rSep ){ |
| 28054 | 28353 | p->nLine++; |
| 28055 | 28354 | } |
| 28056 | 28355 | p->cTerm = c; |
| @@ -30151,11 +30450,11 @@ | ||
| 30151 | 30450 | ; |
| 30152 | 30451 | static const char * const zCollectVar = "\ |
| 30153 | 30452 | SELECT\ |
| 30154 | 30453 | '('||x'0a'\ |
| 30155 | 30454 | || group_concat(\ |
| 30156 | - cname||' TEXT',\ | |
| 30455 | + cname||' ANY',\ | |
| 30157 | 30456 | ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ |
| 30158 | 30457 | ||')' AS ColsSpec \ |
| 30159 | 30458 | FROM (\ |
| 30160 | 30459 | SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \ |
| 30161 | 30460 | FROM ColNames ORDER BY cpos\ |
| @@ -30351,19 +30650,33 @@ | ||
| 30351 | 30650 | ** USAGE: .import [OPTIONS] FILE TABLE |
| 30352 | 30651 | ** |
| 30353 | 30652 | ** Import CSV or similar text from FILE into TABLE. If TABLE does |
| 30354 | 30653 | ** not exist, it is created using the first row of FILE as the column |
| 30355 | 30654 | ** names. If FILE begins with "|" then it is a command that is run |
| 30356 | -** and the output from the command is used as the input data. | |
| 30655 | +** and the output from the command is used as the input data. If | |
| 30656 | +** FILE begins with "<<" followed by a label, then content is read from | |
| 30657 | +** the script until the first line that matches the label. | |
| 30658 | +** | |
| 30659 | +** The content of FILE is interpreted using RFC-4180 ("CSV") quoting | |
| 30660 | +** rules unless the current mode is "ascii" or "tabs" or unless one | |
| 30661 | +** the --ascii option is used. | |
| 30357 | 30662 | ** |
| 30358 | -** FILE is assumed to be in a CSV format, unless the current mode | |
| 30359 | -** is "ascii" or "tabs" or unless one of the options below specify | |
| 30360 | -** an alternative. | |
| 30663 | +** The column and row separators must be single ASCII characters. If | |
| 30664 | +** multiple characters or a Unicode character are specified for the | |
| 30665 | +** separators, then only the first byte of the separator is used. Except, | |
| 30666 | +** if the row separator is \n and the mode is not --ascii, then \r\n is | |
| 30667 | +** understood as a row separator too. | |
| 30361 | 30668 | ** |
| 30362 | 30669 | ** Options: |
| 30363 | -** --ascii Use \037 and \036 as column and row separators on input | |
| 30670 | +** --ascii Do not use RFC-4180 quoting. Use \037 and \036 | |
| 30671 | +** as column and row separators on input, unless other | |
| 30672 | +** delimiters are specified using --colsep and/or --rowsep | |
| 30673 | +** --colsep CHAR Use CHAR as the column separator. | |
| 30364 | 30674 | ** --csv Input is standard RFC-4180 CSV. |
| 30675 | +** --esc CHAR Use CHAR as an escape character in unquoted CSV inputs. | |
| 30676 | +** --qesc CHAR Use CHAR as an escape character in quoted CSV inputs. | |
| 30677 | +** --rowsep CHAR Use CHAR as the row separator. | |
| 30365 | 30678 | ** --schema S When creating TABLE, put it in schema S |
| 30366 | 30679 | ** --skip N Ignore the first N rows of input |
| 30367 | 30680 | ** -v Verbose mode |
| 30368 | 30681 | */ |
| 30369 | 30682 | static int dotCmdImport(ShellState *p){ |
| @@ -30375,17 +30688,16 @@ | ||
| 30375 | 30688 | sqlite3_stmt *pStmt = NULL; /* A statement */ |
| 30376 | 30689 | int nCol; /* Number of columns in the table */ |
| 30377 | 30690 | i64 nByte; /* Number of bytes in an SQL string */ |
| 30378 | 30691 | int i, j; /* Loop counters */ |
| 30379 | 30692 | int needCommit; /* True to COMMIT or ROLLBACK at end */ |
| 30380 | - int nSep; /* Number of bytes in spec.zColumnSep */ | |
| 30381 | 30693 | char *zSql = 0; /* An SQL statement */ |
| 30382 | 30694 | ImportCtx sCtx; /* Reader context */ |
| 30383 | 30695 | char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ |
| 30384 | 30696 | int eVerbose = 0; /* Larger for more console output */ |
| 30385 | 30697 | i64 nSkip = 0; /* Initial lines to skip */ |
| 30386 | - int useOutputMode = 1; /* Use output mode to determine separators */ | |
| 30698 | + i64 iLineOffset = 0; /* Offset to the first line of input */ | |
| 30387 | 30699 | char *zCreate = 0; /* CREATE TABLE statement text */ |
| 30388 | 30700 | int rc; /* Result code */ |
| 30389 | 30701 | |
| 30390 | 30702 | failIfSafeMode(p, "cannot run .import in safe mode"); |
| 30391 | 30703 | memset(&sCtx, 0, sizeof(sCtx)); |
| @@ -30411,70 +30723,71 @@ | ||
| 30411 | 30723 | }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){ |
| 30412 | 30724 | zSchema = azArg[++i]; |
| 30413 | 30725 | }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){ |
| 30414 | 30726 | nSkip = integerValue(azArg[++i]); |
| 30415 | 30727 | }else if( cli_strcmp(z,"-ascii")==0 ){ |
| 30416 | - sCtx.cColSep = SEP_Unit[0]; | |
| 30417 | - sCtx.cRowSep = SEP_Record[0]; | |
| 30728 | + if( sCtx.cColSep==0 ) sCtx.cColSep = SEP_Unit[0]; | |
| 30729 | + if( sCtx.cRowSep==0 ) sCtx.cRowSep = SEP_Record[0]; | |
| 30418 | 30730 | xRead = ascii_read_one_field; |
| 30419 | - useOutputMode = 0; | |
| 30420 | 30731 | }else if( cli_strcmp(z,"-csv")==0 ){ |
| 30421 | - sCtx.cColSep = ','; | |
| 30422 | - sCtx.cRowSep = '\n'; | |
| 30732 | + if( sCtx.cColSep==0 ) sCtx.cColSep = ','; | |
| 30733 | + if( sCtx.cRowSep==0 ) sCtx.cRowSep = '\n'; | |
| 30423 | 30734 | xRead = csv_read_one_field; |
| 30424 | - useOutputMode = 0; | |
| 30735 | + }else if( cli_strcmp(z,"-esc")==0 ){ | |
| 30736 | + sCtx.cUQEscape = azArg[++i][0]; | |
| 30737 | + }else if( cli_strcmp(z,"-qesc")==0 ){ | |
| 30738 | + sCtx.cQEscape = azArg[++i][0]; | |
| 30739 | + }else if( cli_strcmp(z,"-colsep")==0 ){ | |
| 30740 | + if( i==nArg-1 ){ | |
| 30741 | + dotCmdError(p, i, "missing argument", 0); | |
| 30742 | + return 1; | |
| 30743 | + } | |
| 30744 | + i++; | |
| 30745 | + sCtx.cColSep = azArg[i][0]; | |
| 30746 | + }else if( cli_strcmp(z,"-rowsep")==0 ){ | |
| 30747 | + if( i==nArg-1 ){ | |
| 30748 | + dotCmdError(p, i, "missing argument", 0); | |
| 30749 | + return 1; | |
| 30750 | + } | |
| 30751 | + i++; | |
| 30752 | + sCtx.cRowSep = azArg[i][0]; | |
| 30425 | 30753 | }else{ |
| 30426 | 30754 | dotCmdError(p, i, "unknown option", 0); |
| 30427 | 30755 | return 1; |
| 30428 | 30756 | } |
| 30429 | 30757 | } |
| 30430 | 30758 | if( zTable==0 ){ |
| 30431 | - cli_printf(p->out, "ERROR: missing %s argument\n", | |
| 30759 | + dotCmdError(p, nArg, 0, "Missing %s argument\n", | |
| 30432 | 30760 | zFile==0 ? "FILE" : "TABLE"); |
| 30433 | 30761 | return 1; |
| 30434 | 30762 | } |
| 30435 | 30763 | seenInterrupt = 0; |
| 30436 | 30764 | open_db(p, 0); |
| 30437 | - if( useOutputMode ){ | |
| 30438 | - /* If neither the --csv or --ascii options are specified, then set | |
| 30439 | - ** the column and row separator characters from the output mode. */ | |
| 30440 | - if( p->mode.spec.zColumnSep==0 ){ | |
| 30441 | - modeSetStr(&p->mode.spec.zColumnSep, ","); | |
| 30442 | - nSep = 1; | |
| 30443 | - }else if( (nSep = strlen30(p->mode.spec.zColumnSep))==0 ){ | |
| 30444 | - eputz("Error: non-null column separator required for import\n"); | |
| 30445 | - return 1; | |
| 30446 | - } | |
| 30447 | - if( nSep>1 ){ | |
| 30448 | - eputz("Error: multi-character column separators not allowed" | |
| 30449 | - " for import\n"); | |
| 30450 | - return 1; | |
| 30451 | - } | |
| 30452 | - if( p->mode.spec.zRowSep==0 ){ | |
| 30453 | - modeSetStr(&p->mode.spec.zRowSep, "\n"); | |
| 30454 | - nSep = 1; | |
| 30455 | - }else if( (nSep = strlen30(p->mode.spec.zRowSep))==0 ){ | |
| 30456 | - eputz("Error: non-null row separator required for import\n"); | |
| 30457 | - return 1; | |
| 30458 | - } | |
| 30459 | - if( nSep==2 && p->mode.eMode==MODE_Csv | |
| 30460 | - && cli_strcmp(p->mode.spec.zRowSep,SEP_CrLf)==0 | |
| 30461 | - ){ | |
| 30462 | - /* When importing CSV (only), if the row separator is set to the | |
| 30463 | - ** default output row separator, change it to the default input | |
| 30464 | - ** row separator. This avoids having to maintain different input | |
| 30465 | - ** and output row separators. */ | |
| 30466 | - modeSetStr(&p->mode.spec.zRowSep, SEP_Row); | |
| 30467 | - nSep = strlen30(p->mode.spec.zRowSep); | |
| 30468 | - } | |
| 30469 | - if( nSep>1 ){ | |
| 30470 | - eputz("Error: multi-character row separators not allowed" | |
| 30471 | - " for import\n"); | |
| 30472 | - return 1; | |
| 30473 | - } | |
| 30474 | - sCtx.cColSep = (u8)p->mode.spec.zColumnSep[0]; | |
| 30475 | - sCtx.cRowSep = (u8)p->mode.spec.zRowSep[0]; | |
| 30765 | + if( sCtx.cColSep==0 ){ | |
| 30766 | + if( p->mode.spec.zColumnSep && p->mode.spec.zColumnSep[0]!=0 ){ | |
| 30767 | + sCtx.cColSep = p->mode.spec.zColumnSep[0]; | |
| 30768 | + }else{ | |
| 30769 | + sCtx.cColSep = ','; | |
| 30770 | + } | |
| 30771 | + } | |
| 30772 | + if( (sCtx.cColSep & 0x80)!=0 ){ | |
| 30773 | + eputz("Error: .import column separator must be ASCII\n"); | |
| 30774 | + return 1; | |
| 30775 | + } | |
| 30776 | + if( sCtx.cRowSep==0 ){ | |
| 30777 | + if( p->mode.spec.zRowSep && p->mode.spec.zRowSep[0]!=0 ){ | |
| 30778 | + sCtx.cRowSep = p->mode.spec.zRowSep[0]; | |
| 30779 | + }else{ | |
| 30780 | + sCtx.cRowSep = '\n'; | |
| 30781 | + } | |
| 30782 | + } | |
| 30783 | + if( sCtx.cRowSep=='\r' && xRead!=ascii_read_one_field ){ | |
| 30784 | + sCtx.cRowSep = '\n'; | |
| 30785 | + } | |
| 30786 | + if( (sCtx.cRowSep & 0x80)!=0 ){ | |
| 30787 | + eputz("Error: .import row separator must be ASCII\n"); | |
| 30788 | + return 1; | |
| 30476 | 30789 | } |
| 30477 | 30790 | sCtx.zFile = zFile; |
| 30478 | 30791 | sCtx.nLine = 1; |
| 30479 | 30792 | if( sCtx.zFile[0]=='|' ){ |
| 30480 | 30793 | #ifdef SQLITE_OMIT_POPEN |
| @@ -30483,19 +30796,58 @@ | ||
| 30483 | 30796 | #else |
| 30484 | 30797 | sCtx.in = sqlite3_popen(sCtx.zFile+1, "r"); |
| 30485 | 30798 | sCtx.zFile = "<pipe>"; |
| 30486 | 30799 | sCtx.xCloser = pclose; |
| 30487 | 30800 | #endif |
| 30801 | + }else if( sCtx.zFile[0]=='<' && sCtx.zFile[1]=='<' && sCtx.zFile[2]!=0 ){ | |
| 30802 | + /* Input text comes from subsequent lines of script until the zFile | |
| 30803 | + ** delimiter */ | |
| 30804 | + int nEndMark = strlen30(zFile)-2; | |
| 30805 | + char *zEndMark = &zFile[2]; | |
| 30806 | + sqlite3_str *pContent = sqlite3_str_new(p->db); | |
| 30807 | + int ckEnd = 1; | |
| 30808 | + i64 iStart = p->lineno; | |
| 30809 | + char zLine[2000]; | |
| 30810 | + sCtx.zFile = p->zInFile; | |
| 30811 | + sCtx.nLine = p->lineno+1; | |
| 30812 | + iLineOffset = p->lineno; | |
| 30813 | + while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){ | |
| 30814 | + if( ckEnd && cli_strncmp(zLine,zEndMark,nEndMark)==0 ){ | |
| 30815 | + ckEnd = 2; | |
| 30816 | + if( strchr(zLine,'\n') ) p->lineno++; | |
| 30817 | + break; | |
| 30818 | + } | |
| 30819 | + if( strchr(zLine,'\n') ){ | |
| 30820 | + p->lineno++; | |
| 30821 | + ckEnd = 1; | |
| 30822 | + }else{ | |
| 30823 | + ckEnd = 0; | |
| 30824 | + } | |
| 30825 | + sqlite3_str_appendall(pContent, zLine); | |
| 30826 | + } | |
| 30827 | + sCtx.zIn = sqlite3_str_finish(pContent); | |
| 30828 | + if( sCtx.zIn==0 ){ | |
| 30829 | + sCtx.zIn = sqlite3_mprintf(""); | |
| 30830 | + } | |
| 30831 | + if( ckEnd<2 ){ | |
| 30832 | + i64 savedLn = p->lineno; | |
| 30833 | + p->lineno = iStart; | |
| 30834 | + dotCmdError(p, 0, 0,"Content terminator \"%s\" not found.",zEndMark); | |
| 30835 | + p->lineno = savedLn; | |
| 30836 | + import_cleanup(&sCtx); | |
| 30837 | + return 1; | |
| 30838 | + } | |
| 30488 | 30839 | }else{ |
| 30489 | 30840 | sCtx.in = sqlite3_fopen(sCtx.zFile, "rb"); |
| 30490 | 30841 | sCtx.xCloser = fclose; |
| 30491 | 30842 | } |
| 30492 | - if( sCtx.in==0 ){ | |
| 30493 | - cli_printf(stderr,"Error: cannot open \"%s\"\n", zFile); | |
| 30843 | + if( sCtx.in==0 && sCtx.zIn==0 ){ | |
| 30844 | + dotCmdError(p, 0, 0, "cannot open \"%s\"", zFile); | |
| 30845 | + import_cleanup(&sCtx); | |
| 30494 | 30846 | return 1; |
| 30495 | 30847 | } |
| 30496 | - if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){ | |
| 30848 | + if( eVerbose>=1 ){ | |
| 30497 | 30849 | char zSep[2]; |
| 30498 | 30850 | zSep[1] = 0; |
| 30499 | 30851 | zSep[0] = sCtx.cColSep; |
| 30500 | 30852 | cli_puts("Column separator ", p->out); |
| 30501 | 30853 | output_c_string(p->out, zSep); |
| @@ -30648,10 +31000,14 @@ | ||
| 30648 | 31000 | if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){ |
| 30649 | 31001 | z = ""; |
| 30650 | 31002 | } |
| 30651 | 31003 | sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); |
| 30652 | 31004 | if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){ |
| 31005 | + if( i==0 && (strcmp(z,"\n")==0 || strcmp(z,"\r\n")==0) ){ | |
| 31006 | + /* Ignore trailing \n or \r\n when some other row separator */ | |
| 31007 | + break; | |
| 31008 | + } | |
| 30653 | 31009 | cli_printf(stderr,"%s:%d: expected %d columns but found %d" |
| 30654 | 31010 | " - filling the rest with NULL\n", |
| 30655 | 31011 | sCtx.zFile, startLine, nCol, i+1); |
| 30656 | 31012 | i += 2; |
| 30657 | 31013 | while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; } |
| @@ -30671,10 +31027,11 @@ | ||
| 30671 | 31027 | rc = sqlite3_reset(pStmt); |
| 30672 | 31028 | if( rc!=SQLITE_OK ){ |
| 30673 | 31029 | cli_printf(stderr,"%s:%d: INSERT failed: %s\n", |
| 30674 | 31030 | sCtx.zFile, startLine, sqlite3_errmsg(p->db)); |
| 30675 | 31031 | sCtx.nErr++; |
| 31032 | + if( bail_on_error ) break; | |
| 30676 | 31033 | }else{ |
| 30677 | 31034 | sCtx.nRow++; |
| 30678 | 31035 | } |
| 30679 | 31036 | } |
| 30680 | 31037 | }while( sCtx.cTerm!=EOF ); |
| @@ -30683,13 +31040,13 @@ | ||
| 30683 | 31040 | sqlite3_finalize(pStmt); |
| 30684 | 31041 | if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); |
| 30685 | 31042 | if( eVerbose>0 ){ |
| 30686 | 31043 | cli_printf(p->out, |
| 30687 | 31044 | "Added %d rows with %d errors using %d lines of input\n", |
| 30688 | - sCtx.nRow, sCtx.nErr, sCtx.nLine-1); | |
| 31045 | + sCtx.nRow, sCtx.nErr, sCtx.nLine-1-iLineOffset); | |
| 30689 | 31046 | } |
| 30690 | - return 0; | |
| 31047 | + return sCtx.nErr ? 1 : 0; | |
| 30691 | 31048 | } |
| 30692 | 31049 | |
| 30693 | 31050 | |
| 30694 | 31051 | /* |
| 30695 | 31052 | ** This function computes what to show the user about the configured |
| @@ -31100,10 +31457,11 @@ | ||
| 31100 | 31457 | if( k<0 ){ |
| 31101 | 31458 | dotCmdError(p, i, "bad --titles value","%z", zErr); |
| 31102 | 31459 | return 1; |
| 31103 | 31460 | } |
| 31104 | 31461 | p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No; |
| 31462 | + p->mode.mFlags &= ~MFLG_HDR; | |
| 31105 | 31463 | p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr; |
| 31106 | 31464 | chng = 1; |
| 31107 | 31465 | }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){ |
| 31108 | 31466 | int nWidth = 0; |
| 31109 | 31467 | short int *aWidth; |
| @@ -31328,23 +31686,17 @@ | ||
| 31328 | 31686 | ** --bom Prepend a byte-order mark to the output |
| 31329 | 31687 | ** -e Accumulate output in a temporary text file then |
| 31330 | 31688 | ** launch a text editor when the redirection ends. |
| 31331 | 31689 | ** --error-prefix X Use X as the left-margin prefix for error messages. |
| 31332 | 31690 | ** Set to an empty string to restore the default. |
| 31333 | -** --glob GLOB Raise an error if the memory buffer does not match | |
| 31334 | -** the GLOB pattern. | |
| 31335 | -** --keep Continue using the same "memory" buffer. Do not | |
| 31336 | -** reset it or delete it. Useful in combination with | |
| 31337 | -** --glob, --not-glob, and/or --verify. | |
| 31338 | -** ---notglob GLOB Raise an error if the memory buffer does not match | |
| 31339 | -** the GLOB pattern. | |
| 31691 | +** --keep Keep redirecting output to its current destination. | |
| 31692 | +** Use this option in combination with --show or | |
| 31693 | +** with --error-prefix when you do not want to stop | |
| 31694 | +** a current redirection. | |
| 31340 | 31695 | ** --plain Use plain text rather than HTML tables with -w |
| 31341 | -** --show Write the memory buffer to the screen, for debugging. | |
| 31342 | -** --verify ENDMARK Read subsequent lines of text until the first line | |
| 31343 | -** that matches ENDMARK. Discard the ENDMARK. Compare | |
| 31344 | -** the text against the accumulated output in memory and | |
| 31345 | -** raise an error if there are any differences. | |
| 31696 | +** --show Show output text captured by .testcase or by | |
| 31697 | +** redirecting to "memory". | |
| 31346 | 31698 | ** -w Show the output in a web browser. Output is |
| 31347 | 31699 | ** written into a temporary HTML file until the |
| 31348 | 31700 | ** redirect ends, then the web browser is launched. |
| 31349 | 31701 | ** Query results are shown as HTML tables, unless |
| 31350 | 31702 | ** the --plain is used too. |
| @@ -31382,13 +31734,11 @@ | ||
| 31382 | 31734 | char *zFile = 0; /* The FILE argument */ |
| 31383 | 31735 | int i; /* Loop counter */ |
| 31384 | 31736 | int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */ |
| 31385 | 31737 | int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */ |
| 31386 | 31738 | int bPlain = 0; /* --plain option */ |
| 31387 | - int bKeep = 0; /* --keep option */ | |
| 31388 | - char *zCheck = 0; /* Argument to --glob, --notglob, --verify */ | |
| 31389 | - int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --verify */ | |
| 31739 | + int bKeep = 0; /* Keep redirecting */ | |
| 31390 | 31740 | static const char *zBomUtf8 = "\357\273\277"; |
| 31391 | 31741 | const char *zBom = 0; |
| 31392 | 31742 | char c = azArg[0][0]; |
| 31393 | 31743 | int n = strlen30(azArg[0]); |
| 31394 | 31744 | |
| @@ -31410,36 +31760,21 @@ | ||
| 31410 | 31760 | zBom = zBomUtf8; |
| 31411 | 31761 | }else if( cli_strcmp(z,"-plain")==0 ){ |
| 31412 | 31762 | bPlain = 1; |
| 31413 | 31763 | }else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0 |
| 31414 | 31764 | && (z[1]=='x' || z[1]=='e' || z[1]=='w') ){ |
| 31415 | - if( bKeep || eMode || eCheck ){ | |
| 31765 | + if( bKeep || eMode ){ | |
| 31416 | 31766 | dotCmdError(p, i, "incompatible with prior options",0); |
| 31417 | 31767 | goto dotCmdOutput_error; |
| 31418 | 31768 | } |
| 31419 | 31769 | eMode = z[1]; |
| 31420 | - }else if( cli_strcmp(z,"-keep")==0 ){ | |
| 31421 | - bKeep = 1; | |
| 31422 | 31770 | }else if( cli_strcmp(z,"-show")==0 ){ |
| 31423 | 31771 | if( cli_output_capture ){ |
| 31424 | 31772 | sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture)); |
| 31425 | 31773 | } |
| 31774 | + }else if( cli_strcmp(z,"-keep")==0 ){ | |
| 31426 | 31775 | bKeep = 1; |
| 31427 | - }else if( cli_strcmp(z,"-glob")==0 | |
| 31428 | - || cli_strcmp(z,"-notglob")==0 | |
| 31429 | - || cli_strcmp(z,"-verify")==0 | |
| 31430 | - ){ | |
| 31431 | - if( eCheck || eMode ){ | |
| 31432 | - dotCmdError(p, i, "incompatible with prior options",0); | |
| 31433 | - goto dotCmdOutput_error; | |
| 31434 | - } | |
| 31435 | - if( i+1>=nArg ){ | |
| 31436 | - dotCmdError(p, i, "missing argument", 0); | |
| 31437 | - goto dotCmdOutput_error; | |
| 31438 | - } | |
| 31439 | - zCheck = azArg[++i]; | |
| 31440 | - eCheck = z[1]=='g' ? 1 : z[1]=='n' ? 2 : 3; | |
| 31441 | 31776 | }else if( optionMatch(z,"error-prefix") ){ |
| 31442 | 31777 | if( i+1>=nArg ){ |
| 31443 | 31778 | dotCmdError(p, i, "missing argument", 0); |
| 31444 | 31779 | return 1; |
| 31445 | 31780 | } |
| @@ -31450,11 +31785,11 @@ | ||
| 31450 | 31785 | dotCmdError(p, i, "unknown option", 0); |
| 31451 | 31786 | sqlite3_free(zFile); |
| 31452 | 31787 | return 1; |
| 31453 | 31788 | } |
| 31454 | 31789 | }else if( zFile==0 && eMode==0 ){ |
| 31455 | - if( bKeep || eCheck ){ | |
| 31790 | + if( bKeep ){ | |
| 31456 | 31791 | dotCmdError(p, i, "incompatible with prior options",0); |
| 31457 | 31792 | goto dotCmdOutput_error; |
| 31458 | 31793 | } |
| 31459 | 31794 | if( cli_strcmp(z, "memory")==0 && bOnce ){ |
| 31460 | 31795 | dotCmdError(p, 0, "cannot redirect to \"memory\"", 0); |
| @@ -31486,53 +31821,10 @@ | ||
| 31486 | 31821 | if( bOnce ){ |
| 31487 | 31822 | p->nPopOutput = 2; |
| 31488 | 31823 | }else{ |
| 31489 | 31824 | p->nPopOutput = 0; |
| 31490 | 31825 | } |
| 31491 | - if( eCheck ){ | |
| 31492 | - char *zTest; | |
| 31493 | - if( cli_output_capture ){ | |
| 31494 | - zTest = sqlite3_str_value(cli_output_capture); | |
| 31495 | - }else{ | |
| 31496 | - zTest = ""; | |
| 31497 | - } | |
| 31498 | - p->nTestRun++; | |
| 31499 | - if( eCheck==3 ){ | |
| 31500 | - int nCheck = strlen30(zCheck); | |
| 31501 | - sqlite3_str *pPattern = sqlite3_str_new(p->db); | |
| 31502 | - char *zPattern; | |
| 31503 | - sqlite3_int64 iStart = p->lineno; | |
| 31504 | - char zLine[2000]; | |
| 31505 | - while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){ | |
| 31506 | - if( strchr(zLine,'\n') ) p->lineno++; | |
| 31507 | - if( cli_strncmp(zCheck,zLine,nCheck)==0 ) break; | |
| 31508 | - sqlite3_str_appendall(pPattern, zLine); | |
| 31509 | - } | |
| 31510 | - zPattern = sqlite3_str_finish(pPattern); | |
| 31511 | - if( cli_strcmp(zPattern,zTest)!=0 ){ | |
| 31512 | - sqlite3_fprintf(stderr, | |
| 31513 | - "%s:%lld: --verify does matches prior output\n", | |
| 31514 | - p->zInFile, iStart); | |
| 31515 | - p->nTestErr++; | |
| 31516 | - } | |
| 31517 | - sqlite3_free(zPattern); | |
| 31518 | - }else{ | |
| 31519 | - char *zGlob = sqlite3_mprintf("*%s*", zCheck); | |
| 31520 | - if( eCheck==1 && sqlite3_strglob(zGlob, zTest)!=0 ){ | |
| 31521 | - sqlite3_fprintf(stderr, | |
| 31522 | - "%s:%lld: --glob \"%s\" does not match prior output\n", | |
| 31523 | - p->zInFile, p->lineno, zCheck); | |
| 31524 | - p->nTestErr++; | |
| 31525 | - }else if( eCheck==2 && sqlite3_strglob(zGlob, zTest)==0 ){ | |
| 31526 | - sqlite3_fprintf(stderr, | |
| 31527 | - "%s:%lld: --notglob \"%s\" matches prior output\n", | |
| 31528 | - p->zInFile, p->lineno, zCheck); | |
| 31529 | - p->nTestErr++; | |
| 31530 | - } | |
| 31531 | - sqlite3_free(zGlob); | |
| 31532 | - } | |
| 31533 | - } | |
| 31534 | 31826 | if( !bKeep ) output_reset(p); |
| 31535 | 31827 | #ifndef SQLITE_NOHAVE_SYSTEM |
| 31536 | 31828 | if( eMode=='e' || eMode=='x' || eMode=='w' ){ |
| 31537 | 31829 | p->doXdgOpen = 1; |
| 31538 | 31830 | modePush(p); |
| @@ -31609,10 +31901,199 @@ | ||
| 31609 | 31901 | |
| 31610 | 31902 | dotCmdOutput_error: |
| 31611 | 31903 | sqlite3_free(zFile); |
| 31612 | 31904 | return 1; |
| 31613 | 31905 | } |
| 31906 | + | |
| 31907 | +/* | |
| 31908 | +** DOT-COMMAND: .check | |
| 31909 | +** USAGE: .check [OPTIONS] PATTERN | |
| 31910 | +** | |
| 31911 | +** Verify results of commands since the most recent .testcase command. | |
| 31912 | +** Restore output to the console, unless --keep is used. | |
| 31913 | +** | |
| 31914 | +** If PATTERN starts with "<<ENDMARK" then the actual pattern is taken from | |
| 31915 | +** subsequent lines of text up to the first line that begins with ENDMARK. | |
| 31916 | +** All pattern lines and the ENDMARK are discarded. | |
| 31917 | +** | |
| 31918 | +** Options: | |
| 31919 | +** --exact Do an exact comparison including leading and | |
| 31920 | +** trailing whitespace. | |
| 31921 | +** --glob Treat PATTERN as a GLOB | |
| 31922 | +** --keep Do not reset the testcase. More .check commands | |
| 31923 | +** will follow. | |
| 31924 | +** --notglob Output should not match PATTERN | |
| 31925 | +** --show Write testcase output to the screen, for debugging. | |
| 31926 | +*/ | |
| 31927 | +static int dotCmdCheck(ShellState *p){ | |
| 31928 | + int nArg = p->dot.nArg; /* Number of arguments */ | |
| 31929 | + char **azArg = p->dot.azArg; /* Text of the arguments */ | |
| 31930 | + int i; /* Loop counter */ | |
| 31931 | + int k; /* Result of pickStr() */ | |
| 31932 | + char *zTest; /* Textcase result */ | |
| 31933 | + int bKeep = 0; /* --keep option */ | |
| 31934 | + char *zCheck = 0; /* PATTERN argument */ | |
| 31935 | + char *zPattern = 0; /* Actual test pattern */ | |
| 31936 | + int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --exact */ | |
| 31937 | + int isOk; /* True if results are OK */ | |
| 31938 | + sqlite3_int64 iStart = p->lineno; /* Line number of .check statement */ | |
| 31939 | + | |
| 31940 | + if( p->zTestcase[0]==0 ){ | |
| 31941 | + dotCmdError(p, 0, "no .testcase is active", 0); | |
| 31942 | + return 1; | |
| 31943 | + } | |
| 31944 | + for(i=1; i<nArg; i++){ | |
| 31945 | + char *z = azArg[i]; | |
| 31946 | + if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++; | |
| 31947 | + if( cli_strcmp(z,"-keep")==0 ){ | |
| 31948 | + bKeep = 1; | |
| 31949 | + }else if( cli_strcmp(z,"-show")==0 ){ | |
| 31950 | + if( cli_output_capture ){ | |
| 31951 | + sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture)); | |
| 31952 | + } | |
| 31953 | + bKeep = 1; | |
| 31954 | + }else if( z[0]=='-' | |
| 31955 | + && (k = pickStr(&z[1],0,"glob","notglob","exact",""))>=0 | |
| 31956 | + ){ | |
| 31957 | + if( eCheck && eCheck!=k+1 ){ | |
| 31958 | + dotCmdError(p, i, "incompatible with prior options",0); | |
| 31959 | + return 1; | |
| 31960 | + } | |
| 31961 | + eCheck = k+1; | |
| 31962 | + }else if( zCheck ){ | |
| 31963 | + dotCmdError(p, i, "unknown option", 0); | |
| 31964 | + return 1; | |
| 31965 | + }else{ | |
| 31966 | + zCheck = azArg[i]; | |
| 31967 | + } | |
| 31968 | + } | |
| 31969 | + if( zCheck==0 ){ | |
| 31970 | + dotCmdError(p, 0, "no PATTERN specified", 0); | |
| 31971 | + return 1; | |
| 31972 | + } | |
| 31973 | + if( cli_output_capture && sqlite3_str_length(cli_output_capture) ){ | |
| 31974 | + zTest = sqlite3_str_value(cli_output_capture); | |
| 31975 | + shell_check_oom(zTest); | |
| 31976 | + }else{ | |
| 31977 | + zTest = ""; | |
| 31978 | + } | |
| 31979 | + p->nTestRun++; | |
| 31980 | + if( zCheck[0]=='<' && zCheck[1]=='<' && zCheck[2]!=0 ){ | |
| 31981 | + int nCheck = strlen30(zCheck); | |
| 31982 | + sqlite3_str *pPattern = sqlite3_str_new(p->db); | |
| 31983 | + char zLine[2000]; | |
| 31984 | + while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){ | |
| 31985 | + if( strchr(zLine,'\n') ) p->lineno++; | |
| 31986 | + if( cli_strncmp(&zCheck[2],zLine,nCheck-2)==0 ) break; | |
| 31987 | + sqlite3_str_appendall(pPattern, zLine); | |
| 31988 | + } | |
| 31989 | + zPattern = sqlite3_str_finish(pPattern); | |
| 31990 | + if( zPattern==0 ){ | |
| 31991 | + zPattern = sqlite3_mprintf(""); | |
| 31992 | + } | |
| 31993 | + }else{ | |
| 31994 | + zPattern = zCheck; | |
| 31995 | + } | |
| 31996 | + shell_check_oom(zPattern); | |
| 31997 | + switch( eCheck ){ | |
| 31998 | + case 1: { | |
| 31999 | + char *zGlob = sqlite3_mprintf("*%s*", zPattern); | |
| 32000 | + isOk = testcase_glob(zGlob, zTest)!=0; | |
| 32001 | + sqlite3_free(zGlob); | |
| 32002 | + break; | |
| 32003 | + } | |
| 32004 | + case 2: { | |
| 32005 | + char *zGlob = sqlite3_mprintf("*%s*", zPattern); | |
| 32006 | + isOk = testcase_glob(zGlob, zTest)==0; | |
| 32007 | + sqlite3_free(zGlob); | |
| 32008 | + break; | |
| 32009 | + } | |
| 32010 | + case 3: { | |
| 32011 | + isOk = cli_strcmp(zTest,zPattern)==0; | |
| 32012 | + break; | |
| 32013 | + } | |
| 32014 | + default: { | |
| 32015 | + /* Skip leading and trailing \n and \r on both pattern and test output */ | |
| 32016 | + const char *z1 = zPattern; | |
| 32017 | + const char *z2 = zTest; | |
| 32018 | + size_t n1, n2; | |
| 32019 | + while( z1[0]=='\n' || z1[0]=='\r' ) z1++; | |
| 32020 | + n1 = strlen(z1); | |
| 32021 | + while( n1>0 && (z1[n1-1]=='\n' || z1[n1-1]=='\r') ) n1--; | |
| 32022 | + while( z2[0]=='\n' || z2[0]=='\r' ) z2++; | |
| 32023 | + n2 = strlen(z2); | |
| 32024 | + while( n2>0 && (z2[n2-1]=='\n' || z2[n2-1]=='\r') ) n2--; | |
| 32025 | + isOk = n1==n2 && memcmp(z1,z2,n1)==0; | |
| 32026 | + break; | |
| 32027 | + } | |
| 32028 | + } | |
| 32029 | + if( !isOk ){ | |
| 32030 | + sqlite3_fprintf(stderr, | |
| 32031 | + "%s:%lld: .check failed for testcase %s\n", | |
| 32032 | + p->zInFile, iStart, p->zTestcase); | |
| 32033 | + p->nTestErr++; | |
| 32034 | + sqlite3_fprintf(stderr, "Expected: [%s]\n", zPattern); | |
| 32035 | + sqlite3_fprintf(stderr, "Got: [%s]\n", zTest); | |
| 32036 | + } | |
| 32037 | + if( zPattern!=zCheck ){ | |
| 32038 | + sqlite3_free(zPattern); | |
| 32039 | + } | |
| 32040 | + if( !bKeep ){ | |
| 32041 | + output_reset(p); | |
| 32042 | + p->zTestcase[0] = 0; | |
| 32043 | + } | |
| 32044 | + return 0; | |
| 32045 | +} | |
| 32046 | + | |
| 32047 | +/* | |
| 32048 | +** DOT-COMMAND: .testcase | |
| 32049 | +** USAGE: .testcase [OPTIONS] NAME | |
| 32050 | +** | |
| 32051 | +** Start a new test case identified by NAME. All output | |
| 32052 | +** through the next ".check" command is captured for comparison. See the | |
| 32053 | +** ".check" commandn for additional informatioon. | |
| 32054 | +** | |
| 32055 | +** Options: | |
| 32056 | +** --error-prefix TEXT Change error message prefix text to TEXT | |
| 32057 | +*/ | |
| 32058 | +static int dotCmdTestcase(ShellState *p){ | |
| 32059 | + int nArg = p->dot.nArg; /* Number of arguments */ | |
| 32060 | + char **azArg = p->dot.azArg; /* Text of the arguments */ | |
| 32061 | + int i; /* Loop counter */ | |
| 32062 | + const char *zName = 0; /* Testcase name */ | |
| 32063 | + | |
| 32064 | + for(i=1; i<nArg; i++){ | |
| 32065 | + char *z = azArg[i]; | |
| 32066 | + if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++; | |
| 32067 | + if( optionMatch(z,"error-prefix") ){ | |
| 32068 | + if( i+1>=nArg ){ | |
| 32069 | + dotCmdError(p, i, "missing argument", 0); | |
| 32070 | + return 1; | |
| 32071 | + } | |
| 32072 | + free(p->zErrPrefix); | |
| 32073 | + i++; | |
| 32074 | + p->zErrPrefix = azArg[i][0]==0 ? 0 : strdup(azArg[i]); | |
| 32075 | + }else if( zName ){ | |
| 32076 | + dotCmdError(p, i, "unknown option", 0); | |
| 32077 | + return 1; | |
| 32078 | + }else{ | |
| 32079 | + zName = azArg[i]; | |
| 32080 | + } | |
| 32081 | + } | |
| 32082 | + output_reset(p); | |
| 32083 | + if( cli_output_capture ){ | |
| 32084 | + sqlite3_str_free(cli_output_capture); | |
| 32085 | + } | |
| 32086 | + cli_output_capture = sqlite3_str_new(0); | |
| 32087 | + if( zName ){ | |
| 32088 | + sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", zName); | |
| 32089 | + }else{ | |
| 32090 | + sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s:%lld", | |
| 32091 | + p->zInFile, p->lineno); | |
| 32092 | + } | |
| 32093 | + return 0; | |
| 32094 | +} | |
| 31614 | 32095 | |
| 31615 | 32096 | /* |
| 31616 | 32097 | ** Enlarge the space allocated in p->dot so that it can hold more |
| 31617 | 32098 | ** than nArg parsed command-line arguments. |
| 31618 | 32099 | */ |
| @@ -31641,11 +32122,11 @@ | ||
| 31641 | 32122 | free(p->dot.zCopy); |
| 31642 | 32123 | z = p->dot.zCopy = strdup(zLine); |
| 31643 | 32124 | shell_check_oom(z); |
| 31644 | 32125 | szLine = strlen(z); |
| 31645 | 32126 | while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--; |
| 31646 | - if( szLine>0 && z[szLine-1]==';' && p->iCompat>=20251115 ){ | |
| 32127 | + if( szLine>0 && z[szLine-1]==';' ){ | |
| 31647 | 32128 | szLine--; |
| 31648 | 32129 | while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--; |
| 31649 | 32130 | } |
| 31650 | 32131 | z[szLine] = 0; |
| 31651 | 32132 | parseDotRealloc(p, 2); |
| @@ -31861,35 +32342,17 @@ | ||
| 31861 | 32342 | eputz("Usage: .changes on|off\n"); |
| 31862 | 32343 | rc = 1; |
| 31863 | 32344 | } |
| 31864 | 32345 | }else |
| 31865 | 32346 | |
| 31866 | -#ifndef SQLITE_SHELL_FIDDLE | |
| 31867 | 32347 | /* Cancel output redirection, if it is currently set (by .testcase) |
| 31868 | 32348 | ** Then read the content of the testcase-out.txt file and compare against |
| 31869 | 32349 | ** azArg[1]. If there are differences, report an error and exit. |
| 31870 | 32350 | */ |
| 31871 | 32351 | if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){ |
| 31872 | - char *zRes = 0; | |
| 31873 | - output_reset(p); | |
| 31874 | - if( nArg!=2 ){ | |
| 31875 | - eputz("Usage: .check GLOB-PATTERN\n"); | |
| 31876 | - rc = 2; | |
| 31877 | - }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ | |
| 31878 | - rc = 2; | |
| 31879 | - }else if( testcase_glob(azArg[1],zRes)==0 ){ | |
| 31880 | - cli_printf(stderr, | |
| 31881 | - "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", | |
| 31882 | - p->zTestcase, azArg[1], zRes); | |
| 31883 | - rc = 1; | |
| 31884 | - }else{ | |
| 31885 | - cli_printf(p->out, "testcase-%s ok\n", p->zTestcase); | |
| 31886 | - p->nCheck++; | |
| 31887 | - } | |
| 31888 | - sqlite3_free(zRes); | |
| 32352 | + rc = dotCmdCheck(p); | |
| 31889 | 32353 | }else |
| 31890 | -#endif /* !defined(SQLITE_SHELL_FIDDLE) */ | |
| 31891 | 32354 | |
| 31892 | 32355 | #ifndef SQLITE_SHELL_FIDDLE |
| 31893 | 32356 | if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){ |
| 31894 | 32357 | failIfSafeMode(p, "cannot run .clone in safe mode"); |
| 31895 | 32358 | if( nArg==2 ){ |
| @@ -32468,10 +32931,11 @@ | ||
| 32468 | 32931 | }else |
| 32469 | 32932 | |
| 32470 | 32933 | if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){ |
| 32471 | 32934 | if( nArg==2 ){ |
| 32472 | 32935 | p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No; |
| 32936 | + p->mode.mFlags |= MFLG_HDR; | |
| 32473 | 32937 | p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr; |
| 32474 | 32938 | }else{ |
| 32475 | 32939 | eputz("Usage: .headers on|off\n"); |
| 32476 | 32940 | rc = 1; |
| 32477 | 32941 | } |
| @@ -32521,14 +32985,14 @@ | ||
| 32521 | 32985 | sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); |
| 32522 | 32986 | goto meta_command_exit; |
| 32523 | 32987 | } |
| 32524 | 32988 | zSql = sqlite3_mprintf( |
| 32525 | 32989 | "SELECT rootpage, 0 FROM sqlite_schema" |
| 32526 | - " WHERE name='%q' AND type='index'" | |
| 32990 | + " WHERE type='index' AND lower(name)=lower('%q')" | |
| 32527 | 32991 | "UNION ALL " |
| 32528 | 32992 | "SELECT rootpage, 1 FROM sqlite_schema" |
| 32529 | - " WHERE name='%q' AND type='table'" | |
| 32993 | + " WHERE type='table' AND lower(name)=lower('%q')" | |
| 32530 | 32994 | " AND sql LIKE '%%without%%rowid%%'", |
| 32531 | 32995 | azArg[1], azArg[1] |
| 32532 | 32996 | ); |
| 32533 | 32997 | sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 32534 | 32998 | sqlite3_free(zSql); |
| @@ -32682,13 +33146,14 @@ | ||
| 32682 | 33146 | goto meta_command_exit; |
| 32683 | 33147 | } |
| 32684 | 33148 | if( nArg==3 ){ |
| 32685 | 33149 | sqlite3_limit(p->db, aLimit[iLimit].limitCode, |
| 32686 | 33150 | (int)integerValue(azArg[2])); |
| 33151 | + }else{ | |
| 33152 | + cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName, | |
| 33153 | + sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); | |
| 32687 | 33154 | } |
| 32688 | - cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName, | |
| 32689 | - sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); | |
| 32690 | 33155 | } |
| 32691 | 33156 | }else |
| 32692 | 33157 | |
| 32693 | 33158 | if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){ |
| 32694 | 33159 | open_db(p, 0); |
| @@ -33027,10 +33492,23 @@ | ||
| 33027 | 33492 | continue; |
| 33028 | 33493 | } |
| 33029 | 33494 | if( cli_strcmp(z,"once")==0 ){ |
| 33030 | 33495 | p->flgProgress |= SHELL_PROGRESS_ONCE; |
| 33031 | 33496 | continue; |
| 33497 | + } | |
| 33498 | + if( cli_strcmp(z,"timeout")==0 ){ | |
| 33499 | + if( i==nArg-1 ){ | |
| 33500 | + dotCmdError(p, i, "missing argument", 0); | |
| 33501 | + return 1; | |
| 33502 | + } | |
| 33503 | + i++; | |
| 33504 | + p->tmProgress = atof(azArg[i]); | |
| 33505 | + if( p->tmProgress>0.0 ){ | |
| 33506 | + p->flgProgress = SHELL_PROGRESS_QUIET|SHELL_PROGRESS_TMOUT; | |
| 33507 | + if( nn==0 ) nn = 100; | |
| 33508 | + } | |
| 33509 | + continue; | |
| 33032 | 33510 | } |
| 33033 | 33511 | if( cli_strcmp(z,"limit")==0 ){ |
| 33034 | 33512 | if( i+1>=nArg ){ |
| 33035 | 33513 | eputz("Error: missing argument on --limit\n"); |
| 33036 | 33514 | rc = 1; |
| @@ -33233,21 +33711,22 @@ | ||
| 33233 | 33711 | || sqlite3_strlike(zName, "sqlite_schema", '\\')==0 |
| 33234 | 33712 | || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 |
| 33235 | 33713 | || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0; |
| 33236 | 33714 | if( isSchema ){ |
| 33237 | 33715 | cli_printf(p->out, |
| 33238 | - "CREATE TABLE %s (\n" | |
| 33716 | + "CREATE TABLE %ssqlite_schema (\n" | |
| 33239 | 33717 | " type text,\n" |
| 33240 | 33718 | " name text,\n" |
| 33241 | 33719 | " tbl_name text,\n" |
| 33242 | 33720 | " rootpage integer,\n" |
| 33243 | 33721 | " sql text\n" |
| 33244 | - ");\n", zName); | |
| 33722 | + ");\n", | |
| 33723 | + sqlite3_strlike("sqlite_t%",zName,0)==0 ? "temp." : "" | |
| 33724 | + ); | |
| 33245 | 33725 | } |
| 33246 | 33726 | } |
| 33247 | - rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list", | |
| 33248 | - -1, &pStmt, 0); | |
| 33727 | + rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); | |
| 33249 | 33728 | if( rc ){ |
| 33250 | 33729 | shellDatabaseError(p->db); |
| 33251 | 33730 | sqlite3_finalize(pStmt); |
| 33252 | 33731 | |
| 33253 | 33732 | rc = 1; |
| @@ -33255,11 +33734,11 @@ | ||
| 33255 | 33734 | } |
| 33256 | 33735 | pSql = sqlite3_str_new(p->db); |
| 33257 | 33736 | sqlite3_str_appendf(pSql, "SELECT sql FROM", 0); |
| 33258 | 33737 | iSchema = 0; |
| 33259 | 33738 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 33260 | - const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); | |
| 33739 | + const char *zDb = (const char*)sqlite3_column_text(pStmt, 1); | |
| 33261 | 33740 | char zScNum[30]; |
| 33262 | 33741 | sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); |
| 33263 | 33742 | sqlite3_str_appendall(pSql, zDiv); |
| 33264 | 33743 | zDiv = " UNION ALL "; |
| 33265 | 33744 | if( sqlite3_stricmp(zDb, "main")==0 ){ |
| @@ -33275,11 +33754,12 @@ | ||
| 33275 | 33754 | " AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname", |
| 33276 | 33755 | ++iSchema, zDb); |
| 33277 | 33756 | sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb); |
| 33278 | 33757 | } |
| 33279 | 33758 | sqlite3_finalize(pStmt); |
| 33280 | -#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS | |
| 33759 | +#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) \ | |
| 33760 | + && !defined(SQLITE_OMIT_VIRTUALTABLE) | |
| 33281 | 33761 | if( zName ){ |
| 33282 | 33762 | sqlite3_str_appendall(pSql, |
| 33283 | 33763 | " UNION ALL SELECT shell_module_schema(name)," |
| 33284 | 33764 | " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list"); |
| 33285 | 33765 | } |
| @@ -33299,11 +33779,11 @@ | ||
| 33299 | 33779 | }else{ |
| 33300 | 33780 | sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName); |
| 33301 | 33781 | } |
| 33302 | 33782 | } |
| 33303 | 33783 | if( bNoSystemTabs ){ |
| 33304 | - sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCALE '_' AND "); | |
| 33784 | + sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCAPE '_' AND "); | |
| 33305 | 33785 | } |
| 33306 | 33786 | sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid"); |
| 33307 | 33787 | if( bDebug ){ |
| 33308 | 33788 | cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql)); |
| 33309 | 33789 | }else{ |
| @@ -34017,25 +34497,15 @@ | ||
| 34017 | 34497 | sqlite3_str_free(pSql); |
| 34018 | 34498 | modePop(p); |
| 34019 | 34499 | if( rc ) return shellDatabaseError(p->db); |
| 34020 | 34500 | }else |
| 34021 | 34501 | |
| 34022 | -#ifndef SQLITE_SHELL_FIDDLE | |
| 34023 | - /* Begin redirecting output to the file "testcase-out.txt" */ | |
| 34502 | + /* Set the p->zTestcase name and begin redirecting output into | |
| 34503 | + ** the cli_output_capture sqlite3_str */ | |
| 34024 | 34504 | if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){ |
| 34025 | - output_reset(p); | |
| 34026 | - p->out = output_file_open(p, "testcase-out.txt"); | |
| 34027 | - if( p->out==0 ){ | |
| 34028 | - eputz("Error: cannot open 'testcase-out.txt'\n"); | |
| 34029 | - } | |
| 34030 | - if( nArg>=2 ){ | |
| 34031 | - sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); | |
| 34032 | - }else{ | |
| 34033 | - sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); | |
| 34034 | - } | |
| 34505 | + rc = dotCmdTestcase(p); | |
| 34035 | 34506 | }else |
| 34036 | -#endif /* !defined(SQLITE_SHELL_FIDDLE) */ | |
| 34037 | 34507 | |
| 34038 | 34508 | #ifndef SQLITE_UNTESTABLE |
| 34039 | 34509 | if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){ |
| 34040 | 34510 | static const struct { |
| 34041 | 34511 | const char *zCtrlName; /* Name of a test-control option */ |
| @@ -34527,17 +34997,21 @@ | ||
| 34527 | 34997 | sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); |
| 34528 | 34998 | }else |
| 34529 | 34999 | |
| 34530 | 35000 | if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){ |
| 34531 | 35001 | if( nArg==2 ){ |
| 34532 | - enableTimer = booleanValue(azArg[1]); | |
| 34533 | - if( enableTimer && !HAS_TIMER ){ | |
| 35002 | + if( cli_strcmp(azArg[1],"once")==0 ){ | |
| 35003 | + p->enableTimer = 1; | |
| 35004 | + }else{ | |
| 35005 | + p->enableTimer = 2*booleanValue(azArg[1]); | |
| 35006 | + } | |
| 35007 | + if( p->enableTimer && !HAS_TIMER ){ | |
| 34534 | 35008 | eputz("Error: timer not available on this system.\n"); |
| 34535 | - enableTimer = 0; | |
| 35009 | + p->enableTimer = 0; | |
| 34536 | 35010 | } |
| 34537 | 35011 | }else{ |
| 34538 | - eputz("Usage: .timer on|off\n"); | |
| 35012 | + eputz("Usage: .timer on|off|once\n"); | |
| 34539 | 35013 | rc = 1; |
| 34540 | 35014 | } |
| 34541 | 35015 | }else |
| 34542 | 35016 | |
| 34543 | 35017 | #ifndef SQLITE_OMIT_TRACE |
| @@ -34708,10 +35182,11 @@ | ||
| 34708 | 35182 | if( p->nPopOutput ){ |
| 34709 | 35183 | p->nPopOutput--; |
| 34710 | 35184 | if( p->nPopOutput==0 ) output_reset(p); |
| 34711 | 35185 | } |
| 34712 | 35186 | p->bSafeMode = p->bSafeModePersist; |
| 35187 | + p->dot.nArg = 0; | |
| 34713 | 35188 | return rc; |
| 34714 | 35189 | } |
| 34715 | 35190 | |
| 34716 | 35191 | /* Line scan result and intermediate states (supporting scan resumption) |
| 34717 | 35192 | */ |
| @@ -34944,13 +35419,13 @@ | ||
| 34944 | 35419 | char *zErrMsg = 0; |
| 34945 | 35420 | |
| 34946 | 35421 | open_db(p, 0); |
| 34947 | 35422 | if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql); |
| 34948 | 35423 | if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; |
| 34949 | - BEGIN_TIMER; | |
| 35424 | + BEGIN_TIMER(p); | |
| 34950 | 35425 | rc = shell_exec(p, zSql, &zErrMsg); |
| 34951 | - END_TIMER(p->out); | |
| 35426 | + END_TIMER(p); | |
| 34952 | 35427 | if( rc || zErrMsg ){ |
| 34953 | 35428 | char zPrefix[100]; |
| 34954 | 35429 | const char *zErrorTail; |
| 34955 | 35430 | const char *zErrorType; |
| 34956 | 35431 | if( zErrMsg==0 ){ |
| @@ -35351,11 +35826,10 @@ | ||
| 35351 | 35826 | " -bail stop after hitting an error\n" |
| 35352 | 35827 | " -batch force batch I/O\n" |
| 35353 | 35828 | " -box set output mode to 'box'\n" |
| 35354 | 35829 | " -cmd COMMAND run \"COMMAND\" before reading stdin\n" |
| 35355 | 35830 | " -column set output mode to 'column'\n" |
| 35356 | - " -compat YYYYMMDD set default options for date YYYYMMDD\n" | |
| 35357 | 35831 | " -csv set output mode to 'csv'\n" |
| 35358 | 35832 | #if !defined(SQLITE_OMIT_DESERIALIZE) |
| 35359 | 35833 | " -deserialize open the database using sqlite3_deserialize()\n" |
| 35360 | 35834 | #endif |
| 35361 | 35835 | " -echo print inputs before execution\n" |
| @@ -35435,15 +35909,10 @@ | ||
| 35435 | 35909 | /* |
| 35436 | 35910 | ** Initialize the state information in data |
| 35437 | 35911 | */ |
| 35438 | 35912 | static void main_init(ShellState *p) { |
| 35439 | 35913 | memset(p, 0, sizeof(*p)); |
| 35440 | -#if defined(COMPATIBILITY_DATE) | |
| 35441 | - p->iCompat = COMPATIBILITY_DATE; | |
| 35442 | -#else | |
| 35443 | - p->iCompat = 20251116; | |
| 35444 | -#endif | |
| 35445 | 35914 | p->pAuxDb = &p->aAuxDb[0]; |
| 35446 | 35915 | p->shellFlgs = SHFLG_Lookaside; |
| 35447 | 35916 | sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p); |
| 35448 | 35917 | #if !defined(SQLITE_SHELL_FIDDLE) |
| 35449 | 35918 | verify_uninitialized(); |
| @@ -35498,29 +35967,65 @@ | ||
| 35498 | 35967 | cli_puts(z, p->out); |
| 35499 | 35968 | fflush(p->out); |
| 35500 | 35969 | return 1; |
| 35501 | 35970 | } |
| 35502 | 35971 | |
| 35503 | -#ifndef SQLITE_SHELL_IS_UTF8 | |
| 35504 | -# if (defined(_WIN32) || defined(WIN32)) \ | |
| 35505 | - && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__))) | |
| 35506 | -# define SQLITE_SHELL_IS_UTF8 (0) | |
| 35507 | -# else | |
| 35508 | -# define SQLITE_SHELL_IS_UTF8 (1) | |
| 35509 | -# endif | |
| 35510 | -#endif | |
| 35511 | - | |
| 35972 | +/* Alternative name to the entry point for Fiddle */ | |
| 35512 | 35973 | #ifdef SQLITE_SHELL_FIDDLE |
| 35513 | 35974 | # define main fiddle_main |
| 35514 | 35975 | #endif |
| 35515 | 35976 | |
| 35516 | -#if SQLITE_SHELL_IS_UTF8 | |
| 35517 | -int SQLITE_CDECL main(int argc, char **argv){ | |
| 35518 | -#else | |
| 35977 | +/* Use the wmain() entry point on Windows. Translate arguments to | |
| 35978 | +** UTF8, then invoke the traditional main() entry point which is | |
| 35979 | +** renamed using a #define to utf8_main() . | |
| 35980 | +*/ | |
| 35981 | +#if defined(_WIN32) && !defined(main) | |
| 35982 | +# define main utf8_main /* Rename entry point to utf_main() */ | |
| 35983 | +int SQLITE_CDECL utf8_main(int,char**); /* Forward declaration */ | |
| 35519 | 35984 | int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ |
| 35520 | - char **argv; | |
| 35521 | -#endif | |
| 35985 | + int rc, i; | |
| 35986 | + char **argv = malloc( sizeof(char*) * (argc+1) ); | |
| 35987 | + char **orig = argv; | |
| 35988 | + if( argv==0 ){ | |
| 35989 | + fprintf(stderr, "malloc failed\n"); | |
| 35990 | + exit(1); | |
| 35991 | + } | |
| 35992 | + for(i=0; i<argc; i++){ | |
| 35993 | + int nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, 0, 0, 0, 0); | |
| 35994 | + if( nByte==0 ){ | |
| 35995 | + argv[i] = 0; | |
| 35996 | + }else{ | |
| 35997 | + argv[i] = malloc( nByte ); | |
| 35998 | + if( argv[i]==0 ){ | |
| 35999 | + fprintf(stderr, "malloc failed\n"); | |
| 36000 | + exit(1); | |
| 36001 | + } | |
| 36002 | + nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i],nByte,0,0); | |
| 36003 | + if( nByte==0 ){ | |
| 36004 | + free(argv[i]); | |
| 36005 | + argv[i] = 0; | |
| 36006 | + } | |
| 36007 | + } | |
| 36008 | + } | |
| 36009 | + argv[argc] = 0; | |
| 36010 | + rc = utf8_main(argc, argv); | |
| 36011 | + for(i=0; i<argc; i++) free(orig[i]); | |
| 36012 | + free(argv); | |
| 36013 | + return rc; | |
| 36014 | +} | |
| 36015 | +#endif /* WIN32 */ | |
| 36016 | + | |
| 36017 | +/* | |
| 36018 | +** This is the main entry point for the process. Everything starts here. | |
| 36019 | +** | |
| 36020 | +** The "main" identifier may have been #defined to something else: | |
| 36021 | +** | |
| 36022 | +** utf8_main On Windows | |
| 36023 | +** fiddle_main In Fiddle | |
| 36024 | +** sqlite3_shell Other projects that use shell.c as a subroutine | |
| 36025 | +*/ | |
| 36026 | +int SQLITE_CDECL main(int argc, char **argv){ | |
| 35522 | 36027 | #ifdef SQLITE_DEBUG |
| 35523 | 36028 | sqlite3_int64 mem_main_enter = 0; |
| 35524 | 36029 | #endif |
| 35525 | 36030 | char *zErrMsg = 0; |
| 35526 | 36031 | #ifdef SQLITE_SHELL_FIDDLE |
| @@ -35538,14 +36043,10 @@ | ||
| 35538 | 36043 | int nOptsEnd = argc; |
| 35539 | 36044 | int bEnableVfstrace = 0; |
| 35540 | 36045 | char **azCmd = 0; |
| 35541 | 36046 | int *aiCmd = 0; |
| 35542 | 36047 | const char *zVfs = 0; /* Value of -vfs command-line option */ |
| 35543 | -#if !SQLITE_SHELL_IS_UTF8 | |
| 35544 | - char **argvToFree = 0; | |
| 35545 | - int argcToFree = 0; | |
| 35546 | -#endif | |
| 35547 | 36048 | setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ |
| 35548 | 36049 | |
| 35549 | 36050 | #ifdef SQLITE_SHELL_FIDDLE |
| 35550 | 36051 | stdin_is_interactive = 0; |
| 35551 | 36052 | stdout_is_console = 1; |
| @@ -35596,36 +36097,10 @@ | ||
| 35596 | 36097 | exit(1); |
| 35597 | 36098 | } |
| 35598 | 36099 | #endif |
| 35599 | 36100 | main_init(&data); |
| 35600 | 36101 | |
| 35601 | - /* On Windows, we must translate command-line arguments into UTF-8. | |
| 35602 | - ** The SQLite memory allocator subsystem has to be enabled in order to | |
| 35603 | - ** do this. But we want to run an sqlite3_shutdown() afterwards so that | |
| 35604 | - ** subsequent sqlite3_config() calls will work. So copy all results into | |
| 35605 | - ** memory that does not come from the SQLite memory allocator. | |
| 35606 | - */ | |
| 35607 | -#if !SQLITE_SHELL_IS_UTF8 | |
| 35608 | - sqlite3_initialize(); | |
| 35609 | - argvToFree = malloc(sizeof(argv[0])*argc*2); | |
| 35610 | - shell_check_oom(argvToFree); | |
| 35611 | - argcToFree = argc; | |
| 35612 | - argv = argvToFree + argc; | |
| 35613 | - for(i=0; i<argc; i++){ | |
| 35614 | - char *z = sqlite3_win32_unicode_to_utf8(wargv[i]); | |
| 35615 | - i64 n; | |
| 35616 | - shell_check_oom(z); | |
| 35617 | - n = strlen(z); | |
| 35618 | - argv[i] = malloc( n+1 ); | |
| 35619 | - shell_check_oom(argv[i]); | |
| 35620 | - memcpy(argv[i], z, n+1); | |
| 35621 | - argvToFree[i] = argv[i]; | |
| 35622 | - sqlite3_free(z); | |
| 35623 | - } | |
| 35624 | - sqlite3_shutdown(); | |
| 35625 | -#endif | |
| 35626 | - | |
| 35627 | 36102 | assert( argc>=1 && argv && argv[0] ); |
| 35628 | 36103 | Argv0 = argv[0]; |
| 35629 | 36104 | |
| 35630 | 36105 | #ifdef SQLITE_SHELL_DBNAME_PROC |
| 35631 | 36106 | { |
| @@ -35637,11 +36112,11 @@ | ||
| 35637 | 36112 | SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename); |
| 35638 | 36113 | warnInmemoryDb = 0; |
| 35639 | 36114 | } |
| 35640 | 36115 | #endif |
| 35641 | 36116 | |
| 35642 | - /* Do an initial pass through the command-line argument to locate | |
| 36117 | + /* Do an initial pass through the command-line arguments to locate | |
| 35643 | 36118 | ** the name of the database file, the name of the initialization file, |
| 35644 | 36119 | ** the size of the alternative malloc heap, options affecting commands |
| 35645 | 36120 | ** or SQL run from the command line, and the first command to execute. |
| 35646 | 36121 | */ |
| 35647 | 36122 | #ifndef SQLITE_SHELL_FIDDLE |
| @@ -35649,11 +36124,11 @@ | ||
| 35649 | 36124 | #endif |
| 35650 | 36125 | for(i=1; i<argc; i++){ |
| 35651 | 36126 | char *z; |
| 35652 | 36127 | z = argv[i]; |
| 35653 | 36128 | if( z[0]!='-' || i>nOptsEnd ){ |
| 35654 | - if( data.aAuxDb->zDbFilename==0 ){ | |
| 36129 | + if( data.aAuxDb->zDbFilename==0 && !isScriptFile(z,1) ){ | |
| 35655 | 36130 | data.aAuxDb->zDbFilename = z; |
| 35656 | 36131 | }else{ |
| 35657 | 36132 | /* Excess arguments are interpreted as SQL (or dot-commands) and |
| 35658 | 36133 | ** mean that nothing is read from stdin */ |
| 35659 | 36134 | readStdin = 0; |
| @@ -35694,15 +36169,10 @@ | ||
| 35694 | 36169 | if( n<2 ){ |
| 35695 | 36170 | sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n"); |
| 35696 | 36171 | exit(1); |
| 35697 | 36172 | } |
| 35698 | 36173 | stdout_tty_width = n; |
| 35699 | - }else if( cli_strcmp(z,"-compat")==0 ){ | |
| 35700 | - data.iCompat = atoi(cmdline_option_value(argc, argv, ++i)); | |
| 35701 | - modeFree(&data.mode); | |
| 35702 | - memset(&data.mode, 0, sizeof(data.mode)); | |
| 35703 | - modeDefault(&data); | |
| 35704 | 36174 | }else if( cli_strcmp(z,"-utf8")==0 ){ |
| 35705 | 36175 | }else if( cli_strcmp(z,"-no-utf8")==0 ){ |
| 35706 | 36176 | }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){ |
| 35707 | 36177 | int val = 0; |
| 35708 | 36178 | sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val); |
| @@ -35822,10 +36292,20 @@ | ||
| 35822 | 36292 | }else if( cli_strcmp(z,"-safe")==0 ){ |
| 35823 | 36293 | /* no-op - catch this on the second pass */ |
| 35824 | 36294 | }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ |
| 35825 | 36295 | /* skip over the argument */ |
| 35826 | 36296 | i++; |
| 36297 | + }else if( cli_strcmp(z,"-test-argv")==0 ){ | |
| 36298 | + /* Undocumented test option. Print the values in argv[] and exit. | |
| 36299 | + ** Use this to verify that any translation of the argv[], for example | |
| 36300 | + ** on Windows that receives wargv[] from the OS and must convert | |
| 36301 | + ** to UTF8 prior to calling this routine. */ | |
| 36302 | + int kk; | |
| 36303 | + for(kk=0; kk<argc; kk++){ | |
| 36304 | + sqlite3_fprintf(stdout,"argv[%d] = \"%s\"\n", kk, argv[kk]); | |
| 36305 | + } | |
| 36306 | + return 0; | |
| 35827 | 36307 | } |
| 35828 | 36308 | } |
| 35829 | 36309 | #ifndef SQLITE_SHELL_FIDDLE |
| 35830 | 36310 | if( !bEnableVfstrace ) verify_uninitialized(); |
| 35831 | 36311 | #endif |
| @@ -35848,11 +36328,30 @@ | ||
| 35848 | 36328 | |
| 35849 | 36329 | if( zVfs ){ |
| 35850 | 36330 | sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs); |
| 35851 | 36331 | if( pVfs ){ |
| 35852 | 36332 | sqlite3_vfs_register(pVfs, 1); |
| 35853 | - }else{ | |
| 36333 | + } | |
| 36334 | +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) | |
| 36335 | + else if( access(zVfs,0)==0 ){ | |
| 36336 | + /* If the VFS name is not the name of an existing VFS, but it is | |
| 36337 | + ** the name of a file, then try to load that file as an extension. | |
| 36338 | + ** Presumably the extension implements the desired VFS. */ | |
| 36339 | + sqlite3 *db = 0; | |
| 36340 | + char *zErr = 0; | |
| 36341 | + sqlite3_open(":memory:", &db); | |
| 36342 | + sqlite3_enable_load_extension(db, 1); | |
| 36343 | + rc = sqlite3_load_extension(db, zVfs, 0, &zErr); | |
| 36344 | + sqlite3_close(db); | |
| 36345 | + if( (rc&0xff)!=SQLITE_OK ){ | |
| 36346 | + cli_printf(stderr, "could not load extension VFS \"%s\": %s\n", | |
| 36347 | + zVfs, zErr); | |
| 36348 | + exit(1); | |
| 36349 | + } | |
| 36350 | + } | |
| 36351 | +#endif | |
| 36352 | + else{ | |
| 35854 | 36353 | cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs); |
| 35855 | 36354 | exit(1); |
| 35856 | 36355 | } |
| 35857 | 36356 | } |
| 35858 | 36357 | |
| @@ -35889,11 +36388,11 @@ | ||
| 35889 | 36388 | ** is given on the command line, look for a file named ~/.sqliterc and |
| 35890 | 36389 | ** try to process it. |
| 35891 | 36390 | */ |
| 35892 | 36391 | if( !noInit ) process_sqliterc(&data,zInitFile); |
| 35893 | 36392 | |
| 35894 | - /* Make a second pass through the command-line argument and set | |
| 36393 | + /* Make a second pass through the command-line arguments and set | |
| 35895 | 36394 | ** options. This second pass is delayed until after the initialization |
| 35896 | 36395 | ** file is processed so that the command-line arguments will override |
| 35897 | 36396 | ** settings in the initialization file. |
| 35898 | 36397 | */ |
| 35899 | 36398 | for(i=1; i<argc; i++){ |
| @@ -36015,12 +36514,10 @@ | ||
| 36015 | 36514 | stdin_is_interactive = 1; |
| 36016 | 36515 | }else if( cli_strcmp(z,"-batch")==0 ){ |
| 36017 | 36516 | /* already handled */ |
| 36018 | 36517 | }else if( cli_strcmp(z,"-screenwidth")==0 ){ |
| 36019 | 36518 | i++; |
| 36020 | - }else if( cli_strcmp(z,"-compat")==0 ){ | |
| 36021 | - i++; | |
| 36022 | 36519 | }else if( cli_strcmp(z,"-utf8")==0 ){ |
| 36023 | 36520 | /* already handled */ |
| 36024 | 36521 | }else if( cli_strcmp(z,"-no-utf8")==0 ){ |
| 36025 | 36522 | /* already handled */ |
| 36026 | 36523 | }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){ |
| @@ -36116,11 +36613,22 @@ | ||
| 36116 | 36613 | ** command-line inputs, except for the argToSkip argument which contains |
| 36117 | 36614 | ** the database filename. |
| 36118 | 36615 | */ |
| 36119 | 36616 | for(i=0; i<nCmd; i++){ |
| 36120 | 36617 | echo_group_input(&data, azCmd[i]); |
| 36121 | - if( azCmd[i][0]=='.' ){ | |
| 36618 | + if( isScriptFile(azCmd[i],0) ){ | |
| 36619 | + FILE *inSaved = data.in; | |
| 36620 | + i64 savedLineno = data.lineno; | |
| 36621 | + int res = 1; | |
| 36622 | + if( (data.in = openChrSource(azCmd[i]))!=0 ){ | |
| 36623 | + res = process_input(&data, azCmd[i]); | |
| 36624 | + fclose(data.in); | |
| 36625 | + } | |
| 36626 | + data.in = inSaved; | |
| 36627 | + data.lineno = savedLineno; | |
| 36628 | + if( res ) i = nCmd; | |
| 36629 | + }else if( azCmd[i][0]=='.' ){ | |
| 36122 | 36630 | char *zErrCtx = malloc( 64 ); |
| 36123 | 36631 | shell_check_oom(zErrCtx); |
| 36124 | 36632 | sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]); |
| 36125 | 36633 | data.zInFile = "<cmdline>"; |
| 36126 | 36634 | data.zErrPrefix = zErrCtx; |
| @@ -36231,14 +36739,10 @@ | ||
| 36231 | 36739 | } |
| 36232 | 36740 | find_home_dir(1); |
| 36233 | 36741 | output_reset(&data); |
| 36234 | 36742 | data.doXdgOpen = 0; |
| 36235 | 36743 | clearTempFile(&data); |
| 36236 | -#if !SQLITE_SHELL_IS_UTF8 | |
| 36237 | - for(i=0; i<argcToFree; i++) free(argvToFree[i]); | |
| 36238 | - free(argvToFree); | |
| 36239 | -#endif | |
| 36240 | 36744 | modeFree(&data.mode); |
| 36241 | 36745 | if( data.nSavedModes ){ |
| 36242 | 36746 | int ii; |
| 36243 | 36747 | for(ii=0; ii<data.nSavedModes; ii++){ |
| 36244 | 36748 | modeFree(&data.aSavedModes[ii].mode); |
| 36245 | 36749 |
| --- extsrc/shell.c | |
| +++ extsrc/shell.c | |
| @@ -35,11 +35,11 @@ | |
| 35 | ** ext/recover/sqlite3recover.h |
| 36 | ** src/shell.c.in |
| 37 | ** |
| 38 | ** To modify this program, get a copy of the canonical SQLite source tree, |
| 39 | ** edit the src/shell.c.in file and/or some of the other files that are |
| 40 | ** listed above, then rerun the rerun "make shell.c". |
| 41 | */ |
| 42 | /************************* Begin src/shell.c.in ******************/ |
| 43 | /* |
| 44 | ** 2001 September 15 |
| 45 | ** |
| @@ -49,11 +49,11 @@ | |
| 49 | ** May you do good and not evil. |
| 50 | ** May you find forgiveness for yourself and forgive others. |
| 51 | ** May you share freely, never taking more than you give. |
| 52 | ** |
| 53 | ************************************************************************* |
| 54 | ** This file contains code to implement the "sqlite" command line |
| 55 | ** utility for accessing SQLite databases. |
| 56 | */ |
| 57 | #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) |
| 58 | /* This needs to come before any includes for MSVC compiler */ |
| 59 | #define _CRT_SECURE_NO_WARNINGS |
| @@ -79,10 +79,14 @@ | |
| 79 | ** should only be used when building the "fiddle" web application, as |
| 80 | ** the browser-mode build has much different user input requirements |
| 81 | ** and this build mode rewires the user input subsystem to account for |
| 82 | ** that. |
| 83 | */ |
| 84 | |
| 85 | /* |
| 86 | ** Warning pragmas copied from msvc.h in the core. |
| 87 | */ |
| 88 | #if defined(_MSC_VER) |
| @@ -872,10 +876,11 @@ | |
| 872 | #ifndef SQLITE_QRF_H |
| 873 | #include "qrf.h" |
| 874 | #endif |
| 875 | #include <string.h> |
| 876 | #include <assert.h> |
| 877 | |
| 878 | /* typedef sqlite3_int64 i64; */ |
| 879 | |
| 880 | /* A single line in the EQP output */ |
| 881 | typedef struct qrfEQPGraphRow qrfEQPGraphRow; |
| @@ -889,11 +894,12 @@ | |
| 889 | /* All EQP output is collected into an instance of the following */ |
| 890 | typedef struct qrfEQPGraph qrfEQPGraph; |
| 891 | struct qrfEQPGraph { |
| 892 | qrfEQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ |
| 893 | qrfEQPGraphRow *pLast; /* Last element of the pRow list */ |
| 894 | char zPrefix[100]; /* Graph prefix */ |
| 895 | }; |
| 896 | |
| 897 | /* |
| 898 | ** Private state information. Subject to change from one release to the |
| 899 | ** next. |
| @@ -995,10 +1001,19 @@ | |
| 995 | */ |
| 996 | static void qrfOom(Qrf *p){ |
| 997 | qrfError(p, SQLITE_NOMEM, "out of memory"); |
| 998 | } |
| 999 | |
| 1000 | |
| 1001 | |
| 1002 | /* |
| 1003 | ** Add a new entry to the EXPLAIN QUERY PLAN data |
| 1004 | */ |
| @@ -1074,10 +1089,49 @@ | |
| 1074 | qrfEqpRenderLevel(p, pRow->iEqpId); |
| 1075 | p->u.pGraph->zPrefix[n] = 0; |
| 1076 | } |
| 1077 | } |
| 1078 | } |
| 1079 | |
| 1080 | /* |
| 1081 | ** Display and reset the EXPLAIN QUERY PLAN data |
| 1082 | */ |
| 1083 | static void qrfEqpRender(Qrf *p, i64 nCycle){ |
| @@ -1090,11 +1144,30 @@ | |
| 1090 | } |
| 1091 | sqlite3_str_appendf(p->pOut, "%s\n", pRow->zText+3); |
| 1092 | p->u.pGraph->pRow = pRow->pNext; |
| 1093 | sqlite3_free(pRow); |
| 1094 | }else if( nCycle>0 ){ |
| 1095 | sqlite3_str_appendf(p->pOut, "QUERY PLAN (cycles=%lld [100%%])\n",nCycle); |
| 1096 | }else{ |
| 1097 | sqlite3_str_appendall(p->pOut, "QUERY PLAN\n"); |
| 1098 | } |
| 1099 | p->u.pGraph->zPrefix[0] = 0; |
| 1100 | qrfEqpRenderLevel(p, 0); |
| @@ -1145,10 +1218,12 @@ | |
| 1145 | static const int f = SQLITE_SCANSTAT_COMPLEX; |
| 1146 | sqlite3_stmt *pS = p->pStmt; |
| 1147 | int i = 0; |
| 1148 | i64 nTotal = 0; |
| 1149 | int nWidth = 0; |
| 1150 | sqlite3_str *pLine = sqlite3_str_new(p->db); |
| 1151 | sqlite3_str *pStats = sqlite3_str_new(p->db); |
| 1152 | qrfEqpReset(p); |
| 1153 | |
| 1154 | for(i=0; 1; i++){ |
| @@ -1158,11 +1233,11 @@ | |
| 1158 | break; |
| 1159 | } |
| 1160 | n = (int)strlen(z) + qrfStatsHeight(pS,i)*3; |
| 1161 | if( n>nWidth ) nWidth = n; |
| 1162 | } |
| 1163 | nWidth += 4; |
| 1164 | |
| 1165 | sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal); |
| 1166 | for(i=0; 1; i++){ |
| 1167 | i64 nLoop = 0; |
| 1168 | i64 nRow = 0; |
| @@ -1173,55 +1248,67 @@ | |
| 1173 | const char *zName = 0; |
| 1174 | double rEst = 0.0; |
| 1175 | |
| 1176 | if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){ |
| 1177 | break; |
| 1178 | } |
| 1179 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst); |
| 1180 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop); |
| 1181 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow); |
| 1182 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle); |
| 1183 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId); |
| 1184 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid); |
| 1185 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName); |
| 1186 | |
| 1187 | if( nCycle>=0 || nLoop>=0 || nRow>=0 ){ |
| 1188 | const char *zSp = ""; |
| 1189 | double rpl; |
| 1190 | sqlite3_str_reset(pStats); |
| 1191 | if( nCycle>=0 && nTotal>0 ){ |
| 1192 | sqlite3_str_appendf(pStats, "cycles=%lld [%d%%]", |
| 1193 | nCycle, ((nCycle*100)+nTotal/2) / nTotal |
| 1194 | ); |
| 1195 | zSp = " "; |
| 1196 | } |
| 1197 | if( nLoop>=0 ){ |
| 1198 | sqlite3_str_appendf(pStats, "%sloops=%lld", zSp, nLoop); |
| 1199 | zSp = " "; |
| 1200 | } |
| 1201 | if( nRow>=0 ){ |
| 1202 | sqlite3_str_appendf(pStats, "%srows=%lld", zSp, nRow); |
| 1203 | zSp = " "; |
| 1204 | } |
| 1205 | |
| 1206 | if( p->spec.eStyle==QRF_STYLE_StatsEst ){ |
| 1207 | rpl = (double)nRow / (double)nLoop; |
| 1208 | sqlite3_str_appendf(pStats, "%srpl=%.1f est=%.1f", zSp, rpl, rEst); |
| 1209 | } |
| 1210 | |
| 1211 | sqlite3_str_appendf(pLine, |
| 1212 | "% *s (%s)", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo, |
| 1213 | sqlite3_str_value(pStats) |
| 1214 | ); |
| 1215 | sqlite3_str_reset(pStats); |
| 1216 | qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine)); |
| 1217 | sqlite3_str_reset(pLine); |
| 1218 | }else{ |
| 1219 | qrfEqpAppend(p, iId, iPid, zo); |
| 1220 | } |
| 1221 | } |
| 1222 | sqlite3_free(sqlite3_str_finish(pLine)); |
| 1223 | sqlite3_free(sqlite3_str_finish(pStats)); |
| 1224 | #endif |
| 1225 | } |
| 1226 | |
| 1227 | |
| @@ -1581,13 +1668,15 @@ | |
| 1581 | ** (3) z[] does not looks like a numeric literal |
| 1582 | */ |
| 1583 | static int qrfRelaxable(Qrf *p, const char *z){ |
| 1584 | size_t i, n; |
| 1585 | if( z[0]=='\'' || qrfSpace(z[0]) ) return 0; |
| 1586 | if( z[0]==0 && (p->spec.zNull==0 || p->spec.zNull[0]==0) ) return 0; |
| 1587 | n = strlen(z); |
| 1588 | if( z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0; |
| 1589 | if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0; |
| 1590 | i = (z[0]=='-' || z[0]=='+'); |
| 1591 | if( strcmp(z+i,"Inf")==0 ) return 0; |
| 1592 | if( !qrfDigit(z[i]) ) return 1; |
| 1593 | i++; |
| @@ -2729,10 +2818,11 @@ | |
| 2729 | int nNL = 0; |
| 2730 | int n, w; |
| 2731 | pStr = sqlite3_str_new(p->db); |
| 2732 | qrfEncodeText(p, pStr, z ? z : ""); |
| 2733 | n = sqlite3_str_length(pStr); |
| 2734 | z = data.az[data.n] = sqlite3_str_finish(pStr); |
| 2735 | if( p->spec.nTitleLimit ){ |
| 2736 | nNL = 0; |
| 2737 | data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n], |
| 2738 | p->spec.nTitleLimit ); |
| @@ -2756,10 +2846,11 @@ | |
| 2756 | int n, w; |
| 2757 | int eType = sqlite3_column_type(p->pStmt,i); |
| 2758 | pStr = sqlite3_str_new(p->db); |
| 2759 | qrfRenderValue(p, pStr, i); |
| 2760 | n = sqlite3_str_length(pStr); |
| 2761 | z = data.az[data.n] = sqlite3_str_finish(pStr); |
| 2762 | data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT; |
| 2763 | data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL); |
| 2764 | data.n++; |
| 2765 | if( w>data.a[i].mxW ) data.a[i].mxW = w; |
| @@ -2910,11 +3001,11 @@ | |
| 2910 | ){ |
| 2911 | bRTrim = 1; |
| 2912 | }else{ |
| 2913 | bRTrim = 0; |
| 2914 | } |
| 2915 | for(i=0; i<data.n; i+=nColumn){ |
| 2916 | int bMore; |
| 2917 | int nRow = 0; |
| 2918 | |
| 2919 | /* Draw a single row of the table. This might be the title line |
| 2920 | ** (if there is a title line) or a row in the body of the table. |
| @@ -3097,11 +3188,11 @@ | |
| 3097 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) ); |
| 3098 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) ); |
| 3099 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) ); |
| 3100 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) ); |
| 3101 | |
| 3102 | for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt); iOp++){ |
| 3103 | int iAddr = sqlite3_column_int(p->pStmt, 0); |
| 3104 | const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1); |
| 3105 | int p1 = sqlite3_column_int(p->pStmt, 2); |
| 3106 | int p2 = sqlite3_column_int(p->pStmt, 3); |
| 3107 | |
| @@ -3154,11 +3245,11 @@ | |
| 3154 | nWidth = sizeof(aScanExpWidth)/sizeof(int); |
| 3155 | iIndent = 3; |
| 3156 | } |
| 3157 | if( nArg>nWidth ) nArg = nWidth; |
| 3158 | |
| 3159 | for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW; iOp++){ |
| 3160 | /* If this is the first row seen, print out the headers */ |
| 3161 | if( iOp==0 ){ |
| 3162 | for(i=0; i<nArg; i++){ |
| 3163 | const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]); |
| 3164 | qrfWidthPrint(p,p->pOut, aWidth[i], zCol); |
| @@ -3410,10 +3501,11 @@ | |
| 3410 | sqlite3_str_append(p->pOut, "\n", 1); |
| 3411 | zVal += iNext; |
| 3412 | }while( zVal[0] ); |
| 3413 | sqlite3_str_reset(pVal); |
| 3414 | } |
| 3415 | sqlite3_free(sqlite3_str_finish(pVal)); |
| 3416 | qrfWrite(p); |
| 3417 | break; |
| 3418 | } |
| 3419 | case QRF_STYLE_Eqp: { |
| @@ -3473,11 +3565,11 @@ | |
| 3473 | p->pOut = sqlite3_str_new(p->db); |
| 3474 | if( p->pOut==0 ){ |
| 3475 | qrfOom(p); |
| 3476 | return; |
| 3477 | } |
| 3478 | p->iErr = 0; |
| 3479 | p->nCol = sqlite3_column_count(p->pStmt); |
| 3480 | p->nRow = 0; |
| 3481 | sz = sizeof(sqlite3_qrf_spec); |
| 3482 | memcpy(&p->spec, pSpec, sz); |
| 3483 | if( p->spec.zNull==0 ) p->spec.zNull = ""; |
| @@ -3644,17 +3736,27 @@ | |
| 3644 | sqlite3_free(p->u.sLine.azCol); |
| 3645 | } |
| 3646 | break; |
| 3647 | } |
| 3648 | case QRF_STYLE_Stats: |
| 3649 | case QRF_STYLE_StatsEst: |
| 3650 | case QRF_STYLE_Eqp: { |
| 3651 | qrfEqpRender(p, 0); |
| 3652 | qrfWrite(p); |
| 3653 | break; |
| 3654 | } |
| 3655 | } |
| 3656 | if( p->spec.pzOutput ){ |
| 3657 | if( p->spec.pzOutput[0] ){ |
| 3658 | sqlite3_int64 n, sz; |
| 3659 | char *zCombined; |
| 3660 | sz = strlen(p->spec.pzOutput[0]); |
| @@ -3815,13 +3917,10 @@ | |
| 3815 | |
| 3816 | |
| 3817 | #define eputz(z) cli_puts(z,stderr) |
| 3818 | #define sputz(fp,z) cli_puts(z,fp) |
| 3819 | |
| 3820 | /* True if the timer is enabled */ |
| 3821 | static int enableTimer = 0; |
| 3822 | |
| 3823 | /* A version of strcmp() that works with NULL values */ |
| 3824 | static int cli_strcmp(const char *a, const char *b){ |
| 3825 | if( a==0 ) a = ""; |
| 3826 | if( b==0 ) b = ""; |
| 3827 | return strcmp(a,b); |
| @@ -3834,11 +3933,11 @@ | |
| 3834 | |
| 3835 | /* Return the current wall-clock time in microseconds since the |
| 3836 | ** Unix epoch (1970-01-01T00:00:00Z) |
| 3837 | */ |
| 3838 | static sqlite3_int64 timeOfDay(void){ |
| 3839 | #if defined(_WIN64) |
| 3840 | sqlite3_uint64 t; |
| 3841 | FILETIME tm; |
| 3842 | GetSystemTimePreciseAsFileTime(&tm); |
| 3843 | t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime; |
| 3844 | t += 116444736000000000LL; |
| @@ -3862,154 +3961,10 @@ | |
| 3862 | (void)gettimeofday(&sNow,0); |
| 3863 | return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec; |
| 3864 | #endif |
| 3865 | } |
| 3866 | |
| 3867 | #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) |
| 3868 | #include <sys/time.h> |
| 3869 | #include <sys/resource.h> |
| 3870 | |
| 3871 | /* VxWorks does not support getrusage() as far as we can determine */ |
| 3872 | #if defined(_WRS_KERNEL) || defined(__RTP__) |
| 3873 | struct rusage { |
| 3874 | struct timeval ru_utime; /* user CPU time used */ |
| 3875 | struct timeval ru_stime; /* system CPU time used */ |
| 3876 | }; |
| 3877 | #define getrusage(A,B) memset(B,0,sizeof(*B)) |
| 3878 | #endif |
| 3879 | |
| 3880 | |
| 3881 | /* Saved resource information for the beginning of an operation */ |
| 3882 | static struct rusage sBegin; /* CPU time at start */ |
| 3883 | static sqlite3_int64 iBegin; /* Wall-clock time at start */ |
| 3884 | |
| 3885 | /* |
| 3886 | ** Begin timing an operation |
| 3887 | */ |
| 3888 | static void beginTimer(void){ |
| 3889 | if( enableTimer ){ |
| 3890 | getrusage(RUSAGE_SELF, &sBegin); |
| 3891 | iBegin = timeOfDay(); |
| 3892 | } |
| 3893 | } |
| 3894 | |
| 3895 | /* Return the difference of two time_structs in seconds */ |
| 3896 | static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ |
| 3897 | return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + |
| 3898 | (double)(pEnd->tv_sec - pStart->tv_sec); |
| 3899 | } |
| 3900 | |
| 3901 | /* |
| 3902 | ** Print the timing results. |
| 3903 | */ |
| 3904 | static void endTimer(FILE *out){ |
| 3905 | if( enableTimer ){ |
| 3906 | sqlite3_int64 iEnd = timeOfDay(); |
| 3907 | struct rusage sEnd; |
| 3908 | getrusage(RUSAGE_SELF, &sEnd); |
| 3909 | cli_printf(out, "Run Time: real %.6f user %.6f sys %.6f\n", |
| 3910 | (iEnd - iBegin)*0.000001, |
| 3911 | timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), |
| 3912 | timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); |
| 3913 | } |
| 3914 | } |
| 3915 | |
| 3916 | #define BEGIN_TIMER beginTimer() |
| 3917 | #define END_TIMER(X) endTimer(X) |
| 3918 | #define HAS_TIMER 1 |
| 3919 | |
| 3920 | #elif (defined(_WIN32) || defined(WIN32)) |
| 3921 | |
| 3922 | /* Saved resource information for the beginning of an operation */ |
| 3923 | static HANDLE hProcess; |
| 3924 | static FILETIME ftKernelBegin; |
| 3925 | static FILETIME ftUserBegin; |
| 3926 | static sqlite3_int64 ftWallBegin; |
| 3927 | typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, |
| 3928 | LPFILETIME, LPFILETIME); |
| 3929 | static GETPROCTIMES getProcessTimesAddr = NULL; |
| 3930 | |
| 3931 | /* |
| 3932 | ** Check to see if we have timer support. Return 1 if necessary |
| 3933 | ** support found (or found previously). |
| 3934 | */ |
| 3935 | static int hasTimer(void){ |
| 3936 | if( getProcessTimesAddr ){ |
| 3937 | return 1; |
| 3938 | } else { |
| 3939 | /* GetProcessTimes() isn't supported in WIN95 and some other Windows |
| 3940 | ** versions. See if the version we are running on has it, and if it |
| 3941 | ** does, save off a pointer to it and the current process handle. |
| 3942 | */ |
| 3943 | hProcess = GetCurrentProcess(); |
| 3944 | if( hProcess ){ |
| 3945 | HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); |
| 3946 | if( NULL != hinstLib ){ |
| 3947 | getProcessTimesAddr = |
| 3948 | (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); |
| 3949 | if( NULL != getProcessTimesAddr ){ |
| 3950 | return 1; |
| 3951 | } |
| 3952 | FreeLibrary(hinstLib); |
| 3953 | } |
| 3954 | } |
| 3955 | } |
| 3956 | return 0; |
| 3957 | } |
| 3958 | |
| 3959 | /* |
| 3960 | ** Begin timing an operation |
| 3961 | */ |
| 3962 | static void beginTimer(void){ |
| 3963 | if( enableTimer && getProcessTimesAddr ){ |
| 3964 | FILETIME ftCreation, ftExit; |
| 3965 | getProcessTimesAddr(hProcess,&ftCreation,&ftExit, |
| 3966 | &ftKernelBegin,&ftUserBegin); |
| 3967 | ftWallBegin = timeOfDay(); |
| 3968 | } |
| 3969 | } |
| 3970 | |
| 3971 | /* Return the difference of two FILETIME structs in seconds */ |
| 3972 | static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ |
| 3973 | sqlite_int64 i64Start = *((sqlite_int64 *) pStart); |
| 3974 | sqlite_int64 i64End = *((sqlite_int64 *) pEnd); |
| 3975 | return (double) ((i64End - i64Start) / 10000000.0); |
| 3976 | } |
| 3977 | |
| 3978 | /* |
| 3979 | ** Print the timing results. |
| 3980 | */ |
| 3981 | static void endTimer(FILE *out){ |
| 3982 | if( enableTimer && getProcessTimesAddr){ |
| 3983 | FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; |
| 3984 | sqlite3_int64 ftWallEnd = timeOfDay(); |
| 3985 | getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); |
| 3986 | #ifdef _WIN64 |
| 3987 | /* microsecond precision on 64-bit windows */ |
| 3988 | cli_printf(out, "Run Time: real %.6f user %f sys %f\n", |
| 3989 | (ftWallEnd - ftWallBegin)*0.000001, |
| 3990 | timeDiff(&ftUserBegin, &ftUserEnd), |
| 3991 | timeDiff(&ftKernelBegin, &ftKernelEnd)); |
| 3992 | #else |
| 3993 | /* millisecond precisino on 32-bit windows */ |
| 3994 | cli_printf(out, "Run Time: real %.3f user %.3f sys %.3f\n", |
| 3995 | (ftWallEnd - ftWallBegin)*0.000001, |
| 3996 | timeDiff(&ftUserBegin, &ftUserEnd), |
| 3997 | timeDiff(&ftKernelBegin, &ftKernelEnd)); |
| 3998 | #endif |
| 3999 | } |
| 4000 | } |
| 4001 | |
| 4002 | #define BEGIN_TIMER beginTimer() |
| 4003 | #define END_TIMER(X) endTimer(X) |
| 4004 | #define HAS_TIMER hasTimer() |
| 4005 | |
| 4006 | #else |
| 4007 | #define BEGIN_TIMER |
| 4008 | #define END_TIMER(X) /*no-op*/ |
| 4009 | #define HAS_TIMER 0 |
| 4010 | #endif |
| 4011 | |
| 4012 | /* |
| 4013 | ** Used to prevent warnings about unused parameters |
| 4014 | */ |
| 4015 | #define UNUSED_PARAMETER(x) (void)(x) |
| @@ -4068,10 +4023,18 @@ | |
| 4068 | #define PROMPT_LEN_MAX 128 |
| 4069 | /* First line prompt. default: "sqlite> " */ |
| 4070 | static char mainPrompt[PROMPT_LEN_MAX]; |
| 4071 | /* Continuation prompt. default: " ...> " */ |
| 4072 | static char continuePrompt[PROMPT_LEN_MAX]; |
| 4073 | |
| 4074 | /* This is variant of the standard-library strncpy() routine with the |
| 4075 | ** one change that the destination string is always zero-terminated, even |
| 4076 | ** if there is no zero-terminator in the first n-1 characters of the source |
| 4077 | ** string. |
| @@ -4188,17 +4151,10 @@ | |
| 4188 | */ |
| 4189 | static void shell_check_oom(const void *p){ |
| 4190 | if( p==0 ) shell_out_of_memory(); |
| 4191 | } |
| 4192 | |
| 4193 | /* |
| 4194 | ** Write I/O traces to the following stream. |
| 4195 | */ |
| 4196 | #ifdef SQLITE_ENABLE_IOTRACE |
| 4197 | static FILE *iotrace = 0; |
| 4198 | #endif |
| 4199 | |
| 4200 | /* |
| 4201 | ** This routine works like printf in that its first argument is a |
| 4202 | ** format string and subsequent arguments are values to be substituted |
| 4203 | ** in place of % fields. The result of formatting this string |
| 4204 | ** is written to iotrace. |
| @@ -8349,13 +8305,13 @@ | |
| 8349 | }else if( e<-10000 ){ |
| 8350 | e = -10000; |
| 8351 | } |
| 8352 | |
| 8353 | if( m<0 ){ |
| 8354 | isNeg = 1; |
| 8355 | m = -m; |
| 8356 | if( m<0 ) return; |
| 8357 | }else if( m==0 && e>-1000 && e<1000 ){ |
| 8358 | sqlite3_result_double(context, 0.0); |
| 8359 | return; |
| 8360 | } |
| 8361 | while( (m>>32)&0xffe00000 ){ |
| @@ -9472,11 +9428,11 @@ | |
| 9472 | ** (X) match X |
| 9473 | ** X|Y X or Y |
| 9474 | ** ^X X occurring at the beginning of the string |
| 9475 | ** X$ X occurring at the end of the string |
| 9476 | ** . Match any single character |
| 9477 | ** \c Character c where c is one of \{}()[]|*+?. |
| 9478 | ** \c C-language escapes for c in afnrtv. ex: \t or \n |
| 9479 | ** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX |
| 9480 | ** \xXX Where XX is exactly 2 hex digits, unicode value XX |
| 9481 | ** [abc] Any single character from the set abc |
| 9482 | ** [^abc] Any single character not in the set abc |
| @@ -9857,11 +9813,11 @@ | |
| 9857 | |
| 9858 | /* A backslash character has been seen, read the next character and |
| 9859 | ** return its interpretation. |
| 9860 | */ |
| 9861 | static unsigned re_esc_char(ReCompiled *p){ |
| 9862 | static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]"; |
| 9863 | static const char zTrans[] = "\a\f\n\r\t\v"; |
| 9864 | int i, v = 0; |
| 9865 | char c; |
| 9866 | if( p->sIn.i>=p->sIn.mx ) return 0; |
| 9867 | c = p->sIn.z[p->sIn.i]; |
| @@ -10180,15 +10136,22 @@ | |
| 10180 | } |
| 10181 | return pRe->zErr; |
| 10182 | } |
| 10183 | |
| 10184 | /* |
| 10185 | ** Compute a reasonable limit on the length of the REGEXP NFA. |
| 10186 | */ |
| 10187 | static int re_maxlen(sqlite3_context *context){ |
| 10188 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 10189 | return 75 + sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1)/2; |
| 10190 | } |
| 10191 | |
| 10192 | /* |
| 10193 | ** Implementation of the regexp() SQL function. This function implements |
| 10194 | ** the build-in REGEXP operator. The first argument to the function is the |
| @@ -10210,14 +10173,21 @@ | |
| 10210 | int setAux = 0; /* True to invoke sqlite3_set_auxdata() */ |
| 10211 | |
| 10212 | (void)argc; /* Unused */ |
| 10213 | pRe = sqlite3_get_auxdata(context, 0); |
| 10214 | if( pRe==0 ){ |
| 10215 | zPattern = (const char*)sqlite3_value_text(argv[0]); |
| 10216 | if( zPattern==0 ) return; |
| 10217 | zErr = re_compile(&pRe, zPattern, re_maxlen(context), |
| 10218 | sqlite3_user_data(context)!=0); |
| 10219 | if( zErr ){ |
| 10220 | re_free(pRe); |
| 10221 | sqlite3_result_error(context, zErr, -1); |
| 10222 | return; |
| 10223 | } |
| @@ -10279,11 +10249,11 @@ | |
| 10279 | "ATSTART", |
| 10280 | }; |
| 10281 | |
| 10282 | zPattern = (const char*)sqlite3_value_text(argv[0]); |
| 10283 | if( zPattern==0 ) return; |
| 10284 | zErr = re_compile(&pRe, zPattern, re_maxlen(context), |
| 10285 | sqlite3_user_data(context)!=0); |
| 10286 | if( zErr ){ |
| 10287 | re_free(pRe); |
| 10288 | sqlite3_result_error(context, zErr, -1); |
| 10289 | return; |
| @@ -13067,11 +13037,11 @@ | |
| 13067 | nFile = (int)strlen(zFile)+1; |
| 13068 | } |
| 13069 | |
| 13070 | rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA); |
| 13071 | if( rc==SQLITE_OK ){ |
| 13072 | pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile); |
| 13073 | if( pNew==0 ) return SQLITE_NOMEM; |
| 13074 | memset(pNew, 0, nByte+nFile); |
| 13075 | pNew->db = db; |
| 13076 | pNew->aBuffer = (u8*)&pNew[1]; |
| 13077 | if( zFile ){ |
| @@ -13213,18 +13183,19 @@ | |
| 13213 | ** sqlite3_free(). |
| 13214 | */ |
| 13215 | static int zipfileReadData( |
| 13216 | FILE *pFile, /* Read from this file */ |
| 13217 | u8 *aRead, /* Read into this buffer */ |
| 13218 | int nRead, /* Number of bytes to read */ |
| 13219 | i64 iOff, /* Offset to read from */ |
| 13220 | char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */ |
| 13221 | ){ |
| 13222 | size_t n; |
| 13223 | fseek(pFile, (long)iOff, SEEK_SET); |
| 13224 | n = fread(aRead, 1, nRead, pFile); |
| 13225 | if( (int)n!=nRead ){ |
| 13226 | *pzErrmsg = sqlite3_mprintf("error in fread()"); |
| 13227 | return SQLITE_ERROR; |
| 13228 | } |
| 13229 | return SQLITE_OK; |
| 13230 | } |
| @@ -13237,11 +13208,11 @@ | |
| 13237 | if( nWrite>0 ){ |
| 13238 | size_t n = nWrite; |
| 13239 | fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET); |
| 13240 | n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd); |
| 13241 | if( (int)n!=nWrite ){ |
| 13242 | pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()"); |
| 13243 | return SQLITE_ERROR; |
| 13244 | } |
| 13245 | pTab->szCurrent += nWrite; |
| 13246 | } |
| 13247 | return SQLITE_OK; |
| @@ -13484,10 +13455,11 @@ | |
| 13484 | /* |
| 13485 | ** Set (*pzErr) to point to a buffer from sqlite3_malloc() containing a |
| 13486 | ** generic corruption message and return SQLITE_CORRUPT; |
| 13487 | */ |
| 13488 | static int zipfileCorrupt(char **pzErr){ |
| 13489 | *pzErr = sqlite3_mprintf("zip archive is corrupt"); |
| 13490 | return SQLITE_CORRUPT; |
| 13491 | } |
| 13492 | |
| 13493 | /* |
| @@ -13502,11 +13474,11 @@ | |
| 13502 | ** final value of (*ppEntry) undefined. |
| 13503 | */ |
| 13504 | static int zipfileGetEntry( |
| 13505 | ZipfileTab *pTab, /* Store any error message here */ |
| 13506 | const u8 *aBlob, /* Pointer to in-memory file image */ |
| 13507 | int nBlob, /* Size of aBlob[] in bytes */ |
| 13508 | FILE *pFile, /* If aBlob==0, read from this file */ |
| 13509 | i64 iOff, /* Offset of CDS record */ |
| 13510 | ZipfileEntry **ppEntry /* OUT: Pointer to new object */ |
| 13511 | ){ |
| 13512 | u8 *aRead; |
| @@ -13542,18 +13514,18 @@ | |
| 13542 | rc = SQLITE_NOMEM; |
| 13543 | }else{ |
| 13544 | memset(pNew, 0, sizeof(ZipfileEntry)); |
| 13545 | rc = zipfileReadCDS(aRead, &pNew->cds); |
| 13546 | if( rc!=SQLITE_OK ){ |
| 13547 | *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff); |
| 13548 | }else if( aBlob==0 ){ |
| 13549 | rc = zipfileReadData( |
| 13550 | pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr |
| 13551 | ); |
| 13552 | }else{ |
| 13553 | aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ]; |
| 13554 | if( (iOff + ZIPFILE_LFH_FIXED_SZ + nFile + nExtra)>nBlob ){ |
| 13555 | rc = zipfileCorrupt(pzErr); |
| 13556 | } |
| 13557 | } |
| 13558 | } |
| 13559 | |
| @@ -13574,19 +13546,19 @@ | |
| 13574 | ZipfileLFH lfh; |
| 13575 | if( pFile ){ |
| 13576 | rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr); |
| 13577 | }else{ |
| 13578 | aRead = (u8*)&aBlob[pNew->cds.iOffset]; |
| 13579 | if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>(unsigned)nBlob ){ |
| 13580 | rc = zipfileCorrupt(pzErr); |
| 13581 | } |
| 13582 | } |
| 13583 | |
| 13584 | memset(&lfh, 0, sizeof(lfh)); |
| 13585 | if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh); |
| 13586 | if( rc==SQLITE_OK ){ |
| 13587 | pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; |
| 13588 | pNew->iDataOff += lfh.nFile + lfh.nExtra; |
| 13589 | if( aBlob && pNew->cds.szCompressed ){ |
| 13590 | if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){ |
| 13591 | rc = zipfileCorrupt(pzErr); |
| 13592 | }else{ |
| @@ -13593,11 +13565,11 @@ | |
| 13593 | pNew->aData = &pNew->aExtra[nExtra]; |
| 13594 | memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed); |
| 13595 | } |
| 13596 | } |
| 13597 | }else{ |
| 13598 | *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", |
| 13599 | (int)pNew->cds.iOffset |
| 13600 | ); |
| 13601 | } |
| 13602 | } |
| 13603 | |
| @@ -13617,11 +13589,11 @@ | |
| 13617 | static int zipfileNext(sqlite3_vtab_cursor *cur){ |
| 13618 | ZipfileCsr *pCsr = (ZipfileCsr*)cur; |
| 13619 | int rc = SQLITE_OK; |
| 13620 | |
| 13621 | if( pCsr->pFile ){ |
| 13622 | i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize; |
| 13623 | zipfileEntryFree(pCsr->pCurrent); |
| 13624 | pCsr->pCurrent = 0; |
| 13625 | if( pCsr->iNextOff>=iEof ){ |
| 13626 | pCsr->bEof = 1; |
| 13627 | }else{ |
| @@ -13855,16 +13827,16 @@ | |
| 13855 | ** an English language error message may be left in virtual-table pTab. |
| 13856 | */ |
| 13857 | static int zipfileReadEOCD( |
| 13858 | ZipfileTab *pTab, /* Return errors here */ |
| 13859 | const u8 *aBlob, /* Pointer to in-memory file image */ |
| 13860 | int nBlob, /* Size of aBlob[] in bytes */ |
| 13861 | FILE *pFile, /* Read from this file if aBlob==0 */ |
| 13862 | ZipfileEOCD *pEOCD /* Object to populate */ |
| 13863 | ){ |
| 13864 | u8 *aRead = pTab->aBuffer; /* Temporary buffer */ |
| 13865 | int nRead; /* Bytes to read from file */ |
| 13866 | int rc = SQLITE_OK; |
| 13867 | |
| 13868 | memset(pEOCD, 0, sizeof(ZipfileEOCD)); |
| 13869 | if( aBlob==0 ){ |
| 13870 | i64 iOff; /* Offset to read from */ |
| @@ -13881,11 +13853,11 @@ | |
| 13881 | nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE)); |
| 13882 | aRead = (u8*)&aBlob[nBlob-nRead]; |
| 13883 | } |
| 13884 | |
| 13885 | if( rc==SQLITE_OK ){ |
| 13886 | int i; |
| 13887 | |
| 13888 | /* Scan backwards looking for the signature bytes */ |
| 13889 | for(i=nRead-20; i>=0; i--){ |
| 13890 | if( aRead[i]==0x50 && aRead[i+1]==0x4b |
| 13891 | && aRead[i+2]==0x05 && aRead[i+3]==0x06 |
| @@ -13892,13 +13864,11 @@ | |
| 13892 | ){ |
| 13893 | break; |
| 13894 | } |
| 13895 | } |
| 13896 | if( i<0 ){ |
| 13897 | pTab->base.zErrMsg = sqlite3_mprintf( |
| 13898 | "cannot find end of central directory record" |
| 13899 | ); |
| 13900 | return SQLITE_ERROR; |
| 13901 | } |
| 13902 | |
| 13903 | aRead += i+4; |
| 13904 | pEOCD->iDisk = zipfileRead16(aRead); |
| @@ -13939,11 +13909,11 @@ | |
| 13939 | pNew->pNext = pBefore; |
| 13940 | *pp = pNew; |
| 13941 | } |
| 13942 | } |
| 13943 | |
| 13944 | static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){ |
| 13945 | ZipfileEOCD eocd; |
| 13946 | int rc; |
| 13947 | int i; |
| 13948 | i64 iOff; |
| 13949 | |
| @@ -13987,11 +13957,11 @@ | |
| 13987 | zipfileCursorErr(pCsr, "zipfile() function requires an argument"); |
| 13988 | return SQLITE_ERROR; |
| 13989 | }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ |
| 13990 | static const u8 aEmptyBlob = 0; |
| 13991 | const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]); |
| 13992 | int nBlob = sqlite3_value_bytes(argv[0]); |
| 13993 | assert( pTab->pFirstEntry==0 ); |
| 13994 | if( aBlob==0 ){ |
| 13995 | aBlob = &aEmptyBlob; |
| 13996 | nBlob = 0; |
| 13997 | } |
| @@ -14185,23 +14155,23 @@ | |
| 14185 | ZipfileTab *pTab = (ZipfileTab*)pVtab; |
| 14186 | int rc = SQLITE_OK; |
| 14187 | |
| 14188 | assert( pTab->pWriteFd==0 ); |
| 14189 | if( pTab->zFile==0 || pTab->zFile[0]==0 ){ |
| 14190 | pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename"); |
| 14191 | return SQLITE_ERROR; |
| 14192 | } |
| 14193 | |
| 14194 | /* Open a write fd on the file. Also load the entire central directory |
| 14195 | ** structure into memory. During the transaction any new file data is |
| 14196 | ** appended to the archive file, but the central directory is accumulated |
| 14197 | ** in main-memory until the transaction is committed. */ |
| 14198 | pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+"); |
| 14199 | if( pTab->pWriteFd==0 ){ |
| 14200 | pTab->base.zErrMsg = sqlite3_mprintf( |
| 14201 | "zipfile: failed to open file %s for writing", pTab->zFile |
| 14202 | ); |
| 14203 | rc = SQLITE_ERROR; |
| 14204 | }else{ |
| 14205 | fseek(pTab->pWriteFd, 0, SEEK_END); |
| 14206 | pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd); |
| 14207 | rc = zipfileLoadDirectory(pTab, 0, 0); |
| @@ -14662,11 +14632,11 @@ | |
| 14662 | int nEntry; |
| 14663 | ZipfileBuffer body; |
| 14664 | ZipfileBuffer cds; |
| 14665 | }; |
| 14666 | |
| 14667 | static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){ |
| 14668 | if( pBuf->n+nByte>pBuf->nAlloc ){ |
| 14669 | u8 *aNew; |
| 14670 | sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512; |
| 14671 | int nReq = pBuf->n + nByte; |
| 14672 | |
| @@ -14711,11 +14681,11 @@ | |
| 14711 | u32 iCrc32 = 0; /* crc32 of uncompressed data */ |
| 14712 | |
| 14713 | char *zName = 0; /* Path (name) of new entry */ |
| 14714 | int nName = 0; /* Size of zName in bytes */ |
| 14715 | char *zFree = 0; /* Free this before returning */ |
| 14716 | int nByte; |
| 14717 | |
| 14718 | memset(&e, 0, sizeof(e)); |
| 14719 | p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); |
| 14720 | if( p==0 ) return; |
| 14721 | |
| @@ -24161,28 +24131,28 @@ | |
| 24161 | u8 autoExplain; /* Automatically turn on .explain mode */ |
| 24162 | u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */ |
| 24163 | u8 autoEQPtrace; /* autoEQP is in trace mode */ |
| 24164 | u8 scanstatsOn; /* True to display scan stats before each finalize */ |
| 24165 | u8 bAutoScreenWidth; /* Using the TTY to determine screen width */ |
| 24166 | u8 mFlags; /* MFLG_ECHO and/or MFLG_CRLF */ |
| 24167 | u8 eMode; /* One of the MODE_ values */ |
| 24168 | sqlite3_qrf_spec spec; /* Spec to be passed into QRF */ |
| 24169 | } Mode; |
| 24170 | |
| 24171 | /* Flags for Mode.mFlags */ |
| 24172 | #define MFLG_ECHO 0x01 /* Echo inputs to output */ |
| 24173 | #define MFLG_CRLF 0x02 /* Use CR/LF output line endings */ |
| 24174 | |
| 24175 | |
| 24176 | /* |
| 24177 | ** State information about the database connection is contained in an |
| 24178 | ** instance of the following structure. |
| 24179 | */ |
| 24180 | typedef struct ShellState ShellState; |
| 24181 | struct ShellState { |
| 24182 | sqlite3 *db; /* The database */ |
| 24183 | int iCompat; /* Compatibility date YYYYMMDD */ |
| 24184 | u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ |
| 24185 | u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ |
| 24186 | u8 nEqpLevel; /* Depth of the EQP output graph */ |
| 24187 | u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ |
| 24188 | u8 bSafeMode; /* True to prohibit unsafe operations */ |
| @@ -24190,11 +24160,14 @@ | |
| 24190 | u8 eRestoreState; /* See comments above doAutoDetectRestore() */ |
| 24191 | unsigned statsOn; /* True to display memory stats before each finalize */ |
| 24192 | unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */ |
| 24193 | u8 nPopOutput; /* Revert .output settings when reaching zero */ |
| 24194 | u8 nPopMode; /* Revert .mode settings when reaching zero */ |
| 24195 | int inputNesting; /* Track nesting level of .read and other redirects */ |
| 24196 | i64 lineno; /* Line number of last line read from in */ |
| 24197 | const char *zInFile; /* Name of the input file */ |
| 24198 | int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ |
| 24199 | FILE *in; /* Read commands from this stream */ |
| 24200 | FILE *out; /* Write results here */ |
| @@ -24286,10 +24259,11 @@ | |
| 24286 | #define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */ |
| 24287 | #define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progress |
| 24288 | ** callback limit is reached, and for each |
| 24289 | ** top-level SQL statement */ |
| 24290 | #define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */ |
| 24291 | |
| 24292 | /* Names of values for Mode.spec.eEsc and Mode.spec.eText |
| 24293 | */ |
| 24294 | static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" }; |
| 24295 | static const char *qrfQuoteNames[] = |
| @@ -24447,10 +24421,181 @@ | |
| 24447 | ** Limit input nesting via .read or any other input redirect. |
| 24448 | ** It's not too expensive, so a generous allowance can be made. |
| 24449 | */ |
| 24450 | #define MAX_INPUT_NESTING 25 |
| 24451 | |
| 24452 | |
| 24453 | /* |
| 24454 | ** Clear a display mode, freeing any allocated memory that it |
| 24455 | ** contains. |
| 24456 | */ |
| @@ -24534,11 +24679,13 @@ | |
| 24534 | if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]); |
| 24535 | if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]); |
| 24536 | if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]); |
| 24537 | pM->spec.eText = pI->eText; |
| 24538 | pM->spec.eBlob = pI->eBlob; |
| 24539 | pM->spec.bTitles = pI->bHdr; |
| 24540 | pM->spec.eTitle = pI->eHdr; |
| 24541 | if( pI->mFlg & 0x01 ){ |
| 24542 | pM->spec.bBorder = QRF_No; |
| 24543 | }else{ |
| 24544 | pM->spec.bBorder = QRF_Auto; |
| @@ -24570,18 +24717,17 @@ | |
| 24570 | p->mode.mFlags = mFlags; |
| 24571 | } |
| 24572 | } |
| 24573 | |
| 24574 | /* |
| 24575 | ** Set the mode to the default according to p->iCompat. It assumed |
| 24576 | ** that the mode has already been freed and zeroed prior to calling |
| 24577 | ** this routine. |
| 24578 | */ |
| 24579 | static void modeDefault(ShellState *p){ |
| 24580 | p->mode.spec.iVersion = 1; |
| 24581 | p->mode.autoExplain = 1; |
| 24582 | if( p->iCompat>=20251115 && (stdin_is_interactive || stdout_is_console) ){ |
| 24583 | modeChange(p, MODE_TTY); |
| 24584 | }else{ |
| 24585 | modeChange(p, MODE_BATCH); |
| 24586 | } |
| 24587 | } |
| @@ -25371,10 +25517,17 @@ | |
| 25371 | ** Progress handler callback. |
| 25372 | */ |
| 25373 | static int progress_handler(void *pClientData) { |
| 25374 | ShellState *p = (ShellState*)pClientData; |
| 25375 | p->nProgress++; |
| 25376 | if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){ |
| 25377 | cli_printf(p->out, "Progress limit reached (%u)\n", p->nProgress); |
| 25378 | if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; |
| 25379 | if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0; |
| 25380 | return 1; |
| @@ -25908,10 +26061,12 @@ | |
| 25908 | char *zBuf = sqlite3_malloc64( szVar-5 ); |
| 25909 | if( zBuf ){ |
| 25910 | memcpy(zBuf, &zVar[6], szVar-5); |
| 25911 | sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8); |
| 25912 | } |
| 25913 | #ifdef SQLITE_ENABLE_CARRAY |
| 25914 | }else if( strncmp(zVar, "$carray_", 8)==0 ){ |
| 25915 | static char *azColorNames[] = { |
| 25916 | "azure", "black", "blue", "brown", "cyan", "fuchsia", "gold", |
| 25917 | "gray", "green", "indigo", "khaki", "lime", "magenta", "maroon", |
| @@ -26167,27 +26322,36 @@ | |
| 26167 | pArg->pStmt = pStmt; |
| 26168 | } |
| 26169 | |
| 26170 | /* Show the EXPLAIN QUERY PLAN if .eqp is on */ |
| 26171 | isExplain = sqlite3_stmt_isexplain(pStmt); |
| 26172 | if( pArg && pArg->mode.autoEQP && isExplain==0 ){ |
| 26173 | int triggerEQP = 0; |
| 26174 | disable_debug_trace_modes(); |
| 26175 | sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP); |
| 26176 | if( pArg->mode.autoEQP>=AUTOEQP_trigger ){ |
| 26177 | sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0); |
| 26178 | } |
| 26179 | sqlite3_reset(pStmt); |
| 26180 | spec.eStyle = QRF_STYLE_Auto; |
| 26181 | sqlite3_stmt_explain(pStmt, 2-(pArg->mode.autoEQP>=AUTOEQP_full)); |
| 26182 | sqlite3_format_query_result(pStmt, &spec, 0); |
| 26183 | if( pArg->mode.autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){ |
| 26184 | sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0); |
| 26185 | } |
| 26186 | sqlite3_reset(pStmt); |
| 26187 | sqlite3_stmt_explain(pStmt, 0); |
| 26188 | restore_debug_trace_modes(); |
| 26189 | } |
| 26190 | |
| 26191 | bind_prepared_stmt(pArg, pStmt); |
| 26192 | if( isExplain && pArg->mode.autoExplain ){ |
| 26193 | spec.eStyle = isExplain==1 ? QRF_STYLE_Explain : QRF_STYLE_Eqp; |
| @@ -26604,12 +26768,12 @@ | |
| 26604 | ".bail on|off Stop after hitting an error. Default OFF", |
| 26605 | #ifndef SQLITE_SHELL_FIDDLE |
| 26606 | ".cd DIRECTORY Change the working directory to DIRECTORY", |
| 26607 | #endif |
| 26608 | ".changes on|off Show number of rows changed by SQL", |
| 26609 | #ifndef SQLITE_SHELL_FIDDLE |
| 26610 | ".check GLOB Fail if output since .testcase does not match", |
| 26611 | ".clone NEWDB Clone data into NEWDB from the existing database", |
| 26612 | #endif |
| 26613 | ".connection [close] [#] Open or close an auxiliary database connection", |
| 26614 | ".crlf ?on|off? Whether or not to use \\r\\n line endings", |
| 26615 | ".databases List names and files of attached databases", |
| @@ -26721,10 +26885,11 @@ | |
| 26721 | ".progress N Invoke progress handler after every N opcodes", |
| 26722 | " --limit N Interrupt after N progress callbacks", |
| 26723 | " --once Do no more than one progress interrupt", |
| 26724 | " --quiet|-q No output except at interrupts", |
| 26725 | " --reset Reset the count for each input and interrupt", |
| 26726 | #endif |
| 26727 | ".prompt MAIN CONTINUE Replace the standard prompts", |
| 26728 | #ifndef SQLITE_SHELL_FIDDLE |
| 26729 | ".quit Stop interpreting input stream, exit if primary.", |
| 26730 | ".read FILE Read input from FILE or command output", |
| @@ -26785,17 +26950,15 @@ | |
| 26785 | " vmstep Show the virtual machine step count only", |
| 26786 | #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) |
| 26787 | ".system CMD ARGS... Run CMD ARGS... in a system shell", |
| 26788 | #endif |
| 26789 | ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", |
| 26790 | #ifndef SQLITE_SHELL_FIDDLE |
| 26791 | ",testcase NAME Begin redirecting output to 'testcase-out.txt'", |
| 26792 | #endif |
| 26793 | ",testctrl CMD ... Run various sqlite3_test_control() operations", |
| 26794 | " Run \".testctrl\" with no arguments for details", |
| 26795 | ".timeout MS Try opening locked tables for MS milliseconds", |
| 26796 | ".timer on|off Turn SQL timer on or off", |
| 26797 | #ifndef SQLITE_OMIT_TRACE |
| 26798 | ".trace ?OPTIONS? Output each SQL statement as it is run", |
| 26799 | " FILE Send output to FILE", |
| 26800 | " stdout Send output to stdout", |
| 26801 | " stderr Send output to stderr", |
| @@ -26836,19 +26999,33 @@ | |
| 26836 | "USAGE: .import [OPTIONS] FILE TABLE\n" |
| 26837 | "\n" |
| 26838 | "Import CSV or similar text from FILE into TABLE. If TABLE does\n" |
| 26839 | "not exist, it is created using the first row of FILE as the column\n" |
| 26840 | "names. If FILE begins with \"|\" then it is a command that is run\n" |
| 26841 | "and the output from the command is used as the input data.\n" |
| 26842 | "\n" |
| 26843 | "FILE is assumed to be in a CSV format, unless the current mode\n" |
| 26844 | "is \"ascii\" or \"tabs\" or unless one of the options below specify\n" |
| 26845 | "an alternative.\n" |
| 26846 | "\n" |
| 26847 | "Options:\n" |
| 26848 | " --ascii Use \\037 and \\036 as column and row separators on input\n" |
| 26849 | " --csv Input is standard RFC-4180 CSV.\n" |
| 26850 | " --schema S When creating TABLE, put it in schema S\n" |
| 26851 | " --skip N Ignore the first N rows of input\n" |
| 26852 | " -v Verbose mode\n" |
| 26853 | }, |
| 26854 | { ".mode", |
| @@ -26930,23 +27107,17 @@ | |
| 26930 | " --bom Prepend a byte-order mark to the output\n" |
| 26931 | " -e Accumulate output in a temporary text file then\n" |
| 26932 | " launch a text editor when the redirection ends.\n" |
| 26933 | " --error-prefix X Use X as the left-margin prefix for error messages.\n" |
| 26934 | " Set to an empty string to restore the default.\n" |
| 26935 | " --glob GLOB Raise an error if the memory buffer does not match\n" |
| 26936 | " the GLOB pattern.\n" |
| 26937 | " --keep Continue using the same \"memory\" buffer. Do not\n" |
| 26938 | " reset it or delete it. Useful in combination with\n" |
| 26939 | " --glob, --not-glob, and/or --verify.\n" |
| 26940 | " ---notglob GLOB Raise an error if the memory buffer does not match\n" |
| 26941 | " the GLOB pattern.\n" |
| 26942 | " --plain Use plain text rather than HTML tables with -w\n" |
| 26943 | " --show Write the memory buffer to the screen, for debugging.\n" |
| 26944 | " --verify ENDMARK Read subsequent lines of text until the first line\n" |
| 26945 | " that matches ENDMARK. Discard the ENDMARK. Compare\n" |
| 26946 | " the text against the accumulated output in memory and\n" |
| 26947 | " raise an error if there are any differences.\n" |
| 26948 | " -w Show the output in a web browser. Output is\n" |
| 26949 | " written into a temporary HTML file until the\n" |
| 26950 | " redirect ends, then the web browser is launched.\n" |
| 26951 | " Query results are shown as HTML tables, unless\n" |
| 26952 | " the --plain is used too.\n" |
| @@ -26970,10 +27141,39 @@ | |
| 26970 | " file in a web browser\n" |
| 26971 | " -x Show the output in a spreadsheet. Output is\n" |
| 26972 | " written to a temp file as CSV then the spreadsheet\n" |
| 26973 | " is launched when\n" |
| 26974 | }, |
| 26975 | }; |
| 26976 | |
| 26977 | /* |
| 26978 | ** Return a pointer to usage text for zCmd, or NULL if none exists. |
| 26979 | */ |
| @@ -27193,10 +27393,56 @@ | |
| 27193 | if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0; |
| 27194 | } |
| 27195 | return 1; |
| 27196 | } |
| 27197 | #endif |
| 27198 | |
| 27199 | /* |
| 27200 | ** Try to deduce the type of file for zName based on its content. Return |
| 27201 | ** one of the SHELL_OPEN_* constants. |
| 27202 | ** |
| @@ -27206,24 +27452,16 @@ | |
| 27206 | ** the type cannot be determined from content. |
| 27207 | */ |
| 27208 | int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){ |
| 27209 | FILE *f; |
| 27210 | size_t n; |
| 27211 | sqlite3 *db = 0; |
| 27212 | sqlite3_stmt *pStmt = 0; |
| 27213 | int rc = SHELL_OPEN_UNSPEC; |
| 27214 | char zBuf[100]; |
| 27215 | if( access(zName,0)!=0 ) goto database_type_by_name; |
| 27216 | if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK |
| 27217 | && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0) |
| 27218 | ==SQLITE_OK |
| 27219 | && sqlite3_step(pStmt)==SQLITE_ROW |
| 27220 | ){ |
| 27221 | rc = SHELL_OPEN_NORMAL; |
| 27222 | } |
| 27223 | sqlite3_finalize(pStmt); |
| 27224 | sqlite3_close(db); |
| 27225 | if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL; |
| 27226 | f = sqlite3_fopen(zName, "rb"); |
| 27227 | if( f==0 ) goto database_type_by_name; |
| 27228 | n = fread(zBuf, 16, 1, f); |
| 27229 | if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ |
| @@ -27253,10 +27491,39 @@ | |
| 27253 | }else{ |
| 27254 | rc = SHELL_OPEN_NORMAL; |
| 27255 | } |
| 27256 | return rc; |
| 27257 | } |
| 27258 | |
| 27259 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 27260 | /* |
| 27261 | ** Reconstruct an in-memory database using the output from the "dbtotxt" |
| 27262 | ** program. Read content from the file in p->aAuxDb[].zDbFilename. |
| @@ -27899,20 +28166,24 @@ | |
| 27899 | typedef struct ImportCtx ImportCtx; |
| 27900 | struct ImportCtx { |
| 27901 | const char *zFile; /* Name of the input file */ |
| 27902 | FILE *in; /* Read the CSV text from this input stream */ |
| 27903 | int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */ |
| 27904 | char *z; /* Accumulated text for a field */ |
| 27905 | i64 n; /* Number of bytes in z */ |
| 27906 | i64 nAlloc; /* Space allocated for z[] */ |
| 27907 | int nLine; /* Current line number */ |
| 27908 | int nRow; /* Number of rows imported */ |
| 27909 | int nErr; /* Number of errors encountered */ |
| 27910 | int bNotFirst; /* True if one or more bytes already read */ |
| 27911 | int cTerm; /* Character that terminated the most recent field */ |
| 27912 | int cColSep; /* The column separator character. (Usually ",") */ |
| 27913 | int cRowSep; /* The row separator character. (Usually "\n") */ |
| 27914 | }; |
| 27915 | |
| 27916 | /* Clean up resourced used by an ImportCtx */ |
| 27917 | static void import_cleanup(ImportCtx *p){ |
| 27918 | if( p->in!=0 && p->xCloser!=0 ){ |
| @@ -27919,13 +28190,32 @@ | |
| 27919 | p->xCloser(p->in); |
| 27920 | p->in = 0; |
| 27921 | } |
| 27922 | sqlite3_free(p->z); |
| 27923 | p->z = 0; |
| 27924 | } |
| 27925 | |
| 27926 | /* Append a single byte to z[] */ |
| 27927 | static void import_append_char(ImportCtx *p, int c){ |
| 27928 | if( p->n+1>=p->nAlloc ){ |
| 27929 | p->nAlloc += p->nAlloc + 100; |
| 27930 | p->z = sqlite3_realloc64(p->z, p->nAlloc); |
| 27931 | shell_check_oom(p->z); |
| @@ -27937,12 +28227,12 @@ | |
| 27937 | ** with the option of having a separator other than ",". |
| 27938 | ** |
| 27939 | ** + Input comes from p->in. |
| 27940 | ** + Store results in p->z of length p->n. Space to hold p->z comes |
| 27941 | ** from sqlite3_malloc64(). |
| 27942 | ** + Use p->cSep as the column separator. The default is ",". |
| 27943 | ** + Use p->rSep as the row separator. The default is "\n". |
| 27944 | ** + Keep track of the line number in p->nLine. |
| 27945 | ** + Store the character that terminates the field in p->cTerm. Store |
| 27946 | ** EOF on end-of-file. |
| 27947 | ** + Report syntax errors on stderr |
| 27948 | */ |
| @@ -27949,23 +28239,30 @@ | |
| 27949 | static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ |
| 27950 | int c; |
| 27951 | int cSep = (u8)p->cColSep; |
| 27952 | int rSep = (u8)p->cRowSep; |
| 27953 | p->n = 0; |
| 27954 | c = fgetc(p->in); |
| 27955 | if( c==EOF || seenInterrupt ){ |
| 27956 | p->cTerm = EOF; |
| 27957 | return 0; |
| 27958 | } |
| 27959 | if( c=='"' ){ |
| 27960 | int pc, ppc; |
| 27961 | int startLine = p->nLine; |
| 27962 | int cQuote = c; |
| 27963 | pc = ppc = 0; |
| 27964 | while( 1 ){ |
| 27965 | c = fgetc(p->in); |
| 27966 | if( c==rSep ) p->nLine++; |
| 27967 | if( c==cQuote ){ |
| 27968 | if( pc==cQuote ){ |
| 27969 | pc = 0; |
| 27970 | continue; |
| 27971 | } |
| @@ -27979,11 +28276,11 @@ | |
| 27979 | p->cTerm = c; |
| 27980 | break; |
| 27981 | } |
| 27982 | if( pc==cQuote && c!='\r' ){ |
| 27983 | cli_printf(stderr,"%s:%d: unescaped %c character\n", |
| 27984 | p->zFile, p->nLine, cQuote); |
| 27985 | } |
| 27986 | if( c==EOF ){ |
| 27987 | cli_printf(stderr,"%s:%d: unterminated %c-quoted field\n", |
| 27988 | p->zFile, startLine, cQuote); |
| 27989 | p->cTerm = c; |
| @@ -27994,26 +28291,28 @@ | |
| 27994 | pc = c; |
| 27995 | } |
| 27996 | }else{ |
| 27997 | /* If this is the first field being parsed and it begins with the |
| 27998 | ** UTF-8 BOM (0xEF BB BF) then skip the BOM */ |
| 27999 | if( (c&0xff)==0xef && p->bNotFirst==0 ){ |
| 28000 | import_append_char(p, c); |
| 28001 | c = fgetc(p->in); |
| 28002 | if( (c&0xff)==0xbb ){ |
| 28003 | import_append_char(p, c); |
| 28004 | c = fgetc(p->in); |
| 28005 | if( (c&0xff)==0xbf ){ |
| 28006 | p->bNotFirst = 1; |
| 28007 | p->n = 0; |
| 28008 | return csv_read_one_field(p); |
| 28009 | } |
| 28010 | } |
| 28011 | } |
| 28012 | while( c!=EOF && c!=cSep && c!=rSep ){ |
| 28013 | import_append_char(p, c); |
| 28014 | c = fgetc(p->in); |
| 28015 | } |
| 28016 | if( c==rSep ){ |
| 28017 | p->nLine++; |
| 28018 | if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; |
| 28019 | } |
| @@ -28027,12 +28326,12 @@ | |
| 28027 | /* Read a single field of ASCII delimited text. |
| 28028 | ** |
| 28029 | ** + Input comes from p->in. |
| 28030 | ** + Store results in p->z of length p->n. Space to hold p->z comes |
| 28031 | ** from sqlite3_malloc64(). |
| 28032 | ** + Use p->cSep as the column separator. The default is "\x1F". |
| 28033 | ** + Use p->rSep as the row separator. The default is "\x1E". |
| 28034 | ** + Keep track of the row number in p->nLine. |
| 28035 | ** + Store the character that terminates the field in p->cTerm. Store |
| 28036 | ** EOF on end-of-file. |
| 28037 | ** + Report syntax errors on stderr |
| 28038 | */ |
| @@ -28039,18 +28338,18 @@ | |
| 28039 | static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ |
| 28040 | int c; |
| 28041 | int cSep = (u8)p->cColSep; |
| 28042 | int rSep = (u8)p->cRowSep; |
| 28043 | p->n = 0; |
| 28044 | c = fgetc(p->in); |
| 28045 | if( c==EOF || seenInterrupt ){ |
| 28046 | p->cTerm = EOF; |
| 28047 | return 0; |
| 28048 | } |
| 28049 | while( c!=EOF && c!=cSep && c!=rSep ){ |
| 28050 | import_append_char(p, c); |
| 28051 | c = fgetc(p->in); |
| 28052 | } |
| 28053 | if( c==rSep ){ |
| 28054 | p->nLine++; |
| 28055 | } |
| 28056 | p->cTerm = c; |
| @@ -30151,11 +30450,11 @@ | |
| 30151 | ; |
| 30152 | static const char * const zCollectVar = "\ |
| 30153 | SELECT\ |
| 30154 | '('||x'0a'\ |
| 30155 | || group_concat(\ |
| 30156 | cname||' TEXT',\ |
| 30157 | ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ |
| 30158 | ||')' AS ColsSpec \ |
| 30159 | FROM (\ |
| 30160 | SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \ |
| 30161 | FROM ColNames ORDER BY cpos\ |
| @@ -30351,19 +30650,33 @@ | |
| 30351 | ** USAGE: .import [OPTIONS] FILE TABLE |
| 30352 | ** |
| 30353 | ** Import CSV or similar text from FILE into TABLE. If TABLE does |
| 30354 | ** not exist, it is created using the first row of FILE as the column |
| 30355 | ** names. If FILE begins with "|" then it is a command that is run |
| 30356 | ** and the output from the command is used as the input data. |
| 30357 | ** |
| 30358 | ** FILE is assumed to be in a CSV format, unless the current mode |
| 30359 | ** is "ascii" or "tabs" or unless one of the options below specify |
| 30360 | ** an alternative. |
| 30361 | ** |
| 30362 | ** Options: |
| 30363 | ** --ascii Use \037 and \036 as column and row separators on input |
| 30364 | ** --csv Input is standard RFC-4180 CSV. |
| 30365 | ** --schema S When creating TABLE, put it in schema S |
| 30366 | ** --skip N Ignore the first N rows of input |
| 30367 | ** -v Verbose mode |
| 30368 | */ |
| 30369 | static int dotCmdImport(ShellState *p){ |
| @@ -30375,17 +30688,16 @@ | |
| 30375 | sqlite3_stmt *pStmt = NULL; /* A statement */ |
| 30376 | int nCol; /* Number of columns in the table */ |
| 30377 | i64 nByte; /* Number of bytes in an SQL string */ |
| 30378 | int i, j; /* Loop counters */ |
| 30379 | int needCommit; /* True to COMMIT or ROLLBACK at end */ |
| 30380 | int nSep; /* Number of bytes in spec.zColumnSep */ |
| 30381 | char *zSql = 0; /* An SQL statement */ |
| 30382 | ImportCtx sCtx; /* Reader context */ |
| 30383 | char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ |
| 30384 | int eVerbose = 0; /* Larger for more console output */ |
| 30385 | i64 nSkip = 0; /* Initial lines to skip */ |
| 30386 | int useOutputMode = 1; /* Use output mode to determine separators */ |
| 30387 | char *zCreate = 0; /* CREATE TABLE statement text */ |
| 30388 | int rc; /* Result code */ |
| 30389 | |
| 30390 | failIfSafeMode(p, "cannot run .import in safe mode"); |
| 30391 | memset(&sCtx, 0, sizeof(sCtx)); |
| @@ -30411,70 +30723,71 @@ | |
| 30411 | }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){ |
| 30412 | zSchema = azArg[++i]; |
| 30413 | }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){ |
| 30414 | nSkip = integerValue(azArg[++i]); |
| 30415 | }else if( cli_strcmp(z,"-ascii")==0 ){ |
| 30416 | sCtx.cColSep = SEP_Unit[0]; |
| 30417 | sCtx.cRowSep = SEP_Record[0]; |
| 30418 | xRead = ascii_read_one_field; |
| 30419 | useOutputMode = 0; |
| 30420 | }else if( cli_strcmp(z,"-csv")==0 ){ |
| 30421 | sCtx.cColSep = ','; |
| 30422 | sCtx.cRowSep = '\n'; |
| 30423 | xRead = csv_read_one_field; |
| 30424 | useOutputMode = 0; |
| 30425 | }else{ |
| 30426 | dotCmdError(p, i, "unknown option", 0); |
| 30427 | return 1; |
| 30428 | } |
| 30429 | } |
| 30430 | if( zTable==0 ){ |
| 30431 | cli_printf(p->out, "ERROR: missing %s argument\n", |
| 30432 | zFile==0 ? "FILE" : "TABLE"); |
| 30433 | return 1; |
| 30434 | } |
| 30435 | seenInterrupt = 0; |
| 30436 | open_db(p, 0); |
| 30437 | if( useOutputMode ){ |
| 30438 | /* If neither the --csv or --ascii options are specified, then set |
| 30439 | ** the column and row separator characters from the output mode. */ |
| 30440 | if( p->mode.spec.zColumnSep==0 ){ |
| 30441 | modeSetStr(&p->mode.spec.zColumnSep, ","); |
| 30442 | nSep = 1; |
| 30443 | }else if( (nSep = strlen30(p->mode.spec.zColumnSep))==0 ){ |
| 30444 | eputz("Error: non-null column separator required for import\n"); |
| 30445 | return 1; |
| 30446 | } |
| 30447 | if( nSep>1 ){ |
| 30448 | eputz("Error: multi-character column separators not allowed" |
| 30449 | " for import\n"); |
| 30450 | return 1; |
| 30451 | } |
| 30452 | if( p->mode.spec.zRowSep==0 ){ |
| 30453 | modeSetStr(&p->mode.spec.zRowSep, "\n"); |
| 30454 | nSep = 1; |
| 30455 | }else if( (nSep = strlen30(p->mode.spec.zRowSep))==0 ){ |
| 30456 | eputz("Error: non-null row separator required for import\n"); |
| 30457 | return 1; |
| 30458 | } |
| 30459 | if( nSep==2 && p->mode.eMode==MODE_Csv |
| 30460 | && cli_strcmp(p->mode.spec.zRowSep,SEP_CrLf)==0 |
| 30461 | ){ |
| 30462 | /* When importing CSV (only), if the row separator is set to the |
| 30463 | ** default output row separator, change it to the default input |
| 30464 | ** row separator. This avoids having to maintain different input |
| 30465 | ** and output row separators. */ |
| 30466 | modeSetStr(&p->mode.spec.zRowSep, SEP_Row); |
| 30467 | nSep = strlen30(p->mode.spec.zRowSep); |
| 30468 | } |
| 30469 | if( nSep>1 ){ |
| 30470 | eputz("Error: multi-character row separators not allowed" |
| 30471 | " for import\n"); |
| 30472 | return 1; |
| 30473 | } |
| 30474 | sCtx.cColSep = (u8)p->mode.spec.zColumnSep[0]; |
| 30475 | sCtx.cRowSep = (u8)p->mode.spec.zRowSep[0]; |
| 30476 | } |
| 30477 | sCtx.zFile = zFile; |
| 30478 | sCtx.nLine = 1; |
| 30479 | if( sCtx.zFile[0]=='|' ){ |
| 30480 | #ifdef SQLITE_OMIT_POPEN |
| @@ -30483,19 +30796,58 @@ | |
| 30483 | #else |
| 30484 | sCtx.in = sqlite3_popen(sCtx.zFile+1, "r"); |
| 30485 | sCtx.zFile = "<pipe>"; |
| 30486 | sCtx.xCloser = pclose; |
| 30487 | #endif |
| 30488 | }else{ |
| 30489 | sCtx.in = sqlite3_fopen(sCtx.zFile, "rb"); |
| 30490 | sCtx.xCloser = fclose; |
| 30491 | } |
| 30492 | if( sCtx.in==0 ){ |
| 30493 | cli_printf(stderr,"Error: cannot open \"%s\"\n", zFile); |
| 30494 | return 1; |
| 30495 | } |
| 30496 | if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){ |
| 30497 | char zSep[2]; |
| 30498 | zSep[1] = 0; |
| 30499 | zSep[0] = sCtx.cColSep; |
| 30500 | cli_puts("Column separator ", p->out); |
| 30501 | output_c_string(p->out, zSep); |
| @@ -30648,10 +31000,14 @@ | |
| 30648 | if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){ |
| 30649 | z = ""; |
| 30650 | } |
| 30651 | sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); |
| 30652 | if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){ |
| 30653 | cli_printf(stderr,"%s:%d: expected %d columns but found %d" |
| 30654 | " - filling the rest with NULL\n", |
| 30655 | sCtx.zFile, startLine, nCol, i+1); |
| 30656 | i += 2; |
| 30657 | while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; } |
| @@ -30671,10 +31027,11 @@ | |
| 30671 | rc = sqlite3_reset(pStmt); |
| 30672 | if( rc!=SQLITE_OK ){ |
| 30673 | cli_printf(stderr,"%s:%d: INSERT failed: %s\n", |
| 30674 | sCtx.zFile, startLine, sqlite3_errmsg(p->db)); |
| 30675 | sCtx.nErr++; |
| 30676 | }else{ |
| 30677 | sCtx.nRow++; |
| 30678 | } |
| 30679 | } |
| 30680 | }while( sCtx.cTerm!=EOF ); |
| @@ -30683,13 +31040,13 @@ | |
| 30683 | sqlite3_finalize(pStmt); |
| 30684 | if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); |
| 30685 | if( eVerbose>0 ){ |
| 30686 | cli_printf(p->out, |
| 30687 | "Added %d rows with %d errors using %d lines of input\n", |
| 30688 | sCtx.nRow, sCtx.nErr, sCtx.nLine-1); |
| 30689 | } |
| 30690 | return 0; |
| 30691 | } |
| 30692 | |
| 30693 | |
| 30694 | /* |
| 30695 | ** This function computes what to show the user about the configured |
| @@ -31100,10 +31457,11 @@ | |
| 31100 | if( k<0 ){ |
| 31101 | dotCmdError(p, i, "bad --titles value","%z", zErr); |
| 31102 | return 1; |
| 31103 | } |
| 31104 | p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No; |
| 31105 | p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr; |
| 31106 | chng = 1; |
| 31107 | }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){ |
| 31108 | int nWidth = 0; |
| 31109 | short int *aWidth; |
| @@ -31328,23 +31686,17 @@ | |
| 31328 | ** --bom Prepend a byte-order mark to the output |
| 31329 | ** -e Accumulate output in a temporary text file then |
| 31330 | ** launch a text editor when the redirection ends. |
| 31331 | ** --error-prefix X Use X as the left-margin prefix for error messages. |
| 31332 | ** Set to an empty string to restore the default. |
| 31333 | ** --glob GLOB Raise an error if the memory buffer does not match |
| 31334 | ** the GLOB pattern. |
| 31335 | ** --keep Continue using the same "memory" buffer. Do not |
| 31336 | ** reset it or delete it. Useful in combination with |
| 31337 | ** --glob, --not-glob, and/or --verify. |
| 31338 | ** ---notglob GLOB Raise an error if the memory buffer does not match |
| 31339 | ** the GLOB pattern. |
| 31340 | ** --plain Use plain text rather than HTML tables with -w |
| 31341 | ** --show Write the memory buffer to the screen, for debugging. |
| 31342 | ** --verify ENDMARK Read subsequent lines of text until the first line |
| 31343 | ** that matches ENDMARK. Discard the ENDMARK. Compare |
| 31344 | ** the text against the accumulated output in memory and |
| 31345 | ** raise an error if there are any differences. |
| 31346 | ** -w Show the output in a web browser. Output is |
| 31347 | ** written into a temporary HTML file until the |
| 31348 | ** redirect ends, then the web browser is launched. |
| 31349 | ** Query results are shown as HTML tables, unless |
| 31350 | ** the --plain is used too. |
| @@ -31382,13 +31734,11 @@ | |
| 31382 | char *zFile = 0; /* The FILE argument */ |
| 31383 | int i; /* Loop counter */ |
| 31384 | int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */ |
| 31385 | int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */ |
| 31386 | int bPlain = 0; /* --plain option */ |
| 31387 | int bKeep = 0; /* --keep option */ |
| 31388 | char *zCheck = 0; /* Argument to --glob, --notglob, --verify */ |
| 31389 | int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --verify */ |
| 31390 | static const char *zBomUtf8 = "\357\273\277"; |
| 31391 | const char *zBom = 0; |
| 31392 | char c = azArg[0][0]; |
| 31393 | int n = strlen30(azArg[0]); |
| 31394 | |
| @@ -31410,36 +31760,21 @@ | |
| 31410 | zBom = zBomUtf8; |
| 31411 | }else if( cli_strcmp(z,"-plain")==0 ){ |
| 31412 | bPlain = 1; |
| 31413 | }else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0 |
| 31414 | && (z[1]=='x' || z[1]=='e' || z[1]=='w') ){ |
| 31415 | if( bKeep || eMode || eCheck ){ |
| 31416 | dotCmdError(p, i, "incompatible with prior options",0); |
| 31417 | goto dotCmdOutput_error; |
| 31418 | } |
| 31419 | eMode = z[1]; |
| 31420 | }else if( cli_strcmp(z,"-keep")==0 ){ |
| 31421 | bKeep = 1; |
| 31422 | }else if( cli_strcmp(z,"-show")==0 ){ |
| 31423 | if( cli_output_capture ){ |
| 31424 | sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture)); |
| 31425 | } |
| 31426 | bKeep = 1; |
| 31427 | }else if( cli_strcmp(z,"-glob")==0 |
| 31428 | || cli_strcmp(z,"-notglob")==0 |
| 31429 | || cli_strcmp(z,"-verify")==0 |
| 31430 | ){ |
| 31431 | if( eCheck || eMode ){ |
| 31432 | dotCmdError(p, i, "incompatible with prior options",0); |
| 31433 | goto dotCmdOutput_error; |
| 31434 | } |
| 31435 | if( i+1>=nArg ){ |
| 31436 | dotCmdError(p, i, "missing argument", 0); |
| 31437 | goto dotCmdOutput_error; |
| 31438 | } |
| 31439 | zCheck = azArg[++i]; |
| 31440 | eCheck = z[1]=='g' ? 1 : z[1]=='n' ? 2 : 3; |
| 31441 | }else if( optionMatch(z,"error-prefix") ){ |
| 31442 | if( i+1>=nArg ){ |
| 31443 | dotCmdError(p, i, "missing argument", 0); |
| 31444 | return 1; |
| 31445 | } |
| @@ -31450,11 +31785,11 @@ | |
| 31450 | dotCmdError(p, i, "unknown option", 0); |
| 31451 | sqlite3_free(zFile); |
| 31452 | return 1; |
| 31453 | } |
| 31454 | }else if( zFile==0 && eMode==0 ){ |
| 31455 | if( bKeep || eCheck ){ |
| 31456 | dotCmdError(p, i, "incompatible with prior options",0); |
| 31457 | goto dotCmdOutput_error; |
| 31458 | } |
| 31459 | if( cli_strcmp(z, "memory")==0 && bOnce ){ |
| 31460 | dotCmdError(p, 0, "cannot redirect to \"memory\"", 0); |
| @@ -31486,53 +31821,10 @@ | |
| 31486 | if( bOnce ){ |
| 31487 | p->nPopOutput = 2; |
| 31488 | }else{ |
| 31489 | p->nPopOutput = 0; |
| 31490 | } |
| 31491 | if( eCheck ){ |
| 31492 | char *zTest; |
| 31493 | if( cli_output_capture ){ |
| 31494 | zTest = sqlite3_str_value(cli_output_capture); |
| 31495 | }else{ |
| 31496 | zTest = ""; |
| 31497 | } |
| 31498 | p->nTestRun++; |
| 31499 | if( eCheck==3 ){ |
| 31500 | int nCheck = strlen30(zCheck); |
| 31501 | sqlite3_str *pPattern = sqlite3_str_new(p->db); |
| 31502 | char *zPattern; |
| 31503 | sqlite3_int64 iStart = p->lineno; |
| 31504 | char zLine[2000]; |
| 31505 | while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){ |
| 31506 | if( strchr(zLine,'\n') ) p->lineno++; |
| 31507 | if( cli_strncmp(zCheck,zLine,nCheck)==0 ) break; |
| 31508 | sqlite3_str_appendall(pPattern, zLine); |
| 31509 | } |
| 31510 | zPattern = sqlite3_str_finish(pPattern); |
| 31511 | if( cli_strcmp(zPattern,zTest)!=0 ){ |
| 31512 | sqlite3_fprintf(stderr, |
| 31513 | "%s:%lld: --verify does matches prior output\n", |
| 31514 | p->zInFile, iStart); |
| 31515 | p->nTestErr++; |
| 31516 | } |
| 31517 | sqlite3_free(zPattern); |
| 31518 | }else{ |
| 31519 | char *zGlob = sqlite3_mprintf("*%s*", zCheck); |
| 31520 | if( eCheck==1 && sqlite3_strglob(zGlob, zTest)!=0 ){ |
| 31521 | sqlite3_fprintf(stderr, |
| 31522 | "%s:%lld: --glob \"%s\" does not match prior output\n", |
| 31523 | p->zInFile, p->lineno, zCheck); |
| 31524 | p->nTestErr++; |
| 31525 | }else if( eCheck==2 && sqlite3_strglob(zGlob, zTest)==0 ){ |
| 31526 | sqlite3_fprintf(stderr, |
| 31527 | "%s:%lld: --notglob \"%s\" matches prior output\n", |
| 31528 | p->zInFile, p->lineno, zCheck); |
| 31529 | p->nTestErr++; |
| 31530 | } |
| 31531 | sqlite3_free(zGlob); |
| 31532 | } |
| 31533 | } |
| 31534 | if( !bKeep ) output_reset(p); |
| 31535 | #ifndef SQLITE_NOHAVE_SYSTEM |
| 31536 | if( eMode=='e' || eMode=='x' || eMode=='w' ){ |
| 31537 | p->doXdgOpen = 1; |
| 31538 | modePush(p); |
| @@ -31609,10 +31901,199 @@ | |
| 31609 | |
| 31610 | dotCmdOutput_error: |
| 31611 | sqlite3_free(zFile); |
| 31612 | return 1; |
| 31613 | } |
| 31614 | |
| 31615 | /* |
| 31616 | ** Enlarge the space allocated in p->dot so that it can hold more |
| 31617 | ** than nArg parsed command-line arguments. |
| 31618 | */ |
| @@ -31641,11 +32122,11 @@ | |
| 31641 | free(p->dot.zCopy); |
| 31642 | z = p->dot.zCopy = strdup(zLine); |
| 31643 | shell_check_oom(z); |
| 31644 | szLine = strlen(z); |
| 31645 | while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--; |
| 31646 | if( szLine>0 && z[szLine-1]==';' && p->iCompat>=20251115 ){ |
| 31647 | szLine--; |
| 31648 | while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--; |
| 31649 | } |
| 31650 | z[szLine] = 0; |
| 31651 | parseDotRealloc(p, 2); |
| @@ -31861,35 +32342,17 @@ | |
| 31861 | eputz("Usage: .changes on|off\n"); |
| 31862 | rc = 1; |
| 31863 | } |
| 31864 | }else |
| 31865 | |
| 31866 | #ifndef SQLITE_SHELL_FIDDLE |
| 31867 | /* Cancel output redirection, if it is currently set (by .testcase) |
| 31868 | ** Then read the content of the testcase-out.txt file and compare against |
| 31869 | ** azArg[1]. If there are differences, report an error and exit. |
| 31870 | */ |
| 31871 | if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){ |
| 31872 | char *zRes = 0; |
| 31873 | output_reset(p); |
| 31874 | if( nArg!=2 ){ |
| 31875 | eputz("Usage: .check GLOB-PATTERN\n"); |
| 31876 | rc = 2; |
| 31877 | }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ |
| 31878 | rc = 2; |
| 31879 | }else if( testcase_glob(azArg[1],zRes)==0 ){ |
| 31880 | cli_printf(stderr, |
| 31881 | "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", |
| 31882 | p->zTestcase, azArg[1], zRes); |
| 31883 | rc = 1; |
| 31884 | }else{ |
| 31885 | cli_printf(p->out, "testcase-%s ok\n", p->zTestcase); |
| 31886 | p->nCheck++; |
| 31887 | } |
| 31888 | sqlite3_free(zRes); |
| 31889 | }else |
| 31890 | #endif /* !defined(SQLITE_SHELL_FIDDLE) */ |
| 31891 | |
| 31892 | #ifndef SQLITE_SHELL_FIDDLE |
| 31893 | if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){ |
| 31894 | failIfSafeMode(p, "cannot run .clone in safe mode"); |
| 31895 | if( nArg==2 ){ |
| @@ -32468,10 +32931,11 @@ | |
| 32468 | }else |
| 32469 | |
| 32470 | if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){ |
| 32471 | if( nArg==2 ){ |
| 32472 | p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No; |
| 32473 | p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr; |
| 32474 | }else{ |
| 32475 | eputz("Usage: .headers on|off\n"); |
| 32476 | rc = 1; |
| 32477 | } |
| @@ -32521,14 +32985,14 @@ | |
| 32521 | sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); |
| 32522 | goto meta_command_exit; |
| 32523 | } |
| 32524 | zSql = sqlite3_mprintf( |
| 32525 | "SELECT rootpage, 0 FROM sqlite_schema" |
| 32526 | " WHERE name='%q' AND type='index'" |
| 32527 | "UNION ALL " |
| 32528 | "SELECT rootpage, 1 FROM sqlite_schema" |
| 32529 | " WHERE name='%q' AND type='table'" |
| 32530 | " AND sql LIKE '%%without%%rowid%%'", |
| 32531 | azArg[1], azArg[1] |
| 32532 | ); |
| 32533 | sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 32534 | sqlite3_free(zSql); |
| @@ -32682,13 +33146,14 @@ | |
| 32682 | goto meta_command_exit; |
| 32683 | } |
| 32684 | if( nArg==3 ){ |
| 32685 | sqlite3_limit(p->db, aLimit[iLimit].limitCode, |
| 32686 | (int)integerValue(azArg[2])); |
| 32687 | } |
| 32688 | cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName, |
| 32689 | sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); |
| 32690 | } |
| 32691 | }else |
| 32692 | |
| 32693 | if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){ |
| 32694 | open_db(p, 0); |
| @@ -33027,10 +33492,23 @@ | |
| 33027 | continue; |
| 33028 | } |
| 33029 | if( cli_strcmp(z,"once")==0 ){ |
| 33030 | p->flgProgress |= SHELL_PROGRESS_ONCE; |
| 33031 | continue; |
| 33032 | } |
| 33033 | if( cli_strcmp(z,"limit")==0 ){ |
| 33034 | if( i+1>=nArg ){ |
| 33035 | eputz("Error: missing argument on --limit\n"); |
| 33036 | rc = 1; |
| @@ -33233,21 +33711,22 @@ | |
| 33233 | || sqlite3_strlike(zName, "sqlite_schema", '\\')==0 |
| 33234 | || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 |
| 33235 | || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0; |
| 33236 | if( isSchema ){ |
| 33237 | cli_printf(p->out, |
| 33238 | "CREATE TABLE %s (\n" |
| 33239 | " type text,\n" |
| 33240 | " name text,\n" |
| 33241 | " tbl_name text,\n" |
| 33242 | " rootpage integer,\n" |
| 33243 | " sql text\n" |
| 33244 | ");\n", zName); |
| 33245 | } |
| 33246 | } |
| 33247 | rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list", |
| 33248 | -1, &pStmt, 0); |
| 33249 | if( rc ){ |
| 33250 | shellDatabaseError(p->db); |
| 33251 | sqlite3_finalize(pStmt); |
| 33252 | |
| 33253 | rc = 1; |
| @@ -33255,11 +33734,11 @@ | |
| 33255 | } |
| 33256 | pSql = sqlite3_str_new(p->db); |
| 33257 | sqlite3_str_appendf(pSql, "SELECT sql FROM", 0); |
| 33258 | iSchema = 0; |
| 33259 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 33260 | const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); |
| 33261 | char zScNum[30]; |
| 33262 | sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); |
| 33263 | sqlite3_str_appendall(pSql, zDiv); |
| 33264 | zDiv = " UNION ALL "; |
| 33265 | if( sqlite3_stricmp(zDb, "main")==0 ){ |
| @@ -33275,11 +33754,12 @@ | |
| 33275 | " AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname", |
| 33276 | ++iSchema, zDb); |
| 33277 | sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb); |
| 33278 | } |
| 33279 | sqlite3_finalize(pStmt); |
| 33280 | #ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS |
| 33281 | if( zName ){ |
| 33282 | sqlite3_str_appendall(pSql, |
| 33283 | " UNION ALL SELECT shell_module_schema(name)," |
| 33284 | " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list"); |
| 33285 | } |
| @@ -33299,11 +33779,11 @@ | |
| 33299 | }else{ |
| 33300 | sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName); |
| 33301 | } |
| 33302 | } |
| 33303 | if( bNoSystemTabs ){ |
| 33304 | sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCALE '_' AND "); |
| 33305 | } |
| 33306 | sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid"); |
| 33307 | if( bDebug ){ |
| 33308 | cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql)); |
| 33309 | }else{ |
| @@ -34017,25 +34497,15 @@ | |
| 34017 | sqlite3_str_free(pSql); |
| 34018 | modePop(p); |
| 34019 | if( rc ) return shellDatabaseError(p->db); |
| 34020 | }else |
| 34021 | |
| 34022 | #ifndef SQLITE_SHELL_FIDDLE |
| 34023 | /* Begin redirecting output to the file "testcase-out.txt" */ |
| 34024 | if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){ |
| 34025 | output_reset(p); |
| 34026 | p->out = output_file_open(p, "testcase-out.txt"); |
| 34027 | if( p->out==0 ){ |
| 34028 | eputz("Error: cannot open 'testcase-out.txt'\n"); |
| 34029 | } |
| 34030 | if( nArg>=2 ){ |
| 34031 | sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); |
| 34032 | }else{ |
| 34033 | sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); |
| 34034 | } |
| 34035 | }else |
| 34036 | #endif /* !defined(SQLITE_SHELL_FIDDLE) */ |
| 34037 | |
| 34038 | #ifndef SQLITE_UNTESTABLE |
| 34039 | if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){ |
| 34040 | static const struct { |
| 34041 | const char *zCtrlName; /* Name of a test-control option */ |
| @@ -34527,17 +34997,21 @@ | |
| 34527 | sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); |
| 34528 | }else |
| 34529 | |
| 34530 | if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){ |
| 34531 | if( nArg==2 ){ |
| 34532 | enableTimer = booleanValue(azArg[1]); |
| 34533 | if( enableTimer && !HAS_TIMER ){ |
| 34534 | eputz("Error: timer not available on this system.\n"); |
| 34535 | enableTimer = 0; |
| 34536 | } |
| 34537 | }else{ |
| 34538 | eputz("Usage: .timer on|off\n"); |
| 34539 | rc = 1; |
| 34540 | } |
| 34541 | }else |
| 34542 | |
| 34543 | #ifndef SQLITE_OMIT_TRACE |
| @@ -34708,10 +35182,11 @@ | |
| 34708 | if( p->nPopOutput ){ |
| 34709 | p->nPopOutput--; |
| 34710 | if( p->nPopOutput==0 ) output_reset(p); |
| 34711 | } |
| 34712 | p->bSafeMode = p->bSafeModePersist; |
| 34713 | return rc; |
| 34714 | } |
| 34715 | |
| 34716 | /* Line scan result and intermediate states (supporting scan resumption) |
| 34717 | */ |
| @@ -34944,13 +35419,13 @@ | |
| 34944 | char *zErrMsg = 0; |
| 34945 | |
| 34946 | open_db(p, 0); |
| 34947 | if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql); |
| 34948 | if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; |
| 34949 | BEGIN_TIMER; |
| 34950 | rc = shell_exec(p, zSql, &zErrMsg); |
| 34951 | END_TIMER(p->out); |
| 34952 | if( rc || zErrMsg ){ |
| 34953 | char zPrefix[100]; |
| 34954 | const char *zErrorTail; |
| 34955 | const char *zErrorType; |
| 34956 | if( zErrMsg==0 ){ |
| @@ -35351,11 +35826,10 @@ | |
| 35351 | " -bail stop after hitting an error\n" |
| 35352 | " -batch force batch I/O\n" |
| 35353 | " -box set output mode to 'box'\n" |
| 35354 | " -cmd COMMAND run \"COMMAND\" before reading stdin\n" |
| 35355 | " -column set output mode to 'column'\n" |
| 35356 | " -compat YYYYMMDD set default options for date YYYYMMDD\n" |
| 35357 | " -csv set output mode to 'csv'\n" |
| 35358 | #if !defined(SQLITE_OMIT_DESERIALIZE) |
| 35359 | " -deserialize open the database using sqlite3_deserialize()\n" |
| 35360 | #endif |
| 35361 | " -echo print inputs before execution\n" |
| @@ -35435,15 +35909,10 @@ | |
| 35435 | /* |
| 35436 | ** Initialize the state information in data |
| 35437 | */ |
| 35438 | static void main_init(ShellState *p) { |
| 35439 | memset(p, 0, sizeof(*p)); |
| 35440 | #if defined(COMPATIBILITY_DATE) |
| 35441 | p->iCompat = COMPATIBILITY_DATE; |
| 35442 | #else |
| 35443 | p->iCompat = 20251116; |
| 35444 | #endif |
| 35445 | p->pAuxDb = &p->aAuxDb[0]; |
| 35446 | p->shellFlgs = SHFLG_Lookaside; |
| 35447 | sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p); |
| 35448 | #if !defined(SQLITE_SHELL_FIDDLE) |
| 35449 | verify_uninitialized(); |
| @@ -35498,29 +35967,65 @@ | |
| 35498 | cli_puts(z, p->out); |
| 35499 | fflush(p->out); |
| 35500 | return 1; |
| 35501 | } |
| 35502 | |
| 35503 | #ifndef SQLITE_SHELL_IS_UTF8 |
| 35504 | # if (defined(_WIN32) || defined(WIN32)) \ |
| 35505 | && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__))) |
| 35506 | # define SQLITE_SHELL_IS_UTF8 (0) |
| 35507 | # else |
| 35508 | # define SQLITE_SHELL_IS_UTF8 (1) |
| 35509 | # endif |
| 35510 | #endif |
| 35511 | |
| 35512 | #ifdef SQLITE_SHELL_FIDDLE |
| 35513 | # define main fiddle_main |
| 35514 | #endif |
| 35515 | |
| 35516 | #if SQLITE_SHELL_IS_UTF8 |
| 35517 | int SQLITE_CDECL main(int argc, char **argv){ |
| 35518 | #else |
| 35519 | int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ |
| 35520 | char **argv; |
| 35521 | #endif |
| 35522 | #ifdef SQLITE_DEBUG |
| 35523 | sqlite3_int64 mem_main_enter = 0; |
| 35524 | #endif |
| 35525 | char *zErrMsg = 0; |
| 35526 | #ifdef SQLITE_SHELL_FIDDLE |
| @@ -35538,14 +36043,10 @@ | |
| 35538 | int nOptsEnd = argc; |
| 35539 | int bEnableVfstrace = 0; |
| 35540 | char **azCmd = 0; |
| 35541 | int *aiCmd = 0; |
| 35542 | const char *zVfs = 0; /* Value of -vfs command-line option */ |
| 35543 | #if !SQLITE_SHELL_IS_UTF8 |
| 35544 | char **argvToFree = 0; |
| 35545 | int argcToFree = 0; |
| 35546 | #endif |
| 35547 | setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ |
| 35548 | |
| 35549 | #ifdef SQLITE_SHELL_FIDDLE |
| 35550 | stdin_is_interactive = 0; |
| 35551 | stdout_is_console = 1; |
| @@ -35596,36 +36097,10 @@ | |
| 35596 | exit(1); |
| 35597 | } |
| 35598 | #endif |
| 35599 | main_init(&data); |
| 35600 | |
| 35601 | /* On Windows, we must translate command-line arguments into UTF-8. |
| 35602 | ** The SQLite memory allocator subsystem has to be enabled in order to |
| 35603 | ** do this. But we want to run an sqlite3_shutdown() afterwards so that |
| 35604 | ** subsequent sqlite3_config() calls will work. So copy all results into |
| 35605 | ** memory that does not come from the SQLite memory allocator. |
| 35606 | */ |
| 35607 | #if !SQLITE_SHELL_IS_UTF8 |
| 35608 | sqlite3_initialize(); |
| 35609 | argvToFree = malloc(sizeof(argv[0])*argc*2); |
| 35610 | shell_check_oom(argvToFree); |
| 35611 | argcToFree = argc; |
| 35612 | argv = argvToFree + argc; |
| 35613 | for(i=0; i<argc; i++){ |
| 35614 | char *z = sqlite3_win32_unicode_to_utf8(wargv[i]); |
| 35615 | i64 n; |
| 35616 | shell_check_oom(z); |
| 35617 | n = strlen(z); |
| 35618 | argv[i] = malloc( n+1 ); |
| 35619 | shell_check_oom(argv[i]); |
| 35620 | memcpy(argv[i], z, n+1); |
| 35621 | argvToFree[i] = argv[i]; |
| 35622 | sqlite3_free(z); |
| 35623 | } |
| 35624 | sqlite3_shutdown(); |
| 35625 | #endif |
| 35626 | |
| 35627 | assert( argc>=1 && argv && argv[0] ); |
| 35628 | Argv0 = argv[0]; |
| 35629 | |
| 35630 | #ifdef SQLITE_SHELL_DBNAME_PROC |
| 35631 | { |
| @@ -35637,11 +36112,11 @@ | |
| 35637 | SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename); |
| 35638 | warnInmemoryDb = 0; |
| 35639 | } |
| 35640 | #endif |
| 35641 | |
| 35642 | /* Do an initial pass through the command-line argument to locate |
| 35643 | ** the name of the database file, the name of the initialization file, |
| 35644 | ** the size of the alternative malloc heap, options affecting commands |
| 35645 | ** or SQL run from the command line, and the first command to execute. |
| 35646 | */ |
| 35647 | #ifndef SQLITE_SHELL_FIDDLE |
| @@ -35649,11 +36124,11 @@ | |
| 35649 | #endif |
| 35650 | for(i=1; i<argc; i++){ |
| 35651 | char *z; |
| 35652 | z = argv[i]; |
| 35653 | if( z[0]!='-' || i>nOptsEnd ){ |
| 35654 | if( data.aAuxDb->zDbFilename==0 ){ |
| 35655 | data.aAuxDb->zDbFilename = z; |
| 35656 | }else{ |
| 35657 | /* Excess arguments are interpreted as SQL (or dot-commands) and |
| 35658 | ** mean that nothing is read from stdin */ |
| 35659 | readStdin = 0; |
| @@ -35694,15 +36169,10 @@ | |
| 35694 | if( n<2 ){ |
| 35695 | sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n"); |
| 35696 | exit(1); |
| 35697 | } |
| 35698 | stdout_tty_width = n; |
| 35699 | }else if( cli_strcmp(z,"-compat")==0 ){ |
| 35700 | data.iCompat = atoi(cmdline_option_value(argc, argv, ++i)); |
| 35701 | modeFree(&data.mode); |
| 35702 | memset(&data.mode, 0, sizeof(data.mode)); |
| 35703 | modeDefault(&data); |
| 35704 | }else if( cli_strcmp(z,"-utf8")==0 ){ |
| 35705 | }else if( cli_strcmp(z,"-no-utf8")==0 ){ |
| 35706 | }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){ |
| 35707 | int val = 0; |
| 35708 | sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val); |
| @@ -35822,10 +36292,20 @@ | |
| 35822 | }else if( cli_strcmp(z,"-safe")==0 ){ |
| 35823 | /* no-op - catch this on the second pass */ |
| 35824 | }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ |
| 35825 | /* skip over the argument */ |
| 35826 | i++; |
| 35827 | } |
| 35828 | } |
| 35829 | #ifndef SQLITE_SHELL_FIDDLE |
| 35830 | if( !bEnableVfstrace ) verify_uninitialized(); |
| 35831 | #endif |
| @@ -35848,11 +36328,30 @@ | |
| 35848 | |
| 35849 | if( zVfs ){ |
| 35850 | sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs); |
| 35851 | if( pVfs ){ |
| 35852 | sqlite3_vfs_register(pVfs, 1); |
| 35853 | }else{ |
| 35854 | cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs); |
| 35855 | exit(1); |
| 35856 | } |
| 35857 | } |
| 35858 | |
| @@ -35889,11 +36388,11 @@ | |
| 35889 | ** is given on the command line, look for a file named ~/.sqliterc and |
| 35890 | ** try to process it. |
| 35891 | */ |
| 35892 | if( !noInit ) process_sqliterc(&data,zInitFile); |
| 35893 | |
| 35894 | /* Make a second pass through the command-line argument and set |
| 35895 | ** options. This second pass is delayed until after the initialization |
| 35896 | ** file is processed so that the command-line arguments will override |
| 35897 | ** settings in the initialization file. |
| 35898 | */ |
| 35899 | for(i=1; i<argc; i++){ |
| @@ -36015,12 +36514,10 @@ | |
| 36015 | stdin_is_interactive = 1; |
| 36016 | }else if( cli_strcmp(z,"-batch")==0 ){ |
| 36017 | /* already handled */ |
| 36018 | }else if( cli_strcmp(z,"-screenwidth")==0 ){ |
| 36019 | i++; |
| 36020 | }else if( cli_strcmp(z,"-compat")==0 ){ |
| 36021 | i++; |
| 36022 | }else if( cli_strcmp(z,"-utf8")==0 ){ |
| 36023 | /* already handled */ |
| 36024 | }else if( cli_strcmp(z,"-no-utf8")==0 ){ |
| 36025 | /* already handled */ |
| 36026 | }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){ |
| @@ -36116,11 +36613,22 @@ | |
| 36116 | ** command-line inputs, except for the argToSkip argument which contains |
| 36117 | ** the database filename. |
| 36118 | */ |
| 36119 | for(i=0; i<nCmd; i++){ |
| 36120 | echo_group_input(&data, azCmd[i]); |
| 36121 | if( azCmd[i][0]=='.' ){ |
| 36122 | char *zErrCtx = malloc( 64 ); |
| 36123 | shell_check_oom(zErrCtx); |
| 36124 | sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]); |
| 36125 | data.zInFile = "<cmdline>"; |
| 36126 | data.zErrPrefix = zErrCtx; |
| @@ -36231,14 +36739,10 @@ | |
| 36231 | } |
| 36232 | find_home_dir(1); |
| 36233 | output_reset(&data); |
| 36234 | data.doXdgOpen = 0; |
| 36235 | clearTempFile(&data); |
| 36236 | #if !SQLITE_SHELL_IS_UTF8 |
| 36237 | for(i=0; i<argcToFree; i++) free(argvToFree[i]); |
| 36238 | free(argvToFree); |
| 36239 | #endif |
| 36240 | modeFree(&data.mode); |
| 36241 | if( data.nSavedModes ){ |
| 36242 | int ii; |
| 36243 | for(ii=0; ii<data.nSavedModes; ii++){ |
| 36244 | modeFree(&data.aSavedModes[ii].mode); |
| 36245 |
| --- extsrc/shell.c | |
| +++ extsrc/shell.c | |
| @@ -35,11 +35,11 @@ | |
| 35 | ** ext/recover/sqlite3recover.h |
| 36 | ** src/shell.c.in |
| 37 | ** |
| 38 | ** To modify this program, get a copy of the canonical SQLite source tree, |
| 39 | ** edit the src/shell.c.in file and/or some of the other files that are |
| 40 | ** listed above, then rerun the command "make shell.c". |
| 41 | */ |
| 42 | /************************* Begin src/shell.c.in ******************/ |
| 43 | /* |
| 44 | ** 2001 September 15 |
| 45 | ** |
| @@ -49,11 +49,11 @@ | |
| 49 | ** May you do good and not evil. |
| 50 | ** May you find forgiveness for yourself and forgive others. |
| 51 | ** May you share freely, never taking more than you give. |
| 52 | ** |
| 53 | ************************************************************************* |
| 54 | ** This file contains code to implement the "sqlite3" command line |
| 55 | ** utility for accessing SQLite databases. |
| 56 | */ |
| 57 | #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) |
| 58 | /* This needs to come before any includes for MSVC compiler */ |
| 59 | #define _CRT_SECURE_NO_WARNINGS |
| @@ -79,10 +79,14 @@ | |
| 79 | ** should only be used when building the "fiddle" web application, as |
| 80 | ** the browser-mode build has much different user input requirements |
| 81 | ** and this build mode rewires the user input subsystem to account for |
| 82 | ** that. |
| 83 | */ |
| 84 | #if defined(SQLITE_SHELL_FIDDLE) |
| 85 | # undef SQLITE_OMIT_LOAD_EXTENSION |
| 86 | # define SQLITE_OMIT_LOAD_EXTENSION 1 |
| 87 | #endif |
| 88 | |
| 89 | /* |
| 90 | ** Warning pragmas copied from msvc.h in the core. |
| 91 | */ |
| 92 | #if defined(_MSC_VER) |
| @@ -872,10 +876,11 @@ | |
| 876 | #ifndef SQLITE_QRF_H |
| 877 | #include "qrf.h" |
| 878 | #endif |
| 879 | #include <string.h> |
| 880 | #include <assert.h> |
| 881 | #include <stdint.h> |
| 882 | |
| 883 | /* typedef sqlite3_int64 i64; */ |
| 884 | |
| 885 | /* A single line in the EQP output */ |
| 886 | typedef struct qrfEQPGraphRow qrfEQPGraphRow; |
| @@ -889,11 +894,12 @@ | |
| 894 | /* All EQP output is collected into an instance of the following */ |
| 895 | typedef struct qrfEQPGraph qrfEQPGraph; |
| 896 | struct qrfEQPGraph { |
| 897 | qrfEQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ |
| 898 | qrfEQPGraphRow *pLast; /* Last element of the pRow list */ |
| 899 | int nWidth; /* Width of the graph */ |
| 900 | char zPrefix[400]; /* Graph prefix */ |
| 901 | }; |
| 902 | |
| 903 | /* |
| 904 | ** Private state information. Subject to change from one release to the |
| 905 | ** next. |
| @@ -995,10 +1001,19 @@ | |
| 1001 | */ |
| 1002 | static void qrfOom(Qrf *p){ |
| 1003 | qrfError(p, SQLITE_NOMEM, "out of memory"); |
| 1004 | } |
| 1005 | |
| 1006 | /* |
| 1007 | ** Transfer any error in pStr over into p. |
| 1008 | */ |
| 1009 | static void qrfStrErr(Qrf *p, sqlite3_str *pStr){ |
| 1010 | int rc = pStr ? sqlite3_str_errcode(pStr) : 0; |
| 1011 | if( rc ){ |
| 1012 | qrfError(p, rc, sqlite3_errstr(rc)); |
| 1013 | } |
| 1014 | } |
| 1015 | |
| 1016 | |
| 1017 | /* |
| 1018 | ** Add a new entry to the EXPLAIN QUERY PLAN data |
| 1019 | */ |
| @@ -1074,10 +1089,49 @@ | |
| 1089 | qrfEqpRenderLevel(p, pRow->iEqpId); |
| 1090 | p->u.pGraph->zPrefix[n] = 0; |
| 1091 | } |
| 1092 | } |
| 1093 | } |
| 1094 | |
| 1095 | /* |
| 1096 | ** Render the 64-bit value N in a more human-readable format into |
| 1097 | ** pOut. |
| 1098 | ** |
| 1099 | ** + Only show the first three significant digits. |
| 1100 | ** + Append suffixes K, M, G, T, P, and E for 1e3, 1e6, ... 1e18 |
| 1101 | */ |
| 1102 | static void qrfApproxInt64(sqlite3_str *pOut, i64 N){ |
| 1103 | static const char aSuffix[] = { 'K', 'M', 'G', 'T', 'P', 'E' }; |
| 1104 | int i; |
| 1105 | if( N<0 ){ |
| 1106 | N = N==INT64_MIN ? INT64_MAX : -N; |
| 1107 | sqlite3_str_append(pOut, "-", 1); |
| 1108 | } |
| 1109 | if( N<10000 ){ |
| 1110 | sqlite3_str_appendf(pOut, "%4lld ", N); |
| 1111 | return; |
| 1112 | } |
| 1113 | for(i=1; i<=18; i++){ |
| 1114 | N = (N+5)/10; |
| 1115 | if( N<10000 ){ |
| 1116 | int n = (int)N; |
| 1117 | switch( i%3 ){ |
| 1118 | case 0: |
| 1119 | sqlite3_str_appendf(pOut, "%d.%02d", n/1000, (n%1000)/10); |
| 1120 | break; |
| 1121 | case 1: |
| 1122 | sqlite3_str_appendf(pOut, "%2d.%d", n/100, (n%100)/10); |
| 1123 | break; |
| 1124 | case 2: |
| 1125 | sqlite3_str_appendf(pOut, "%4d", n/10); |
| 1126 | break; |
| 1127 | } |
| 1128 | sqlite3_str_append(pOut, &aSuffix[i/3], 1); |
| 1129 | break; |
| 1130 | } |
| 1131 | } |
| 1132 | } |
| 1133 | |
| 1134 | /* |
| 1135 | ** Display and reset the EXPLAIN QUERY PLAN data |
| 1136 | */ |
| 1137 | static void qrfEqpRender(Qrf *p, i64 nCycle){ |
| @@ -1090,11 +1144,30 @@ | |
| 1144 | } |
| 1145 | sqlite3_str_appendf(p->pOut, "%s\n", pRow->zText+3); |
| 1146 | p->u.pGraph->pRow = pRow->pNext; |
| 1147 | sqlite3_free(pRow); |
| 1148 | }else if( nCycle>0 ){ |
| 1149 | int nSp = p->u.pGraph->nWidth - 2; |
| 1150 | if( p->spec.eStyle==QRF_STYLE_StatsEst ){ |
| 1151 | sqlite3_str_appendchar(p->pOut, nSp, ' '); |
| 1152 | sqlite3_str_appendall(p->pOut, |
| 1153 | "Cycles Loops (est) Rows (est)\n"); |
| 1154 | sqlite3_str_appendchar(p->pOut, nSp, ' '); |
| 1155 | sqlite3_str_appendall(p->pOut, |
| 1156 | "---------- ------------ ------------\n"); |
| 1157 | }else{ |
| 1158 | sqlite3_str_appendchar(p->pOut, nSp, ' '); |
| 1159 | sqlite3_str_appendall(p->pOut, |
| 1160 | "Cycles Loops Rows \n"); |
| 1161 | sqlite3_str_appendchar(p->pOut, nSp, ' '); |
| 1162 | sqlite3_str_appendall(p->pOut, |
| 1163 | "---------- ----- -----\n"); |
| 1164 | } |
| 1165 | sqlite3_str_appendall(p->pOut, "QUERY PLAN"); |
| 1166 | sqlite3_str_appendchar(p->pOut, nSp - 10, ' '); |
| 1167 | qrfApproxInt64(p->pOut, nCycle); |
| 1168 | sqlite3_str_appendall(p->pOut, " 100%\n"); |
| 1169 | }else{ |
| 1170 | sqlite3_str_appendall(p->pOut, "QUERY PLAN\n"); |
| 1171 | } |
| 1172 | p->u.pGraph->zPrefix[0] = 0; |
| 1173 | qrfEqpRenderLevel(p, 0); |
| @@ -1145,10 +1218,12 @@ | |
| 1218 | static const int f = SQLITE_SCANSTAT_COMPLEX; |
| 1219 | sqlite3_stmt *pS = p->pStmt; |
| 1220 | int i = 0; |
| 1221 | i64 nTotal = 0; |
| 1222 | int nWidth = 0; |
| 1223 | int prevPid = -1; /* Previous iPid */ |
| 1224 | double rEstCum = 1.0; /* Cumulative row estimate */ |
| 1225 | sqlite3_str *pLine = sqlite3_str_new(p->db); |
| 1226 | sqlite3_str *pStats = sqlite3_str_new(p->db); |
| 1227 | qrfEqpReset(p); |
| 1228 | |
| 1229 | for(i=0; 1; i++){ |
| @@ -1158,11 +1233,11 @@ | |
| 1233 | break; |
| 1234 | } |
| 1235 | n = (int)strlen(z) + qrfStatsHeight(pS,i)*3; |
| 1236 | if( n>nWidth ) nWidth = n; |
| 1237 | } |
| 1238 | nWidth += 2; |
| 1239 | |
| 1240 | sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal); |
| 1241 | for(i=0; 1; i++){ |
| 1242 | i64 nLoop = 0; |
| 1243 | i64 nRow = 0; |
| @@ -1173,55 +1248,67 @@ | |
| 1248 | const char *zName = 0; |
| 1249 | double rEst = 0.0; |
| 1250 | |
| 1251 | if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){ |
| 1252 | break; |
| 1253 | } |
| 1254 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid); |
| 1255 | if( iPid!=prevPid ){ |
| 1256 | prevPid = iPid; |
| 1257 | rEstCum = 1.0; |
| 1258 | } |
| 1259 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst); |
| 1260 | rEstCum *= rEst; |
| 1261 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop); |
| 1262 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow); |
| 1263 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle); |
| 1264 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId); |
| 1265 | sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName); |
| 1266 | |
| 1267 | if( nCycle>=0 || nLoop>=0 || nRow>=0 ){ |
| 1268 | int nSp = 0; |
| 1269 | sqlite3_str_reset(pStats); |
| 1270 | if( nCycle>=0 && nTotal>0 ){ |
| 1271 | qrfApproxInt64(pStats, nCycle); |
| 1272 | sqlite3_str_appendf(pStats, " %3d%%", |
| 1273 | ((nCycle*100)+nTotal/2) / nTotal |
| 1274 | ); |
| 1275 | nSp = 2; |
| 1276 | } |
| 1277 | if( nLoop>=0 ){ |
| 1278 | if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' '); |
| 1279 | qrfApproxInt64(pStats, nLoop); |
| 1280 | nSp = 2; |
| 1281 | if( p->spec.eStyle==QRF_STYLE_StatsEst ){ |
| 1282 | sqlite3_str_appendf(pStats, " "); |
| 1283 | qrfApproxInt64(pStats, (i64)(rEstCum/rEst)); |
| 1284 | } |
| 1285 | } |
| 1286 | if( nRow>=0 ){ |
| 1287 | if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' '); |
| 1288 | qrfApproxInt64(pStats, nRow); |
| 1289 | nSp = 2; |
| 1290 | if( p->spec.eStyle==QRF_STYLE_StatsEst ){ |
| 1291 | sqlite3_str_appendf(pStats, " "); |
| 1292 | qrfApproxInt64(pStats, (i64)rEstCum); |
| 1293 | } |
| 1294 | } |
| 1295 | sqlite3_str_appendf(pLine, |
| 1296 | "% *s %s", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo, |
| 1297 | sqlite3_str_value(pStats) |
| 1298 | ); |
| 1299 | sqlite3_str_reset(pStats); |
| 1300 | qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine)); |
| 1301 | sqlite3_str_reset(pLine); |
| 1302 | }else{ |
| 1303 | qrfEqpAppend(p, iId, iPid, zo); |
| 1304 | } |
| 1305 | } |
| 1306 | if( p->u.pGraph ) p->u.pGraph->nWidth = nWidth; |
| 1307 | qrfStrErr(p, pLine); |
| 1308 | sqlite3_free(sqlite3_str_finish(pLine)); |
| 1309 | qrfStrErr(p, pStats); |
| 1310 | sqlite3_free(sqlite3_str_finish(pStats)); |
| 1311 | #endif |
| 1312 | } |
| 1313 | |
| 1314 | |
| @@ -1581,13 +1668,15 @@ | |
| 1668 | ** (3) z[] does not looks like a numeric literal |
| 1669 | */ |
| 1670 | static int qrfRelaxable(Qrf *p, const char *z){ |
| 1671 | size_t i, n; |
| 1672 | if( z[0]=='\'' || qrfSpace(z[0]) ) return 0; |
| 1673 | if( z[0]==0 ){ |
| 1674 | return (p->spec.zNull!=0 && p->spec.zNull[0]!=0); |
| 1675 | } |
| 1676 | n = strlen(z); |
| 1677 | if( n==0 || z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0; |
| 1678 | if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0; |
| 1679 | i = (z[0]=='-' || z[0]=='+'); |
| 1680 | if( strcmp(z+i,"Inf")==0 ) return 0; |
| 1681 | if( !qrfDigit(z[i]) ) return 1; |
| 1682 | i++; |
| @@ -2729,10 +2818,11 @@ | |
| 2818 | int nNL = 0; |
| 2819 | int n, w; |
| 2820 | pStr = sqlite3_str_new(p->db); |
| 2821 | qrfEncodeText(p, pStr, z ? z : ""); |
| 2822 | n = sqlite3_str_length(pStr); |
| 2823 | qrfStrErr(p, pStr); |
| 2824 | z = data.az[data.n] = sqlite3_str_finish(pStr); |
| 2825 | if( p->spec.nTitleLimit ){ |
| 2826 | nNL = 0; |
| 2827 | data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n], |
| 2828 | p->spec.nTitleLimit ); |
| @@ -2756,10 +2846,11 @@ | |
| 2846 | int n, w; |
| 2847 | int eType = sqlite3_column_type(p->pStmt,i); |
| 2848 | pStr = sqlite3_str_new(p->db); |
| 2849 | qrfRenderValue(p, pStr, i); |
| 2850 | n = sqlite3_str_length(pStr); |
| 2851 | qrfStrErr(p, pStr); |
| 2852 | z = data.az[data.n] = sqlite3_str_finish(pStr); |
| 2853 | data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT; |
| 2854 | data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL); |
| 2855 | data.n++; |
| 2856 | if( w>data.a[i].mxW ) data.a[i].mxW = w; |
| @@ -2910,11 +3001,11 @@ | |
| 3001 | ){ |
| 3002 | bRTrim = 1; |
| 3003 | }else{ |
| 3004 | bRTrim = 0; |
| 3005 | } |
| 3006 | for(i=0; i<data.n && sqlite3_str_errcode(p->pOut)==SQLITE_OK; i+=nColumn){ |
| 3007 | int bMore; |
| 3008 | int nRow = 0; |
| 3009 | |
| 3010 | /* Draw a single row of the table. This might be the title line |
| 3011 | ** (if there is a title line) or a row in the body of the table. |
| @@ -3097,11 +3188,11 @@ | |
| 3188 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) ); |
| 3189 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) ); |
| 3190 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) ); |
| 3191 | assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) ); |
| 3192 | |
| 3193 | for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){ |
| 3194 | int iAddr = sqlite3_column_int(p->pStmt, 0); |
| 3195 | const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1); |
| 3196 | int p1 = sqlite3_column_int(p->pStmt, 2); |
| 3197 | int p2 = sqlite3_column_int(p->pStmt, 3); |
| 3198 | |
| @@ -3154,11 +3245,11 @@ | |
| 3245 | nWidth = sizeof(aScanExpWidth)/sizeof(int); |
| 3246 | iIndent = 3; |
| 3247 | } |
| 3248 | if( nArg>nWidth ) nArg = nWidth; |
| 3249 | |
| 3250 | for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW && !p->iErr; iOp++){ |
| 3251 | /* If this is the first row seen, print out the headers */ |
| 3252 | if( iOp==0 ){ |
| 3253 | for(i=0; i<nArg; i++){ |
| 3254 | const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]); |
| 3255 | qrfWidthPrint(p,p->pOut, aWidth[i], zCol); |
| @@ -3410,10 +3501,11 @@ | |
| 3501 | sqlite3_str_append(p->pOut, "\n", 1); |
| 3502 | zVal += iNext; |
| 3503 | }while( zVal[0] ); |
| 3504 | sqlite3_str_reset(pVal); |
| 3505 | } |
| 3506 | qrfStrErr(p, pVal); |
| 3507 | sqlite3_free(sqlite3_str_finish(pVal)); |
| 3508 | qrfWrite(p); |
| 3509 | break; |
| 3510 | } |
| 3511 | case QRF_STYLE_Eqp: { |
| @@ -3473,11 +3565,11 @@ | |
| 3565 | p->pOut = sqlite3_str_new(p->db); |
| 3566 | if( p->pOut==0 ){ |
| 3567 | qrfOom(p); |
| 3568 | return; |
| 3569 | } |
| 3570 | p->iErr = SQLITE_OK; |
| 3571 | p->nCol = sqlite3_column_count(p->pStmt); |
| 3572 | p->nRow = 0; |
| 3573 | sz = sizeof(sqlite3_qrf_spec); |
| 3574 | memcpy(&p->spec, pSpec, sz); |
| 3575 | if( p->spec.zNull==0 ) p->spec.zNull = ""; |
| @@ -3644,17 +3736,27 @@ | |
| 3736 | sqlite3_free(p->u.sLine.azCol); |
| 3737 | } |
| 3738 | break; |
| 3739 | } |
| 3740 | case QRF_STYLE_Stats: |
| 3741 | case QRF_STYLE_StatsEst: { |
| 3742 | i64 nCycle = 0; |
| 3743 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 3744 | sqlite3_stmt_scanstatus_v2(p->pStmt, -1, SQLITE_SCANSTAT_NCYCLE, |
| 3745 | SQLITE_SCANSTAT_COMPLEX, (void*)&nCycle); |
| 3746 | #endif |
| 3747 | qrfEqpRender(p, nCycle); |
| 3748 | qrfWrite(p); |
| 3749 | break; |
| 3750 | } |
| 3751 | case QRF_STYLE_Eqp: { |
| 3752 | qrfEqpRender(p, 0); |
| 3753 | qrfWrite(p); |
| 3754 | break; |
| 3755 | } |
| 3756 | } |
| 3757 | qrfStrErr(p, p->pOut); |
| 3758 | if( p->spec.pzOutput ){ |
| 3759 | if( p->spec.pzOutput[0] ){ |
| 3760 | sqlite3_int64 n, sz; |
| 3761 | char *zCombined; |
| 3762 | sz = strlen(p->spec.pzOutput[0]); |
| @@ -3815,13 +3917,10 @@ | |
| 3917 | |
| 3918 | |
| 3919 | #define eputz(z) cli_puts(z,stderr) |
| 3920 | #define sputz(fp,z) cli_puts(z,fp) |
| 3921 | |
| 3922 | /* A version of strcmp() that works with NULL values */ |
| 3923 | static int cli_strcmp(const char *a, const char *b){ |
| 3924 | if( a==0 ) a = ""; |
| 3925 | if( b==0 ) b = ""; |
| 3926 | return strcmp(a,b); |
| @@ -3834,11 +3933,11 @@ | |
| 3933 | |
| 3934 | /* Return the current wall-clock time in microseconds since the |
| 3935 | ** Unix epoch (1970-01-01T00:00:00Z) |
| 3936 | */ |
| 3937 | static sqlite3_int64 timeOfDay(void){ |
| 3938 | #if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8 |
| 3939 | sqlite3_uint64 t; |
| 3940 | FILETIME tm; |
| 3941 | GetSystemTimePreciseAsFileTime(&tm); |
| 3942 | t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime; |
| 3943 | t += 116444736000000000LL; |
| @@ -3862,154 +3961,10 @@ | |
| 3961 | (void)gettimeofday(&sNow,0); |
| 3962 | return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec; |
| 3963 | #endif |
| 3964 | } |
| 3965 | |
| 3966 | |
| 3967 | /* |
| 3968 | ** Used to prevent warnings about unused parameters |
| 3969 | */ |
| 3970 | #define UNUSED_PARAMETER(x) (void)(x) |
| @@ -4068,10 +4023,18 @@ | |
| 4023 | #define PROMPT_LEN_MAX 128 |
| 4024 | /* First line prompt. default: "sqlite> " */ |
| 4025 | static char mainPrompt[PROMPT_LEN_MAX]; |
| 4026 | /* Continuation prompt. default: " ...> " */ |
| 4027 | static char continuePrompt[PROMPT_LEN_MAX]; |
| 4028 | |
| 4029 | /* |
| 4030 | ** Write I/O traces to the following stream. |
| 4031 | */ |
| 4032 | #ifdef SQLITE_ENABLE_IOTRACE |
| 4033 | static FILE *iotrace = 0; |
| 4034 | #endif |
| 4035 | |
| 4036 | |
| 4037 | /* This is variant of the standard-library strncpy() routine with the |
| 4038 | ** one change that the destination string is always zero-terminated, even |
| 4039 | ** if there is no zero-terminator in the first n-1 characters of the source |
| 4040 | ** string. |
| @@ -4188,17 +4151,10 @@ | |
| 4151 | */ |
| 4152 | static void shell_check_oom(const void *p){ |
| 4153 | if( p==0 ) shell_out_of_memory(); |
| 4154 | } |
| 4155 | |
| 4156 | /* |
| 4157 | ** This routine works like printf in that its first argument is a |
| 4158 | ** format string and subsequent arguments are values to be substituted |
| 4159 | ** in place of % fields. The result of formatting this string |
| 4160 | ** is written to iotrace. |
| @@ -8349,13 +8305,13 @@ | |
| 8305 | }else if( e<-10000 ){ |
| 8306 | e = -10000; |
| 8307 | } |
| 8308 | |
| 8309 | if( m<0 ){ |
| 8310 | if( m<(-9223372036854775807LL) ) return; |
| 8311 | isNeg = 1; |
| 8312 | m = -m; |
| 8313 | }else if( m==0 && e>-1000 && e<1000 ){ |
| 8314 | sqlite3_result_double(context, 0.0); |
| 8315 | return; |
| 8316 | } |
| 8317 | while( (m>>32)&0xffe00000 ){ |
| @@ -9472,11 +9428,11 @@ | |
| 9428 | ** (X) match X |
| 9429 | ** X|Y X or Y |
| 9430 | ** ^X X occurring at the beginning of the string |
| 9431 | ** X$ X occurring at the end of the string |
| 9432 | ** . Match any single character |
| 9433 | ** \c Character c where c is one of \{}()[]|*+?-. |
| 9434 | ** \c C-language escapes for c in afnrtv. ex: \t or \n |
| 9435 | ** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX |
| 9436 | ** \xXX Where XX is exactly 2 hex digits, unicode value XX |
| 9437 | ** [abc] Any single character from the set abc |
| 9438 | ** [^abc] Any single character not in the set abc |
| @@ -9857,11 +9813,11 @@ | |
| 9813 | |
| 9814 | /* A backslash character has been seen, read the next character and |
| 9815 | ** return its interpretation. |
| 9816 | */ |
| 9817 | static unsigned re_esc_char(ReCompiled *p){ |
| 9818 | static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]-"; |
| 9819 | static const char zTrans[] = "\a\f\n\r\t\v"; |
| 9820 | int i, v = 0; |
| 9821 | char c; |
| 9822 | if( p->sIn.i>=p->sIn.mx ) return 0; |
| 9823 | c = p->sIn.z[p->sIn.i]; |
| @@ -10180,15 +10136,22 @@ | |
| 10136 | } |
| 10137 | return pRe->zErr; |
| 10138 | } |
| 10139 | |
| 10140 | /* |
| 10141 | ** The value of LIMIT_MAX_PATTERN_LENGTH. |
| 10142 | */ |
| 10143 | static int re_maxlen(sqlite3_context *context){ |
| 10144 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 10145 | return sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1); |
| 10146 | } |
| 10147 | |
| 10148 | /* |
| 10149 | ** Maximum NFA size given a maximum pattern length. |
| 10150 | */ |
| 10151 | static int re_maxnfa(int mxlen){ |
| 10152 | return 75+mxlen/2; |
| 10153 | } |
| 10154 | |
| 10155 | /* |
| 10156 | ** Implementation of the regexp() SQL function. This function implements |
| 10157 | ** the build-in REGEXP operator. The first argument to the function is the |
| @@ -10210,14 +10173,21 @@ | |
| 10173 | int setAux = 0; /* True to invoke sqlite3_set_auxdata() */ |
| 10174 | |
| 10175 | (void)argc; /* Unused */ |
| 10176 | pRe = sqlite3_get_auxdata(context, 0); |
| 10177 | if( pRe==0 ){ |
| 10178 | int mxLen = re_maxlen(context); |
| 10179 | int nPattern; |
| 10180 | zPattern = (const char*)sqlite3_value_text(argv[0]); |
| 10181 | if( zPattern==0 ) return; |
| 10182 | nPattern = sqlite3_value_bytes(argv[0]); |
| 10183 | if( nPattern>mxLen ){ |
| 10184 | zErr = "REGEXP pattern too big"; |
| 10185 | }else{ |
| 10186 | zErr = re_compile(&pRe, zPattern, re_maxnfa(mxLen), |
| 10187 | sqlite3_user_data(context)!=0); |
| 10188 | } |
| 10189 | if( zErr ){ |
| 10190 | re_free(pRe); |
| 10191 | sqlite3_result_error(context, zErr, -1); |
| 10192 | return; |
| 10193 | } |
| @@ -10279,11 +10249,11 @@ | |
| 10249 | "ATSTART", |
| 10250 | }; |
| 10251 | |
| 10252 | zPattern = (const char*)sqlite3_value_text(argv[0]); |
| 10253 | if( zPattern==0 ) return; |
| 10254 | zErr = re_compile(&pRe, zPattern, re_maxnfa(re_maxlen(context)), |
| 10255 | sqlite3_user_data(context)!=0); |
| 10256 | if( zErr ){ |
| 10257 | re_free(pRe); |
| 10258 | sqlite3_result_error(context, zErr, -1); |
| 10259 | return; |
| @@ -13067,11 +13037,11 @@ | |
| 13037 | nFile = (int)strlen(zFile)+1; |
| 13038 | } |
| 13039 | |
| 13040 | rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA); |
| 13041 | if( rc==SQLITE_OK ){ |
| 13042 | pNew = (ZipfileTab*)sqlite3_malloc64((i64)nByte+nFile); |
| 13043 | if( pNew==0 ) return SQLITE_NOMEM; |
| 13044 | memset(pNew, 0, nByte+nFile); |
| 13045 | pNew->db = db; |
| 13046 | pNew->aBuffer = (u8*)&pNew[1]; |
| 13047 | if( zFile ){ |
| @@ -13213,18 +13183,19 @@ | |
| 13183 | ** sqlite3_free(). |
| 13184 | */ |
| 13185 | static int zipfileReadData( |
| 13186 | FILE *pFile, /* Read from this file */ |
| 13187 | u8 *aRead, /* Read into this buffer */ |
| 13188 | i64 nRead, /* Number of bytes to read */ |
| 13189 | i64 iOff, /* Offset to read from */ |
| 13190 | char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */ |
| 13191 | ){ |
| 13192 | size_t n; |
| 13193 | fseek(pFile, (long)iOff, SEEK_SET); |
| 13194 | n = fread(aRead, 1, (long)nRead, pFile); |
| 13195 | if( n!=(size_t)nRead ){ |
| 13196 | sqlite3_free(*pzErrmsg); |
| 13197 | *pzErrmsg = sqlite3_mprintf("error in fread()"); |
| 13198 | return SQLITE_ERROR; |
| 13199 | } |
| 13200 | return SQLITE_OK; |
| 13201 | } |
| @@ -13237,11 +13208,11 @@ | |
| 13208 | if( nWrite>0 ){ |
| 13209 | size_t n = nWrite; |
| 13210 | fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET); |
| 13211 | n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd); |
| 13212 | if( (int)n!=nWrite ){ |
| 13213 | zipfileTableErr(pTab,"error in fwrite()"); |
| 13214 | return SQLITE_ERROR; |
| 13215 | } |
| 13216 | pTab->szCurrent += nWrite; |
| 13217 | } |
| 13218 | return SQLITE_OK; |
| @@ -13484,10 +13455,11 @@ | |
| 13455 | /* |
| 13456 | ** Set (*pzErr) to point to a buffer from sqlite3_malloc() containing a |
| 13457 | ** generic corruption message and return SQLITE_CORRUPT; |
| 13458 | */ |
| 13459 | static int zipfileCorrupt(char **pzErr){ |
| 13460 | sqlite3_free(*pzErr); |
| 13461 | *pzErr = sqlite3_mprintf("zip archive is corrupt"); |
| 13462 | return SQLITE_CORRUPT; |
| 13463 | } |
| 13464 | |
| 13465 | /* |
| @@ -13502,11 +13474,11 @@ | |
| 13474 | ** final value of (*ppEntry) undefined. |
| 13475 | */ |
| 13476 | static int zipfileGetEntry( |
| 13477 | ZipfileTab *pTab, /* Store any error message here */ |
| 13478 | const u8 *aBlob, /* Pointer to in-memory file image */ |
| 13479 | i64 nBlob, /* Size of aBlob[] in bytes */ |
| 13480 | FILE *pFile, /* If aBlob==0, read from this file */ |
| 13481 | i64 iOff, /* Offset of CDS record */ |
| 13482 | ZipfileEntry **ppEntry /* OUT: Pointer to new object */ |
| 13483 | ){ |
| 13484 | u8 *aRead; |
| @@ -13542,18 +13514,18 @@ | |
| 13514 | rc = SQLITE_NOMEM; |
| 13515 | }else{ |
| 13516 | memset(pNew, 0, sizeof(ZipfileEntry)); |
| 13517 | rc = zipfileReadCDS(aRead, &pNew->cds); |
| 13518 | if( rc!=SQLITE_OK ){ |
| 13519 | zipfileTableErr(pTab, "failed to read CDS at offset %lld", iOff); |
| 13520 | }else if( aBlob==0 ){ |
| 13521 | rc = zipfileReadData( |
| 13522 | pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr |
| 13523 | ); |
| 13524 | }else{ |
| 13525 | aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ]; |
| 13526 | if( (iOff + ZIPFILE_CDS_FIXED_SZ + nFile + nExtra)>nBlob ){ |
| 13527 | rc = zipfileCorrupt(pzErr); |
| 13528 | } |
| 13529 | } |
| 13530 | } |
| 13531 | |
| @@ -13574,19 +13546,19 @@ | |
| 13546 | ZipfileLFH lfh; |
| 13547 | if( pFile ){ |
| 13548 | rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr); |
| 13549 | }else{ |
| 13550 | aRead = (u8*)&aBlob[pNew->cds.iOffset]; |
| 13551 | if( ((i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){ |
| 13552 | rc = zipfileCorrupt(pzErr); |
| 13553 | } |
| 13554 | } |
| 13555 | |
| 13556 | memset(&lfh, 0, sizeof(lfh)); |
| 13557 | if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh); |
| 13558 | if( rc==SQLITE_OK ){ |
| 13559 | pNew->iDataOff = (i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; |
| 13560 | pNew->iDataOff += lfh.nFile + lfh.nExtra; |
| 13561 | if( aBlob && pNew->cds.szCompressed ){ |
| 13562 | if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){ |
| 13563 | rc = zipfileCorrupt(pzErr); |
| 13564 | }else{ |
| @@ -13593,11 +13565,11 @@ | |
| 13565 | pNew->aData = &pNew->aExtra[nExtra]; |
| 13566 | memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed); |
| 13567 | } |
| 13568 | } |
| 13569 | }else{ |
| 13570 | zipfileTableErr(pTab, "failed to read LFH at offset %d", |
| 13571 | (int)pNew->cds.iOffset |
| 13572 | ); |
| 13573 | } |
| 13574 | } |
| 13575 | |
| @@ -13617,11 +13589,11 @@ | |
| 13589 | static int zipfileNext(sqlite3_vtab_cursor *cur){ |
| 13590 | ZipfileCsr *pCsr = (ZipfileCsr*)cur; |
| 13591 | int rc = SQLITE_OK; |
| 13592 | |
| 13593 | if( pCsr->pFile ){ |
| 13594 | i64 iEof = (i64)pCsr->eocd.iOffset + (i64)pCsr->eocd.nSize; |
| 13595 | zipfileEntryFree(pCsr->pCurrent); |
| 13596 | pCsr->pCurrent = 0; |
| 13597 | if( pCsr->iNextOff>=iEof ){ |
| 13598 | pCsr->bEof = 1; |
| 13599 | }else{ |
| @@ -13855,16 +13827,16 @@ | |
| 13827 | ** an English language error message may be left in virtual-table pTab. |
| 13828 | */ |
| 13829 | static int zipfileReadEOCD( |
| 13830 | ZipfileTab *pTab, /* Return errors here */ |
| 13831 | const u8 *aBlob, /* Pointer to in-memory file image */ |
| 13832 | i64 nBlob, /* Size of aBlob[] in bytes */ |
| 13833 | FILE *pFile, /* Read from this file if aBlob==0 */ |
| 13834 | ZipfileEOCD *pEOCD /* Object to populate */ |
| 13835 | ){ |
| 13836 | u8 *aRead = pTab->aBuffer; /* Temporary buffer */ |
| 13837 | i64 nRead; /* Bytes to read from file */ |
| 13838 | int rc = SQLITE_OK; |
| 13839 | |
| 13840 | memset(pEOCD, 0, sizeof(ZipfileEOCD)); |
| 13841 | if( aBlob==0 ){ |
| 13842 | i64 iOff; /* Offset to read from */ |
| @@ -13881,11 +13853,11 @@ | |
| 13853 | nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE)); |
| 13854 | aRead = (u8*)&aBlob[nBlob-nRead]; |
| 13855 | } |
| 13856 | |
| 13857 | if( rc==SQLITE_OK ){ |
| 13858 | i64 i; |
| 13859 | |
| 13860 | /* Scan backwards looking for the signature bytes */ |
| 13861 | for(i=nRead-20; i>=0; i--){ |
| 13862 | if( aRead[i]==0x50 && aRead[i+1]==0x4b |
| 13863 | && aRead[i+2]==0x05 && aRead[i+3]==0x06 |
| @@ -13892,13 +13864,11 @@ | |
| 13864 | ){ |
| 13865 | break; |
| 13866 | } |
| 13867 | } |
| 13868 | if( i<0 ){ |
| 13869 | zipfileTableErr(pTab, "cannot find end of central directory record"); |
| 13870 | return SQLITE_ERROR; |
| 13871 | } |
| 13872 | |
| 13873 | aRead += i+4; |
| 13874 | pEOCD->iDisk = zipfileRead16(aRead); |
| @@ -13939,11 +13909,11 @@ | |
| 13909 | pNew->pNext = pBefore; |
| 13910 | *pp = pNew; |
| 13911 | } |
| 13912 | } |
| 13913 | |
| 13914 | static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, i64 nBlob){ |
| 13915 | ZipfileEOCD eocd; |
| 13916 | int rc; |
| 13917 | int i; |
| 13918 | i64 iOff; |
| 13919 | |
| @@ -13987,11 +13957,11 @@ | |
| 13957 | zipfileCursorErr(pCsr, "zipfile() function requires an argument"); |
| 13958 | return SQLITE_ERROR; |
| 13959 | }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ |
| 13960 | static const u8 aEmptyBlob = 0; |
| 13961 | const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]); |
| 13962 | i64 nBlob = sqlite3_value_bytes(argv[0]); |
| 13963 | assert( pTab->pFirstEntry==0 ); |
| 13964 | if( aBlob==0 ){ |
| 13965 | aBlob = &aEmptyBlob; |
| 13966 | nBlob = 0; |
| 13967 | } |
| @@ -14185,23 +14155,23 @@ | |
| 14155 | ZipfileTab *pTab = (ZipfileTab*)pVtab; |
| 14156 | int rc = SQLITE_OK; |
| 14157 | |
| 14158 | assert( pTab->pWriteFd==0 ); |
| 14159 | if( pTab->zFile==0 || pTab->zFile[0]==0 ){ |
| 14160 | zipfileTableErr(pTab, "zipfile: missing filename"); |
| 14161 | return SQLITE_ERROR; |
| 14162 | } |
| 14163 | |
| 14164 | /* Open a write fd on the file. Also load the entire central directory |
| 14165 | ** structure into memory. During the transaction any new file data is |
| 14166 | ** appended to the archive file, but the central directory is accumulated |
| 14167 | ** in main-memory until the transaction is committed. */ |
| 14168 | pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+"); |
| 14169 | if( pTab->pWriteFd==0 ){ |
| 14170 | zipfileTableErr(pTab, |
| 14171 | "zipfile: failed to open file %s for writing", pTab->zFile |
| 14172 | ); |
| 14173 | rc = SQLITE_ERROR; |
| 14174 | }else{ |
| 14175 | fseek(pTab->pWriteFd, 0, SEEK_END); |
| 14176 | pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd); |
| 14177 | rc = zipfileLoadDirectory(pTab, 0, 0); |
| @@ -14662,11 +14632,11 @@ | |
| 14632 | int nEntry; |
| 14633 | ZipfileBuffer body; |
| 14634 | ZipfileBuffer cds; |
| 14635 | }; |
| 14636 | |
| 14637 | static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){ |
| 14638 | if( pBuf->n+nByte>pBuf->nAlloc ){ |
| 14639 | u8 *aNew; |
| 14640 | sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512; |
| 14641 | int nReq = pBuf->n + nByte; |
| 14642 | |
| @@ -14711,11 +14681,11 @@ | |
| 14681 | u32 iCrc32 = 0; /* crc32 of uncompressed data */ |
| 14682 | |
| 14683 | char *zName = 0; /* Path (name) of new entry */ |
| 14684 | int nName = 0; /* Size of zName in bytes */ |
| 14685 | char *zFree = 0; /* Free this before returning */ |
| 14686 | i64 nByte; |
| 14687 | |
| 14688 | memset(&e, 0, sizeof(e)); |
| 14689 | p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); |
| 14690 | if( p==0 ) return; |
| 14691 | |
| @@ -24161,28 +24131,28 @@ | |
| 24131 | u8 autoExplain; /* Automatically turn on .explain mode */ |
| 24132 | u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */ |
| 24133 | u8 autoEQPtrace; /* autoEQP is in trace mode */ |
| 24134 | u8 scanstatsOn; /* True to display scan stats before each finalize */ |
| 24135 | u8 bAutoScreenWidth; /* Using the TTY to determine screen width */ |
| 24136 | u8 mFlags; /* MFLG_ECHO, MFLG_CRLF, etc. */ |
| 24137 | u8 eMode; /* One of the MODE_ values */ |
| 24138 | sqlite3_qrf_spec spec; /* Spec to be passed into QRF */ |
| 24139 | } Mode; |
| 24140 | |
| 24141 | /* Flags for Mode.mFlags */ |
| 24142 | #define MFLG_ECHO 0x01 /* Echo inputs to output */ |
| 24143 | #define MFLG_CRLF 0x02 /* Use CR/LF output line endings */ |
| 24144 | #define MFLG_HDR 0x04 /* .header used to change headers on/off */ |
| 24145 | |
| 24146 | |
| 24147 | /* |
| 24148 | ** State information about the database connection is contained in an |
| 24149 | ** instance of the following structure. |
| 24150 | */ |
| 24151 | typedef struct ShellState ShellState; |
| 24152 | struct ShellState { |
| 24153 | sqlite3 *db; /* The database */ |
| 24154 | u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ |
| 24155 | u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ |
| 24156 | u8 nEqpLevel; /* Depth of the EQP output graph */ |
| 24157 | u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ |
| 24158 | u8 bSafeMode; /* True to prohibit unsafe operations */ |
| @@ -24190,11 +24160,14 @@ | |
| 24160 | u8 eRestoreState; /* See comments above doAutoDetectRestore() */ |
| 24161 | unsigned statsOn; /* True to display memory stats before each finalize */ |
| 24162 | unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */ |
| 24163 | u8 nPopOutput; /* Revert .output settings when reaching zero */ |
| 24164 | u8 nPopMode; /* Revert .mode settings when reaching zero */ |
| 24165 | u8 enableTimer; /* Enable the timer. 2: permanently 1: only once */ |
| 24166 | int inputNesting; /* Track nesting level of .read and other redirects */ |
| 24167 | double prevTimer; /* Last reported timer value */ |
| 24168 | double tmProgress; /* --timeout option for .progress */ |
| 24169 | i64 lineno; /* Line number of last line read from in */ |
| 24170 | const char *zInFile; /* Name of the input file */ |
| 24171 | int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ |
| 24172 | FILE *in; /* Read commands from this stream */ |
| 24173 | FILE *out; /* Write results here */ |
| @@ -24286,10 +24259,11 @@ | |
| 24259 | #define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */ |
| 24260 | #define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progress |
| 24261 | ** callback limit is reached, and for each |
| 24262 | ** top-level SQL statement */ |
| 24263 | #define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */ |
| 24264 | #define SHELL_PROGRESS_TMOUT 0x08 /* Stop after tmProgress seconds */ |
| 24265 | |
| 24266 | /* Names of values for Mode.spec.eEsc and Mode.spec.eText |
| 24267 | */ |
| 24268 | static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" }; |
| 24269 | static const char *qrfQuoteNames[] = |
| @@ -24447,10 +24421,181 @@ | |
| 24421 | ** Limit input nesting via .read or any other input redirect. |
| 24422 | ** It's not too expensive, so a generous allowance can be made. |
| 24423 | */ |
| 24424 | #define MAX_INPUT_NESTING 25 |
| 24425 | |
| 24426 | /************************* BEGIN PERFORMANCE TIMER *****************************/ |
| 24427 | #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) |
| 24428 | #include <sys/time.h> |
| 24429 | #include <sys/resource.h> |
| 24430 | /* VxWorks does not support getrusage() as far as we can determine */ |
| 24431 | #if defined(_WRS_KERNEL) || defined(__RTP__) |
| 24432 | struct rusage { |
| 24433 | struct timeval ru_utime; /* user CPU time used */ |
| 24434 | struct timeval ru_stime; /* system CPU time used */ |
| 24435 | }; |
| 24436 | #define getrusage(A,B) memset(B,0,sizeof(*B)) |
| 24437 | #endif |
| 24438 | |
| 24439 | /* Saved resource information for the beginning of an operation */ |
| 24440 | static struct rusage sBegin; /* CPU time at start */ |
| 24441 | static sqlite3_int64 iBegin; /* Wall-clock time at start */ |
| 24442 | |
| 24443 | /* |
| 24444 | ** Begin timing an operation |
| 24445 | */ |
| 24446 | static void beginTimer(ShellState *p){ |
| 24447 | if( p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0 ){ |
| 24448 | getrusage(RUSAGE_SELF, &sBegin); |
| 24449 | iBegin = timeOfDay(); |
| 24450 | } |
| 24451 | } |
| 24452 | |
| 24453 | /* Return the difference of two time_structs in seconds */ |
| 24454 | static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ |
| 24455 | return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + |
| 24456 | (double)(pEnd->tv_sec - pStart->tv_sec); |
| 24457 | } |
| 24458 | |
| 24459 | /* Return the time since the start of the timer in |
| 24460 | ** seconds. */ |
| 24461 | static double elapseTime(ShellState *NotUsed){ |
| 24462 | (void)NotUsed; |
| 24463 | if( iBegin==0 ) return 0.0; |
| 24464 | return (timeOfDay() - iBegin)*0.000001; |
| 24465 | } |
| 24466 | |
| 24467 | /* |
| 24468 | ** Print the timing results. |
| 24469 | */ |
| 24470 | static void endTimer(ShellState *p){ |
| 24471 | if( p->enableTimer ){ |
| 24472 | sqlite3_int64 iEnd = timeOfDay(); |
| 24473 | struct rusage sEnd; |
| 24474 | getrusage(RUSAGE_SELF, &sEnd); |
| 24475 | p->prevTimer = (iEnd - iBegin)*0.000001; |
| 24476 | cli_printf(p->out, "Run Time: real %.6f user %.6f sys %.6f\n", |
| 24477 | p->prevTimer, |
| 24478 | timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), |
| 24479 | timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); |
| 24480 | if( p->enableTimer==1 ) p->enableTimer = 0; |
| 24481 | iBegin = 0; |
| 24482 | } |
| 24483 | } |
| 24484 | |
| 24485 | #define BEGIN_TIMER(X) beginTimer(X) |
| 24486 | #define END_TIMER(X) endTimer(X) |
| 24487 | #define ELAPSE_TIME(X) elapseTime(X) |
| 24488 | #define HAS_TIMER 1 |
| 24489 | |
| 24490 | #elif (defined(_WIN32) || defined(WIN32)) |
| 24491 | |
| 24492 | /* Saved resource information for the beginning of an operation */ |
| 24493 | static HANDLE hProcess; |
| 24494 | static FILETIME ftKernelBegin; |
| 24495 | static FILETIME ftUserBegin; |
| 24496 | static sqlite3_int64 ftWallBegin; |
| 24497 | typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, |
| 24498 | LPFILETIME, LPFILETIME); |
| 24499 | static GETPROCTIMES getProcessTimesAddr = NULL; |
| 24500 | |
| 24501 | /* |
| 24502 | ** Check to see if we have timer support. Return 1 if necessary |
| 24503 | ** support found (or found previously). |
| 24504 | */ |
| 24505 | static int hasTimer(void){ |
| 24506 | if( getProcessTimesAddr ){ |
| 24507 | return 1; |
| 24508 | } else { |
| 24509 | /* GetProcessTimes() isn't supported in WIN95 and some other Windows |
| 24510 | ** versions. See if the version we are running on has it, and if it |
| 24511 | ** does, save off a pointer to it and the current process handle. |
| 24512 | */ |
| 24513 | hProcess = GetCurrentProcess(); |
| 24514 | if( hProcess ){ |
| 24515 | HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); |
| 24516 | if( NULL != hinstLib ){ |
| 24517 | getProcessTimesAddr = |
| 24518 | (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); |
| 24519 | if( NULL != getProcessTimesAddr ){ |
| 24520 | return 1; |
| 24521 | } |
| 24522 | FreeLibrary(hinstLib); |
| 24523 | } |
| 24524 | } |
| 24525 | } |
| 24526 | return 0; |
| 24527 | } |
| 24528 | |
| 24529 | /* |
| 24530 | ** Begin timing an operation |
| 24531 | */ |
| 24532 | static void beginTimer(ShellState *p){ |
| 24533 | if( (p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0) |
| 24534 | && getProcessTimesAddr |
| 24535 | ){ |
| 24536 | FILETIME ftCreation, ftExit; |
| 24537 | getProcessTimesAddr(hProcess,&ftCreation,&ftExit, |
| 24538 | &ftKernelBegin,&ftUserBegin); |
| 24539 | ftWallBegin = timeOfDay(); |
| 24540 | } |
| 24541 | } |
| 24542 | |
| 24543 | /* Return the difference of two FILETIME structs in seconds */ |
| 24544 | static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ |
| 24545 | sqlite_int64 i64Start = *((sqlite_int64 *) pStart); |
| 24546 | sqlite_int64 i64End = *((sqlite_int64 *) pEnd); |
| 24547 | return (double) ((i64End - i64Start) / 10000000.0); |
| 24548 | } |
| 24549 | |
| 24550 | /* Return the time since the start of the timer in |
| 24551 | ** seconds. */ |
| 24552 | static double elapseTime(ShellState *NotUsed){ |
| 24553 | (void)NotUsed; |
| 24554 | if( ftWallBegin==0 ) return 0.0; |
| 24555 | return (timeOfDay() - ftWallBegin)*0.000001; |
| 24556 | } |
| 24557 | |
| 24558 | /* |
| 24559 | ** Print the timing results. |
| 24560 | */ |
| 24561 | static void endTimer(ShellState *p){ |
| 24562 | if( p->enableTimer && getProcessTimesAddr){ |
| 24563 | FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; |
| 24564 | sqlite3_int64 ftWallEnd = timeOfDay(); |
| 24565 | getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); |
| 24566 | p->prevTimer = (ftWallEnd - ftWallBegin)*0.000001; |
| 24567 | #ifdef _WIN64 |
| 24568 | /* microsecond precision on 64-bit windows */ |
| 24569 | cli_printf(p->out, "Run Time: real %.6f user %f sys %f\n", |
| 24570 | p->prevTimer, |
| 24571 | timeDiff(&ftUserBegin, &ftUserEnd), |
| 24572 | timeDiff(&ftKernelBegin, &ftKernelEnd)); |
| 24573 | #else |
| 24574 | /* millisecond precisino on 32-bit windows */ |
| 24575 | cli_printf(p->out, "Run Time: real %.3f user %.3f sys %.3f\n", |
| 24576 | p->prevTimer, |
| 24577 | timeDiff(&ftUserBegin, &ftUserEnd), |
| 24578 | timeDiff(&ftKernelBegin, &ftKernelEnd)); |
| 24579 | #endif |
| 24580 | if( p->enableTimer==1 ) p->enableTimer = 0; |
| 24581 | ftWallBegin = 0; |
| 24582 | } |
| 24583 | } |
| 24584 | |
| 24585 | #define BEGIN_TIMER(X) beginTimer(X) |
| 24586 | #define ELAPSE_TIME(X) elapseTime(X) |
| 24587 | #define END_TIMER(X) endTimer(X) |
| 24588 | #define HAS_TIMER hasTimer() |
| 24589 | |
| 24590 | #else |
| 24591 | #define BEGIN_TIMER(X) /* no-op */ |
| 24592 | #define ELAPSE_TIME(X) 0.0 |
| 24593 | #define END_TIMER(X) /*no-op*/ |
| 24594 | #define HAS_TIMER 0 |
| 24595 | #endif |
| 24596 | /************************* END PERFORMANCE TIMER ******************************/ |
| 24597 | |
| 24598 | /* |
| 24599 | ** Clear a display mode, freeing any allocated memory that it |
| 24600 | ** contains. |
| 24601 | */ |
| @@ -24534,11 +24679,13 @@ | |
| 24679 | if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]); |
| 24680 | if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]); |
| 24681 | if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]); |
| 24682 | pM->spec.eText = pI->eText; |
| 24683 | pM->spec.eBlob = pI->eBlob; |
| 24684 | if( (pM->mFlags & MFLG_HDR)==0 ){ |
| 24685 | pM->spec.bTitles = pI->bHdr; |
| 24686 | } |
| 24687 | pM->spec.eTitle = pI->eHdr; |
| 24688 | if( pI->mFlg & 0x01 ){ |
| 24689 | pM->spec.bBorder = QRF_No; |
| 24690 | }else{ |
| 24691 | pM->spec.bBorder = QRF_Auto; |
| @@ -24570,18 +24717,17 @@ | |
| 24717 | p->mode.mFlags = mFlags; |
| 24718 | } |
| 24719 | } |
| 24720 | |
| 24721 | /* |
| 24722 | ** Set the mode to the default. It assumed that the mode has |
| 24723 | ** already been freed and zeroed prior to calling this routine. |
| 24724 | */ |
| 24725 | static void modeDefault(ShellState *p){ |
| 24726 | p->mode.spec.iVersion = 1; |
| 24727 | p->mode.autoExplain = 1; |
| 24728 | if( stdin_is_interactive || stdout_is_console ){ |
| 24729 | modeChange(p, MODE_TTY); |
| 24730 | }else{ |
| 24731 | modeChange(p, MODE_BATCH); |
| 24732 | } |
| 24733 | } |
| @@ -25371,10 +25517,17 @@ | |
| 25517 | ** Progress handler callback. |
| 25518 | */ |
| 25519 | static int progress_handler(void *pClientData) { |
| 25520 | ShellState *p = (ShellState*)pClientData; |
| 25521 | p->nProgress++; |
| 25522 | if( (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0 |
| 25523 | && ELAPSE_TIME(p)>=p->tmProgress |
| 25524 | ){ |
| 25525 | cli_printf(p->out, "Progress timeout after %.6f seconds\n", |
| 25526 | ELAPSE_TIME(p)); |
| 25527 | return 1; |
| 25528 | } |
| 25529 | if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){ |
| 25530 | cli_printf(p->out, "Progress limit reached (%u)\n", p->nProgress); |
| 25531 | if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; |
| 25532 | if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0; |
| 25533 | return 1; |
| @@ -25908,10 +26061,12 @@ | |
| 26061 | char *zBuf = sqlite3_malloc64( szVar-5 ); |
| 26062 | if( zBuf ){ |
| 26063 | memcpy(zBuf, &zVar[6], szVar-5); |
| 26064 | sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8); |
| 26065 | } |
| 26066 | }else if( strcmp(zVar, "$TIMER")==0 ){ |
| 26067 | sqlite3_bind_double(pStmt, i, pArg->prevTimer); |
| 26068 | #ifdef SQLITE_ENABLE_CARRAY |
| 26069 | }else if( strncmp(zVar, "$carray_", 8)==0 ){ |
| 26070 | static char *azColorNames[] = { |
| 26071 | "azure", "black", "blue", "brown", "cyan", "fuchsia", "gold", |
| 26072 | "gray", "green", "indigo", "khaki", "lime", "magenta", "maroon", |
| @@ -26167,27 +26322,36 @@ | |
| 26322 | pArg->pStmt = pStmt; |
| 26323 | } |
| 26324 | |
| 26325 | /* Show the EXPLAIN QUERY PLAN if .eqp is on */ |
| 26326 | isExplain = sqlite3_stmt_isexplain(pStmt); |
| 26327 | if( pArg && pArg->mode.autoEQP && isExplain==0 && pArg->dot.nArg==0 ){ |
| 26328 | int triggerEQP = 0; |
| 26329 | u8 savedEnableTimer = pArg->enableTimer; |
| 26330 | pArg->enableTimer = 0; |
| 26331 | disable_debug_trace_modes(); |
| 26332 | sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP); |
| 26333 | if( pArg->mode.autoEQP>=AUTOEQP_trigger ){ |
| 26334 | sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0); |
| 26335 | } |
| 26336 | sqlite3_reset(pStmt); |
| 26337 | spec.eStyle = QRF_STYLE_Auto; |
| 26338 | sqlite3_stmt_explain(pStmt, 2); |
| 26339 | sqlite3_format_query_result(pStmt, &spec, 0); |
| 26340 | if( pArg->mode.autoEQP>=AUTOEQP_full ){ |
| 26341 | sqlite3_reset(pStmt); |
| 26342 | sqlite3_stmt_explain(pStmt, 1); |
| 26343 | sqlite3_format_query_result(pStmt, &spec, 0); |
| 26344 | } |
| 26345 | |
| 26346 | if( pArg->mode.autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){ |
| 26347 | sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0); |
| 26348 | } |
| 26349 | sqlite3_reset(pStmt); |
| 26350 | sqlite3_stmt_explain(pStmt, 0); |
| 26351 | restore_debug_trace_modes(); |
| 26352 | pArg->enableTimer = savedEnableTimer; |
| 26353 | } |
| 26354 | |
| 26355 | bind_prepared_stmt(pArg, pStmt); |
| 26356 | if( isExplain && pArg->mode.autoExplain ){ |
| 26357 | spec.eStyle = isExplain==1 ? QRF_STYLE_Explain : QRF_STYLE_Eqp; |
| @@ -26604,12 +26768,12 @@ | |
| 26768 | ".bail on|off Stop after hitting an error. Default OFF", |
| 26769 | #ifndef SQLITE_SHELL_FIDDLE |
| 26770 | ".cd DIRECTORY Change the working directory to DIRECTORY", |
| 26771 | #endif |
| 26772 | ".changes on|off Show number of rows changed by SQL", |
| 26773 | ".check OPTIONS ... Verify the results of a .testcase", |
| 26774 | #ifndef SQLITE_SHELL_FIDDLE |
| 26775 | ".clone NEWDB Clone data into NEWDB from the existing database", |
| 26776 | #endif |
| 26777 | ".connection [close] [#] Open or close an auxiliary database connection", |
| 26778 | ".crlf ?on|off? Whether or not to use \\r\\n line endings", |
| 26779 | ".databases List names and files of attached databases", |
| @@ -26721,10 +26885,11 @@ | |
| 26885 | ".progress N Invoke progress handler after every N opcodes", |
| 26886 | " --limit N Interrupt after N progress callbacks", |
| 26887 | " --once Do no more than one progress interrupt", |
| 26888 | " --quiet|-q No output except at interrupts", |
| 26889 | " --reset Reset the count for each input and interrupt", |
| 26890 | " --timeout S Halt after running for S seconds", |
| 26891 | #endif |
| 26892 | ".prompt MAIN CONTINUE Replace the standard prompts", |
| 26893 | #ifndef SQLITE_SHELL_FIDDLE |
| 26894 | ".quit Stop interpreting input stream, exit if primary.", |
| 26895 | ".read FILE Read input from FILE or command output", |
| @@ -26785,17 +26950,15 @@ | |
| 26950 | " vmstep Show the virtual machine step count only", |
| 26951 | #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) |
| 26952 | ".system CMD ARGS... Run CMD ARGS... in a system shell", |
| 26953 | #endif |
| 26954 | ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", |
| 26955 | ".testcase NAME Begin a test case.", |
| 26956 | ",testctrl CMD ... Run various sqlite3_test_control() operations", |
| 26957 | " Run \".testctrl\" with no arguments for details", |
| 26958 | ".timeout MS Try opening locked tables for MS milliseconds", |
| 26959 | ".timer on|off|once Turn SQL timer on or off.", |
| 26960 | #ifndef SQLITE_OMIT_TRACE |
| 26961 | ".trace ?OPTIONS? Output each SQL statement as it is run", |
| 26962 | " FILE Send output to FILE", |
| 26963 | " stdout Send output to stdout", |
| 26964 | " stderr Send output to stderr", |
| @@ -26836,19 +26999,33 @@ | |
| 26999 | "USAGE: .import [OPTIONS] FILE TABLE\n" |
| 27000 | "\n" |
| 27001 | "Import CSV or similar text from FILE into TABLE. If TABLE does\n" |
| 27002 | "not exist, it is created using the first row of FILE as the column\n" |
| 27003 | "names. If FILE begins with \"|\" then it is a command that is run\n" |
| 27004 | "and the output from the command is used as the input data. If\n" |
| 27005 | "FILE begins with \"<<\" followed by a label, then content is read from\n" |
| 27006 | "the script until the first line that matches the label.\n" |
| 27007 | "\n" |
| 27008 | "The content of FILE is interpreted using RFC-4180 (\"CSV\") quoting\n" |
| 27009 | "rules unless the current mode is \"ascii\" or \"tabs\" or unless one\n" |
| 27010 | "the --ascii option is used.\n" |
| 27011 | "\n" |
| 27012 | "The column and row separators must be single ASCII characters. If\n" |
| 27013 | "multiple characters or a Unicode character are specified for the\n" |
| 27014 | "separators, then only the first byte of the separator is used. Except,\n" |
| 27015 | "if the row separator is \\n and the mode is not --ascii, then \\r\\n is\n" |
| 27016 | "understood as a row separator too.\n" |
| 27017 | "\n" |
| 27018 | "Options:\n" |
| 27019 | " --ascii Do not use RFC-4180 quoting. Use \\037 and \\036\n" |
| 27020 | " as column and row separators on input, unless other\n" |
| 27021 | " delimiters are specified using --colsep and/or --rowsep\n" |
| 27022 | " --colsep CHAR Use CHAR as the column separator.\n" |
| 27023 | " --csv Input is standard RFC-4180 CSV.\n" |
| 27024 | " --esc CHAR Use CHAR as an escape character in unquoted CSV inputs.\n" |
| 27025 | " --qesc CHAR Use CHAR as an escape character in quoted CSV inputs.\n" |
| 27026 | " --rowsep CHAR Use CHAR as the row separator.\n" |
| 27027 | " --schema S When creating TABLE, put it in schema S\n" |
| 27028 | " --skip N Ignore the first N rows of input\n" |
| 27029 | " -v Verbose mode\n" |
| 27030 | }, |
| 27031 | { ".mode", |
| @@ -26930,23 +27107,17 @@ | |
| 27107 | " --bom Prepend a byte-order mark to the output\n" |
| 27108 | " -e Accumulate output in a temporary text file then\n" |
| 27109 | " launch a text editor when the redirection ends.\n" |
| 27110 | " --error-prefix X Use X as the left-margin prefix for error messages.\n" |
| 27111 | " Set to an empty string to restore the default.\n" |
| 27112 | " --keep Keep redirecting output to its current destination.\n" |
| 27113 | " Use this option in combination with --show or\n" |
| 27114 | " with --error-prefix when you do not want to stop\n" |
| 27115 | " a current redirection.\n" |
| 27116 | " --plain Use plain text rather than HTML tables with -w\n" |
| 27117 | " --show Show output text captured by .testcase or by\n" |
| 27118 | " redirecting to \"memory\".\n" |
| 27119 | " -w Show the output in a web browser. Output is\n" |
| 27120 | " written into a temporary HTML file until the\n" |
| 27121 | " redirect ends, then the web browser is launched.\n" |
| 27122 | " Query results are shown as HTML tables, unless\n" |
| 27123 | " the --plain is used too.\n" |
| @@ -26970,10 +27141,39 @@ | |
| 27141 | " file in a web browser\n" |
| 27142 | " -x Show the output in a spreadsheet. Output is\n" |
| 27143 | " written to a temp file as CSV then the spreadsheet\n" |
| 27144 | " is launched when\n" |
| 27145 | }, |
| 27146 | { ".check", |
| 27147 | "USAGE: .check [OPTIONS] PATTERN\n" |
| 27148 | "\n" |
| 27149 | "Verify results of commands since the most recent .testcase command.\n" |
| 27150 | "Restore output to the console, unless --keep is used.\n" |
| 27151 | "\n" |
| 27152 | "If PATTERN starts with \"<<ENDMARK\" then the actual pattern is taken from\n" |
| 27153 | "subsequent lines of text up to the first line that begins with ENDMARK.\n" |
| 27154 | "All pattern lines and the ENDMARK are discarded.\n" |
| 27155 | "\n" |
| 27156 | "Options:\n" |
| 27157 | " --exact Do an exact comparison including leading and\n" |
| 27158 | " trailing whitespace.\n" |
| 27159 | " --glob Treat PATTERN as a GLOB\n" |
| 27160 | " --keep Do not reset the testcase. More .check commands\n" |
| 27161 | " will follow.\n" |
| 27162 | " --notglob Output should not match PATTERN\n" |
| 27163 | " --show Write testcase output to the screen, for debugging.\n" |
| 27164 | }, |
| 27165 | { ".testcase", |
| 27166 | "USAGE: .testcase [OPTIONS] NAME\n" |
| 27167 | "\n" |
| 27168 | "Start a new test case identified by NAME. All output\n" |
| 27169 | "through the next \".check\" command is captured for comparison. See the\n" |
| 27170 | "\".check\" commandn for additional informatioon.\n" |
| 27171 | "\n" |
| 27172 | "Options:\n" |
| 27173 | " --error-prefix TEXT Change error message prefix text to TEXT\n" |
| 27174 | }, |
| 27175 | }; |
| 27176 | |
| 27177 | /* |
| 27178 | ** Return a pointer to usage text for zCmd, or NULL if none exists. |
| 27179 | */ |
| @@ -27193,10 +27393,56 @@ | |
| 27393 | if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0; |
| 27394 | } |
| 27395 | return 1; |
| 27396 | } |
| 27397 | #endif |
| 27398 | |
| 27399 | /* |
| 27400 | ** Return the size of the named file in bytes. Or return a negative |
| 27401 | ** number if the file does not exist. |
| 27402 | */ |
| 27403 | static sqlite3_int64 fileSize(const char *zFile){ |
| 27404 | #if defined(_WIN32) || defined(WIN32) |
| 27405 | struct _stat64 x; |
| 27406 | if( _stat64(zFile, &x)!=0 ) return -1; |
| 27407 | return (sqlite3_int64)x.st_size; |
| 27408 | #else |
| 27409 | struct stat x; |
| 27410 | if( stat(zFile, &x)!=0 ) return -1; |
| 27411 | return (sqlite3_int64)x.st_size; |
| 27412 | #endif |
| 27413 | } |
| 27414 | |
| 27415 | /* |
| 27416 | ** Return true if zFile is an SQLite database. |
| 27417 | ** |
| 27418 | ** Algorithm: |
| 27419 | ** * If the file does not exist -> return false |
| 27420 | ** * If the size of the file is not a multiple of 512 -> return false |
| 27421 | ** * If sqlite3_open() fails -> return false |
| 27422 | ** * if sqlite3_prepare() or sqlite3_step() fails -> return false |
| 27423 | ** * Otherwise -> return true |
| 27424 | */ |
| 27425 | static int isDatabaseFile(const char *zFile, int openFlags){ |
| 27426 | sqlite3 *db = 0; |
| 27427 | sqlite3_stmt *pStmt = 0; |
| 27428 | int rc; |
| 27429 | sqlite3_int64 sz = fileSize(zFile); |
| 27430 | if( sz<512 || (sz%512)!=0 ) return 0; |
| 27431 | if( sqlite3_open_v2(zFile, &db, openFlags, 0)==SQLITE_OK |
| 27432 | && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0) |
| 27433 | ==SQLITE_OK |
| 27434 | && sqlite3_step(pStmt)==SQLITE_ROW |
| 27435 | ){ |
| 27436 | rc = 1; |
| 27437 | }else{ |
| 27438 | rc = 0; |
| 27439 | } |
| 27440 | sqlite3_finalize(pStmt); |
| 27441 | sqlite3_close(db); |
| 27442 | return rc; |
| 27443 | } |
| 27444 | |
| 27445 | /* |
| 27446 | ** Try to deduce the type of file for zName based on its content. Return |
| 27447 | ** one of the SHELL_OPEN_* constants. |
| 27448 | ** |
| @@ -27206,24 +27452,16 @@ | |
| 27452 | ** the type cannot be determined from content. |
| 27453 | */ |
| 27454 | int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){ |
| 27455 | FILE *f; |
| 27456 | size_t n; |
| 27457 | int rc = SHELL_OPEN_UNSPEC; |
| 27458 | char zBuf[100]; |
| 27459 | if( access(zName,0)!=0 ) goto database_type_by_name; |
| 27460 | if( isDatabaseFile(zName, openFlags) ){ |
| 27461 | rc = SHELL_OPEN_NORMAL; |
| 27462 | } |
| 27463 | if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL; |
| 27464 | f = sqlite3_fopen(zName, "rb"); |
| 27465 | if( f==0 ) goto database_type_by_name; |
| 27466 | n = fread(zBuf, 16, 1, f); |
| 27467 | if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ |
| @@ -27253,10 +27491,39 @@ | |
| 27491 | }else{ |
| 27492 | rc = SHELL_OPEN_NORMAL; |
| 27493 | } |
| 27494 | return rc; |
| 27495 | } |
| 27496 | |
| 27497 | /* |
| 27498 | ** If the text in z[] is the name of a readable file and that file appears |
| 27499 | ** to contain SQL text and/or dot-commands, then return true. If z[] is |
| 27500 | ** not a file, or if the file is unreadable, or if the file is a database |
| 27501 | ** or anything else that is not SQL text and dot-commands, then return false. |
| 27502 | ** |
| 27503 | ** If the bLeaveUninit flag is set, then be sure to leave SQLite in an |
| 27504 | ** uninitialized state. This means invoking sqlite3_shutdown() after any |
| 27505 | ** SQLite API is used. |
| 27506 | ** |
| 27507 | ** Some amount of guesswork is involved in this decision. |
| 27508 | */ |
| 27509 | static int isScriptFile(const char *z, int bLeaveUninit){ |
| 27510 | sqlite3_int64 sz = fileSize(z); |
| 27511 | if( sz<=0 ) return 0; |
| 27512 | if( (sz%512)==0 ){ |
| 27513 | int rc; |
| 27514 | sqlite3_initialize(); |
| 27515 | rc = isDatabaseFile(z, SQLITE_OPEN_READONLY); |
| 27516 | if( bLeaveUninit ){ |
| 27517 | sqlite3_shutdown(); |
| 27518 | } |
| 27519 | if( rc ) return 0; /* Is a database */ |
| 27520 | } |
| 27521 | if( sqlite3_strlike("%.sql",z,0)==0 ) return 1; |
| 27522 | if( sqlite3_strlike("%.txt",z,0)==0 ) return 1; |
| 27523 | return 0; |
| 27524 | } |
| 27525 | |
| 27526 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 27527 | /* |
| 27528 | ** Reconstruct an in-memory database using the output from the "dbtotxt" |
| 27529 | ** program. Read content from the file in p->aAuxDb[].zDbFilename. |
| @@ -27899,20 +28166,24 @@ | |
| 28166 | typedef struct ImportCtx ImportCtx; |
| 28167 | struct ImportCtx { |
| 28168 | const char *zFile; /* Name of the input file */ |
| 28169 | FILE *in; /* Read the CSV text from this input stream */ |
| 28170 | int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */ |
| 28171 | char *zIn; /* Input text */ |
| 28172 | char *z; /* Accumulated text for a field */ |
| 28173 | i64 nUsed; /* Bytes of zIn[] used so far */ |
| 28174 | i64 n; /* Number of bytes in z */ |
| 28175 | i64 nAlloc; /* Space allocated for z[] */ |
| 28176 | int nLine; /* Current line number */ |
| 28177 | int nRow; /* Number of rows imported */ |
| 28178 | int nErr; /* Number of errors encountered */ |
| 28179 | int bNotFirst; /* True if one or more bytes already read */ |
| 28180 | int cTerm; /* Character that terminated the most recent field */ |
| 28181 | int cColSep; /* The column separator character. (Usually ",") */ |
| 28182 | int cRowSep; /* The row separator character. (Usually "\n") */ |
| 28183 | int cQEscape; /* Escape character with "...". 0 for none */ |
| 28184 | int cUQEscape; /* Escape character not with "...". 0 for none */ |
| 28185 | }; |
| 28186 | |
| 28187 | /* Clean up resourced used by an ImportCtx */ |
| 28188 | static void import_cleanup(ImportCtx *p){ |
| 28189 | if( p->in!=0 && p->xCloser!=0 ){ |
| @@ -27919,13 +28190,32 @@ | |
| 28190 | p->xCloser(p->in); |
| 28191 | p->in = 0; |
| 28192 | } |
| 28193 | sqlite3_free(p->z); |
| 28194 | p->z = 0; |
| 28195 | if( p->zIn ){ |
| 28196 | sqlite3_free(p->zIn); |
| 28197 | p->zIn = 0; |
| 28198 | } |
| 28199 | } |
| 28200 | |
| 28201 | /* Read a single character of the .import input text. Return EOF |
| 28202 | ** at end-of-file. |
| 28203 | */ |
| 28204 | static int import_getc(ImportCtx *p){ |
| 28205 | if( p->in ){ |
| 28206 | return fgetc(p->in); |
| 28207 | }else if( p->zIn && p->zIn[p->nUsed]!=0 ){ |
| 28208 | return p->zIn[p->nUsed++]; |
| 28209 | }else{ |
| 28210 | return EOF; |
| 28211 | } |
| 28212 | } |
| 28213 | |
| 28214 | /* Append a single byte to the field value begin constructed |
| 28215 | ** in the p->z[] buffer |
| 28216 | */ |
| 28217 | static void import_append_char(ImportCtx *p, int c){ |
| 28218 | if( p->n+1>=p->nAlloc ){ |
| 28219 | p->nAlloc += p->nAlloc + 100; |
| 28220 | p->z = sqlite3_realloc64(p->z, p->nAlloc); |
| 28221 | shell_check_oom(p->z); |
| @@ -27937,12 +28227,12 @@ | |
| 28227 | ** with the option of having a separator other than ",". |
| 28228 | ** |
| 28229 | ** + Input comes from p->in. |
| 28230 | ** + Store results in p->z of length p->n. Space to hold p->z comes |
| 28231 | ** from sqlite3_malloc64(). |
| 28232 | ** + Use p->cColSep as the column separator. The default is ",". |
| 28233 | ** + Use p->cRowSep as the row separator. The default is "\n". |
| 28234 | ** + Keep track of the line number in p->nLine. |
| 28235 | ** + Store the character that terminates the field in p->cTerm. Store |
| 28236 | ** EOF on end-of-file. |
| 28237 | ** + Report syntax errors on stderr |
| 28238 | */ |
| @@ -27949,23 +28239,30 @@ | |
| 28239 | static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ |
| 28240 | int c; |
| 28241 | int cSep = (u8)p->cColSep; |
| 28242 | int rSep = (u8)p->cRowSep; |
| 28243 | p->n = 0; |
| 28244 | c = import_getc(p); |
| 28245 | if( c==EOF || seenInterrupt ){ |
| 28246 | p->cTerm = EOF; |
| 28247 | return 0; |
| 28248 | } |
| 28249 | if( c=='"' ){ |
| 28250 | int pc, ppc; |
| 28251 | int startLine = p->nLine; |
| 28252 | int cQuote = c; |
| 28253 | int cEsc = (u8)p->cQEscape; |
| 28254 | pc = ppc = 0; |
| 28255 | while( 1 ){ |
| 28256 | c = import_getc(p); |
| 28257 | if( c==rSep ) p->nLine++; |
| 28258 | if( c==cEsc && cEsc!=0 ){ |
| 28259 | c = import_getc(p); |
| 28260 | import_append_char(p, c); |
| 28261 | ppc = pc = 0; |
| 28262 | continue; |
| 28263 | } |
| 28264 | if( c==cQuote ){ |
| 28265 | if( pc==cQuote ){ |
| 28266 | pc = 0; |
| 28267 | continue; |
| 28268 | } |
| @@ -27979,11 +28276,11 @@ | |
| 28276 | p->cTerm = c; |
| 28277 | break; |
| 28278 | } |
| 28279 | if( pc==cQuote && c!='\r' ){ |
| 28280 | cli_printf(stderr,"%s:%d: unescaped %c character\n", |
| 28281 | p->zFile, p->nLine, cQuote); |
| 28282 | } |
| 28283 | if( c==EOF ){ |
| 28284 | cli_printf(stderr,"%s:%d: unterminated %c-quoted field\n", |
| 28285 | p->zFile, startLine, cQuote); |
| 28286 | p->cTerm = c; |
| @@ -27994,26 +28291,28 @@ | |
| 28291 | pc = c; |
| 28292 | } |
| 28293 | }else{ |
| 28294 | /* If this is the first field being parsed and it begins with the |
| 28295 | ** UTF-8 BOM (0xEF BB BF) then skip the BOM */ |
| 28296 | int cEsc = p->cUQEscape; |
| 28297 | if( (c&0xff)==0xef && p->bNotFirst==0 ){ |
| 28298 | import_append_char(p, c); |
| 28299 | c = import_getc(p); |
| 28300 | if( (c&0xff)==0xbb ){ |
| 28301 | import_append_char(p, c); |
| 28302 | c = import_getc(p); |
| 28303 | if( (c&0xff)==0xbf ){ |
| 28304 | p->bNotFirst = 1; |
| 28305 | p->n = 0; |
| 28306 | return csv_read_one_field(p); |
| 28307 | } |
| 28308 | } |
| 28309 | } |
| 28310 | while( c!=EOF && c!=cSep && c!=rSep ){ |
| 28311 | if( c==cEsc && cEsc!=0 ) c = import_getc(p); |
| 28312 | import_append_char(p, c); |
| 28313 | c = import_getc(p); |
| 28314 | } |
| 28315 | if( c==rSep ){ |
| 28316 | p->nLine++; |
| 28317 | if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; |
| 28318 | } |
| @@ -28027,12 +28326,12 @@ | |
| 28326 | /* Read a single field of ASCII delimited text. |
| 28327 | ** |
| 28328 | ** + Input comes from p->in. |
| 28329 | ** + Store results in p->z of length p->n. Space to hold p->z comes |
| 28330 | ** from sqlite3_malloc64(). |
| 28331 | ** + Use p->cColSep as the column separator. The default is "\x1F". |
| 28332 | ** + Use p->cRowSep as the row separator. The default is "\x1E". |
| 28333 | ** + Keep track of the row number in p->nLine. |
| 28334 | ** + Store the character that terminates the field in p->cTerm. Store |
| 28335 | ** EOF on end-of-file. |
| 28336 | ** + Report syntax errors on stderr |
| 28337 | */ |
| @@ -28039,18 +28338,18 @@ | |
| 28338 | static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ |
| 28339 | int c; |
| 28340 | int cSep = (u8)p->cColSep; |
| 28341 | int rSep = (u8)p->cRowSep; |
| 28342 | p->n = 0; |
| 28343 | c = import_getc(p); |
| 28344 | if( c==EOF || seenInterrupt ){ |
| 28345 | p->cTerm = EOF; |
| 28346 | return 0; |
| 28347 | } |
| 28348 | while( c!=EOF && c!=cSep && c!=rSep ){ |
| 28349 | import_append_char(p, c); |
| 28350 | c = import_getc(p); |
| 28351 | } |
| 28352 | if( c==rSep ){ |
| 28353 | p->nLine++; |
| 28354 | } |
| 28355 | p->cTerm = c; |
| @@ -30151,11 +30450,11 @@ | |
| 30450 | ; |
| 30451 | static const char * const zCollectVar = "\ |
| 30452 | SELECT\ |
| 30453 | '('||x'0a'\ |
| 30454 | || group_concat(\ |
| 30455 | cname||' ANY',\ |
| 30456 | ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ |
| 30457 | ||')' AS ColsSpec \ |
| 30458 | FROM (\ |
| 30459 | SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \ |
| 30460 | FROM ColNames ORDER BY cpos\ |
| @@ -30351,19 +30650,33 @@ | |
| 30650 | ** USAGE: .import [OPTIONS] FILE TABLE |
| 30651 | ** |
| 30652 | ** Import CSV or similar text from FILE into TABLE. If TABLE does |
| 30653 | ** not exist, it is created using the first row of FILE as the column |
| 30654 | ** names. If FILE begins with "|" then it is a command that is run |
| 30655 | ** and the output from the command is used as the input data. If |
| 30656 | ** FILE begins with "<<" followed by a label, then content is read from |
| 30657 | ** the script until the first line that matches the label. |
| 30658 | ** |
| 30659 | ** The content of FILE is interpreted using RFC-4180 ("CSV") quoting |
| 30660 | ** rules unless the current mode is "ascii" or "tabs" or unless one |
| 30661 | ** the --ascii option is used. |
| 30662 | ** |
| 30663 | ** The column and row separators must be single ASCII characters. If |
| 30664 | ** multiple characters or a Unicode character are specified for the |
| 30665 | ** separators, then only the first byte of the separator is used. Except, |
| 30666 | ** if the row separator is \n and the mode is not --ascii, then \r\n is |
| 30667 | ** understood as a row separator too. |
| 30668 | ** |
| 30669 | ** Options: |
| 30670 | ** --ascii Do not use RFC-4180 quoting. Use \037 and \036 |
| 30671 | ** as column and row separators on input, unless other |
| 30672 | ** delimiters are specified using --colsep and/or --rowsep |
| 30673 | ** --colsep CHAR Use CHAR as the column separator. |
| 30674 | ** --csv Input is standard RFC-4180 CSV. |
| 30675 | ** --esc CHAR Use CHAR as an escape character in unquoted CSV inputs. |
| 30676 | ** --qesc CHAR Use CHAR as an escape character in quoted CSV inputs. |
| 30677 | ** --rowsep CHAR Use CHAR as the row separator. |
| 30678 | ** --schema S When creating TABLE, put it in schema S |
| 30679 | ** --skip N Ignore the first N rows of input |
| 30680 | ** -v Verbose mode |
| 30681 | */ |
| 30682 | static int dotCmdImport(ShellState *p){ |
| @@ -30375,17 +30688,16 @@ | |
| 30688 | sqlite3_stmt *pStmt = NULL; /* A statement */ |
| 30689 | int nCol; /* Number of columns in the table */ |
| 30690 | i64 nByte; /* Number of bytes in an SQL string */ |
| 30691 | int i, j; /* Loop counters */ |
| 30692 | int needCommit; /* True to COMMIT or ROLLBACK at end */ |
| 30693 | char *zSql = 0; /* An SQL statement */ |
| 30694 | ImportCtx sCtx; /* Reader context */ |
| 30695 | char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ |
| 30696 | int eVerbose = 0; /* Larger for more console output */ |
| 30697 | i64 nSkip = 0; /* Initial lines to skip */ |
| 30698 | i64 iLineOffset = 0; /* Offset to the first line of input */ |
| 30699 | char *zCreate = 0; /* CREATE TABLE statement text */ |
| 30700 | int rc; /* Result code */ |
| 30701 | |
| 30702 | failIfSafeMode(p, "cannot run .import in safe mode"); |
| 30703 | memset(&sCtx, 0, sizeof(sCtx)); |
| @@ -30411,70 +30723,71 @@ | |
| 30723 | }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){ |
| 30724 | zSchema = azArg[++i]; |
| 30725 | }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){ |
| 30726 | nSkip = integerValue(azArg[++i]); |
| 30727 | }else if( cli_strcmp(z,"-ascii")==0 ){ |
| 30728 | if( sCtx.cColSep==0 ) sCtx.cColSep = SEP_Unit[0]; |
| 30729 | if( sCtx.cRowSep==0 ) sCtx.cRowSep = SEP_Record[0]; |
| 30730 | xRead = ascii_read_one_field; |
| 30731 | }else if( cli_strcmp(z,"-csv")==0 ){ |
| 30732 | if( sCtx.cColSep==0 ) sCtx.cColSep = ','; |
| 30733 | if( sCtx.cRowSep==0 ) sCtx.cRowSep = '\n'; |
| 30734 | xRead = csv_read_one_field; |
| 30735 | }else if( cli_strcmp(z,"-esc")==0 ){ |
| 30736 | sCtx.cUQEscape = azArg[++i][0]; |
| 30737 | }else if( cli_strcmp(z,"-qesc")==0 ){ |
| 30738 | sCtx.cQEscape = azArg[++i][0]; |
| 30739 | }else if( cli_strcmp(z,"-colsep")==0 ){ |
| 30740 | if( i==nArg-1 ){ |
| 30741 | dotCmdError(p, i, "missing argument", 0); |
| 30742 | return 1; |
| 30743 | } |
| 30744 | i++; |
| 30745 | sCtx.cColSep = azArg[i][0]; |
| 30746 | }else if( cli_strcmp(z,"-rowsep")==0 ){ |
| 30747 | if( i==nArg-1 ){ |
| 30748 | dotCmdError(p, i, "missing argument", 0); |
| 30749 | return 1; |
| 30750 | } |
| 30751 | i++; |
| 30752 | sCtx.cRowSep = azArg[i][0]; |
| 30753 | }else{ |
| 30754 | dotCmdError(p, i, "unknown option", 0); |
| 30755 | return 1; |
| 30756 | } |
| 30757 | } |
| 30758 | if( zTable==0 ){ |
| 30759 | dotCmdError(p, nArg, 0, "Missing %s argument\n", |
| 30760 | zFile==0 ? "FILE" : "TABLE"); |
| 30761 | return 1; |
| 30762 | } |
| 30763 | seenInterrupt = 0; |
| 30764 | open_db(p, 0); |
| 30765 | if( sCtx.cColSep==0 ){ |
| 30766 | if( p->mode.spec.zColumnSep && p->mode.spec.zColumnSep[0]!=0 ){ |
| 30767 | sCtx.cColSep = p->mode.spec.zColumnSep[0]; |
| 30768 | }else{ |
| 30769 | sCtx.cColSep = ','; |
| 30770 | } |
| 30771 | } |
| 30772 | if( (sCtx.cColSep & 0x80)!=0 ){ |
| 30773 | eputz("Error: .import column separator must be ASCII\n"); |
| 30774 | return 1; |
| 30775 | } |
| 30776 | if( sCtx.cRowSep==0 ){ |
| 30777 | if( p->mode.spec.zRowSep && p->mode.spec.zRowSep[0]!=0 ){ |
| 30778 | sCtx.cRowSep = p->mode.spec.zRowSep[0]; |
| 30779 | }else{ |
| 30780 | sCtx.cRowSep = '\n'; |
| 30781 | } |
| 30782 | } |
| 30783 | if( sCtx.cRowSep=='\r' && xRead!=ascii_read_one_field ){ |
| 30784 | sCtx.cRowSep = '\n'; |
| 30785 | } |
| 30786 | if( (sCtx.cRowSep & 0x80)!=0 ){ |
| 30787 | eputz("Error: .import row separator must be ASCII\n"); |
| 30788 | return 1; |
| 30789 | } |
| 30790 | sCtx.zFile = zFile; |
| 30791 | sCtx.nLine = 1; |
| 30792 | if( sCtx.zFile[0]=='|' ){ |
| 30793 | #ifdef SQLITE_OMIT_POPEN |
| @@ -30483,19 +30796,58 @@ | |
| 30796 | #else |
| 30797 | sCtx.in = sqlite3_popen(sCtx.zFile+1, "r"); |
| 30798 | sCtx.zFile = "<pipe>"; |
| 30799 | sCtx.xCloser = pclose; |
| 30800 | #endif |
| 30801 | }else if( sCtx.zFile[0]=='<' && sCtx.zFile[1]=='<' && sCtx.zFile[2]!=0 ){ |
| 30802 | /* Input text comes from subsequent lines of script until the zFile |
| 30803 | ** delimiter */ |
| 30804 | int nEndMark = strlen30(zFile)-2; |
| 30805 | char *zEndMark = &zFile[2]; |
| 30806 | sqlite3_str *pContent = sqlite3_str_new(p->db); |
| 30807 | int ckEnd = 1; |
| 30808 | i64 iStart = p->lineno; |
| 30809 | char zLine[2000]; |
| 30810 | sCtx.zFile = p->zInFile; |
| 30811 | sCtx.nLine = p->lineno+1; |
| 30812 | iLineOffset = p->lineno; |
| 30813 | while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){ |
| 30814 | if( ckEnd && cli_strncmp(zLine,zEndMark,nEndMark)==0 ){ |
| 30815 | ckEnd = 2; |
| 30816 | if( strchr(zLine,'\n') ) p->lineno++; |
| 30817 | break; |
| 30818 | } |
| 30819 | if( strchr(zLine,'\n') ){ |
| 30820 | p->lineno++; |
| 30821 | ckEnd = 1; |
| 30822 | }else{ |
| 30823 | ckEnd = 0; |
| 30824 | } |
| 30825 | sqlite3_str_appendall(pContent, zLine); |
| 30826 | } |
| 30827 | sCtx.zIn = sqlite3_str_finish(pContent); |
| 30828 | if( sCtx.zIn==0 ){ |
| 30829 | sCtx.zIn = sqlite3_mprintf(""); |
| 30830 | } |
| 30831 | if( ckEnd<2 ){ |
| 30832 | i64 savedLn = p->lineno; |
| 30833 | p->lineno = iStart; |
| 30834 | dotCmdError(p, 0, 0,"Content terminator \"%s\" not found.",zEndMark); |
| 30835 | p->lineno = savedLn; |
| 30836 | import_cleanup(&sCtx); |
| 30837 | return 1; |
| 30838 | } |
| 30839 | }else{ |
| 30840 | sCtx.in = sqlite3_fopen(sCtx.zFile, "rb"); |
| 30841 | sCtx.xCloser = fclose; |
| 30842 | } |
| 30843 | if( sCtx.in==0 && sCtx.zIn==0 ){ |
| 30844 | dotCmdError(p, 0, 0, "cannot open \"%s\"", zFile); |
| 30845 | import_cleanup(&sCtx); |
| 30846 | return 1; |
| 30847 | } |
| 30848 | if( eVerbose>=1 ){ |
| 30849 | char zSep[2]; |
| 30850 | zSep[1] = 0; |
| 30851 | zSep[0] = sCtx.cColSep; |
| 30852 | cli_puts("Column separator ", p->out); |
| 30853 | output_c_string(p->out, zSep); |
| @@ -30648,10 +31000,14 @@ | |
| 31000 | if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){ |
| 31001 | z = ""; |
| 31002 | } |
| 31003 | sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); |
| 31004 | if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){ |
| 31005 | if( i==0 && (strcmp(z,"\n")==0 || strcmp(z,"\r\n")==0) ){ |
| 31006 | /* Ignore trailing \n or \r\n when some other row separator */ |
| 31007 | break; |
| 31008 | } |
| 31009 | cli_printf(stderr,"%s:%d: expected %d columns but found %d" |
| 31010 | " - filling the rest with NULL\n", |
| 31011 | sCtx.zFile, startLine, nCol, i+1); |
| 31012 | i += 2; |
| 31013 | while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; } |
| @@ -30671,10 +31027,11 @@ | |
| 31027 | rc = sqlite3_reset(pStmt); |
| 31028 | if( rc!=SQLITE_OK ){ |
| 31029 | cli_printf(stderr,"%s:%d: INSERT failed: %s\n", |
| 31030 | sCtx.zFile, startLine, sqlite3_errmsg(p->db)); |
| 31031 | sCtx.nErr++; |
| 31032 | if( bail_on_error ) break; |
| 31033 | }else{ |
| 31034 | sCtx.nRow++; |
| 31035 | } |
| 31036 | } |
| 31037 | }while( sCtx.cTerm!=EOF ); |
| @@ -30683,13 +31040,13 @@ | |
| 31040 | sqlite3_finalize(pStmt); |
| 31041 | if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); |
| 31042 | if( eVerbose>0 ){ |
| 31043 | cli_printf(p->out, |
| 31044 | "Added %d rows with %d errors using %d lines of input\n", |
| 31045 | sCtx.nRow, sCtx.nErr, sCtx.nLine-1-iLineOffset); |
| 31046 | } |
| 31047 | return sCtx.nErr ? 1 : 0; |
| 31048 | } |
| 31049 | |
| 31050 | |
| 31051 | /* |
| 31052 | ** This function computes what to show the user about the configured |
| @@ -31100,10 +31457,11 @@ | |
| 31457 | if( k<0 ){ |
| 31458 | dotCmdError(p, i, "bad --titles value","%z", zErr); |
| 31459 | return 1; |
| 31460 | } |
| 31461 | p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No; |
| 31462 | p->mode.mFlags &= ~MFLG_HDR; |
| 31463 | p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr; |
| 31464 | chng = 1; |
| 31465 | }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){ |
| 31466 | int nWidth = 0; |
| 31467 | short int *aWidth; |
| @@ -31328,23 +31686,17 @@ | |
| 31686 | ** --bom Prepend a byte-order mark to the output |
| 31687 | ** -e Accumulate output in a temporary text file then |
| 31688 | ** launch a text editor when the redirection ends. |
| 31689 | ** --error-prefix X Use X as the left-margin prefix for error messages. |
| 31690 | ** Set to an empty string to restore the default. |
| 31691 | ** --keep Keep redirecting output to its current destination. |
| 31692 | ** Use this option in combination with --show or |
| 31693 | ** with --error-prefix when you do not want to stop |
| 31694 | ** a current redirection. |
| 31695 | ** --plain Use plain text rather than HTML tables with -w |
| 31696 | ** --show Show output text captured by .testcase or by |
| 31697 | ** redirecting to "memory". |
| 31698 | ** -w Show the output in a web browser. Output is |
| 31699 | ** written into a temporary HTML file until the |
| 31700 | ** redirect ends, then the web browser is launched. |
| 31701 | ** Query results are shown as HTML tables, unless |
| 31702 | ** the --plain is used too. |
| @@ -31382,13 +31734,11 @@ | |
| 31734 | char *zFile = 0; /* The FILE argument */ |
| 31735 | int i; /* Loop counter */ |
| 31736 | int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */ |
| 31737 | int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */ |
| 31738 | int bPlain = 0; /* --plain option */ |
| 31739 | int bKeep = 0; /* Keep redirecting */ |
| 31740 | static const char *zBomUtf8 = "\357\273\277"; |
| 31741 | const char *zBom = 0; |
| 31742 | char c = azArg[0][0]; |
| 31743 | int n = strlen30(azArg[0]); |
| 31744 | |
| @@ -31410,36 +31760,21 @@ | |
| 31760 | zBom = zBomUtf8; |
| 31761 | }else if( cli_strcmp(z,"-plain")==0 ){ |
| 31762 | bPlain = 1; |
| 31763 | }else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0 |
| 31764 | && (z[1]=='x' || z[1]=='e' || z[1]=='w') ){ |
| 31765 | if( bKeep || eMode ){ |
| 31766 | dotCmdError(p, i, "incompatible with prior options",0); |
| 31767 | goto dotCmdOutput_error; |
| 31768 | } |
| 31769 | eMode = z[1]; |
| 31770 | }else if( cli_strcmp(z,"-show")==0 ){ |
| 31771 | if( cli_output_capture ){ |
| 31772 | sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture)); |
| 31773 | } |
| 31774 | }else if( cli_strcmp(z,"-keep")==0 ){ |
| 31775 | bKeep = 1; |
| 31776 | }else if( optionMatch(z,"error-prefix") ){ |
| 31777 | if( i+1>=nArg ){ |
| 31778 | dotCmdError(p, i, "missing argument", 0); |
| 31779 | return 1; |
| 31780 | } |
| @@ -31450,11 +31785,11 @@ | |
| 31785 | dotCmdError(p, i, "unknown option", 0); |
| 31786 | sqlite3_free(zFile); |
| 31787 | return 1; |
| 31788 | } |
| 31789 | }else if( zFile==0 && eMode==0 ){ |
| 31790 | if( bKeep ){ |
| 31791 | dotCmdError(p, i, "incompatible with prior options",0); |
| 31792 | goto dotCmdOutput_error; |
| 31793 | } |
| 31794 | if( cli_strcmp(z, "memory")==0 && bOnce ){ |
| 31795 | dotCmdError(p, 0, "cannot redirect to \"memory\"", 0); |
| @@ -31486,53 +31821,10 @@ | |
| 31821 | if( bOnce ){ |
| 31822 | p->nPopOutput = 2; |
| 31823 | }else{ |
| 31824 | p->nPopOutput = 0; |
| 31825 | } |
| 31826 | if( !bKeep ) output_reset(p); |
| 31827 | #ifndef SQLITE_NOHAVE_SYSTEM |
| 31828 | if( eMode=='e' || eMode=='x' || eMode=='w' ){ |
| 31829 | p->doXdgOpen = 1; |
| 31830 | modePush(p); |
| @@ -31609,10 +31901,199 @@ | |
| 31901 | |
| 31902 | dotCmdOutput_error: |
| 31903 | sqlite3_free(zFile); |
| 31904 | return 1; |
| 31905 | } |
| 31906 | |
| 31907 | /* |
| 31908 | ** DOT-COMMAND: .check |
| 31909 | ** USAGE: .check [OPTIONS] PATTERN |
| 31910 | ** |
| 31911 | ** Verify results of commands since the most recent .testcase command. |
| 31912 | ** Restore output to the console, unless --keep is used. |
| 31913 | ** |
| 31914 | ** If PATTERN starts with "<<ENDMARK" then the actual pattern is taken from |
| 31915 | ** subsequent lines of text up to the first line that begins with ENDMARK. |
| 31916 | ** All pattern lines and the ENDMARK are discarded. |
| 31917 | ** |
| 31918 | ** Options: |
| 31919 | ** --exact Do an exact comparison including leading and |
| 31920 | ** trailing whitespace. |
| 31921 | ** --glob Treat PATTERN as a GLOB |
| 31922 | ** --keep Do not reset the testcase. More .check commands |
| 31923 | ** will follow. |
| 31924 | ** --notglob Output should not match PATTERN |
| 31925 | ** --show Write testcase output to the screen, for debugging. |
| 31926 | */ |
| 31927 | static int dotCmdCheck(ShellState *p){ |
| 31928 | int nArg = p->dot.nArg; /* Number of arguments */ |
| 31929 | char **azArg = p->dot.azArg; /* Text of the arguments */ |
| 31930 | int i; /* Loop counter */ |
| 31931 | int k; /* Result of pickStr() */ |
| 31932 | char *zTest; /* Textcase result */ |
| 31933 | int bKeep = 0; /* --keep option */ |
| 31934 | char *zCheck = 0; /* PATTERN argument */ |
| 31935 | char *zPattern = 0; /* Actual test pattern */ |
| 31936 | int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --exact */ |
| 31937 | int isOk; /* True if results are OK */ |
| 31938 | sqlite3_int64 iStart = p->lineno; /* Line number of .check statement */ |
| 31939 | |
| 31940 | if( p->zTestcase[0]==0 ){ |
| 31941 | dotCmdError(p, 0, "no .testcase is active", 0); |
| 31942 | return 1; |
| 31943 | } |
| 31944 | for(i=1; i<nArg; i++){ |
| 31945 | char *z = azArg[i]; |
| 31946 | if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++; |
| 31947 | if( cli_strcmp(z,"-keep")==0 ){ |
| 31948 | bKeep = 1; |
| 31949 | }else if( cli_strcmp(z,"-show")==0 ){ |
| 31950 | if( cli_output_capture ){ |
| 31951 | sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture)); |
| 31952 | } |
| 31953 | bKeep = 1; |
| 31954 | }else if( z[0]=='-' |
| 31955 | && (k = pickStr(&z[1],0,"glob","notglob","exact",""))>=0 |
| 31956 | ){ |
| 31957 | if( eCheck && eCheck!=k+1 ){ |
| 31958 | dotCmdError(p, i, "incompatible with prior options",0); |
| 31959 | return 1; |
| 31960 | } |
| 31961 | eCheck = k+1; |
| 31962 | }else if( zCheck ){ |
| 31963 | dotCmdError(p, i, "unknown option", 0); |
| 31964 | return 1; |
| 31965 | }else{ |
| 31966 | zCheck = azArg[i]; |
| 31967 | } |
| 31968 | } |
| 31969 | if( zCheck==0 ){ |
| 31970 | dotCmdError(p, 0, "no PATTERN specified", 0); |
| 31971 | return 1; |
| 31972 | } |
| 31973 | if( cli_output_capture && sqlite3_str_length(cli_output_capture) ){ |
| 31974 | zTest = sqlite3_str_value(cli_output_capture); |
| 31975 | shell_check_oom(zTest); |
| 31976 | }else{ |
| 31977 | zTest = ""; |
| 31978 | } |
| 31979 | p->nTestRun++; |
| 31980 | if( zCheck[0]=='<' && zCheck[1]=='<' && zCheck[2]!=0 ){ |
| 31981 | int nCheck = strlen30(zCheck); |
| 31982 | sqlite3_str *pPattern = sqlite3_str_new(p->db); |
| 31983 | char zLine[2000]; |
| 31984 | while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){ |
| 31985 | if( strchr(zLine,'\n') ) p->lineno++; |
| 31986 | if( cli_strncmp(&zCheck[2],zLine,nCheck-2)==0 ) break; |
| 31987 | sqlite3_str_appendall(pPattern, zLine); |
| 31988 | } |
| 31989 | zPattern = sqlite3_str_finish(pPattern); |
| 31990 | if( zPattern==0 ){ |
| 31991 | zPattern = sqlite3_mprintf(""); |
| 31992 | } |
| 31993 | }else{ |
| 31994 | zPattern = zCheck; |
| 31995 | } |
| 31996 | shell_check_oom(zPattern); |
| 31997 | switch( eCheck ){ |
| 31998 | case 1: { |
| 31999 | char *zGlob = sqlite3_mprintf("*%s*", zPattern); |
| 32000 | isOk = testcase_glob(zGlob, zTest)!=0; |
| 32001 | sqlite3_free(zGlob); |
| 32002 | break; |
| 32003 | } |
| 32004 | case 2: { |
| 32005 | char *zGlob = sqlite3_mprintf("*%s*", zPattern); |
| 32006 | isOk = testcase_glob(zGlob, zTest)==0; |
| 32007 | sqlite3_free(zGlob); |
| 32008 | break; |
| 32009 | } |
| 32010 | case 3: { |
| 32011 | isOk = cli_strcmp(zTest,zPattern)==0; |
| 32012 | break; |
| 32013 | } |
| 32014 | default: { |
| 32015 | /* Skip leading and trailing \n and \r on both pattern and test output */ |
| 32016 | const char *z1 = zPattern; |
| 32017 | const char *z2 = zTest; |
| 32018 | size_t n1, n2; |
| 32019 | while( z1[0]=='\n' || z1[0]=='\r' ) z1++; |
| 32020 | n1 = strlen(z1); |
| 32021 | while( n1>0 && (z1[n1-1]=='\n' || z1[n1-1]=='\r') ) n1--; |
| 32022 | while( z2[0]=='\n' || z2[0]=='\r' ) z2++; |
| 32023 | n2 = strlen(z2); |
| 32024 | while( n2>0 && (z2[n2-1]=='\n' || z2[n2-1]=='\r') ) n2--; |
| 32025 | isOk = n1==n2 && memcmp(z1,z2,n1)==0; |
| 32026 | break; |
| 32027 | } |
| 32028 | } |
| 32029 | if( !isOk ){ |
| 32030 | sqlite3_fprintf(stderr, |
| 32031 | "%s:%lld: .check failed for testcase %s\n", |
| 32032 | p->zInFile, iStart, p->zTestcase); |
| 32033 | p->nTestErr++; |
| 32034 | sqlite3_fprintf(stderr, "Expected: [%s]\n", zPattern); |
| 32035 | sqlite3_fprintf(stderr, "Got: [%s]\n", zTest); |
| 32036 | } |
| 32037 | if( zPattern!=zCheck ){ |
| 32038 | sqlite3_free(zPattern); |
| 32039 | } |
| 32040 | if( !bKeep ){ |
| 32041 | output_reset(p); |
| 32042 | p->zTestcase[0] = 0; |
| 32043 | } |
| 32044 | return 0; |
| 32045 | } |
| 32046 | |
| 32047 | /* |
| 32048 | ** DOT-COMMAND: .testcase |
| 32049 | ** USAGE: .testcase [OPTIONS] NAME |
| 32050 | ** |
| 32051 | ** Start a new test case identified by NAME. All output |
| 32052 | ** through the next ".check" command is captured for comparison. See the |
| 32053 | ** ".check" commandn for additional informatioon. |
| 32054 | ** |
| 32055 | ** Options: |
| 32056 | ** --error-prefix TEXT Change error message prefix text to TEXT |
| 32057 | */ |
| 32058 | static int dotCmdTestcase(ShellState *p){ |
| 32059 | int nArg = p->dot.nArg; /* Number of arguments */ |
| 32060 | char **azArg = p->dot.azArg; /* Text of the arguments */ |
| 32061 | int i; /* Loop counter */ |
| 32062 | const char *zName = 0; /* Testcase name */ |
| 32063 | |
| 32064 | for(i=1; i<nArg; i++){ |
| 32065 | char *z = azArg[i]; |
| 32066 | if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++; |
| 32067 | if( optionMatch(z,"error-prefix") ){ |
| 32068 | if( i+1>=nArg ){ |
| 32069 | dotCmdError(p, i, "missing argument", 0); |
| 32070 | return 1; |
| 32071 | } |
| 32072 | free(p->zErrPrefix); |
| 32073 | i++; |
| 32074 | p->zErrPrefix = azArg[i][0]==0 ? 0 : strdup(azArg[i]); |
| 32075 | }else if( zName ){ |
| 32076 | dotCmdError(p, i, "unknown option", 0); |
| 32077 | return 1; |
| 32078 | }else{ |
| 32079 | zName = azArg[i]; |
| 32080 | } |
| 32081 | } |
| 32082 | output_reset(p); |
| 32083 | if( cli_output_capture ){ |
| 32084 | sqlite3_str_free(cli_output_capture); |
| 32085 | } |
| 32086 | cli_output_capture = sqlite3_str_new(0); |
| 32087 | if( zName ){ |
| 32088 | sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", zName); |
| 32089 | }else{ |
| 32090 | sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s:%lld", |
| 32091 | p->zInFile, p->lineno); |
| 32092 | } |
| 32093 | return 0; |
| 32094 | } |
| 32095 | |
| 32096 | /* |
| 32097 | ** Enlarge the space allocated in p->dot so that it can hold more |
| 32098 | ** than nArg parsed command-line arguments. |
| 32099 | */ |
| @@ -31641,11 +32122,11 @@ | |
| 32122 | free(p->dot.zCopy); |
| 32123 | z = p->dot.zCopy = strdup(zLine); |
| 32124 | shell_check_oom(z); |
| 32125 | szLine = strlen(z); |
| 32126 | while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--; |
| 32127 | if( szLine>0 && z[szLine-1]==';' ){ |
| 32128 | szLine--; |
| 32129 | while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--; |
| 32130 | } |
| 32131 | z[szLine] = 0; |
| 32132 | parseDotRealloc(p, 2); |
| @@ -31861,35 +32342,17 @@ | |
| 32342 | eputz("Usage: .changes on|off\n"); |
| 32343 | rc = 1; |
| 32344 | } |
| 32345 | }else |
| 32346 | |
| 32347 | /* Cancel output redirection, if it is currently set (by .testcase) |
| 32348 | ** Then read the content of the testcase-out.txt file and compare against |
| 32349 | ** azArg[1]. If there are differences, report an error and exit. |
| 32350 | */ |
| 32351 | if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){ |
| 32352 | rc = dotCmdCheck(p); |
| 32353 | }else |
| 32354 | |
| 32355 | #ifndef SQLITE_SHELL_FIDDLE |
| 32356 | if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){ |
| 32357 | failIfSafeMode(p, "cannot run .clone in safe mode"); |
| 32358 | if( nArg==2 ){ |
| @@ -32468,10 +32931,11 @@ | |
| 32931 | }else |
| 32932 | |
| 32933 | if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){ |
| 32934 | if( nArg==2 ){ |
| 32935 | p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No; |
| 32936 | p->mode.mFlags |= MFLG_HDR; |
| 32937 | p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr; |
| 32938 | }else{ |
| 32939 | eputz("Usage: .headers on|off\n"); |
| 32940 | rc = 1; |
| 32941 | } |
| @@ -32521,14 +32985,14 @@ | |
| 32985 | sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); |
| 32986 | goto meta_command_exit; |
| 32987 | } |
| 32988 | zSql = sqlite3_mprintf( |
| 32989 | "SELECT rootpage, 0 FROM sqlite_schema" |
| 32990 | " WHERE type='index' AND lower(name)=lower('%q')" |
| 32991 | "UNION ALL " |
| 32992 | "SELECT rootpage, 1 FROM sqlite_schema" |
| 32993 | " WHERE type='table' AND lower(name)=lower('%q')" |
| 32994 | " AND sql LIKE '%%without%%rowid%%'", |
| 32995 | azArg[1], azArg[1] |
| 32996 | ); |
| 32997 | sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 32998 | sqlite3_free(zSql); |
| @@ -32682,13 +33146,14 @@ | |
| 33146 | goto meta_command_exit; |
| 33147 | } |
| 33148 | if( nArg==3 ){ |
| 33149 | sqlite3_limit(p->db, aLimit[iLimit].limitCode, |
| 33150 | (int)integerValue(azArg[2])); |
| 33151 | }else{ |
| 33152 | cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName, |
| 33153 | sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); |
| 33154 | } |
| 33155 | } |
| 33156 | }else |
| 33157 | |
| 33158 | if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){ |
| 33159 | open_db(p, 0); |
| @@ -33027,10 +33492,23 @@ | |
| 33492 | continue; |
| 33493 | } |
| 33494 | if( cli_strcmp(z,"once")==0 ){ |
| 33495 | p->flgProgress |= SHELL_PROGRESS_ONCE; |
| 33496 | continue; |
| 33497 | } |
| 33498 | if( cli_strcmp(z,"timeout")==0 ){ |
| 33499 | if( i==nArg-1 ){ |
| 33500 | dotCmdError(p, i, "missing argument", 0); |
| 33501 | return 1; |
| 33502 | } |
| 33503 | i++; |
| 33504 | p->tmProgress = atof(azArg[i]); |
| 33505 | if( p->tmProgress>0.0 ){ |
| 33506 | p->flgProgress = SHELL_PROGRESS_QUIET|SHELL_PROGRESS_TMOUT; |
| 33507 | if( nn==0 ) nn = 100; |
| 33508 | } |
| 33509 | continue; |
| 33510 | } |
| 33511 | if( cli_strcmp(z,"limit")==0 ){ |
| 33512 | if( i+1>=nArg ){ |
| 33513 | eputz("Error: missing argument on --limit\n"); |
| 33514 | rc = 1; |
| @@ -33233,21 +33711,22 @@ | |
| 33711 | || sqlite3_strlike(zName, "sqlite_schema", '\\')==0 |
| 33712 | || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 |
| 33713 | || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0; |
| 33714 | if( isSchema ){ |
| 33715 | cli_printf(p->out, |
| 33716 | "CREATE TABLE %ssqlite_schema (\n" |
| 33717 | " type text,\n" |
| 33718 | " name text,\n" |
| 33719 | " tbl_name text,\n" |
| 33720 | " rootpage integer,\n" |
| 33721 | " sql text\n" |
| 33722 | ");\n", |
| 33723 | sqlite3_strlike("sqlite_t%",zName,0)==0 ? "temp." : "" |
| 33724 | ); |
| 33725 | } |
| 33726 | } |
| 33727 | rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); |
| 33728 | if( rc ){ |
| 33729 | shellDatabaseError(p->db); |
| 33730 | sqlite3_finalize(pStmt); |
| 33731 | |
| 33732 | rc = 1; |
| @@ -33255,11 +33734,11 @@ | |
| 33734 | } |
| 33735 | pSql = sqlite3_str_new(p->db); |
| 33736 | sqlite3_str_appendf(pSql, "SELECT sql FROM", 0); |
| 33737 | iSchema = 0; |
| 33738 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 33739 | const char *zDb = (const char*)sqlite3_column_text(pStmt, 1); |
| 33740 | char zScNum[30]; |
| 33741 | sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); |
| 33742 | sqlite3_str_appendall(pSql, zDiv); |
| 33743 | zDiv = " UNION ALL "; |
| 33744 | if( sqlite3_stricmp(zDb, "main")==0 ){ |
| @@ -33275,11 +33754,12 @@ | |
| 33754 | " AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname", |
| 33755 | ++iSchema, zDb); |
| 33756 | sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb); |
| 33757 | } |
| 33758 | sqlite3_finalize(pStmt); |
| 33759 | #if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) \ |
| 33760 | && !defined(SQLITE_OMIT_VIRTUALTABLE) |
| 33761 | if( zName ){ |
| 33762 | sqlite3_str_appendall(pSql, |
| 33763 | " UNION ALL SELECT shell_module_schema(name)," |
| 33764 | " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list"); |
| 33765 | } |
| @@ -33299,11 +33779,11 @@ | |
| 33779 | }else{ |
| 33780 | sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName); |
| 33781 | } |
| 33782 | } |
| 33783 | if( bNoSystemTabs ){ |
| 33784 | sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCAPE '_' AND "); |
| 33785 | } |
| 33786 | sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid"); |
| 33787 | if( bDebug ){ |
| 33788 | cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql)); |
| 33789 | }else{ |
| @@ -34017,25 +34497,15 @@ | |
| 34497 | sqlite3_str_free(pSql); |
| 34498 | modePop(p); |
| 34499 | if( rc ) return shellDatabaseError(p->db); |
| 34500 | }else |
| 34501 | |
| 34502 | /* Set the p->zTestcase name and begin redirecting output into |
| 34503 | ** the cli_output_capture sqlite3_str */ |
| 34504 | if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){ |
| 34505 | rc = dotCmdTestcase(p); |
| 34506 | }else |
| 34507 | |
| 34508 | #ifndef SQLITE_UNTESTABLE |
| 34509 | if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){ |
| 34510 | static const struct { |
| 34511 | const char *zCtrlName; /* Name of a test-control option */ |
| @@ -34527,17 +34997,21 @@ | |
| 34997 | sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); |
| 34998 | }else |
| 34999 | |
| 35000 | if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){ |
| 35001 | if( nArg==2 ){ |
| 35002 | if( cli_strcmp(azArg[1],"once")==0 ){ |
| 35003 | p->enableTimer = 1; |
| 35004 | }else{ |
| 35005 | p->enableTimer = 2*booleanValue(azArg[1]); |
| 35006 | } |
| 35007 | if( p->enableTimer && !HAS_TIMER ){ |
| 35008 | eputz("Error: timer not available on this system.\n"); |
| 35009 | p->enableTimer = 0; |
| 35010 | } |
| 35011 | }else{ |
| 35012 | eputz("Usage: .timer on|off|once\n"); |
| 35013 | rc = 1; |
| 35014 | } |
| 35015 | }else |
| 35016 | |
| 35017 | #ifndef SQLITE_OMIT_TRACE |
| @@ -34708,10 +35182,11 @@ | |
| 35182 | if( p->nPopOutput ){ |
| 35183 | p->nPopOutput--; |
| 35184 | if( p->nPopOutput==0 ) output_reset(p); |
| 35185 | } |
| 35186 | p->bSafeMode = p->bSafeModePersist; |
| 35187 | p->dot.nArg = 0; |
| 35188 | return rc; |
| 35189 | } |
| 35190 | |
| 35191 | /* Line scan result and intermediate states (supporting scan resumption) |
| 35192 | */ |
| @@ -34944,13 +35419,13 @@ | |
| 35419 | char *zErrMsg = 0; |
| 35420 | |
| 35421 | open_db(p, 0); |
| 35422 | if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql); |
| 35423 | if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; |
| 35424 | BEGIN_TIMER(p); |
| 35425 | rc = shell_exec(p, zSql, &zErrMsg); |
| 35426 | END_TIMER(p); |
| 35427 | if( rc || zErrMsg ){ |
| 35428 | char zPrefix[100]; |
| 35429 | const char *zErrorTail; |
| 35430 | const char *zErrorType; |
| 35431 | if( zErrMsg==0 ){ |
| @@ -35351,11 +35826,10 @@ | |
| 35826 | " -bail stop after hitting an error\n" |
| 35827 | " -batch force batch I/O\n" |
| 35828 | " -box set output mode to 'box'\n" |
| 35829 | " -cmd COMMAND run \"COMMAND\" before reading stdin\n" |
| 35830 | " -column set output mode to 'column'\n" |
| 35831 | " -csv set output mode to 'csv'\n" |
| 35832 | #if !defined(SQLITE_OMIT_DESERIALIZE) |
| 35833 | " -deserialize open the database using sqlite3_deserialize()\n" |
| 35834 | #endif |
| 35835 | " -echo print inputs before execution\n" |
| @@ -35435,15 +35909,10 @@ | |
| 35909 | /* |
| 35910 | ** Initialize the state information in data |
| 35911 | */ |
| 35912 | static void main_init(ShellState *p) { |
| 35913 | memset(p, 0, sizeof(*p)); |
| 35914 | p->pAuxDb = &p->aAuxDb[0]; |
| 35915 | p->shellFlgs = SHFLG_Lookaside; |
| 35916 | sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p); |
| 35917 | #if !defined(SQLITE_SHELL_FIDDLE) |
| 35918 | verify_uninitialized(); |
| @@ -35498,29 +35967,65 @@ | |
| 35967 | cli_puts(z, p->out); |
| 35968 | fflush(p->out); |
| 35969 | return 1; |
| 35970 | } |
| 35971 | |
| 35972 | /* Alternative name to the entry point for Fiddle */ |
| 35973 | #ifdef SQLITE_SHELL_FIDDLE |
| 35974 | # define main fiddle_main |
| 35975 | #endif |
| 35976 | |
| 35977 | /* Use the wmain() entry point on Windows. Translate arguments to |
| 35978 | ** UTF8, then invoke the traditional main() entry point which is |
| 35979 | ** renamed using a #define to utf8_main() . |
| 35980 | */ |
| 35981 | #if defined(_WIN32) && !defined(main) |
| 35982 | # define main utf8_main /* Rename entry point to utf_main() */ |
| 35983 | int SQLITE_CDECL utf8_main(int,char**); /* Forward declaration */ |
| 35984 | int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ |
| 35985 | int rc, i; |
| 35986 | char **argv = malloc( sizeof(char*) * (argc+1) ); |
| 35987 | char **orig = argv; |
| 35988 | if( argv==0 ){ |
| 35989 | fprintf(stderr, "malloc failed\n"); |
| 35990 | exit(1); |
| 35991 | } |
| 35992 | for(i=0; i<argc; i++){ |
| 35993 | int nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, 0, 0, 0, 0); |
| 35994 | if( nByte==0 ){ |
| 35995 | argv[i] = 0; |
| 35996 | }else{ |
| 35997 | argv[i] = malloc( nByte ); |
| 35998 | if( argv[i]==0 ){ |
| 35999 | fprintf(stderr, "malloc failed\n"); |
| 36000 | exit(1); |
| 36001 | } |
| 36002 | nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i],nByte,0,0); |
| 36003 | if( nByte==0 ){ |
| 36004 | free(argv[i]); |
| 36005 | argv[i] = 0; |
| 36006 | } |
| 36007 | } |
| 36008 | } |
| 36009 | argv[argc] = 0; |
| 36010 | rc = utf8_main(argc, argv); |
| 36011 | for(i=0; i<argc; i++) free(orig[i]); |
| 36012 | free(argv); |
| 36013 | return rc; |
| 36014 | } |
| 36015 | #endif /* WIN32 */ |
| 36016 | |
| 36017 | /* |
| 36018 | ** This is the main entry point for the process. Everything starts here. |
| 36019 | ** |
| 36020 | ** The "main" identifier may have been #defined to something else: |
| 36021 | ** |
| 36022 | ** utf8_main On Windows |
| 36023 | ** fiddle_main In Fiddle |
| 36024 | ** sqlite3_shell Other projects that use shell.c as a subroutine |
| 36025 | */ |
| 36026 | int SQLITE_CDECL main(int argc, char **argv){ |
| 36027 | #ifdef SQLITE_DEBUG |
| 36028 | sqlite3_int64 mem_main_enter = 0; |
| 36029 | #endif |
| 36030 | char *zErrMsg = 0; |
| 36031 | #ifdef SQLITE_SHELL_FIDDLE |
| @@ -35538,14 +36043,10 @@ | |
| 36043 | int nOptsEnd = argc; |
| 36044 | int bEnableVfstrace = 0; |
| 36045 | char **azCmd = 0; |
| 36046 | int *aiCmd = 0; |
| 36047 | const char *zVfs = 0; /* Value of -vfs command-line option */ |
| 36048 | setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ |
| 36049 | |
| 36050 | #ifdef SQLITE_SHELL_FIDDLE |
| 36051 | stdin_is_interactive = 0; |
| 36052 | stdout_is_console = 1; |
| @@ -35596,36 +36097,10 @@ | |
| 36097 | exit(1); |
| 36098 | } |
| 36099 | #endif |
| 36100 | main_init(&data); |
| 36101 | |
| 36102 | assert( argc>=1 && argv && argv[0] ); |
| 36103 | Argv0 = argv[0]; |
| 36104 | |
| 36105 | #ifdef SQLITE_SHELL_DBNAME_PROC |
| 36106 | { |
| @@ -35637,11 +36112,11 @@ | |
| 36112 | SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename); |
| 36113 | warnInmemoryDb = 0; |
| 36114 | } |
| 36115 | #endif |
| 36116 | |
| 36117 | /* Do an initial pass through the command-line arguments to locate |
| 36118 | ** the name of the database file, the name of the initialization file, |
| 36119 | ** the size of the alternative malloc heap, options affecting commands |
| 36120 | ** or SQL run from the command line, and the first command to execute. |
| 36121 | */ |
| 36122 | #ifndef SQLITE_SHELL_FIDDLE |
| @@ -35649,11 +36124,11 @@ | |
| 36124 | #endif |
| 36125 | for(i=1; i<argc; i++){ |
| 36126 | char *z; |
| 36127 | z = argv[i]; |
| 36128 | if( z[0]!='-' || i>nOptsEnd ){ |
| 36129 | if( data.aAuxDb->zDbFilename==0 && !isScriptFile(z,1) ){ |
| 36130 | data.aAuxDb->zDbFilename = z; |
| 36131 | }else{ |
| 36132 | /* Excess arguments are interpreted as SQL (or dot-commands) and |
| 36133 | ** mean that nothing is read from stdin */ |
| 36134 | readStdin = 0; |
| @@ -35694,15 +36169,10 @@ | |
| 36169 | if( n<2 ){ |
| 36170 | sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n"); |
| 36171 | exit(1); |
| 36172 | } |
| 36173 | stdout_tty_width = n; |
| 36174 | }else if( cli_strcmp(z,"-utf8")==0 ){ |
| 36175 | }else if( cli_strcmp(z,"-no-utf8")==0 ){ |
| 36176 | }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){ |
| 36177 | int val = 0; |
| 36178 | sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val); |
| @@ -35822,10 +36292,20 @@ | |
| 36292 | }else if( cli_strcmp(z,"-safe")==0 ){ |
| 36293 | /* no-op - catch this on the second pass */ |
| 36294 | }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ |
| 36295 | /* skip over the argument */ |
| 36296 | i++; |
| 36297 | }else if( cli_strcmp(z,"-test-argv")==0 ){ |
| 36298 | /* Undocumented test option. Print the values in argv[] and exit. |
| 36299 | ** Use this to verify that any translation of the argv[], for example |
| 36300 | ** on Windows that receives wargv[] from the OS and must convert |
| 36301 | ** to UTF8 prior to calling this routine. */ |
| 36302 | int kk; |
| 36303 | for(kk=0; kk<argc; kk++){ |
| 36304 | sqlite3_fprintf(stdout,"argv[%d] = \"%s\"\n", kk, argv[kk]); |
| 36305 | } |
| 36306 | return 0; |
| 36307 | } |
| 36308 | } |
| 36309 | #ifndef SQLITE_SHELL_FIDDLE |
| 36310 | if( !bEnableVfstrace ) verify_uninitialized(); |
| 36311 | #endif |
| @@ -35848,11 +36328,30 @@ | |
| 36328 | |
| 36329 | if( zVfs ){ |
| 36330 | sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs); |
| 36331 | if( pVfs ){ |
| 36332 | sqlite3_vfs_register(pVfs, 1); |
| 36333 | } |
| 36334 | #if !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| 36335 | else if( access(zVfs,0)==0 ){ |
| 36336 | /* If the VFS name is not the name of an existing VFS, but it is |
| 36337 | ** the name of a file, then try to load that file as an extension. |
| 36338 | ** Presumably the extension implements the desired VFS. */ |
| 36339 | sqlite3 *db = 0; |
| 36340 | char *zErr = 0; |
| 36341 | sqlite3_open(":memory:", &db); |
| 36342 | sqlite3_enable_load_extension(db, 1); |
| 36343 | rc = sqlite3_load_extension(db, zVfs, 0, &zErr); |
| 36344 | sqlite3_close(db); |
| 36345 | if( (rc&0xff)!=SQLITE_OK ){ |
| 36346 | cli_printf(stderr, "could not load extension VFS \"%s\": %s\n", |
| 36347 | zVfs, zErr); |
| 36348 | exit(1); |
| 36349 | } |
| 36350 | } |
| 36351 | #endif |
| 36352 | else{ |
| 36353 | cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs); |
| 36354 | exit(1); |
| 36355 | } |
| 36356 | } |
| 36357 | |
| @@ -35889,11 +36388,11 @@ | |
| 36388 | ** is given on the command line, look for a file named ~/.sqliterc and |
| 36389 | ** try to process it. |
| 36390 | */ |
| 36391 | if( !noInit ) process_sqliterc(&data,zInitFile); |
| 36392 | |
| 36393 | /* Make a second pass through the command-line arguments and set |
| 36394 | ** options. This second pass is delayed until after the initialization |
| 36395 | ** file is processed so that the command-line arguments will override |
| 36396 | ** settings in the initialization file. |
| 36397 | */ |
| 36398 | for(i=1; i<argc; i++){ |
| @@ -36015,12 +36514,10 @@ | |
| 36514 | stdin_is_interactive = 1; |
| 36515 | }else if( cli_strcmp(z,"-batch")==0 ){ |
| 36516 | /* already handled */ |
| 36517 | }else if( cli_strcmp(z,"-screenwidth")==0 ){ |
| 36518 | i++; |
| 36519 | }else if( cli_strcmp(z,"-utf8")==0 ){ |
| 36520 | /* already handled */ |
| 36521 | }else if( cli_strcmp(z,"-no-utf8")==0 ){ |
| 36522 | /* already handled */ |
| 36523 | }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){ |
| @@ -36116,11 +36613,22 @@ | |
| 36613 | ** command-line inputs, except for the argToSkip argument which contains |
| 36614 | ** the database filename. |
| 36615 | */ |
| 36616 | for(i=0; i<nCmd; i++){ |
| 36617 | echo_group_input(&data, azCmd[i]); |
| 36618 | if( isScriptFile(azCmd[i],0) ){ |
| 36619 | FILE *inSaved = data.in; |
| 36620 | i64 savedLineno = data.lineno; |
| 36621 | int res = 1; |
| 36622 | if( (data.in = openChrSource(azCmd[i]))!=0 ){ |
| 36623 | res = process_input(&data, azCmd[i]); |
| 36624 | fclose(data.in); |
| 36625 | } |
| 36626 | data.in = inSaved; |
| 36627 | data.lineno = savedLineno; |
| 36628 | if( res ) i = nCmd; |
| 36629 | }else if( azCmd[i][0]=='.' ){ |
| 36630 | char *zErrCtx = malloc( 64 ); |
| 36631 | shell_check_oom(zErrCtx); |
| 36632 | sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]); |
| 36633 | data.zInFile = "<cmdline>"; |
| 36634 | data.zErrPrefix = zErrCtx; |
| @@ -36231,14 +36739,10 @@ | |
| 36739 | } |
| 36740 | find_home_dir(1); |
| 36741 | output_reset(&data); |
| 36742 | data.doXdgOpen = 0; |
| 36743 | clearTempFile(&data); |
| 36744 | modeFree(&data.mode); |
| 36745 | if( data.nSavedModes ){ |
| 36746 | int ii; |
| 36747 | for(ii=0; ii<data.nSavedModes; ii++){ |
| 36748 | modeFree(&data.aSavedModes[ii].mode); |
| 36749 |
+1112
-736
| --- 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 | -** 01409738afc2c0d5bdaa248ffb508aa5f36a with changes in files: | |
| 21 | +** c476d956d0bd3065cf894de6f9d393b999ff 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.52.0" |
| 471 | 471 | #define SQLITE_VERSION_NUMBER 3052000 |
| 472 | -#define SQLITE_SOURCE_ID "2025-12-11 23:24:05 01409738afc2c0d5bdaa248ffb508aa5f36a66390f6b8e4834734529ee8ed2fa" | |
| 472 | +#define SQLITE_SOURCE_ID "2026-02-04 20:51:27 c476d956d0bd3065cf894de6f9d393b999ff7d2268a35f01a6d88804789ab58f" | |
| 473 | 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 474 | 474 | #define SQLITE_SCM_TAGS "" |
| 475 | -#define SQLITE_SCM_DATETIME "2025-12-11T23:24:05.667Z" | |
| 475 | +#define SQLITE_SCM_DATETIME "2026-02-04T20:51:27.822Z" | |
| 476 | 476 | |
| 477 | 477 | /* |
| 478 | 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 479 | 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 480 | 480 | ** |
| @@ -4752,16 +4752,32 @@ | ||
| 4752 | 4752 | ** compiles to see if some SQL syntax is well-formed, without generating |
| 4753 | 4753 | ** messages on the global error log when it is not. If the test compile |
| 4754 | 4754 | ** fails, the sqlite3_prepare_v3() call returns the same error indications |
| 4755 | 4755 | ** with or without this flag; it just omits the call to [sqlite3_log()] that |
| 4756 | 4756 | ** logs the error. |
| 4757 | +** | |
| 4758 | +** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt> | |
| 4759 | +** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to behave as if | |
| 4760 | +** the SQL statement is part of a database schema. This makes a difference | |
| 4761 | +** when the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] option is set to off. | |
| 4762 | +** When this option is used and SQLITE_DBCONFIG_TRUSTED_SCHEMA is off, | |
| 4763 | +** SQL functions may not be called unless they are tagged with | |
| 4764 | +** [SQLITE_INNOCUOUS] and virtual tables may not be used unless tagged | |
| 4765 | +** with [SQLITE_VTAB_INNOCUOUS]. Use the SQLITE_PREPARE_FROM_DDL option | |
| 4766 | +** when preparing SQL that is derived from parts of the database | |
| 4767 | +** schema. In particular, virtual table implementations that | |
| 4768 | +** run SQL statements based on the arguments to their CREATE VIRTUAL | |
| 4769 | +** TABLE statement should use [sqlite3_prepare_v3()] and set the | |
| 4770 | +** SQLITE_PREPARE_FROM_DLL flag to prevent bypass of the | |
| 4771 | +** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks. | |
| 4757 | 4772 | ** </dl> |
| 4758 | 4773 | */ |
| 4759 | 4774 | #define SQLITE_PREPARE_PERSISTENT 0x01 |
| 4760 | 4775 | #define SQLITE_PREPARE_NORMALIZE 0x02 |
| 4761 | 4776 | #define SQLITE_PREPARE_NO_VTAB 0x04 |
| 4762 | 4777 | #define SQLITE_PREPARE_DONT_LOG 0x10 |
| 4778 | +#define SQLITE_PREPARE_FROM_DDL 0x20 | |
| 4763 | 4779 | |
| 4764 | 4780 | /* |
| 4765 | 4781 | ** CAPI3REF: Compiling An SQL Statement |
| 4766 | 4782 | ** KEYWORDS: {SQL statement compiler} |
| 4767 | 4783 | ** METHOD: sqlite3 |
| @@ -4771,12 +4787,13 @@ | ||
| 4771 | 4787 | ** program using one of these routines. Or, in other words, these routines |
| 4772 | 4788 | ** are constructors for the [prepared statement] object. |
| 4773 | 4789 | ** |
| 4774 | 4790 | ** The preferred routine to use is [sqlite3_prepare_v2()]. The |
| 4775 | 4791 | ** [sqlite3_prepare()] interface is legacy and should be avoided. |
| 4776 | -** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used | |
| 4777 | -** for special purposes. | |
| 4792 | +** [sqlite3_prepare_v3()] has an extra | |
| 4793 | +** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times | |
| 4794 | +** needed for special purpose or to pass along security restrictions. | |
| 4778 | 4795 | ** |
| 4779 | 4796 | ** The use of the UTF-8 interfaces is preferred, as SQLite currently |
| 4780 | 4797 | ** does all parsing using UTF-8. The UTF-16 interfaces are provided |
| 4781 | 4798 | ** as a convenience. The UTF-16 interfaces work by converting the |
| 4782 | 4799 | ** input text into UTF-8, then invoking the corresponding UTF-8 interface. |
| @@ -5177,12 +5194,12 @@ | ||
| 5177 | 5194 | ** it should be a pointer to well-formed UTF8 text. |
| 5178 | 5195 | ** ^If the third parameter to sqlite3_bind_text16() is not NULL, then |
| 5179 | 5196 | ** it should be a pointer to well-formed UTF16 text. |
| 5180 | 5197 | ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then |
| 5181 | 5198 | ** it should be a pointer to a well-formed unicode string that is |
| 5182 | -** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16 | |
| 5183 | -** otherwise. | |
| 5199 | +** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT, | |
| 5200 | +** or UTF16 otherwise. | |
| 5184 | 5201 | ** |
| 5185 | 5202 | ** [[byte-order determination rules]] ^The byte-order of |
| 5186 | 5203 | ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF) |
| 5187 | 5204 | ** found in the first character, which is removed, or in the absence of a BOM |
| 5188 | 5205 | ** the byte order is the native byte order of the host |
| @@ -5224,14 +5241,19 @@ | ||
| 5224 | 5241 | ** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the |
| 5225 | 5242 | ** object is to be copied prior to the return from sqlite3_bind_*(). ^The |
| 5226 | 5243 | ** object and pointer to it must remain valid until then. ^SQLite will then |
| 5227 | 5244 | ** manage the lifetime of its private copy. |
| 5228 | 5245 | ** |
| 5229 | -** ^The sixth argument to sqlite3_bind_text64() must be one of | |
| 5230 | -** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] | |
| 5231 | -** to specify the encoding of the text in the third parameter. If | |
| 5232 | -** the sixth argument to sqlite3_bind_text64() is not one of the | |
| 5246 | +** ^The sixth argument (the E argument) | |
| 5247 | +** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of | |
| 5248 | +** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], | |
| 5249 | +** or [SQLITE_UTF16LE] to specify the encoding of the text in the | |
| 5250 | +** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the | |
| 5251 | +** string argument is both UTF-8 encoded and is zero-terminated. In other | |
| 5252 | +** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at | |
| 5253 | +** least N+1 bytes and that the Z[N] byte is zero. If | |
| 5254 | +** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the | |
| 5233 | 5255 | ** allowed values shown above, or if the text encoding is different |
| 5234 | 5256 | ** from the encoding specified by the sixth parameter, then the behavior |
| 5235 | 5257 | ** is undefined. |
| 5236 | 5258 | ** |
| 5237 | 5259 | ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that |
| @@ -6094,17 +6116,63 @@ | ||
| 6094 | 6116 | /* |
| 6095 | 6117 | ** CAPI3REF: Text Encodings |
| 6096 | 6118 | ** |
| 6097 | 6119 | ** These constants define integer codes that represent the various |
| 6098 | 6120 | ** text encodings supported by SQLite. |
| 6121 | +** | |
| 6122 | +** <dl> | |
| 6123 | +** [[SQLITE_UTF8]] <dt>SQLITE_UTF8</dt><dd>Text is encoding as UTF-8</dd> | |
| 6124 | +** | |
| 6125 | +** [[SQLITE_UTF16LE]] <dt>SQLITE_UTF16LE</dt><dd>Text is encoding as UTF-16 | |
| 6126 | +** with each code point being expressed "little endian" - the least significant | |
| 6127 | +** byte first. This is the usual encoding, for example on Windows.</dd> | |
| 6128 | +** | |
| 6129 | +** [[SQLITE_UTF16BE]] <dt>SQLITE_UTF16BE</dt><dd>Text is encoding as UTF-16 | |
| 6130 | +** with each code point being expressed "big endian" - the most significant | |
| 6131 | +** byte first. This encoding is less common, but is still sometimes seen, | |
| 6132 | +** specially on older systems. | |
| 6133 | +** | |
| 6134 | +** [[SQLITE_UTF16]] <dt>SQLITE_UTF16</dt><dd>Text is encoding as UTF-16 | |
| 6135 | +** with each code point being expressed either little endian or as big | |
| 6136 | +** endian, according to the native endianness of the host computer. | |
| 6137 | +** | |
| 6138 | +** [[SQLITE_ANY]] <dt>SQLITE_ANY</dt><dd>This encoding value may only be used | |
| 6139 | +** to declare the preferred text for [application-defined SQL functions] | |
| 6140 | +** created using [sqlite3_create_function()] and similar. If the preferred | |
| 6141 | +** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep | |
| 6142 | +** parameter) is SQLITE_ANY, that indicates that the function does not have | |
| 6143 | +** a preference regarding the text encoding of its parameters and can take | |
| 6144 | +** any text encoding that the SQLite core find convenient to supply. This | |
| 6145 | +** option is deprecated. Please do not use it in new applications. | |
| 6146 | +** | |
| 6147 | +** [[SQLITE_UTF16_ALIGNED]] <dt>SQLITE_UTF16_ALIGNED</dt><dd>This encoding | |
| 6148 | +** value may be used as the 3rd parameter (the eTextRep parameter) to | |
| 6149 | +** [sqlite3_create_collation()] and similar. This encoding value means | |
| 6150 | +** that the application-defined collating sequence created expects its | |
| 6151 | +** input strings to be in UTF16 in native byte order, and that the start | |
| 6152 | +** of the strings must be aligned to a 2-byte boundary. | |
| 6153 | +** | |
| 6154 | +** [[SQLITE_UTF8_ZT]] <dt>SQLITE_UTF8_ZT</dt><dd>This option can only be | |
| 6155 | +** used to specify the text encoding to strings input to [sqlite3_result_text64()] | |
| 6156 | +** and [sqlite3_bind_text64()]. It means that the input string (call it "z") | |
| 6157 | +** is UTF-8 encoded and that it is zero-terminated. If the length parameter | |
| 6158 | +** (call it "n") is non-negative, this encoding option means that the caller | |
| 6159 | +** guarantees that z array contains at least n+1 bytes and that the z[n] | |
| 6160 | +** byte has a value of zero. | |
| 6161 | +** This option gives the same output as SQLITE_UTF8, but can be more efficient | |
| 6162 | +** by avoiding the need to make a copy of the input string, in some cases. | |
| 6163 | +** However, if z is allocated to hold fewer than n+1 bytes or if the | |
| 6164 | +** z[n] byte is not zero, undefined behavior may result. | |
| 6165 | +** </dl> | |
| 6099 | 6166 | */ |
| 6100 | 6167 | #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ |
| 6101 | 6168 | #define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */ |
| 6102 | 6169 | #define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */ |
| 6103 | 6170 | #define SQLITE_UTF16 4 /* Use native byte order */ |
| 6104 | 6171 | #define SQLITE_ANY 5 /* Deprecated */ |
| 6105 | 6172 | #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ |
| 6173 | +#define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */ | |
| 6106 | 6174 | |
| 6107 | 6175 | /* |
| 6108 | 6176 | ** CAPI3REF: Function Flags |
| 6109 | 6177 | ** |
| 6110 | 6178 | ** These constants may be ORed together with the |
| @@ -6606,14 +6674,18 @@ | ||
| 6606 | 6674 | ** use for client data is to provide a mechanism for wrapper libraries |
| 6607 | 6675 | ** to store additional information about an SQLite database connection. |
| 6608 | 6676 | ** |
| 6609 | 6677 | ** There is no limit (other than available memory) on the number of different |
| 6610 | 6678 | ** client data pointers (with different names) that can be attached to a |
| 6611 | -** single database connection. However, the implementation is optimized | |
| 6612 | -** for the case of having only one or two different client data names. | |
| 6613 | -** Applications and wrapper libraries are discouraged from using more than | |
| 6614 | -** one client data name each. | |
| 6679 | +** single database connection. However, the current implementation stores | |
| 6680 | +** the content on a linked list. Insert and retrieval performance will | |
| 6681 | +** be proportional to the number of entries. The design use case, and | |
| 6682 | +** the use case for which the implementation is optimized, is | |
| 6683 | +** that an application will store only small number of client data names, | |
| 6684 | +** typically just one or two. This interface is not intended to be a | |
| 6685 | +** generalized key/value store for thousands or millions of keys. It | |
| 6686 | +** will work for that, but performance might be disappointing. | |
| 6615 | 6687 | ** |
| 6616 | 6688 | ** There is no way to enumerate the client data pointers |
| 6617 | 6689 | ** associated with a database connection. The N parameter can be thought |
| 6618 | 6690 | ** of as a secret key such that only code that knows the secret key is able |
| 6619 | 6691 | ** to access the associated data. |
| @@ -6717,14 +6789,18 @@ | ||
| 6717 | 6789 | ** ^The sqlite3_result_text(), sqlite3_result_text16(), |
| 6718 | 6790 | ** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces |
| 6719 | 6791 | ** set the return value of the application-defined function to be |
| 6720 | 6792 | ** a text string which is represented as UTF-8, UTF-16 native byte order, |
| 6721 | 6793 | ** UTF-16 little endian, or UTF-16 big endian, respectively. |
| 6722 | -** ^The sqlite3_result_text64() interface sets the return value of an | |
| 6794 | +** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an | |
| 6723 | 6795 | ** application-defined function to be a text string in an encoding |
| 6724 | -** specified by the fifth (and last) parameter, which must be one | |
| 6725 | -** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. | |
| 6796 | +** specified the E parameter, which must be one | |
| 6797 | +** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], | |
| 6798 | +** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that | |
| 6799 | +** the result text is both UTF-8 and zero-terminated. In other words, | |
| 6800 | +** SQLITE_UTF8_ZT means that the Z array holds at least N+1 byes and that | |
| 6801 | +** the Z[N] is zero. | |
| 6726 | 6802 | ** ^SQLite takes the text result from the application from |
| 6727 | 6803 | ** the 2nd parameter of the sqlite3_result_text* interfaces. |
| 6728 | 6804 | ** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces |
| 6729 | 6805 | ** other than sqlite3_result_text64() is negative, then SQLite computes |
| 6730 | 6806 | ** the string length itself by searching the 2nd parameter for the first |
| @@ -6807,11 +6883,11 @@ | ||
| 6807 | 6883 | SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); |
| 6808 | 6884 | SQLITE_API void sqlite3_result_int(sqlite3_context*, int); |
| 6809 | 6885 | SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); |
| 6810 | 6886 | SQLITE_API void sqlite3_result_null(sqlite3_context*); |
| 6811 | 6887 | SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); |
| 6812 | -SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, | |
| 6888 | +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n, | |
| 6813 | 6889 | void(*)(void*), unsigned char encoding); |
| 6814 | 6890 | SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); |
| 6815 | 6891 | SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); |
| 6816 | 6892 | SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); |
| 6817 | 6893 | SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); |
| @@ -7746,22 +7822,22 @@ | ||
| 7746 | 7822 | ** ^This interface loads an SQLite extension library from the named file. |
| 7747 | 7823 | ** |
| 7748 | 7824 | ** ^The sqlite3_load_extension() interface attempts to load an |
| 7749 | 7825 | ** [SQLite extension] library contained in the file zFile. If |
| 7750 | 7826 | ** the file cannot be loaded directly, attempts are made to load |
| 7751 | -** with various operating-system specific extensions added. | |
| 7827 | +** with various operating-system specific filename extensions added. | |
| 7752 | 7828 | ** So for example, if "samplelib" cannot be loaded, then names like |
| 7753 | 7829 | ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might |
| 7754 | 7830 | ** be tried also. |
| 7755 | 7831 | ** |
| 7756 | 7832 | ** ^The entry point is zProc. |
| 7757 | 7833 | ** ^(zProc may be 0, in which case SQLite will try to come up with an |
| 7758 | 7834 | ** entry point name on its own. It first tries "sqlite3_extension_init". |
| 7759 | -** If that does not work, it constructs a name "sqlite3_X_init" where | |
| 7760 | -** X consists of the lower-case equivalent of all ASCII alphabetic | |
| 7761 | -** characters in the filename from the last "/" to the first following | |
| 7762 | -** "." and omitting any initial "lib".)^ | |
| 7835 | +** If that does not work, it tries names of the form "sqlite3_X_init" | |
| 7836 | +** where X consists of the lower-case equivalent of all ASCII alphabetic | |
| 7837 | +** characters or all ASCII alphanumeric characters in the filename from | |
| 7838 | +** the last "/" to the first following "." and omitting any initial "lib".)^ | |
| 7763 | 7839 | ** ^The sqlite3_load_extension() interface returns |
| 7764 | 7840 | ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. |
| 7765 | 7841 | ** ^If an error occurs and pzErrMsg is not 0, then the |
| 7766 | 7842 | ** [sqlite3_load_extension()] interface shall attempt to |
| 7767 | 7843 | ** fill *pzErrMsg with error message text stored in memory |
| @@ -11495,23 +11571,45 @@ | ||
| 11495 | 11571 | #define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ |
| 11496 | 11572 | |
| 11497 | 11573 | /* |
| 11498 | 11574 | ** CAPI3REF: Bind array values to the CARRAY table-valued function |
| 11499 | 11575 | ** |
| 11500 | -** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to | |
| 11501 | -** one of the first argument of the [carray() table-valued function]. The | |
| 11502 | -** S parameter is a pointer to the [prepared statement] that uses the carray() | |
| 11503 | -** functions. I is the parameter index to be bound. P is a pointer to the | |
| 11504 | -** array to be bound, and N is the number of eements in the array. The | |
| 11505 | -** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], | |
| 11506 | -** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to | |
| 11507 | -** indicate the datatype of the array being bound. The X argument is not a | |
| 11508 | -** NULL pointer, then SQLite will invoke the function X on the P parameter | |
| 11509 | -** after it has finished using P, even if the call to | |
| 11510 | -** sqlite3_carray_bind() fails. The special-case finalizer | |
| 11511 | -** SQLITE_TRANSIENT has no effect here. | |
| 11576 | +** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to | |
| 11577 | +** parameter that is the first argument of the [carray() table-valued function]. | |
| 11578 | +** The S parameter is a pointer to the [prepared statement] that uses the carray() | |
| 11579 | +** functions. I is the parameter index to be bound. I must be the index of the | |
| 11580 | +** parameter that is the first argument to the carray() table-valued function. | |
| 11581 | +** P is a pointer to the array to be bound, and N is the number of elements in | |
| 11582 | +** the array. The F argument is one of constants [SQLITE_CARRAY_INT32], | |
| 11583 | +** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], | |
| 11584 | +** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P. | |
| 11585 | +** | |
| 11586 | +** If the X argument is not a NULL pointer or one of the special | |
| 11587 | +** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke | |
| 11588 | +** the function X with argument D when it is finished using the data in P. | |
| 11589 | +** The call to X(D) is a destructor for the array P. The destructor X(D) | |
| 11590 | +** is invoked even if the call to sqlite3_carray_bind() fails. If the X | |
| 11591 | +** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes | |
| 11592 | +** that the data static and the destructor is never invoked. If the X | |
| 11593 | +** parameter is the special-case value [SQLITE_TRANSIENT], then | |
| 11594 | +** sqlite3_carray_bind_v2() makes its own private copy of the data prior | |
| 11595 | +** to returning and never invokes the destructor X. | |
| 11596 | +** | |
| 11597 | +** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2() | |
| 11598 | +** with a D parameter set to P. In other words, | |
| 11599 | +** sqlite3_carray_bind(S,I,P,N,F,X) is same as | |
| 11600 | +** sqlite3_carray_bind(S,I,P,N,F,X,P). | |
| 11512 | 11601 | */ |
| 11602 | +SQLITE_API int sqlite3_carray_bind_v2( | |
| 11603 | + sqlite3_stmt *pStmt, /* Statement to be bound */ | |
| 11604 | + int i, /* Parameter index */ | |
| 11605 | + void *aData, /* Pointer to array data */ | |
| 11606 | + int nData, /* Number of data elements */ | |
| 11607 | + int mFlags, /* CARRAY flags */ | |
| 11608 | + void (*xDel)(void*), /* Destructor for aData */ | |
| 11609 | + void *pDel /* Optional argument to xDel() */ | |
| 11610 | +); | |
| 11513 | 11611 | SQLITE_API int sqlite3_carray_bind( |
| 11514 | 11612 | sqlite3_stmt *pStmt, /* Statement to be bound */ |
| 11515 | 11613 | int i, /* Parameter index */ |
| 11516 | 11614 | void *aData, /* Pointer to array data */ |
| 11517 | 11615 | int nData, /* Number of data elements */ |
| @@ -14352,10 +14450,31 @@ | ||
| 14352 | 14450 | #ifndef SQLITE_MAX_LENGTH |
| 14353 | 14451 | # define SQLITE_MAX_LENGTH 1000000000 |
| 14354 | 14452 | #endif |
| 14355 | 14453 | #define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */ |
| 14356 | 14454 | |
| 14455 | +/* | |
| 14456 | +** Maximum size of any single memory allocation. | |
| 14457 | +** | |
| 14458 | +** This is not a limit on the total amount of memory used. This is | |
| 14459 | +** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc(). | |
| 14460 | +** | |
| 14461 | +** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391 | |
| 14462 | +** This provides a 256-byte safety margin for defense against 32-bit | |
| 14463 | +** signed integer overflow bugs when computing memory allocation sizes. | |
| 14464 | +** Paranoid applications might want to reduce the maximum allocation size | |
| 14465 | +** further for an even larger safety margin. 0x3fffffff or 0x0fffffff | |
| 14466 | +** or even smaller would be reasonable upper bounds on the size of a memory | |
| 14467 | +** allocations for most applications. | |
| 14468 | +*/ | |
| 14469 | +#ifndef SQLITE_MAX_ALLOCATION_SIZE | |
| 14470 | +# define SQLITE_MAX_ALLOCATION_SIZE 2147483391 | |
| 14471 | +#endif | |
| 14472 | +#if SQLITE_MAX_ALLOCATION_SIZE>2147483391 | |
| 14473 | +# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391 | |
| 14474 | +#endif | |
| 14475 | + | |
| 14357 | 14476 | /* |
| 14358 | 14477 | ** This is the maximum number of |
| 14359 | 14478 | ** |
| 14360 | 14479 | ** * Columns in a table |
| 14361 | 14480 | ** * Columns in an index |
| @@ -17529,11 +17648,11 @@ | ||
| 17529 | 17648 | |
| 17530 | 17649 | /* |
| 17531 | 17650 | ** Additional non-public SQLITE_PREPARE_* flags |
| 17532 | 17651 | */ |
| 17533 | 17652 | #define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */ |
| 17534 | -#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */ | |
| 17653 | +#define SQLITE_PREPARE_MASK 0x3f /* Mask of public flags */ | |
| 17535 | 17654 | |
| 17536 | 17655 | /* |
| 17537 | 17656 | ** Prototypes for the VDBE interface. See comments on the implementation |
| 17538 | 17657 | ** for a description of what each of these routines does. |
| 17539 | 17658 | */ |
| @@ -20202,31 +20321,17 @@ | ||
| 20202 | 20321 | }; |
| 20203 | 20322 | |
| 20204 | 20323 | /* |
| 20205 | 20324 | ** An instance of the following structure contains all information |
| 20206 | 20325 | ** needed to generate code for a single SELECT statement. |
| 20207 | -** | |
| 20208 | -** See the header comment on the computeLimitRegisters() routine for a | |
| 20209 | -** detailed description of the meaning of the iLimit and iOffset fields. | |
| 20210 | -** | |
| 20211 | -** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. | |
| 20212 | -** These addresses must be stored so that we can go back and fill in | |
| 20213 | -** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor | |
| 20214 | -** the number of columns in P2 can be computed at the same time | |
| 20215 | -** as the OP_OpenEphm instruction is coded because not | |
| 20216 | -** enough information about the compound query is known at that point. | |
| 20217 | -** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences | |
| 20218 | -** for the result set. The KeyInfo for addrOpenEphm[2] contains collating | |
| 20219 | -** sequences for the ORDER BY clause. | |
| 20220 | 20326 | */ |
| 20221 | 20327 | struct Select { |
| 20222 | 20328 | u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ |
| 20223 | 20329 | LogEst nSelectRow; /* Estimated number of result rows */ |
| 20224 | 20330 | u32 selFlags; /* Various SF_* values */ |
| 20225 | 20331 | int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ |
| 20226 | 20332 | u32 selId; /* Unique identifier number for this SELECT */ |
| 20227 | - int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ | |
| 20228 | 20333 | ExprList *pEList; /* The fields of the result */ |
| 20229 | 20334 | SrcList *pSrc; /* The FROM clause */ |
| 20230 | 20335 | Expr *pWhere; /* The WHERE clause */ |
| 20231 | 20336 | ExprList *pGroupBy; /* The GROUP BY clause */ |
| 20232 | 20337 | Expr *pHaving; /* The HAVING clause */ |
| @@ -20254,28 +20359,28 @@ | ||
| 20254 | 20359 | #define SF_Distinct 0x0000001 /* Output should be DISTINCT */ |
| 20255 | 20360 | #define SF_All 0x0000002 /* Includes the ALL keyword */ |
| 20256 | 20361 | #define SF_Resolved 0x0000004 /* Identifiers have been resolved */ |
| 20257 | 20362 | #define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */ |
| 20258 | 20363 | #define SF_HasAgg 0x0000010 /* Contains aggregate functions */ |
| 20259 | -#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */ | |
| 20364 | +/* 0x0000020 // available for reuse */ | |
| 20260 | 20365 | #define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */ |
| 20261 | 20366 | #define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */ |
| 20262 | 20367 | #define SF_Compound 0x0000100 /* Part of a compound query */ |
| 20263 | 20368 | #define SF_Values 0x0000200 /* Synthesized from VALUES clause */ |
| 20264 | 20369 | #define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */ |
| 20265 | 20370 | #define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */ |
| 20266 | 20371 | #define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */ |
| 20267 | 20372 | #define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */ |
| 20268 | 20373 | #define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */ |
| 20269 | -#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */ | |
| 20374 | +/* 0x0008000 // available for reuse */ | |
| 20270 | 20375 | #define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */ |
| 20271 | 20376 | #define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */ |
| 20272 | 20377 | #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */ |
| 20273 | 20378 | #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ |
| 20274 | 20379 | #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ |
| 20275 | 20380 | #define SF_View 0x0200000 /* SELECT statement is a view */ |
| 20276 | -#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ | |
| 20381 | +/* 0x0400000 // available for reuse */ | |
| 20277 | 20382 | #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ |
| 20278 | 20383 | #define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */ |
| 20279 | 20384 | #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ |
| 20280 | 20385 | #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ |
| 20281 | 20386 | #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ |
| @@ -20291,15 +20396,10 @@ | ||
| 20291 | 20396 | /* |
| 20292 | 20397 | ** The results of a SELECT can be distributed in several ways, as defined |
| 20293 | 20398 | ** by one of the following macros. The "SRT" prefix means "SELECT Result |
| 20294 | 20399 | ** Type". |
| 20295 | 20400 | ** |
| 20296 | -** SRT_Union Store results as a key in a temporary index | |
| 20297 | -** identified by pDest->iSDParm. | |
| 20298 | -** | |
| 20299 | -** SRT_Except Remove results from the temporary index pDest->iSDParm. | |
| 20300 | -** | |
| 20301 | 20401 | ** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result |
| 20302 | 20402 | ** set is not empty. |
| 20303 | 20403 | ** |
| 20304 | 20404 | ** SRT_Discard Throw the results away. This is used by SELECT |
| 20305 | 20405 | ** statements within triggers whose only purpose is |
| @@ -20359,34 +20459,32 @@ | ||
| 20359 | 20459 | ** column returned by the SELECT is used as the integer |
| 20360 | 20460 | ** key. If (pDest->iSDParm>0), then the table is an index |
| 20361 | 20461 | ** table. (pDest->iSDParm) is the number of key columns in |
| 20362 | 20462 | ** each index record in this case. |
| 20363 | 20463 | */ |
| 20364 | -#define SRT_Union 1 /* Store result as keys in an index */ | |
| 20365 | -#define SRT_Except 2 /* Remove result from a UNION index */ | |
| 20366 | -#define SRT_Exists 3 /* Store 1 if the result is not empty */ | |
| 20367 | -#define SRT_Discard 4 /* Do not save the results anywhere */ | |
| 20368 | -#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */ | |
| 20369 | -#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */ | |
| 20464 | +#define SRT_Exists 1 /* Store 1 if the result is not empty */ | |
| 20465 | +#define SRT_Discard 2 /* Do not save the results anywhere */ | |
| 20466 | +#define SRT_DistFifo 3 /* Like SRT_Fifo, but unique results only */ | |
| 20467 | +#define SRT_DistQueue 4 /* Like SRT_Queue, but unique results only */ | |
| 20370 | 20468 | |
| 20371 | 20469 | /* The DISTINCT clause is ignored for all of the above. Not that |
| 20372 | 20470 | ** IgnorableDistinct() implies IgnorableOrderby() */ |
| 20373 | 20471 | #define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue) |
| 20374 | 20472 | |
| 20375 | -#define SRT_Queue 7 /* Store result in an queue */ | |
| 20376 | -#define SRT_Fifo 8 /* Store result as data with an automatic rowid */ | |
| 20473 | +#define SRT_Queue 5 /* Store result in an queue */ | |
| 20474 | +#define SRT_Fifo 6 /* Store result as data with an automatic rowid */ | |
| 20377 | 20475 | |
| 20378 | 20476 | /* The ORDER BY clause is ignored for all of the above */ |
| 20379 | 20477 | #define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo) |
| 20380 | 20478 | |
| 20381 | -#define SRT_Output 9 /* Output each row of result */ | |
| 20382 | -#define SRT_Mem 10 /* Store result in a memory cell */ | |
| 20383 | -#define SRT_Set 11 /* Store results as keys in an index */ | |
| 20384 | -#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */ | |
| 20385 | -#define SRT_Coroutine 13 /* Generate a single row of result */ | |
| 20386 | -#define SRT_Table 14 /* Store result as data with an automatic rowid */ | |
| 20387 | -#define SRT_Upfrom 15 /* Store result as data with rowid */ | |
| 20479 | +#define SRT_Output 7 /* Output each row of result */ | |
| 20480 | +#define SRT_Mem 8 /* Store result in a memory cell */ | |
| 20481 | +#define SRT_Set 9 /* Store results as keys in an index */ | |
| 20482 | +#define SRT_EphemTab 10 /* Create transient tab and store like SRT_Table */ | |
| 20483 | +#define SRT_Coroutine 11 /* Generate a single row of result */ | |
| 20484 | +#define SRT_Table 12 /* Store result as data with an automatic rowid */ | |
| 20485 | +#define SRT_Upfrom 13 /* Store result as data with rowid */ | |
| 20388 | 20486 | |
| 20389 | 20487 | /* |
| 20390 | 20488 | ** An instance of this object describes where to put of the results of |
| 20391 | 20489 | ** a SELECT statement. |
| 20392 | 20490 | */ |
| @@ -21018,10 +21116,11 @@ | ||
| 21018 | 21116 | u16 mWFlags; /* Use-dependent flags */ |
| 21019 | 21117 | union { /* Extra data for callback */ |
| 21020 | 21118 | NameContext *pNC; /* Naming context */ |
| 21021 | 21119 | int n; /* A counter */ |
| 21022 | 21120 | int iCur; /* A cursor number */ |
| 21121 | + int sz; /* String literal length */ | |
| 21023 | 21122 | SrcList *pSrcList; /* FROM clause */ |
| 21024 | 21123 | struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ |
| 21025 | 21124 | struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */ |
| 21026 | 21125 | int *aiCol; /* array of column indexes */ |
| 21027 | 21126 | struct IdxCover *pIdxCover; /* Check for index coverage */ |
| @@ -21801,10 +21900,11 @@ | ||
| 21801 | 21900 | SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); |
| 21802 | 21901 | #endif |
| 21803 | 21902 | SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*); |
| 21804 | 21903 | SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); |
| 21805 | 21904 | SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); |
| 21905 | +SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr*); | |
| 21806 | 21906 | SQLITE_PRIVATE int sqlite3IsRowid(const char*); |
| 21807 | 21907 | SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab); |
| 21808 | 21908 | SQLITE_PRIVATE void sqlite3GenerateRowDelete( |
| 21809 | 21909 | Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); |
| 21810 | 21910 | SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); |
| @@ -24489,10 +24589,11 @@ | ||
| 24489 | 24589 | SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*); |
| 24490 | 24590 | SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); |
| 24491 | 24591 | SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); |
| 24492 | 24592 | SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); |
| 24493 | 24593 | SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*)); |
| 24594 | +SQLITE_PRIVATE int sqlite3VdbeMemSetText(Mem*, const char*, i64, void(*)(void*)); | |
| 24494 | 24595 | SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); |
| 24495 | 24596 | #ifdef SQLITE_OMIT_FLOATING_POINT |
| 24496 | 24597 | # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 |
| 24497 | 24598 | #else |
| 24498 | 24599 | SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); |
| @@ -31335,31 +31436,10 @@ | ||
| 31335 | 31436 | sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); |
| 31336 | 31437 | } |
| 31337 | 31438 | *pp = p; |
| 31338 | 31439 | } |
| 31339 | 31440 | |
| 31340 | -/* | |
| 31341 | -** Maximum size of any single memory allocation. | |
| 31342 | -** | |
| 31343 | -** This is not a limit on the total amount of memory used. This is | |
| 31344 | -** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc(). | |
| 31345 | -** | |
| 31346 | -** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391 | |
| 31347 | -** This provides a 256-byte safety margin for defense against 32-bit | |
| 31348 | -** signed integer overflow bugs when computing memory allocation sizes. | |
| 31349 | -** Paranoid applications might want to reduce the maximum allocation size | |
| 31350 | -** further for an even larger safety margin. 0x3fffffff or 0x0fffffff | |
| 31351 | -** or even smaller would be reasonable upper bounds on the size of a memory | |
| 31352 | -** allocations for most applications. | |
| 31353 | -*/ | |
| 31354 | -#ifndef SQLITE_MAX_ALLOCATION_SIZE | |
| 31355 | -# define SQLITE_MAX_ALLOCATION_SIZE 2147483391 | |
| 31356 | -#endif | |
| 31357 | -#if SQLITE_MAX_ALLOCATION_SIZE>2147483391 | |
| 31358 | -# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391 | |
| 31359 | -#endif | |
| 31360 | - | |
| 31361 | 31441 | /* |
| 31362 | 31442 | ** Allocate memory. This routine is like sqlite3_malloc() except that it |
| 31363 | 31443 | ** assumes the memory subsystem has already been initialized. |
| 31364 | 31444 | */ |
| 31365 | 31445 | SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ |
| @@ -31579,12 +31659,11 @@ | ||
| 31579 | 31659 | } |
| 31580 | 31660 | if( nBytes==0 ){ |
| 31581 | 31661 | sqlite3_free(pOld); /* IMP: R-26507-47431 */ |
| 31582 | 31662 | return 0; |
| 31583 | 31663 | } |
| 31584 | - if( nBytes>=0x7fffff00 ){ | |
| 31585 | - /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */ | |
| 31664 | + if( nBytes>SQLITE_MAX_ALLOCATION_SIZE ){ | |
| 31586 | 31665 | return 0; |
| 31587 | 31666 | } |
| 31588 | 31667 | nOld = sqlite3MallocSize(pOld); |
| 31589 | 31668 | /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second |
| 31590 | 31669 | ** argument to xRealloc is always a value returned by a prior call to |
| @@ -48881,78 +48960,54 @@ | ||
| 48881 | 48960 | { "WriteFile", (SYSCALL)WriteFile, 0 }, |
| 48882 | 48961 | |
| 48883 | 48962 | #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \ |
| 48884 | 48963 | LPOVERLAPPED))aSyscall[61].pCurrent) |
| 48885 | 48964 | |
| 48886 | - { "CreateEventExW", (SYSCALL)CreateEventExW, 0 }, | |
| 48887 | - | |
| 48888 | -#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ | |
| 48889 | - DWORD,DWORD))aSyscall[62].pCurrent) | |
| 48890 | - | |
| 48891 | 48965 | /* |
| 48892 | 48966 | ** For WaitForSingleObject(), MSDN says: |
| 48893 | 48967 | ** |
| 48894 | 48968 | ** Minimum supported client: Windows XP [desktop apps | UWP apps] |
| 48895 | 48969 | ** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] |
| 48896 | 48970 | */ |
| 48897 | 48971 | { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, |
| 48898 | 48972 | |
| 48899 | 48973 | #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ |
| 48900 | - DWORD))aSyscall[63].pCurrent) | |
| 48974 | + DWORD))aSyscall[62].pCurrent) | |
| 48901 | 48975 | |
| 48902 | 48976 | #if !SQLITE_OS_WINCE |
| 48903 | 48977 | { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, |
| 48904 | 48978 | #else |
| 48905 | 48979 | { "WaitForSingleObjectEx", (SYSCALL)0, 0 }, |
| 48906 | 48980 | #endif |
| 48907 | 48981 | |
| 48908 | 48982 | #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ |
| 48909 | - BOOL))aSyscall[64].pCurrent) | |
| 48910 | - | |
| 48911 | - { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 }, | |
| 48912 | - | |
| 48913 | -#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \ | |
| 48914 | - PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent) | |
| 48915 | - | |
| 48916 | - { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 }, | |
| 48917 | - | |
| 48918 | -#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ | |
| 48919 | - FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) | |
| 48920 | - | |
| 48921 | - { "CreateFile2", (SYSCALL)CreateFile2, 0 }, | |
| 48922 | - | |
| 48923 | -#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \ | |
| 48924 | - LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent) | |
| 48925 | - | |
| 48926 | - { "GetTickCount64", (SYSCALL)GetTickCount64, 0 }, | |
| 48927 | - | |
| 48928 | -#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent) | |
| 48983 | + BOOL))aSyscall[63].pCurrent) | |
| 48929 | 48984 | |
| 48930 | 48985 | { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 }, |
| 48931 | 48986 | |
| 48932 | 48987 | #define osGetNativeSystemInfo ((VOID(WINAPI*)( \ |
| 48933 | - LPSYSTEM_INFO))aSyscall[71].pCurrent) | |
| 48988 | + LPSYSTEM_INFO))aSyscall[64].pCurrent) | |
| 48934 | 48989 | |
| 48935 | 48990 | #if defined(SQLITE_WIN32_HAS_ANSI) |
| 48936 | 48991 | { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 }, |
| 48937 | 48992 | #else |
| 48938 | 48993 | { "OutputDebugStringA", (SYSCALL)0, 0 }, |
| 48939 | 48994 | #endif |
| 48940 | 48995 | |
| 48941 | -#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent) | |
| 48996 | +#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[65].pCurrent) | |
| 48942 | 48997 | |
| 48943 | 48998 | #if defined(SQLITE_WIN32_HAS_WIDE) |
| 48944 | 48999 | { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 }, |
| 48945 | 49000 | #else |
| 48946 | 49001 | { "OutputDebugStringW", (SYSCALL)0, 0 }, |
| 48947 | 49002 | #endif |
| 48948 | 49003 | |
| 48949 | -#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent) | |
| 49004 | +#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[66].pCurrent) | |
| 48950 | 49005 | |
| 48951 | 49006 | { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, |
| 48952 | 49007 | |
| 48953 | -#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) | |
| 49008 | +#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[67].pCurrent) | |
| 48954 | 49009 | |
| 48955 | 49010 | /* |
| 48956 | 49011 | ** NOTE: On some sub-platforms, the InterlockedCompareExchange "function" |
| 48957 | 49012 | ** is really just a macro that uses a compiler intrinsic (e.g. x64). |
| 48958 | 49013 | ** So do not try to make this is into a redefinable interface. |
| @@ -48963,38 +49018,38 @@ | ||
| 48963 | 49018 | #define osInterlockedCompareExchange InterlockedCompareExchange |
| 48964 | 49019 | #else |
| 48965 | 49020 | { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 }, |
| 48966 | 49021 | |
| 48967 | 49022 | #define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \ |
| 48968 | - SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) | |
| 49023 | + SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[68].pCurrent) | |
| 48969 | 49024 | #endif /* defined(InterlockedCompareExchange) */ |
| 48970 | 49025 | |
| 48971 | 49026 | #if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID |
| 48972 | 49027 | { "UuidCreate", (SYSCALL)UuidCreate, 0 }, |
| 48973 | 49028 | #else |
| 48974 | 49029 | { "UuidCreate", (SYSCALL)0, 0 }, |
| 48975 | 49030 | #endif |
| 48976 | 49031 | |
| 48977 | -#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent) | |
| 49032 | +#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[69].pCurrent) | |
| 48978 | 49033 | |
| 48979 | 49034 | #if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID |
| 48980 | 49035 | { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 }, |
| 48981 | 49036 | #else |
| 48982 | 49037 | { "UuidCreateSequential", (SYSCALL)0, 0 }, |
| 48983 | 49038 | #endif |
| 48984 | 49039 | |
| 48985 | 49040 | #define osUuidCreateSequential \ |
| 48986 | - ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) | |
| 49041 | + ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[70].pCurrent) | |
| 48987 | 49042 | |
| 48988 | 49043 | #if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0 |
| 48989 | 49044 | { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 }, |
| 48990 | 49045 | #else |
| 48991 | 49046 | { "FlushViewOfFile", (SYSCALL)0, 0 }, |
| 48992 | 49047 | #endif |
| 48993 | 49048 | |
| 48994 | 49049 | #define osFlushViewOfFile \ |
| 48995 | - ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) | |
| 49050 | + ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[71].pCurrent) | |
| 48996 | 49051 | |
| 48997 | 49052 | /* |
| 48998 | 49053 | ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent() |
| 48999 | 49054 | ** to implement blocking locks with timeouts. MSDN says: |
| 49000 | 49055 | ** |
| @@ -49007,11 +49062,11 @@ | ||
| 49007 | 49062 | { "CreateEvent", (SYSCALL)0, 0 }, |
| 49008 | 49063 | #endif |
| 49009 | 49064 | |
| 49010 | 49065 | #define osCreateEvent ( \ |
| 49011 | 49066 | (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \ |
| 49012 | - aSyscall[80].pCurrent \ | |
| 49067 | + aSyscall[72].pCurrent \ | |
| 49013 | 49068 | ) |
| 49014 | 49069 | |
| 49015 | 49070 | /* |
| 49016 | 49071 | ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo() |
| 49017 | 49072 | ** for the case where a timeout expires and a lock request must be |
| @@ -49024,68 +49079,68 @@ | ||
| 49024 | 49079 | { "CancelIo", (SYSCALL)CancelIo, 0 }, |
| 49025 | 49080 | #else |
| 49026 | 49081 | { "CancelIo", (SYSCALL)0, 0 }, |
| 49027 | 49082 | #endif |
| 49028 | 49083 | |
| 49029 | -#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent) | |
| 49084 | +#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[73].pCurrent) | |
| 49030 | 49085 | |
| 49031 | 49086 | #if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32) |
| 49032 | 49087 | { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 }, |
| 49033 | 49088 | #else |
| 49034 | 49089 | { "GetModuleHandleW", (SYSCALL)0, 0 }, |
| 49035 | 49090 | #endif |
| 49036 | 49091 | |
| 49037 | -#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[82].pCurrent) | |
| 49092 | +#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[74].pCurrent) | |
| 49038 | 49093 | |
| 49039 | 49094 | #ifndef _WIN32 |
| 49040 | 49095 | { "getenv", (SYSCALL)getenv, 0 }, |
| 49041 | 49096 | #else |
| 49042 | 49097 | { "getenv", (SYSCALL)0, 0 }, |
| 49043 | 49098 | #endif |
| 49044 | 49099 | |
| 49045 | -#define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent) | |
| 49100 | +#define osGetenv ((const char *(*)(const char *))aSyscall[75].pCurrent) | |
| 49046 | 49101 | |
| 49047 | 49102 | #ifndef _WIN32 |
| 49048 | 49103 | { "getcwd", (SYSCALL)getcwd, 0 }, |
| 49049 | 49104 | #else |
| 49050 | 49105 | { "getcwd", (SYSCALL)0, 0 }, |
| 49051 | 49106 | #endif |
| 49052 | 49107 | |
| 49053 | -#define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].pCurrent) | |
| 49108 | +#define osGetcwd ((char*(*)(char*,size_t))aSyscall[76].pCurrent) | |
| 49054 | 49109 | |
| 49055 | 49110 | #ifndef _WIN32 |
| 49056 | 49111 | { "readlink", (SYSCALL)readlink, 0 }, |
| 49057 | 49112 | #else |
| 49058 | 49113 | { "readlink", (SYSCALL)0, 0 }, |
| 49059 | 49114 | #endif |
| 49060 | 49115 | |
| 49061 | -#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[85].pCurrent) | |
| 49116 | +#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[77].pCurrent) | |
| 49062 | 49117 | |
| 49063 | 49118 | #ifndef _WIN32 |
| 49064 | 49119 | { "lstat", (SYSCALL)lstat, 0 }, |
| 49065 | 49120 | #else |
| 49066 | 49121 | { "lstat", (SYSCALL)0, 0 }, |
| 49067 | 49122 | #endif |
| 49068 | 49123 | |
| 49069 | -#define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent) | |
| 49124 | +#define osLstat ((int(*)(const char*,struct stat*))aSyscall[78].pCurrent) | |
| 49070 | 49125 | |
| 49071 | 49126 | #ifndef _WIN32 |
| 49072 | 49127 | { "__errno", (SYSCALL)__errno, 0 }, |
| 49073 | 49128 | #else |
| 49074 | 49129 | { "__errno", (SYSCALL)0, 0 }, |
| 49075 | 49130 | #endif |
| 49076 | 49131 | |
| 49077 | -#define osErrno (*((int*(*)(void))aSyscall[87].pCurrent)()) | |
| 49132 | +#define osErrno (*((int*(*)(void))aSyscall[79].pCurrent)()) | |
| 49078 | 49133 | |
| 49079 | 49134 | #ifndef _WIN32 |
| 49080 | 49135 | { "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 }, |
| 49081 | 49136 | #else |
| 49082 | 49137 | { "cygwin_conv_path", (SYSCALL)0, 0 }, |
| 49083 | 49138 | #endif |
| 49084 | 49139 | |
| 49085 | 49140 | #define osCygwin_conv_path ((size_t(*)(unsigned int, \ |
| 49086 | - const void *, void *, size_t))aSyscall[88].pCurrent) | |
| 49141 | + const void *, void *, size_t))aSyscall[80].pCurrent) | |
| 49087 | 49142 | |
| 49088 | 49143 | }; /* End of the overrideable system calls */ |
| 49089 | 49144 | |
| 49090 | 49145 | /* |
| 49091 | 49146 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| @@ -53659,10 +53714,11 @@ | ||
| 53659 | 53714 | attr = INVALID_FILE_ATTRIBUTES; |
| 53660 | 53715 | }else{ |
| 53661 | 53716 | attr = sAttrData.dwFileAttributes; |
| 53662 | 53717 | } |
| 53663 | 53718 | }else{ |
| 53719 | + if( noRetry ) lastErrno = osGetLastError(); | |
| 53664 | 53720 | winLogIoerr(cnt, __LINE__); |
| 53665 | 53721 | if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ |
| 53666 | 53722 | sqlite3_free(zConverted); |
| 53667 | 53723 | return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", |
| 53668 | 53724 | zFilename); |
| @@ -54399,11 +54455,16 @@ | ||
| 54399 | 54455 | }; |
| 54400 | 54456 | #endif |
| 54401 | 54457 | |
| 54402 | 54458 | /* Double-check that the aSyscall[] array has been constructed |
| 54403 | 54459 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 54404 | - assert( ArraySize(aSyscall)==86 ); | |
| 54460 | + assert( ArraySize(aSyscall)==81 ); | |
| 54461 | + assert( strcmp(aSyscall[0].zName,"AreFileApisANSI")==0 ); | |
| 54462 | + assert( strcmp(aSyscall[20].zName,"GetFileAttributesA")==0 ); | |
| 54463 | + assert( strcmp(aSyscall[40].zName,"HeapReAlloc")==0 ); | |
| 54464 | + assert( strcmp(aSyscall[60].zName,"WideCharToMultiByte")==0 ); | |
| 54465 | + assert( strcmp(aSyscall[80].zName,"cygwin_conv_path")==0 ); | |
| 54405 | 54466 | |
| 54406 | 54467 | /* get memory map allocation granularity */ |
| 54407 | 54468 | memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); |
| 54408 | 54469 | osGetSystemInfo(&winSysInfo); |
| 54409 | 54470 | assert( winSysInfo.dwAllocationGranularity>0 ); |
| @@ -77426,11 +77487,11 @@ | ||
| 77426 | 77487 | } |
| 77427 | 77488 | assert( cursorHoldsMutex(pCur) ); |
| 77428 | 77489 | |
| 77429 | 77490 | getCellInfo(pCur); |
| 77430 | 77491 | aPayload = pCur->info.pPayload; |
| 77431 | - assert( offset+amt <= pCur->info.nPayload ); | |
| 77492 | + assert( (u64)offset+(u64)amt <= (u64)pCur->info.nPayload ); | |
| 77432 | 77493 | |
| 77433 | 77494 | assert( aPayload > pPage->aData ); |
| 77434 | 77495 | if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){ |
| 77435 | 77496 | /* Trying to read or write past the end of the data is an error. The |
| 77436 | 77497 | ** conditional above is really: |
| @@ -77983,11 +78044,11 @@ | ||
| 77983 | 78044 | SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){ |
| 77984 | 78045 | int rc; |
| 77985 | 78046 | |
| 77986 | 78047 | assert( cursorOwnsBtShared(pCur) ); |
| 77987 | 78048 | assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); |
| 77988 | - if( pCur->eState==CURSOR_VALID ){ | |
| 78049 | + if( NEVER(pCur->eState==CURSOR_VALID) ){ | |
| 77989 | 78050 | *pRes = 0; |
| 77990 | 78051 | return SQLITE_OK; |
| 77991 | 78052 | } |
| 77992 | 78053 | rc = moveToRoot(pCur); |
| 77993 | 78054 | if( rc==SQLITE_EMPTY ){ |
| @@ -85876,10 +85937,88 @@ | ||
| 85876 | 85937 | #endif |
| 85877 | 85938 | |
| 85878 | 85939 | |
| 85879 | 85940 | return SQLITE_OK; |
| 85880 | 85941 | } |
| 85942 | + | |
| 85943 | +/* Like sqlite3VdbeMemSetStr() except: | |
| 85944 | +** | |
| 85945 | +** enc is always SQLITE_UTF8 | |
| 85946 | +** pMem->db is always non-NULL | |
| 85947 | +*/ | |
| 85948 | +SQLITE_PRIVATE int sqlite3VdbeMemSetText( | |
| 85949 | + Mem *pMem, /* Memory cell to set to string value */ | |
| 85950 | + const char *z, /* String pointer */ | |
| 85951 | + i64 n, /* Bytes in string, or negative */ | |
| 85952 | + void (*xDel)(void*) /* Destructor function */ | |
| 85953 | +){ | |
| 85954 | + i64 nByte = n; /* New value for pMem->n */ | |
| 85955 | + u16 flags; | |
| 85956 | + | |
| 85957 | + assert( pMem!=0 ); | |
| 85958 | + assert( pMem->db!=0 ); | |
| 85959 | + assert( sqlite3_mutex_held(pMem->db->mutex) ); | |
| 85960 | + assert( !sqlite3VdbeMemIsRowSet(pMem) ); | |
| 85961 | + | |
| 85962 | + /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ | |
| 85963 | + if( !z ){ | |
| 85964 | + sqlite3VdbeMemSetNull(pMem); | |
| 85965 | + return SQLITE_OK; | |
| 85966 | + } | |
| 85967 | + | |
| 85968 | + if( nByte<0 ){ | |
| 85969 | + nByte = strlen(z); | |
| 85970 | + flags = MEM_Str|MEM_Term; | |
| 85971 | + }else{ | |
| 85972 | + flags = MEM_Str; | |
| 85973 | + } | |
| 85974 | + if( nByte>(i64)pMem->db->aLimit[SQLITE_LIMIT_LENGTH] ){ | |
| 85975 | + if( xDel && xDel!=SQLITE_TRANSIENT ){ | |
| 85976 | + if( xDel==SQLITE_DYNAMIC ){ | |
| 85977 | + sqlite3DbFree(pMem->db, (void*)z); | |
| 85978 | + }else{ | |
| 85979 | + xDel((void*)z); | |
| 85980 | + } | |
| 85981 | + } | |
| 85982 | + sqlite3VdbeMemSetNull(pMem); | |
| 85983 | + return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); | |
| 85984 | + } | |
| 85985 | + | |
| 85986 | + /* The following block sets the new values of Mem.z and Mem.xDel. It | |
| 85987 | + ** also sets a flag in local variable "flags" to indicate the memory | |
| 85988 | + ** management (one of MEM_Dyn or MEM_Static). | |
| 85989 | + */ | |
| 85990 | + if( xDel==SQLITE_TRANSIENT ){ | |
| 85991 | + i64 nAlloc = nByte + 1; | |
| 85992 | + testcase( nAlloc==31 ); | |
| 85993 | + testcase( nAlloc==32 ); | |
| 85994 | + if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){ | |
| 85995 | + return SQLITE_NOMEM_BKPT; | |
| 85996 | + } | |
| 85997 | + assert( pMem->z!=0 ); | |
| 85998 | + memcpy(pMem->z, z, nByte); | |
| 85999 | + pMem->z[nByte] = 0; | |
| 86000 | + }else{ | |
| 86001 | + sqlite3VdbeMemRelease(pMem); | |
| 86002 | + pMem->z = (char *)z; | |
| 86003 | + if( xDel==SQLITE_DYNAMIC ){ | |
| 86004 | + pMem->zMalloc = pMem->z; | |
| 86005 | + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); | |
| 86006 | + pMem->xDel = 0; | |
| 86007 | + }else if( xDel==SQLITE_STATIC ){ | |
| 86008 | + pMem->xDel = xDel; | |
| 86009 | + flags |= MEM_Static; | |
| 86010 | + }else{ | |
| 86011 | + pMem->xDel = xDel; | |
| 86012 | + flags |= MEM_Dyn; | |
| 86013 | + } | |
| 86014 | + } | |
| 86015 | + pMem->flags = flags; | |
| 86016 | + pMem->n = (int)(nByte & 0x7fffffff); | |
| 86017 | + pMem->enc = SQLITE_UTF8; | |
| 86018 | + return SQLITE_OK; | |
| 86019 | +} | |
| 85881 | 86020 | |
| 85882 | 86021 | /* |
| 85883 | 86022 | ** Move data out of a btree key or data field and into a Mem structure. |
| 85884 | 86023 | ** The data is payload from the entry that pCur is currently pointing |
| 85885 | 86024 | ** to. offset and amt determine what portion of the data or key to retrieve. |
| @@ -85900,11 +86039,16 @@ | ||
| 85900 | 86039 | u32 amt, /* Number of bytes to return. */ |
| 85901 | 86040 | Mem *pMem /* OUT: Return data in this Mem structure. */ |
| 85902 | 86041 | ){ |
| 85903 | 86042 | int rc; |
| 85904 | 86043 | pMem->flags = MEM_Null; |
| 85905 | - if( sqlite3BtreeMaxRecordSize(pCur)<offset+amt ){ | |
| 86044 | + testcase( amt==SQLITE_MAX_ALLOCATION_SIZE-1 ); | |
| 86045 | + testcase( amt==SQLITE_MAX_ALLOCATION_SIZE ); | |
| 86046 | + if( amt>=SQLITE_MAX_ALLOCATION_SIZE ){ | |
| 86047 | + return SQLITE_NOMEM_BKPT; | |
| 86048 | + } | |
| 86049 | + if( (u64)amt + (u64)offset > (u64)sqlite3BtreeMaxRecordSize(pCur) ){ | |
| 85906 | 86050 | return SQLITE_CORRUPT_BKPT; |
| 85907 | 86051 | } |
| 85908 | 86052 | if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){ |
| 85909 | 86053 | rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z); |
| 85910 | 86054 | if( rc==SQLITE_OK ){ |
| @@ -86568,10 +86712,15 @@ | ||
| 86568 | 86712 | ** the column value into *ppVal. If *ppVal is initially NULL then a new |
| 86569 | 86713 | ** sqlite3_value object is allocated. |
| 86570 | 86714 | ** |
| 86571 | 86715 | ** If *ppVal is initially NULL then the caller is responsible for |
| 86572 | 86716 | ** ensuring that the value written into *ppVal is eventually freed. |
| 86717 | +** | |
| 86718 | +** If the buffer does not contain a well-formed record, this routine may | |
| 86719 | +** read several bytes past the end of the buffer. Callers must therefore | |
| 86720 | +** ensure that any buffer which may contain a corrupt record is padded | |
| 86721 | +** with at least 8 bytes of addressable memory. | |
| 86573 | 86722 | */ |
| 86574 | 86723 | SQLITE_PRIVATE int sqlite3Stat4Column( |
| 86575 | 86724 | sqlite3 *db, /* Database handle */ |
| 86576 | 86725 | const void *pRec, /* Pointer to buffer containing record */ |
| 86577 | 86726 | int nRec, /* Size of buffer pRec in bytes */ |
| @@ -89584,11 +89733,11 @@ | ||
| 89584 | 89733 | assert( !zName || xDel!=SQLITE_DYNAMIC ); |
| 89585 | 89734 | return SQLITE_NOMEM_BKPT; |
| 89586 | 89735 | } |
| 89587 | 89736 | assert( p->aColName!=0 ); |
| 89588 | 89737 | pColName = &(p->aColName[idx+var*p->nResAlloc]); |
| 89589 | - rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); | |
| 89738 | + rc = sqlite3VdbeMemSetText(pColName, zName, -1, xDel); | |
| 89590 | 89739 | assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); |
| 89591 | 89740 | return rc; |
| 89592 | 89741 | } |
| 89593 | 89742 | |
| 89594 | 89743 | /* |
| @@ -92662,11 +92811,27 @@ | ||
| 92662 | 92811 | int n, /* Bytes in string, or negative */ |
| 92663 | 92812 | u8 enc, /* Encoding of z. 0 for BLOBs */ |
| 92664 | 92813 | void (*xDel)(void*) /* Destructor function */ |
| 92665 | 92814 | ){ |
| 92666 | 92815 | Mem *pOut = pCtx->pOut; |
| 92667 | - int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel); | |
| 92816 | + int rc; | |
| 92817 | + if( enc==SQLITE_UTF8 ){ | |
| 92818 | + rc = sqlite3VdbeMemSetText(pOut, z, n, xDel); | |
| 92819 | + }else if( enc==SQLITE_UTF8_ZT ){ | |
| 92820 | + /* It is usually considered improper to assert() on an input. However, | |
| 92821 | + ** the following assert() is checking for inputs that are documented | |
| 92822 | + ** to result in undefined behavior. */ | |
| 92823 | + assert( z==0 | |
| 92824 | + || n<0 | |
| 92825 | + || n>pOut->db->aLimit[SQLITE_LIMIT_LENGTH] | |
| 92826 | + || z[n]==0 | |
| 92827 | + ); | |
| 92828 | + rc = sqlite3VdbeMemSetText(pOut, z, n, xDel); | |
| 92829 | + pOut->flags |= MEM_Term; | |
| 92830 | + }else{ | |
| 92831 | + rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel); | |
| 92832 | + } | |
| 92668 | 92833 | if( rc ){ |
| 92669 | 92834 | if( rc==SQLITE_TOOBIG ){ |
| 92670 | 92835 | sqlite3_result_error_toobig(pCtx); |
| 92671 | 92836 | }else{ |
| 92672 | 92837 | /* The only errors possible from sqlite3VdbeMemSetStr are |
| @@ -92855,11 +93020,11 @@ | ||
| 92855 | 93020 | return; |
| 92856 | 93021 | } |
| 92857 | 93022 | #endif |
| 92858 | 93023 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 92859 | 93024 | assert( xDel!=SQLITE_DYNAMIC ); |
| 92860 | - if( enc!=SQLITE_UTF8 ){ | |
| 93025 | + if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){ | |
| 92861 | 93026 | if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; |
| 92862 | 93027 | n &= ~(u64)1; |
| 92863 | 93028 | } |
| 92864 | 93029 | if( n>0x7fffffff ){ |
| 92865 | 93030 | (void)invokeValueDestructor(z, xDel, pCtx); |
| @@ -93315,11 +93480,11 @@ | ||
| 93315 | 93480 | if( rc==SQLITE_OK ){ |
| 93316 | 93481 | u32 sz; /* Size of current row in bytes */ |
| 93317 | 93482 | Mem sMem; /* Raw content of current row */ |
| 93318 | 93483 | memset(&sMem, 0, sizeof(sMem)); |
| 93319 | 93484 | sz = sqlite3BtreePayloadSize(pRhs->pCsr); |
| 93320 | - rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem); | |
| 93485 | + rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,sz,&sMem); | |
| 93321 | 93486 | if( rc==SQLITE_OK ){ |
| 93322 | 93487 | u8 *zBuf = (u8*)sMem.z; |
| 93323 | 93488 | u32 iSerial; |
| 93324 | 93489 | sqlite3_value *pOut = pRhs->pOut; |
| 93325 | 93490 | int iOff = 1 + getVarint32(&zBuf[1], iSerial); |
| @@ -93964,17 +94129,29 @@ | ||
| 93964 | 94129 | rc = vdbeUnbind(p, (u32)(i-1)); |
| 93965 | 94130 | if( rc==SQLITE_OK ){ |
| 93966 | 94131 | assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ |
| 93967 | 94132 | if( zData!=0 ){ |
| 93968 | 94133 | pVar = &p->aVar[i-1]; |
| 93969 | - rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); | |
| 93970 | - if( rc==SQLITE_OK ){ | |
| 93971 | - if( encoding==0 ){ | |
| 93972 | - pVar->enc = ENC(p->db); | |
| 93973 | - }else{ | |
| 93974 | - rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); | |
| 93975 | - } | |
| 94134 | + if( encoding==SQLITE_UTF8 ){ | |
| 94135 | + rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel); | |
| 94136 | + }else if( encoding==SQLITE_UTF8_ZT ){ | |
| 94137 | + /* It is usually consider improper to assert() on an input. | |
| 94138 | + ** However, the following assert() is checking for inputs | |
| 94139 | + ** that are documented to result in undefined behavior. */ | |
| 94140 | + assert( zData==0 | |
| 94141 | + || nData<0 | |
| 94142 | + || nData>pVar->db->aLimit[SQLITE_LIMIT_LENGTH] | |
| 94143 | + || ((u8*)zData)[nData]==0 | |
| 94144 | + ); | |
| 94145 | + rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel); | |
| 94146 | + pVar->flags |= MEM_Term; | |
| 94147 | + }else{ | |
| 94148 | + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); | |
| 94149 | + if( encoding==0 ) pVar->enc = ENC(p->db); | |
| 94150 | + } | |
| 94151 | + if( rc==SQLITE_OK && encoding!=0 ){ | |
| 94152 | + rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); | |
| 93976 | 94153 | } |
| 93977 | 94154 | if( rc ){ |
| 93978 | 94155 | sqlite3Error(p->db, rc); |
| 93979 | 94156 | rc = sqlite3ApiExit(p->db, rc); |
| 93980 | 94157 | } |
| @@ -94082,11 +94259,11 @@ | ||
| 94082 | 94259 | sqlite3_uint64 nData, |
| 94083 | 94260 | void (*xDel)(void*), |
| 94084 | 94261 | unsigned char enc |
| 94085 | 94262 | ){ |
| 94086 | 94263 | assert( xDel!=SQLITE_DYNAMIC ); |
| 94087 | - if( enc!=SQLITE_UTF8 ){ | |
| 94264 | + if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){ | |
| 94088 | 94265 | if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; |
| 94089 | 94266 | nData &= ~(u64)1; |
| 94090 | 94267 | } |
| 94091 | 94268 | return bindText(pStmt, i, zData, nData, xDel, enc); |
| 94092 | 94269 | } |
| @@ -101780,24 +101957,19 @@ | ||
| 101780 | 101957 | rc = sqlite3VdbeSorterWrite(pC, pIn2); |
| 101781 | 101958 | if( rc) goto abort_due_to_error; |
| 101782 | 101959 | break; |
| 101783 | 101960 | } |
| 101784 | 101961 | |
| 101785 | -/* Opcode: IdxDelete P1 P2 P3 * P5 | |
| 101962 | +/* Opcode: IdxDelete P1 P2 P3 * * | |
| 101786 | 101963 | ** Synopsis: key=r[P2@P3] |
| 101787 | 101964 | ** |
| 101788 | 101965 | ** The content of P3 registers starting at register P2 form |
| 101789 | 101966 | ** an unpacked index key. This opcode removes that entry from the |
| 101790 | 101967 | ** index opened by cursor P1. |
| 101791 | 101968 | ** |
| 101792 | -** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error | |
| 101793 | -** if no matching index entry is found. This happens when running | |
| 101794 | -** an UPDATE or DELETE statement and the index entry to be updated | |
| 101795 | -** or deleted is not found. For some uses of IdxDelete | |
| 101796 | -** (example: the EXCEPT operator) it does not matter that no matching | |
| 101797 | -** entry is found. For those cases, P5 is zero. Also, do not raise | |
| 101798 | -** this (self-correcting and non-critical) error if in writable_schema mode. | |
| 101969 | +** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found | |
| 101970 | +** and not in writable_schema mode. | |
| 101799 | 101971 | */ |
| 101800 | 101972 | case OP_IdxDelete: { |
| 101801 | 101973 | VdbeCursor *pC; |
| 101802 | 101974 | BtCursor *pCrsr; |
| 101803 | 101975 | int res; |
| @@ -101819,11 +101991,11 @@ | ||
| 101819 | 101991 | rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res); |
| 101820 | 101992 | if( rc ) goto abort_due_to_error; |
| 101821 | 101993 | if( res==0 ){ |
| 101822 | 101994 | rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); |
| 101823 | 101995 | if( rc ) goto abort_due_to_error; |
| 101824 | - }else if( pOp->p5 && !sqlite3WritableSchema(db) ){ | |
| 101996 | + }else if( !sqlite3WritableSchema(db) ){ | |
| 101825 | 101997 | rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption"); |
| 101826 | 101998 | goto abort_due_to_error; |
| 101827 | 101999 | } |
| 101828 | 102000 | assert( pC->deferredMoveto==0 ); |
| 101829 | 102001 | pC->cacheStatus = CACHE_STALE; |
| @@ -110988,14 +111160,10 @@ | ||
| 110988 | 111160 | } |
| 110989 | 111161 | } |
| 110990 | 111162 | } |
| 110991 | 111163 | #endif |
| 110992 | 111164 | |
| 110993 | - /* The ORDER BY and GROUP BY clauses may not refer to terms in | |
| 110994 | - ** outer queries | |
| 110995 | - */ | |
| 110996 | - sNC.pNext = 0; | |
| 110997 | 111165 | sNC.ncFlags |= NC_AllowAgg|NC_AllowWin; |
| 110998 | 111166 | |
| 110999 | 111167 | /* If this is a converted compound query, move the ORDER BY clause from |
| 111000 | 111168 | ** the sub-query back to the parent query. At this point each term |
| 111001 | 111169 | ** within the ORDER BY clause has been transformed to an integer value. |
| @@ -112575,11 +112743,13 @@ | ||
| 112575 | 112743 | const Expr *pExpr, /* The function invocation */ |
| 112576 | 112744 | const FuncDef *pDef /* The function being invoked */ |
| 112577 | 112745 | ){ |
| 112578 | 112746 | assert( !IN_RENAME_OBJECT ); |
| 112579 | 112747 | assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 ); |
| 112580 | - if( ExprHasProperty(pExpr, EP_FromDDL) ){ | |
| 112748 | + if( ExprHasProperty(pExpr, EP_FromDDL) | |
| 112749 | + || pParse->prepFlags & SQLITE_PREPARE_FROM_DDL | |
| 112750 | + ){ | |
| 112581 | 112751 | if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0 |
| 112582 | 112752 | || (pParse->db->flags & SQLITE_TrustedSchema)==0 |
| 112583 | 112753 | ){ |
| 112584 | 112754 | /* Functions prohibited in triggers and views if: |
| 112585 | 112755 | ** (1) tagged with SQLITE_DIRECTONLY |
| @@ -113271,13 +113441,11 @@ | ||
| 113271 | 113441 | pNew->pNext = pNext; |
| 113272 | 113442 | pNew->pPrior = 0; |
| 113273 | 113443 | pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); |
| 113274 | 113444 | pNew->iLimit = 0; |
| 113275 | 113445 | pNew->iOffset = 0; |
| 113276 | - pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral; | |
| 113277 | - pNew->addrOpenEphm[0] = -1; | |
| 113278 | - pNew->addrOpenEphm[1] = -1; | |
| 113446 | + pNew->selFlags = p->selFlags; | |
| 113279 | 113447 | pNew->nSelectRow = p->nSelectRow; |
| 113280 | 113448 | pNew->pWith = sqlite3WithDup(db, p->pWith); |
| 113281 | 113449 | #ifndef SQLITE_OMIT_WINDOWFUNC |
| 113282 | 113450 | pNew->pWin = 0; |
| 113283 | 113451 | pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn); |
| @@ -115495,12 +115663,13 @@ | ||
| 115495 | 115663 | if( destIfFalse==destIfNull ){ |
| 115496 | 115664 | /* Combine Step 3 and Step 5 into a single opcode */ |
| 115497 | 115665 | if( ExprHasProperty(pExpr, EP_Subrtn) ){ |
| 115498 | 115666 | const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr); |
| 115499 | 115667 | assert( pOp->opcode==OP_Once || pParse->nErr ); |
| 115500 | - if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */ | |
| 115501 | - assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ); | |
| 115668 | + if( pOp->p3>0 ){ /* tag-202407032019 */ | |
| 115669 | + assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) | |
| 115670 | + || pParse->nErr ); | |
| 115502 | 115671 | sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse, |
| 115503 | 115672 | rLhs, nVector); VdbeCoverage(v); |
| 115504 | 115673 | } |
| 115505 | 115674 | } |
| 115506 | 115675 | sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse, |
| @@ -118687,11 +118856,14 @@ | ||
| 118687 | 118856 | if( sqlite3ExprCompare(0, pExpr, pIEpr->pExpr, iDataCur)==0 ) break; |
| 118688 | 118857 | } |
| 118689 | 118858 | if( pIEpr==0 ) break; |
| 118690 | 118859 | if( NEVER(!ExprUseYTab(pExpr)) ) break; |
| 118691 | 118860 | for(i=0; i<pSrcList->nSrc; i++){ |
| 118692 | - if( pSrcList->a[0].iCursor==pIEpr->iDataCur ) break; | |
| 118861 | + if( pSrcList->a[i].iCursor==pIEpr->iDataCur ){ | |
| 118862 | + testcase( i>0 ); | |
| 118863 | + break; | |
| 118864 | + } | |
| 118693 | 118865 | } |
| 118694 | 118866 | if( i>=pSrcList->nSrc ) break; |
| 118695 | 118867 | if( NEVER(pExpr->pAggInfo!=0) ) break; /* Resolved by outer context */ |
| 118696 | 118868 | if( pParse->nErr ){ return WRC_Abort; } |
| 118697 | 118869 | |
| @@ -131401,11 +131573,11 @@ | ||
| 131401 | 131573 | ** * Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY |
| 131402 | 131574 | ** virtual tables |
| 131403 | 131575 | ** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS |
| 131404 | 131576 | ** virtual tables if PRAGMA trusted_schema=ON. |
| 131405 | 131577 | */ |
| 131406 | - if( pParse->pToplevel!=0 | |
| 131578 | + if( (pParse->pToplevel!=0 || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL)) | |
| 131407 | 131579 | && pTab->u.vtab.p->eVtabRisk > |
| 131408 | 131580 | ((pParse->db->flags & SQLITE_TrustedSchema)!=0) |
| 131409 | 131581 | ){ |
| 131410 | 131582 | sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"", |
| 131411 | 131583 | pTab->zName); |
| @@ -132239,11 +132411,10 @@ | ||
| 132239 | 132411 | VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName)); |
| 132240 | 132412 | r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, |
| 132241 | 132413 | &iPartIdxLabel, pPrior, r1); |
| 132242 | 132414 | sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, |
| 132243 | 132415 | pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); |
| 132244 | - sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */ | |
| 132245 | 132416 | sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); |
| 132246 | 132417 | pPrior = pIdx; |
| 132247 | 132418 | } |
| 132248 | 132419 | } |
| 132249 | 132420 | |
| @@ -133586,11 +133757,11 @@ | ||
| 133586 | 133757 | }else{ |
| 133587 | 133758 | goto unistr_error; |
| 133588 | 133759 | } |
| 133589 | 133760 | } |
| 133590 | 133761 | zOut[j] = 0; |
| 133591 | - sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8); | |
| 133762 | + sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8_ZT); | |
| 133592 | 133763 | return; |
| 133593 | 133764 | |
| 133594 | 133765 | unistr_error: |
| 133595 | 133766 | sqlite3_free(zOut); |
| 133596 | 133767 | sqlite3_result_error(context, "invalid Unicode escape", -1); |
| @@ -133679,11 +133850,11 @@ | ||
| 133679 | 133850 | *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); |
| 133680 | 133851 | *zOut++ = 0x80 + (u8)(c & 0x3F); |
| 133681 | 133852 | } \ |
| 133682 | 133853 | } |
| 133683 | 133854 | *zOut = 0; |
| 133684 | - sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8); | |
| 133855 | + sqlite3_result_text64(context, (char*)z, zOut-z,sqlite3_free,SQLITE_UTF8_ZT); | |
| 133685 | 133856 | } |
| 133686 | 133857 | |
| 133687 | 133858 | /* |
| 133688 | 133859 | ** The hex() function. Interpret the argument as a blob. Return |
| 133689 | 133860 | ** a hexadecimal rendering as text. |
| @@ -133708,11 +133879,11 @@ | ||
| 133708 | 133879 | *(z++) = hexdigits[(c>>4)&0xf]; |
| 133709 | 133880 | *(z++) = hexdigits[c&0xf]; |
| 133710 | 133881 | } |
| 133711 | 133882 | *z = 0; |
| 133712 | 133883 | sqlite3_result_text64(context, zHex, (u64)(z-zHex), |
| 133713 | - sqlite3_free, SQLITE_UTF8); | |
| 133884 | + sqlite3_free, SQLITE_UTF8_ZT); | |
| 133714 | 133885 | } |
| 133715 | 133886 | } |
| 133716 | 133887 | |
| 133717 | 133888 | /* |
| 133718 | 133889 | ** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr |
| @@ -134046,11 +134217,11 @@ | ||
| 134046 | 134217 | } |
| 134047 | 134218 | } |
| 134048 | 134219 | } |
| 134049 | 134220 | z[j] = 0; |
| 134050 | 134221 | assert( j<=n ); |
| 134051 | - sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8); | |
| 134222 | + sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8_ZT); | |
| 134052 | 134223 | } |
| 134053 | 134224 | |
| 134054 | 134225 | /* |
| 134055 | 134226 | ** The CONCAT(...) function. Generate a string result that is the |
| 134056 | 134227 | ** concatentation of all non-null arguments. |
| @@ -141234,10 +141405,12 @@ | ||
| 141234 | 141405 | int (*set_errmsg)(sqlite3*,int,const char*); |
| 141235 | 141406 | int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int); |
| 141236 | 141407 | /* Version 3.52.0 and later */ |
| 141237 | 141408 | void (*str_truncate)(sqlite3_str*,int); |
| 141238 | 141409 | void (*str_free)(sqlite3_str*); |
| 141410 | + int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*)); | |
| 141411 | + int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*); | |
| 141239 | 141412 | }; |
| 141240 | 141413 | |
| 141241 | 141414 | /* |
| 141242 | 141415 | ** This is the function signature used for all extension entry points. It |
| 141243 | 141416 | ** is also defined in the file "loadext.c". |
| @@ -141575,10 +141748,12 @@ | ||
| 141575 | 141748 | #define sqlite3_set_errmsg sqlite3_api->set_errmsg |
| 141576 | 141749 | #define sqlite3_db_status64 sqlite3_api->db_status64 |
| 141577 | 141750 | /* Version 3.52.0 and later */ |
| 141578 | 141751 | #define sqlite3_str_truncate sqlite3_api->str_truncate |
| 141579 | 141752 | #define sqlite3_str_free sqlite3_api->str_free |
| 141753 | +#define sqlite3_carray_bind sqlite3_api->carray_bind | |
| 141754 | +#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2 | |
| 141580 | 141755 | #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
| 141581 | 141756 | |
| 141582 | 141757 | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| 141583 | 141758 | /* This case when the file really is being compiled as a loadable |
| 141584 | 141759 | ** extension */ |
| @@ -142104,11 +142279,18 @@ | ||
| 142104 | 142279 | /* Version 3.51.0 and later */ |
| 142105 | 142280 | sqlite3_set_errmsg, |
| 142106 | 142281 | sqlite3_db_status64, |
| 142107 | 142282 | /* Version 3.52.0 and later */ |
| 142108 | 142283 | sqlite3_str_truncate, |
| 142109 | - sqlite3_str_free | |
| 142284 | + sqlite3_str_free, | |
| 142285 | +#ifdef SQLITE_ENABLE_CARRAY | |
| 142286 | + sqlite3_carray_bind, | |
| 142287 | + sqlite3_carray_bind_v2 | |
| 142288 | +#else | |
| 142289 | + 0, | |
| 142290 | + 0 | |
| 142291 | +#endif | |
| 142110 | 142292 | }; |
| 142111 | 142293 | |
| 142112 | 142294 | /* True if x is the directory separator character |
| 142113 | 142295 | */ |
| 142114 | 142296 | #if SQLITE_OS_WIN |
| @@ -142206,37 +142388,46 @@ | ||
| 142206 | 142388 | |
| 142207 | 142389 | /* If no entry point was specified and the default legacy |
| 142208 | 142390 | ** entry point name "sqlite3_extension_init" was not found, then |
| 142209 | 142391 | ** construct an entry point name "sqlite3_X_init" where the X is |
| 142210 | 142392 | ** replaced by the lowercase value of every ASCII alphabetic |
| 142211 | - ** character in the filename after the last "/" upto the first ".", | |
| 142212 | - ** and eliding the first three characters if they are "lib". | |
| 142393 | + ** character in the filename after the last "/" up to the first ".", | |
| 142394 | + ** and skipping the first three characters if they are "lib". | |
| 142213 | 142395 | ** Examples: |
| 142214 | 142396 | ** |
| 142215 | 142397 | ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init |
| 142216 | 142398 | ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init |
| 142399 | + ** | |
| 142400 | + ** If that still finds no entry point, repeat a second time but this | |
| 142401 | + ** time include both alphabetic and numeric characters up to the first | |
| 142402 | + ** ".". Example: | |
| 142403 | + ** | |
| 142404 | + ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example5_init | |
| 142217 | 142405 | */ |
| 142218 | 142406 | if( xInit==0 && zProc==0 ){ |
| 142219 | 142407 | int iFile, iEntry, c; |
| 142220 | 142408 | int ncFile = sqlite3Strlen30(zFile); |
| 142409 | + int cnt = 0; | |
| 142221 | 142410 | zAltEntry = sqlite3_malloc64(ncFile+30); |
| 142222 | 142411 | if( zAltEntry==0 ){ |
| 142223 | 142412 | sqlite3OsDlClose(pVfs, handle); |
| 142224 | 142413 | return SQLITE_NOMEM_BKPT; |
| 142225 | 142414 | } |
| 142226 | - memcpy(zAltEntry, "sqlite3_", 8); | |
| 142227 | - for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){} | |
| 142228 | - iFile++; | |
| 142229 | - if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; | |
| 142230 | - for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ | |
| 142231 | - if( sqlite3Isalpha(c) ){ | |
| 142232 | - zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; | |
| 142233 | - } | |
| 142234 | - } | |
| 142235 | - memcpy(zAltEntry+iEntry, "_init", 6); | |
| 142236 | - zEntry = zAltEntry; | |
| 142237 | - xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); | |
| 142415 | + do{ | |
| 142416 | + memcpy(zAltEntry, "sqlite3_", 8); | |
| 142417 | + for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){} | |
| 142418 | + iFile++; | |
| 142419 | + if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; | |
| 142420 | + for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ | |
| 142421 | + if( sqlite3Isalpha(c) || (cnt && sqlite3Isdigit(c)) ){ | |
| 142422 | + zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; | |
| 142423 | + } | |
| 142424 | + } | |
| 142425 | + memcpy(zAltEntry+iEntry, "_init", 6); | |
| 142426 | + zEntry = zAltEntry; | |
| 142427 | + xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); | |
| 142428 | + }while( xInit==0 && (++cnt)<2 ); | |
| 142238 | 142429 | } |
| 142239 | 142430 | if( xInit==0 ){ |
| 142240 | 142431 | if( pzErrMsg ){ |
| 142241 | 142432 | nMsg += strlen(zEntry) + 300; |
| 142242 | 142433 | *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); |
| @@ -147518,12 +147709,10 @@ | ||
| 147518 | 147709 | pNew->op = TK_SELECT; |
| 147519 | 147710 | pNew->selFlags = selFlags; |
| 147520 | 147711 | pNew->iLimit = 0; |
| 147521 | 147712 | pNew->iOffset = 0; |
| 147522 | 147713 | pNew->selId = ++pParse->nSelect; |
| 147523 | - pNew->addrOpenEphm[0] = -1; | |
| 147524 | - pNew->addrOpenEphm[1] = -1; | |
| 147525 | 147714 | pNew->nSelectRow = 0; |
| 147526 | 147715 | if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1); |
| 147527 | 147716 | pNew->pSrc = pSrc; |
| 147528 | 147717 | pNew->pWhere = pWhere; |
| 147529 | 147718 | pNew->pGroupBy = pGroupBy; |
| @@ -148667,33 +148856,10 @@ | ||
| 148667 | 148856 | codeOffset(v, p->iOffset, iContinue); |
| 148668 | 148857 | } |
| 148669 | 148858 | } |
| 148670 | 148859 | |
| 148671 | 148860 | switch( eDest ){ |
| 148672 | - /* In this mode, write each query result to the key of the temporary | |
| 148673 | - ** table iParm. | |
| 148674 | - */ | |
| 148675 | -#ifndef SQLITE_OMIT_COMPOUND_SELECT | |
| 148676 | - case SRT_Union: { | |
| 148677 | - int r1; | |
| 148678 | - r1 = sqlite3GetTempReg(pParse); | |
| 148679 | - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); | |
| 148680 | - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); | |
| 148681 | - sqlite3ReleaseTempReg(pParse, r1); | |
| 148682 | - break; | |
| 148683 | - } | |
| 148684 | - | |
| 148685 | - /* Construct a record from the query result, but instead of | |
| 148686 | - ** saving that record, use it as a key to delete elements from | |
| 148687 | - ** the temporary table iParm. | |
| 148688 | - */ | |
| 148689 | - case SRT_Except: { | |
| 148690 | - sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol); | |
| 148691 | - break; | |
| 148692 | - } | |
| 148693 | -#endif /* SQLITE_OMIT_COMPOUND_SELECT */ | |
| 148694 | - | |
| 148695 | 148861 | /* Store the result as data using a unique key. |
| 148696 | 148862 | */ |
| 148697 | 148863 | case SRT_Fifo: |
| 148698 | 148864 | case SRT_DistFifo: |
| 148699 | 148865 | case SRT_Table: |
| @@ -149976,13 +150142,13 @@ | ||
| 149976 | 150142 | ** |
| 149977 | 150143 | ** Space to hold the KeyInfo structure is obtained from malloc. The calling |
| 149978 | 150144 | ** function is responsible for ensuring that this structure is eventually |
| 149979 | 150145 | ** freed. |
| 149980 | 150146 | */ |
| 149981 | -static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ | |
| 150147 | +static KeyInfo *multiSelectByMergeKeyInfo(Parse *pParse, Select *p, int nExtra){ | |
| 149982 | 150148 | ExprList *pOrderBy = p->pOrderBy; |
| 149983 | - int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0; | |
| 150149 | + int nOrderBy = (pOrderBy!=0) ? pOrderBy->nExpr : 0; | |
| 149984 | 150150 | sqlite3 *db = pParse->db; |
| 149985 | 150151 | KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1); |
| 149986 | 150152 | if( pRet ){ |
| 149987 | 150153 | int i; |
| 149988 | 150154 | for(i=0; i<nOrderBy; i++){ |
| @@ -150111,21 +150277,41 @@ | ||
| 150111 | 150277 | |
| 150112 | 150278 | /* Allocate cursors for Current, Queue, and Distinct. */ |
| 150113 | 150279 | regCurrent = ++pParse->nMem; |
| 150114 | 150280 | sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol); |
| 150115 | 150281 | if( pOrderBy ){ |
| 150116 | - KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1); | |
| 150282 | + KeyInfo *pKeyInfo = multiSelectByMergeKeyInfo(pParse, p, 1); | |
| 150117 | 150283 | sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0, |
| 150118 | 150284 | (char*)pKeyInfo, P4_KEYINFO); |
| 150119 | 150285 | destQueue.pOrderBy = pOrderBy; |
| 150120 | 150286 | }else{ |
| 150121 | 150287 | sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol); |
| 150122 | 150288 | } |
| 150123 | 150289 | VdbeComment((v, "Queue table")); |
| 150124 | 150290 | if( iDistinct ){ |
| 150125 | - p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0); | |
| 150126 | - p->selFlags |= SF_UsesEphemeral; | |
| 150291 | + /* Generate an ephemeral table used to enforce distinctness on the | |
| 150292 | + ** output of the recursive part of the CTE. | |
| 150293 | + */ | |
| 150294 | + KeyInfo *pKeyInfo; /* Collating sequence for the result set */ | |
| 150295 | + CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ | |
| 150296 | + | |
| 150297 | + assert( p->pNext==0 ); | |
| 150298 | + assert( p->pEList!=0 ); | |
| 150299 | + nCol = p->pEList->nExpr; | |
| 150300 | + pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nCol, 1); | |
| 150301 | + if( pKeyInfo ){ | |
| 150302 | + for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ | |
| 150303 | + *apColl = multiSelectCollSeq(pParse, p, i); | |
| 150304 | + if( 0==*apColl ){ | |
| 150305 | + *apColl = pParse->db->pDfltColl; | |
| 150306 | + } | |
| 150307 | + } | |
| 150308 | + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iDistinct, nCol, 0, | |
| 150309 | + (void*)pKeyInfo, P4_KEYINFO); | |
| 150310 | + }else{ | |
| 150311 | + assert( pParse->nErr>0 ); | |
| 150312 | + } | |
| 150127 | 150313 | } |
| 150128 | 150314 | |
| 150129 | 150315 | /* Detach the ORDER BY clause from the compound SELECT */ |
| 150130 | 150316 | p->pOrderBy = 0; |
| 150131 | 150317 | |
| @@ -150196,11 +150382,11 @@ | ||
| 150196 | 150382 | return; |
| 150197 | 150383 | } |
| 150198 | 150384 | #endif /* SQLITE_OMIT_CTE */ |
| 150199 | 150385 | |
| 150200 | 150386 | /* Forward references */ |
| 150201 | -static int multiSelectOrderBy( | |
| 150387 | +static int multiSelectByMerge( | |
| 150202 | 150388 | Parse *pParse, /* Parsing context */ |
| 150203 | 150389 | Select *p, /* The right-most of SELECTs to be coded */ |
| 150204 | 150390 | SelectDest *pDest /* What to do with query results */ |
| 150205 | 150391 | ); |
| 150206 | 150392 | |
| @@ -150345,317 +150531,80 @@ | ||
| 150345 | 150531 | #ifndef SQLITE_OMIT_CTE |
| 150346 | 150532 | if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){ |
| 150347 | 150533 | generateWithRecursiveQuery(pParse, p, &dest); |
| 150348 | 150534 | }else |
| 150349 | 150535 | #endif |
| 150350 | - | |
| 150351 | - /* Compound SELECTs that have an ORDER BY clause are handled separately. | |
| 150352 | - */ | |
| 150353 | 150536 | if( p->pOrderBy ){ |
| 150354 | - return multiSelectOrderBy(pParse, p, pDest); | |
| 150537 | + /* If the compound has an ORDER BY clause, then always use the merge | |
| 150538 | + ** algorithm. */ | |
| 150539 | + return multiSelectByMerge(pParse, p, pDest); | |
| 150540 | + }else if( p->op!=TK_ALL ){ | |
| 150541 | + /* If the compound is EXCEPT, INTERSECT, or UNION (anything other than | |
| 150542 | + ** UNION ALL) then also always use the merge algorithm. However, the | |
| 150543 | + ** multiSelectByMerge() routine requires that the compound have an | |
| 150544 | + ** ORDER BY clause, and it doesn't right now. So invent one first. */ | |
| 150545 | + Expr *pOne = sqlite3ExprInt32(db, 1); | |
| 150546 | + p->pOrderBy = sqlite3ExprListAppend(pParse, 0, pOne); | |
| 150547 | + if( pParse->nErr ) goto multi_select_end; | |
| 150548 | + assert( p->pOrderBy!=0 ); | |
| 150549 | + p->pOrderBy->a[0].u.x.iOrderByCol = 1; | |
| 150550 | + return multiSelectByMerge(pParse, p, pDest); | |
| 150355 | 150551 | }else{ |
| 150552 | + /* For a UNION ALL compound without ORDER BY, simply run the left | |
| 150553 | + ** query, then run the right query */ | |
| 150554 | + int addr = 0; | |
| 150555 | + int nLimit = 0; /* Initialize to suppress harmless compiler warning */ | |
| 150356 | 150556 | |
| 150357 | 150557 | #ifndef SQLITE_OMIT_EXPLAIN |
| 150358 | 150558 | if( pPrior->pPrior==0 ){ |
| 150359 | 150559 | ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); |
| 150360 | 150560 | ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); |
| 150361 | 150561 | } |
| 150362 | 150562 | #endif |
| 150363 | - | |
| 150364 | - /* Generate code for the left and right SELECT statements. | |
| 150365 | - */ | |
| 150366 | - switch( p->op ){ | |
| 150367 | - case TK_ALL: { | |
| 150368 | - int addr = 0; | |
| 150369 | - int nLimit = 0; /* Initialize to suppress harmless compiler warning */ | |
| 150370 | - assert( !pPrior->pLimit ); | |
| 150371 | - pPrior->iLimit = p->iLimit; | |
| 150372 | - pPrior->iOffset = p->iOffset; | |
| 150373 | - pPrior->pLimit = p->pLimit; | |
| 150374 | - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n")); | |
| 150375 | - rc = sqlite3Select(pParse, pPrior, &dest); | |
| 150376 | - pPrior->pLimit = 0; | |
| 150377 | - if( rc ){ | |
| 150378 | - goto multi_select_end; | |
| 150379 | - } | |
| 150380 | - p->pPrior = 0; | |
| 150381 | - p->iLimit = pPrior->iLimit; | |
| 150382 | - p->iOffset = pPrior->iOffset; | |
| 150383 | - if( p->iLimit ){ | |
| 150384 | - addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); | |
| 150385 | - VdbeComment((v, "Jump ahead if LIMIT reached")); | |
| 150386 | - if( p->iOffset ){ | |
| 150387 | - sqlite3VdbeAddOp3(v, OP_OffsetLimit, | |
| 150388 | - p->iLimit, p->iOffset+1, p->iOffset); | |
| 150389 | - } | |
| 150390 | - } | |
| 150391 | - ExplainQueryPlan((pParse, 1, "UNION ALL")); | |
| 150392 | - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n")); | |
| 150393 | - rc = sqlite3Select(pParse, p, &dest); | |
| 150394 | - testcase( rc!=SQLITE_OK ); | |
| 150395 | - pDelete = p->pPrior; | |
| 150396 | - p->pPrior = pPrior; | |
| 150397 | - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); | |
| 150398 | - if( p->pLimit | |
| 150399 | - && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse) | |
| 150400 | - && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) | |
| 150401 | - ){ | |
| 150402 | - p->nSelectRow = sqlite3LogEst((u64)nLimit); | |
| 150403 | - } | |
| 150404 | - if( addr ){ | |
| 150405 | - sqlite3VdbeJumpHere(v, addr); | |
| 150406 | - } | |
| 150407 | - break; | |
| 150408 | - } | |
| 150409 | - case TK_EXCEPT: | |
| 150410 | - case TK_UNION: { | |
| 150411 | - int unionTab; /* Cursor number of the temp table holding result */ | |
| 150412 | - u8 op = 0; /* One of the SRT_ operations to apply to self */ | |
| 150413 | - int priorOp; /* The SRT_ operation to apply to prior selects */ | |
| 150414 | - Expr *pLimit; /* Saved values of p->nLimit */ | |
| 150415 | - int addr; | |
| 150416 | - int emptyBypass = 0; /* IfEmpty opcode to bypass RHS */ | |
| 150417 | - SelectDest uniondest; | |
| 150418 | - | |
| 150419 | - | |
| 150420 | - testcase( p->op==TK_EXCEPT ); | |
| 150421 | - testcase( p->op==TK_UNION ); | |
| 150422 | - priorOp = SRT_Union; | |
| 150423 | - if( dest.eDest==priorOp ){ | |
| 150424 | - /* We can reuse a temporary table generated by a SELECT to our | |
| 150425 | - ** right. | |
| 150426 | - */ | |
| 150427 | - assert( p->pLimit==0 ); /* Not allowed on leftward elements */ | |
| 150428 | - unionTab = dest.iSDParm; | |
| 150429 | - }else{ | |
| 150430 | - /* We will need to create our own temporary table to hold the | |
| 150431 | - ** intermediate results. | |
| 150432 | - */ | |
| 150433 | - unionTab = pParse->nTab++; | |
| 150434 | - assert( p->pOrderBy==0 ); | |
| 150435 | - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); | |
| 150436 | - assert( p->addrOpenEphm[0] == -1 ); | |
| 150437 | - p->addrOpenEphm[0] = addr; | |
| 150438 | - findRightmost(p)->selFlags |= SF_UsesEphemeral; | |
| 150439 | - assert( p->pEList ); | |
| 150440 | - } | |
| 150441 | - | |
| 150442 | - | |
| 150443 | - /* Code the SELECT statements to our left | |
| 150444 | - */ | |
| 150445 | - assert( !pPrior->pOrderBy ); | |
| 150446 | - sqlite3SelectDestInit(&uniondest, priorOp, unionTab); | |
| 150447 | - TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n")); | |
| 150448 | - rc = sqlite3Select(pParse, pPrior, &uniondest); | |
| 150449 | - if( rc ){ | |
| 150450 | - goto multi_select_end; | |
| 150451 | - } | |
| 150452 | - | |
| 150453 | - /* Code the current SELECT statement | |
| 150454 | - */ | |
| 150455 | - if( p->op==TK_EXCEPT ){ | |
| 150456 | - op = SRT_Except; | |
| 150457 | - emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, unionTab); | |
| 150458 | - VdbeCoverage(v); | |
| 150459 | - }else{ | |
| 150460 | - assert( p->op==TK_UNION ); | |
| 150461 | - op = SRT_Union; | |
| 150462 | - } | |
| 150463 | - p->pPrior = 0; | |
| 150464 | - pLimit = p->pLimit; | |
| 150465 | - p->pLimit = 0; | |
| 150466 | - uniondest.eDest = op; | |
| 150467 | - ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", | |
| 150468 | - sqlite3SelectOpName(p->op))); | |
| 150469 | - TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n")); | |
| 150470 | - rc = sqlite3Select(pParse, p, &uniondest); | |
| 150471 | - testcase( rc!=SQLITE_OK ); | |
| 150472 | - assert( p->pOrderBy==0 ); | |
| 150473 | - pDelete = p->pPrior; | |
| 150474 | - p->pPrior = pPrior; | |
| 150475 | - p->pOrderBy = 0; | |
| 150476 | - if( p->op==TK_UNION ){ | |
| 150477 | - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); | |
| 150478 | - } | |
| 150479 | - if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass); | |
| 150480 | - sqlite3ExprDelete(db, p->pLimit); | |
| 150481 | - p->pLimit = pLimit; | |
| 150482 | - p->iLimit = 0; | |
| 150483 | - p->iOffset = 0; | |
| 150484 | - | |
| 150485 | - /* Convert the data in the temporary table into whatever form | |
| 150486 | - ** it is that we currently need. | |
| 150487 | - */ | |
| 150488 | - assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); | |
| 150489 | - assert( p->pEList || db->mallocFailed ); | |
| 150490 | - if( dest.eDest!=priorOp && db->mallocFailed==0 ){ | |
| 150491 | - int iCont, iBreak, iStart; | |
| 150492 | - iBreak = sqlite3VdbeMakeLabel(pParse); | |
| 150493 | - iCont = sqlite3VdbeMakeLabel(pParse); | |
| 150494 | - computeLimitRegisters(pParse, p, iBreak); | |
| 150495 | - sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); | |
| 150496 | - iStart = sqlite3VdbeCurrentAddr(v); | |
| 150497 | - selectInnerLoop(pParse, p, unionTab, | |
| 150498 | - 0, 0, &dest, iCont, iBreak); | |
| 150499 | - sqlite3VdbeResolveLabel(v, iCont); | |
| 150500 | - sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); | |
| 150501 | - sqlite3VdbeResolveLabel(v, iBreak); | |
| 150502 | - sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); | |
| 150503 | - } | |
| 150504 | - break; | |
| 150505 | - } | |
| 150506 | - default: assert( p->op==TK_INTERSECT ); { | |
| 150507 | - int tab1, tab2; | |
| 150508 | - int iCont, iBreak, iStart; | |
| 150509 | - Expr *pLimit; | |
| 150510 | - int addr, iLimit, iOffset; | |
| 150511 | - SelectDest intersectdest; | |
| 150512 | - int r1; | |
| 150513 | - int emptyBypass; | |
| 150514 | - | |
| 150515 | - /* INTERSECT is different from the others since it requires | |
| 150516 | - ** two temporary tables. Hence it has its own case. Begin | |
| 150517 | - ** by allocating the tables we will need. | |
| 150518 | - */ | |
| 150519 | - tab1 = pParse->nTab++; | |
| 150520 | - tab2 = pParse->nTab++; | |
| 150521 | - assert( p->pOrderBy==0 ); | |
| 150522 | - | |
| 150523 | - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); | |
| 150524 | - assert( p->addrOpenEphm[0] == -1 ); | |
| 150525 | - p->addrOpenEphm[0] = addr; | |
| 150526 | - findRightmost(p)->selFlags |= SF_UsesEphemeral; | |
| 150527 | - assert( p->pEList ); | |
| 150528 | - | |
| 150529 | - /* Code the SELECTs to our left into temporary table "tab1". | |
| 150530 | - */ | |
| 150531 | - sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); | |
| 150532 | - TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n")); | |
| 150533 | - rc = sqlite3Select(pParse, pPrior, &intersectdest); | |
| 150534 | - if( rc ){ | |
| 150535 | - goto multi_select_end; | |
| 150536 | - } | |
| 150537 | - | |
| 150538 | - /* Initialize LIMIT counters before checking to see if the LHS | |
| 150539 | - ** is empty, in case the jump is taken */ | |
| 150540 | - iBreak = sqlite3VdbeMakeLabel(pParse); | |
| 150541 | - computeLimitRegisters(pParse, p, iBreak); | |
| 150542 | - emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, tab1); VdbeCoverage(v); | |
| 150543 | - | |
| 150544 | - /* Code the current SELECT into temporary table "tab2" | |
| 150545 | - */ | |
| 150546 | - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); | |
| 150547 | - assert( p->addrOpenEphm[1] == -1 ); | |
| 150548 | - p->addrOpenEphm[1] = addr; | |
| 150549 | - | |
| 150550 | - /* Disable prior SELECTs and the LIMIT counters during the computation | |
| 150551 | - ** of the RHS select */ | |
| 150552 | - pLimit = p->pLimit; | |
| 150553 | - iLimit = p->iLimit; | |
| 150554 | - iOffset = p->iOffset; | |
| 150555 | - p->pPrior = 0; | |
| 150556 | - p->pLimit = 0; | |
| 150557 | - p->iLimit = 0; | |
| 150558 | - p->iOffset = 0; | |
| 150559 | - | |
| 150560 | - intersectdest.iSDParm = tab2; | |
| 150561 | - ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", | |
| 150562 | - sqlite3SelectOpName(p->op))); | |
| 150563 | - TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n")); | |
| 150564 | - rc = sqlite3Select(pParse, p, &intersectdest); | |
| 150565 | - testcase( rc!=SQLITE_OK ); | |
| 150566 | - pDelete = p->pPrior; | |
| 150567 | - p->pPrior = pPrior; | |
| 150568 | - if( p->nSelectRow>pPrior->nSelectRow ){ | |
| 150569 | - p->nSelectRow = pPrior->nSelectRow; | |
| 150570 | - } | |
| 150571 | - sqlite3ExprDelete(db, p->pLimit); | |
| 150572 | - | |
| 150573 | - /* Reinstate the LIMIT counters prior to running the final intersect */ | |
| 150574 | - p->pLimit = pLimit; | |
| 150575 | - p->iLimit = iLimit; | |
| 150576 | - p->iOffset = iOffset; | |
| 150577 | - | |
| 150578 | - /* Generate code to take the intersection of the two temporary | |
| 150579 | - ** tables. | |
| 150580 | - */ | |
| 150581 | - if( rc ) break; | |
| 150582 | - assert( p->pEList ); | |
| 150583 | - sqlite3VdbeAddOp1(v, OP_Rewind, tab1); | |
| 150584 | - r1 = sqlite3GetTempReg(pParse); | |
| 150585 | - iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); | |
| 150586 | - iCont = sqlite3VdbeMakeLabel(pParse); | |
| 150587 | - sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); | |
| 150588 | - VdbeCoverage(v); | |
| 150589 | - sqlite3ReleaseTempReg(pParse, r1); | |
| 150590 | - selectInnerLoop(pParse, p, tab1, | |
| 150591 | - 0, 0, &dest, iCont, iBreak); | |
| 150592 | - sqlite3VdbeResolveLabel(v, iCont); | |
| 150593 | - sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); | |
| 150594 | - sqlite3VdbeResolveLabel(v, iBreak); | |
| 150595 | - sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); | |
| 150596 | - sqlite3VdbeJumpHere(v, emptyBypass); | |
| 150597 | - sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); | |
| 150598 | - break; | |
| 150599 | - } | |
| 150600 | - } | |
| 150601 | - | |
| 150602 | - #ifndef SQLITE_OMIT_EXPLAIN | |
| 150563 | + assert( !pPrior->pLimit ); | |
| 150564 | + pPrior->iLimit = p->iLimit; | |
| 150565 | + pPrior->iOffset = p->iOffset; | |
| 150566 | + pPrior->pLimit = sqlite3ExprDup(db, p->pLimit, 0); | |
| 150567 | + TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n")); | |
| 150568 | + rc = sqlite3Select(pParse, pPrior, &dest); | |
| 150569 | + sqlite3ExprDelete(db, pPrior->pLimit); | |
| 150570 | + pPrior->pLimit = 0; | |
| 150571 | + if( rc ){ | |
| 150572 | + goto multi_select_end; | |
| 150573 | + } | |
| 150574 | + p->pPrior = 0; | |
| 150575 | + p->iLimit = pPrior->iLimit; | |
| 150576 | + p->iOffset = pPrior->iOffset; | |
| 150577 | + if( p->iLimit ){ | |
| 150578 | + addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); | |
| 150579 | + VdbeComment((v, "Jump ahead if LIMIT reached")); | |
| 150580 | + if( p->iOffset ){ | |
| 150581 | + sqlite3VdbeAddOp3(v, OP_OffsetLimit, | |
| 150582 | + p->iLimit, p->iOffset+1, p->iOffset); | |
| 150583 | + } | |
| 150584 | + } | |
| 150585 | + ExplainQueryPlan((pParse, 1, "UNION ALL")); | |
| 150586 | + TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n")); | |
| 150587 | + rc = sqlite3Select(pParse, p, &dest); | |
| 150588 | + testcase( rc!=SQLITE_OK ); | |
| 150589 | + pDelete = p->pPrior; | |
| 150590 | + p->pPrior = pPrior; | |
| 150591 | + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); | |
| 150592 | + if( p->pLimit | |
| 150593 | + && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse) | |
| 150594 | + && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) | |
| 150595 | + ){ | |
| 150596 | + p->nSelectRow = sqlite3LogEst((u64)nLimit); | |
| 150597 | + } | |
| 150598 | + if( addr ){ | |
| 150599 | + sqlite3VdbeJumpHere(v, addr); | |
| 150600 | + } | |
| 150601 | +#ifndef SQLITE_OMIT_EXPLAIN | |
| 150603 | 150602 | if( p->pNext==0 ){ |
| 150604 | 150603 | ExplainQueryPlanPop(pParse); |
| 150605 | 150604 | } |
| 150606 | - #endif | |
| 150607 | - } | |
| 150608 | - if( pParse->nErr ) goto multi_select_end; | |
| 150609 | - | |
| 150610 | - /* Compute collating sequences used by | |
| 150611 | - ** temporary tables needed to implement the compound select. | |
| 150612 | - ** Attach the KeyInfo structure to all temporary tables. | |
| 150613 | - ** | |
| 150614 | - ** This section is run by the right-most SELECT statement only. | |
| 150615 | - ** SELECT statements to the left always skip this part. The right-most | |
| 150616 | - ** SELECT might also skip this part if it has no ORDER BY clause and | |
| 150617 | - ** no temp tables are required. | |
| 150618 | - */ | |
| 150619 | - if( p->selFlags & SF_UsesEphemeral ){ | |
| 150620 | - int i; /* Loop counter */ | |
| 150621 | - KeyInfo *pKeyInfo; /* Collating sequence for the result set */ | |
| 150622 | - Select *pLoop; /* For looping through SELECT statements */ | |
| 150623 | - CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ | |
| 150624 | - int nCol; /* Number of columns in result set */ | |
| 150625 | - | |
| 150626 | - assert( p->pNext==0 ); | |
| 150627 | - assert( p->pEList!=0 ); | |
| 150628 | - nCol = p->pEList->nExpr; | |
| 150629 | - pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1); | |
| 150630 | - if( !pKeyInfo ){ | |
| 150631 | - rc = SQLITE_NOMEM_BKPT; | |
| 150632 | - goto multi_select_end; | |
| 150633 | - } | |
| 150634 | - for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ | |
| 150635 | - *apColl = multiSelectCollSeq(pParse, p, i); | |
| 150636 | - if( 0==*apColl ){ | |
| 150637 | - *apColl = db->pDfltColl; | |
| 150638 | - } | |
| 150639 | - } | |
| 150640 | - | |
| 150641 | - for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ | |
| 150642 | - for(i=0; i<2; i++){ | |
| 150643 | - int addr = pLoop->addrOpenEphm[i]; | |
| 150644 | - if( addr<0 ){ | |
| 150645 | - /* If [0] is unused then [1] is also unused. So we can | |
| 150646 | - ** always safely abort as soon as the first unused slot is found */ | |
| 150647 | - assert( pLoop->addrOpenEphm[1]<0 ); | |
| 150648 | - break; | |
| 150649 | - } | |
| 150650 | - sqlite3VdbeChangeP2(v, addr, nCol); | |
| 150651 | - sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo), | |
| 150652 | - P4_KEYINFO); | |
| 150653 | - pLoop->addrOpenEphm[i] = -1; | |
| 150654 | - } | |
| 150655 | - } | |
| 150656 | - sqlite3KeyInfoUnref(pKeyInfo); | |
| 150605 | +#endif | |
| 150657 | 150606 | } |
| 150658 | 150607 | |
| 150659 | 150608 | multi_select_end: |
| 150660 | 150609 | pDest->iSdst = dest.iSdst; |
| 150661 | 150610 | pDest->nSdst = dest.nSdst; |
| @@ -150683,12 +150632,12 @@ | ||
| 150683 | 150632 | |
| 150684 | 150633 | /* |
| 150685 | 150634 | ** Code an output subroutine for a coroutine implementation of a |
| 150686 | 150635 | ** SELECT statement. |
| 150687 | 150636 | ** |
| 150688 | -** The data to be output is contained in pIn->iSdst. There are | |
| 150689 | -** pIn->nSdst columns to be output. pDest is where the output should | |
| 150637 | +** The data to be output is contained in an array of pIn->nSdst registers | |
| 150638 | +** starting at register pIn->iSdst. pDest is where the output should | |
| 150690 | 150639 | ** be sent. |
| 150691 | 150640 | ** |
| 150692 | 150641 | ** regReturn is the number of the register holding the subroutine |
| 150693 | 150642 | ** return address. |
| 150694 | 150643 | ** |
| @@ -150713,10 +150662,12 @@ | ||
| 150713 | 150662 | ){ |
| 150714 | 150663 | Vdbe *v = pParse->pVdbe; |
| 150715 | 150664 | int iContinue; |
| 150716 | 150665 | int addr; |
| 150717 | 150666 | |
| 150667 | + assert( pIn->eDest==SRT_Coroutine ); | |
| 150668 | + | |
| 150718 | 150669 | addr = sqlite3VdbeCurrentAddr(v); |
| 150719 | 150670 | iContinue = sqlite3VdbeMakeLabel(pParse); |
| 150720 | 150671 | |
| 150721 | 150672 | /* Suppress duplicates for UNION, EXCEPT, and INTERSECT |
| 150722 | 150673 | */ |
| @@ -150734,26 +150685,63 @@ | ||
| 150734 | 150685 | |
| 150735 | 150686 | /* Suppress the first OFFSET entries if there is an OFFSET clause |
| 150736 | 150687 | */ |
| 150737 | 150688 | codeOffset(v, p->iOffset, iContinue); |
| 150738 | 150689 | |
| 150739 | - assert( pDest->eDest!=SRT_Exists ); | |
| 150740 | - assert( pDest->eDest!=SRT_Table ); | |
| 150741 | 150690 | switch( pDest->eDest ){ |
| 150742 | 150691 | /* Store the result as data using a unique key. |
| 150743 | 150692 | */ |
| 150693 | + case SRT_Fifo: | |
| 150694 | + case SRT_DistFifo: | |
| 150695 | + case SRT_Table: | |
| 150744 | 150696 | case SRT_EphemTab: { |
| 150745 | 150697 | int r1 = sqlite3GetTempReg(pParse); |
| 150746 | 150698 | int r2 = sqlite3GetTempReg(pParse); |
| 150699 | + int iParm = pDest->iSDParm; | |
| 150700 | + testcase( pDest->eDest==SRT_Table ); | |
| 150701 | + testcase( pDest->eDest==SRT_EphemTab ); | |
| 150702 | + testcase( pDest->eDest==SRT_Fifo ); | |
| 150703 | + testcase( pDest->eDest==SRT_DistFifo ); | |
| 150747 | 150704 | sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); |
| 150748 | - sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); | |
| 150749 | - sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2); | |
| 150705 | +#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG) | |
| 150706 | + /* A destination of SRT_Table and a non-zero iSDParm2 parameter means | |
| 150707 | + ** that this is an "UPDATE ... FROM" on a virtual table or view. In this | |
| 150708 | + ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC. | |
| 150709 | + ** This does not affect operation in any way - it just allows MakeRecord | |
| 150710 | + ** to process OPFLAG_NOCHANGE values without an assert() failing. */ | |
| 150711 | + if( pDest->eDest==SRT_Table && pDest->iSDParm2 ){ | |
| 150712 | + sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); | |
| 150713 | + } | |
| 150714 | +#endif | |
| 150715 | +#ifndef SQLITE_OMIT_CTE | |
| 150716 | + if( pDest->eDest==SRT_DistFifo ){ | |
| 150717 | + /* If the destination is DistFifo, then cursor (iParm+1) is open | |
| 150718 | + ** on an ephemeral index that is used to enforce uniqueness on the | |
| 150719 | + ** total result. At this point, we are processing the setup portion | |
| 150720 | + ** of the recursive CTE using the merge algorithm, so the results are | |
| 150721 | + ** guaranteed to be unique anyhow. But we still need to populate the | |
| 150722 | + ** (iParm+1) cursor for use by the subsequent recursive phase. | |
| 150723 | + */ | |
| 150724 | + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1, | |
| 150725 | + pIn->iSdst, pIn->nSdst); | |
| 150726 | + } | |
| 150727 | +#endif | |
| 150728 | + sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); | |
| 150729 | + sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2); | |
| 150750 | 150730 | sqlite3VdbeChangeP5(v, OPFLAG_APPEND); |
| 150751 | 150731 | sqlite3ReleaseTempReg(pParse, r2); |
| 150752 | 150732 | sqlite3ReleaseTempReg(pParse, r1); |
| 150753 | 150733 | break; |
| 150754 | 150734 | } |
| 150735 | + | |
| 150736 | + /* If any row exist in the result set, record that fact and abort. | |
| 150737 | + */ | |
| 150738 | + case SRT_Exists: { | |
| 150739 | + sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm); | |
| 150740 | + /* The LIMIT clause will terminate the loop for us */ | |
| 150741 | + break; | |
| 150742 | + } | |
| 150755 | 150743 | |
| 150756 | 150744 | #ifndef SQLITE_OMIT_SUBQUERY |
| 150757 | 150745 | /* If we are creating a set for an "expr IN (SELECT ...)". |
| 150758 | 150746 | */ |
| 150759 | 150747 | case SRT_Set: { |
| @@ -150796,14 +150784,74 @@ | ||
| 150796 | 150784 | } |
| 150797 | 150785 | sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst); |
| 150798 | 150786 | sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); |
| 150799 | 150787 | break; |
| 150800 | 150788 | } |
| 150789 | + | |
| 150790 | +#ifndef SQLITE_OMIT_CTE | |
| 150791 | + /* Write the results into a priority queue that is order according to | |
| 150792 | + ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an | |
| 150793 | + ** index with pSO->nExpr+2 columns. Build a key using pSO for the first | |
| 150794 | + ** pSO->nExpr columns, then make sure all keys are unique by adding a | |
| 150795 | + ** final OP_Sequence column. The last column is the record as a blob. | |
| 150796 | + */ | |
| 150797 | + case SRT_DistQueue: | |
| 150798 | + case SRT_Queue: { | |
| 150799 | + int nKey; | |
| 150800 | + int r1, r2, r3, ii; | |
| 150801 | + ExprList *pSO; | |
| 150802 | + int iParm = pDest->iSDParm; | |
| 150803 | + pSO = pDest->pOrderBy; | |
| 150804 | + assert( pSO ); | |
| 150805 | + nKey = pSO->nExpr; | |
| 150806 | + r1 = sqlite3GetTempReg(pParse); | |
| 150807 | + r2 = sqlite3GetTempRange(pParse, nKey+2); | |
| 150808 | + r3 = r2+nKey+1; | |
| 150809 | + | |
| 150810 | +#if 0 /* <-- Why the next block of code is commented out: (tag-20260125-a) | |
| 150811 | + ** | |
| 150812 | + ** If the destination is DistQueue, then cursor (iParm+1) is open | |
| 150813 | + ** on a second ephemeral index that holds all values previously | |
| 150814 | + ** added to the queue. This code only runs during the setup phase | |
| 150815 | + ** using the merge algorithm, and so the values here are already | |
| 150816 | + ** guaranteed to be unique. | |
| 150817 | + */ | |
| 150818 | + if( pDest->eDest==SRT_DistQueue ){ | |
| 150819 | + addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, | |
| 150820 | + pIn->iSdst, pIn->nSdst); | |
| 150821 | + VdbeCoverage(v); | |
| 150822 | + } | |
| 150823 | +#endif | |
| 150824 | + sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r3); | |
| 150825 | + if( pDest->eDest==SRT_DistQueue ){ | |
| 150826 | + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3); | |
| 150827 | + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); | |
| 150828 | + } | |
| 150829 | + for(ii=0; ii<nKey; ii++){ | |
| 150830 | + sqlite3VdbeAddOp2(v, OP_SCopy, | |
| 150831 | + pIn->iSdst + pSO->a[ii].u.x.iOrderByCol - 1, | |
| 150832 | + r2+ii); | |
| 150833 | + } | |
| 150834 | + sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); | |
| 150835 | + sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); | |
| 150836 | + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2); | |
| 150837 | +#if 0 /* tag-20260125-a */ | |
| 150838 | + if( addrTest ) sqlite3VdbeJumpHere(v, addrTest); | |
| 150839 | +#endif | |
| 150840 | + sqlite3ReleaseTempReg(pParse, r1); | |
| 150841 | + sqlite3ReleaseTempRange(pParse, r2, nKey+2); | |
| 150842 | + break; | |
| 150843 | + } | |
| 150844 | +#endif /* SQLITE_OMIT_CTE */ | |
| 150845 | + | |
| 150846 | + /* Ignore the output */ | |
| 150847 | + case SRT_Discard: { | |
| 150848 | + break; | |
| 150849 | + } | |
| 150801 | 150850 | |
| 150802 | 150851 | /* If none of the above, then the result destination must be |
| 150803 | - ** SRT_Output. This routine is never called with any other | |
| 150804 | - ** destination other than the ones handled above or SRT_Output. | |
| 150852 | + ** SRT_Output. | |
| 150805 | 150853 | ** |
| 150806 | 150854 | ** For SRT_Output, results are stored in a sequence of registers. |
| 150807 | 150855 | ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to |
| 150808 | 150856 | ** return the next row of result. |
| 150809 | 150857 | */ |
| @@ -150827,12 +150875,13 @@ | ||
| 150827 | 150875 | |
| 150828 | 150876 | return addr; |
| 150829 | 150877 | } |
| 150830 | 150878 | |
| 150831 | 150879 | /* |
| 150832 | -** Alternative compound select code generator for cases when there | |
| 150833 | -** is an ORDER BY clause. | |
| 150880 | +** Generate code for a compound SELECT statement using a merge | |
| 150881 | +** algorithm. The compound must have an ORDER BY clause for this | |
| 150882 | +** to work. | |
| 150834 | 150883 | ** |
| 150835 | 150884 | ** We assume a query of the following form: |
| 150836 | 150885 | ** |
| 150837 | 150886 | ** <selectA> <operator> <selectB> ORDER BY <orderbylist> |
| 150838 | 150887 | ** |
| @@ -150845,11 +150894,11 @@ | ||
| 150845 | 150894 | ** outA: Move the output of the selectA coroutine into the output |
| 150846 | 150895 | ** of the compound query. |
| 150847 | 150896 | ** |
| 150848 | 150897 | ** outB: Move the output of the selectB coroutine into the output |
| 150849 | 150898 | ** of the compound query. (Only generated for UNION and |
| 150850 | -** UNION ALL. EXCEPT and INSERTSECT never output a row that | |
| 150899 | +** UNION ALL. EXCEPT and INTERSECT never output a row that | |
| 150851 | 150900 | ** appears only in B.) |
| 150852 | 150901 | ** |
| 150853 | 150902 | ** AltB: Called when there is data from both coroutines and A<B. |
| 150854 | 150903 | ** |
| 150855 | 150904 | ** AeqB: Called when there is data from both coroutines and A==B. |
| @@ -150898,25 +150947,23 @@ | ||
| 150898 | 150947 | ** EofB: ... |
| 150899 | 150948 | ** AltB: ... |
| 150900 | 150949 | ** AeqB: ... |
| 150901 | 150950 | ** AgtB: ... |
| 150902 | 150951 | ** Init: initialize coroutine registers |
| 150903 | -** yield coA | |
| 150904 | -** if eof(A) goto EofA | |
| 150905 | -** yield coB | |
| 150906 | -** if eof(B) goto EofB | |
| 150952 | +** yield coA, on eof goto EofA | |
| 150953 | +** yield coB, on eof goto EofB | |
| 150907 | 150954 | ** Cmpr: Compare A, B |
| 150908 | 150955 | ** Jump AltB, AeqB, AgtB |
| 150909 | 150956 | ** End: ... |
| 150910 | 150957 | ** |
| 150911 | 150958 | ** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not |
| 150912 | 150959 | ** actually called using Gosub and they do not Return. EofA and EofB loop |
| 150913 | 150960 | ** until all data is exhausted then jump to the "end" label. AltB, AeqB, |
| 150914 | -** and AgtB jump to either L2 or to one of EofA or EofB. | |
| 150961 | +** and AgtB jump to either Cmpr or to one of EofA or EofB. | |
| 150915 | 150962 | */ |
| 150916 | 150963 | #ifndef SQLITE_OMIT_COMPOUND_SELECT |
| 150917 | -static int multiSelectOrderBy( | |
| 150964 | +static int multiSelectByMerge( | |
| 150918 | 150965 | Parse *pParse, /* Parsing context */ |
| 150919 | 150966 | Select *p, /* The right-most of SELECTs to be coded */ |
| 150920 | 150967 | SelectDest *pDest /* What to do with query results */ |
| 150921 | 150968 | ){ |
| 150922 | 150969 | int i, j; /* Loop counters */ |
| @@ -150993,30 +151040,33 @@ | ||
| 150993 | 151040 | } |
| 150994 | 151041 | } |
| 150995 | 151042 | } |
| 150996 | 151043 | |
| 150997 | 151044 | /* Compute the comparison permutation and keyinfo that is used with |
| 150998 | - ** the permutation used to determine if the next | |
| 150999 | - ** row of results comes from selectA or selectB. Also add explicit | |
| 151000 | - ** collations to the ORDER BY clause terms so that when the subqueries | |
| 151001 | - ** to the right and the left are evaluated, they use the correct | |
| 151002 | - ** collation. | |
| 151045 | + ** the permutation to determine if the next row of results comes | |
| 151046 | + ** from selectA or selectB. Also add literal collations to the | |
| 151047 | + ** ORDER BY clause terms so that when selectA and selectB are | |
| 151048 | + ** evaluated, they use the correct collation. | |
| 151003 | 151049 | */ |
| 151004 | 151050 | aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1)); |
| 151005 | 151051 | if( aPermute ){ |
| 151006 | 151052 | struct ExprList_item *pItem; |
| 151053 | + int bKeep = 0; | |
| 151007 | 151054 | aPermute[0] = nOrderBy; |
| 151008 | 151055 | for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){ |
| 151009 | 151056 | assert( pItem!=0 ); |
| 151010 | 151057 | assert( pItem->u.x.iOrderByCol>0 ); |
| 151011 | 151058 | assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); |
| 151012 | 151059 | aPermute[i] = pItem->u.x.iOrderByCol - 1; |
| 151060 | + if( aPermute[i]!=(u32)i-1 ) bKeep = 1; | |
| 151013 | 151061 | } |
| 151014 | - pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); | |
| 151015 | - }else{ | |
| 151016 | - pKeyMerge = 0; | |
| 151062 | + if( bKeep==0 ){ | |
| 151063 | + sqlite3DbFreeNN(db, aPermute); | |
| 151064 | + aPermute = 0; | |
| 151065 | + } | |
| 151017 | 151066 | } |
| 151067 | + pKeyMerge = multiSelectByMergeKeyInfo(pParse, p, 1); | |
| 151018 | 151068 | |
| 151019 | 151069 | /* Allocate a range of temporary registers and the KeyInfo needed |
| 151020 | 151070 | ** for the logic that removes duplicate result rows when the |
| 151021 | 151071 | ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL). |
| 151022 | 151072 | */ |
| @@ -151091,11 +151141,11 @@ | ||
| 151091 | 151141 | /* Generate a coroutine to evaluate the SELECT statement to the |
| 151092 | 151142 | ** left of the compound operator - the "A" select. |
| 151093 | 151143 | */ |
| 151094 | 151144 | addrSelectA = sqlite3VdbeCurrentAddr(v) + 1; |
| 151095 | 151145 | addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); |
| 151096 | - VdbeComment((v, "left SELECT")); | |
| 151146 | + VdbeComment((v, "SUBR: next-A")); | |
| 151097 | 151147 | pPrior->iLimit = regLimitA; |
| 151098 | 151148 | ExplainQueryPlan((pParse, 1, "LEFT")); |
| 151099 | 151149 | sqlite3Select(pParse, pPrior, &destA); |
| 151100 | 151150 | sqlite3VdbeEndCoroutine(v, regAddrA); |
| 151101 | 151151 | sqlite3VdbeJumpHere(v, addr1); |
| @@ -151103,11 +151153,11 @@ | ||
| 151103 | 151153 | /* Generate a coroutine to evaluate the SELECT statement on |
| 151104 | 151154 | ** the right - the "B" select |
| 151105 | 151155 | */ |
| 151106 | 151156 | addrSelectB = sqlite3VdbeCurrentAddr(v) + 1; |
| 151107 | 151157 | addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); |
| 151108 | - VdbeComment((v, "right SELECT")); | |
| 151158 | + VdbeComment((v, "SUBR: next-B")); | |
| 151109 | 151159 | savedLimit = p->iLimit; |
| 151110 | 151160 | savedOffset = p->iOffset; |
| 151111 | 151161 | p->iLimit = regLimitB; |
| 151112 | 151162 | p->iOffset = 0; |
| 151113 | 151163 | ExplainQueryPlan((pParse, 1, "RIGHT")); |
| @@ -151117,20 +151167,20 @@ | ||
| 151117 | 151167 | sqlite3VdbeEndCoroutine(v, regAddrB); |
| 151118 | 151168 | |
| 151119 | 151169 | /* Generate a subroutine that outputs the current row of the A |
| 151120 | 151170 | ** select as the next output row of the compound select. |
| 151121 | 151171 | */ |
| 151122 | - VdbeNoopComment((v, "Output routine for A")); | |
| 151172 | + VdbeNoopComment((v, "SUBR: out-A")); | |
| 151123 | 151173 | addrOutA = generateOutputSubroutine(pParse, |
| 151124 | 151174 | p, &destA, pDest, regOutA, |
| 151125 | 151175 | regPrev, pKeyDup, labelEnd); |
| 151126 | 151176 | |
| 151127 | 151177 | /* Generate a subroutine that outputs the current row of the B |
| 151128 | 151178 | ** select as the next output row of the compound select. |
| 151129 | 151179 | */ |
| 151130 | 151180 | if( op==TK_ALL || op==TK_UNION ){ |
| 151131 | - VdbeNoopComment((v, "Output routine for B")); | |
| 151181 | + VdbeNoopComment((v, "SUBR: out-B")); | |
| 151132 | 151182 | addrOutB = generateOutputSubroutine(pParse, |
| 151133 | 151183 | p, &destB, pDest, regOutB, |
| 151134 | 151184 | regPrev, pKeyDup, labelEnd); |
| 151135 | 151185 | } |
| 151136 | 151186 | sqlite3KeyInfoUnref(pKeyDup); |
| @@ -151139,14 +151189,16 @@ | ||
| 151139 | 151189 | ** are exhausted and only data in select B remains. |
| 151140 | 151190 | */ |
| 151141 | 151191 | if( op==TK_EXCEPT || op==TK_INTERSECT ){ |
| 151142 | 151192 | addrEofA_noB = addrEofA = labelEnd; |
| 151143 | 151193 | }else{ |
| 151144 | - VdbeNoopComment((v, "eof-A subroutine")); | |
| 151194 | + VdbeNoopComment((v, "SUBR: eof-A")); | |
| 151145 | 151195 | addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); |
| 151196 | + VdbeComment((v, "out-B")); | |
| 151146 | 151197 | addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); |
| 151147 | 151198 | VdbeCoverage(v); |
| 151199 | + VdbeComment((v, "next-B")); | |
| 151148 | 151200 | sqlite3VdbeGoto(v, addrEofA); |
| 151149 | 151201 | p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); |
| 151150 | 151202 | } |
| 151151 | 151203 | |
| 151152 | 151204 | /* Generate a subroutine to run when the results from select B |
| @@ -151154,21 +151206,24 @@ | ||
| 151154 | 151206 | */ |
| 151155 | 151207 | if( op==TK_INTERSECT ){ |
| 151156 | 151208 | addrEofB = addrEofA; |
| 151157 | 151209 | if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; |
| 151158 | 151210 | }else{ |
| 151159 | - VdbeNoopComment((v, "eof-B subroutine")); | |
| 151211 | + VdbeNoopComment((v, "SUBR: eof-B")); | |
| 151160 | 151212 | addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); |
| 151213 | + VdbeComment((v, "out-A")); | |
| 151161 | 151214 | sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); |
| 151215 | + VdbeComment((v, "next-A")); | |
| 151162 | 151216 | sqlite3VdbeGoto(v, addrEofB); |
| 151163 | 151217 | } |
| 151164 | 151218 | |
| 151165 | 151219 | /* Generate code to handle the case of A<B |
| 151166 | 151220 | */ |
| 151167 | - VdbeNoopComment((v, "A-lt-B subroutine")); | |
| 151168 | 151221 | addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); |
| 151222 | + VdbeComment((v, "out-A")); | |
| 151169 | 151223 | sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); |
| 151224 | + VdbeComment((v, "next-A")); | |
| 151170 | 151225 | sqlite3VdbeGoto(v, labelCmpr); |
| 151171 | 151226 | |
| 151172 | 151227 | /* Generate code to handle the case of A==B |
| 151173 | 151228 | */ |
| 151174 | 151229 | if( op==TK_ALL ){ |
| @@ -151175,40 +151230,52 @@ | ||
| 151175 | 151230 | addrAeqB = addrAltB; |
| 151176 | 151231 | }else if( op==TK_INTERSECT ){ |
| 151177 | 151232 | addrAeqB = addrAltB; |
| 151178 | 151233 | addrAltB++; |
| 151179 | 151234 | }else{ |
| 151180 | - VdbeNoopComment((v, "A-eq-B subroutine")); | |
| 151181 | - addrAeqB = | |
| 151182 | - sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); | |
| 151183 | - sqlite3VdbeGoto(v, labelCmpr); | |
| 151235 | + addrAeqB = addrAltB + 1; | |
| 151184 | 151236 | } |
| 151185 | 151237 | |
| 151186 | 151238 | /* Generate code to handle the case of A>B |
| 151187 | 151239 | */ |
| 151188 | - VdbeNoopComment((v, "A-gt-B subroutine")); | |
| 151189 | 151240 | addrAgtB = sqlite3VdbeCurrentAddr(v); |
| 151190 | 151241 | if( op==TK_ALL || op==TK_UNION ){ |
| 151191 | 151242 | sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); |
| 151243 | + VdbeComment((v, "out-B")); | |
| 151244 | + sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); | |
| 151245 | + VdbeComment((v, "next-B")); | |
| 151246 | + sqlite3VdbeGoto(v, labelCmpr); | |
| 151247 | + }else{ | |
| 151248 | + addrAgtB++; /* Just do next-B. Might as well use the next-B call | |
| 151249 | + ** in the next code block */ | |
| 151192 | 151250 | } |
| 151193 | - sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); | |
| 151194 | - sqlite3VdbeGoto(v, labelCmpr); | |
| 151195 | 151251 | |
| 151196 | 151252 | /* This code runs once to initialize everything. |
| 151197 | 151253 | */ |
| 151198 | 151254 | sqlite3VdbeJumpHere(v, addr1); |
| 151199 | 151255 | sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); |
| 151256 | + VdbeComment((v, "next-A")); | |
| 151257 | + /* v--- Also the A>B case for EXCEPT and INTERSECT */ | |
| 151200 | 151258 | sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); |
| 151259 | + VdbeComment((v, "next-B")); | |
| 151201 | 151260 | |
| 151202 | 151261 | /* Implement the main merge loop |
| 151203 | 151262 | */ |
| 151263 | + if( aPermute!=0 ){ | |
| 151264 | + sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); | |
| 151265 | + } | |
| 151204 | 151266 | sqlite3VdbeResolveLabel(v, labelCmpr); |
| 151205 | - sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); | |
| 151206 | 151267 | sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, |
| 151207 | 151268 | (char*)pKeyMerge, P4_KEYINFO); |
| 151208 | - sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); | |
| 151209 | - sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v); | |
| 151269 | + if( aPermute!=0 ){ | |
| 151270 | + sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); | |
| 151271 | + } | |
| 151272 | + sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); | |
| 151273 | + VdbeCoverageIf(v, op==TK_ALL); | |
| 151274 | + VdbeCoverageIf(v, op==TK_UNION); | |
| 151275 | + VdbeCoverageIf(v, op==TK_EXCEPT); | |
| 151276 |