From: drh <> Date: Fri, 4 Feb 2022 16:43:30 +0000 (+0000) Subject: Allow ALTER TABLE RENAME COLUMN to proceed even if there are errors in X-Git-Tag: version-3.38.0~55^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5a80050dd33e46cc70ac2ecfb30b52f39dce8363;p=thirdparty%2Fsqlite.git Allow ALTER TABLE RENAME COLUMN to proceed even if there are errors in the schema, as long as PRAGMA writable_schema=ON is active. FossilOrigin-Name: 197cbabf1767d0603928462fb75cf8100f6999f725e0db60d096c7ca20e3da28 --- diff --git a/manifest b/manifest index 4eafb3043f..eff80ce005 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\svarious\sharmless\scompiler\swarnings. -D 2022-02-04T13:15:01.508 +C Allow\sALTER\sTABLE\sRENAME\sCOLUMN\sto\sproceed\seven\sif\sthere\sare\serrors\sin\nthe\sschema,\sas\slong\sas\sPRAGMA\swritable_schema=ON\sis\sactive. +D 2022-02-04T16:43:30.569 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -485,7 +485,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c e8ac1df663bf4ec74920edd1299435f2a616d2404de0ac4013c151ea4e7a11f2 +F src/alter.c 11c8e4d382632a024c19fa09131d271c8c36f5b520023066e08408973a20e82d F src/analyze.c 7518b99e07c5494111fe3bd867f28f804b6c5c1ad0703ec3d116de9bab3fa516 F src/attach.c f26d400f3ffe2cdca01406bca70e5f58c5488bf165b4fc37c228136dfcf1b583 F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf @@ -657,7 +657,7 @@ F test/alter3.test ffc4ab29ce78a3517a66afd69b2730667e3471622509c283b2bd4c46f680f F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707 F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959 F test/alterauth2.test 48967abae0494d9a300d1c92473d99fcb66edfcc23579c89322f033f49410adc -F test/altercol.test 9471187fe155d9c4211ae185e104ff48ce8f114262ee1256cf1e110b339c725f +F test/altercol.test d4f25038a7a72c38267f99ff7c0153d720c0a908321bbbf0639c301e6ea1c57c F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12 F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41 @@ -1943,8 +1943,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9f67ad00cd38b7c5ec6d14b379e1a611777bbdf6901d843a80712ba7d94d6d33 -R ed2fd6b08e6120318ad847a61dee5a51 +P 70049342d5ad57ea3e863bba19253934b868bacdd1c26c9371bac024a829badf +R ade5a35b1c4e6334138f31a1e28c7fb0 +T *branch * relaxed-alter-table +T *sym-relaxed-alter-table * +T -sym-trunk * U drh -Z 871646465b8062211df8c4f3cf586a8c +Z 7858525677fe7d863fef5513c510c7f5 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 2dd02dd9db..dd1dfb7900 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -70049342d5ad57ea3e863bba19253934b868bacdd1c26c9371bac024a829badf \ No newline at end of file +197cbabf1767d0603928462fb75cf8100f6999f725e0db60d096c7ca20e3da28 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 4de7cc51d3..5cf28147c2 100644 --- a/src/alter.c +++ b/src/alter.c @@ -1427,7 +1427,7 @@ static void renameParseCleanup(Parse *pParse){ /* ** SQL function: ** -** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld) +** sqlite_rename_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP) ** ** 0. zSql: SQL statement to rewrite ** 1. type: Type of object ("table", "view" etc.) @@ -1445,7 +1445,8 @@ static void renameParseCleanup(Parse *pParse){ ** ** This function is used internally by the ALTER TABLE RENAME COLUMN command. ** It is only accessible to SQL created using sqlite3NestedParse(). It is -** not reachable from ordinary SQL passed into sqlite3_prepare(). +** not reachable from ordinary SQL passed into sqlite3_prepare() unless the +** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled. */ static void renameColumnFunc( sqlite3_context *context, @@ -1594,7 +1595,9 @@ static void renameColumnFunc( renameColumnFunc_done: if( rc!=SQLITE_OK ){ - if( sParse.zErrMsg ){ + if( sqlite3WritableSchema(db) ){ + sqlite3_result_value(context, argv[0]); + }else if( sParse.zErrMsg ){ renameColumnParseError(context, "", argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); @@ -1818,10 +1821,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } -/* -** The implementation of an SQL scalar function that rewrites DDL statements -** so that any string literals that use double-quotes are modified so that -** they use single quotes. +/* SQL function: sqlite_rename_quotefix(DB,SQL) +** +** Rewrite the DDL statement "SQL" so that any string literals that use +** double-quotes use single quotes instead. ** ** Two arguments must be passed: ** @@ -1840,6 +1843,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){ ** returns the string: ** ** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1 +** +** If there is a error in the input SQL, then raise an error, except +** if PRAGMA writable_schema=ON, then just return the input string +** unmodified following an error. */ static void renameQuotefixFunc( sqlite3_context *context, @@ -1914,7 +1921,11 @@ static void renameQuotefixFunc( renameTokenFree(db, sCtx.pList); } if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(context, rc); + if( sqlite3WritableSchema(db) ){ + sqlite3_result_value(context, argv[1]); + }else{ + sqlite3_result_error_code(context, rc); + } } renameParseCleanup(&sParse); } @@ -1926,7 +1937,8 @@ static void renameQuotefixFunc( sqlite3BtreeLeaveAll(db); } -/* +/* Function: sqlite_rename_test(DB,SQL,TYPE,NAME,ISTEMP,WHEN,DQS) +** ** An SQL user function that checks that there are no parse or symbol ** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement. ** After an ALTER TABLE .. RENAME operation is performed and the schema @@ -1941,11 +1953,13 @@ static void renameQuotefixFunc( ** 5: "when" part of error message. ** 6: True to disable the DQS quirk when parsing SQL. ** -** Unless it finds an error, this function normally returns NULL. However, it -** returns integer value 1 if: +** The return value is computed as follows: ** -** * the SQL argument creates a trigger, and -** * the table that the trigger is attached to is in database zDb. +** A. If an error is seen and not in PRAGMA writable_schema=ON mode, +** then raise the error. +** B. Else if a trigger is created and the the table that the trigger is +** attached to is in database zDb, then return 1. +** C. Otherwise return NULL. */ static void renameTableTest( sqlite3_context *context, @@ -1990,12 +2004,16 @@ static void renameTableTest( if( rc==SQLITE_OK ){ int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); int i2 = sqlite3FindDbName(db, zDb); - if( i1==i2 ) sqlite3_result_int(context, 1); + if( i1==i2 ){ + /* Handle output case B */ + sqlite3_result_int(context, 1); + } } } } - if( rc!=SQLITE_OK && zWhen ){ + if( rc!=SQLITE_OK && !sqlite3WritableSchema(db) ){ + /* Output case A */ renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse); } renameParseCleanup(&sParse); diff --git a/test/altercol.test b/test/altercol.test index 10ff9e773f..1d31e4ec06 100644 --- a/test/altercol.test +++ b/test/altercol.test @@ -553,8 +553,9 @@ do_execsql_test 13.1.3 { sqlite3_db_config db DEFENSIVE 0 do_execsql_test 13.1.4 { - PRAGMA writable_schema = 1; + PRAGMA writable_schema = ON; UPDATE sqlite_master SET sql = 'CREATE INDEX x1i ON x1(j)' WHERE name='x1i'; + PRAGMA writable_schema = OFF; } {} do_catchsql_test 13.1.5 { @@ -562,7 +563,9 @@ do_catchsql_test 13.1.5 { } {1 {error in index x1i: no such column: j}} do_execsql_test 13.1.6 { + PRAGMA writable_schema = ON; UPDATE sqlite_master SET sql = '' WHERE name='x1i'; + PRAGMA writable_schema = OFF; } {} do_catchsql_test 13.1.7 { @@ -570,7 +573,9 @@ do_catchsql_test 13.1.7 { } {1 {error in index x1i: }} do_execsql_test 13.1.8 { + PRAGMA writable_schema = ON; DELETE FROM sqlite_master WHERE name = 'x1i'; + PRAGMA writable_schema = OFF; } do_execsql_test 13.2.0 { @@ -861,5 +866,59 @@ do_execsql_test 23.0 { } {ok {CREATE TABLE t1("x" "b",c)}} +# 2022-02-04 +# Do not complain about syntax errors in the schema if +# in PRAGMA writable_schema=ON mode. +# +reset_db +do_execsql_test 23.0 { + CREATE TABLE t1(a INT, b REAL, c TEXT, d BLOB, e ANY); + CREATE INDEX t1abx ON t1(a, b, a+b) WHERE c IS NOT NULL; + CREATE VIEW t2 AS SELECT a+10, b*5.0, xyz FROM t1; -- unknown column "xyz" + CREATE TABLE schema_copy(name TEXT, sql TEXT); + INSERT INTO schema_copy(name,sql) SELECT name, sql FROM sqlite_schema WHERE sql IS NOT NULL; +} {} +do_catchsql_test 23.1 { + ALTER TABLE t1 RENAME COLUMN e TO eeee; +} {1 {error in view t2: no such column: xyz}} +do_execsql_test 23.2 { + SELECT name, sql FROM sqlite_master + EXCEPT SELECT name, sql FROM schema_copy; +} {} +do_execsql_test 23.3 { + BEGIN; + PRAGMA writable_schema=ON; + ALTER TABLE t1 RENAME COLUMN e TO eeee; + PRAGMA writable_schema=OFF; + SELECT name FROM sqlite_master + WHERE (name, sql) NOT IN (SELECT name, sql FROM schema_copy); + ROLLBACK; +} {t1} +do_execsql_test 23.10 { + DROP VIEW t2; + CREATE TRIGGER r3 AFTER INSERT ON t1 BEGIN + INSERT INTO t3(x,y) VALUES(new.a, new.b); + INSERT INTO t4(p) VALUES(new.c); -- no such table "t4" + END; + DELETE FROM schema_copy; + INSERT INTO schema_copy(name,sql) SELECT name, sql FROM sqlite_schema WHERE sql IS NOT NULL; +} {} +do_catchsql_test 23.11 { + ALTER TABLE t1 RENAME COLUMN e TO eeee; +} {1 {error in trigger r3: no such table: main.t3}} +do_execsql_test 23.12 { + SELECT name, sql FROM sqlite_master + EXCEPT SELECT name, sql FROM schema_copy; +} {} +do_execsql_test 23.13 { + BEGIN; + PRAGMA writable_schema=ON; + ALTER TABLE t1 RENAME COLUMN e TO eeee; + PRAGMA writable_schema=OFF; + SELECT name FROM sqlite_master + WHERE (name, sql) NOT IN (SELECT name, sql FROM schema_copy); + ROLLBACK; +} {t1} + finish_test