/ Check-in [7908e8a4a3]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Have ALTER TABLE RENAME COLUMN also edit trigger and view definitions.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | alter-table-rename-column
Files: files | file ages | folders
SHA3-256: 7908e8a4a3b9577211a5d3da9c4142c46e9d5872be4a6499ec053f2b547019b8
User & Date: dan 2018-08-18 18:01:58
Context
2018-08-18
18:14
Merge trunk fixes. check-in: ccad277927 user: drh tags: alter-table-rename-column
18:01
Have ALTER TABLE RENAME COLUMN also edit trigger and view definitions. check-in: 7908e8a4a3 user: dan tags: alter-table-rename-column
17:35
Improvements to error handling in ALTER TABLE RENAME COLUMN. Closed-Leaf check-in: 7fa1faeaff user: dan tags: edit-trigger-wrapper
2018-08-14
21:03
Fix a problem when renaming an IPK column that is also part of a child key. check-in: ad15486022 user: dan tags: alter-table-rename-column
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/alter.c.

   813    813     /* Locate the table to be altered */
   814    814     pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
   815    815     if( !pTab ) goto exit_rename_column;
   816    816   
   817    817     /* Cannot alter a system table */
   818    818     if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column;
   819    819   
   820         -  /* Cannot rename columns of a virtual table */
   821         -  if( IsVirtual(pTab) ){
   822         -    sqlite3ErrorMsg(pParse, "cannot rename columns in a virtual table (%s)",
   823         -                    pTab->zName);
   824         -    goto exit_rename_column;
   825         -  }
   826         -
   827    820     /* Which schema holds the table to be altered */  
   828    821     iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
   829    822     assert( iSchema>=0 );
   830    823     zDb = db->aDb[iSchema].zDbSName;
   831    824   
   832    825     /* Make sure the old name really is a column name in the table to be
   833    826     ** altered.  Set iCol to be the index of the column being renamed */
................................................................................
   847    840     */
   848    841     zNew = sqlite3NameFromToken(db, pNew);
   849    842     if( !zNew ) goto exit_rename_column;
   850    843     assert( pNew->n>0 );
   851    844     bQuote = sqlite3Isquote(pNew->z[0]);
   852    845     sqlite3NestedParse(pParse, 
   853    846         "UPDATE \"%w\".%s SET "
   854         -      "sql = sqlite_rename_column(sql, %d, %d, %Q, %Q, %Q) "
   855         -      "WHERE name NOT LIKE 'sqlite_%%' AND ("
   856         -      "   type = 'table' OR (type='index' AND tbl_name = %Q)"
   857         -      ")",
   858         -      zDb, MASTER_NAME, iCol, bQuote, zNew, pTab->zName, zOld, pTab->zName
          847  +      "sql = sqlite_rename_column(sql, %Q, %Q, %d, %Q, %d) "
          848  +      "WHERE name NOT LIKE 'sqlite_%%' AND (type != 'index' OR tbl_name = %Q)"
          849  +      " AND sql NOT LIKE 'create virtual%%'",
          850  +      zDb, MASTER_NAME, 
          851  +      zDb, pTab->zName, iCol, zNew, bQuote,
          852  +      pTab->zName
   859    853     );
   860    854   
   861    855     /* Drop and reload the database schema. */
   862    856     if( pParse->pVdbe ){
   863    857       sqlite3ChangeCookie(pParse, iSchema);
   864    858       sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iSchema, 0);
   865    859     }
................................................................................
   894    888     RenameToken *pNext;    /* Next is a list of all RenameToken objects */
   895    889   };
   896    890   
   897    891   /*
   898    892   ** The context of an ALTER TABLE RENAME COLUMN operation that gets passed
   899    893   ** down into the Walker.
   900    894   */
          895  +typedef struct RenameCtx RenameCtx;
   901    896   struct RenameCtx {
   902    897     RenameToken *pList;             /* List of tokens to overwrite */
   903    898     int nList;                      /* Number of tokens in pList */
   904    899     int iCol;                       /* Index of column being renamed */
          900  +  Table *pTab;                    /* Table being ALTERed */ 
          901  +  const char *zOld;               /* Old column name */
   905    902   };
   906    903   
   907    904   /*
   908    905   ** Add a new RenameToken object mapping parse tree element pPtr into
   909    906   ** token *pToken to the Parse object currently under construction.
   910    907   */
   911    908   void sqlite3RenameToken(Parse *pParse, void *pPtr, Token *pToken){
................................................................................
   963    960         pCtx->pList = pToken;
   964    961         pCtx->nList++;
   965    962         break;
   966    963       }
   967    964     }
   968    965   }
   969    966   
          967  +/*
          968  +** This is a Walker select callback. It does nothing. It is only required
          969  +** because without a dummy callback, sqlite3WalkExpr() and similar do not
          970  +** descend into sub-select statements.
          971  +*/
          972  +static int renameColumnSelectCb(Walker *pWalker, Select *p){
          973  +  return WRC_Continue;
          974  +}
   970    975   
   971    976   /*
   972    977   ** This is a Walker expression callback.
   973    978   **
   974    979   ** For every TK_COLUMN node in the expression tree, search to see
   975    980   ** if the column being references is the column being renamed by an
   976    981   ** ALTER TABLE statement.  If it is, then attach its associated
   977    982   ** RenameToken object to the list of RenameToken objects being
   978    983   ** constructed in RenameCtx object at pWalker->u.pRename.
   979    984   */
   980    985   static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
   981         -  struct RenameCtx *p = pWalker->u.pRename;
   982         -  if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol ){
          986  +  RenameCtx *p = pWalker->u.pRename;
          987  +  if( pExpr->op==TK_TRIGGER 
          988  +   && pExpr->iColumn==p->iCol 
          989  +   && pWalker->pParse->pTriggerTab==p->pTab
          990  +  ){
          991  +    renameTokenFind(pWalker->pParse, p, (void*)pExpr);
          992  +  }else if( pExpr->op==TK_COLUMN 
          993  +   && pExpr->iColumn==p->iCol 
          994  +   && p->pTab==pExpr->pTab
          995  +  ){
   983    996       renameTokenFind(pWalker->pParse, p, (void*)pExpr);
   984    997     }
   985    998     return WRC_Continue;
   986    999   }
   987   1000   
   988   1001   /*
   989   1002   ** The RenameCtx contains a list of tokens that reference a column that
   990         -** is being renamed by an ALTER TABLE statement.  Return the "first"
         1003  +** is being renamed by an ALTER TABLE statement.  Return the "last"
   991   1004   ** RenameToken in the RenameCtx and remove that RenameToken from the
   992         -** RenameContext.  "First" means the first RenameToken encountered when
   993         -** the input SQL from left to right.  Repeated calls to this routine
         1005  +** RenameContext.  "Last" means the last RenameToken encountered when
         1006  +** the input SQL is parsed from left to right.  Repeated calls to this routine
   994   1007   ** return all column name tokens in the order that they are encountered
   995   1008   ** in the SQL statement.
   996   1009   */
   997         -static RenameToken *renameColumnTokenNext(struct RenameCtx *pCtx){
         1010  +static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){
   998   1011     RenameToken *pBest = pCtx->pList;
   999   1012     RenameToken *pToken;
  1000   1013     RenameToken **pp;
  1001   1014   
  1002   1015     for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){
  1003   1016       if( pToken->t.z>pBest->t.z ) pBest = pToken;
  1004   1017     }
  1005   1018     for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext);
  1006   1019     *pp = pBest->pNext;
  1007   1020   
  1008   1021     return pBest;
  1009   1022   }
         1023  +
         1024  +/*
         1025  +** An error occured while parsing or otherwise processing a database
         1026  +** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an
         1027  +** ALTER TABLE RENAME COLUMN program. The error message emitted by the
         1028  +** sub-routine is currently stored in pParse->zErrMsg. This function
         1029  +** adds context to the error message and then stores it in pCtx.
         1030  +*/
         1031  +static void renameColumnParseError(sqlite3_context *pCtx, Parse *pParse){
         1032  +  const char *zT;
         1033  +  const char *zN;
         1034  +  char *zErr;
         1035  +  if( pParse->pNewTable ){
         1036  +    zT = pParse->pNewTable->pSelect ? "view" : "table";
         1037  +    zN = pParse->pNewTable->zName;
         1038  +  }else if( pParse->pNewIndex ){
         1039  +    zT = "index";
         1040  +    zN = pParse->pNewIndex->zName;
         1041  +  }else{
         1042  +    assert( pParse->pNewTrigger );
         1043  +    zT = "trigger";
         1044  +    zN = pParse->pNewTrigger->zName;
         1045  +  }
         1046  +  zErr = sqlite3_mprintf("error processing %s %s: %s", zT, zN, pParse->zErrMsg);
         1047  +  sqlite3_result_error(pCtx, zErr, -1);
         1048  +  sqlite3_free(zErr);
         1049  +}
  1010   1050   
  1011   1051   /*
  1012   1052   ** SQL function:
  1013   1053   **
  1014   1054   **     sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld)
  1015   1055   **
         1056  +**   0. zSql:     SQL statement to rewrite
         1057  +**   1. Database: Database name (e.g. "main")
         1058  +**   2. Table:    Table name
         1059  +**   3. iCol:     Index of column to rename
         1060  +**   4. zNew:     New column name
         1061  +**   5. bQuote: True if the new column name should be quoted
         1062  +**
  1016   1063   ** Do a column rename operation on the CREATE statement given in zSql.
  1017   1064   ** The iCol-th column (left-most is 0) of table zTable is renamed from zCol
  1018   1065   ** into zNew.  The name should be quoted if bQuote is true.
  1019   1066   **
  1020   1067   ** This function is used internally by the ALTER TABLE RENAME COLUMN command.
  1021   1068   ** Though accessible to application code, it is not intended for use by
  1022   1069   ** applications.  The existance of this function, and the way it works,
................................................................................
  1030   1077   */
  1031   1078   static void renameColumnFunc(
  1032   1079     sqlite3_context *context,
  1033   1080     int NotUsed,
  1034   1081     sqlite3_value **argv
  1035   1082   ){
  1036   1083     sqlite3 *db = sqlite3_context_db_handle(context);
  1037         -  struct RenameCtx sCtx;
         1084  +  RenameCtx sCtx;
  1038   1085     const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  1039   1086     int nSql = sqlite3_value_bytes(argv[0]);
  1040         -  int bQuote = sqlite3_value_int(argv[2]);
  1041         -  const char *zNew = (const char*)sqlite3_value_text(argv[3]);
  1042         -  int nNew = sqlite3_value_bytes(argv[3]);
  1043         -  const char *zTable = (const char*)sqlite3_value_text(argv[4]);
  1044         -  const char *zOld = (const char*)sqlite3_value_text(argv[5]);
         1087  +  const char *zDb = (const char*)sqlite3_value_text(argv[1]);
         1088  +  const char *zTable = (const char*)sqlite3_value_text(argv[2]);
         1089  +  int iCol = sqlite3_value_int(argv[3]);
         1090  +  const char *zNew = (const char*)sqlite3_value_text(argv[4]);
         1091  +  int nNew = sqlite3_value_bytes(argv[4]);
         1092  +  int bQuote = sqlite3_value_int(argv[5]);
         1093  +  const char *zOld;
  1045   1094   
  1046   1095     int rc;
  1047   1096     char *zErr = 0;
  1048   1097     Parse sParse;
  1049   1098     Walker sWalker;
  1050   1099     Index *pIdx;
  1051   1100     char *zOut = 0;
  1052   1101   
  1053   1102     char *zQuot = 0;                /* Quoted version of zNew */
  1054   1103     int nQuot = 0;                  /* Length of zQuot in bytes */
  1055   1104     int i;
         1105  +  Table *pTab;
  1056   1106   
  1057   1107     if( zSql==0 ) return;
  1058   1108     if( zNew==0 ) return;
  1059   1109     if( zTable==0 ) return;
  1060         -  if( zOld==0 ) return;
         1110  +  if( iCol<0 ) return;
         1111  +  pTab = sqlite3FindTable(db, zTable, zDb);
         1112  +  if( pTab==0 || iCol>=pTab->nCol ) return;
         1113  +  zOld = pTab->aCol[iCol].zName;
  1061   1114     memset(&sCtx, 0, sizeof(sCtx));
  1062         -  sCtx.iCol = sqlite3_value_int(argv[1]);
  1063         -  if( sCtx.iCol<0 ) return;
         1115  +  sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);
  1064   1116   
         1117  +  /* Parse the SQL statement passed as the first argument. If no error
         1118  +  ** occurs and the parse does not result in a new table, index or
         1119  +  ** trigger object, the database must be corrupt. */
  1065   1120     memset(&sParse, 0, sizeof(sParse));
  1066   1121     sParse.eParseMode = PARSE_MODE_RENAME_COLUMN;
  1067   1122     sParse.db = db;
  1068   1123     sParse.nQueryLoop = 1;
  1069   1124     rc = sqlite3RunParser(&sParse, zSql, &zErr);
  1070         -  assert( sParse.pNewTable==0 || sParse.pNewIndex==0 );
         1125  +  assert( sParse.zErrMsg==0 );
         1126  +  assert( rc!=SQLITE_OK || zErr==0 );
         1127  +  assert( (!!sParse.pNewTable)+(!!sParse.pNewIndex)+(!!sParse.pNewTrigger)<2 );
         1128  +  sParse.zErrMsg = zErr;
  1071   1129     if( db->mallocFailed ) rc = SQLITE_NOMEM;
  1072         -  if( rc==SQLITE_OK && sParse.pNewTable==0 && sParse.pNewIndex==0 ){
         1130  +  if( rc==SQLITE_OK 
         1131  +   && sParse.pNewTable==0 && sParse.pNewIndex==0 && sParse.pNewTrigger==0 
         1132  +  ){
  1073   1133       rc = SQLITE_CORRUPT_BKPT;
  1074   1134     }
  1075   1135   
         1136  +#ifdef SQLITE_DEBUG
         1137  +  /* Ensure that all mappings in the Parse.pRename list really do map to
         1138  +  ** a part of the input string.  */
         1139  +  assert( sqlite3Strlen30(zSql)==nSql );
         1140  +  if( rc==SQLITE_OK ){
         1141  +    RenameToken *pToken;
         1142  +    for(pToken=sParse.pRename; pToken; pToken=pToken->pNext){
         1143  +      assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
         1144  +    }
         1145  +  }
         1146  +#endif
         1147  +
         1148  +  /* Set zQuot to point to a buffer containing a quoted copy of the 
         1149  +  ** identifier zNew. If the corresponding identifier in the original 
         1150  +  ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
         1151  +  ** point to zQuot so that all substitutions are made using the
         1152  +  ** quoted version of the new column name.  */
  1076   1153     if( rc==SQLITE_OK ){
  1077   1154       zQuot = sqlite3_mprintf("\"%w\"", zNew);
  1078   1155       if( zQuot==0 ){
  1079   1156         rc = SQLITE_NOMEM;
  1080   1157       }else{
  1081   1158         nQuot = sqlite3Strlen30(zQuot);
  1082   1159       }
  1083   1160     }
  1084         -
  1085         -  if( rc!=SQLITE_OK ){
  1086         -    if( zErr ){
  1087         -      sqlite3_result_error(context, zErr, -1);
  1088         -    }else{
  1089         -      sqlite3_result_error_code(context, rc);
  1090         -    }
  1091         -    sqlite3DbFree(db, zErr);
  1092         -    goto renameColumnFunc_done;
  1093         -  }
  1094         -
  1095   1161     if( bQuote ){
  1096   1162       zNew = zQuot;
  1097   1163       nNew = nQuot;
  1098   1164     }
  1099   1165   
  1100         -#ifdef SQLITE_DEBUG
  1101         -  assert( sqlite3Strlen30(zSql)==nSql );
  1102         -  {
  1103         -    RenameToken *pToken;
  1104         -    for(pToken=sParse.pRename; pToken; pToken=pToken->pNext){
  1105         -      assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
  1106         -    }
  1107         -  }
  1108         -#endif
  1109         -
  1110   1166     /* Find tokens that need to be replaced. */
  1111   1167     memset(&sWalker, 0, sizeof(Walker));
  1112   1168     sWalker.pParse = &sParse;
  1113   1169     sWalker.xExprCallback = renameColumnExprCb;
         1170  +  sWalker.xSelectCallback = renameColumnSelectCb;
  1114   1171     sWalker.u.pRename = &sCtx;
  1115   1172   
         1173  +  sCtx.pTab = pTab;
         1174  +  if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
  1116   1175     if( sParse.pNewTable ){
  1117         -    int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
  1118         -    FKey *pFKey;
  1119         -    for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
  1120         -      for(i=0; i<pFKey->nCol; i++){
  1121         -        if( bFKOnly==0 && pFKey->aCol[i].iFrom==sCtx.iCol ){
  1122         -          renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
         1176  +    Select *pSelect = sParse.pNewTable->pSelect;
         1177  +    if( pSelect ){
         1178  +      sParse.rc = SQLITE_OK;
         1179  +      sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0);
         1180  +      rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
         1181  +      if( rc==SQLITE_OK ){
         1182  +        sqlite3WalkSelect(&sWalker, pSelect);
         1183  +      }
         1184  +      if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
         1185  +    }else{
         1186  +      /* A regular table */
         1187  +      int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
         1188  +      FKey *pFKey;
         1189  +      assert( sParse.pNewTable->pSelect==0 );
         1190  +      sCtx.pTab = sParse.pNewTable;
         1191  +      if( bFKOnly==0 ){
         1192  +        renameTokenFind(
         1193  +            &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
         1194  +        );
         1195  +        if( sCtx.iCol<0 ){
         1196  +          renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
         1197  +        }
         1198  +        sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
         1199  +        for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
         1200  +          sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
         1201  +        }
         1202  +      }
         1203  +
         1204  +      for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
         1205  +        for(i=0; i<pFKey->nCol; i++){
         1206  +          if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){
         1207  +            renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
         1208  +          }
         1209  +          if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
         1210  +           && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld)
         1211  +          ){
         1212  +            renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol);
         1213  +          }
         1214  +        }
         1215  +      }
         1216  +    }
         1217  +  }else if( sParse.pNewIndex ){
         1218  +    sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
         1219  +    sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
         1220  +  }else{
         1221  +    /* A trigger */
         1222  +    TriggerStep *pStep;
         1223  +    NameContext sNC;
         1224  +    memset(&sNC, 0, sizeof(sNC));
         1225  +    sNC.pParse = &sParse;
         1226  +    sParse.pTriggerTab = sqlite3FindTable(db, sParse.pNewTrigger->table, zDb);
         1227  +    sParse.eTriggerOp = sParse.pNewTrigger->op;
         1228  +
         1229  +    /* Resolve symbols in WHEN clause */
         1230  +    if( sParse.pNewTrigger->pWhen ){
         1231  +      rc = sqlite3ResolveExprNames(&sNC, sParse.pNewTrigger->pWhen);
         1232  +    }
         1233  +
         1234  +    for(pStep=sParse.pNewTrigger->step_list; 
         1235  +        rc==SQLITE_OK && pStep; 
         1236  +        pStep=pStep->pNext
         1237  +    ){
         1238  +      if( pStep->pSelect ) sqlite3SelectPrep(&sParse, pStep->pSelect, &sNC);
         1239  +      if( pStep->zTarget ){ 
         1240  +        Table *pTarget = sqlite3FindTable(db, pStep->zTarget, zDb);
         1241  +        if( pTarget==0 ){
         1242  +          rc = SQLITE_ERROR;
         1243  +        }else{
         1244  +          SrcList sSrc;
         1245  +          memset(&sSrc, 0, sizeof(sSrc));
         1246  +          sSrc.nSrc = 1;
         1247  +          sSrc.a[0].zName = pStep->zTarget;
         1248  +          sSrc.a[0].pTab = pTarget;
         1249  +          sNC.pSrcList = &sSrc;
         1250  +          if( pStep->pWhere ){
         1251  +            rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere);
         1252  +          }
         1253  +          if( rc==SQLITE_OK ){
         1254  +            rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
         1255  +          }
         1256  +          if( pStep->pUpsert ){
         1257  +            Upsert *pUpsert = pStep->pUpsert;
         1258  +            if( rc==SQLITE_OK ){
         1259  +              rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
         1260  +            }
         1261  +            if( rc==SQLITE_OK && pUpsert->pUpsertSet){
         1262  +              ExprList *pUpsertSet = pUpsert->pUpsertSet;
         1263  +              rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet);
         1264  +              if( rc==SQLITE_OK && pTarget==pTab ){
         1265  +                for(i=0; i<pUpsertSet->nExpr; i++){
         1266  +                  char *zName = pUpsertSet->a[i].zName;
         1267  +                  if( 0==sqlite3_stricmp(zName, zOld) ){
         1268  +                    renameTokenFind(&sParse, &sCtx, (void*)zName);
         1269  +                  }
         1270  +                }
         1271  +              }
         1272  +            }
         1273  +            if( rc==SQLITE_OK ){
         1274  +              rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere);
         1275  +            }
         1276  +            if( rc==SQLITE_OK ){
         1277  +              rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
         1278  +            }
         1279  +          }
         1280  +
         1281  +          if( rc==SQLITE_OK && pTarget==pTab ){
         1282  +            if( pStep->pIdList ){
         1283  +              for(i=0; i<pStep->pIdList->nId; i++){
         1284  +                char *zName = pStep->pIdList->a[i].zName;
         1285  +                if( 0==sqlite3_stricmp(zName, zOld) ){
         1286  +                  renameTokenFind(&sParse, &sCtx, (void*)zName);
         1287  +                }
         1288  +              }
         1289  +            }
         1290  +            if( pStep->op==TK_UPDATE ){
         1291  +              assert( pStep->pExprList );
         1292  +              for(i=0; i<pStep->pExprList->nExpr; i++){
         1293  +                char *zName = pStep->pExprList->a[i].zName;
         1294  +                if( 0==sqlite3_stricmp(zName, zOld) ){
         1295  +                  renameTokenFind(&sParse, &sCtx, (void*)zName);
         1296  +                }
         1297  +              }
         1298  +            }
         1299  +          }
  1123   1300           }
  1124         -        if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
  1125         -         && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld)
  1126         -        ){
  1127         -          renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol);
         1301  +      }
         1302  +    }
         1303  +
         1304  +    if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
         1305  +
         1306  +    /* Find tokens to edit in UPDATE OF clause */
         1307  +    if( sParse.pTriggerTab==pTab && sParse.pNewTrigger->pColumns ){
         1308  +      for(i=0; i<sParse.pNewTrigger->pColumns->nId; i++){
         1309  +        char *zName = sParse.pNewTrigger->pColumns->a[i].zName;
         1310  +        if( 0==sqlite3_stricmp(zName, zOld) ){
         1311  +          renameTokenFind(&sParse, &sCtx, (void*)zName);
  1128   1312           }
  1129   1313         }
  1130   1314       }
  1131         -    if( bFKOnly==0 ){
  1132         -      renameTokenFind(
  1133         -          &sParse, &sCtx, (void*)sParse.pNewTable->aCol[sCtx.iCol].zName
  1134         -      );
  1135         -      assert( sCtx.iCol>=0 );
  1136         -      if( sParse.pNewTable->iPKey==sCtx.iCol ){
  1137         -        renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
  1138         -        sCtx.iCol = -1;
  1139         -      }
  1140         -      sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
  1141         -      for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
  1142         -        sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
         1315  +
         1316  +    /* Find tokens to edit in WHEN clause */
         1317  +    sqlite3WalkExpr(&sWalker, sParse.pNewTrigger->pWhen);
         1318  +
         1319  +    /* Find tokens to edit in trigger steps */
         1320  +    for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){
         1321  +      sqlite3WalkSelect(&sWalker, pStep->pSelect);
         1322  +      sqlite3WalkExpr(&sWalker, pStep->pWhere);
         1323  +      sqlite3WalkExprList(&sWalker, pStep->pExprList);
         1324  +      if( pStep->pUpsert ){
         1325  +        Upsert *pUpsert = pStep->pUpsert;
         1326  +        sqlite3WalkExprList(&sWalker, pUpsert->pUpsertTarget);
         1327  +        sqlite3WalkExprList(&sWalker, pUpsert->pUpsertSet);
         1328  +        sqlite3WalkExpr(&sWalker, pUpsert->pUpsertWhere);
         1329  +        sqlite3WalkExpr(&sWalker, pUpsert->pUpsertTargetWhere);
  1143   1330         }
  1144   1331       }
  1145         -  }else{
  1146         -    sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
  1147         -    sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
  1148   1332     }
  1149   1333   
         1334  +  /* At this point sCtx.pList contains a list of RenameToken objects
         1335  +  ** corresponding to all tokens in the input SQL that must be replaced
         1336  +  ** with the new column name. All that remains is to construct and
         1337  +  ** return the edited SQL string. */
         1338  +  assert( rc==SQLITE_OK );
  1150   1339     assert( nQuot>=nNew );
  1151   1340     zOut = sqlite3DbMallocZero(db, nSql + sCtx.nList*nQuot + 1);
  1152   1341     if( zOut ){
  1153   1342       int nOut = nSql;
  1154   1343       memcpy(zOut, zSql, nSql);
  1155   1344       while( sCtx.pList ){
  1156   1345         int iOff;                   /* Offset of token to replace in zOut */
................................................................................
  1176   1365         }
  1177   1366         memcpy(&zOut[iOff], zReplace, nReplace);
  1178   1367         sqlite3DbFree(db, pBest);
  1179   1368       }
  1180   1369   
  1181   1370       sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT);
  1182   1371       sqlite3DbFree(db, zOut);
         1372  +  }else{
         1373  +    rc = SQLITE_NOMEM;
  1183   1374     }
  1184   1375   
  1185   1376   renameColumnFunc_done:
         1377  +  if( rc!=SQLITE_OK ){
         1378  +    if( sParse.zErrMsg ){
         1379  +      renameColumnParseError(context, &sParse);
         1380  +    }else{
         1381  +      sqlite3_result_error_code(context, rc);
         1382  +    }
         1383  +  }
         1384  +
  1186   1385     if( sParse.pVdbe ){
  1187   1386       sqlite3VdbeFinalize(sParse.pVdbe);
  1188   1387     }
  1189   1388     sqlite3DeleteTable(db, sParse.pNewTable);
  1190   1389     if( sParse.pNewIndex ) sqlite3FreeIndex(db, sParse.pNewIndex);
         1390  +  sqlite3DeleteTrigger(db, sParse.pNewTrigger);
  1191   1391     renameTokenFree(db, sParse.pRename);
  1192   1392     renameTokenFree(db, sCtx.pList);
         1393  +  sqlite3DbFree(db, sParse.zErrMsg);
  1193   1394     sqlite3ParserReset(&sParse);
  1194   1395     sqlite3_free(zQuot);
  1195   1396   }
  1196   1397   
  1197   1398   /*
  1198   1399   ** Register built-in functions used to help implement ALTER TABLE
  1199   1400   */

Changes to src/build.c.

  2171   2171     if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
  2172   2172   
  2173   2173     /* Make a copy of the entire SELECT statement that defines the view.
  2174   2174     ** This will force all the Expr.token.z values to be dynamically
  2175   2175     ** allocated rather than point to the input string - which means that
  2176   2176     ** they will persist after the current sqlite3_exec() call returns.
  2177   2177     */
  2178         -  p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
         2178  +  if( IN_RENAME_COLUMN ){
         2179  +    p->pSelect = pSelect;
         2180  +    pSelect = 0;
         2181  +  }else{
         2182  +    p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
         2183  +  }
  2179   2184     p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
  2180   2185     if( db->mallocFailed ) goto create_view_fail;
  2181   2186   
  2182   2187     /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  2183   2188     ** the end.
  2184   2189     */
  2185   2190     sEnd = pParse->sLastToken;
................................................................................
  3685   3690   
  3686   3691   /*
  3687   3692   ** Append a new element to the given IdList.  Create a new IdList if
  3688   3693   ** need be.
  3689   3694   **
  3690   3695   ** A new IdList is returned, or NULL if malloc() fails.
  3691   3696   */
  3692         -IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){
         3697  +IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
         3698  +  sqlite3 *db = pParse->db;
  3693   3699     int i;
  3694   3700     if( pList==0 ){
  3695   3701       pList = sqlite3DbMallocZero(db, sizeof(IdList) );
  3696   3702       if( pList==0 ) return 0;
  3697   3703     }
  3698   3704     pList->a = sqlite3ArrayAllocate(
  3699   3705         db,
................................................................................
  3703   3709         &i
  3704   3710     );
  3705   3711     if( i<0 ){
  3706   3712       sqlite3IdListDelete(db, pList);
  3707   3713       return 0;
  3708   3714     }
  3709   3715     pList->a[i].zName = sqlite3NameFromToken(db, pToken);
         3716  +  if( IN_RENAME_COLUMN && pList->a[i].zName ){
         3717  +    sqlite3RenameToken(pParse, (void*)pList->a[i].zName, pToken);
         3718  +  }
  3710   3719     return pList;
  3711   3720   }
  3712   3721   
  3713   3722   /*
  3714   3723   ** Delete an IdList.
  3715   3724   */
  3716   3725   void sqlite3IdListDelete(sqlite3 *db, IdList *pList){

Changes to src/expr.c.

  1662   1662     if( pList ){
  1663   1663       struct ExprList_item *pItem;
  1664   1664       assert( pList->nExpr>0 );
  1665   1665       pItem = &pList->a[pList->nExpr-1];
  1666   1666       assert( pItem->zName==0 );
  1667   1667       pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
  1668   1668       if( dequote ) sqlite3Dequote(pItem->zName);
         1669  +    if( IN_RENAME_COLUMN ){
         1670  +      sqlite3RenameToken(pParse, (void*)pItem->zName, pName);
         1671  +    }
  1669   1672     }
  1670   1673   }
  1671   1674   
  1672   1675   /*
  1673   1676   ** Set the ExprList.a[].zSpan element of the most recently added item
  1674   1677   ** on the expression list.
  1675   1678   **

Changes to src/parse.y.

   904    904   %destructor idlist_opt {sqlite3IdListDelete(pParse->db, $$);}
   905    905   %type idlist {IdList*}
   906    906   %destructor idlist {sqlite3IdListDelete(pParse->db, $$);}
   907    907   
   908    908   idlist_opt(A) ::= .                       {A = 0;}
   909    909   idlist_opt(A) ::= LP idlist(X) RP.    {A = X;}
   910    910   idlist(A) ::= idlist(A) COMMA nm(Y).
   911         -    {A = sqlite3IdListAppend(pParse->db,A,&Y);}
          911  +    {A = sqlite3IdListAppend(pParse,A,&Y);}
   912    912   idlist(A) ::= nm(Y).
   913         -    {A = sqlite3IdListAppend(pParse->db,0,&Y); /*A-overwrites-Y*/}
          913  +    {A = sqlite3IdListAppend(pParse,0,&Y); /*A-overwrites-Y*/}
   914    914   
   915    915   /////////////////////////// Expression Processing /////////////////////////////
   916    916   //
   917    917   
   918    918   %type expr {Expr*}
   919    919   %destructor expr {sqlite3ExprDelete(pParse->db, $$);}
   920    920   %type term {Expr*}
................................................................................
  1447   1447   
  1448   1448   
  1449   1449   %type trigger_cmd {TriggerStep*}
  1450   1450   %destructor trigger_cmd {sqlite3DeleteTriggerStep(pParse->db, $$);}
  1451   1451   // UPDATE 
  1452   1452   trigger_cmd(A) ::=
  1453   1453      UPDATE(B) orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z) scanpt(E).  
  1454         -   {A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R, B.z, E);}
         1454  +   {A = sqlite3TriggerUpdateStep(pParse, &X, Y, Z, R, B.z, E);}
  1455   1455   
  1456   1456   // INSERT
  1457   1457   trigger_cmd(A) ::= scanpt(B) insert_cmd(R) INTO
  1458   1458                         trnm(X) idlist_opt(F) select(S) upsert(U) scanpt(Z). {
  1459         -   A = sqlite3TriggerInsertStep(pParse->db,&X,F,S,R,U,B,Z);/*A-overwrites-R*/
         1459  +   A = sqlite3TriggerInsertStep(pParse,&X,F,S,R,U,B,Z);/*A-overwrites-R*/
  1460   1460   }
  1461   1461   // DELETE
  1462   1462   trigger_cmd(A) ::= DELETE(B) FROM trnm(X) tridxby where_opt(Y) scanpt(E).
  1463         -   {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y, B.z, E);}
         1463  +   {A = sqlite3TriggerDeleteStep(pParse, &X, Y, B.z, E);}
  1464   1464   
  1465   1465   // SELECT
  1466   1466   trigger_cmd(A) ::= scanpt(B) select(X) scanpt(E).
  1467   1467      {A = sqlite3TriggerSelectStep(pParse->db, X, B, E); /*A-overwrites-X*/}
  1468   1468   
  1469   1469   // The special RAISE expression that may occur in trigger programs
  1470   1470   expr(A) ::= RAISE LP IGNORE RP.  {

Changes to src/resolve.c.

   756    756             ** sqlite_version() that might change over time cannot be used
   757    757             ** in an index. */
   758    758             notValid(pParse, pNC, "non-deterministic functions",
   759    759                      NC_IdxExpr|NC_PartIdx);
   760    760           }
   761    761         }
   762    762   
          763  +      if( 0==IN_RENAME_COLUMN ){
   763    764   #ifndef SQLITE_OMIT_WINDOWFUNC
   764         -      assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX)
          765  +        assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX)
   765    766             || (pDef->xValue==0 && pDef->xInverse==0)
   766    767             || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
   767         -      );
   768         -      if( pDef && pDef->xValue==0 && pExpr->pWin ){
   769         -        sqlite3ErrorMsg(pParse, 
   770         -            "%.*s() may not be used as a window function", nId, zId
   771    768           );
   772         -        pNC->nErr++;
   773         -      }else if( 
   774         -            (is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
   775         -         || (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin)
   776         -         || (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
   777         -      ){
   778         -        const char *zType;
   779         -        if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){
   780         -          zType = "window";
   781         -        }else{
   782         -          zType = "aggregate";
          769  +        if( pDef && pDef->xValue==0 && pExpr->pWin ){
          770  +          sqlite3ErrorMsg(pParse, 
          771  +              "%.*s() may not be used as a window function", nId, zId
          772  +          );
          773  +          pNC->nErr++;
          774  +        }else if( 
          775  +              (is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
          776  +           || (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin)
          777  +           || (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
          778  +        ){
          779  +          const char *zType;
          780  +          if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){
          781  +            zType = "window";
          782  +          }else{
          783  +            zType = "aggregate";
          784  +          }
          785  +          sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
          786  +          pNC->nErr++;
          787  +          is_agg = 0;
   783    788           }
   784         -        sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()", zType, nId,zId);
   785         -        pNC->nErr++;
   786         -        is_agg = 0;
   787         -      }
   788    789   #else
   789         -      if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
   790         -        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
   791         -        pNC->nErr++;
   792         -        is_agg = 0;
   793         -      }
          790  +        if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
          791  +          sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
          792  +          pNC->nErr++;
          793  +          is_agg = 0;
          794  +        }
   794    795   #endif
   795         -      else if( no_such_func && pParse->db->init.busy==0
          796  +        else if( no_such_func && pParse->db->init.busy==0 && !IN_RENAME_COLUMN
   796    797   #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
   797         -                && pParse->explain==0
          798  +                  && pParse->explain==0
   798    799   #endif
   799         -      ){
   800         -        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
   801         -        pNC->nErr++;
   802         -      }else if( wrong_num_args ){
   803         -        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
   804         -             nId, zId);
   805         -        pNC->nErr++;
   806         -      }
   807         -      if( is_agg ){
          800  +        ){
          801  +          sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
          802  +          pNC->nErr++;
          803  +        }else if( wrong_num_args ){
          804  +          sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
          805  +               nId, zId);
          806  +          pNC->nErr++;
          807  +        }
          808  +        if( is_agg ){
   808    809   #ifndef SQLITE_OMIT_WINDOWFUNC
   809         -        pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg);
          810  +          pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg);
   810    811   #else
   811         -        pNC->ncFlags &= ~NC_AllowAgg;
          812  +          pNC->ncFlags &= ~NC_AllowAgg;
   812    813   #endif
          814  +        }
   813    815         }
   814    816         sqlite3WalkExprList(pWalker, pList);
   815    817         if( is_agg ){
   816    818   #ifndef SQLITE_OMIT_WINDOWFUNC
   817    819           if( pExpr->pWin ){
   818    820             Select *pSel = pNC->pWinSelect;
   819    821             sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition);

Changes to src/sqliteInt.h.

  3883   3883     void sqlite3AutoincrementEnd(Parse *pParse);
  3884   3884   #else
  3885   3885   # define sqlite3AutoincrementBegin(X)
  3886   3886   # define sqlite3AutoincrementEnd(X)
  3887   3887   #endif
  3888   3888   void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
  3889   3889   void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
  3890         -IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
         3890  +IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
  3891   3891   int sqlite3IdListIndex(IdList*,const char*);
  3892   3892   SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
  3893   3893   SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
  3894   3894   SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
  3895   3895                                         Token*, Select*, Expr*, IdList*);
  3896   3896   void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
  3897   3897   void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
................................................................................
  4045   4045     void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *,
  4046   4046                               int, int, int);
  4047   4047     void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
  4048   4048     void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
  4049   4049     void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
  4050   4050     TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
  4051   4051                                           const char*,const char*);
  4052         -  TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
         4052  +  TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
  4053   4053                                           Select*,u8,Upsert*,
  4054   4054                                           const char*,const char*);
  4055         -  TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8,
         4055  +  TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8,
  4056   4056                                           const char*,const char*);
  4057         -  TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*,
         4057  +  TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
  4058   4058                                           const char*,const char*);
  4059   4059     void sqlite3DeleteTrigger(sqlite3*, Trigger*);
  4060   4060     void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
  4061   4061     u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
  4062   4062   # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
  4063   4063   # define sqlite3IsToplevel(p) ((p)->pToplevel==0)
  4064   4064   #else

Changes to src/tokenize.c.

   693    693     if( !IN_SPECIAL_PARSE ){
   694    694       /* If the pParse->declareVtab flag is set, do not delete any table 
   695    695       ** structure built up in pParse->pNewTable. The calling code (see vtab.c)
   696    696       ** will take responsibility for freeing the Table structure.
   697    697       */
   698    698       sqlite3DeleteTable(db, pParse->pNewTable);
   699    699     }
          700  +  if( !IN_RENAME_COLUMN ){
          701  +    sqlite3DeleteTrigger(db, pParse->pNewTrigger);
          702  +  }
   700    703   
   701    704     if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
   702         -  sqlite3DeleteTrigger(db, pParse->pNewTrigger);
   703    705     sqlite3DbFree(db, pParse->pVList);
   704    706     while( pParse->pAinc ){
   705    707       AutoincInfo *p = pParse->pAinc;
   706    708       pParse->pAinc = p->pNext;
   707    709       sqlite3DbFreeNN(db, p);
   708    710     }
   709    711     while( pParse->pZombieTab ){

Changes to src/trigger.c.

   177    177     /* Check that the trigger name is not reserved and that no trigger of the
   178    178     ** specified name exists */
   179    179     zName = sqlite3NameFromToken(db, pName);
   180    180     if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
   181    181       goto trigger_cleanup;
   182    182     }
   183    183     assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   184         -  if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
   185         -    if( !noErr ){
   186         -      sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
   187         -    }else{
   188         -      assert( !db->init.busy );
   189         -      sqlite3CodeVerifySchema(pParse, iDb);
          184  +  if( !IN_RENAME_COLUMN ){
          185  +    if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
          186  +      if( !noErr ){
          187  +        sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
          188  +      }else{
          189  +        assert( !db->init.busy );
          190  +        sqlite3CodeVerifySchema(pParse, iDb);
          191  +      }
          192  +      goto trigger_cleanup;
   190    193       }
   191         -    goto trigger_cleanup;
   192    194     }
   193    195   
   194    196     /* Do not create a trigger on a system table */
   195    197     if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
   196    198       sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
   197    199       goto trigger_cleanup;
   198    200     }
................................................................................
   208    210     if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
   209    211       sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
   210    212           " trigger on table: %S", pTableName, 0);
   211    213       goto trigger_cleanup;
   212    214     }
   213    215   
   214    216   #ifndef SQLITE_OMIT_AUTHORIZATION
   215         -  {
          217  +  if( !IN_RENAME_COLUMN ){
   216    218       int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
   217    219       int code = SQLITE_CREATE_TRIGGER;
   218    220       const char *zDb = db->aDb[iTabDb].zDbSName;
   219    221       const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb;
   220    222       if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
   221    223       if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
   222    224         goto trigger_cleanup;
................................................................................
   242    244     pTrigger->zName = zName;
   243    245     zName = 0;
   244    246     pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
   245    247     pTrigger->pSchema = db->aDb[iDb].pSchema;
   246    248     pTrigger->pTabSchema = pTab->pSchema;
   247    249     pTrigger->op = (u8)op;
   248    250     pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
   249         -  pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
   250         -  pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
          251  +  if( IN_RENAME_COLUMN ){
          252  +    pTrigger->pWhen = pWhen;
          253  +    pWhen = 0;
          254  +  }else{
          255  +    pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
          256  +  }
          257  +  pTrigger->pColumns = pColumns;
          258  +  pColumns = 0;
   251    259     assert( pParse->pNewTrigger==0 );
   252    260     pParse->pNewTrigger = pTrigger;
   253    261   
   254    262   trigger_cleanup:
   255    263     sqlite3DbFree(db, zName);
   256    264     sqlite3SrcListDelete(db, pTableName);
   257    265     sqlite3IdListDelete(db, pColumns);
................................................................................
   291    299     sqlite3TokenInit(&nameToken, pTrig->zName);
   292    300     sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
   293    301     if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) 
   294    302      || sqlite3FixExpr(&sFix, pTrig->pWhen) 
   295    303     ){
   296    304       goto triggerfinish_cleanup;
   297    305     }
          306  +
          307  +#ifndef SQLITE_OMIT_ALTERTABLE
          308  +  if( IN_RENAME_COLUMN ){
          309  +    assert( !db->init.busy );
          310  +    pParse->pNewTrigger = pTrig;
          311  +    pTrig = 0;
          312  +  }else
          313  +#endif
   298    314   
   299    315     /* if we are not initializing,
   300    316     ** build the sqlite_master entry
   301    317     */
   302    318     if( !db->init.busy ){
   303    319       Vdbe *v;
   304    320       char *z;
................................................................................
   333    349         pLink->pNext = pTab->pTrigger;
   334    350         pTab->pTrigger = pLink;
   335    351       }
   336    352     }
   337    353   
   338    354   triggerfinish_cleanup:
   339    355     sqlite3DeleteTrigger(db, pTrig);
   340         -  assert( !pParse->pNewTrigger );
          356  +  assert( IN_RENAME_COLUMN || !pParse->pNewTrigger );
   341    357     sqlite3DeleteTriggerStep(db, pStepList);
   342    358   }
   343    359   
   344    360   /*
   345    361   ** Duplicate a range of text from an SQL statement, then convert all
   346    362   ** whitespace characters into ordinary space characters.
   347    363   */
................................................................................
   408    424   ** Build a trigger step out of an INSERT statement.  Return a pointer
   409    425   ** to the new trigger step.
   410    426   **
   411    427   ** The parser calls this routine when it sees an INSERT inside the
   412    428   ** body of a trigger.
   413    429   */
   414    430   TriggerStep *sqlite3TriggerInsertStep(
   415         -  sqlite3 *db,        /* The database connection */
          431  +  Parse *pParse,      /* Parser */
   416    432     Token *pTableName,  /* Name of the table into which we insert */
   417    433     IdList *pColumn,    /* List of columns in pTableName to insert into */
   418    434     Select *pSelect,    /* A SELECT statement that supplies values */
   419    435     u8 orconf,          /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
   420    436     Upsert *pUpsert,    /* ON CONFLICT clauses for upsert */
   421    437     const char *zStart, /* Start of SQL text */
   422    438     const char *zEnd    /* End of SQL text */
   423    439   ){
          440  +  sqlite3 *db = pParse->db;
   424    441     TriggerStep *pTriggerStep;
   425    442   
   426    443     assert(pSelect != 0 || db->mallocFailed);
   427    444   
   428    445     pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName, zStart, zEnd);
   429    446     if( pTriggerStep ){
   430         -    pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
          447  +    if( IN_RENAME_COLUMN ){
          448  +      pTriggerStep->pSelect = pSelect;
          449  +      pSelect = 0;
          450  +    }else{
          451  +      pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
          452  +    }
   431    453       pTriggerStep->pIdList = pColumn;
   432    454       pTriggerStep->pUpsert = pUpsert;
   433    455       pTriggerStep->orconf = orconf;
   434    456     }else{
   435    457       testcase( pColumn );
   436    458       sqlite3IdListDelete(db, pColumn);
   437    459       testcase( pUpsert );
................................................................................
   444    466   
   445    467   /*
   446    468   ** Construct a trigger step that implements an UPDATE statement and return
   447    469   ** a pointer to that trigger step.  The parser calls this routine when it
   448    470   ** sees an UPDATE statement inside the body of a CREATE TRIGGER.
   449    471   */
   450    472   TriggerStep *sqlite3TriggerUpdateStep(
   451         -  sqlite3 *db,         /* The database connection */
          473  +  Parse *pParse,          /* Parser */
   452    474     Token *pTableName,   /* Name of the table to be updated */
   453    475     ExprList *pEList,    /* The SET clause: list of column and new values */
   454    476     Expr *pWhere,        /* The WHERE clause */
   455    477     u8 orconf,           /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
   456    478     const char *zStart,  /* Start of SQL text */
   457    479     const char *zEnd     /* End of SQL text */
   458    480   ){
          481  +  sqlite3 *db = pParse->db;
   459    482     TriggerStep *pTriggerStep;
   460    483   
   461    484     pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName, zStart, zEnd);
   462    485     if( pTriggerStep ){
   463         -    pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
   464         -    pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
          486  +    if( IN_RENAME_COLUMN ){
          487  +      pTriggerStep->pExprList = pEList;
          488  +      pTriggerStep->pWhere = pWhere;
          489  +      pEList = 0;
          490  +      pWhere = 0;
          491  +    }else{
          492  +      pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
          493  +      pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
          494  +    }
   465    495       pTriggerStep->orconf = orconf;
   466    496     }
   467    497     sqlite3ExprListDelete(db, pEList);
   468    498     sqlite3ExprDelete(db, pWhere);
   469    499     return pTriggerStep;
   470    500   }
   471    501   
   472    502   /*
   473    503   ** Construct a trigger step that implements a DELETE statement and return
   474    504   ** a pointer to that trigger step.  The parser calls this routine when it
   475    505   ** sees a DELETE statement inside the body of a CREATE TRIGGER.
   476    506   */
   477    507   TriggerStep *sqlite3TriggerDeleteStep(
   478         -  sqlite3 *db,            /* Database connection */
          508  +  Parse *pParse,          /* Parser */
   479    509     Token *pTableName,      /* The table from which rows are deleted */
   480    510     Expr *pWhere,           /* The WHERE clause */
   481    511     const char *zStart,     /* Start of SQL text */
   482    512     const char *zEnd        /* End of SQL text */
   483    513   ){
          514  +  sqlite3 *db = pParse->db;
   484    515     TriggerStep *pTriggerStep;
   485    516   
   486    517     pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName, zStart, zEnd);
   487    518     if( pTriggerStep ){
   488         -    pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
          519  +    if( IN_RENAME_COLUMN ){
          520  +      pTriggerStep->pWhere = pWhere;
          521  +      pWhere = 0;
          522  +    }else{
          523  +      pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
          524  +    }
   489    525       pTriggerStep->orconf = OE_Default;
   490    526     }
   491    527     sqlite3ExprDelete(db, pWhere);
   492    528     return pTriggerStep;
   493    529   }
   494    530   
   495    531   /* 

Changes to test/altercol.test.

    21     21   set testprefix altercol
    22     22   
    23     23   # If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
    24     24   ifcapable !altertable {
    25     25     finish_test
    26     26     return
    27     27   }
           28  +
           29  +# Drop all the tables and views in the 'main' database of database connect
           30  +# [db]. Sort the objects by name before dropping them.
           31  +#
           32  +proc drop_all_tables_and_views {db} {
           33  +  set SQL {
           34  +    SELECT name, type FROM sqlite_master 
           35  +    WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%'
           36  +    ORDER BY 1
           37  +  }
           38  +  foreach {z t} [db eval $SQL] {
           39  +    db eval "DROP $t $z"
           40  +  }
           41  +}
    28     42   
    29     43   foreach {tn before after} {
    30     44     1 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB)}
    31     45       {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB)}
    32     46   
    33     47     2 {CREATE TABLE t1(a INTEGER, x TEXT, "b" BLOB)}
    34     48       {CREATE TABLE t1(a INTEGER, x TEXT, "d" BLOB)}
................................................................................
    61     75       {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(d, c)}}
    62     76   
    63     77    12 {CREATE TABLE t1(a, b, c);   CREATE INDEX t1i ON t1(b+b+b+b, c) WHERE b>0}
    64     78       {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(d+d+d+d, c) WHERE d>0}}
    65     79   
    66     80    13 {CREATE TABLE t1(a, b, c, FOREIGN KEY (b) REFERENCES t2)}
    67     81       {CREATE TABLE t1(a, d, c, FOREIGN KEY (d) REFERENCES t2)}
           82  +
           83  + 14 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, PRIMARY KEY(b))}
           84  +    {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, PRIMARY KEY(d))}
    68     85   
    69     86    15 {CREATE TABLE t1(a INTEGER, b INTEGER, c BLOB, PRIMARY KEY(b))}
    70     87       {CREATE TABLE t1(a INTEGER, d INTEGER, c BLOB, PRIMARY KEY(d))}
    71     88   
    72     89    16 {CREATE TABLE t1(a INTEGER, b INTEGER PRIMARY KEY, c BLOB)}
    73     90       {CREATE TABLE t1(a INTEGER, d INTEGER PRIMARY KEY, c BLOB)}
    74     91   
................................................................................
   118    135   do_execsql_test -db db2 2.3 { SELECT biglongname FROM t3 }
   119    136   
   120    137   #-------------------------------------------------------------------------
   121    138   #
   122    139   do_execsql_test 3.0 {
   123    140     CREATE TABLE t4(x, y, z);
   124    141     CREATE TRIGGER ttt AFTER INSERT ON t4 WHEN new.y<0 BEGIN
   125         -    SELECT 1, 2, 3, 4;
          142  +    SELECT x, y, z FROM t4;
          143  +    DELETE FROM t4 WHERE y=32;
          144  +    UPDATE t4 SET x=y+1, y=0 WHERE y=32;
          145  +    INSERT INTO t4(x, y, z) SELECT 4, 5, 6 WHERE 0;
   126    146     END;
   127    147     INSERT INTO t4 VALUES(3, 2, 1);
   128    148   }
   129    149   
   130    150   do_execsql_test 3.1 {
   131    151     ALTER TABLE t4 RENAME y TO abc;
   132    152     SELECT sql FROM sqlite_master WHERE name='t4';
   133    153   } {{CREATE TABLE t4(x, abc, z)}}
   134    154   
   135         -db close
   136         -sqlite3 db test.db
   137         -
   138    155   do_execsql_test 3.2 {
   139    156     SELECT * FROM t4;
   140    157   } {3 2 1}
   141    158   
   142         -# do_execsql_test 3.3 { INSERT INTO t4 VALUES(6, 5, 4); } {}
          159  +do_execsql_test 3.3 { INSERT INTO t4 VALUES(6, 5, 4); } {}
          160  +
          161  +do_execsql_test 3.4 { SELECT sql FROM sqlite_master WHERE type='trigger' } {
          162  +{CREATE TRIGGER ttt AFTER INSERT ON t4 WHEN new.abc<0 BEGIN
          163  +    SELECT x, abc, z FROM t4;
          164  +    DELETE FROM t4 WHERE abc=32;
          165  +    UPDATE t4 SET x=abc+1, abc=0 WHERE abc=32;
          166  +    INSERT INTO t4(x, abc, z) SELECT 4, 5, 6 WHERE 0;
          167  +  END}
          168  +}
   143    169   
   144    170   #-------------------------------------------------------------------------
   145    171   #
   146    172   do_execsql_test 4.0 {
   147    173     CREATE TABLE c1(a, b, FOREIGN KEY (a, b) REFERENCES p1(c, d));
   148    174     CREATE TABLE p1(c, d, PRIMARY KEY(c, d));
   149    175     PRAGMA foreign_keys = 1;
................................................................................
   213    239     ALTER TABLE "blob" RENAME COLUMN "a1" TO [where];
   214    240   } {0 {}}
   215    241   
   216    242   do_execsql_test 6.3 {
   217    243     SELECT "where" FROM blob;
   218    244   } {}
   219    245   
   220         -finish_test
          246  +#-------------------------------------------------------------------------
          247  +# Triggers.
          248  +#
          249  +reset_db
          250  +do_execsql_test 7.0 {
          251  +  CREATE TABLE c(x);
          252  +  INSERT INTO c VALUES(0);
          253  +  CREATE TABLE t6("col a", "col b", "col c");
          254  +  CREATE TRIGGER zzz AFTER UPDATE OF "col a", "col c" ON t6 BEGIN
          255  +    UPDATE c SET x=x+1;
          256  +  END;
          257  +}
          258  +
          259  +do_execsql_test 7.1.1 {
          260  +  INSERT INTO t6 VALUES(0, 0, 0);
          261  +  UPDATE t6 SET "col c" = 1;
          262  +  SELECT * FROM c;
          263  +} {1}
          264  +
          265  +do_execsql_test 7.1.2 {
          266  +  ALTER TABLE t6 RENAME "col c" TO "col 3";
          267  +}
          268  +
          269  +do_execsql_test 7.1.3 {
          270  +  UPDATE t6 SET "col 3" = 0;
          271  +  SELECT * FROM c;
          272  +} {2}
          273  +
          274  +#-------------------------------------------------------------------------
          275  +# Views.
          276  +#
          277  +reset_db
          278  +do_execsql_test 8.0 {
          279  +  CREATE TABLE a1(x INTEGER, y TEXT, z BLOB, PRIMARY KEY(x));
          280  +  CREATE TABLE a2(a, b, c);
          281  +  CREATE VIEW v1 AS SELECT x, y, z FROM a1;
          282  +}
          283  +
          284  +do_execsql_test 8.1 {
          285  +  ALTER TABLE a1 RENAME y TO yyy;
          286  +  SELECT sql FROM sqlite_master WHERE type='view';
          287  +} {{CREATE VIEW v1 AS SELECT x, yyy, z FROM a1}}
          288  +
          289  +do_execsql_test 8.2.1 {
          290  +  DROP VIEW v1;
          291  +  CREATE VIEW v2 AS SELECT x, x+x, a, a+a FROM a1, a2;
          292  +} {}
          293  +do_execsql_test 8.2.2 {
          294  +  ALTER TABLE a1 RENAME x TO xxx;
          295  +}
          296  +do_execsql_test 8.2.3 {
          297  +  SELECT sql FROM sqlite_master WHERE type='view';
          298  +} {{CREATE VIEW v2 AS SELECT xxx, xxx+xxx, a, a+a FROM a1, a2}}
          299  +
          300  +do_execsql_test 8.3.1 {
          301  +  DROP TABLE a2;
          302  +  DROP VIEW v2;
          303  +  CREATE TABLE a2(a INTEGER PRIMARY KEY, b, c);
          304  +  CREATE VIEW v2 AS SELECT xxx, xxx+xxx, a, a+a FROM a1, a2;
          305  +} {}
          306  +do_execsql_test 8.3.2 {
          307  +  ALTER TABLE a1 RENAME xxx TO x;
          308  +}
          309  +do_execsql_test 8.3.3 {
          310  +  SELECT sql FROM sqlite_master WHERE type='view';
          311  +} {{CREATE VIEW v2 AS SELECT x, x+x, a, a+a FROM a1, a2}}
          312  +
          313  +do_execsql_test 8.4.0 {
          314  +  CREATE TABLE b1(a, b, c);
          315  +  CREATE TABLE b2(x, y, z);
          316  +}
          317  +
          318  +do_execsql_test 8.4.1 {
          319  +  CREATE VIEW vvv AS SELECT c+c || coalesce(c, c) FROM b1, b2 WHERE x=c GROUP BY c HAVING c>0;
          320  +  ALTER TABLE b1 RENAME c TO "a;b";
          321  +  SELECT sql FROM sqlite_master WHERE name='vvv';
          322  +} {{CREATE VIEW vvv AS SELECT "a;b"+"a;b" || coalesce("a;b", "a;b") FROM b1, b2 WHERE x="a;b" GROUP BY "a;b" HAVING "a;b">0}}
          323  +
          324  +do_execsql_test 8.4.2 {
          325  +  CREATE VIEW www AS SELECT b FROM b1 UNION ALL SELECT y FROM b2;
          326  +  ALTER TABLE b1 RENAME b TO bbb;
          327  +  SELECT sql FROM sqlite_master WHERE name='www';
          328  +} {{CREATE VIEW www AS SELECT bbb FROM b1 UNION ALL SELECT y FROM b2}}
          329  +
          330  +db collate nocase {string compare}
          331  +
          332  +do_execsql_test 8.4.3 {
          333  +  CREATE VIEW xxx AS SELECT a FROM b1 UNION SELECT x FROM b2 ORDER BY 1 COLLATE nocase;
          334  +}
          335  +
          336  +do_execsql_test 8.4.4 {
          337  +  ALTER TABLE b2 RENAME x TO hello;
          338  +  SELECT sql FROM sqlite_master WHERE name='xxx';
          339  +} {{CREATE VIEW xxx AS SELECT a FROM b1 UNION SELECT hello FROM b2 ORDER BY 1 COLLATE nocase}}
          340  +
          341  +do_catchsql_test 8.4.5 {
          342  +  CREATE VIEW zzz AS SELECT george, ringo FROM b1;
          343  +  ALTER TABLE b1 RENAME a TO aaa;
          344  +} {1 {error processing view zzz: no such column: george}}
          345  +
          346  +#-------------------------------------------------------------------------
          347  +# More triggers.
          348  +#
          349  +proc do_rename_column_test {tn old new lSchema} {
          350  +  for {set i 0} {$i < 2} {incr i} {
          351  +    drop_all_tables_and_views db
          352  +
          353  +    set lSorted [list]
          354  +    foreach sql $lSchema { 
          355  +      execsql $sql 
          356  +      lappend lSorted [string trim $sql]
          357  +    }
          358  +    set lSorted [lsort $lSorted]
          359  +
          360  +    do_execsql_test $tn.$i.1 {
          361  +      SELECT sql FROM sqlite_master WHERE sql!='' ORDER BY 1
          362  +    } $lSorted
          363  +
          364  +    if {$i==1} {
          365  +      db close
          366  +      sqlite3 db test.db
          367  +    }
          368  +
          369  +    do_execsql_test $tn.$i.2 "ALTER TABLE t1 RENAME $old TO $new"
          370  +
          371  +    do_execsql_test $tn.$i.3 {
          372  +      SELECT sql FROM sqlite_master ORDER BY 1
          373  +    } [string map [list $old $new] $lSorted]
          374  +  }
          375  +}
          376  +
          377  +foreach {tn old new lSchema} {
          378  +  1 _x_ _xxx_ {
          379  +    { CREATE TABLE t1(a, b, _x_) }
          380  +    { CREATE TRIGGER AFTER INSERT ON t1 BEGIN
          381  +        SELECT _x_ FROM t1;
          382  +      END }
          383  +  }
          384  +
          385  +  2 _x_ _xxx_ {
          386  +    { CREATE TABLE t1(a, b, _x_) }
          387  +    { CREATE TABLE t2(c, d, e) }
          388  +    { CREATE TRIGGER ttt AFTER INSERT ON t2 BEGIN
          389  +        SELECT _x_ FROM t1;
          390  +      END }
          391  +  }
          392  +
          393  +  3 _x_ _xxx_ {
          394  +    { CREATE TABLE t1(a, b, _x_ INTEGER, PRIMARY KEY(_x_), CHECK(_x_>0)) }
          395  +    { CREATE TABLE t2(c, d, e) }
          396  +    { CREATE TRIGGER ttt AFTER UPDATE  ON t1 BEGIN
          397  +        INSERT INTO t2 VALUES(new.a, new.b, new._x_);
          398  +      END }
          399  +  }
          400  +
          401  +  4 _x_ _xxx_ {
          402  +    { CREATE TABLE t1(a, b, _x_ INTEGER, PRIMARY KEY(_x_), CHECK(_x_>0)) }
          403  +    { CREATE TRIGGER ttt AFTER UPDATE  ON t1 BEGIN
          404  +        INSERT INTO t1 VALUES(new.a, new.b, new._x_)
          405  +          ON CONFLICT (_x_) WHERE _x_>10 DO UPDATE SET _x_ = _x_+1;
          406  +      END }
          407  +  }
          408  +} {
          409  +  do_rename_column_test 9.$tn $old $new $lSchema
          410  +}
          411  +
          412  +#-------------------------------------------------------------------------
          413  +# Test that views can be edited even if there are missing collation 
          414  +# sequences or user defined functions.
          415  +#
          416  +reset_db
          417  +
          418  +foreach {tn old new lSchema} {
          419  +  1 _x_ _xxx_ {
          420  +    { CREATE TABLE t1(a, b, _x_) }
          421  +    { CREATE VIEW s1 AS SELECT a, b, _x_ FROM t1 WHERE _x_='abc' COLLATE xyz }
          422  +  }
          423  +
          424  +  2 _x_ _xxx_ {
          425  +    { CREATE TABLE t1(a, b, _x_) }
          426  +    { CREATE VIEW v1 AS SELECT a, b, _x_ FROM t1 WHERE scalar(_x_) }
          427  +  }
          428  +
          429  +  3 _x_ _xxx_ {
          430  +    { CREATE TABLE t1(a, b, _x_) }
          431  +    { CREATE VIEW v1 AS SELECT a, b, _x_ FROM t1 WHERE _x_ = unicode(1, 2, 3) }
          432  +  }
          433  +
          434  +  4 _x_ _xxx_ {
          435  +    { CREATE TABLE t1(a, b, _x_) }
          436  +    { CREATE VIRTUAL TABLE e1 USING echo(t1) }
          437  +  }
          438  +} {
          439  +  register_echo_module db
          440  +  do_rename_column_test 10.$tn $old $new $lSchema
          441  +}
          442  +
          443  +#--------------------------------------------------------------------------
          444  +# Test that if a view or trigger refers to a virtual table for which the
          445  +# module is not available, RENAME COLUMN cannot proceed.
          446  +#
          447  +reset_db
          448  +register_echo_module db
          449  +do_execsql_test 11.0 {
          450  +  CREATE TABLE x1(a, b, c);
          451  +  CREATE VIRTUAL TABLE e1 USING echo(x1);
          452  +}
          453  +db close
          454  +sqlite3 db test.db
          455  +
          456  +do_execsql_test 11.1 {
          457  +  ALTER TABLE x1 RENAME b TO bbb;
          458  +  SELECT sql FROM sqlite_master;
          459  +} { {CREATE TABLE x1(a, bbb, c)} {CREATE VIRTUAL TABLE e1 USING echo(x1)} }
          460  +
          461  +do_execsql_test 11.2 {
          462  +  CREATE VIEW v1 AS SELECT e1.*, x1.c FROM e1, x1;
          463  +}
          464  +
          465  +do_catchsql_test 11.3 {
          466  +  ALTER TABLE x1 RENAME c TO ccc;
          467  +} {1 {error processing view v1: no such module: echo}}
   221    468   
          469  +finish_test