1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

CLI's .import column rename made more minimal, and reports renames.

FossilOrigin-Name: c626cff7f99ec502ebd46f9cdafc3d088697544ef5d6559b6b3ae85679b4f9fa
This commit is contained in:
larrybr
2022-02-14 01:12:46 +00:00
parent 42de1c52dd
commit 3363386145
4 changed files with 98 additions and 32 deletions

View File

@ -1,5 +1,5 @@
C Sync\sw/trunk,\sfix\szAutoColumns\splacement\sblunder,\sall\sto\spass\sall\sTCL\stests C CLI's\s.import\scolumn\srename\smade\smore\sminimal,\sand\sreports\srenames.
D 2022-02-13T22:18:22.163 D 2022-02-14T01:12:46.316
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -553,7 +553,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c 3baa9dd8cf240654773c7974e2bcce398ac9dd24419c36684156963defe43b35 F src/select.c 3baa9dd8cf240654773c7974e2bcce398ac9dd24419c36684156963defe43b35
F src/shell.c.in 233a5c7f0ee9a9d1b88f1caed538d813390bb474082d9d74504d846ccb49f31e x F src/shell.c.in 1289a2e10f48e75956700f61aac63beff7f05988ac7a4c701800b9f0e9adad4e x
F src/sqlite.h.in 7047c4b60fa550264d6363bb1d983540e7828fb19d2d1e5aa43b52ca13144807 F src/sqlite.h.in 7047c4b60fa550264d6363bb1d983540e7828fb19d2d1e5aa43b52ca13144807
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6 F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6
@ -1392,7 +1392,7 @@ F test/shell1.test b224e0793c5f48aa3749e65d8c64b93a30731bd206f2e41e6c5f1bee1bdb1
F test/shell2.test 89e4b2db062d52baed75022227b462d085cff495809de1699652779d8e0257d6 F test/shell2.test 89e4b2db062d52baed75022227b462d085cff495809de1699652779d8e0257d6
F test/shell3.test a50628ab1d78d90889d9d3f32fb2c084ee15674771e96afe954aaa0accd1de3c F test/shell3.test a50628ab1d78d90889d9d3f32fb2c084ee15674771e96afe954aaa0accd1de3c
F test/shell4.test 8f6c0fce4abed19a8a7f7262517149812a04caa905d01bdc8f5e92573504b759 F test/shell4.test 8f6c0fce4abed19a8a7f7262517149812a04caa905d01bdc8f5e92573504b759
F test/shell5.test 1be5454b8376e363f99cd0947ab43e1121e5b802c067d1fe7089e3461de1421d x F test/shell5.test 3be444397eb1e91619ce289a6216a8df9ac690cc45d5e9595f60e750a944161f x
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3 F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae
@ -1944,8 +1944,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 433e5ead2b711d1e3b0b62cf8cb5a8a65e2474c68ef2173317ed4323fc8bdc58 bf8dbfd499e732f14c7a8efee527e8ce155937dbb2a3e85213f8aa64ac497189 P 67dc59f46d742ad69742fb34540a3074af163a3f1a0f9093f83db2276bf944ca
R d0a4f648a76dcc064c4b8040fefbc80a R ef7ea611e7a4e14ff938dd85400a84e0
U larrybr U larrybr
Z 9500253e6d614600afa73cc694266a23 Z 0a705a46f17a261142cf326cb58d0cbc
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
67dc59f46d742ad69742fb34540a3074af163a3f1a0f9093f83db2276bf944ca c626cff7f99ec502ebd46f9cdafc3d088697544ef5d6559b6b3ae85679b4f9fa

View File

@ -7830,8 +7830,9 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
* (a) The db was not initialized and zCol==0 (There are no columns.) * (a) The db was not initialized and zCol==0 (There are no columns.)
* (b) zCol!=0 (Column was added, db initialized as needed.) * (b) zCol!=0 (Column was added, db initialized as needed.)
* The 3rd argument, pRenamed, references an out parameter. If the * The 3rd argument, pRenamed, references an out parameter. If the
* pointer is non-zero, its referent will be set to 1 if renaming was * pointer is non-zero, its referent will be set to a summary of renames
* necessary, or set to 0 if none was done. * done if renaming was necessary, or set to 0 if none was done. The out
* string (if any) must be sqlite3_free()'ed by the caller.
*/ */
#ifdef SHELL_DEBUG #ifdef SHELL_DEBUG
#define rc_err_oom_die(rc) \ #define rc_err_oom_die(rc) \
@ -7862,12 +7863,17 @@ static const char *zCOL_DB = ":memory:";
# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP) # define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP)
#endif #endif
static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, int *pRenamed){ static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){
/* Queries and D{D,M}L used here */ /* Queries and D{D,M}L used here */
static const char * const zTabMake = "\ static const char * const zTabMake = "\
CREATE TABLE ColNames(\ CREATE TABLE ColNames(\
cpos INTEGER PRIMARY KEY,\ cpos INTEGER PRIMARY KEY,\
name TEXT, nlen INT, chop INT, reps INT, suff TEXT)\ name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\
CREATE VIEW RepeatedNames AS \
SELECT DISTINCT t.name FROM ColNames t \
WHERE t.name COLLATE NOCASE IN (\
SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\
);\
"; ";
static const char * const zTabFill = "\ static const char * const zTabFill = "\
INSERT INTO ColNames(name,nlen,chop,reps,suff)\ INSERT INTO ColNames(name,nlen,chop,reps,suff)\
@ -7877,6 +7883,7 @@ INSERT INTO ColNames(name,nlen,chop,reps,suff)\
SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\ SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\
<count(name) FROM ColNames\ <count(name) FROM ColNames\
"; ";
#ifdef SHELL_COLUMN_RENAME_CLEAN
static const char * const zDedoctor = "\ static const char * const zDedoctor = "\
UPDATE ColNames SET chop=iif(\ UPDATE ColNames SET chop=iif(\
(substring(name,nlen,1) BETWEEN '0' AND '9')\ (substring(name,nlen,1) BETWEEN '0' AND '9')\
@ -7885,6 +7892,7 @@ UPDATE ColNames SET chop=iif(\
0\ 0\
)\ )\
"; ";
#endif
static const char * const zSetReps = "\ static const char * const zSetReps = "\
UPDATE ColNames AS t SET reps=\ UPDATE ColNames AS t SET reps=\
(SELECT count(*) FROM ColNames d \ (SELECT count(*) FROM ColNames d \
@ -7898,11 +7906,40 @@ SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
"; ";
#endif #endif
static const char * const zRenameRank = static const char * const zRenameRank =
#ifndef SHELL_COLUMN_RENAME_DML #ifdef SHELL_COLUMN_RENAME_CLEAN
"UPDATE ColNames AS t SET suff=" "UPDATE ColNames AS t SET suff="
"iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')" "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
#else #else /* ...RENAME_MINIMAL_ONE_PASS */
SHELL_COLUMN_RENAME_DML "WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
" SELECT 0 AS nlz"
" UNION"
" SELECT nlz+1 AS nlz FROM Lzn"
" WHERE EXISTS("
" SELECT 1"
" FROM ColNames t, ColNames o"
" WHERE"
" iif(t.name IN (SELECT * FROM RepeatedNames),"
" printf('%s"AUTOCOLUMN_SEP"%s',"
" t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2)),"
" t.name"
" )"
" ="
" iif(o.name IN (SELECT * FROM RepeatedNames),"
" printf('%s"AUTOCOLUMN_SEP"%s',"
" o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2)),"
" o.name"
" )"
" COLLATE NOCASE"
" AND o.cpos<>t.cpos"
" GROUP BY t.cpos"
" )"
") UPDATE Colnames AS t SET"
" chop = 0," /* No chopping, never touch incoming names. */
" suff = iif(name IN (SELECT * FROM RepeatedNames),"
" printf('"AUTOCOLUMN_SEP"%s', substring("
" printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2)),"
" ''"
" )"
#endif #endif
; ;
static const char * const zCollectVar = "\ static const char * const zCollectVar = "\
@ -7916,7 +7953,12 @@ FROM (\
SELECT cpos, printf('\"%w\"',printf('%.*s%s', nlen-chop,name,suff)) AS cname \ SELECT cpos, printf('\"%w\"',printf('%.*s%s', nlen-chop,name,suff)) AS cname \
FROM ColNames ORDER BY cpos\ FROM ColNames ORDER BY cpos\
)"; )";
static const char * const zRenamesDone =
"SELECT group_concat("
" printf('\"%w\" to \"%w\"',name,printf('%.*s%s', nlen-chop, name, suff)),"
" ','||x'0a')"
"FROM ColNames WHERE suff<>'' OR chop!=0"
;
int rc; int rc;
sqlite3_stmt *pStmt = 0; sqlite3_stmt *pStmt = 0;
assert(pDb!=0); assert(pDb!=0);
@ -7926,7 +7968,8 @@ FROM (\
if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0; if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
#ifdef SHELL_COLFIX_DB #ifdef SHELL_COLFIX_DB
if(*zCOL_DB!=':') if(*zCOL_DB!=':')
sqlite3_exec(*pDb,"drop table if exists ColNames",0,0,0); sqlite3_exec(*pDb,"drop table if exists ColNames;"
"drop view if exists RepeatedNames;",0,0,0);
#endif #endif
rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0); rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
rc_err_oom_die(rc); rc_err_oom_die(rc);
@ -7952,8 +7995,10 @@ FROM (\
# define nDigits 2 # define nDigits 2
#endif #endif
if( hasDupes ){ if( hasDupes ){
#ifdef SHELL_COLUMN_RENAME_CLEAN
rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0); rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
rc_err_oom_die(rc); rc_err_oom_die(rc);
#endif
rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0); rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0);
rc_err_oom_die(rc); rc_err_oom_die(rc);
rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0); rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0);
@ -7972,7 +8017,17 @@ FROM (\
}else{ }else{
zColsSpec = 0; zColsSpec = 0;
} }
if( pRenamed!=0 ) *pRenamed = hasDupes; if( pzRenamed!=0 ){
if( !hasDupes ) *pzRenamed = 0;
else{
sqlite3_finalize(pStmt);
if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0)
&& SQLITE_ROW==sqlite3_step(pStmt) ){
*pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
}else
*pzRenamed = 0;
}
}
sqlite3_finalize(pStmt); sqlite3_finalize(pStmt);
sqlite3_close(*pDb); sqlite3_close(*pDb);
*pDb = 0; *pDb = 0;
@ -8929,17 +8984,18 @@ static int do_meta_command(char *zLine, ShellState *p){
char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"", char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"",
zSchema, zTable); zSchema, zTable);
sqlite3 *dbCols = 0; sqlite3 *dbCols = 0;
int renamed = 0; char *zRenames = 0;
char *zColDefs; char *zColDefs;
while( xRead(&sCtx) ){ while( xRead(&sCtx) ){
zAutoColumn(sCtx.z, &dbCols, 0); zAutoColumn(sCtx.z, &dbCols, 0);
if( sCtx.cTerm!=sCtx.cColSep ) break; if( sCtx.cTerm!=sCtx.cColSep ) break;
} }
zColDefs = zAutoColumn(0, &dbCols, &renamed); zColDefs = zAutoColumn(0, &dbCols, &zRenames);
if( renamed!=0 ){ if( zRenames!=0 ){
utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr, utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
"Columns renamed during .import %s due to duplicates.\n", "Columns renamed during .import %s due to duplicates:\n"
sCtx.zFile); "%s\n", sCtx.zFile, zRenames);
sqlite3_free(zRenames);
} }
assert(dbCols==0); assert(dbCols==0);
if( zColDefs==0 ){ if( zColDefs==0 ){

View File

@ -484,20 +484,26 @@ CREATE TABLE t8(a, b, c);
do_test shell5-5.1 { do_test shell5-5.1 {
set out [open shell5.csv w] set out [open shell5.csv w]
fconfigure $out -translation lf fconfigure $out -translation lf
puts $out {"","x","x","y","z","z_0"} puts $out {"","x","x","y","z","z_0","z_5","z"}
puts $out {0,"ex2","ex3","wye4","zee5","zee6"} puts $out {0,"x2","x3","y4","z5","z6","z7","z8"}
close $out close $out
forcedelete test.db forcedelete test.db
catchcmd test.db {.import -csv shell5.csv t1 catchcmd test.db {.import -csv shell5.csv t1
.mode line .mode line
SELECT * FROM t1;} SELECT * FROM t1;}
} {1 { ? = 0 } {1 { ? = 0
x_2 = ex2 x_02 = x2
x_3 = ex3 x_03 = x3
y = wye4 y = y4
z_5 = zee5 z_05 = z5
z_6 = zee6 z_0 = z6
Columns renamed during .import shell5.csv due to duplicates.}} z_5 = z7
z_08 = z8
Columns renamed during .import shell5.csv due to duplicates:
"x" to "x_02",
"x" to "x_03",
"z" to "z_05",
"z" to "z_08"}}
do_test shell5-5.1 { do_test shell5-5.1 {
set out [open shell5.csv w] set out [open shell5.csv w]
@ -513,6 +519,10 @@ SELECT * FROM t1;}
cow_2 = lll cow_2 = lll
CoW_3 = ulu CoW_3 = ulu
cOw_4 = lul cOw_4 = lul
Columns renamed during .import shell5.csv due to duplicates.}} Columns renamed during .import shell5.csv due to duplicates:
"COW" to "COW_1",
"cow" to "cow_2",
"CoW" to "CoW_3",
"cOw" to "cOw_4"}}
finish_test finish_test