]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem with schema error detection when processing ALTER TABLE DROP COLUMN...
authordan <Dan Kennedy>
Thu, 18 Feb 2021 19:25:44 +0000 (19:25 +0000)
committerdan <Dan Kennedy>
Thu, 18 Feb 2021 19:25:44 +0000 (19:25 +0000)
FossilOrigin-Name: 565a6fd0c95b438fea7bf84913b38de1718117e16e0d685534a8650e1dc8421b

manifest
manifest.uuid
src/alter.c
test/alterdropcol.test

index 12294215e9b4610935ee6384bbd8c89b7e561115..bc2e3dbf4b28b5c47fa1d1b569f6b9e5ef31430a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\stest\scases\sfor\sALTER\sTABLE\sDROP\sCOLUMN.
-D 2021-02-18T17:48:36.327
+C Fix\sa\sproblem\swith\sschema\serror\sdetection\swhen\sprocessing\sALTER\sTABLE\sDROP\sCOLUMN\scommands.
+D 2021-02-18T19:25:44.637
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -475,7 +475,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
 F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c d56ceae00c743ef991e5ab1e9be2095a441dcee085bccf8795eba3da71b4d85f
+F src/alter.c 2e5a29206228e57739e644dab71f268a5d95348e29fc498aa2c31ccc33229fcc
 F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
 F src/attach.c e80162a47411f296bea550ed8fafd730481f4aa71e89ece23ba9c957eed15d4a
 F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
@@ -647,7 +647,7 @@ F test/alter4.test dfd6086faf461b27ca2d2999848dcd207edf23352fc1592d0005c0844f3f0
 F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
 F test/alterauth2.test c0a1ddf5b93d93cb0d15ba7acaf0c5c6fb515bbe861ede75b2d3fabad33b6499
 F test/altercol.test 1d6a6fe698b81e626baea4881f5717f9bc53d7d07f1cd23ee7ad1b931f117ddf
-F test/alterdropcol.test e75893837c5a9b6422c646c36cb9b50b6ff5a526e6c827bd96a9cea7112ca9ad
+F test/alterdropcol.test f4fb3a02a7274740769506f2af2eb8cc60aac26a148b71564b79fe3a19acae3b
 F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e228c15811
 F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
 F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
@@ -1902,7 +1902,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 ea999c9db59e4193b306a2e1b15fc94f8f04cb05e852bb0d068b7d5243a0849b
-R e87cb22a663d50f61a2888642ea17223
+P 204ee5e28210738fb624a9cf85dc6f9b59de0d7eb4fddd46c8babe9beddd4944
+R 845ed6581bddfe7c8da85d38a6d123ff
 U dan
-Z a5aedcb976c3c92cd79e2c941a67f828
+Z f3602657c19c9bc4f7de01775efae4db
index 6ed839059c402dcdebc446d7e196812f30107f20..70e8900803cfab812fbc466a1e688d9352b5ec5e 100644 (file)
@@ -1 +1 @@
-204ee5e28210738fb624a9cf85dc6f9b59de0d7eb4fddd46c8babe9beddd4944
\ No newline at end of file
+565a6fd0c95b438fea7bf84913b38de1718117e16e0d685534a8650e1dc8421b
\ No newline at end of file
index d48b5ec919ee8f53e739a66076fc80b23d7e436f..36cc9f3213b2cb600bc0f4e379ea5e7ca51cf0d4 100644 (file)
@@ -49,16 +49,21 @@ static int isAlterableTable(Parse *pParse, Table *pTab){
 ** statement to ensure that the operation has not rendered any schema
 ** objects unusable.
 */
-static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
+static void renameTestSchema(
+  Parse *pParse,                  /* Parse context */
+  const char *zDb,                /* Name of db to verify schema of */
+  int bTemp,                      /* True if this is the temp db */
+  const char *zWhen               /* "when" part of error message */
+){
   pParse->colNamesSet = 1;
   sqlite3NestedParse(pParse, 
       "SELECT 1 "
       "FROM \"%w\"." DFLT_SCHEMA_TABLE " "
       "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
       " AND sql NOT LIKE 'create virtual%%'"
-      " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ",
+      " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q)=NULL ",
       zDb,
-      zDb, bTemp
+      zDb, bTemp, zWhen
   );
 
   if( bTemp==0 ){
@@ -67,8 +72,8 @@ static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
         "FROM temp." DFLT_SCHEMA_TABLE " "
         "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
         " AND sql NOT LIKE 'create virtual%%'"
-        " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ",
-        zDb 
+        " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q)=NULL ",
+        zDb, zWhen
     );
   }
 }
@@ -231,7 +236,7 @@ void sqlite3AlterRenameTable(
             "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
             "tbl_name = "
               "CASE WHEN tbl_name=%Q COLLATE nocase AND "
-              "          sqlite_rename_test(%Q, sql, type, name, 1) "
+              "    sqlite_rename_test(%Q, sql, type, name, 1, 'after rename') "
               "THEN %Q ELSE tbl_name END "
             "WHERE type IN ('view', 'trigger')"
         , zDb, zTabName, zName, zTabName, zDb, zName);
@@ -251,7 +256,7 @@ void sqlite3AlterRenameTable(
 #endif
 
   renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
-  renameTestSchema(pParse, zDb, iDb==1);
+  renameTestSchema(pParse, zDb, iDb==1, "after rename");
 
 exit_rename_table:
   sqlite3SrcListDelete(db, pSrc);
@@ -619,7 +624,7 @@ void sqlite3AlterRenameColumn(
 
   /* Drop and reload the database schema. */
   renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);
-  renameTestSchema(pParse, zDb, iSchema==1);
+  renameTestSchema(pParse, zDb, iSchema==1, "after rename");
 
  exit_rename_column:
   sqlite3SrcListDelete(db, pSrc);
@@ -968,7 +973,7 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){
 */
 static void renameColumnParseError(
   sqlite3_context *pCtx, 
-  int bPost,
+  const char *zWhen,
   sqlite3_value *pType,
   sqlite3_value *pObject,
   Parse *pParse
@@ -977,8 +982,8 @@ static void renameColumnParseError(
   const char *zN = (const char*)sqlite3_value_text(pObject);
   char *zErr;
 
-  zErr = sqlite3_mprintf("error in %s %s%s: %s", 
-      zT, zN, (bPost ? " after rename" : ""),
+  zErr = sqlite3_mprintf("error in %s %s%s%s: %s", 
+      zT, zN, (zWhen[0] ? " " : ""), zWhen,
       pParse->zErrMsg
   );
   sqlite3_result_error(pCtx, zErr, -1);
@@ -1484,7 +1489,7 @@ static void renameColumnFunc(
 renameColumnFunc_done:
   if( rc!=SQLITE_OK ){
     if( sParse.zErrMsg ){
-      renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+      renameColumnParseError(context, "", argv[1], argv[2], &sParse);
     }else{
       sqlite3_result_error_code(context, rc);
     }
@@ -1673,7 +1678,7 @@ static void renameTableFunc(
     }
     if( rc!=SQLITE_OK ){
       if( sParse.zErrMsg ){
-        renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+        renameColumnParseError(context, "", argv[1], argv[2], &sParse);
       }else{
         sqlite3_result_error_code(context, rc);
       }
@@ -1702,6 +1707,7 @@ static void renameTableFunc(
 **   2: Object type ("view", "table", "trigger" or "index").
 **   3: Object name.
 **   4: True if object is from temp schema.
+**   5: "when" part of error message.
 **
 ** Unless it finds an error, this function normally returns NULL. However, it
 ** returns integer value 1 if:
@@ -1719,6 +1725,7 @@ static void renameTableTest(
   char const *zInput = (const char*)sqlite3_value_text(argv[1]);
   int bTemp = sqlite3_value_int(argv[4]);
   int isLegacy = (db->flags & SQLITE_LegacyAlter);
+  char const *zWhen = (const char*)sqlite3_value_text(argv[5]);
 
 #ifndef SQLITE_OMIT_AUTHORIZATION
   sqlite3_xauth xAuth = db->xAuth;
@@ -1751,8 +1758,8 @@ static void renameTableTest(
       }
     }
 
-    if( rc!=SQLITE_OK ){
-      renameColumnParseError(context, 1, argv[2], argv[3], &sParse);
+    if( rc!=SQLITE_OK && zWhen ){
+      renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse);
     }
     renameParseCleanup(&sParse);
   }
@@ -1869,6 +1876,7 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
   iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
   assert( iDb>=0 );
   zDb = db->aDb[iDb].zDbSName;
+  renameTestSchema(pParse, zDb, iDb==1, "");
   sqlite3NestedParse(pParse, 
       "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
       "sql = sqlite_drop_column(%d, sql, %d, %d) "
@@ -1878,7 +1886,7 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
 
   /* Drop and reload the database schema. */
   renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop);
-  renameTestSchema(pParse, zDb, iDb==1);
+  renameTestSchema(pParse, zDb, iDb==1, "after drop column");
 
   /* Edit rows of table on disk */
   if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
@@ -1939,7 +1947,7 @@ void sqlite3AlterFunctions(void){
   static FuncDef aAlterTableFuncs[] = {
     INTERNAL_FUNCTION(sqlite_rename_column,  9, renameColumnFunc),
     INTERNAL_FUNCTION(sqlite_rename_table,   7, renameTableFunc),
-    INTERNAL_FUNCTION(sqlite_rename_test,    5, renameTableTest),
+    INTERNAL_FUNCTION(sqlite_rename_test,    6, renameTableTest),
     INTERNAL_FUNCTION(sqlite_drop_column,    4, dropColumnFunc),
   };
   sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
index fecd9e121a0fa03fdfef9a4f7a75ddf929f5e0fd..7edb05f4b9413a65ba3b18a00595c3c5be6e5195 100644 (file)
@@ -223,6 +223,37 @@ do_execsql_test 5.1 {
   {CREATE TABLE c2(x, y, w REFERENCES p1(b))}
 }
 
+do_execsql_test 5.2.1 {
+  CREATE VIEW v1 AS SELECT d, e FROM p1
+}
+do_catchsql_test 5.2.2 {
+  ALTER TABLE c1 DROP COLUMN x
+} {1 {error in view v1: no such column: d}}
+do_execsql_test 5.3.1 {
+  DROP VIEW v1;
+  CREATE VIEW v1 AS SELECT x, y FROM c1;
+}
+do_catchsql_test 5.3.2 {
+  ALTER TABLE c1 DROP COLUMN x
+} {1 {error in view v1 after drop column: no such column: x}}
+
+do_execsql_test 5.4.1 {
+  CREATE TRIGGER tr AFTER INSERT ON c1 BEGIN
+    INSERT INTO p1 VALUES(new.y, new.xyz);
+  END;
+}
+do_catchsql_test 5.4.2 {
+  ALTER TABLE c1 DROP COLUMN y
+} {1 {error in trigger tr: no such column: new.xyz}}
+do_execsql_test 5.5.1 {
+  DROP TRIGGER tr;
+  CREATE TRIGGER tr AFTER INSERT ON c1 BEGIN
+    INSERT INTO p1 VALUES(new.y, new.z);
+  END;
+}
+do_catchsql_test 5.5.2 {
+  ALTER TABLE c1 DROP COLUMN y
+} {1 {error in trigger tr: no such column: new.z}}
 
 finish_test