diff --git a/manifest b/manifest index be0eda8fcc..2cc6986f5f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\san\sinfinite\sloop\sin\sfts3/4\sincremental-merge\sin\sthe\scase\swhere\sthe\slowest\slevel\sin\sthe\sdatabase\scontains\ssegments\sbut\sno\sdata\s(because\sthere\sis\sa\sdelete-marker\sfor\seach\svalid\sentry).\sFix\sfor\s[bf1aab89]. -D 2019-10-17T15:41:36.813 +C Enhance\sthe\s".imposter"\scommand\sin\sthe\sCLI\sso\sthat\sthe\sfirst\sargument\ncan\sbe\san\sexisting\sWITHOUT\sROWID\stable\sinstead\sof\san\sindex.\s\sThe\sresulting\nimposter\sis\sthe\ssame\stable,\sbut\swith\scolumns\sin\sstorage\sorder\sand\swith\nall\sconstraints\sremoved. +D 2019-10-18T15:58:50.284 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -526,7 +526,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c e021be0c1c4a2125fa38aabcd8dbb764bf5b2c889a948c30d3708430ec6ccd00 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c 7ef05eeb7f686f84dd1428cbdca280c898915bbf56e1ea97bd42ecc070af78d3 -F src/shell.c.in d70bcf630c4073eaa994fa74be98886c781918e794cb8b562be8df10f018e274 +F src/shell.c.in 3093bdf5eedd91da08f0268f1442aa510a60798c9441868149ddbecdf8bcaa79 F src/sqlite.h.in 5725a6b20190a1e8d662077a1c1c8ea889ad7be90dd803f914c2de226f5fe6ab F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h cef696ce3293242c67b2339763608427bf72ee66f1f3a05389ac2a7b46001c31 @@ -1847,7 +1847,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 bba975c7af3de9aeb5c62fb8b05d61b96e4ecd0b030008442bbdd345e1e5f134 -R c0ee123c55e0634eada3c2d56906af99 -U dan -Z 5c41036d47f05063f5938d5d5c2f4f4a +P 35beaee059a6cccead4311886ca928d936f23584cf435e35e265e98feea723dc +R 79321ef818ef0b98008c7f3041b73ac3 +U drh +Z 758d9d25f4ac17fe1f5333a4da39c6af diff --git a/manifest.uuid b/manifest.uuid index 076e023d3b..c818b549f5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -35beaee059a6cccead4311886ca928d936f23584cf435e35e265e98feea723dc \ No newline at end of file +9dc0d34586eebf6705d9bd81494c417ac76707b8625d1ff99eda18b4ca2d8a50 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 7f82675e35..f2473ce155 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -7758,10 +7758,19 @@ static int do_meta_command(char *zLine, ShellState *p){ char *zCollist = 0; sqlite3_stmt *pStmt; int tnum = 0; + int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */ + int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */ int i; if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" " .imposter off\n"); + /* Also allowed, but not documented: + ** + ** .imposter TABLE IMPOSTER + ** + ** where TABLE is a WITHOUT ROWID table. In that case, the + ** imposter is another WITHOUT ROWID table with the columns in + ** storage order. */ rc = 1; goto meta_command_exit; } @@ -7770,19 +7779,22 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); goto meta_command_exit; } - zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master" - " WHERE name='%q' AND type='index'", azArg[1]); + zSql = sqlite3_mprintf( + "SELECT rootpage, 0 FROM sqlite_master" + " WHERE name='%q' AND type='index'" + "UNION ALL " + "SELECT rootpage, 1 FROM sqlite_master" + " WHERE name='%q' AND type='table'" + " AND sql LIKE '%%without%%rowid%%'", + azArg[1], azArg[1] + ); sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( sqlite3_step(pStmt)==SQLITE_ROW ){ tnum = sqlite3_column_int(pStmt, 0); + isWO = sqlite3_column_int(pStmt, 1); } sqlite3_finalize(pStmt); - if( tnum==0 ){ - utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); - rc = 1; - goto meta_command_exit; - } zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); @@ -7799,6 +7811,9 @@ static int do_meta_command(char *zLine, ShellState *p){ zCol = zLabel; } } + if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){ + lenPK = (int)strlen(zCollist); + } if( zCollist==0 ){ zCollist = sqlite3_mprintf("\"%w\"", zCol); }else{ @@ -7806,9 +7821,16 @@ static int do_meta_command(char *zLine, ShellState *p){ } } sqlite3_finalize(pStmt); + if( i==0 || tnum==0 ){ + utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); + rc = 1; + sqlite3_free(zCollist); + goto meta_command_exit; + } + if( lenPK==0 ) lenPK = 100000; zSql = sqlite3_mprintf( - "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID", - azArg[2], zCollist, zCollist); + "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID", + azArg[2], zCollist, lenPK, zCollist); sqlite3_free(zCollist); rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum); if( rc==SQLITE_OK ){ @@ -7819,7 +7841,8 @@ static int do_meta_command(char *zLine, ShellState *p){ }else{ utf8_printf(stdout, "%s;\n", zSql); raw_printf(stdout, - "WARNING: writing to an imposter table will corrupt the index!\n" + "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n", + azArg[1], isWO ? "table" : "index" ); } }else{