Fossil SCM
Cherry-pick [http://www.sqlite.org/src/info/11a70e1ae7f05d06e4e09c9d20db0444b8881584|11a70e1ae7]: Refactor the names of state objects in the command-line shell implementation
Commit
e4bc6f12ead5d4056325291d112388203af19cb6
Parent
bb5fa492744aec6…
1 file changed
+66
-59
+66
-59
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -430,23 +430,28 @@ | ||
| 430 | 430 | #endif |
| 431 | 431 | } |
| 432 | 432 | return zResult; |
| 433 | 433 | } |
| 434 | 434 | |
| 435 | -struct previous_mode_data { | |
| 436 | - int valid; /* Is there legit data in here? */ | |
| 437 | - int mode; | |
| 438 | - int showHeader; | |
| 439 | - int colWidth[100]; | |
| 435 | +/* | |
| 436 | +** Shell output mode information from before ".explain on", | |
| 437 | +** saved so that it can be restored by ".explain off" | |
| 438 | +*/ | |
| 439 | +typedef struct SavedModeInfo SavedModeInfo; | |
| 440 | +struct SavedModeInfo { | |
| 441 | + int valid; /* Is there legit data in here? */ | |
| 442 | + int mode; /* Mode prior to ".explain on" */ | |
| 443 | + int showHeader; /* The ".header" setting prior to ".explain on" */ | |
| 444 | + int colWidth[100]; /* Column widths prior to ".explain on" */ | |
| 440 | 445 | }; |
| 441 | 446 | |
| 442 | 447 | /* |
| 443 | -** An pointer to an instance of this structure is passed from | |
| 444 | -** the main program to the callback. This is used to communicate | |
| 445 | -** state and mode information. | |
| 448 | +** State information about the database connection is contained in an | |
| 449 | +** instance of the following structure. | |
| 446 | 450 | */ |
| 447 | -struct callback_data { | |
| 451 | +typedef struct ShellState ShellState; | |
| 452 | +struct ShellState { | |
| 448 | 453 | sqlite3 *db; /* The database */ |
| 449 | 454 | int echoOn; /* True to echo input commands */ |
| 450 | 455 | int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ |
| 451 | 456 | int statsOn; /* True to display memory stats before each finalize */ |
| 452 | 457 | int outCount; /* Revert to stdout when reaching zero */ |
| @@ -462,13 +467,11 @@ | ||
| 462 | 467 | char newline[20]; /* Record separator in MODE_Csv */ |
| 463 | 468 | int colWidth[100]; /* Requested width of each column when in column mode*/ |
| 464 | 469 | int actualWidth[100]; /* Actual width of each column */ |
| 465 | 470 | char nullvalue[20]; /* The text to print when a NULL comes back from |
| 466 | 471 | ** the database */ |
| 467 | - struct previous_mode_data explainPrev; | |
| 468 | - /* Holds the mode information just before | |
| 469 | - ** .explain ON */ | |
| 472 | + SavedModeInfo normalMode;/* Holds the mode just before .explain ON */ | |
| 470 | 473 | char outfile[FILENAME_MAX]; /* Filename for *out */ |
| 471 | 474 | const char *zDbFilename; /* name of the database file */ |
| 472 | 475 | char *zFreeOnClose; /* Filename to free when closing */ |
| 473 | 476 | const char *zVfs; /* Name of VFS to use */ |
| 474 | 477 | sqlite3_stmt *pStmt; /* Current statement if any. */ |
| @@ -520,11 +523,11 @@ | ||
| 520 | 523 | |
| 521 | 524 | /* |
| 522 | 525 | ** A callback for the sqlite3_log() interface. |
| 523 | 526 | */ |
| 524 | 527 | static void shellLog(void *pArg, int iErrCode, const char *zMsg){ |
| 525 | - struct callback_data *p = (struct callback_data*)pArg; | |
| 528 | + ShellState *p = (ShellState*)pArg; | |
| 526 | 529 | if( p->pLog==0 ) return; |
| 527 | 530 | fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); |
| 528 | 531 | fflush(p->pLog); |
| 529 | 532 | } |
| 530 | 533 | |
| @@ -662,11 +665,11 @@ | ||
| 662 | 665 | ** Output a single term of CSV. Actually, p->separator is used for |
| 663 | 666 | ** the separator, which may or may not be a comma. p->nullvalue is |
| 664 | 667 | ** the null value. Strings are quoted if necessary. The separator |
| 665 | 668 | ** is only issued if bSep is true. |
| 666 | 669 | */ |
| 667 | -static void output_csv(struct callback_data *p, const char *z, int bSep){ | |
| 670 | +static void output_csv(ShellState *p, const char *z, int bSep){ | |
| 668 | 671 | FILE *out = p->out; |
| 669 | 672 | if( z==0 ){ |
| 670 | 673 | fprintf(out,"%s",p->nullvalue); |
| 671 | 674 | }else{ |
| 672 | 675 | int i; |
| @@ -711,11 +714,11 @@ | ||
| 711 | 714 | ** This is the callback routine that the shell |
| 712 | 715 | ** invokes for each row of a query result. |
| 713 | 716 | */ |
| 714 | 717 | static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){ |
| 715 | 718 | int i; |
| 716 | - struct callback_data *p = (struct callback_data*)pArg; | |
| 719 | + ShellState *p = (ShellState*)pArg; | |
| 717 | 720 | |
| 718 | 721 | switch( p->mode ){ |
| 719 | 722 | case MODE_Line: { |
| 720 | 723 | int w = 5; |
| 721 | 724 | if( azArg==0 ) break; |
| @@ -921,15 +924,15 @@ | ||
| 921 | 924 | /* since we don't have type info, call the shell_callback with a NULL value */ |
| 922 | 925 | return shell_callback(pArg, nArg, azArg, azCol, NULL); |
| 923 | 926 | } |
| 924 | 927 | |
| 925 | 928 | /* |
| 926 | -** Set the destination table field of the callback_data structure to | |
| 929 | +** Set the destination table field of the ShellState structure to | |
| 927 | 930 | ** the name of the table given. Escape any quote characters in the |
| 928 | 931 | ** table name. |
| 929 | 932 | */ |
| 930 | -static void set_table_name(struct callback_data *p, const char *zName){ | |
| 933 | +static void set_table_name(ShellState *p, const char *zName){ | |
| 931 | 934 | int i, n; |
| 932 | 935 | int needQuote; |
| 933 | 936 | char *z; |
| 934 | 937 | |
| 935 | 938 | if( p->zDestTable ){ |
| @@ -1015,11 +1018,11 @@ | ||
| 1015 | 1018 | ** then write the semicolon on a separate line. That way, if a |
| 1016 | 1019 | ** "--" comment occurs at the end of the statement, the comment |
| 1017 | 1020 | ** won't consume the semicolon terminator. |
| 1018 | 1021 | */ |
| 1019 | 1022 | static int run_table_dump_query( |
| 1020 | - struct callback_data *p, /* Query context */ | |
| 1023 | + ShellState *p, /* Query context */ | |
| 1021 | 1024 | const char *zSelect, /* SELECT statement to extract content */ |
| 1022 | 1025 | const char *zFirstRow /* Print before first row, if not NULL */ |
| 1023 | 1026 | ){ |
| 1024 | 1027 | sqlite3_stmt *pSelect; |
| 1025 | 1028 | int rc; |
| @@ -1078,11 +1081,11 @@ | ||
| 1078 | 1081 | /* |
| 1079 | 1082 | ** Display memory stats. |
| 1080 | 1083 | */ |
| 1081 | 1084 | static int display_stats( |
| 1082 | 1085 | sqlite3 *db, /* Database to query */ |
| 1083 | - struct callback_data *pArg, /* Pointer to struct callback_data */ | |
| 1086 | + ShellState *pArg, /* Pointer to ShellState */ | |
| 1084 | 1087 | int bReset /* True to reset the stats */ |
| 1085 | 1088 | ){ |
| 1086 | 1089 | int iCur; |
| 1087 | 1090 | int iHiwtr; |
| 1088 | 1091 | |
| @@ -1185,11 +1188,11 @@ | ||
| 1185 | 1188 | return 0; |
| 1186 | 1189 | } |
| 1187 | 1190 | |
| 1188 | 1191 | /* |
| 1189 | 1192 | ** If compiled statement pSql appears to be an EXPLAIN statement, allocate |
| 1190 | -** and populate the callback_data.aiIndent[] array with the number of | |
| 1193 | +** and populate the ShellState.aiIndent[] array with the number of | |
| 1191 | 1194 | ** spaces each opcode should be indented before it is output. |
| 1192 | 1195 | ** |
| 1193 | 1196 | ** The indenting rules are: |
| 1194 | 1197 | ** |
| 1195 | 1198 | ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent |
| @@ -1201,11 +1204,11 @@ | ||
| 1201 | 1204 | ** Yield SeekGt SeekLt RowSetRead Rewind |
| 1202 | 1205 | ** or if the P1 parameter is one instead of zero, |
| 1203 | 1206 | ** then indent all opcodes between the earlier instruction |
| 1204 | 1207 | ** and "Goto" by 2 spaces. |
| 1205 | 1208 | */ |
| 1206 | -static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ | |
| 1209 | +static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ | |
| 1207 | 1210 | const char *zSql; /* The text of the SQL statement */ |
| 1208 | 1211 | const char *z; /* Used to check if this is an EXPLAIN */ |
| 1209 | 1212 | int *abYield = 0; /* True if op is an OP_Yield */ |
| 1210 | 1213 | int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ |
| 1211 | 1214 | int iOp; /* Index of operation in p->aiIndent[] */ |
| @@ -1261,11 +1264,11 @@ | ||
| 1261 | 1264 | } |
| 1262 | 1265 | |
| 1263 | 1266 | /* |
| 1264 | 1267 | ** Free the array allocated by explain_data_prepare(). |
| 1265 | 1268 | */ |
| 1266 | -static void explain_data_delete(struct callback_data *p){ | |
| 1269 | +static void explain_data_delete(ShellState *p){ | |
| 1267 | 1270 | sqlite3_free(p->aiIndent); |
| 1268 | 1271 | p->aiIndent = 0; |
| 1269 | 1272 | p->nIndent = 0; |
| 1270 | 1273 | p->iIndent = 0; |
| 1271 | 1274 | } |
| @@ -1278,16 +1281,16 @@ | ||
| 1278 | 1281 | ** This is very similar to SQLite's built-in sqlite3_exec() |
| 1279 | 1282 | ** function except it takes a slightly different callback |
| 1280 | 1283 | ** and callback data argument. |
| 1281 | 1284 | */ |
| 1282 | 1285 | static int shell_exec( |
| 1283 | - sqlite3 *db, /* An open database */ | |
| 1284 | - const char *zSql, /* SQL to be evaluated */ | |
| 1286 | + sqlite3 *db, /* An open database */ | |
| 1287 | + const char *zSql, /* SQL to be evaluated */ | |
| 1285 | 1288 | int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ |
| 1286 | - /* (not the same as sqlite3_exec) */ | |
| 1287 | - struct callback_data *pArg, /* Pointer to struct callback_data */ | |
| 1288 | - char **pzErrMsg /* Error msg written here */ | |
| 1289 | + /* (not the same as sqlite3_exec) */ | |
| 1290 | + ShellState *pArg, /* Pointer to ShellState */ | |
| 1291 | + char **pzErrMsg /* Error msg written here */ | |
| 1289 | 1292 | ){ |
| 1290 | 1293 | sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ |
| 1291 | 1294 | int rc = SQLITE_OK; /* Return Code */ |
| 1292 | 1295 | int rc2; |
| 1293 | 1296 | const char *zLeftover; /* Tail of unprocessed SQL */ |
| @@ -1451,11 +1454,11 @@ | ||
| 1451 | 1454 | int rc; |
| 1452 | 1455 | const char *zTable; |
| 1453 | 1456 | const char *zType; |
| 1454 | 1457 | const char *zSql; |
| 1455 | 1458 | const char *zPrepStmt = 0; |
| 1456 | - struct callback_data *p = (struct callback_data *)pArg; | |
| 1459 | + ShellState *p = (ShellState *)pArg; | |
| 1457 | 1460 | |
| 1458 | 1461 | UNUSED_PARAMETER(azCol); |
| 1459 | 1462 | if( nArg!=3 ) return 1; |
| 1460 | 1463 | zTable = azArg[0]; |
| 1461 | 1464 | zType = azArg[1]; |
| @@ -1547,11 +1550,11 @@ | ||
| 1547 | 1550 | ** |
| 1548 | 1551 | ** If we get a SQLITE_CORRUPT error, rerun the query after appending |
| 1549 | 1552 | ** "ORDER BY rowid DESC" to the end. |
| 1550 | 1553 | */ |
| 1551 | 1554 | static int run_schema_dump_query( |
| 1552 | - struct callback_data *p, | |
| 1555 | + ShellState *p, | |
| 1553 | 1556 | const char *zQuery |
| 1554 | 1557 | ){ |
| 1555 | 1558 | int rc; |
| 1556 | 1559 | char *zErr = 0; |
| 1557 | 1560 | rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); |
| @@ -1647,11 +1650,11 @@ | ||
| 1647 | 1650 | ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" |
| 1648 | 1651 | " Negative values right-justify\n" |
| 1649 | 1652 | ; |
| 1650 | 1653 | |
| 1651 | 1654 | /* Forward reference */ |
| 1652 | -static int process_input(struct callback_data *p, FILE *in); | |
| 1655 | +static int process_input(ShellState *p, FILE *in); | |
| 1653 | 1656 | /* |
| 1654 | 1657 | ** Implementation of the "readfile(X)" SQL function. The entire content |
| 1655 | 1658 | ** of the file named X is read and returned as a BLOB. NULL is returned |
| 1656 | 1659 | ** if the file does not exist or is unreadable. |
| 1657 | 1660 | */ |
| @@ -1713,11 +1716,11 @@ | ||
| 1713 | 1716 | |
| 1714 | 1717 | /* |
| 1715 | 1718 | ** Make sure the database is open. If it is not, then open it. If |
| 1716 | 1719 | ** the database fails to open, print an error message and exit. |
| 1717 | 1720 | */ |
| 1718 | -static void open_db(struct callback_data *p, int keepAlive){ | |
| 1721 | +static void open_db(ShellState *p, int keepAlive){ | |
| 1719 | 1722 | if( p->db==0 ){ |
| 1720 | 1723 | sqlite3_initialize(); |
| 1721 | 1724 | sqlite3_open(p->zDbFilename, &p->db); |
| 1722 | 1725 | db = p->db; |
| 1723 | 1726 | if( db && sqlite3_errcode(db)==SQLITE_OK ){ |
| @@ -1894,11 +1897,15 @@ | ||
| 1894 | 1897 | /* |
| 1895 | 1898 | ** A routine for handling output from sqlite3_trace(). |
| 1896 | 1899 | */ |
| 1897 | 1900 | static void sql_trace_callback(void *pArg, const char *z){ |
| 1898 | 1901 | FILE *f = (FILE*)pArg; |
| 1899 | - if( f ) fprintf(f, "%s\n", z); | |
| 1902 | + if( f ){ | |
| 1903 | + int i = (int)strlen(z); | |
| 1904 | + while( i>0 && z[i-1]==';' ){ i--; } | |
| 1905 | + fprintf(f, "%.*s;\n", i, z); | |
| 1906 | + } | |
| 1900 | 1907 | } |
| 1901 | 1908 | |
| 1902 | 1909 | /* |
| 1903 | 1910 | ** A no-op routine that runs with the ".breakpoint" doc-command. This is |
| 1904 | 1911 | ** a useful spot to set a debugger breakpoint. |
| @@ -2012,11 +2019,11 @@ | ||
| 2012 | 2019 | ** Try to transfer data for table zTable. If an error is seen while |
| 2013 | 2020 | ** moving forward, try to go backwards. The backwards movement won't |
| 2014 | 2021 | ** work for WITHOUT ROWID tables. |
| 2015 | 2022 | */ |
| 2016 | 2023 | static void tryToCloneData( |
| 2017 | - struct callback_data *p, | |
| 2024 | + ShellState *p, | |
| 2018 | 2025 | sqlite3 *newDb, |
| 2019 | 2026 | const char *zTable |
| 2020 | 2027 | ){ |
| 2021 | 2028 | sqlite3_stmt *pQuery = 0; |
| 2022 | 2029 | sqlite3_stmt *pInsert = 0; |
| @@ -2125,14 +2132,14 @@ | ||
| 2125 | 2132 | ** each row, invoke xForEach() on the object defined by that row. |
| 2126 | 2133 | ** If an error is encountered while moving forward through the |
| 2127 | 2134 | ** sqlite_master table, try again moving backwards. |
| 2128 | 2135 | */ |
| 2129 | 2136 | static void tryToCloneSchema( |
| 2130 | - struct callback_data *p, | |
| 2137 | + ShellState *p, | |
| 2131 | 2138 | sqlite3 *newDb, |
| 2132 | 2139 | const char *zWhere, |
| 2133 | - void (*xForEach)(struct callback_data*,sqlite3*,const char*) | |
| 2140 | + void (*xForEach)(ShellState*,sqlite3*,const char*) | |
| 2134 | 2141 | ){ |
| 2135 | 2142 | sqlite3_stmt *pQuery = 0; |
| 2136 | 2143 | char *zQuery = 0; |
| 2137 | 2144 | int rc; |
| 2138 | 2145 | const unsigned char *zName; |
| @@ -2199,11 +2206,11 @@ | ||
| 2199 | 2206 | /* |
| 2200 | 2207 | ** Open a new database file named "zNewDb". Try to recover as much information |
| 2201 | 2208 | ** as possible out of the main database (which might be corrupt) and write it |
| 2202 | 2209 | ** into zNewDb. |
| 2203 | 2210 | */ |
| 2204 | -static void tryToClone(struct callback_data *p, const char *zNewDb){ | |
| 2211 | +static void tryToClone(ShellState *p, const char *zNewDb){ | |
| 2205 | 2212 | int rc; |
| 2206 | 2213 | sqlite3 *newDb = 0; |
| 2207 | 2214 | if( access(zNewDb,0)==0 ){ |
| 2208 | 2215 | fprintf(stderr, "File \"%s\" already exists.\n", zNewDb); |
| 2209 | 2216 | return; |
| @@ -2224,11 +2231,11 @@ | ||
| 2224 | 2231 | } |
| 2225 | 2232 | |
| 2226 | 2233 | /* |
| 2227 | 2234 | ** Change the output file back to stdout |
| 2228 | 2235 | */ |
| 2229 | -static void output_reset(struct callback_data *p){ | |
| 2236 | +static void output_reset(ShellState *p){ | |
| 2230 | 2237 | if( p->outfile[0]=='|' ){ |
| 2231 | 2238 | pclose(p->out); |
| 2232 | 2239 | }else{ |
| 2233 | 2240 | output_file_close(p->out); |
| 2234 | 2241 | } |
| @@ -2240,11 +2247,11 @@ | ||
| 2240 | 2247 | ** If an input line begins with "." then invoke this routine to |
| 2241 | 2248 | ** process that line. |
| 2242 | 2249 | ** |
| 2243 | 2250 | ** Return 1 on error, 2 to exit, and 0 otherwise. |
| 2244 | 2251 | */ |
| 2245 | -static int do_meta_command(char *zLine, struct callback_data *p){ | |
| 2252 | +static int do_meta_command(char *zLine, ShellState *p){ | |
| 2246 | 2253 | int i = 1; |
| 2247 | 2254 | int nArg = 0; |
| 2248 | 2255 | int n, c; |
| 2249 | 2256 | int rc = 0; |
| 2250 | 2257 | char *azArg[50]; |
| @@ -2358,11 +2365,11 @@ | ||
| 2358 | 2365 | rc = 1; |
| 2359 | 2366 | } |
| 2360 | 2367 | }else |
| 2361 | 2368 | |
| 2362 | 2369 | if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ |
| 2363 | - struct callback_data data; | |
| 2370 | + ShellState data; | |
| 2364 | 2371 | char *zErrMsg = 0; |
| 2365 | 2372 | open_db(p, 0); |
| 2366 | 2373 | memcpy(&data, p, sizeof(data)); |
| 2367 | 2374 | data.showHeader = 1; |
| 2368 | 2375 | data.mode = MODE_Column; |
| @@ -2456,15 +2463,15 @@ | ||
| 2456 | 2463 | }else |
| 2457 | 2464 | |
| 2458 | 2465 | if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ |
| 2459 | 2466 | int val = nArg>=2 ? booleanValue(azArg[1]) : 1; |
| 2460 | 2467 | if(val == 1) { |
| 2461 | - if(!p->explainPrev.valid) { | |
| 2462 | - p->explainPrev.valid = 1; | |
| 2463 | - p->explainPrev.mode = p->mode; | |
| 2464 | - p->explainPrev.showHeader = p->showHeader; | |
| 2465 | - memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); | |
| 2468 | + if(!p->normalMode.valid) { | |
| 2469 | + p->normalMode.valid = 1; | |
| 2470 | + p->normalMode.mode = p->mode; | |
| 2471 | + p->normalMode.showHeader = p->showHeader; | |
| 2472 | + memcpy(p->normalMode.colWidth,p->colWidth,sizeof(p->colWidth)); | |
| 2466 | 2473 | } |
| 2467 | 2474 | /* We could put this code under the !p->explainValid |
| 2468 | 2475 | ** condition so that it does not execute if we are already in |
| 2469 | 2476 | ** explain mode. However, always executing it allows us an easy |
| 2470 | 2477 | ** was to reset to explain mode in case the user previously |
| @@ -2480,20 +2487,20 @@ | ||
| 2480 | 2487 | p->colWidth[3] = 4; /* P2 */ |
| 2481 | 2488 | p->colWidth[4] = 4; /* P3 */ |
| 2482 | 2489 | p->colWidth[5] = 13; /* P4 */ |
| 2483 | 2490 | p->colWidth[6] = 2; /* P5 */ |
| 2484 | 2491 | p->colWidth[7] = 13; /* Comment */ |
| 2485 | - }else if (p->explainPrev.valid) { | |
| 2486 | - p->explainPrev.valid = 0; | |
| 2487 | - p->mode = p->explainPrev.mode; | |
| 2488 | - p->showHeader = p->explainPrev.showHeader; | |
| 2489 | - memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); | |
| 2492 | + }else if (p->normalMode.valid) { | |
| 2493 | + p->normalMode.valid = 0; | |
| 2494 | + p->mode = p->normalMode.mode; | |
| 2495 | + p->showHeader = p->normalMode.showHeader; | |
| 2496 | + memcpy(p->colWidth,p->normalMode.colWidth,sizeof(p->colWidth)); | |
| 2490 | 2497 | } |
| 2491 | 2498 | }else |
| 2492 | 2499 | |
| 2493 | 2500 | if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ |
| 2494 | - struct callback_data data; | |
| 2501 | + ShellState data; | |
| 2495 | 2502 | char *zErrMsg = 0; |
| 2496 | 2503 | int doStats = 0; |
| 2497 | 2504 | if( nArg!=1 ){ |
| 2498 | 2505 | fprintf(stderr, "Usage: .fullschema\n"); |
| 2499 | 2506 | rc = 1; |
| @@ -2506,11 +2513,11 @@ | ||
| 2506 | 2513 | rc = sqlite3_exec(p->db, |
| 2507 | 2514 | "SELECT sql FROM" |
| 2508 | 2515 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 2509 | 2516 | " FROM sqlite_master UNION ALL" |
| 2510 | 2517 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 2511 | - "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" | |
| 2518 | + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " | |
| 2512 | 2519 | "ORDER BY rowid", |
| 2513 | 2520 | callback, &data, &zErrMsg |
| 2514 | 2521 | ); |
| 2515 | 2522 | if( rc==SQLITE_OK ){ |
| 2516 | 2523 | sqlite3_stmt *pStmt; |
| @@ -2710,11 +2717,11 @@ | ||
| 2710 | 2717 | sqlite3_finalize(pStmt); |
| 2711 | 2718 | if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0); |
| 2712 | 2719 | }else |
| 2713 | 2720 | |
| 2714 | 2721 | if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){ |
| 2715 | - struct callback_data data; | |
| 2722 | + ShellState data; | |
| 2716 | 2723 | char *zErrMsg = 0; |
| 2717 | 2724 | open_db(p, 0); |
| 2718 | 2725 | memcpy(&data, p, sizeof(data)); |
| 2719 | 2726 | data.showHeader = 0; |
| 2720 | 2727 | data.mode = MODE_List; |
| @@ -3004,11 +3011,11 @@ | ||
| 3004 | 3011 | } |
| 3005 | 3012 | sqlite3_close(pSrc); |
| 3006 | 3013 | }else |
| 3007 | 3014 | |
| 3008 | 3015 | if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ |
| 3009 | - struct callback_data data; | |
| 3016 | + ShellState data; | |
| 3010 | 3017 | char *zErrMsg = 0; |
| 3011 | 3018 | open_db(p, 0); |
| 3012 | 3019 | memcpy(&data, p, sizeof(data)); |
| 3013 | 3020 | data.showHeader = 0; |
| 3014 | 3021 | data.mode = MODE_Semi; |
| @@ -3060,11 +3067,11 @@ | ||
| 3060 | 3067 | rc = sqlite3_exec(p->db, |
| 3061 | 3068 | "SELECT sql FROM " |
| 3062 | 3069 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 3063 | 3070 | " FROM sqlite_master UNION ALL" |
| 3064 | 3071 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 3065 | - "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" | |
| 3072 | + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " | |
| 3066 | 3073 | "ORDER BY rowid", |
| 3067 | 3074 | callback, &data, &zErrMsg |
| 3068 | 3075 | ); |
| 3069 | 3076 | }else{ |
| 3070 | 3077 | fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n"); |
| @@ -3146,11 +3153,11 @@ | ||
| 3146 | 3153 | rc = 1; |
| 3147 | 3154 | goto meta_command_exit; |
| 3148 | 3155 | } |
| 3149 | 3156 | fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); |
| 3150 | 3157 | fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off"); |
| 3151 | - fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); | |
| 3158 | + fprintf(p->out,"%9.9s: %s\n","explain", p->normalMode.valid ? "on" :"off"); | |
| 3152 | 3159 | fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); |
| 3153 | 3160 | fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); |
| 3154 | 3161 | fprintf(p->out,"%9.9s: ", "nullvalue"); |
| 3155 | 3162 | output_c_string(p->out, p->nullvalue); |
| 3156 | 3163 | fprintf(p->out, "\n"); |
| @@ -3538,11 +3545,11 @@ | ||
| 3538 | 3545 | ** is saved only if input is interactive. An interrupt signal will |
| 3539 | 3546 | ** cause this routine to exit immediately, unless input is interactive. |
| 3540 | 3547 | ** |
| 3541 | 3548 | ** Return the number of errors. |
| 3542 | 3549 | */ |
| 3543 | -static int process_input(struct callback_data *p, FILE *in){ | |
| 3550 | +static int process_input(ShellState *p, FILE *in){ | |
| 3544 | 3551 | char *zLine = 0; /* A single input line */ |
| 3545 | 3552 | char *zSql = 0; /* Accumulated SQL text */ |
| 3546 | 3553 | int nLine; /* Length of current line */ |
| 3547 | 3554 | int nSql = 0; /* Bytes of zSql[] used */ |
| 3548 | 3555 | int nAlloc = 0; /* Allocated zSql[] space */ |
| @@ -3717,11 +3724,11 @@ | ||
| 3717 | 3724 | ** parameter is NULL, take input from ~/.sqliterc |
| 3718 | 3725 | ** |
| 3719 | 3726 | ** Returns the number of errors. |
| 3720 | 3727 | */ |
| 3721 | 3728 | static int process_sqliterc( |
| 3722 | - struct callback_data *p, /* Configuration data */ | |
| 3729 | + ShellState *p, /* Configuration data */ | |
| 3723 | 3730 | const char *sqliterc_override /* Name of config file. NULL to use default */ |
| 3724 | 3731 | ){ |
| 3725 | 3732 | char *home_dir = NULL; |
| 3726 | 3733 | const char *sqliterc = sqliterc_override; |
| 3727 | 3734 | char *zBuf = 0; |
| @@ -3800,11 +3807,11 @@ | ||
| 3800 | 3807 | } |
| 3801 | 3808 | |
| 3802 | 3809 | /* |
| 3803 | 3810 | ** Initialize the state information in data |
| 3804 | 3811 | */ |
| 3805 | -static void main_init(struct callback_data *data) { | |
| 3812 | +static void main_init(ShellState *data) { | |
| 3806 | 3813 | memset(data, 0, sizeof(*data)); |
| 3807 | 3814 | data->mode = MODE_List; |
| 3808 | 3815 | memcpy(data->separator,"|", 2); |
| 3809 | 3816 | memcpy(data->newline,"\r\n", 3); |
| 3810 | 3817 | data->showHeader = 0; |
| @@ -3848,11 +3855,11 @@ | ||
| 3848 | 3855 | return argv[i]; |
| 3849 | 3856 | } |
| 3850 | 3857 | |
| 3851 | 3858 | int main(int argc, char **argv){ |
| 3852 | 3859 | char *zErrMsg = 0; |
| 3853 | - struct callback_data data; | |
| 3860 | + ShellState data; | |
| 3854 | 3861 | const char *zInitFile = 0; |
| 3855 | 3862 | char *zFirstCmd = 0; |
| 3856 | 3863 | int i; |
| 3857 | 3864 | int rc = 0; |
| 3858 | 3865 | int warnInmemoryDb = 0; |
| 3859 | 3866 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -430,23 +430,28 @@ | |
| 430 | #endif |
| 431 | } |
| 432 | return zResult; |
| 433 | } |
| 434 | |
| 435 | struct previous_mode_data { |
| 436 | int valid; /* Is there legit data in here? */ |
| 437 | int mode; |
| 438 | int showHeader; |
| 439 | int colWidth[100]; |
| 440 | }; |
| 441 | |
| 442 | /* |
| 443 | ** An pointer to an instance of this structure is passed from |
| 444 | ** the main program to the callback. This is used to communicate |
| 445 | ** state and mode information. |
| 446 | */ |
| 447 | struct callback_data { |
| 448 | sqlite3 *db; /* The database */ |
| 449 | int echoOn; /* True to echo input commands */ |
| 450 | int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ |
| 451 | int statsOn; /* True to display memory stats before each finalize */ |
| 452 | int outCount; /* Revert to stdout when reaching zero */ |
| @@ -462,13 +467,11 @@ | |
| 462 | char newline[20]; /* Record separator in MODE_Csv */ |
| 463 | int colWidth[100]; /* Requested width of each column when in column mode*/ |
| 464 | int actualWidth[100]; /* Actual width of each column */ |
| 465 | char nullvalue[20]; /* The text to print when a NULL comes back from |
| 466 | ** the database */ |
| 467 | struct previous_mode_data explainPrev; |
| 468 | /* Holds the mode information just before |
| 469 | ** .explain ON */ |
| 470 | char outfile[FILENAME_MAX]; /* Filename for *out */ |
| 471 | const char *zDbFilename; /* name of the database file */ |
| 472 | char *zFreeOnClose; /* Filename to free when closing */ |
| 473 | const char *zVfs; /* Name of VFS to use */ |
| 474 | sqlite3_stmt *pStmt; /* Current statement if any. */ |
| @@ -520,11 +523,11 @@ | |
| 520 | |
| 521 | /* |
| 522 | ** A callback for the sqlite3_log() interface. |
| 523 | */ |
| 524 | static void shellLog(void *pArg, int iErrCode, const char *zMsg){ |
| 525 | struct callback_data *p = (struct callback_data*)pArg; |
| 526 | if( p->pLog==0 ) return; |
| 527 | fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); |
| 528 | fflush(p->pLog); |
| 529 | } |
| 530 | |
| @@ -662,11 +665,11 @@ | |
| 662 | ** Output a single term of CSV. Actually, p->separator is used for |
| 663 | ** the separator, which may or may not be a comma. p->nullvalue is |
| 664 | ** the null value. Strings are quoted if necessary. The separator |
| 665 | ** is only issued if bSep is true. |
| 666 | */ |
| 667 | static void output_csv(struct callback_data *p, const char *z, int bSep){ |
| 668 | FILE *out = p->out; |
| 669 | if( z==0 ){ |
| 670 | fprintf(out,"%s",p->nullvalue); |
| 671 | }else{ |
| 672 | int i; |
| @@ -711,11 +714,11 @@ | |
| 711 | ** This is the callback routine that the shell |
| 712 | ** invokes for each row of a query result. |
| 713 | */ |
| 714 | static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){ |
| 715 | int i; |
| 716 | struct callback_data *p = (struct callback_data*)pArg; |
| 717 | |
| 718 | switch( p->mode ){ |
| 719 | case MODE_Line: { |
| 720 | int w = 5; |
| 721 | if( azArg==0 ) break; |
| @@ -921,15 +924,15 @@ | |
| 921 | /* since we don't have type info, call the shell_callback with a NULL value */ |
| 922 | return shell_callback(pArg, nArg, azArg, azCol, NULL); |
| 923 | } |
| 924 | |
| 925 | /* |
| 926 | ** Set the destination table field of the callback_data structure to |
| 927 | ** the name of the table given. Escape any quote characters in the |
| 928 | ** table name. |
| 929 | */ |
| 930 | static void set_table_name(struct callback_data *p, const char *zName){ |
| 931 | int i, n; |
| 932 | int needQuote; |
| 933 | char *z; |
| 934 | |
| 935 | if( p->zDestTable ){ |
| @@ -1015,11 +1018,11 @@ | |
| 1015 | ** then write the semicolon on a separate line. That way, if a |
| 1016 | ** "--" comment occurs at the end of the statement, the comment |
| 1017 | ** won't consume the semicolon terminator. |
| 1018 | */ |
| 1019 | static int run_table_dump_query( |
| 1020 | struct callback_data *p, /* Query context */ |
| 1021 | const char *zSelect, /* SELECT statement to extract content */ |
| 1022 | const char *zFirstRow /* Print before first row, if not NULL */ |
| 1023 | ){ |
| 1024 | sqlite3_stmt *pSelect; |
| 1025 | int rc; |
| @@ -1078,11 +1081,11 @@ | |
| 1078 | /* |
| 1079 | ** Display memory stats. |
| 1080 | */ |
| 1081 | static int display_stats( |
| 1082 | sqlite3 *db, /* Database to query */ |
| 1083 | struct callback_data *pArg, /* Pointer to struct callback_data */ |
| 1084 | int bReset /* True to reset the stats */ |
| 1085 | ){ |
| 1086 | int iCur; |
| 1087 | int iHiwtr; |
| 1088 | |
| @@ -1185,11 +1188,11 @@ | |
| 1185 | return 0; |
| 1186 | } |
| 1187 | |
| 1188 | /* |
| 1189 | ** If compiled statement pSql appears to be an EXPLAIN statement, allocate |
| 1190 | ** and populate the callback_data.aiIndent[] array with the number of |
| 1191 | ** spaces each opcode should be indented before it is output. |
| 1192 | ** |
| 1193 | ** The indenting rules are: |
| 1194 | ** |
| 1195 | ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent |
| @@ -1201,11 +1204,11 @@ | |
| 1201 | ** Yield SeekGt SeekLt RowSetRead Rewind |
| 1202 | ** or if the P1 parameter is one instead of zero, |
| 1203 | ** then indent all opcodes between the earlier instruction |
| 1204 | ** and "Goto" by 2 spaces. |
| 1205 | */ |
| 1206 | static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ |
| 1207 | const char *zSql; /* The text of the SQL statement */ |
| 1208 | const char *z; /* Used to check if this is an EXPLAIN */ |
| 1209 | int *abYield = 0; /* True if op is an OP_Yield */ |
| 1210 | int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ |
| 1211 | int iOp; /* Index of operation in p->aiIndent[] */ |
| @@ -1261,11 +1264,11 @@ | |
| 1261 | } |
| 1262 | |
| 1263 | /* |
| 1264 | ** Free the array allocated by explain_data_prepare(). |
| 1265 | */ |
| 1266 | static void explain_data_delete(struct callback_data *p){ |
| 1267 | sqlite3_free(p->aiIndent); |
| 1268 | p->aiIndent = 0; |
| 1269 | p->nIndent = 0; |
| 1270 | p->iIndent = 0; |
| 1271 | } |
| @@ -1278,16 +1281,16 @@ | |
| 1278 | ** This is very similar to SQLite's built-in sqlite3_exec() |
| 1279 | ** function except it takes a slightly different callback |
| 1280 | ** and callback data argument. |
| 1281 | */ |
| 1282 | static int shell_exec( |
| 1283 | sqlite3 *db, /* An open database */ |
| 1284 | const char *zSql, /* SQL to be evaluated */ |
| 1285 | int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ |
| 1286 | /* (not the same as sqlite3_exec) */ |
| 1287 | struct callback_data *pArg, /* Pointer to struct callback_data */ |
| 1288 | char **pzErrMsg /* Error msg written here */ |
| 1289 | ){ |
| 1290 | sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ |
| 1291 | int rc = SQLITE_OK; /* Return Code */ |
| 1292 | int rc2; |
| 1293 | const char *zLeftover; /* Tail of unprocessed SQL */ |
| @@ -1451,11 +1454,11 @@ | |
| 1451 | int rc; |
| 1452 | const char *zTable; |
| 1453 | const char *zType; |
| 1454 | const char *zSql; |
| 1455 | const char *zPrepStmt = 0; |
| 1456 | struct callback_data *p = (struct callback_data *)pArg; |
| 1457 | |
| 1458 | UNUSED_PARAMETER(azCol); |
| 1459 | if( nArg!=3 ) return 1; |
| 1460 | zTable = azArg[0]; |
| 1461 | zType = azArg[1]; |
| @@ -1547,11 +1550,11 @@ | |
| 1547 | ** |
| 1548 | ** If we get a SQLITE_CORRUPT error, rerun the query after appending |
| 1549 | ** "ORDER BY rowid DESC" to the end. |
| 1550 | */ |
| 1551 | static int run_schema_dump_query( |
| 1552 | struct callback_data *p, |
| 1553 | const char *zQuery |
| 1554 | ){ |
| 1555 | int rc; |
| 1556 | char *zErr = 0; |
| 1557 | rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); |
| @@ -1647,11 +1650,11 @@ | |
| 1647 | ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" |
| 1648 | " Negative values right-justify\n" |
| 1649 | ; |
| 1650 | |
| 1651 | /* Forward reference */ |
| 1652 | static int process_input(struct callback_data *p, FILE *in); |
| 1653 | /* |
| 1654 | ** Implementation of the "readfile(X)" SQL function. The entire content |
| 1655 | ** of the file named X is read and returned as a BLOB. NULL is returned |
| 1656 | ** if the file does not exist or is unreadable. |
| 1657 | */ |
| @@ -1713,11 +1716,11 @@ | |
| 1713 | |
| 1714 | /* |
| 1715 | ** Make sure the database is open. If it is not, then open it. If |
| 1716 | ** the database fails to open, print an error message and exit. |
| 1717 | */ |
| 1718 | static void open_db(struct callback_data *p, int keepAlive){ |
| 1719 | if( p->db==0 ){ |
| 1720 | sqlite3_initialize(); |
| 1721 | sqlite3_open(p->zDbFilename, &p->db); |
| 1722 | db = p->db; |
| 1723 | if( db && sqlite3_errcode(db)==SQLITE_OK ){ |
| @@ -1894,11 +1897,15 @@ | |
| 1894 | /* |
| 1895 | ** A routine for handling output from sqlite3_trace(). |
| 1896 | */ |
| 1897 | static void sql_trace_callback(void *pArg, const char *z){ |
| 1898 | FILE *f = (FILE*)pArg; |
| 1899 | if( f ) fprintf(f, "%s\n", z); |
| 1900 | } |
| 1901 | |
| 1902 | /* |
| 1903 | ** A no-op routine that runs with the ".breakpoint" doc-command. This is |
| 1904 | ** a useful spot to set a debugger breakpoint. |
| @@ -2012,11 +2019,11 @@ | |
| 2012 | ** Try to transfer data for table zTable. If an error is seen while |
| 2013 | ** moving forward, try to go backwards. The backwards movement won't |
| 2014 | ** work for WITHOUT ROWID tables. |
| 2015 | */ |
| 2016 | static void tryToCloneData( |
| 2017 | struct callback_data *p, |
| 2018 | sqlite3 *newDb, |
| 2019 | const char *zTable |
| 2020 | ){ |
| 2021 | sqlite3_stmt *pQuery = 0; |
| 2022 | sqlite3_stmt *pInsert = 0; |
| @@ -2125,14 +2132,14 @@ | |
| 2125 | ** each row, invoke xForEach() on the object defined by that row. |
| 2126 | ** If an error is encountered while moving forward through the |
| 2127 | ** sqlite_master table, try again moving backwards. |
| 2128 | */ |
| 2129 | static void tryToCloneSchema( |
| 2130 | struct callback_data *p, |
| 2131 | sqlite3 *newDb, |
| 2132 | const char *zWhere, |
| 2133 | void (*xForEach)(struct callback_data*,sqlite3*,const char*) |
| 2134 | ){ |
| 2135 | sqlite3_stmt *pQuery = 0; |
| 2136 | char *zQuery = 0; |
| 2137 | int rc; |
| 2138 | const unsigned char *zName; |
| @@ -2199,11 +2206,11 @@ | |
| 2199 | /* |
| 2200 | ** Open a new database file named "zNewDb". Try to recover as much information |
| 2201 | ** as possible out of the main database (which might be corrupt) and write it |
| 2202 | ** into zNewDb. |
| 2203 | */ |
| 2204 | static void tryToClone(struct callback_data *p, const char *zNewDb){ |
| 2205 | int rc; |
| 2206 | sqlite3 *newDb = 0; |
| 2207 | if( access(zNewDb,0)==0 ){ |
| 2208 | fprintf(stderr, "File \"%s\" already exists.\n", zNewDb); |
| 2209 | return; |
| @@ -2224,11 +2231,11 @@ | |
| 2224 | } |
| 2225 | |
| 2226 | /* |
| 2227 | ** Change the output file back to stdout |
| 2228 | */ |
| 2229 | static void output_reset(struct callback_data *p){ |
| 2230 | if( p->outfile[0]=='|' ){ |
| 2231 | pclose(p->out); |
| 2232 | }else{ |
| 2233 | output_file_close(p->out); |
| 2234 | } |
| @@ -2240,11 +2247,11 @@ | |
| 2240 | ** If an input line begins with "." then invoke this routine to |
| 2241 | ** process that line. |
| 2242 | ** |
| 2243 | ** Return 1 on error, 2 to exit, and 0 otherwise. |
| 2244 | */ |
| 2245 | static int do_meta_command(char *zLine, struct callback_data *p){ |
| 2246 | int i = 1; |
| 2247 | int nArg = 0; |
| 2248 | int n, c; |
| 2249 | int rc = 0; |
| 2250 | char *azArg[50]; |
| @@ -2358,11 +2365,11 @@ | |
| 2358 | rc = 1; |
| 2359 | } |
| 2360 | }else |
| 2361 | |
| 2362 | if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ |
| 2363 | struct callback_data data; |
| 2364 | char *zErrMsg = 0; |
| 2365 | open_db(p, 0); |
| 2366 | memcpy(&data, p, sizeof(data)); |
| 2367 | data.showHeader = 1; |
| 2368 | data.mode = MODE_Column; |
| @@ -2456,15 +2463,15 @@ | |
| 2456 | }else |
| 2457 | |
| 2458 | if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ |
| 2459 | int val = nArg>=2 ? booleanValue(azArg[1]) : 1; |
| 2460 | if(val == 1) { |
| 2461 | if(!p->explainPrev.valid) { |
| 2462 | p->explainPrev.valid = 1; |
| 2463 | p->explainPrev.mode = p->mode; |
| 2464 | p->explainPrev.showHeader = p->showHeader; |
| 2465 | memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); |
| 2466 | } |
| 2467 | /* We could put this code under the !p->explainValid |
| 2468 | ** condition so that it does not execute if we are already in |
| 2469 | ** explain mode. However, always executing it allows us an easy |
| 2470 | ** was to reset to explain mode in case the user previously |
| @@ -2480,20 +2487,20 @@ | |
| 2480 | p->colWidth[3] = 4; /* P2 */ |
| 2481 | p->colWidth[4] = 4; /* P3 */ |
| 2482 | p->colWidth[5] = 13; /* P4 */ |
| 2483 | p->colWidth[6] = 2; /* P5 */ |
| 2484 | p->colWidth[7] = 13; /* Comment */ |
| 2485 | }else if (p->explainPrev.valid) { |
| 2486 | p->explainPrev.valid = 0; |
| 2487 | p->mode = p->explainPrev.mode; |
| 2488 | p->showHeader = p->explainPrev.showHeader; |
| 2489 | memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); |
| 2490 | } |
| 2491 | }else |
| 2492 | |
| 2493 | if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ |
| 2494 | struct callback_data data; |
| 2495 | char *zErrMsg = 0; |
| 2496 | int doStats = 0; |
| 2497 | if( nArg!=1 ){ |
| 2498 | fprintf(stderr, "Usage: .fullschema\n"); |
| 2499 | rc = 1; |
| @@ -2506,11 +2513,11 @@ | |
| 2506 | rc = sqlite3_exec(p->db, |
| 2507 | "SELECT sql FROM" |
| 2508 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 2509 | " FROM sqlite_master UNION ALL" |
| 2510 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 2511 | "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" |
| 2512 | "ORDER BY rowid", |
| 2513 | callback, &data, &zErrMsg |
| 2514 | ); |
| 2515 | if( rc==SQLITE_OK ){ |
| 2516 | sqlite3_stmt *pStmt; |
| @@ -2710,11 +2717,11 @@ | |
| 2710 | sqlite3_finalize(pStmt); |
| 2711 | if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0); |
| 2712 | }else |
| 2713 | |
| 2714 | if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){ |
| 2715 | struct callback_data data; |
| 2716 | char *zErrMsg = 0; |
| 2717 | open_db(p, 0); |
| 2718 | memcpy(&data, p, sizeof(data)); |
| 2719 | data.showHeader = 0; |
| 2720 | data.mode = MODE_List; |
| @@ -3004,11 +3011,11 @@ | |
| 3004 | } |
| 3005 | sqlite3_close(pSrc); |
| 3006 | }else |
| 3007 | |
| 3008 | if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ |
| 3009 | struct callback_data data; |
| 3010 | char *zErrMsg = 0; |
| 3011 | open_db(p, 0); |
| 3012 | memcpy(&data, p, sizeof(data)); |
| 3013 | data.showHeader = 0; |
| 3014 | data.mode = MODE_Semi; |
| @@ -3060,11 +3067,11 @@ | |
| 3060 | rc = sqlite3_exec(p->db, |
| 3061 | "SELECT sql FROM " |
| 3062 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 3063 | " FROM sqlite_master UNION ALL" |
| 3064 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 3065 | "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" |
| 3066 | "ORDER BY rowid", |
| 3067 | callback, &data, &zErrMsg |
| 3068 | ); |
| 3069 | }else{ |
| 3070 | fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n"); |
| @@ -3146,11 +3153,11 @@ | |
| 3146 | rc = 1; |
| 3147 | goto meta_command_exit; |
| 3148 | } |
| 3149 | fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); |
| 3150 | fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off"); |
| 3151 | fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); |
| 3152 | fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); |
| 3153 | fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); |
| 3154 | fprintf(p->out,"%9.9s: ", "nullvalue"); |
| 3155 | output_c_string(p->out, p->nullvalue); |
| 3156 | fprintf(p->out, "\n"); |
| @@ -3538,11 +3545,11 @@ | |
| 3538 | ** is saved only if input is interactive. An interrupt signal will |
| 3539 | ** cause this routine to exit immediately, unless input is interactive. |
| 3540 | ** |
| 3541 | ** Return the number of errors. |
| 3542 | */ |
| 3543 | static int process_input(struct callback_data *p, FILE *in){ |
| 3544 | char *zLine = 0; /* A single input line */ |
| 3545 | char *zSql = 0; /* Accumulated SQL text */ |
| 3546 | int nLine; /* Length of current line */ |
| 3547 | int nSql = 0; /* Bytes of zSql[] used */ |
| 3548 | int nAlloc = 0; /* Allocated zSql[] space */ |
| @@ -3717,11 +3724,11 @@ | |
| 3717 | ** parameter is NULL, take input from ~/.sqliterc |
| 3718 | ** |
| 3719 | ** Returns the number of errors. |
| 3720 | */ |
| 3721 | static int process_sqliterc( |
| 3722 | struct callback_data *p, /* Configuration data */ |
| 3723 | const char *sqliterc_override /* Name of config file. NULL to use default */ |
| 3724 | ){ |
| 3725 | char *home_dir = NULL; |
| 3726 | const char *sqliterc = sqliterc_override; |
| 3727 | char *zBuf = 0; |
| @@ -3800,11 +3807,11 @@ | |
| 3800 | } |
| 3801 | |
| 3802 | /* |
| 3803 | ** Initialize the state information in data |
| 3804 | */ |
| 3805 | static void main_init(struct callback_data *data) { |
| 3806 | memset(data, 0, sizeof(*data)); |
| 3807 | data->mode = MODE_List; |
| 3808 | memcpy(data->separator,"|", 2); |
| 3809 | memcpy(data->newline,"\r\n", 3); |
| 3810 | data->showHeader = 0; |
| @@ -3848,11 +3855,11 @@ | |
| 3848 | return argv[i]; |
| 3849 | } |
| 3850 | |
| 3851 | int main(int argc, char **argv){ |
| 3852 | char *zErrMsg = 0; |
| 3853 | struct callback_data data; |
| 3854 | const char *zInitFile = 0; |
| 3855 | char *zFirstCmd = 0; |
| 3856 | int i; |
| 3857 | int rc = 0; |
| 3858 | int warnInmemoryDb = 0; |
| 3859 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -430,23 +430,28 @@ | |
| 430 | #endif |
| 431 | } |
| 432 | return zResult; |
| 433 | } |
| 434 | |
| 435 | /* |
| 436 | ** Shell output mode information from before ".explain on", |
| 437 | ** saved so that it can be restored by ".explain off" |
| 438 | */ |
| 439 | typedef struct SavedModeInfo SavedModeInfo; |
| 440 | struct SavedModeInfo { |
| 441 | int valid; /* Is there legit data in here? */ |
| 442 | int mode; /* Mode prior to ".explain on" */ |
| 443 | int showHeader; /* The ".header" setting prior to ".explain on" */ |
| 444 | int colWidth[100]; /* Column widths prior to ".explain on" */ |
| 445 | }; |
| 446 | |
| 447 | /* |
| 448 | ** State information about the database connection is contained in an |
| 449 | ** instance of the following structure. |
| 450 | */ |
| 451 | typedef struct ShellState ShellState; |
| 452 | struct ShellState { |
| 453 | sqlite3 *db; /* The database */ |
| 454 | int echoOn; /* True to echo input commands */ |
| 455 | int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ |
| 456 | int statsOn; /* True to display memory stats before each finalize */ |
| 457 | int outCount; /* Revert to stdout when reaching zero */ |
| @@ -462,13 +467,11 @@ | |
| 467 | char newline[20]; /* Record separator in MODE_Csv */ |
| 468 | int colWidth[100]; /* Requested width of each column when in column mode*/ |
| 469 | int actualWidth[100]; /* Actual width of each column */ |
| 470 | char nullvalue[20]; /* The text to print when a NULL comes back from |
| 471 | ** the database */ |
| 472 | SavedModeInfo normalMode;/* Holds the mode just before .explain ON */ |
| 473 | char outfile[FILENAME_MAX]; /* Filename for *out */ |
| 474 | const char *zDbFilename; /* name of the database file */ |
| 475 | char *zFreeOnClose; /* Filename to free when closing */ |
| 476 | const char *zVfs; /* Name of VFS to use */ |
| 477 | sqlite3_stmt *pStmt; /* Current statement if any. */ |
| @@ -520,11 +523,11 @@ | |
| 523 | |
| 524 | /* |
| 525 | ** A callback for the sqlite3_log() interface. |
| 526 | */ |
| 527 | static void shellLog(void *pArg, int iErrCode, const char *zMsg){ |
| 528 | ShellState *p = (ShellState*)pArg; |
| 529 | if( p->pLog==0 ) return; |
| 530 | fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); |
| 531 | fflush(p->pLog); |
| 532 | } |
| 533 | |
| @@ -662,11 +665,11 @@ | |
| 665 | ** Output a single term of CSV. Actually, p->separator is used for |
| 666 | ** the separator, which may or may not be a comma. p->nullvalue is |
| 667 | ** the null value. Strings are quoted if necessary. The separator |
| 668 | ** is only issued if bSep is true. |
| 669 | */ |
| 670 | static void output_csv(ShellState *p, const char *z, int bSep){ |
| 671 | FILE *out = p->out; |
| 672 | if( z==0 ){ |
| 673 | fprintf(out,"%s",p->nullvalue); |
| 674 | }else{ |
| 675 | int i; |
| @@ -711,11 +714,11 @@ | |
| 714 | ** This is the callback routine that the shell |
| 715 | ** invokes for each row of a query result. |
| 716 | */ |
| 717 | static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){ |
| 718 | int i; |
| 719 | ShellState *p = (ShellState*)pArg; |
| 720 | |
| 721 | switch( p->mode ){ |
| 722 | case MODE_Line: { |
| 723 | int w = 5; |
| 724 | if( azArg==0 ) break; |
| @@ -921,15 +924,15 @@ | |
| 924 | /* since we don't have type info, call the shell_callback with a NULL value */ |
| 925 | return shell_callback(pArg, nArg, azArg, azCol, NULL); |
| 926 | } |
| 927 | |
| 928 | /* |
| 929 | ** Set the destination table field of the ShellState structure to |
| 930 | ** the name of the table given. Escape any quote characters in the |
| 931 | ** table name. |
| 932 | */ |
| 933 | static void set_table_name(ShellState *p, const char *zName){ |
| 934 | int i, n; |
| 935 | int needQuote; |
| 936 | char *z; |
| 937 | |
| 938 | if( p->zDestTable ){ |
| @@ -1015,11 +1018,11 @@ | |
| 1018 | ** then write the semicolon on a separate line. That way, if a |
| 1019 | ** "--" comment occurs at the end of the statement, the comment |
| 1020 | ** won't consume the semicolon terminator. |
| 1021 | */ |
| 1022 | static int run_table_dump_query( |
| 1023 | ShellState *p, /* Query context */ |
| 1024 | const char *zSelect, /* SELECT statement to extract content */ |
| 1025 | const char *zFirstRow /* Print before first row, if not NULL */ |
| 1026 | ){ |
| 1027 | sqlite3_stmt *pSelect; |
| 1028 | int rc; |
| @@ -1078,11 +1081,11 @@ | |
| 1081 | /* |
| 1082 | ** Display memory stats. |
| 1083 | */ |
| 1084 | static int display_stats( |
| 1085 | sqlite3 *db, /* Database to query */ |
| 1086 | ShellState *pArg, /* Pointer to ShellState */ |
| 1087 | int bReset /* True to reset the stats */ |
| 1088 | ){ |
| 1089 | int iCur; |
| 1090 | int iHiwtr; |
| 1091 | |
| @@ -1185,11 +1188,11 @@ | |
| 1188 | return 0; |
| 1189 | } |
| 1190 | |
| 1191 | /* |
| 1192 | ** If compiled statement pSql appears to be an EXPLAIN statement, allocate |
| 1193 | ** and populate the ShellState.aiIndent[] array with the number of |
| 1194 | ** spaces each opcode should be indented before it is output. |
| 1195 | ** |
| 1196 | ** The indenting rules are: |
| 1197 | ** |
| 1198 | ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent |
| @@ -1201,11 +1204,11 @@ | |
| 1204 | ** Yield SeekGt SeekLt RowSetRead Rewind |
| 1205 | ** or if the P1 parameter is one instead of zero, |
| 1206 | ** then indent all opcodes between the earlier instruction |
| 1207 | ** and "Goto" by 2 spaces. |
| 1208 | */ |
| 1209 | static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ |
| 1210 | const char *zSql; /* The text of the SQL statement */ |
| 1211 | const char *z; /* Used to check if this is an EXPLAIN */ |
| 1212 | int *abYield = 0; /* True if op is an OP_Yield */ |
| 1213 | int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ |
| 1214 | int iOp; /* Index of operation in p->aiIndent[] */ |
| @@ -1261,11 +1264,11 @@ | |
| 1264 | } |
| 1265 | |
| 1266 | /* |
| 1267 | ** Free the array allocated by explain_data_prepare(). |
| 1268 | */ |
| 1269 | static void explain_data_delete(ShellState *p){ |
| 1270 | sqlite3_free(p->aiIndent); |
| 1271 | p->aiIndent = 0; |
| 1272 | p->nIndent = 0; |
| 1273 | p->iIndent = 0; |
| 1274 | } |
| @@ -1278,16 +1281,16 @@ | |
| 1281 | ** This is very similar to SQLite's built-in sqlite3_exec() |
| 1282 | ** function except it takes a slightly different callback |
| 1283 | ** and callback data argument. |
| 1284 | */ |
| 1285 | static int shell_exec( |
| 1286 | sqlite3 *db, /* An open database */ |
| 1287 | const char *zSql, /* SQL to be evaluated */ |
| 1288 | int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ |
| 1289 | /* (not the same as sqlite3_exec) */ |
| 1290 | ShellState *pArg, /* Pointer to ShellState */ |
| 1291 | char **pzErrMsg /* Error msg written here */ |
| 1292 | ){ |
| 1293 | sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ |
| 1294 | int rc = SQLITE_OK; /* Return Code */ |
| 1295 | int rc2; |
| 1296 | const char *zLeftover; /* Tail of unprocessed SQL */ |
| @@ -1451,11 +1454,11 @@ | |
| 1454 | int rc; |
| 1455 | const char *zTable; |
| 1456 | const char *zType; |
| 1457 | const char *zSql; |
| 1458 | const char *zPrepStmt = 0; |
| 1459 | ShellState *p = (ShellState *)pArg; |
| 1460 | |
| 1461 | UNUSED_PARAMETER(azCol); |
| 1462 | if( nArg!=3 ) return 1; |
| 1463 | zTable = azArg[0]; |
| 1464 | zType = azArg[1]; |
| @@ -1547,11 +1550,11 @@ | |
| 1550 | ** |
| 1551 | ** If we get a SQLITE_CORRUPT error, rerun the query after appending |
| 1552 | ** "ORDER BY rowid DESC" to the end. |
| 1553 | */ |
| 1554 | static int run_schema_dump_query( |
| 1555 | ShellState *p, |
| 1556 | const char *zQuery |
| 1557 | ){ |
| 1558 | int rc; |
| 1559 | char *zErr = 0; |
| 1560 | rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); |
| @@ -1647,11 +1650,11 @@ | |
| 1650 | ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" |
| 1651 | " Negative values right-justify\n" |
| 1652 | ; |
| 1653 | |
| 1654 | /* Forward reference */ |
| 1655 | static int process_input(ShellState *p, FILE *in); |
| 1656 | /* |
| 1657 | ** Implementation of the "readfile(X)" SQL function. The entire content |
| 1658 | ** of the file named X is read and returned as a BLOB. NULL is returned |
| 1659 | ** if the file does not exist or is unreadable. |
| 1660 | */ |
| @@ -1713,11 +1716,11 @@ | |
| 1716 | |
| 1717 | /* |
| 1718 | ** Make sure the database is open. If it is not, then open it. If |
| 1719 | ** the database fails to open, print an error message and exit. |
| 1720 | */ |
| 1721 | static void open_db(ShellState *p, int keepAlive){ |
| 1722 | if( p->db==0 ){ |
| 1723 | sqlite3_initialize(); |
| 1724 | sqlite3_open(p->zDbFilename, &p->db); |
| 1725 | db = p->db; |
| 1726 | if( db && sqlite3_errcode(db)==SQLITE_OK ){ |
| @@ -1894,11 +1897,15 @@ | |
| 1897 | /* |
| 1898 | ** A routine for handling output from sqlite3_trace(). |
| 1899 | */ |
| 1900 | static void sql_trace_callback(void *pArg, const char *z){ |
| 1901 | FILE *f = (FILE*)pArg; |
| 1902 | if( f ){ |
| 1903 | int i = (int)strlen(z); |
| 1904 | while( i>0 && z[i-1]==';' ){ i--; } |
| 1905 | fprintf(f, "%.*s;\n", i, z); |
| 1906 | } |
| 1907 | } |
| 1908 | |
| 1909 | /* |
| 1910 | ** A no-op routine that runs with the ".breakpoint" doc-command. This is |
| 1911 | ** a useful spot to set a debugger breakpoint. |
| @@ -2012,11 +2019,11 @@ | |
| 2019 | ** Try to transfer data for table zTable. If an error is seen while |
| 2020 | ** moving forward, try to go backwards. The backwards movement won't |
| 2021 | ** work for WITHOUT ROWID tables. |
| 2022 | */ |
| 2023 | static void tryToCloneData( |
| 2024 | ShellState *p, |
| 2025 | sqlite3 *newDb, |
| 2026 | const char *zTable |
| 2027 | ){ |
| 2028 | sqlite3_stmt *pQuery = 0; |
| 2029 | sqlite3_stmt *pInsert = 0; |
| @@ -2125,14 +2132,14 @@ | |
| 2132 | ** each row, invoke xForEach() on the object defined by that row. |
| 2133 | ** If an error is encountered while moving forward through the |
| 2134 | ** sqlite_master table, try again moving backwards. |
| 2135 | */ |
| 2136 | static void tryToCloneSchema( |
| 2137 | ShellState *p, |
| 2138 | sqlite3 *newDb, |
| 2139 | const char *zWhere, |
| 2140 | void (*xForEach)(ShellState*,sqlite3*,const char*) |
| 2141 | ){ |
| 2142 | sqlite3_stmt *pQuery = 0; |
| 2143 | char *zQuery = 0; |
| 2144 | int rc; |
| 2145 | const unsigned char *zName; |
| @@ -2199,11 +2206,11 @@ | |
| 2206 | /* |
| 2207 | ** Open a new database file named "zNewDb". Try to recover as much information |
| 2208 | ** as possible out of the main database (which might be corrupt) and write it |
| 2209 | ** into zNewDb. |
| 2210 | */ |
| 2211 | static void tryToClone(ShellState *p, const char *zNewDb){ |
| 2212 | int rc; |
| 2213 | sqlite3 *newDb = 0; |
| 2214 | if( access(zNewDb,0)==0 ){ |
| 2215 | fprintf(stderr, "File \"%s\" already exists.\n", zNewDb); |
| 2216 | return; |
| @@ -2224,11 +2231,11 @@ | |
| 2231 | } |
| 2232 | |
| 2233 | /* |
| 2234 | ** Change the output file back to stdout |
| 2235 | */ |
| 2236 | static void output_reset(ShellState *p){ |
| 2237 | if( p->outfile[0]=='|' ){ |
| 2238 | pclose(p->out); |
| 2239 | }else{ |
| 2240 | output_file_close(p->out); |
| 2241 | } |
| @@ -2240,11 +2247,11 @@ | |
| 2247 | ** If an input line begins with "." then invoke this routine to |
| 2248 | ** process that line. |
| 2249 | ** |
| 2250 | ** Return 1 on error, 2 to exit, and 0 otherwise. |
| 2251 | */ |
| 2252 | static int do_meta_command(char *zLine, ShellState *p){ |
| 2253 | int i = 1; |
| 2254 | int nArg = 0; |
| 2255 | int n, c; |
| 2256 | int rc = 0; |
| 2257 | char *azArg[50]; |
| @@ -2358,11 +2365,11 @@ | |
| 2365 | rc = 1; |
| 2366 | } |
| 2367 | }else |
| 2368 | |
| 2369 | if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ |
| 2370 | ShellState data; |
| 2371 | char *zErrMsg = 0; |
| 2372 | open_db(p, 0); |
| 2373 | memcpy(&data, p, sizeof(data)); |
| 2374 | data.showHeader = 1; |
| 2375 | data.mode = MODE_Column; |
| @@ -2456,15 +2463,15 @@ | |
| 2463 | }else |
| 2464 | |
| 2465 | if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ |
| 2466 | int val = nArg>=2 ? booleanValue(azArg[1]) : 1; |
| 2467 | if(val == 1) { |
| 2468 | if(!p->normalMode.valid) { |
| 2469 | p->normalMode.valid = 1; |
| 2470 | p->normalMode.mode = p->mode; |
| 2471 | p->normalMode.showHeader = p->showHeader; |
| 2472 | memcpy(p->normalMode.colWidth,p->colWidth,sizeof(p->colWidth)); |
| 2473 | } |
| 2474 | /* We could put this code under the !p->explainValid |
| 2475 | ** condition so that it does not execute if we are already in |
| 2476 | ** explain mode. However, always executing it allows us an easy |
| 2477 | ** was to reset to explain mode in case the user previously |
| @@ -2480,20 +2487,20 @@ | |
| 2487 | p->colWidth[3] = 4; /* P2 */ |
| 2488 | p->colWidth[4] = 4; /* P3 */ |
| 2489 | p->colWidth[5] = 13; /* P4 */ |
| 2490 | p->colWidth[6] = 2; /* P5 */ |
| 2491 | p->colWidth[7] = 13; /* Comment */ |
| 2492 | }else if (p->normalMode.valid) { |
| 2493 | p->normalMode.valid = 0; |
| 2494 | p->mode = p->normalMode.mode; |
| 2495 | p->showHeader = p->normalMode.showHeader; |
| 2496 | memcpy(p->colWidth,p->normalMode.colWidth,sizeof(p->colWidth)); |
| 2497 | } |
| 2498 | }else |
| 2499 | |
| 2500 | if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ |
| 2501 | ShellState data; |
| 2502 | char *zErrMsg = 0; |
| 2503 | int doStats = 0; |
| 2504 | if( nArg!=1 ){ |
| 2505 | fprintf(stderr, "Usage: .fullschema\n"); |
| 2506 | rc = 1; |
| @@ -2506,11 +2513,11 @@ | |
| 2513 | rc = sqlite3_exec(p->db, |
| 2514 | "SELECT sql FROM" |
| 2515 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 2516 | " FROM sqlite_master UNION ALL" |
| 2517 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 2518 | "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " |
| 2519 | "ORDER BY rowid", |
| 2520 | callback, &data, &zErrMsg |
| 2521 | ); |
| 2522 | if( rc==SQLITE_OK ){ |
| 2523 | sqlite3_stmt *pStmt; |
| @@ -2710,11 +2717,11 @@ | |
| 2717 | sqlite3_finalize(pStmt); |
| 2718 | if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0); |
| 2719 | }else |
| 2720 | |
| 2721 | if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){ |
| 2722 | ShellState data; |
| 2723 | char *zErrMsg = 0; |
| 2724 | open_db(p, 0); |
| 2725 | memcpy(&data, p, sizeof(data)); |
| 2726 | data.showHeader = 0; |
| 2727 | data.mode = MODE_List; |
| @@ -3004,11 +3011,11 @@ | |
| 3011 | } |
| 3012 | sqlite3_close(pSrc); |
| 3013 | }else |
| 3014 | |
| 3015 | if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ |
| 3016 | ShellState data; |
| 3017 | char *zErrMsg = 0; |
| 3018 | open_db(p, 0); |
| 3019 | memcpy(&data, p, sizeof(data)); |
| 3020 | data.showHeader = 0; |
| 3021 | data.mode = MODE_Semi; |
| @@ -3060,11 +3067,11 @@ | |
| 3067 | rc = sqlite3_exec(p->db, |
| 3068 | "SELECT sql FROM " |
| 3069 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 3070 | " FROM sqlite_master UNION ALL" |
| 3071 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 3072 | "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " |
| 3073 | "ORDER BY rowid", |
| 3074 | callback, &data, &zErrMsg |
| 3075 | ); |
| 3076 | }else{ |
| 3077 | fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n"); |
| @@ -3146,11 +3153,11 @@ | |
| 3153 | rc = 1; |
| 3154 | goto meta_command_exit; |
| 3155 | } |
| 3156 | fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); |
| 3157 | fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off"); |
| 3158 | fprintf(p->out,"%9.9s: %s\n","explain", p->normalMode.valid ? "on" :"off"); |
| 3159 | fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); |
| 3160 | fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); |
| 3161 | fprintf(p->out,"%9.9s: ", "nullvalue"); |
| 3162 | output_c_string(p->out, p->nullvalue); |
| 3163 | fprintf(p->out, "\n"); |
| @@ -3538,11 +3545,11 @@ | |
| 3545 | ** is saved only if input is interactive. An interrupt signal will |
| 3546 | ** cause this routine to exit immediately, unless input is interactive. |
| 3547 | ** |
| 3548 | ** Return the number of errors. |
| 3549 | */ |
| 3550 | static int process_input(ShellState *p, FILE *in){ |
| 3551 | char *zLine = 0; /* A single input line */ |
| 3552 | char *zSql = 0; /* Accumulated SQL text */ |
| 3553 | int nLine; /* Length of current line */ |
| 3554 | int nSql = 0; /* Bytes of zSql[] used */ |
| 3555 | int nAlloc = 0; /* Allocated zSql[] space */ |
| @@ -3717,11 +3724,11 @@ | |
| 3724 | ** parameter is NULL, take input from ~/.sqliterc |
| 3725 | ** |
| 3726 | ** Returns the number of errors. |
| 3727 | */ |
| 3728 | static int process_sqliterc( |
| 3729 | ShellState *p, /* Configuration data */ |
| 3730 | const char *sqliterc_override /* Name of config file. NULL to use default */ |
| 3731 | ){ |
| 3732 | char *home_dir = NULL; |
| 3733 | const char *sqliterc = sqliterc_override; |
| 3734 | char *zBuf = 0; |
| @@ -3800,11 +3807,11 @@ | |
| 3807 | } |
| 3808 | |
| 3809 | /* |
| 3810 | ** Initialize the state information in data |
| 3811 | */ |
| 3812 | static void main_init(ShellState *data) { |
| 3813 | memset(data, 0, sizeof(*data)); |
| 3814 | data->mode = MODE_List; |
| 3815 | memcpy(data->separator,"|", 2); |
| 3816 | memcpy(data->newline,"\r\n", 3); |
| 3817 | data->showHeader = 0; |
| @@ -3848,11 +3855,11 @@ | |
| 3855 | return argv[i]; |
| 3856 | } |
| 3857 | |
| 3858 | int main(int argc, char **argv){ |
| 3859 | char *zErrMsg = 0; |
| 3860 | ShellState data; |
| 3861 | const char *zInitFile = 0; |
| 3862 | char *zFirstCmd = 0; |
| 3863 | int i; |
| 3864 | int rc = 0; |
| 3865 | int warnInmemoryDb = 0; |
| 3866 |