From 8402a9a1adc1422322417d4d139002aed329eeee Mon Sep 17 00:00:00 2001 From: "D. Richard Hipp" Date: Mon, 1 Jan 2018 21:28:25 +0000 Subject: [PATCH] In the output of ".schema", show the column names of virtual tables and views in a separate comment. --- src/shell.c.in | 127 ++++++++++++++++++++++++++++++++++++------------------ test/pragma5.test | 2 +- test/shell1.test | 6 ++- 3 files changed, 90 insertions(+), 45 deletions(-) diff --git a/src/shell.c.in b/src/shell.c.in index 7b994336ea..a1e4362f58 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -730,6 +730,33 @@ static char quoteChar(const char *zName){ } /* +** Construct a fake CREATE TABLE statement (or at least the part that comes +** after the "CREATE TABLE" keywords) that describes the columns of +** the view, virtual table, or table valued function zName in zSchema. +*/ +static char *shellFakeCrTab( + sqlite3 *db, /* The database connection containing the vtab */ + const char *zSchema, /* Schema of the database holding the vtab */ + const char *zName /* The name of the virtual table */ +){ + sqlite3_stmt *pStmt = 0; + char *zSql; + char *z = 0; + + zSql = sqlite3_mprintf("SELECT group_concat(name,',')" + " FROM pragma_table_info(%Q,%Q);", + zName, zSchema); + sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + z = sqlite3_mprintf("/* %s.%s(%s) */", + zSchema ? zSchema : "main", zName, sqlite3_column_text(pStmt, 0)); + } + sqlite3_finalize(pStmt); + return z; +} + +/* ** SQL function: shell_add_schema(S,X) ** ** Add the schema name X to the CREATE statement in S and return the result. @@ -764,20 +791,29 @@ static void shellAddSchemaName( int i = 0; const char *zIn = (const char*)sqlite3_value_text(apVal[0]); const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); - assert( nVal==2 ); + sqlite3 *db = sqlite3_context_db_handle(pCtx); if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){ int n = strlen30(aPrefix[i]); if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){ - char cQuote = quoteChar(zSchema); - char *z; - if( cQuote ){ - z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); - }else{ - z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); + char *z = 0; + if( zSchema ){ + char cQuote = quoteChar(zSchema); + if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){ + z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); + }else{ + z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); + } + } + if( aPrefix[i][0]=='V' ){ + const char *zName = (const char*)sqlite3_value_text(apVal[2]); + if( z==0 ) z = sqlite3_mprintf("%s", zIn); + z = sqlite3_mprintf("%z\n%z", z, shellFakeCrTab(db, zSchema, zName)); + } + if( z ){ + sqlite3_result_text(pCtx, z, -1, sqlite3_free); + return; } - sqlite3_result_text(pCtx, z, -1, sqlite3_free); - return; } } } @@ -2998,7 +3034,7 @@ static void open_db(ShellState *p, int keepAlive){ sqlite3_fileio_init(p->db, 0, 0); sqlite3_shathree_init(p->db, 0, 0); sqlite3_completion_init(p->db, 0, 0); - sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0, + sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, shellAddSchemaName, 0, 0); } } @@ -5319,23 +5355,32 @@ static int do_meta_command(char *zLine, ShellState *p){ ShellState data; char *zErrMsg = 0; const char *zDiv = 0; + const char *zName = 0; int iSchema = 0; + int bDebug = 0; + int ii; 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--; - if( nArg==2 ) azArg[1] = azArg[2]; + for(ii=1; ii1 ){ - char *zQarg = sqlite3_mprintf("%Q", azArg[1]); - if( strchr(azArg[1], '.') ){ + if( zName ){ + char *zQarg = sqlite3_mprintf("%Q", zName); + if( strchr(zName, '.') ){ 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, strchr(zName, '*') ? " 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); + if( bDebug ){ + utf8_printf(p->out, "SQL: %s;\n", sSelect.z); + }else{ + rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); + } freeText(&sSelect); } if( zErrMsg ){ diff --git a/test/pragma5.test b/test/pragma5.test index 625ab92012..d2c58000cf 100644 --- a/test/pragma5.test +++ b/test/pragma5.test @@ -34,7 +34,7 @@ do_execsql_test 1.0 { 1 builtin {} 0 {} 0 } do_execsql_test 1.1 { - SELECT * FROM pragma_function_list WHERE name='upper' + SELECT * FROM pragma_function_list WHERE name='upper' AND builtin } {upper 1} do_execsql_test 1.2 { SELECT * FROM pragma_function_list WHERE name LIKE 'exter%'; diff --git a/test/shell1.test b/test/shell1.test index ddd72c7180..c2f39435b8 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -581,8 +581,10 @@ do_test shell1-3.21.4 { } catchcmd "test.db" ".schema" } {0 {CREATE TABLE t1(x); -CREATE VIEW v2 AS SELECT x+1 AS y FROM t1; -CREATE VIEW v1 AS SELECT y+1 FROM v2;}} +CREATE VIEW v2 AS SELECT x+1 AS y FROM t1 +/* main.v2(y) */; +CREATE VIEW v1 AS SELECT y+1 FROM v2 +/* main.v1(y+1) */;}} db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;} } -- 2.11.4.GIT