Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -889,10 +889,21 @@ /* Drop and reload the database schema. */ if( pParse->pVdbe ){ sqlite3ChangeCookie(pParse, iSchema); sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iSchema, 0); } + + sqlite3NestedParse(pParse, + "SELECT 1 " + "FROM \"%w\".%s " + "WHERE name NOT LIKE 'sqlite_%%' AND (type != 'index' OR tbl_name = %Q)" + " AND sql NOT LIKE 'create virtual%%'" + " AND sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, -1)=0 ", + zDb, MASTER_NAME, + pTab->zName, + zDb, pTab->zName, iCol, zNew + ); exit_rename_column: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zOld); sqlite3DbFree(db, zNew); @@ -1068,19 +1079,23 @@ ** sub-routine is currently stored in pParse->zErrMsg. This function ** adds context to the error message and then stores it in pCtx. */ static void renameColumnParseError( sqlite3_context *pCtx, + int bPost, sqlite3_value *pType, sqlite3_value *pObject, Parse *pParse ){ const char *zT = (const char*)sqlite3_value_text(pType); const char *zN = (const char*)sqlite3_value_text(pObject); char *zErr; - zErr = sqlite3_mprintf("error processing %s %s: %s", zT, zN, pParse->zErrMsg); + zErr = sqlite3_mprintf("error in %s %s%s: %s", + zT, zN, (bPost ? " after rename" : ""), + pParse->zErrMsg + ); sqlite3_result_error(pCtx, zErr, -1); sqlite3_free(zErr); } /* @@ -1138,11 +1153,14 @@ ** 2. object: Name of object ** 3. Database: Database name (e.g. "main") ** 4. Table: Table name ** 5. iCol: Index of column to rename ** 6. zNew: New column name -** 7. bQuote: True if the new column name should be quoted +** 7. bQuote: Non-zero if the new column name should be quoted. Negative +** if this function is being called to check that the schema +** can still be parsed and symbols resolved after the column +** has been renamed. ** ** Do a column rename operation on the CREATE statement given in zSql. ** The iCol-th column (left-most is 0) of table zTable is renamed from zCol ** into zNew. The name should be quoted if bQuote is true. ** @@ -1435,11 +1453,11 @@ } renameColumnFunc_done: if( rc!=SQLITE_OK ){ if( sParse.zErrMsg ){ - renameColumnParseError(context, argv[1], argv[2], &sParse); + renameColumnParseError(context, (bQuote<0), argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); } } Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -5752,10 +5752,11 @@ if( pOp->p4.z==0 ){ sqlite3SchemaClear(db->aDb[iDb].pSchema); db->mDbFlags &= ~DBFLAG_SchemaKnownOk; rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable); db->mDbFlags |= DBFLAG_SchemaChange; + p->expired = 0; }else #endif { zMaster = MASTER_NAME; initData.db = db; Index: test/altercol.test ================================================================== --- test/altercol.test +++ test/altercol.test @@ -339,11 +339,11 @@ } {{CREATE VIEW xxx AS SELECT a FROM b1 UNION SELECT hello FROM b2 ORDER BY 1 COLLATE nocase}} do_catchsql_test 8.4.5 { CREATE VIEW zzz AS SELECT george, ringo FROM b1; ALTER TABLE b1 RENAME a TO aaa; -} {1 {error processing view zzz: no such column: george}} +} {1 {error in view zzz: no such column: george}} #------------------------------------------------------------------------- # More triggers. # proc do_rename_column_test {tn old new lSchema} { @@ -470,11 +470,11 @@ CREATE VIEW v1 AS SELECT e1.*, x1.c FROM e1, x1; } do_catchsql_test 11.3 { ALTER TABLE x1 RENAME c TO ccc; -} {1 {error processing view v1: no such module: echo}} +} {1 {error in view v1: no such module: echo}} #------------------------------------------------------------------------- # Test some error conditions: # # 1. Renaming a column of a system table, @@ -539,11 +539,11 @@ END; } do_catchsql_test 13.1.2 { ALTER TABLE x1 RENAME COLUMN t TO ttt; -} {1 {error processing trigger tr1: no such table: main.nosuchtable}} +} {1 {error in trigger tr1: no such table: main.nosuchtable}} do_execsql_test 13.1.3 { DROP TRIGGER tr1; CREATE INDEX x1i ON x1(i); SELECT sql FROM sqlite_master WHERE name='x1i'; @@ -554,11 +554,11 @@ UPDATE sqlite_master SET sql = 'CREATE INDEX x1i ON x1(j)' WHERE name='x1i'; } {} do_catchsql_test 13.1.5 { ALTER TABLE x1 RENAME COLUMN t TO ttt; -} {1 {error processing index x1i: no such column: j}} +} {1 {error in index x1i: no such column: j}} do_execsql_test 13.1.6 { UPDATE sqlite_master SET sql = '' WHERE name='x1i'; } {} @@ -605,11 +605,11 @@ $trigger " do_catchsql_test 13.2.$tn.2 { ALTER TABLE x1 RENAME COLUMN t TO ttt; - } "1 {error processing trigger tr1: $error}" + } "1 {error in trigger tr1: $error}" } #------------------------------------------------------------------------- # Passing invalid parameters directly to sqlite_rename_column(). # @@ -647,7 +647,28 @@ } do_execsql_test 15.2 { SELECT sql FROM sqlite_master WHERE type='view'; } {{CREATE VIEW vvv AS SELECT xyz AS d FROM xxx WHERE d=0}} + +#------------------------------------------------------------------------- +# +do_execsql_test 16.0 { + CREATE TABLE t1(a,b,c); + CREATE TABLE t2(d,e,f); + INSERT INTO t1 VALUES(1,2,3); + INSERT INTO t2 VALUES(4,5,6); + CREATE VIEW v4 AS SELECT a, d FROM t1, t2; + SELECT * FROM v4; +} {1 4} + +do_catchsql_test 16.1 { + ALTER TABLE t2 RENAME d TO a; +} {1 {error in view v4 after rename: ambiguous column name: a}} + +do_execsql_test 16.2 { + SELECT * FROM v4; +} {1 4} + +reset_db finish_test