Fossil SCM
Bring in the enhanced "shell.c" with the improved ".schema" and ".tables" commands from upstream SQLite.
Commit
d9e555194ac7709eb4eb6c3d3d2cdeac0cad5800a77bf99001390a31648fd015
Parent
e62161976ef8873…
1 file changed
+269
-150
+269
-150
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -16,15 +16,29 @@ | ||
| 16 | 16 | /* This needs to come before any includes for MSVC compiler */ |
| 17 | 17 | #define _CRT_SECURE_NO_WARNINGS |
| 18 | 18 | #endif |
| 19 | 19 | |
| 20 | 20 | /* |
| 21 | -** If requested, include the SQLite compiler options file for MSVC. | |
| 21 | +** Warning pragmas copied from msvc.h in the core. | |
| 22 | 22 | */ |
| 23 | -#if defined(INCLUDE_MSVC_H) | |
| 24 | -#include "msvc.h" | |
| 25 | -#endif | |
| 23 | +#if defined(_MSC_VER) | |
| 24 | +#pragma warning(disable : 4054) | |
| 25 | +#pragma warning(disable : 4055) | |
| 26 | +#pragma warning(disable : 4100) | |
| 27 | +#pragma warning(disable : 4127) | |
| 28 | +#pragma warning(disable : 4130) | |
| 29 | +#pragma warning(disable : 4152) | |
| 30 | +#pragma warning(disable : 4189) | |
| 31 | +#pragma warning(disable : 4206) | |
| 32 | +#pragma warning(disable : 4210) | |
| 33 | +#pragma warning(disable : 4232) | |
| 34 | +#pragma warning(disable : 4244) | |
| 35 | +#pragma warning(disable : 4305) | |
| 36 | +#pragma warning(disable : 4306) | |
| 37 | +#pragma warning(disable : 4702) | |
| 38 | +#pragma warning(disable : 4706) | |
| 39 | +#endif /* defined(_MSC_VER) */ | |
| 26 | 40 | |
| 27 | 41 | /* |
| 28 | 42 | ** No support for loadable extensions in VxWorks. |
| 29 | 43 | */ |
| 30 | 44 | #if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION |
| @@ -492,10 +506,22 @@ | ||
| 492 | 506 | static int strlen30(const char *z){ |
| 493 | 507 | const char *z2 = z; |
| 494 | 508 | while( *z2 ){ z2++; } |
| 495 | 509 | return 0x3fffffff & (int)(z2 - z); |
| 496 | 510 | } |
| 511 | + | |
| 512 | +/* | |
| 513 | +** Return the length of a string in characters. Multibyte UTF8 characters | |
| 514 | +** count as a single character. | |
| 515 | +*/ | |
| 516 | +static int strlenChar(const char *z){ | |
| 517 | + int n = 0; | |
| 518 | + while( *z ){ | |
| 519 | + if( (0xc0&*(z++))!=0x80 ) n++; | |
| 520 | + } | |
| 521 | + return n; | |
| 522 | +} | |
| 497 | 523 | |
| 498 | 524 | /* |
| 499 | 525 | ** This routine reads a line of text from FILE in, stores |
| 500 | 526 | ** the text in memory obtained from malloc() and returns a pointer |
| 501 | 527 | ** to the text. NULL is returned at end of file, or if malloc() |
| @@ -1156,16 +1182,71 @@ | ||
| 1156 | 1182 | for(i=0; i<p->nRate; i++){ |
| 1157 | 1183 | p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; |
| 1158 | 1184 | } |
| 1159 | 1185 | return &p->u.x[p->nRate]; |
| 1160 | 1186 | } |
| 1187 | + | |
| 1188 | +/* | |
| 1189 | +** SQL function: shell_add_schema(S,X) | |
| 1190 | +** | |
| 1191 | +** Add the schema name X to the CREATE statement in S and return the result. | |
| 1192 | +** Examples: | |
| 1193 | +** | |
| 1194 | +** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x); | |
| 1195 | +** | |
| 1196 | +** Also works on | |
| 1197 | +** | |
| 1198 | +** CREATE INDEX | |
| 1199 | +** CREATE UNIQUE INDEX | |
| 1200 | +** CREATE VIEW | |
| 1201 | +** CREATE TRIGGER | |
| 1202 | +** CREATE VIRTUAL TABLE | |
| 1203 | +** | |
| 1204 | +** This UDF is used by the .schema command to insert the schema name of | |
| 1205 | +** attached databases into the middle of the sqlite_master.sql field. | |
| 1206 | +*/ | |
| 1207 | +static void shellAddSchemaName( | |
| 1208 | + sqlite3_context *pCtx, | |
| 1209 | + int nVal, | |
| 1210 | + sqlite3_value **apVal | |
| 1211 | +){ | |
| 1212 | + static const char *aPrefix[] = { | |
| 1213 | + "TABLE", | |
| 1214 | + "INDEX", | |
| 1215 | + "UNIQUE INDEX", | |
| 1216 | + "VIEW", | |
| 1217 | + "TRIGGER", | |
| 1218 | + "VIRTUAL TABLE" | |
| 1219 | + }; | |
| 1220 | + int i = 0, n; | |
| 1221 | + const char *zIn = (const char*)sqlite3_value_text(apVal[0]); | |
| 1222 | + const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); | |
| 1223 | + assert( nVal==2 ); | |
| 1224 | + if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ | |
| 1225 | + for(i=0; i<sizeof(aPrefix)/sizeof(aPrefix[0]); i++){ | |
| 1226 | + int n = strlen30(aPrefix[i]); | |
| 1227 | + if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){ | |
| 1228 | + char cQuote = quoteChar(zSchema); | |
| 1229 | + char *z; | |
| 1230 | + if( cQuote ){ | |
| 1231 | + z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); | |
| 1232 | + }else{ | |
| 1233 | + z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); | |
| 1234 | + } | |
| 1235 | + sqlite3_result_text(pCtx, z, -1, sqlite3_free); | |
| 1236 | + return; | |
| 1237 | + } | |
| 1238 | + } | |
| 1239 | + } | |
| 1240 | + sqlite3_result_value(pCtx, apVal[0]); | |
| 1241 | +} | |
| 1161 | 1242 | |
| 1162 | 1243 | /* |
| 1163 | 1244 | ** Implementation of the sha3(X,SIZE) function. |
| 1164 | 1245 | ** |
| 1165 | 1246 | ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default |
| 1166 | -** size is 256. If X is a BLOB, it is hashed as is. | |
| 1247 | +** size is 256. If X is a BLOB, it is hashed as is. | |
| 1167 | 1248 | ** For all other non-NULL types of input, X is converted into a UTF-8 string |
| 1168 | 1249 | ** and the string is hashed without the trailing 0x00 terminator. The hash |
| 1169 | 1250 | ** of a NULL value is NULL. |
| 1170 | 1251 | */ |
| 1171 | 1252 | static void sha3Func( |
| @@ -1901,13 +1982,13 @@ | ||
| 1901 | 1982 | w = colWidth[i]; |
| 1902 | 1983 | }else{ |
| 1903 | 1984 | w = 0; |
| 1904 | 1985 | } |
| 1905 | 1986 | if( w==0 ){ |
| 1906 | - w = strlen30(azCol[i] ? azCol[i] : ""); | |
| 1987 | + w = strlenChar(azCol[i] ? azCol[i] : ""); | |
| 1907 | 1988 | if( w<10 ) w = 10; |
| 1908 | - n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue); | |
| 1989 | + n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue); | |
| 1909 | 1990 | if( w<n ) w = n; |
| 1910 | 1991 | } |
| 1911 | 1992 | if( i<ArraySize(p->actualWidth) ){ |
| 1912 | 1993 | p->actualWidth[i] = w; |
| 1913 | 1994 | } |
| @@ -1938,12 +2019,12 @@ | ||
| 1938 | 2019 | if( i<ArraySize(p->actualWidth) ){ |
| 1939 | 2020 | w = p->actualWidth[i]; |
| 1940 | 2021 | }else{ |
| 1941 | 2022 | w = 10; |
| 1942 | 2023 | } |
| 1943 | - if( p->cMode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ | |
| 1944 | - w = strlen30(azArg[i]); | |
| 2024 | + if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){ | |
| 2025 | + w = strlenChar(azArg[i]); | |
| 1945 | 2026 | } |
| 1946 | 2027 | if( i==1 && p->aiIndent && p->pStmt ){ |
| 1947 | 2028 | if( p->iIndent<p->nIndent ){ |
| 1948 | 2029 | utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); |
| 1949 | 2030 | } |
| @@ -2995,11 +3076,11 @@ | ||
| 2995 | 3076 | azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); |
| 2996 | 3077 | if( sqlite3_column_int(pStmt, 5) ){ |
| 2997 | 3078 | nPK++; |
| 2998 | 3079 | if( nPK==1 |
| 2999 | 3080 | && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), |
| 3000 | - "INTEGER")==0 | |
| 3081 | + "INTEGER")==0 | |
| 3001 | 3082 | ){ |
| 3002 | 3083 | isIPK = 1; |
| 3003 | 3084 | }else{ |
| 3004 | 3085 | isIPK = 0; |
| 3005 | 3086 | } |
| @@ -3232,10 +3313,11 @@ | ||
| 3232 | 3313 | ".auth ON|OFF Show authorizer callbacks\n" |
| 3233 | 3314 | #endif |
| 3234 | 3315 | ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" |
| 3235 | 3316 | ".bail on|off Stop after hitting an error. Default OFF\n" |
| 3236 | 3317 | ".binary on|off Turn binary output on or off. Default OFF\n" |
| 3318 | + ".cd DIRECTORY Change the working directory to DIRECTORY\n" | |
| 3237 | 3319 | ".changes on|off Show number of rows changed by SQL\n" |
| 3238 | 3320 | ".check GLOB Fail if output since .testcase does not match\n" |
| 3239 | 3321 | ".clone NEWDB Clone data into NEWDB from the existing database\n" |
| 3240 | 3322 | ".databases List names and files of attached databases\n" |
| 3241 | 3323 | ".dbinfo ?DB? Show status information about the database\n" |
| @@ -3277,12 +3359,12 @@ | ||
| 3277 | 3359 | " quote Escape answers as for SQL\n" |
| 3278 | 3360 | " tabs Tab-separated values\n" |
| 3279 | 3361 | " tcl TCL list elements\n" |
| 3280 | 3362 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 3281 | 3363 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 3282 | - ".open ?--new? ?FILE? Close existing database and reopen FILE\n" | |
| 3283 | - " The --new starts with an empty file\n" | |
| 3364 | + ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n" | |
| 3365 | + " The --new option starts with an empty file\n" | |
| 3284 | 3366 | ".output ?FILENAME? Send output to FILENAME or stdout\n" |
| 3285 | 3367 | ".print STRING... Print literal STRING\n" |
| 3286 | 3368 | ".prompt MAIN CONTINUE Replace the standard prompts\n" |
| 3287 | 3369 | ".quit Exit this program\n" |
| 3288 | 3370 | ".read FILENAME Execute SQL in FILENAME\n" |
| @@ -3343,12 +3425,12 @@ | ||
| 3343 | 3425 | /* Forward reference */ |
| 3344 | 3426 | static int process_input(ShellState *p, FILE *in); |
| 3345 | 3427 | |
| 3346 | 3428 | /* |
| 3347 | 3429 | ** Read the content of file zName into memory obtained from sqlite3_malloc64() |
| 3348 | -** and return a pointer to the buffer. The caller is responsible for freeing | |
| 3349 | -** the memory. | |
| 3430 | +** and return a pointer to the buffer. The caller is responsible for freeing | |
| 3431 | +** the memory. | |
| 3350 | 3432 | ** |
| 3351 | 3433 | ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes |
| 3352 | 3434 | ** read. |
| 3353 | 3435 | ** |
| 3354 | 3436 | ** For convenience, a nul-terminator byte is always appended to the data read |
| @@ -3507,10 +3589,13 @@ | ||
| 3507 | 3589 | sha3Func, 0, 0); |
| 3508 | 3590 | sqlite3_create_function(p->db, "sha3_query", 1, SQLITE_UTF8, 0, |
| 3509 | 3591 | sha3QueryFunc, 0, 0); |
| 3510 | 3592 | sqlite3_create_function(p->db, "sha3_query", 2, SQLITE_UTF8, 0, |
| 3511 | 3593 | sha3QueryFunc, 0, 0); |
| 3594 | + sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0, | |
| 3595 | + shellAddSchemaName, 0, 0); | |
| 3596 | + | |
| 3512 | 3597 | } |
| 3513 | 3598 | } |
| 3514 | 3599 | |
| 3515 | 3600 | /* |
| 3516 | 3601 | ** Do C-language style dequoting. |
| @@ -4351,19 +4436,19 @@ | ||
| 4351 | 4436 | ** the child table name and the child column name. |
| 4352 | 4437 | ** |
| 4353 | 4438 | ** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col') |
| 4354 | 4439 | ** |
| 4355 | 4440 | ** If either of the named tables or columns do not exist, this function |
| 4356 | -** returns an empty string. An empty string is also returned if both tables | |
| 4441 | +** returns an empty string. An empty string is also returned if both tables | |
| 4357 | 4442 | ** and columns exist but have the same default collation sequence. Or, |
| 4358 | 4443 | ** if both exist but the default collation sequences are different, this |
| 4359 | 4444 | ** function returns the string " COLLATE <parent-collation>", where |
| 4360 | 4445 | ** <parent-collation> is the default collation sequence of the parent column. |
| 4361 | 4446 | */ |
| 4362 | 4447 | static void shellFkeyCollateClause( |
| 4363 | - sqlite3_context *pCtx, | |
| 4364 | - int nVal, | |
| 4448 | + sqlite3_context *pCtx, | |
| 4449 | + int nVal, | |
| 4365 | 4450 | sqlite3_value **apVal |
| 4366 | 4451 | ){ |
| 4367 | 4452 | sqlite3 *db = sqlite3_context_db_handle(pCtx); |
| 4368 | 4453 | const char *zParent; |
| 4369 | 4454 | const char *zParentCol; |
| @@ -4370,11 +4455,11 @@ | ||
| 4370 | 4455 | const char *zParentSeq; |
| 4371 | 4456 | const char *zChild; |
| 4372 | 4457 | const char *zChildCol; |
| 4373 | 4458 | const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */ |
| 4374 | 4459 | int rc; |
| 4375 | - | |
| 4460 | + | |
| 4376 | 4461 | assert( nVal==4 ); |
| 4377 | 4462 | zParent = (const char*)sqlite3_value_text(apVal[0]); |
| 4378 | 4463 | zParentCol = (const char*)sqlite3_value_text(apVal[1]); |
| 4379 | 4464 | zChild = (const char*)sqlite3_value_text(apVal[2]); |
| 4380 | 4465 | zChildCol = (const char*)sqlite3_value_text(apVal[3]); |
| @@ -4492,11 +4577,11 @@ | ||
| 4492 | 4577 | azArg[0], azArg[1] |
| 4493 | 4578 | ); |
| 4494 | 4579 | return SQLITE_ERROR; |
| 4495 | 4580 | } |
| 4496 | 4581 | } |
| 4497 | - | |
| 4582 | + | |
| 4498 | 4583 | /* Register the fkey_collate_clause() SQL function */ |
| 4499 | 4584 | rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8, |
| 4500 | 4585 | 0, shellFkeyCollateClause, 0, 0 |
| 4501 | 4586 | ); |
| 4502 | 4587 | |
| @@ -4535,23 +4620,23 @@ | ||
| 4535 | 4620 | |
| 4536 | 4621 | if( res<0 ){ |
| 4537 | 4622 | raw_printf(stderr, "Error: internal error"); |
| 4538 | 4623 | break; |
| 4539 | 4624 | }else{ |
| 4540 | - if( bGroupByParent | |
| 4625 | + if( bGroupByParent | |
| 4541 | 4626 | && (bVerbose || res==0) |
| 4542 | - && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) | |
| 4627 | + && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) | |
| 4543 | 4628 | ){ |
| 4544 | 4629 | raw_printf(out, "-- Parent table %s\n", zParent); |
| 4545 | 4630 | sqlite3_free(zPrev); |
| 4546 | 4631 | zPrev = sqlite3_mprintf("%s", zParent); |
| 4547 | 4632 | } |
| 4548 | 4633 | |
| 4549 | 4634 | if( res==0 ){ |
| 4550 | 4635 | raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); |
| 4551 | 4636 | }else if( bVerbose ){ |
| 4552 | - raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n", | |
| 4637 | + raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n", | |
| 4553 | 4638 | zIndent, zFrom, zTarget |
| 4554 | 4639 | ); |
| 4555 | 4640 | } |
| 4556 | 4641 | } |
| 4557 | 4642 | } |
| @@ -4728,10 +4813,29 @@ | ||
| 4728 | 4813 | }else{ |
| 4729 | 4814 | raw_printf(stderr, "Usage: .binary on|off\n"); |
| 4730 | 4815 | rc = 1; |
| 4731 | 4816 | } |
| 4732 | 4817 | }else |
| 4818 | + | |
| 4819 | + if( c=='c' && strcmp(azArg[0],"cd")==0 ){ | |
| 4820 | + if( nArg==2 ){ | |
| 4821 | +#if defined(_WIN32) || defined(WIN32) | |
| 4822 | + wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]); | |
| 4823 | + rc = !SetCurrentDirectoryW(z); | |
| 4824 | + sqlite3_free(z); | |
| 4825 | +#else | |
| 4826 | + rc = chdir(azArg[1]); | |
| 4827 | +#endif | |
| 4828 | + if( rc ){ | |
| 4829 | + utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]); | |
| 4830 | + rc = 1; | |
| 4831 | + } | |
| 4832 | + }else{ | |
| 4833 | + raw_printf(stderr, "Usage: .cd DIRECTORY\n"); | |
| 4834 | + rc = 1; | |
| 4835 | + } | |
| 4836 | + }else | |
| 4733 | 4837 | |
| 4734 | 4838 | /* The undocumented ".breakpoint" command causes a call to the no-op |
| 4735 | 4839 | ** routine named test_breakpoint(). |
| 4736 | 4840 | */ |
| 4737 | 4841 | if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ |
| @@ -5641,16 +5745,21 @@ | ||
| 5641 | 5745 | rc = 1; |
| 5642 | 5746 | } |
| 5643 | 5747 | }else |
| 5644 | 5748 | |
| 5645 | 5749 | if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ |
| 5750 | + ShellText sSelect; | |
| 5646 | 5751 | ShellState data; |
| 5647 | 5752 | char *zErrMsg = 0; |
| 5753 | + const char *zDiv = 0; | |
| 5754 | + int iSchema = 0; | |
| 5755 | + | |
| 5648 | 5756 | open_db(p, 0); |
| 5649 | 5757 | memcpy(&data, p, sizeof(data)); |
| 5650 | 5758 | data.showHeader = 0; |
| 5651 | 5759 | data.cMode = data.mode = MODE_Semi; |
| 5760 | + initText(&sSelect); | |
| 5652 | 5761 | if( nArg>=2 && optionMatch(azArg[1], "indent") ){ |
| 5653 | 5762 | data.cMode = data.mode = MODE_Pretty; |
| 5654 | 5763 | nArg--; |
| 5655 | 5764 | if( nArg==2 ) azArg[1] = azArg[2]; |
| 5656 | 5765 | } |
| @@ -5684,37 +5793,66 @@ | ||
| 5684 | 5793 | new_colv[0] = "sql"; |
| 5685 | 5794 | new_colv[1] = 0; |
| 5686 | 5795 | callback(&data, 1, new_argv, new_colv); |
| 5687 | 5796 | rc = SQLITE_OK; |
| 5688 | 5797 | }else{ |
| 5689 | - char *zSql; | |
| 5690 | - zSql = sqlite3_mprintf( | |
| 5691 | - "SELECT sql FROM " | |
| 5692 | - " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" | |
| 5693 | - " FROM sqlite_master UNION ALL" | |
| 5694 | - " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " | |
| 5695 | - "WHERE lower(tbl_name) LIKE %Q" | |
| 5696 | - " AND type!='meta' AND sql NOTNULL " | |
| 5697 | - "ORDER BY rowid", azArg[1]); | |
| 5698 | - rc = sqlite3_exec(p->db, zSql, callback, &data, &zErrMsg); | |
| 5699 | - sqlite3_free(zSql); | |
| 5798 | + zDiv = "("; | |
| 5700 | 5799 | } |
| 5701 | 5800 | }else if( nArg==1 ){ |
| 5702 | - rc = sqlite3_exec(p->db, | |
| 5703 | - "SELECT sql FROM " | |
| 5704 | - " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" | |
| 5705 | - " FROM sqlite_master UNION ALL" | |
| 5706 | - " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " | |
| 5707 | - "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " | |
| 5708 | - "ORDER BY rowid", | |
| 5709 | - callback, &data, &zErrMsg | |
| 5710 | - ); | |
| 5801 | + zDiv = "("; | |
| 5711 | 5802 | }else{ |
| 5712 | 5803 | raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); |
| 5713 | 5804 | rc = 1; |
| 5714 | 5805 | goto meta_command_exit; |
| 5715 | 5806 | } |
| 5807 | + if( zDiv ){ | |
| 5808 | + sqlite3_stmt *pStmt = 0; | |
| 5809 | + sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list", | |
| 5810 | + -1, &pStmt, 0); | |
| 5811 | + appendText(&sSelect, "SELECT sql FROM", 0); | |
| 5812 | + iSchema = 0; | |
| 5813 | + while( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 5814 | + const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); | |
| 5815 | + char zScNum[30]; | |
| 5816 | + sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); | |
| 5817 | + appendText(&sSelect, zDiv, 0); | |
| 5818 | + zDiv = " UNION ALL "; | |
| 5819 | + if( strcmp(zDb, "main")!=0 ){ | |
| 5820 | + appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); | |
| 5821 | + appendText(&sSelect, sqlite3_column_text(pStmt, 0), '"'); | |
| 5822 | + appendText(&sSelect, ") AS sql, type, tbl_name, name, rowid,", 0); | |
| 5823 | + appendText(&sSelect, zScNum, 0); | |
| 5824 | + appendText(&sSelect, " AS snum, ", 0); | |
| 5825 | + appendText(&sSelect, zDb, '\''); | |
| 5826 | + appendText(&sSelect, " AS sname FROM ", 0); | |
| 5827 | + appendText(&sSelect, sqlite3_column_text(pStmt, 0), '"'); | |
| 5828 | + appendText(&sSelect, ".sqlite_master", 0); | |
| 5829 | + }else{ | |
| 5830 | + appendText(&sSelect, "SELECT sql, type, tbl_name, name, rowid, ", 0); | |
| 5831 | + appendText(&sSelect, zScNum, 0); | |
| 5832 | + appendText(&sSelect, " AS snum, 'main' AS sname FROM sqlite_master",0); | |
| 5833 | + } | |
| 5834 | + } | |
| 5835 | + sqlite3_finalize(pStmt); | |
| 5836 | + appendText(&sSelect, ") WHERE ", 0); | |
| 5837 | + if( nArg>1 ){ | |
| 5838 | + char *zQarg = sqlite3_mprintf("%Q", azArg[1]); | |
| 5839 | + if( strchr(azArg[1], '.') ){ | |
| 5840 | + appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); | |
| 5841 | + }else{ | |
| 5842 | + appendText(&sSelect, "lower(tbl_name)", 0); | |
| 5843 | + } | |
| 5844 | + appendText(&sSelect, strchr(azArg[1], '*') ? " GLOB " : " LIKE ", 0); | |
| 5845 | + appendText(&sSelect, zQarg, 0); | |
| 5846 | + appendText(&sSelect, " AND ", 0); | |
| 5847 | + sqlite3_free(zQarg); | |
| 5848 | + } | |
| 5849 | + appendText(&sSelect, "type!='meta' AND sql IS NOT NULL" | |
| 5850 | + " ORDER BY snum, rowid", 0); | |
| 5851 | + rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); | |
| 5852 | + freeText(&sSelect); | |
| 5853 | + } | |
| 5716 | 5854 | if( zErrMsg ){ |
| 5717 | 5855 | utf8_printf(stderr,"Error: %s\n", zErrMsg); |
| 5718 | 5856 | sqlite3_free(zErrMsg); |
| 5719 | 5857 | rc = 1; |
| 5720 | 5858 | }else if( rc != SQLITE_OK ){ |
| @@ -5952,23 +6090,15 @@ | ||
| 5952 | 6090 | |
| 5953 | 6091 | if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){ |
| 5954 | 6092 | int bIsInit = 0; /* True to initialize the SELFTEST table */ |
| 5955 | 6093 | int bVerbose = 0; /* Verbose output */ |
| 5956 | 6094 | int bSelftestExists; /* True if SELFTEST already exists */ |
| 5957 | - char **azTest = 0; /* Content of the SELFTEST table */ | |
| 5958 | - int nRow = 0; /* Number of rows in the SELFTEST table */ | |
| 5959 | - int nCol = 4; /* Number of columns in the SELFTEST table */ | |
| 5960 | - int i; /* Loop counter */ | |
| 6095 | + int i, k; /* Loop counters */ | |
| 5961 | 6096 | int nTest = 0; /* Number of tests runs */ |
| 5962 | 6097 | int nErr = 0; /* Number of errors seen */ |
| 5963 | 6098 | ShellText str; /* Answer for a query */ |
| 5964 | - static char *azDefaultTest[] = { | |
| 5965 | - 0, 0, 0, 0, | |
| 5966 | - "0", "memo", "Missing SELFTEST table - default checks only", "", | |
| 5967 | - "1", "run", "PRAGMA integrity_check", "ok" | |
| 5968 | - }; | |
| 5969 | - static const int nDefaultRow = 2; | |
| 6099 | + sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */ | |
| 5970 | 6100 | |
| 5971 | 6101 | open_db(p,0); |
| 5972 | 6102 | for(i=1; i<nArg; i++){ |
| 5973 | 6103 | const char *z = azArg[i]; |
| 5974 | 6104 | if( z[0]=='-' && z[1]=='-' ) z++; |
| @@ -5994,74 +6124,75 @@ | ||
| 5994 | 6124 | } |
| 5995 | 6125 | if( bIsInit ){ |
| 5996 | 6126 | createSelftestTable(p); |
| 5997 | 6127 | bSelftestExists = 1; |
| 5998 | 6128 | } |
| 5999 | - if( bSelftestExists ){ | |
| 6000 | - rc = sqlite3_get_table(p->db, | |
| 6001 | - "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", | |
| 6002 | - &azTest, &nRow, &nCol, 0); | |
| 6129 | + initText(&str); | |
| 6130 | + appendText(&str, "x", 0); | |
| 6131 | + for(k=bSelftestExists; k>=0; k--){ | |
| 6132 | + if( k==1 ){ | |
| 6133 | + rc = sqlite3_prepare_v2(p->db, | |
| 6134 | + "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", | |
| 6135 | + -1, &pStmt, 0); | |
| 6136 | + }else{ | |
| 6137 | + rc = sqlite3_prepare_v2(p->db, | |
| 6138 | + "VALUES(0,'memo','Missing SELFTEST table - default checks only','')," | |
| 6139 | + " (1,'run','PRAGMA integrity_check','ok')", | |
| 6140 | + -1, &pStmt, 0); | |
| 6141 | + } | |
| 6003 | 6142 | if( rc ){ |
| 6004 | 6143 | raw_printf(stderr, "Error querying the selftest table\n"); |
| 6005 | 6144 | rc = 1; |
| 6006 | - sqlite3_free_table(azTest); | |
| 6007 | - goto meta_command_exit; | |
| 6008 | - }else if( nRow==0 ){ | |
| 6009 | - sqlite3_free_table(azTest); | |
| 6010 | - azTest = azDefaultTest; | |
| 6011 | - nRow = nDefaultRow; | |
| 6012 | - } | |
| 6013 | - }else{ | |
| 6014 | - azTest = azDefaultTest; | |
| 6015 | - nRow = nDefaultRow; | |
| 6016 | - } | |
| 6017 | - initText(&str); | |
| 6018 | - appendText(&str, "x", 0); | |
| 6019 | - for(i=1; i<=nRow; i++){ | |
| 6020 | - int tno = atoi(azTest[i*nCol]); | |
| 6021 | - const char *zOp = azTest[i*nCol+1]; | |
| 6022 | - const char *zSql = azTest[i*nCol+2]; | |
| 6023 | - const char *zAns = azTest[i*nCol+3]; | |
| 6024 | - | |
| 6025 | - if( bVerbose>0 ){ | |
| 6026 | - char *zQuote = sqlite3_mprintf("%q", zSql); | |
| 6027 | - printf("%d: %s %s\n", tno, zOp, zSql); | |
| 6028 | - sqlite3_free(zQuote); | |
| 6029 | - } | |
| 6030 | - if( strcmp(zOp,"memo")==0 ){ | |
| 6031 | - utf8_printf(p->out, "%s\n", zSql); | |
| 6032 | - }else | |
| 6033 | - if( strcmp(zOp,"run")==0 ){ | |
| 6034 | - char *zErrMsg = 0; | |
| 6035 | - str.n = 0; | |
| 6036 | - str.z[0] = 0; | |
| 6037 | - rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); | |
| 6038 | - nTest++; | |
| 6039 | - if( bVerbose ){ | |
| 6040 | - utf8_printf(p->out, "Result: %s\n", str.z); | |
| 6041 | - } | |
| 6042 | - if( rc || zErrMsg ){ | |
| 6043 | - nErr++; | |
| 6044 | - rc = 1; | |
| 6045 | - utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); | |
| 6046 | - sqlite3_free(zErrMsg); | |
| 6047 | - }else if( strcmp(zAns,str.z)!=0 ){ | |
| 6048 | - nErr++; | |
| 6049 | - rc = 1; | |
| 6050 | - utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); | |
| 6051 | - utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); | |
| 6052 | - } | |
| 6053 | - }else | |
| 6054 | - { | |
| 6055 | - utf8_printf(stderr, | |
| 6056 | - "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); | |
| 6057 | - rc = 1; | |
| 6058 | - break; | |
| 6059 | - } | |
| 6060 | - } | |
| 6061 | - freeText(&str); | |
| 6062 | - if( azTest!=azDefaultTest ) sqlite3_free_table(azTest); | |
| 6145 | + sqlite3_finalize(pStmt); | |
| 6146 | + goto meta_command_exit; | |
| 6147 | + } | |
| 6148 | + for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){ | |
| 6149 | + int tno = sqlite3_column_int(pStmt, 0); | |
| 6150 | + const char *zOp = (const char*)sqlite3_column_text(pStmt, 1); | |
| 6151 | + const char *zSql = (const char*)sqlite3_column_text(pStmt, 2); | |
| 6152 | + const char *zAns = (const char*)sqlite3_column_text(pStmt, 3); | |
| 6153 | + | |
| 6154 | + k = 0; | |
| 6155 | + if( bVerbose>0 ){ | |
| 6156 | + char *zQuote = sqlite3_mprintf("%q", zSql); | |
| 6157 | + printf("%d: %s %s\n", tno, zOp, zSql); | |
| 6158 | + sqlite3_free(zQuote); | |
| 6159 | + } | |
| 6160 | + if( strcmp(zOp,"memo")==0 ){ | |
| 6161 | + utf8_printf(p->out, "%s\n", zSql); | |
| 6162 | + }else | |
| 6163 | + if( strcmp(zOp,"run")==0 ){ | |
| 6164 | + char *zErrMsg = 0; | |
| 6165 | + str.n = 0; | |
| 6166 | + str.z[0] = 0; | |
| 6167 | + rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); | |
| 6168 | + nTest++; | |
| 6169 | + if( bVerbose ){ | |
| 6170 | + utf8_printf(p->out, "Result: %s\n", str.z); | |
| 6171 | + } | |
| 6172 | + if( rc || zErrMsg ){ | |
| 6173 | + nErr++; | |
| 6174 | + rc = 1; | |
| 6175 | + utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); | |
| 6176 | + sqlite3_free(zErrMsg); | |
| 6177 | + }else if( strcmp(zAns,str.z)!=0 ){ | |
| 6178 | + nErr++; | |
| 6179 | + rc = 1; | |
| 6180 | + utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); | |
| 6181 | + utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); | |
| 6182 | + } | |
| 6183 | + }else | |
| 6184 | + { | |
| 6185 | + utf8_printf(stderr, | |
| 6186 | + "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); | |
| 6187 | + rc = 1; | |
| 6188 | + break; | |
| 6189 | + } | |
| 6190 | + } /* End loop over rows of content from SELFTEST */ | |
| 6191 | + sqlite3_finalize(pStmt); | |
| 6192 | + } /* End loop over k */ | |
| 6193 | + freeText(&str); | |
| 6063 | 6194 | utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); |
| 6064 | 6195 | }else |
| 6065 | 6196 | |
| 6066 | 6197 | if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ |
| 6067 | 6198 | if( nArg<2 || nArg>3 ){ |
| @@ -6097,12 +6228,12 @@ | ||
| 6097 | 6228 | z++; |
| 6098 | 6229 | if( z[0]=='-' ) z++; |
| 6099 | 6230 | if( strcmp(z,"schema")==0 ){ |
| 6100 | 6231 | bSchema = 1; |
| 6101 | 6232 | }else |
| 6102 | - if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0 | |
| 6103 | - || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0 | |
| 6233 | + if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0 | |
| 6234 | + || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0 | |
| 6104 | 6235 | ){ |
| 6105 | 6236 | iSize = atoi(&z[5]); |
| 6106 | 6237 | }else |
| 6107 | 6238 | if( strcmp(z,"debug")==0 ){ |
| 6108 | 6239 | bDebug = 1; |
| @@ -6266,63 +6397,51 @@ | ||
| 6266 | 6397 | || strncmp(azArg[0], "indexes", n)==0) ) |
| 6267 | 6398 | ){ |
| 6268 | 6399 | sqlite3_stmt *pStmt; |
| 6269 | 6400 | char **azResult; |
| 6270 | 6401 | int nRow, nAlloc; |
| 6271 | - char *zSql = 0; | |
| 6272 | 6402 | int ii; |
| 6403 | + ShellText s; | |
| 6404 | + initText(&s); | |
| 6273 | 6405 | open_db(p, 0); |
| 6274 | 6406 | rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); |
| 6275 | 6407 | if( rc ) return shellDatabaseError(p->db); |
| 6276 | 6408 | |
| 6277 | - /* Create an SQL statement to query for the list of tables in the | |
| 6278 | - ** main and all attached databases where the table name matches the | |
| 6279 | - ** LIKE pattern bound to variable "?1". */ | |
| 6280 | - if( c=='t' ){ | |
| 6281 | - zSql = sqlite3_mprintf( | |
| 6282 | - "SELECT name FROM sqlite_master" | |
| 6283 | - " WHERE type IN ('table','view')" | |
| 6284 | - " AND name NOT LIKE 'sqlite_%%'" | |
| 6285 | - " AND name LIKE ?1"); | |
| 6286 | - }else if( nArg>2 ){ | |
| 6409 | + if( nArg>2 && c=='i' ){ | |
| 6287 | 6410 | /* It is an historical accident that the .indexes command shows an error |
| 6288 | 6411 | ** when called with the wrong number of arguments whereas the .tables |
| 6289 | 6412 | ** command does not. */ |
| 6290 | 6413 | raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); |
| 6291 | 6414 | rc = 1; |
| 6292 | 6415 | goto meta_command_exit; |
| 6293 | - }else{ | |
| 6294 | - zSql = sqlite3_mprintf( | |
| 6295 | - "SELECT name FROM sqlite_master" | |
| 6296 | - " WHERE type='index'" | |
| 6297 | - " AND tbl_name LIKE ?1"); | |
| 6298 | 6416 | } |
| 6299 | - for(ii=0; zSql && sqlite3_step(pStmt)==SQLITE_ROW; ii++){ | |
| 6417 | + for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ | |
| 6300 | 6418 | const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); |
| 6301 | - if( zDbName==0 || ii==0 ) continue; | |
| 6419 | + if( zDbName==0 ) continue; | |
| 6420 | + if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0); | |
| 6421 | + if( sqlite3_stricmp(zDbName, "main")==0 ){ | |
| 6422 | + appendText(&s, "SELECT name FROM ", 0); | |
| 6423 | + }else{ | |
| 6424 | + appendText(&s, "SELECT ", 0); | |
| 6425 | + appendText(&s, zDbName, '\''); | |
| 6426 | + appendText(&s, "||'.'||name FROM ", 0); | |
| 6427 | + } | |
| 6428 | + appendText(&s, zDbName, '"'); | |
| 6429 | + appendText(&s, ".sqlite_master ", 0); | |
| 6302 | 6430 | if( c=='t' ){ |
| 6303 | - zSql = sqlite3_mprintf( | |
| 6304 | - "%z UNION ALL " | |
| 6305 | - "SELECT '%q.' || name FROM \"%w\".sqlite_master" | |
| 6306 | - " WHERE type IN ('table','view')" | |
| 6307 | - " AND name NOT LIKE 'sqlite_%%'" | |
| 6308 | - " AND name LIKE ?1", zSql, zDbName, zDbName); | |
| 6431 | + appendText(&s," WHERE type IN ('table','view')" | |
| 6432 | + " AND name NOT LIKE 'sqlite_%'" | |
| 6433 | + " AND name LIKE ?1", 0); | |
| 6309 | 6434 | }else{ |
| 6310 | - zSql = sqlite3_mprintf( | |
| 6311 | - "%z UNION ALL " | |
| 6312 | - "SELECT '%q.' || name FROM \"%w\".sqlite_master" | |
| 6313 | - " WHERE type='index'" | |
| 6314 | - " AND tbl_name LIKE ?1", zSql, zDbName, zDbName); | |
| 6435 | + appendText(&s," WHERE type='index'" | |
| 6436 | + " AND tbl_name LIKE ?1", 0); | |
| 6315 | 6437 | } |
| 6316 | 6438 | } |
| 6317 | 6439 | rc = sqlite3_finalize(pStmt); |
| 6318 | - if( zSql && rc==SQLITE_OK ){ | |
| 6319 | - zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); | |
| 6320 | - if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
| 6321 | - } | |
| 6322 | - sqlite3_free(zSql); | |
| 6323 | - if( !zSql ) return shellNomemError(); | |
| 6440 | + appendText(&s, " ORDER BY 1", 0); | |
| 6441 | + rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0); | |
| 6442 | + freeText(&s); | |
| 6324 | 6443 | if( rc ) return shellDatabaseError(p->db); |
| 6325 | 6444 | |
| 6326 | 6445 | /* Run the SQL statement prepared by the above block. Store the results |
| 6327 | 6446 | ** as an array of nul-terminated strings in azResult[]. */ |
| 6328 | 6447 | nRow = nAlloc = 0; |
| 6329 | 6448 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -16,15 +16,29 @@ | |
| 16 | /* This needs to come before any includes for MSVC compiler */ |
| 17 | #define _CRT_SECURE_NO_WARNINGS |
| 18 | #endif |
| 19 | |
| 20 | /* |
| 21 | ** If requested, include the SQLite compiler options file for MSVC. |
| 22 | */ |
| 23 | #if defined(INCLUDE_MSVC_H) |
| 24 | #include "msvc.h" |
| 25 | #endif |
| 26 | |
| 27 | /* |
| 28 | ** No support for loadable extensions in VxWorks. |
| 29 | */ |
| 30 | #if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION |
| @@ -492,10 +506,22 @@ | |
| 492 | static int strlen30(const char *z){ |
| 493 | const char *z2 = z; |
| 494 | while( *z2 ){ z2++; } |
| 495 | return 0x3fffffff & (int)(z2 - z); |
| 496 | } |
| 497 | |
| 498 | /* |
| 499 | ** This routine reads a line of text from FILE in, stores |
| 500 | ** the text in memory obtained from malloc() and returns a pointer |
| 501 | ** to the text. NULL is returned at end of file, or if malloc() |
| @@ -1156,16 +1182,71 @@ | |
| 1156 | for(i=0; i<p->nRate; i++){ |
| 1157 | p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; |
| 1158 | } |
| 1159 | return &p->u.x[p->nRate]; |
| 1160 | } |
| 1161 | |
| 1162 | /* |
| 1163 | ** Implementation of the sha3(X,SIZE) function. |
| 1164 | ** |
| 1165 | ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default |
| 1166 | ** size is 256. If X is a BLOB, it is hashed as is. |
| 1167 | ** For all other non-NULL types of input, X is converted into a UTF-8 string |
| 1168 | ** and the string is hashed without the trailing 0x00 terminator. The hash |
| 1169 | ** of a NULL value is NULL. |
| 1170 | */ |
| 1171 | static void sha3Func( |
| @@ -1901,13 +1982,13 @@ | |
| 1901 | w = colWidth[i]; |
| 1902 | }else{ |
| 1903 | w = 0; |
| 1904 | } |
| 1905 | if( w==0 ){ |
| 1906 | w = strlen30(azCol[i] ? azCol[i] : ""); |
| 1907 | if( w<10 ) w = 10; |
| 1908 | n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue); |
| 1909 | if( w<n ) w = n; |
| 1910 | } |
| 1911 | if( i<ArraySize(p->actualWidth) ){ |
| 1912 | p->actualWidth[i] = w; |
| 1913 | } |
| @@ -1938,12 +2019,12 @@ | |
| 1938 | if( i<ArraySize(p->actualWidth) ){ |
| 1939 | w = p->actualWidth[i]; |
| 1940 | }else{ |
| 1941 | w = 10; |
| 1942 | } |
| 1943 | if( p->cMode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ |
| 1944 | w = strlen30(azArg[i]); |
| 1945 | } |
| 1946 | if( i==1 && p->aiIndent && p->pStmt ){ |
| 1947 | if( p->iIndent<p->nIndent ){ |
| 1948 | utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); |
| 1949 | } |
| @@ -2995,11 +3076,11 @@ | |
| 2995 | azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); |
| 2996 | if( sqlite3_column_int(pStmt, 5) ){ |
| 2997 | nPK++; |
| 2998 | if( nPK==1 |
| 2999 | && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), |
| 3000 | "INTEGER")==0 |
| 3001 | ){ |
| 3002 | isIPK = 1; |
| 3003 | }else{ |
| 3004 | isIPK = 0; |
| 3005 | } |
| @@ -3232,10 +3313,11 @@ | |
| 3232 | ".auth ON|OFF Show authorizer callbacks\n" |
| 3233 | #endif |
| 3234 | ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" |
| 3235 | ".bail on|off Stop after hitting an error. Default OFF\n" |
| 3236 | ".binary on|off Turn binary output on or off. Default OFF\n" |
| 3237 | ".changes on|off Show number of rows changed by SQL\n" |
| 3238 | ".check GLOB Fail if output since .testcase does not match\n" |
| 3239 | ".clone NEWDB Clone data into NEWDB from the existing database\n" |
| 3240 | ".databases List names and files of attached databases\n" |
| 3241 | ".dbinfo ?DB? Show status information about the database\n" |
| @@ -3277,12 +3359,12 @@ | |
| 3277 | " quote Escape answers as for SQL\n" |
| 3278 | " tabs Tab-separated values\n" |
| 3279 | " tcl TCL list elements\n" |
| 3280 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 3281 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 3282 | ".open ?--new? ?FILE? Close existing database and reopen FILE\n" |
| 3283 | " The --new starts with an empty file\n" |
| 3284 | ".output ?FILENAME? Send output to FILENAME or stdout\n" |
| 3285 | ".print STRING... Print literal STRING\n" |
| 3286 | ".prompt MAIN CONTINUE Replace the standard prompts\n" |
| 3287 | ".quit Exit this program\n" |
| 3288 | ".read FILENAME Execute SQL in FILENAME\n" |
| @@ -3343,12 +3425,12 @@ | |
| 3343 | /* Forward reference */ |
| 3344 | static int process_input(ShellState *p, FILE *in); |
| 3345 | |
| 3346 | /* |
| 3347 | ** Read the content of file zName into memory obtained from sqlite3_malloc64() |
| 3348 | ** and return a pointer to the buffer. The caller is responsible for freeing |
| 3349 | ** the memory. |
| 3350 | ** |
| 3351 | ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes |
| 3352 | ** read. |
| 3353 | ** |
| 3354 | ** For convenience, a nul-terminator byte is always appended to the data read |
| @@ -3507,10 +3589,13 @@ | |
| 3507 | sha3Func, 0, 0); |
| 3508 | sqlite3_create_function(p->db, "sha3_query", 1, SQLITE_UTF8, 0, |
| 3509 | sha3QueryFunc, 0, 0); |
| 3510 | sqlite3_create_function(p->db, "sha3_query", 2, SQLITE_UTF8, 0, |
| 3511 | sha3QueryFunc, 0, 0); |
| 3512 | } |
| 3513 | } |
| 3514 | |
| 3515 | /* |
| 3516 | ** Do C-language style dequoting. |
| @@ -4351,19 +4436,19 @@ | |
| 4351 | ** the child table name and the child column name. |
| 4352 | ** |
| 4353 | ** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col') |
| 4354 | ** |
| 4355 | ** If either of the named tables or columns do not exist, this function |
| 4356 | ** returns an empty string. An empty string is also returned if both tables |
| 4357 | ** and columns exist but have the same default collation sequence. Or, |
| 4358 | ** if both exist but the default collation sequences are different, this |
| 4359 | ** function returns the string " COLLATE <parent-collation>", where |
| 4360 | ** <parent-collation> is the default collation sequence of the parent column. |
| 4361 | */ |
| 4362 | static void shellFkeyCollateClause( |
| 4363 | sqlite3_context *pCtx, |
| 4364 | int nVal, |
| 4365 | sqlite3_value **apVal |
| 4366 | ){ |
| 4367 | sqlite3 *db = sqlite3_context_db_handle(pCtx); |
| 4368 | const char *zParent; |
| 4369 | const char *zParentCol; |
| @@ -4370,11 +4455,11 @@ | |
| 4370 | const char *zParentSeq; |
| 4371 | const char *zChild; |
| 4372 | const char *zChildCol; |
| 4373 | const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */ |
| 4374 | int rc; |
| 4375 | |
| 4376 | assert( nVal==4 ); |
| 4377 | zParent = (const char*)sqlite3_value_text(apVal[0]); |
| 4378 | zParentCol = (const char*)sqlite3_value_text(apVal[1]); |
| 4379 | zChild = (const char*)sqlite3_value_text(apVal[2]); |
| 4380 | zChildCol = (const char*)sqlite3_value_text(apVal[3]); |
| @@ -4492,11 +4577,11 @@ | |
| 4492 | azArg[0], azArg[1] |
| 4493 | ); |
| 4494 | return SQLITE_ERROR; |
| 4495 | } |
| 4496 | } |
| 4497 | |
| 4498 | /* Register the fkey_collate_clause() SQL function */ |
| 4499 | rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8, |
| 4500 | 0, shellFkeyCollateClause, 0, 0 |
| 4501 | ); |
| 4502 | |
| @@ -4535,23 +4620,23 @@ | |
| 4535 | |
| 4536 | if( res<0 ){ |
| 4537 | raw_printf(stderr, "Error: internal error"); |
| 4538 | break; |
| 4539 | }else{ |
| 4540 | if( bGroupByParent |
| 4541 | && (bVerbose || res==0) |
| 4542 | && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) |
| 4543 | ){ |
| 4544 | raw_printf(out, "-- Parent table %s\n", zParent); |
| 4545 | sqlite3_free(zPrev); |
| 4546 | zPrev = sqlite3_mprintf("%s", zParent); |
| 4547 | } |
| 4548 | |
| 4549 | if( res==0 ){ |
| 4550 | raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); |
| 4551 | }else if( bVerbose ){ |
| 4552 | raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n", |
| 4553 | zIndent, zFrom, zTarget |
| 4554 | ); |
| 4555 | } |
| 4556 | } |
| 4557 | } |
| @@ -4728,10 +4813,29 @@ | |
| 4728 | }else{ |
| 4729 | raw_printf(stderr, "Usage: .binary on|off\n"); |
| 4730 | rc = 1; |
| 4731 | } |
| 4732 | }else |
| 4733 | |
| 4734 | /* The undocumented ".breakpoint" command causes a call to the no-op |
| 4735 | ** routine named test_breakpoint(). |
| 4736 | */ |
| 4737 | if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ |
| @@ -5641,16 +5745,21 @@ | |
| 5641 | rc = 1; |
| 5642 | } |
| 5643 | }else |
| 5644 | |
| 5645 | if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ |
| 5646 | ShellState data; |
| 5647 | char *zErrMsg = 0; |
| 5648 | open_db(p, 0); |
| 5649 | memcpy(&data, p, sizeof(data)); |
| 5650 | data.showHeader = 0; |
| 5651 | data.cMode = data.mode = MODE_Semi; |
| 5652 | if( nArg>=2 && optionMatch(azArg[1], "indent") ){ |
| 5653 | data.cMode = data.mode = MODE_Pretty; |
| 5654 | nArg--; |
| 5655 | if( nArg==2 ) azArg[1] = azArg[2]; |
| 5656 | } |
| @@ -5684,37 +5793,66 @@ | |
| 5684 | new_colv[0] = "sql"; |
| 5685 | new_colv[1] = 0; |
| 5686 | callback(&data, 1, new_argv, new_colv); |
| 5687 | rc = SQLITE_OK; |
| 5688 | }else{ |
| 5689 | char *zSql; |
| 5690 | zSql = sqlite3_mprintf( |
| 5691 | "SELECT sql FROM " |
| 5692 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 5693 | " FROM sqlite_master UNION ALL" |
| 5694 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 5695 | "WHERE lower(tbl_name) LIKE %Q" |
| 5696 | " AND type!='meta' AND sql NOTNULL " |
| 5697 | "ORDER BY rowid", azArg[1]); |
| 5698 | rc = sqlite3_exec(p->db, zSql, callback, &data, &zErrMsg); |
| 5699 | sqlite3_free(zSql); |
| 5700 | } |
| 5701 | }else if( nArg==1 ){ |
| 5702 | rc = sqlite3_exec(p->db, |
| 5703 | "SELECT sql FROM " |
| 5704 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 5705 | " FROM sqlite_master UNION ALL" |
| 5706 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 5707 | "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " |
| 5708 | "ORDER BY rowid", |
| 5709 | callback, &data, &zErrMsg |
| 5710 | ); |
| 5711 | }else{ |
| 5712 | raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); |
| 5713 | rc = 1; |
| 5714 | goto meta_command_exit; |
| 5715 | } |
| 5716 | if( zErrMsg ){ |
| 5717 | utf8_printf(stderr,"Error: %s\n", zErrMsg); |
| 5718 | sqlite3_free(zErrMsg); |
| 5719 | rc = 1; |
| 5720 | }else if( rc != SQLITE_OK ){ |
| @@ -5952,23 +6090,15 @@ | |
| 5952 | |
| 5953 | if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){ |
| 5954 | int bIsInit = 0; /* True to initialize the SELFTEST table */ |
| 5955 | int bVerbose = 0; /* Verbose output */ |
| 5956 | int bSelftestExists; /* True if SELFTEST already exists */ |
| 5957 | char **azTest = 0; /* Content of the SELFTEST table */ |
| 5958 | int nRow = 0; /* Number of rows in the SELFTEST table */ |
| 5959 | int nCol = 4; /* Number of columns in the SELFTEST table */ |
| 5960 | int i; /* Loop counter */ |
| 5961 | int nTest = 0; /* Number of tests runs */ |
| 5962 | int nErr = 0; /* Number of errors seen */ |
| 5963 | ShellText str; /* Answer for a query */ |
| 5964 | static char *azDefaultTest[] = { |
| 5965 | 0, 0, 0, 0, |
| 5966 | "0", "memo", "Missing SELFTEST table - default checks only", "", |
| 5967 | "1", "run", "PRAGMA integrity_check", "ok" |
| 5968 | }; |
| 5969 | static const int nDefaultRow = 2; |
| 5970 | |
| 5971 | open_db(p,0); |
| 5972 | for(i=1; i<nArg; i++){ |
| 5973 | const char *z = azArg[i]; |
| 5974 | if( z[0]=='-' && z[1]=='-' ) z++; |
| @@ -5994,74 +6124,75 @@ | |
| 5994 | } |
| 5995 | if( bIsInit ){ |
| 5996 | createSelftestTable(p); |
| 5997 | bSelftestExists = 1; |
| 5998 | } |
| 5999 | if( bSelftestExists ){ |
| 6000 | rc = sqlite3_get_table(p->db, |
| 6001 | "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", |
| 6002 | &azTest, &nRow, &nCol, 0); |
| 6003 | if( rc ){ |
| 6004 | raw_printf(stderr, "Error querying the selftest table\n"); |
| 6005 | rc = 1; |
| 6006 | sqlite3_free_table(azTest); |
| 6007 | goto meta_command_exit; |
| 6008 | }else if( nRow==0 ){ |
| 6009 | sqlite3_free_table(azTest); |
| 6010 | azTest = azDefaultTest; |
| 6011 | nRow = nDefaultRow; |
| 6012 | } |
| 6013 | }else{ |
| 6014 | azTest = azDefaultTest; |
| 6015 | nRow = nDefaultRow; |
| 6016 | } |
| 6017 | initText(&str); |
| 6018 | appendText(&str, "x", 0); |
| 6019 | for(i=1; i<=nRow; i++){ |
| 6020 | int tno = atoi(azTest[i*nCol]); |
| 6021 | const char *zOp = azTest[i*nCol+1]; |
| 6022 | const char *zSql = azTest[i*nCol+2]; |
| 6023 | const char *zAns = azTest[i*nCol+3]; |
| 6024 | |
| 6025 | if( bVerbose>0 ){ |
| 6026 | char *zQuote = sqlite3_mprintf("%q", zSql); |
| 6027 | printf("%d: %s %s\n", tno, zOp, zSql); |
| 6028 | sqlite3_free(zQuote); |
| 6029 | } |
| 6030 | if( strcmp(zOp,"memo")==0 ){ |
| 6031 | utf8_printf(p->out, "%s\n", zSql); |
| 6032 | }else |
| 6033 | if( strcmp(zOp,"run")==0 ){ |
| 6034 | char *zErrMsg = 0; |
| 6035 | str.n = 0; |
| 6036 | str.z[0] = 0; |
| 6037 | rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); |
| 6038 | nTest++; |
| 6039 | if( bVerbose ){ |
| 6040 | utf8_printf(p->out, "Result: %s\n", str.z); |
| 6041 | } |
| 6042 | if( rc || zErrMsg ){ |
| 6043 | nErr++; |
| 6044 | rc = 1; |
| 6045 | utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); |
| 6046 | sqlite3_free(zErrMsg); |
| 6047 | }else if( strcmp(zAns,str.z)!=0 ){ |
| 6048 | nErr++; |
| 6049 | rc = 1; |
| 6050 | utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); |
| 6051 | utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); |
| 6052 | } |
| 6053 | }else |
| 6054 | { |
| 6055 | utf8_printf(stderr, |
| 6056 | "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); |
| 6057 | rc = 1; |
| 6058 | break; |
| 6059 | } |
| 6060 | } |
| 6061 | freeText(&str); |
| 6062 | if( azTest!=azDefaultTest ) sqlite3_free_table(azTest); |
| 6063 | utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); |
| 6064 | }else |
| 6065 | |
| 6066 | if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ |
| 6067 | if( nArg<2 || nArg>3 ){ |
| @@ -6097,12 +6228,12 @@ | |
| 6097 | z++; |
| 6098 | if( z[0]=='-' ) z++; |
| 6099 | if( strcmp(z,"schema")==0 ){ |
| 6100 | bSchema = 1; |
| 6101 | }else |
| 6102 | if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0 |
| 6103 | || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0 |
| 6104 | ){ |
| 6105 | iSize = atoi(&z[5]); |
| 6106 | }else |
| 6107 | if( strcmp(z,"debug")==0 ){ |
| 6108 | bDebug = 1; |
| @@ -6266,63 +6397,51 @@ | |
| 6266 | || strncmp(azArg[0], "indexes", n)==0) ) |
| 6267 | ){ |
| 6268 | sqlite3_stmt *pStmt; |
| 6269 | char **azResult; |
| 6270 | int nRow, nAlloc; |
| 6271 | char *zSql = 0; |
| 6272 | int ii; |
| 6273 | open_db(p, 0); |
| 6274 | rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); |
| 6275 | if( rc ) return shellDatabaseError(p->db); |
| 6276 | |
| 6277 | /* Create an SQL statement to query for the list of tables in the |
| 6278 | ** main and all attached databases where the table name matches the |
| 6279 | ** LIKE pattern bound to variable "?1". */ |
| 6280 | if( c=='t' ){ |
| 6281 | zSql = sqlite3_mprintf( |
| 6282 | "SELECT name FROM sqlite_master" |
| 6283 | " WHERE type IN ('table','view')" |
| 6284 | " AND name NOT LIKE 'sqlite_%%'" |
| 6285 | " AND name LIKE ?1"); |
| 6286 | }else if( nArg>2 ){ |
| 6287 | /* It is an historical accident that the .indexes command shows an error |
| 6288 | ** when called with the wrong number of arguments whereas the .tables |
| 6289 | ** command does not. */ |
| 6290 | raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); |
| 6291 | rc = 1; |
| 6292 | goto meta_command_exit; |
| 6293 | }else{ |
| 6294 | zSql = sqlite3_mprintf( |
| 6295 | "SELECT name FROM sqlite_master" |
| 6296 | " WHERE type='index'" |
| 6297 | " AND tbl_name LIKE ?1"); |
| 6298 | } |
| 6299 | for(ii=0; zSql && sqlite3_step(pStmt)==SQLITE_ROW; ii++){ |
| 6300 | const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); |
| 6301 | if( zDbName==0 || ii==0 ) continue; |
| 6302 | if( c=='t' ){ |
| 6303 | zSql = sqlite3_mprintf( |
| 6304 | "%z UNION ALL " |
| 6305 | "SELECT '%q.' || name FROM \"%w\".sqlite_master" |
| 6306 | " WHERE type IN ('table','view')" |
| 6307 | " AND name NOT LIKE 'sqlite_%%'" |
| 6308 | " AND name LIKE ?1", zSql, zDbName, zDbName); |
| 6309 | }else{ |
| 6310 | zSql = sqlite3_mprintf( |
| 6311 | "%z UNION ALL " |
| 6312 | "SELECT '%q.' || name FROM \"%w\".sqlite_master" |
| 6313 | " WHERE type='index'" |
| 6314 | " AND tbl_name LIKE ?1", zSql, zDbName, zDbName); |
| 6315 | } |
| 6316 | } |
| 6317 | rc = sqlite3_finalize(pStmt); |
| 6318 | if( zSql && rc==SQLITE_OK ){ |
| 6319 | zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); |
| 6320 | if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 6321 | } |
| 6322 | sqlite3_free(zSql); |
| 6323 | if( !zSql ) return shellNomemError(); |
| 6324 | if( rc ) return shellDatabaseError(p->db); |
| 6325 | |
| 6326 | /* Run the SQL statement prepared by the above block. Store the results |
| 6327 | ** as an array of nul-terminated strings in azResult[]. */ |
| 6328 | nRow = nAlloc = 0; |
| 6329 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -16,15 +16,29 @@ | |
| 16 | /* This needs to come before any includes for MSVC compiler */ |
| 17 | #define _CRT_SECURE_NO_WARNINGS |
| 18 | #endif |
| 19 | |
| 20 | /* |
| 21 | ** Warning pragmas copied from msvc.h in the core. |
| 22 | */ |
| 23 | #if defined(_MSC_VER) |
| 24 | #pragma warning(disable : 4054) |
| 25 | #pragma warning(disable : 4055) |
| 26 | #pragma warning(disable : 4100) |
| 27 | #pragma warning(disable : 4127) |
| 28 | #pragma warning(disable : 4130) |
| 29 | #pragma warning(disable : 4152) |
| 30 | #pragma warning(disable : 4189) |
| 31 | #pragma warning(disable : 4206) |
| 32 | #pragma warning(disable : 4210) |
| 33 | #pragma warning(disable : 4232) |
| 34 | #pragma warning(disable : 4244) |
| 35 | #pragma warning(disable : 4305) |
| 36 | #pragma warning(disable : 4306) |
| 37 | #pragma warning(disable : 4702) |
| 38 | #pragma warning(disable : 4706) |
| 39 | #endif /* defined(_MSC_VER) */ |
| 40 | |
| 41 | /* |
| 42 | ** No support for loadable extensions in VxWorks. |
| 43 | */ |
| 44 | #if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION |
| @@ -492,10 +506,22 @@ | |
| 506 | static int strlen30(const char *z){ |
| 507 | const char *z2 = z; |
| 508 | while( *z2 ){ z2++; } |
| 509 | return 0x3fffffff & (int)(z2 - z); |
| 510 | } |
| 511 | |
| 512 | /* |
| 513 | ** Return the length of a string in characters. Multibyte UTF8 characters |
| 514 | ** count as a single character. |
| 515 | */ |
| 516 | static int strlenChar(const char *z){ |
| 517 | int n = 0; |
| 518 | while( *z ){ |
| 519 | if( (0xc0&*(z++))!=0x80 ) n++; |
| 520 | } |
| 521 | return n; |
| 522 | } |
| 523 | |
| 524 | /* |
| 525 | ** This routine reads a line of text from FILE in, stores |
| 526 | ** the text in memory obtained from malloc() and returns a pointer |
| 527 | ** to the text. NULL is returned at end of file, or if malloc() |
| @@ -1156,16 +1182,71 @@ | |
| 1182 | for(i=0; i<p->nRate; i++){ |
| 1183 | p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; |
| 1184 | } |
| 1185 | return &p->u.x[p->nRate]; |
| 1186 | } |
| 1187 | |
| 1188 | /* |
| 1189 | ** SQL function: shell_add_schema(S,X) |
| 1190 | ** |
| 1191 | ** Add the schema name X to the CREATE statement in S and return the result. |
| 1192 | ** Examples: |
| 1193 | ** |
| 1194 | ** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x); |
| 1195 | ** |
| 1196 | ** Also works on |
| 1197 | ** |
| 1198 | ** CREATE INDEX |
| 1199 | ** CREATE UNIQUE INDEX |
| 1200 | ** CREATE VIEW |
| 1201 | ** CREATE TRIGGER |
| 1202 | ** CREATE VIRTUAL TABLE |
| 1203 | ** |
| 1204 | ** This UDF is used by the .schema command to insert the schema name of |
| 1205 | ** attached databases into the middle of the sqlite_master.sql field. |
| 1206 | */ |
| 1207 | static void shellAddSchemaName( |
| 1208 | sqlite3_context *pCtx, |
| 1209 | int nVal, |
| 1210 | sqlite3_value **apVal |
| 1211 | ){ |
| 1212 | static const char *aPrefix[] = { |
| 1213 | "TABLE", |
| 1214 | "INDEX", |
| 1215 | "UNIQUE INDEX", |
| 1216 | "VIEW", |
| 1217 | "TRIGGER", |
| 1218 | "VIRTUAL TABLE" |
| 1219 | }; |
| 1220 | int i = 0, n; |
| 1221 | const char *zIn = (const char*)sqlite3_value_text(apVal[0]); |
| 1222 | const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); |
| 1223 | assert( nVal==2 ); |
| 1224 | if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ |
| 1225 | for(i=0; i<sizeof(aPrefix)/sizeof(aPrefix[0]); i++){ |
| 1226 | int n = strlen30(aPrefix[i]); |
| 1227 | if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){ |
| 1228 | char cQuote = quoteChar(zSchema); |
| 1229 | char *z; |
| 1230 | if( cQuote ){ |
| 1231 | z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); |
| 1232 | }else{ |
| 1233 | z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); |
| 1234 | } |
| 1235 | sqlite3_result_text(pCtx, z, -1, sqlite3_free); |
| 1236 | return; |
| 1237 | } |
| 1238 | } |
| 1239 | } |
| 1240 | sqlite3_result_value(pCtx, apVal[0]); |
| 1241 | } |
| 1242 | |
| 1243 | /* |
| 1244 | ** Implementation of the sha3(X,SIZE) function. |
| 1245 | ** |
| 1246 | ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default |
| 1247 | ** size is 256. If X is a BLOB, it is hashed as is. |
| 1248 | ** For all other non-NULL types of input, X is converted into a UTF-8 string |
| 1249 | ** and the string is hashed without the trailing 0x00 terminator. The hash |
| 1250 | ** of a NULL value is NULL. |
| 1251 | */ |
| 1252 | static void sha3Func( |
| @@ -1901,13 +1982,13 @@ | |
| 1982 | w = colWidth[i]; |
| 1983 | }else{ |
| 1984 | w = 0; |
| 1985 | } |
| 1986 | if( w==0 ){ |
| 1987 | w = strlenChar(azCol[i] ? azCol[i] : ""); |
| 1988 | if( w<10 ) w = 10; |
| 1989 | n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue); |
| 1990 | if( w<n ) w = n; |
| 1991 | } |
| 1992 | if( i<ArraySize(p->actualWidth) ){ |
| 1993 | p->actualWidth[i] = w; |
| 1994 | } |
| @@ -1938,12 +2019,12 @@ | |
| 2019 | if( i<ArraySize(p->actualWidth) ){ |
| 2020 | w = p->actualWidth[i]; |
| 2021 | }else{ |
| 2022 | w = 10; |
| 2023 | } |
| 2024 | if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){ |
| 2025 | w = strlenChar(azArg[i]); |
| 2026 | } |
| 2027 | if( i==1 && p->aiIndent && p->pStmt ){ |
| 2028 | if( p->iIndent<p->nIndent ){ |
| 2029 | utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); |
| 2030 | } |
| @@ -2995,11 +3076,11 @@ | |
| 3076 | azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); |
| 3077 | if( sqlite3_column_int(pStmt, 5) ){ |
| 3078 | nPK++; |
| 3079 | if( nPK==1 |
| 3080 | && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), |
| 3081 | "INTEGER")==0 |
| 3082 | ){ |
| 3083 | isIPK = 1; |
| 3084 | }else{ |
| 3085 | isIPK = 0; |
| 3086 | } |
| @@ -3232,10 +3313,11 @@ | |
| 3313 | ".auth ON|OFF Show authorizer callbacks\n" |
| 3314 | #endif |
| 3315 | ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" |
| 3316 | ".bail on|off Stop after hitting an error. Default OFF\n" |
| 3317 | ".binary on|off Turn binary output on or off. Default OFF\n" |
| 3318 | ".cd DIRECTORY Change the working directory to DIRECTORY\n" |
| 3319 | ".changes on|off Show number of rows changed by SQL\n" |
| 3320 | ".check GLOB Fail if output since .testcase does not match\n" |
| 3321 | ".clone NEWDB Clone data into NEWDB from the existing database\n" |
| 3322 | ".databases List names and files of attached databases\n" |
| 3323 | ".dbinfo ?DB? Show status information about the database\n" |
| @@ -3277,12 +3359,12 @@ | |
| 3359 | " quote Escape answers as for SQL\n" |
| 3360 | " tabs Tab-separated values\n" |
| 3361 | " tcl TCL list elements\n" |
| 3362 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 3363 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 3364 | ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n" |
| 3365 | " The --new option starts with an empty file\n" |
| 3366 | ".output ?FILENAME? Send output to FILENAME or stdout\n" |
| 3367 | ".print STRING... Print literal STRING\n" |
| 3368 | ".prompt MAIN CONTINUE Replace the standard prompts\n" |
| 3369 | ".quit Exit this program\n" |
| 3370 | ".read FILENAME Execute SQL in FILENAME\n" |
| @@ -3343,12 +3425,12 @@ | |
| 3425 | /* Forward reference */ |
| 3426 | static int process_input(ShellState *p, FILE *in); |
| 3427 | |
| 3428 | /* |
| 3429 | ** Read the content of file zName into memory obtained from sqlite3_malloc64() |
| 3430 | ** and return a pointer to the buffer. The caller is responsible for freeing |
| 3431 | ** the memory. |
| 3432 | ** |
| 3433 | ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes |
| 3434 | ** read. |
| 3435 | ** |
| 3436 | ** For convenience, a nul-terminator byte is always appended to the data read |
| @@ -3507,10 +3589,13 @@ | |
| 3589 | sha3Func, 0, 0); |
| 3590 | sqlite3_create_function(p->db, "sha3_query", 1, SQLITE_UTF8, 0, |
| 3591 | sha3QueryFunc, 0, 0); |
| 3592 | sqlite3_create_function(p->db, "sha3_query", 2, SQLITE_UTF8, 0, |
| 3593 | sha3QueryFunc, 0, 0); |
| 3594 | sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0, |
| 3595 | shellAddSchemaName, 0, 0); |
| 3596 | |
| 3597 | } |
| 3598 | } |
| 3599 | |
| 3600 | /* |
| 3601 | ** Do C-language style dequoting. |
| @@ -4351,19 +4436,19 @@ | |
| 4436 | ** the child table name and the child column name. |
| 4437 | ** |
| 4438 | ** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col') |
| 4439 | ** |
| 4440 | ** If either of the named tables or columns do not exist, this function |
| 4441 | ** returns an empty string. An empty string is also returned if both tables |
| 4442 | ** and columns exist but have the same default collation sequence. Or, |
| 4443 | ** if both exist but the default collation sequences are different, this |
| 4444 | ** function returns the string " COLLATE <parent-collation>", where |
| 4445 | ** <parent-collation> is the default collation sequence of the parent column. |
| 4446 | */ |
| 4447 | static void shellFkeyCollateClause( |
| 4448 | sqlite3_context *pCtx, |
| 4449 | int nVal, |
| 4450 | sqlite3_value **apVal |
| 4451 | ){ |
| 4452 | sqlite3 *db = sqlite3_context_db_handle(pCtx); |
| 4453 | const char *zParent; |
| 4454 | const char *zParentCol; |
| @@ -4370,11 +4455,11 @@ | |
| 4455 | const char *zParentSeq; |
| 4456 | const char *zChild; |
| 4457 | const char *zChildCol; |
| 4458 | const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */ |
| 4459 | int rc; |
| 4460 | |
| 4461 | assert( nVal==4 ); |
| 4462 | zParent = (const char*)sqlite3_value_text(apVal[0]); |
| 4463 | zParentCol = (const char*)sqlite3_value_text(apVal[1]); |
| 4464 | zChild = (const char*)sqlite3_value_text(apVal[2]); |
| 4465 | zChildCol = (const char*)sqlite3_value_text(apVal[3]); |
| @@ -4492,11 +4577,11 @@ | |
| 4577 | azArg[0], azArg[1] |
| 4578 | ); |
| 4579 | return SQLITE_ERROR; |
| 4580 | } |
| 4581 | } |
| 4582 | |
| 4583 | /* Register the fkey_collate_clause() SQL function */ |
| 4584 | rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8, |
| 4585 | 0, shellFkeyCollateClause, 0, 0 |
| 4586 | ); |
| 4587 | |
| @@ -4535,23 +4620,23 @@ | |
| 4620 | |
| 4621 | if( res<0 ){ |
| 4622 | raw_printf(stderr, "Error: internal error"); |
| 4623 | break; |
| 4624 | }else{ |
| 4625 | if( bGroupByParent |
| 4626 | && (bVerbose || res==0) |
| 4627 | && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) |
| 4628 | ){ |
| 4629 | raw_printf(out, "-- Parent table %s\n", zParent); |
| 4630 | sqlite3_free(zPrev); |
| 4631 | zPrev = sqlite3_mprintf("%s", zParent); |
| 4632 | } |
| 4633 | |
| 4634 | if( res==0 ){ |
| 4635 | raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); |
| 4636 | }else if( bVerbose ){ |
| 4637 | raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n", |
| 4638 | zIndent, zFrom, zTarget |
| 4639 | ); |
| 4640 | } |
| 4641 | } |
| 4642 | } |
| @@ -4728,10 +4813,29 @@ | |
| 4813 | }else{ |
| 4814 | raw_printf(stderr, "Usage: .binary on|off\n"); |
| 4815 | rc = 1; |
| 4816 | } |
| 4817 | }else |
| 4818 | |
| 4819 | if( c=='c' && strcmp(azArg[0],"cd")==0 ){ |
| 4820 | if( nArg==2 ){ |
| 4821 | #if defined(_WIN32) || defined(WIN32) |
| 4822 | wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]); |
| 4823 | rc = !SetCurrentDirectoryW(z); |
| 4824 | sqlite3_free(z); |
| 4825 | #else |
| 4826 | rc = chdir(azArg[1]); |
| 4827 | #endif |
| 4828 | if( rc ){ |
| 4829 | utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]); |
| 4830 | rc = 1; |
| 4831 | } |
| 4832 | }else{ |
| 4833 | raw_printf(stderr, "Usage: .cd DIRECTORY\n"); |
| 4834 | rc = 1; |
| 4835 | } |
| 4836 | }else |
| 4837 | |
| 4838 | /* The undocumented ".breakpoint" command causes a call to the no-op |
| 4839 | ** routine named test_breakpoint(). |
| 4840 | */ |
| 4841 | if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ |
| @@ -5641,16 +5745,21 @@ | |
| 5745 | rc = 1; |
| 5746 | } |
| 5747 | }else |
| 5748 | |
| 5749 | if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ |
| 5750 | ShellText sSelect; |
| 5751 | ShellState data; |
| 5752 | char *zErrMsg = 0; |
| 5753 | const char *zDiv = 0; |
| 5754 | int iSchema = 0; |
| 5755 | |
| 5756 | open_db(p, 0); |
| 5757 | memcpy(&data, p, sizeof(data)); |
| 5758 | data.showHeader = 0; |
| 5759 | data.cMode = data.mode = MODE_Semi; |
| 5760 | initText(&sSelect); |
| 5761 | if( nArg>=2 && optionMatch(azArg[1], "indent") ){ |
| 5762 | data.cMode = data.mode = MODE_Pretty; |
| 5763 | nArg--; |
| 5764 | if( nArg==2 ) azArg[1] = azArg[2]; |
| 5765 | } |
| @@ -5684,37 +5793,66 @@ | |
| 5793 | new_colv[0] = "sql"; |
| 5794 | new_colv[1] = 0; |
| 5795 | callback(&data, 1, new_argv, new_colv); |
| 5796 | rc = SQLITE_OK; |
| 5797 | }else{ |
| 5798 | zDiv = "("; |
| 5799 | } |
| 5800 | }else if( nArg==1 ){ |
| 5801 | zDiv = "("; |
| 5802 | }else{ |
| 5803 | raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); |
| 5804 | rc = 1; |
| 5805 | goto meta_command_exit; |
| 5806 | } |
| 5807 | if( zDiv ){ |
| 5808 | sqlite3_stmt *pStmt = 0; |
| 5809 | sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list", |
| 5810 | -1, &pStmt, 0); |
| 5811 | appendText(&sSelect, "SELECT sql FROM", 0); |
| 5812 | iSchema = 0; |
| 5813 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 5814 | const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); |
| 5815 | char zScNum[30]; |
| 5816 | sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); |
| 5817 | appendText(&sSelect, zDiv, 0); |
| 5818 | zDiv = " UNION ALL "; |
| 5819 | if( strcmp(zDb, "main")!=0 ){ |
| 5820 | appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); |
| 5821 | appendText(&sSelect, sqlite3_column_text(pStmt, 0), '"'); |
| 5822 | appendText(&sSelect, ") AS sql, type, tbl_name, name, rowid,", 0); |
| 5823 | appendText(&sSelect, zScNum, 0); |
| 5824 | appendText(&sSelect, " AS snum, ", 0); |
| 5825 | appendText(&sSelect, zDb, '\''); |
| 5826 | appendText(&sSelect, " AS sname FROM ", 0); |
| 5827 | appendText(&sSelect, sqlite3_column_text(pStmt, 0), '"'); |
| 5828 | appendText(&sSelect, ".sqlite_master", 0); |
| 5829 | }else{ |
| 5830 | appendText(&sSelect, "SELECT sql, type, tbl_name, name, rowid, ", 0); |
| 5831 | appendText(&sSelect, zScNum, 0); |
| 5832 | appendText(&sSelect, " AS snum, 'main' AS sname FROM sqlite_master",0); |
| 5833 | } |
| 5834 | } |
| 5835 | sqlite3_finalize(pStmt); |
| 5836 | appendText(&sSelect, ") WHERE ", 0); |
| 5837 | if( nArg>1 ){ |
| 5838 | char *zQarg = sqlite3_mprintf("%Q", azArg[1]); |
| 5839 | if( strchr(azArg[1], '.') ){ |
| 5840 | appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); |
| 5841 | }else{ |
| 5842 | appendText(&sSelect, "lower(tbl_name)", 0); |
| 5843 | } |
| 5844 | appendText(&sSelect, strchr(azArg[1], '*') ? " GLOB " : " LIKE ", 0); |
| 5845 | appendText(&sSelect, zQarg, 0); |
| 5846 | appendText(&sSelect, " AND ", 0); |
| 5847 | sqlite3_free(zQarg); |
| 5848 | } |
| 5849 | appendText(&sSelect, "type!='meta' AND sql IS NOT NULL" |
| 5850 | " ORDER BY snum, rowid", 0); |
| 5851 | rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); |
| 5852 | freeText(&sSelect); |
| 5853 | } |
| 5854 | if( zErrMsg ){ |
| 5855 | utf8_printf(stderr,"Error: %s\n", zErrMsg); |
| 5856 | sqlite3_free(zErrMsg); |
| 5857 | rc = 1; |
| 5858 | }else if( rc != SQLITE_OK ){ |
| @@ -5952,23 +6090,15 @@ | |
| 6090 | |
| 6091 | if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){ |
| 6092 | int bIsInit = 0; /* True to initialize the SELFTEST table */ |
| 6093 | int bVerbose = 0; /* Verbose output */ |
| 6094 | int bSelftestExists; /* True if SELFTEST already exists */ |
| 6095 | int i, k; /* Loop counters */ |
| 6096 | int nTest = 0; /* Number of tests runs */ |
| 6097 | int nErr = 0; /* Number of errors seen */ |
| 6098 | ShellText str; /* Answer for a query */ |
| 6099 | sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */ |
| 6100 | |
| 6101 | open_db(p,0); |
| 6102 | for(i=1; i<nArg; i++){ |
| 6103 | const char *z = azArg[i]; |
| 6104 | if( z[0]=='-' && z[1]=='-' ) z++; |
| @@ -5994,74 +6124,75 @@ | |
| 6124 | } |
| 6125 | if( bIsInit ){ |
| 6126 | createSelftestTable(p); |
| 6127 | bSelftestExists = 1; |
| 6128 | } |
| 6129 | initText(&str); |
| 6130 | appendText(&str, "x", 0); |
| 6131 | for(k=bSelftestExists; k>=0; k--){ |
| 6132 | if( k==1 ){ |
| 6133 | rc = sqlite3_prepare_v2(p->db, |
| 6134 | "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", |
| 6135 | -1, &pStmt, 0); |
| 6136 | }else{ |
| 6137 | rc = sqlite3_prepare_v2(p->db, |
| 6138 | "VALUES(0,'memo','Missing SELFTEST table - default checks only','')," |
| 6139 | " (1,'run','PRAGMA integrity_check','ok')", |
| 6140 | -1, &pStmt, 0); |
| 6141 | } |
| 6142 | if( rc ){ |
| 6143 | raw_printf(stderr, "Error querying the selftest table\n"); |
| 6144 | rc = 1; |
| 6145 | sqlite3_finalize(pStmt); |
| 6146 | goto meta_command_exit; |
| 6147 | } |
| 6148 | for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){ |
| 6149 | int tno = sqlite3_column_int(pStmt, 0); |
| 6150 | const char *zOp = (const char*)sqlite3_column_text(pStmt, 1); |
| 6151 | const char *zSql = (const char*)sqlite3_column_text(pStmt, 2); |
| 6152 | const char *zAns = (const char*)sqlite3_column_text(pStmt, 3); |
| 6153 | |
| 6154 | k = 0; |
| 6155 | if( bVerbose>0 ){ |
| 6156 | char *zQuote = sqlite3_mprintf("%q", zSql); |
| 6157 | printf("%d: %s %s\n", tno, zOp, zSql); |
| 6158 | sqlite3_free(zQuote); |
| 6159 | } |
| 6160 | if( strcmp(zOp,"memo")==0 ){ |
| 6161 | utf8_printf(p->out, "%s\n", zSql); |
| 6162 | }else |
| 6163 | if( strcmp(zOp,"run")==0 ){ |
| 6164 | char *zErrMsg = 0; |
| 6165 | str.n = 0; |
| 6166 | str.z[0] = 0; |
| 6167 | rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); |
| 6168 | nTest++; |
| 6169 | if( bVerbose ){ |
| 6170 | utf8_printf(p->out, "Result: %s\n", str.z); |
| 6171 | } |
| 6172 | if( rc || zErrMsg ){ |
| 6173 | nErr++; |
| 6174 | rc = 1; |
| 6175 | utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); |
| 6176 | sqlite3_free(zErrMsg); |
| 6177 | }else if( strcmp(zAns,str.z)!=0 ){ |
| 6178 | nErr++; |
| 6179 | rc = 1; |
| 6180 | utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); |
| 6181 | utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); |
| 6182 | } |
| 6183 | }else |
| 6184 | { |
| 6185 | utf8_printf(stderr, |
| 6186 | "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); |
| 6187 | rc = 1; |
| 6188 | break; |
| 6189 | } |
| 6190 | } /* End loop over rows of content from SELFTEST */ |
| 6191 | sqlite3_finalize(pStmt); |
| 6192 | } /* End loop over k */ |
| 6193 | freeText(&str); |
| 6194 | utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); |
| 6195 | }else |
| 6196 | |
| 6197 | if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ |
| 6198 | if( nArg<2 || nArg>3 ){ |
| @@ -6097,12 +6228,12 @@ | |
| 6228 | z++; |
| 6229 | if( z[0]=='-' ) z++; |
| 6230 | if( strcmp(z,"schema")==0 ){ |
| 6231 | bSchema = 1; |
| 6232 | }else |
| 6233 | if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0 |
| 6234 | || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0 |
| 6235 | ){ |
| 6236 | iSize = atoi(&z[5]); |
| 6237 | }else |
| 6238 | if( strcmp(z,"debug")==0 ){ |
| 6239 | bDebug = 1; |
| @@ -6266,63 +6397,51 @@ | |
| 6397 | || strncmp(azArg[0], "indexes", n)==0) ) |
| 6398 | ){ |
| 6399 | sqlite3_stmt *pStmt; |
| 6400 | char **azResult; |
| 6401 | int nRow, nAlloc; |
| 6402 | int ii; |
| 6403 | ShellText s; |
| 6404 | initText(&s); |
| 6405 | open_db(p, 0); |
| 6406 | rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); |
| 6407 | if( rc ) return shellDatabaseError(p->db); |
| 6408 | |
| 6409 | if( nArg>2 && c=='i' ){ |
| 6410 | /* It is an historical accident that the .indexes command shows an error |
| 6411 | ** when called with the wrong number of arguments whereas the .tables |
| 6412 | ** command does not. */ |
| 6413 | raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); |
| 6414 | rc = 1; |
| 6415 | goto meta_command_exit; |
| 6416 | } |
| 6417 | for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ |
| 6418 | const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); |
| 6419 | if( zDbName==0 ) continue; |
| 6420 | if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0); |
| 6421 | if( sqlite3_stricmp(zDbName, "main")==0 ){ |
| 6422 | appendText(&s, "SELECT name FROM ", 0); |
| 6423 | }else{ |
| 6424 | appendText(&s, "SELECT ", 0); |
| 6425 | appendText(&s, zDbName, '\''); |
| 6426 | appendText(&s, "||'.'||name FROM ", 0); |
| 6427 | } |
| 6428 | appendText(&s, zDbName, '"'); |
| 6429 | appendText(&s, ".sqlite_master ", 0); |
| 6430 | if( c=='t' ){ |
| 6431 | appendText(&s," WHERE type IN ('table','view')" |
| 6432 | " AND name NOT LIKE 'sqlite_%'" |
| 6433 | " AND name LIKE ?1", 0); |
| 6434 | }else{ |
| 6435 | appendText(&s," WHERE type='index'" |
| 6436 | " AND tbl_name LIKE ?1", 0); |
| 6437 | } |
| 6438 | } |
| 6439 | rc = sqlite3_finalize(pStmt); |
| 6440 | appendText(&s, " ORDER BY 1", 0); |
| 6441 | rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0); |
| 6442 | freeText(&s); |
| 6443 | if( rc ) return shellDatabaseError(p->db); |
| 6444 | |
| 6445 | /* Run the SQL statement prepared by the above block. Store the results |
| 6446 | ** as an array of nul-terminated strings in azResult[]. */ |
| 6447 | nRow = nAlloc = 0; |
| 6448 |