From 3a9a76b70a0ee2dce226b4c00b64cd238c6be4a9 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 11 Aug 2018 20:46:54 +0000 Subject: [PATCH] Add the "atrc" test program. "Atrc" is short for "ALTER TABLE RENAME COLUMN". See the header comment on the program itself for further information. FossilOrigin-Name: ed64a55a2242408ac0b889b330cf91d38a954399b75c6ebe71232613b864c70b --- manifest | 13 +++-- manifest.uuid | 2 +- test/atrc.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 test/atrc.c diff --git a/manifest b/manifest index 863aea41fb..934a2b4617 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sthe\snew\scolumn\sname\sin\san\sALTER\sTABLE\sRENAME\sCOLUMN\sstatement\sis\squoted,\nthen\salso\suse\squotes\sfor\sthe\scolumn\sname\sin\sthe\sedited\sSQL\sstatements. -D 2018-08-11T20:38:33.809 +C Add\sthe\s"atrc"\stest\sprogram.\s\s\s"Atrc"\sis\sshort\sfor\s"ALTER\sTABLE\sRENAME\sCOLUMN".\nSee\sthe\sheader\scomment\son\sthe\sprogram\sitself\sfor\sfurther\sinformation. +D 2018-08-11T20:46:54.161 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -625,6 +625,7 @@ F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0 F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061 F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da +F test/atrc.c 834739c220d2715dd513ce76d4773216a9c1bffe40d992876d14c34e103f11be F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be8281c F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce F test/attach3.test c59d92791070c59272e00183b7353eeb94915976 @@ -1755,7 +1756,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 520c1c75dae5e3f4695fcdf0aad5fb9f492f0e528b5fbb49d5d3b5fc02762f47 -R 42d189b99bda0a148c429a132edf76e5 -U dan -Z 03ad3aa61b255b569ff4ff7e8834b149 +P ca5184a25f9150540a3e401ef67df0606efa7a294d70e3fa5edad9854003eb36 +R cecd54c9d63229291534e29203ac7afc +U drh +Z 77329205a7cab2453b99ca75b5ef0d21 diff --git a/manifest.uuid b/manifest.uuid index 58037da7cd..04a611491e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ca5184a25f9150540a3e401ef67df0606efa7a294d70e3fa5edad9854003eb36 \ No newline at end of file +ed64a55a2242408ac0b889b330cf91d38a954399b75c6ebe71232613b864c70b \ No newline at end of file diff --git a/test/atrc.c b/test/atrc.c new file mode 100644 index 0000000000..c4436f9ef2 --- /dev/null +++ b/test/atrc.c @@ -0,0 +1,150 @@ +/* +** This program generates a script that stresses the ALTER TABLE statement. +** Compile like this: +** +** gcc -g -c sqlite3.c +** gcc -g -o atrc atrc.c sqlite3.o -ldl -lpthread +** +** Run the problem this way: +** +** ./atrc DATABASE | ./sqlite3 DATABASE +** +** This program "atrc" generates a script that can be fed into an ordinary +** command-line shell. The script performs many ALTER TABLE statements, +** runs ".schema --indent" and "PRAGMA integrity_check;", does more +** ALTER TABLE statements to restore the original schema, and then +** runs "PRAGMA integrity_check" again. Every table and column has its +** name changed. The entire script is contained within BEGIN...ROLLBACK +** so that no changes are ever actually made to the database. +*/ +#include "sqlite3.h" +#include + +/* +** Generate the text of ALTER TABLE statements that will rename +** every column in table zTable to a generic name composed from +** zColPrefix and a sequential number. The generated text is +** appended pConvert. If pUndo is not NULL, then SQL text that +** will undo the change is appended to pUndo. +** +** The table to be converted must be in the "main" schema. +*/ +int rename_all_columns_of_table( + sqlite3 *db, /* Database connection */ + const char *zTab, /* Table whose columns should all be renamed */ + const char *zColPrefix, /* Prefix for new column names */ + sqlite3_str *pConvert, /* Append ALTER TABLE statements here */ + sqlite3_str *pUndo /* SQL to undo the change, if not NULL */ +){ + sqlite3_stmt *pStmt; + int rc; + int cnt = 0; + + rc = sqlite3_prepare_v2(db, + "SELECT name FROM pragma_table_info(?1);", + -1, &pStmt, 0); + if( rc ) return rc; + sqlite3_bind_text(pStmt, 1, zTab, -1, SQLITE_STATIC); + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zCol = (const char*)sqlite3_column_text(pStmt, 0); + cnt++; + sqlite3_str_appendf(pConvert, + "ALTER TABLE \"%w\" RENAME COLUMN \"%w\" TO \"%w%d\";\n", + zTab, zCol, zColPrefix, cnt + ); + if( pUndo ){ + sqlite3_str_appendf(pUndo, + "ALTER TABLE \"%w\" RENAME COLUMN \"%w%d\" TO \"%w\";\n", + zTab, zColPrefix, cnt, zCol + ); + } + } + sqlite3_finalize(pStmt); + return SQLITE_OK; +} + +/* Rename all tables and their columns in the main database +*/ +int rename_all_tables( + sqlite3 *db, /* Database connection */ + sqlite3_str *pConvert, /* Append SQL to do the rename here */ + sqlite3_str *pUndo /* Append SQL to undo the rename here */ +){ + sqlite3_stmt *pStmt; + int rc; + int cnt = 0; + + rc = sqlite3_prepare_v2(db, + "SELECT name FROM sqlite_master WHERE type='table'" + " AND name NOT LIKE 'sqlite_%';", + -1, &pStmt, 0); + if( rc ) return rc; + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zTab = (const char*)sqlite3_column_text(pStmt, 0); + char *zNewTab; + char zPrefix[2]; + + zPrefix[0] = (cnt%26) + 'a'; + zPrefix[1] = 0; + zNewTab = sqlite3_mprintf("tx%d", ++cnt); + if( pUndo ){ + sqlite3_str_appendf(pUndo, + "ALTER TABLE \"%s\" RENAME TO \"%w\";\n", + zNewTab, zTab + ); + } + rename_all_columns_of_table(db, zTab, zPrefix, pConvert, pUndo); + sqlite3_str_appendf(pConvert, + "ALTER TABLE \"%w\" RENAME TO \"%s\";\n", + zTab, zNewTab + ); + sqlite3_free(zNewTab); + } + sqlite3_finalize(pStmt); + return SQLITE_OK; +} + +/* +** Generate a script that does this: +** +** (1) Start a transaction +** (2) Rename all tables and columns to use generic names. +** (3) Print the schema after this rename +** (4) Run pragma integrity_check +** (5) Do more ALTER TABLE statements to change the names back +** (6) Run pragma integrity_check again +** (7) Rollback the transaction +*/ +int main(int argc, char **argv){ + sqlite3 *db; + int rc; + sqlite3_str *pConvert; + sqlite3_str *pUndo; + char *zDbName; + char *zSql1, *zSql2; + if( argc!=2 ){ + fprintf(stderr, "Usage: %s DATABASE\n", argv[0]); + } + zDbName = argv[1]; + rc = sqlite3_open(zDbName, &db); + if( rc ){ + fprintf(stderr, "sqlite3_open() returns %d\n", rc); + return 1; + } + pConvert = sqlite3_str_new(db); + pUndo = sqlite3_str_new(db); + rename_all_tables(db, pConvert, pUndo); + zSql1 = sqlite3_str_finish(pConvert); + zSql2 = sqlite3_str_finish(pUndo); + sqlite3_close(db); + printf("BEGIN;\n"); + printf("%s", zSql1); + sqlite3_free(zSql1); + printf(".schema --indent\n"); + printf("PRAGMA integrity_check;\n"); + printf("%s", zSql2); + sqlite3_free(zSql2); + printf("PRAGMA integrity_check;\n"); + printf("ROLLBACK;\n"); + return 0; +}