From: drh Date: Thu, 15 Jun 2017 12:21:09 +0000 (+0000) Subject: In the command-line shell, enhance the ".schema" command show that it X-Git-Tag: version-3.20.0~197 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=20c9c3f4ebe8f83a1e2ee4c81ea58a81ff7c6e7f;p=thirdparty%2Fsqlite.git In the command-line shell, enhance the ".schema" command show that it shows the schema for ATTACH-ed databases in addition to "main". FossilOrigin-Name: 48e086284a76da10a85315bc992e2294bd4711e35ec5a5abaa16e39a6a69d206 --- diff --git a/manifest b/manifest index 0c507aca09..3f17a44ce2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\ssqlite3_analyzer.exe\sutility\sso\sthat\sit\scomputes\sand\sshows\sthe\nnumber\sof\sbytes\sof\smetadata\son\sbtree\spages\sand\sper\stable\sand\sindex\sentry. -D 2017-06-15T00:52:03.263 +C In\sthe\scommand-line\sshell,\senhance\sthe\s".schema"\scommand\sshow\sthat\sit\nshows\sthe\sschema\sfor\sATTACH-ed\sdatabases\sin\saddition\sto\s"main". +D 2017-06-15T12:21:09.255 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 8eeb80162074004e906b53d7340a12a14c471a83743aab975947e95ce061efcc @@ -406,7 +406,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c adf3ef9843135b1383321ad751f16f5a40c3f37925154555a3e61653d2a954e8 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 0d2afdbdba5fbc61432c5454a35e0236e7aa4aa3756986a7d51b81a508e8083a -F src/shell.c a43292634af8e3528fec5c6e3360f122fc807a0af619d566ea44fdb98dcfca78 +F src/shell.c 41671b1b9cfed9d1686699ae91ce6ee6e2a8cac5d148a99e2a363a209c549ad8 F src/sqlite.h.in 67fa8bd29808e7988e0ce36c8d4c6043eb1727f94522fc612687aa5af51931e6 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28 @@ -1582,7 +1582,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c433672dd8ab625628bde2f4f40a2dc000ed915dbe91833d3f753d8ab51baf25 -R 3118b76870f7c5e12e646d6dc51a9560 +P 43ad41efa9e1fdd79a9804197a227491236495f14ed56c656224d6ce181703c1 +R d9f0817a6699b9c8517903bc72312e9f U drh -Z 30d19856ae4fa68d439f06a24db9ac5d +Z 79d9a69908657f1d338372f7df43a962 diff --git a/manifest.uuid b/manifest.uuid index a8b314a01d..533cc2e1a1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -43ad41efa9e1fdd79a9804197a227491236495f14ed56c656224d6ce181703c1 \ No newline at end of file +48e086284a76da10a85315bc992e2294bd4711e35ec5a5abaa16e39a6a69d206 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 36f6970d1f..706d3ada68 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1185,6 +1185,61 @@ static unsigned char *SHA3Final(SHA3Context *p){ return &p->u.x[p->nRate]; } +/* +** SQL function: shell_add_schema(S,X) +** +** Add the schema name X to the CREATE statement in S and return the result. +** Examples: +** +** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x); +** +** Also works on +** +** CREATE INDEX +** CREATE UNIQUE INDEX +** CREATE VIEW +** CREATE TRIGGER +** CREATE VIRTUAL TABLE +** +** This UDF is used by the .schema command to insert the schema name of +** attached databases into the middle of the sqlite_master.sql field. +*/ +static void shellAddSchemaName( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + static const char *aPrefix[] = { + "TABLE", + "INDEX", + "UNIQUE INDEX", + "VIEW", + "TRIGGER", + "VIRTUAL TABLE" + }; + int i = 0, n; + const char *zIn = (const char*)sqlite3_value_text(apVal[0]); + const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); + assert( nVal==2 ); + if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ + for(i=0; idb, "sha3_query", 2, SQLITE_UTF8, 0, sha3QueryFunc, 0, 0); + sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0, + shellAddSchemaName, 0, 0); + } } @@ -5689,12 +5747,17 @@ static int do_meta_command(char *zLine, ShellState *p){ }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ + ShellText sSelect; ShellState data; char *zErrMsg = 0; + const char *zDiv = 0; + int iSchema = 0; + open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.cMode = data.mode = MODE_Semi; + initText(&sSelect); if( nArg>=2 && optionMatch(azArg[1], "indent") ){ data.cMode = data.mode = MODE_Pretty; nArg--; @@ -5732,33 +5795,62 @@ static int do_meta_command(char *zLine, ShellState *p){ callback(&data, 1, new_argv, new_colv); rc = SQLITE_OK; }else{ - char *zSql; - zSql = sqlite3_mprintf( - "SELECT sql FROM " - " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" - " FROM sqlite_master UNION ALL" - " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " - "WHERE lower(tbl_name) LIKE %Q" - " AND type!='meta' AND sql NOTNULL " - "ORDER BY rowid", azArg[1]); - rc = sqlite3_exec(p->db, zSql, callback, &data, &zErrMsg); - sqlite3_free(zSql); + zDiv = "("; } }else if( nArg==1 ){ - rc = sqlite3_exec(p->db, - "SELECT sql FROM " - " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" - " FROM sqlite_master UNION ALL" - " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " - "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " - "ORDER BY rowid", - callback, &data, &zErrMsg - ); + zDiv = "("; }else{ raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; } + if( zDiv ){ + sqlite3_stmt *pStmt = 0; + sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list", + -1, &pStmt, 0); + appendText(&sSelect, "SELECT sql FROM", 0); + iSchema = 0; + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); + char zScNum[30]; + sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); + appendText(&sSelect, zDiv, 0); + zDiv = " UNION ALL "; + if( strcmp(zDb, "main")!=0 ){ + appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); + appendText(&sSelect, sqlite3_column_text(pStmt, 0), '"'); + appendText(&sSelect, ") AS sql, type, tbl_name, name, rowid,", 0); + appendText(&sSelect, zScNum, 0); + appendText(&sSelect, " AS snum, ", 0); + appendText(&sSelect, zDb, '\''); + appendText(&sSelect, " AS sname FROM ", 0); + appendText(&sSelect, sqlite3_column_text(pStmt, 0), '"'); + appendText(&sSelect, ".sqlite_master", 0); + }else{ + appendText(&sSelect, "SELECT sql, type, tbl_name, name, rowid, ", 0); + appendText(&sSelect, zScNum, 0); + appendText(&sSelect, " AS snum, 'main' AS sname FROM sqlite_master",0); + } + } + sqlite3_finalize(pStmt); + appendText(&sSelect, ") WHERE ", 0); + if( nArg>1 ){ + char *zQarg = sqlite3_mprintf("%Q", azArg[1]); + if( strchr(azArg[1], '.') ){ + appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); + }else{ + appendText(&sSelect, "lower(tbl_name)", 0); + } + appendText(&sSelect, strchr(azArg[1], '*') ? " GLOB " : " LIKE ", 0); + appendText(&sSelect, zQarg, 0); + appendText(&sSelect, " AND ", 0); + sqlite3_free(zQarg); + } + appendText(&sSelect, "type!='meta' AND sql IS NOT NULL" + " ORDER BY snum, rowid", 0); + rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); + freeText(&sSelect); + } if( zErrMsg ){ utf8_printf(stderr,"Error: %s\n", zErrMsg); sqlite3_free(zErrMsg);