From: larrybr Date: Sun, 13 Feb 2022 22:18:22 +0000 (+0000) Subject: Sync w/trunk, fix zAutoColumns placement blunder, all to pass all TCL tests X-Git-Tag: version-3.38.0~15^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42de1c52dd4ca0747bb54230c14bef08cb3cd1c0;p=thirdparty%2Fsqlite.git Sync w/trunk, fix zAutoColumns placement blunder, all to pass all TCL tests FossilOrigin-Name: 67dc59f46d742ad69742fb34540a3074af163a3f1a0f9093f83db2276bf944ca --- 42de1c52dd4ca0747bb54230c14bef08cb3cd1c0 diff --cc manifest index d5fca950d3,99c4299462..c8b221ba39 --- a/manifest +++ b/manifest @@@ -1,5 -1,5 +1,5 @@@ - C For\s.import\sauto-column,\said\sbuild-time\soverride\sof\srename\sdecoration. - D 2022-02-12T13:12:03.134 -C Do\snot\srun\smerge1.test\swith\sSQLITE_OMIT_VIRTUALTABLE\sbuilds. -D 2022-02-12T18:56:24.181 ++C Sync\sw/trunk,\sfix\szAutoColumns\splacement\sblunder,\sall\sto\spass\sall\sTCL\stests ++D 2022-02-13T22:18:22.163 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@@ -553,7 -553,7 +553,7 @@@ F src/random.c 097dc8b31b8fba5a9aca1697 F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 3baa9dd8cf240654773c7974e2bcce398ac9dd24419c36684156963defe43b35 - F src/shell.c.in c2a03469e2f6f694878bdbee0e99f428c7bd2db104d54bd818f8834419ed666a x -F src/shell.c.in b800bf8e02d9b4fd97078b68ca4371048f7196fc63accaa99c3c5943f72c80a0 ++F src/shell.c.in 233a5c7f0ee9a9d1b88f1caed538d813390bb474082d9d74504d846ccb49f31e x F src/sqlite.h.in 7047c4b60fa550264d6363bb1d983540e7828fb19d2d1e5aa43b52ca13144807 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6 @@@ -1944,8 -1944,8 +1944,8 @@@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a9 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 - P 689137e1b5bc78b0f16e5db86d16415b9fa77d22ded59e93d75e7033b465e673 - R c9aa492d97b18dedc9e846ae1794f2b1 -P 9252619d410293ddefd108f5cf81b6fb4932bd3f2ceaaa92abb7542e34f66111 -R 80e8eecaf7636ea102822137f451668f -U dan -Z 534ed5fc79f3b9c855702c93bc92827c ++P 433e5ead2b711d1e3b0b62cf8cb5a8a65e2474c68ef2173317ed4323fc8bdc58 bf8dbfd499e732f14c7a8efee527e8ce155937dbb2a3e85213f8aa64ac497189 ++R d0a4f648a76dcc064c4b8040fefbc80a +U larrybr - Z f9350e44002aa6905f87e93f2aa43b9c ++Z 9500253e6d614600afa73cc694266a23 # Remove this line to create a well-formed Fossil manifest. diff --cc manifest.uuid index f0f8d99eda,17e7501d4c..505f134e8f --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - 433e5ead2b711d1e3b0b62cf8cb5a8a65e2474c68ef2173317ed4323fc8bdc58 -bf8dbfd499e732f14c7a8efee527e8ce155937dbb2a3e85213f8aa64ac497189 ++67dc59f46d742ad69742fb34540a3074af163a3f1a0f9093f83db2276bf944ca diff --cc src/shell.c.in index fba748bc96,35e99989f5..66428b72b6 mode 100755,100644..100755 --- a/src/shell.c.in +++ b/src/shell.c.in @@@ -7223,187 -7223,6 +7223,7 @@@ static char *shellMPrintf(int *pRc, con return z; } + - /* - * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it. - * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE, - * close db and set it to 0, and return the columns spec, to later - * be sqlite3_free()'ed by the caller. - * The return is 0 when either: - * (a) The db was not initialized and zCol==0 (There are no columns.) - * (b) zCol!=0 (Column was added, db initialized as needed.) - * The 3rd argument, pRenamed, references an out parameter. If the - * pointer is non-zero, its referent will be set to 1 if renaming was - * necessary, or set to 0 if none was done. - */ - #ifdef SHELL_DEBUG - #define rc_err_oom_die(rc) \ - if( rc==SQLITE_NOMEM ) shell_check_oom(0); \ - else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \ - fprintf(stderr,"E:%d\n",rc), assert(0) - #else - static void rc_err_oom_die(int rc){ - if( rc==SQLITE_NOMEM ) shell_check_oom(0); - assert(rc==SQLITE_OK||rc==SQLITE_DONE); - } - #endif - - #ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */ - static char zCOL_DB[] = SHELL_COLFIX_DB; - #else /* Otherwise, memory is faster/better for the transient DB. */ - static const char *zCOL_DB = ":memory:"; - #endif - - /* Define character (as C string) to separate generated column ordinal - * from protected part of incoming column names. This defaults to "_" - * so that incoming column identifiers that did not need not be quoted - * remain usable without being quoted. It must be one character. - */ - #ifndef SHELL_AUTOCOLUMN_SEP - # define AUTOCOLUMN_SEP "_" - #else - # define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP) - #endif - - static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, int *pRenamed){ - /* Queries and D{D,M}L used here */ - static const char const *zTabMake = "\ - CREATE TABLE ColNames(\ - cpos INTEGER PRIMARY KEY,\ - name TEXT, nlen INT, chop INT, reps INT, suff TEXT)\ - "; - static const char const *zTabFill = "\ - INSERT INTO ColNames(name,nlen,chop,reps,suff)\ - VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\ - "; - static const char const *zHasDupes = "\ - SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\ - 0 \ - )\ - SELECT cpos, name, max(chop) AS chop FROM chopping s \ - GROUP BY cpos \ - ) UPDATE ColNames AS c \ - SET chop=n.chop FROM chopped n WHERE c.cpos=n.cpos \ - "; - static const char const *zSetReps = "\ - UPDATE ColNames AS t SET reps=\ - (SELECT count(*) FROM ColNames d \ - WHERE substring(t.name,1,t.nlen-t.chop)=substring(d.name,1,d.nlen-d.chop)\ - COLLATE NOCASE\ - )\ - "; - #ifdef SQLITE_ENABLE_MATH_FUNCTIONS - static const char const *zColDigits = "\ - SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \ - "; - #endif - static const char const *zRenameRank = - #ifndef SHELL_COLUMN_RENAME_DML - "UPDATE ColNames AS t SET suff=" - "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')" - #else - SHELL_COLUMN_RENAME_DML - #endif - ; - static const char const *zCollectVar = "\ - SELECT\ - '('||\ - group_concat(\ - cname||' TEXT',\ - ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ - ||')' AS ColsSpec \ - FROM (\ - SELECT cpos, printf('\"%w\"',printf('%.*s%s', nlen-chop,name,suff)) AS cname \ - FROM ColNames ORDER BY cpos\ - )"; - - int rc; - sqlite3_stmt *pStmt = 0; - assert(pDb!=0); - if( zColNew ){ - /* Add initial or additional column. Init db if necessary. */ - if( *pDb==0 ){ - if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0; - #ifdef SHELL_COLFIX_DB - if(*zCOL_DB!=':') - sqlite3_exec(*pDb,"drop table if exists ColNames",0,0,0); - #endif - rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0); - rc_err_oom_die(rc); - } - assert(*pDb!=0); - rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0); - rc_err_oom_die(rc); - rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0); - rc_err_oom_die(rc); - rc = sqlite3_step(pStmt); - rc_err_oom_die(rc); - sqlite3_finalize(pStmt); - return 0; - }else if( *pDb==0 ){ - return 0; - }else{ - /* Formulate the columns spec, close the DB, zero *pDb. */ - char *zColsSpec = 0; - int hasDupes = db_int(*pDb, zHasDupes); - #ifdef SQLITE_ENABLE_MATH_FUNCTIONS - int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0; - #else - # define nDigits 2 - #endif - if( hasDupes ){ - rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0); - rc_err_oom_die(rc); - rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0); - rc_err_oom_die(rc); - rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0); - rc_err_oom_die(rc); - rc = sqlite3_bind_int(pStmt, 1, nDigits); - rc_err_oom_die(rc); - rc = sqlite3_step(pStmt); - sqlite3_finalize(pStmt); - assert(rc==SQLITE_DONE); - } - assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */ - rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0); - rc_err_oom_die(rc); - rc = sqlite3_step(pStmt); - if( rc==SQLITE_ROW ){ - zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); - }else{ - zColsSpec = 0; - } - if( pRenamed!=0 ) *pRenamed = hasDupes; - sqlite3_finalize(pStmt); - sqlite3_close(*pDb); - *pDb = 0; - return zColsSpec; - } - } - - /* ** When running the ".recover" command, each output table, and the special ** orphaned row table if it is required, is represented by an instance @@@ -8000,6 -7819,6 +7820,166 @@@ static int recoverDatabaseCmd(ShellStat } #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ ++ ++/* ++ * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it. ++ * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE, ++ * close db and set it to 0, and return the columns spec, to later ++ * be sqlite3_free()'ed by the caller. ++ * The return is 0 when either: ++ * (a) The db was not initialized and zCol==0 (There are no columns.) ++ * (b) zCol!=0 (Column was added, db initialized as needed.) ++ * The 3rd argument, pRenamed, references an out parameter. If the ++ * pointer is non-zero, its referent will be set to 1 if renaming was ++ * necessary, or set to 0 if none was done. ++ */ ++#ifdef SHELL_DEBUG ++#define rc_err_oom_die(rc) \ ++ if( rc==SQLITE_NOMEM ) shell_check_oom(0); \ ++ else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \ ++ fprintf(stderr,"E:%d\n",rc), assert(0) ++#else ++static void rc_err_oom_die(int rc){ ++ if( rc==SQLITE_NOMEM ) shell_check_oom(0); ++ assert(rc==SQLITE_OK||rc==SQLITE_DONE); ++} ++#endif ++ ++#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */ ++static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB); ++#else /* Otherwise, memory is faster/better for the transient DB. */ ++static const char *zCOL_DB = ":memory:"; ++#endif ++ ++/* Define character (as C string) to separate generated column ordinal ++ * from protected part of incoming column names. This defaults to "_" ++ * so that incoming column identifiers that did not need not be quoted ++ * remain usable without being quoted. It must be one character. ++ */ ++#ifndef SHELL_AUTOCOLUMN_SEP ++# define AUTOCOLUMN_SEP "_" ++#else ++# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP) ++#endif ++ ++static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, int *pRenamed){ ++ /* Queries and D{D,M}L used here */ ++ static const char * const zTabMake = "\ ++CREATE TABLE ColNames(\ ++ cpos INTEGER PRIMARY KEY,\ ++ name TEXT, nlen INT, chop INT, reps INT, suff TEXT)\ ++"; ++ static const char * const zTabFill = "\ ++INSERT INTO ColNames(name,nlen,chop,reps,suff)\ ++ VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\ ++"; ++ static const char * const zHasDupes = "\ ++SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\ ++ 1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')" ++#else ++ SHELL_COLUMN_RENAME_DML ++#endif ++ ; ++ static const char * const zCollectVar = "\ ++SELECT\ ++ '('||x'0a'\ ++ || group_concat(\ ++ cname||' TEXT',\ ++ ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ ++ ||')' AS ColsSpec \ ++FROM (\ ++ SELECT cpos, printf('\"%w\"',printf('%.*s%s', nlen-chop,name,suff)) AS cname \ ++ FROM ColNames ORDER BY cpos\ ++)"; ++ ++ int rc; ++ sqlite3_stmt *pStmt = 0; ++ assert(pDb!=0); ++ if( zColNew ){ ++ /* Add initial or additional column. Init db if necessary. */ ++ if( *pDb==0 ){ ++ if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0; ++#ifdef SHELL_COLFIX_DB ++ if(*zCOL_DB!=':') ++ sqlite3_exec(*pDb,"drop table if exists ColNames",0,0,0); ++#endif ++ rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0); ++ rc_err_oom_die(rc); ++ } ++ assert(*pDb!=0); ++ rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0); ++ rc_err_oom_die(rc); ++ rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0); ++ rc_err_oom_die(rc); ++ rc = sqlite3_step(pStmt); ++ rc_err_oom_die(rc); ++ sqlite3_finalize(pStmt); ++ return 0; ++ }else if( *pDb==0 ){ ++ return 0; ++ }else{ ++ /* Formulate the columns spec, close the DB, zero *pDb. */ ++ char *zColsSpec = 0; ++ int hasDupes = db_int(*pDb, zHasDupes); ++#ifdef SQLITE_ENABLE_MATH_FUNCTIONS ++ int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0; ++#else ++# define nDigits 2 ++#endif ++ if( hasDupes ){ ++ rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0); ++ rc_err_oom_die(rc); ++ rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0); ++ rc_err_oom_die(rc); ++ rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0); ++ rc_err_oom_die(rc); ++ sqlite3_bind_int(pStmt, 1, nDigits); ++ rc = sqlite3_step(pStmt); ++ sqlite3_finalize(pStmt); ++ assert(rc==SQLITE_DONE); ++ } ++ assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */ ++ rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0); ++ rc_err_oom_die(rc); ++ rc = sqlite3_step(pStmt); ++ if( rc==SQLITE_ROW ){ ++ zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); ++ }else{ ++ zColsSpec = 0; ++ } ++ if( pRenamed!=0 ) *pRenamed = hasDupes; ++ sqlite3_finalize(pStmt); ++ sqlite3_close(*pDb); ++ *pDb = 0; ++ return zColsSpec; ++ } ++} ++ /* ** If an input line begins with "." then invoke this routine to ** process that line.