/ Check-in [fa0fc01e]
Login

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

Overview
Comment:Experimental implementation of ALTER TABLE ... RENAME COLUMN. Still buggy.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | alter-table-rename-column
Files: files | file ages | folders
SHA3-256: fa0fc01eb48a864f0a3d43f9b805d5ed2e530846ee0c34fcbc2eabd9e5696277
User & Date: dan 2018-08-09 20:47:01
Context
2018-08-10
14:23
Fix a problem with renaming columns on tables with REFERENCES clauses that specify a large number of columns. check-in: d48f7bbd user: dan tags: alter-table-rename-column
2018-08-09
20:47
Experimental implementation of ALTER TABLE ... RENAME COLUMN. Still buggy. check-in: fa0fc01e user: dan tags: alter-table-rename-column
18:36
When a column must be a constant due to WHERE clause and the value of that column is being coded as a constant, make sure the affinity is correct. check-in: 7404ea83 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/alter.c.

   221    221       zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
   222    222          zSql, zTableName, tname.z+tname.n);
   223    223       sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
   224    224     }
   225    225   }
   226    226   #endif   /* !SQLITE_OMIT_TRIGGER */
   227    227   
   228         -/*
   229         -** Register built-in functions used to help implement ALTER TABLE
   230         -*/
   231         -void sqlite3AlterFunctions(void){
   232         -  static FuncDef aAlterTableFuncs[] = {
   233         -    FUNCTION(sqlite_rename_table,   2, 0, 0, renameTableFunc),
   234         -#ifndef SQLITE_OMIT_TRIGGER
   235         -    FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
   236         -#endif
   237         -#ifndef SQLITE_OMIT_FOREIGN_KEY
   238         -    FUNCTION(sqlite_rename_parent,  3, 0, 0, renameParentFunc),
   239         -#endif
   240         -  };
   241         -  sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
   242         -}
   243         -
   244    228   /*
   245    229   ** This function is used to create the text of expressions of the form:
   246    230   **
   247    231   **   name=<constant1> OR name=<constant2> OR ...
   248    232   **
   249    233   ** If argument zWhere is NULL, then a pointer string containing the text 
   250    234   ** "name=<constant>" is returned, where <constant> is the quoted version
................................................................................
   801    785     if( !v ) goto exit_begin_add_column;
   802    786     sqlite3ChangeCookie(pParse, iDb);
   803    787   
   804    788   exit_begin_add_column:
   805    789     sqlite3SrcListDelete(db, pSrc);
   806    790     return;
   807    791   }
          792  +
          793  +void sqlite3AlterRenameColumn(
          794  +  Parse *pParse, 
          795  +  SrcList *pSrc, 
          796  +  Token *pOld, 
          797  +  Token *pNew
          798  +){
          799  +  sqlite3 *db = pParse->db;
          800  +  Table *pTab;                    /* Table being updated */
          801  +  int iCol;                       /* Index of column being renamed */
          802  +  char *zOld = 0;
          803  +  char *zNew = 0;
          804  +  const char *zDb;
          805  +  int iSchema;
          806  +
          807  +  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
          808  +  if( !pTab ) goto exit_rename_column;
          809  +  iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
          810  +  assert( iSchema>=0 );
          811  +  zDb = db->aDb[iSchema].zDbSName;
          812  +
          813  +  zOld = sqlite3NameFromToken(db, pOld);
          814  +  if( !zOld ) goto exit_rename_column;
          815  +  for(iCol=0; iCol<pTab->nCol; iCol++){
          816  +    if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
          817  +  }
          818  +  if( iCol==pTab->nCol ){
          819  +    sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
          820  +    goto exit_rename_column;
          821  +  }
          822  +
          823  +  zNew = sqlite3NameFromToken(db, pNew);
          824  +  if( !zNew ) goto exit_rename_column;
          825  +
          826  +  sqlite3NestedParse(pParse, 
          827  +      "UPDATE \"%w\".%s SET "
          828  +      "sql = sqlite_rename_column(sql, %d, %Q) "
          829  +      "WHERE type IN ('table', 'index') AND tbl_name = %Q AND sql!=''",
          830  +      zDb, MASTER_NAME, iCol, zNew, pTab->zName
          831  +  );
          832  +
          833  +  /* Drop and reload the internal table schema. */
          834  +  reloadTableSchema(pParse, pTab, pTab->zName);
          835  +
          836  + exit_rename_column:
          837  +  sqlite3SrcListDelete(db, pSrc);
          838  +  sqlite3DbFree(db, zOld);
          839  +  sqlite3DbFree(db, zNew);
          840  +  return;
          841  +}
          842  +
          843  +struct RenameToken {
          844  +  void *p;
          845  +  Token t;
          846  +  RenameToken *pNext;
          847  +};
          848  +
          849  +struct RenameCtx {
          850  +  RenameToken *pList;             /* List of tokens to overwrite */
          851  +  int nList;                      /* Number of tokens in pList */
          852  +  int iCol;                       /* Index of column being renamed */
          853  +};
          854  +
          855  +void sqlite3RenameToken(Parse *pParse, void *pPtr, Token *pToken){
          856  +  RenameToken *pNew;
          857  +  pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
          858  +  if( pNew ){
          859  +    pNew->p = pPtr;
          860  +    pNew->t = *pToken;
          861  +    pNew->pNext = pParse->pRename;
          862  +    pParse->pRename = pNew;
          863  +  }
          864  +}
          865  +
          866  +void sqlite3MoveRenameToken(Parse *pParse, void *pTo, void *pFrom){
          867  +  RenameToken *p;
          868  +  for(p=pParse->pRename; p; p=p->pNext){
          869  +    if( p->p==pFrom ){
          870  +      p->p = pTo;
          871  +      break;
          872  +    }
          873  +  }
          874  +  assert( p );
          875  +}
          876  +
          877  +static void renameTokenFree(sqlite3 *db, RenameToken *pToken){
          878  +  RenameToken *pNext;
          879  +  RenameToken *p;
          880  +  for(p=pToken; p; p=pNext){
          881  +    pNext = p->pNext;
          882  +    sqlite3DbFree(db, p);
          883  +  }
          884  +}
          885  +
          886  +static RenameToken *renameTokenFind(Parse *pParse, void *pPtr){
          887  +  RenameToken **pp;
          888  +  for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
          889  +    if( (*pp)->p==pPtr ){
          890  +      RenameToken *pToken = *pp;
          891  +      *pp = pToken->pNext;
          892  +      pToken->pNext = 0;
          893  +      return pToken;
          894  +    }
          895  +  }
          896  +  return 0;
          897  +}
          898  +
          899  +static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
          900  +  struct RenameCtx *p = pWalker->u.pRename;
          901  +  if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol ){
          902  +    RenameToken *pTok = renameTokenFind(pWalker->pParse, (void*)pExpr);
          903  +    if( pTok ){
          904  +      pTok->pNext = p->pList;
          905  +      p->pList = pTok;
          906  +      p->nList++;
          907  +    }
          908  +  }
          909  +  return WRC_Continue;
          910  +}
          911  +
          912  +static RenameToken *renameColumnTokenNext(struct RenameCtx *pCtx){
          913  +  RenameToken *pBest = pCtx->pList;
          914  +  RenameToken *pToken;
          915  +  RenameToken **pp;
          916  +
          917  +  for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){
          918  +    if( pToken->t.z>pBest->t.z ) pBest = pToken;
          919  +  }
          920  +  for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext);
          921  +  *pp = pBest->pNext;
          922  +
          923  +  return pBest;
          924  +}
          925  +
          926  +static void renameColumnFunc(
          927  +  sqlite3_context *context,
          928  +  int NotUsed,
          929  +  sqlite3_value **argv
          930  +){
          931  +  sqlite3 *db = sqlite3_context_db_handle(context);
          932  +  struct RenameCtx sCtx;
          933  +  const char *zSql = sqlite3_value_text(argv[0]);
          934  +  int nSql = sqlite3_value_bytes(argv[0]);
          935  +  const char *zNew = sqlite3_value_text(argv[2]);
          936  +  int nNew = sqlite3_value_bytes(argv[2]);
          937  +  int rc;
          938  +  char *zErr = 0;
          939  +  Parse sParse;
          940  +  Walker sWalker;
          941  +  Table *pTab;
          942  +  Index *pIdx;
          943  +  char *zOut = 0;
          944  +
          945  +  char *zQuot = 0;                /* Quoted version of zNew */
          946  +  int nQuot = 0;                  /* Length of zQuot in bytes */
          947  +  int i;
          948  +
          949  +  memset(&sCtx, 0, sizeof(sCtx));
          950  +  sCtx.iCol = sqlite3_value_int(argv[1]);
          951  +
          952  +  memset(&sParse, 0, sizeof(sParse));
          953  +  sParse.eParseMode = PARSE_MODE_RENAME_COLUMN;
          954  +  sParse.db = db;
          955  +  sParse.nQueryLoop = 1;
          956  +  rc = sqlite3RunParser(&sParse, zSql, &zErr);
          957  +  assert( sParse.pNewTable==0 || sParse.pNewIndex==0 );
          958  +  if( rc==SQLITE_OK && sParse.pNewTable==0 && sParse.pNewIndex==0 ){
          959  +    rc = SQLITE_CORRUPT_BKPT;
          960  +  }
          961  +
          962  +  if( rc==SQLITE_OK ){
          963  +    zQuot = sqlite3_mprintf("\"%w\"", zNew);
          964  +    if( zQuot==0 ){
          965  +      rc = SQLITE_NOMEM;
          966  +    }else{
          967  +      nQuot = sqlite3Strlen30(zQuot);
          968  +    }
          969  +  }
          970  +
          971  +  if( rc!=SQLITE_OK ){
          972  +    if( zErr ){
          973  +      sqlite3_result_error(context, zErr, -1);
          974  +    }else{
          975  +      sqlite3_result_error_code(context, rc);
          976  +    }
          977  +    sqlite3DbFree(db, zErr);
          978  +    sqlite3_free(zQuot);
          979  +    return;
          980  +  }
          981  +
          982  +  for(i=0; i<nNew; i++){
          983  +    if( sqlite3IsIdChar(zNew[i])==0 ){
          984  +      zNew = zQuot;
          985  +      nNew = nQuot;
          986  +      break;
          987  +    }
          988  +  }
          989  +
          990  +#ifdef SQLITE_DEBUG
          991  +  assert( sqlite3Strlen30(zSql)==nSql );
          992  +  {
          993  +    RenameToken *pToken;
          994  +    for(pToken=sParse.pRename; pToken; pToken=pToken->pNext){
          995  +      assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
          996  +    }
          997  +  }
          998  +#endif
          999  +
         1000  +  /* Find tokens that need to be replaced. */
         1001  +  memset(&sWalker, 0, sizeof(Walker));
         1002  +  sWalker.pParse = &sParse;
         1003  +  sWalker.xExprCallback = renameColumnExprCb;
         1004  +  sWalker.u.pRename = &sCtx;
         1005  +
         1006  +  if( sParse.pNewTable ){
         1007  +    FKey *pFKey;
         1008  +    sCtx.pList = renameTokenFind(
         1009  +        &sParse, (void*)sParse.pNewTable->aCol[sCtx.iCol].zName
         1010  +    );
         1011  +    sCtx.nList = 1;
         1012  +    sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
         1013  +    for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
         1014  +      sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
         1015  +    }
         1016  +
         1017  +    for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
         1018  +      for(i=0; i<pFKey->nCol; i++){
         1019  +        if( pFKey->aCol[i].iFrom==sCtx.iCol ){
         1020  +          RenameToken *pTok = renameTokenFind(&sParse, (void*)&pFKey->aCol[i]);
         1021  +          if( pTok ){
         1022  +            pTok->pNext = sCtx.pList;
         1023  +            sCtx.pList = pTok;
         1024  +            sCtx.nList++;
         1025  +          }
         1026  +        }
         1027  +      }
         1028  +    }
         1029  +  }else{
         1030  +    sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
         1031  +    sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
         1032  +  }
         1033  +
         1034  +  zOut = sqlite3DbMallocZero(db, nSql + sCtx.nList*nNew + 1);
         1035  +  if( zOut ){
         1036  +    int nOut = nSql;
         1037  +    memcpy(zOut, zSql, nSql);
         1038  +    while( sCtx.pList ){
         1039  +      int iOff;                   /* Offset of token to replace in zOut */
         1040  +      RenameToken *pBest = renameColumnTokenNext(&sCtx);
         1041  +
         1042  +      int nReplace;
         1043  +      const char *zReplace;
         1044  +      if( sqlite3IsIdChar(*pBest->t.z) ){
         1045  +        nReplace = nNew;
         1046  +        zReplace = zNew;
         1047  +      }else{
         1048  +        nReplace = nQuot;
         1049  +        zReplace = zQuot;
         1050  +      }
         1051  +
         1052  +      iOff = pBest->t.z - zSql;
         1053  +      if( pBest->t.n!=nReplace ){
         1054  +        memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], 
         1055  +            nOut - (iOff + pBest->t.n)
         1056  +        );
         1057  +        nOut += nReplace - pBest->t.n;
         1058  +        zOut[nOut] = '\0';
         1059  +      }
         1060  +      memcpy(&zOut[iOff], zReplace, nReplace);
         1061  +      sqlite3DbFree(db, pBest);
         1062  +    }
         1063  +
         1064  +    sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT);
         1065  +    sqlite3DbFree(db, zOut);
         1066  +  }
         1067  +
         1068  +  if( sParse.pVdbe ){
         1069  +    sqlite3VdbeFinalize(sParse.pVdbe);
         1070  +  }
         1071  +  sqlite3DeleteTable(db, sParse.pNewTable);
         1072  +  if( sParse.pNewIndex ) sqlite3FreeIndex(db, sParse.pNewIndex);
         1073  +  renameTokenFree(db, sParse.pRename);
         1074  +  sqlite3ParserReset(&sParse);
         1075  +  sqlite3_free(zQuot);
         1076  +}
         1077  +
         1078  +/*
         1079  +** Register built-in functions used to help implement ALTER TABLE
         1080  +*/
         1081  +void sqlite3AlterFunctions(void){
         1082  +  static FuncDef aAlterTableFuncs[] = {
         1083  +    FUNCTION(sqlite_rename_table,   2, 0, 0, renameTableFunc),
         1084  +    FUNCTION(sqlite_rename_column,   3, 0, 0, renameColumnFunc),
         1085  +#ifndef SQLITE_OMIT_TRIGGER
         1086  +    FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
         1087  +#endif
         1088  +#ifndef SQLITE_OMIT_FOREIGN_KEY
         1089  +    FUNCTION(sqlite_rename_parent,  3, 0, 0, renameParentFunc),
         1090  +#endif
         1091  +  };
         1092  +  sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
         1093  +}
   808   1094   #endif  /* SQLITE_ALTER_TABLE */

Changes to src/auth.c.

   203    203   ){
   204    204     sqlite3 *db = pParse->db;
   205    205     int rc;
   206    206   
   207    207     /* Don't do any authorization checks if the database is initialising
   208    208     ** or if the parser is being invoked from within sqlite3_declare_vtab.
   209    209     */
   210         -  if( db->init.busy || IN_DECLARE_VTAB ){
          210  +  if( db->init.busy || IN_SPECIAL_PARSE ){
   211    211       return SQLITE_OK;
   212    212     }
   213    213   
   214    214     if( db->xAuth==0 ){
   215    215       return SQLITE_OK;
   216    216     }
   217    217   

Changes to src/build.c.

   435    435     }
   436    436     return p;
   437    437   }
   438    438   
   439    439   /*
   440    440   ** Reclaim the memory used by an index
   441    441   */
   442         -static void freeIndex(sqlite3 *db, Index *p){
          442  +void sqlite3FreeIndex(sqlite3 *db, Index *p){
   443    443   #ifndef SQLITE_OMIT_ANALYZE
   444    444     sqlite3DeleteIndexSamples(db, p);
   445    445   #endif
   446    446     sqlite3ExprDelete(db, p->pPartIdxWhere);
   447    447     sqlite3ExprListDelete(db, p->aColExpr);
   448    448     sqlite3DbFree(db, p->zColAff);
   449    449     if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl);
................................................................................
   475    475         ** indices. */
   476    476         p = pIndex->pTable->pIndex;
   477    477         while( ALWAYS(p) && p->pNext!=pIndex ){ p = p->pNext; }
   478    478         if( ALWAYS(p && p->pNext==pIndex) ){
   479    479           p->pNext = pIndex->pNext;
   480    480         }
   481    481       }
   482         -    freeIndex(db, pIndex);
          482  +    sqlite3FreeIndex(db, pIndex);
   483    483     }
   484    484     db->mDbFlags |= DBFLAG_SchemaChange;
   485    485   }
   486    486   
   487    487   /*
   488    488   ** Look through the list of open database files in db->aDb[] and if
   489    489   ** any have been closed, remove them from the list.  Reallocate the
................................................................................
   621    621         char *zName = pIndex->zName; 
   622    622         TESTONLY ( Index *pOld = ) sqlite3HashInsert(
   623    623            &pIndex->pSchema->idxHash, zName, 0
   624    624         );
   625    625         assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
   626    626         assert( pOld==pIndex || pOld==0 );
   627    627       }
   628         -    freeIndex(db, pIndex);
          628  +    sqlite3FreeIndex(db, pIndex);
   629    629     }
   630    630   
   631    631     /* Delete any foreign keys attached to this table. */
   632    632     sqlite3FkDelete(db, pTable);
   633    633   
   634    634     /* Delete the Table structure itself.
   635    635     */
................................................................................
   909    909     /* Make sure the new table name does not collide with an existing
   910    910     ** index or table name in the same database.  Issue an error message if
   911    911     ** it does. The exception is if the statement being parsed was passed
   912    912     ** to an sqlite3_declare_vtab() call. In that case only the column names
   913    913     ** and types will be used, so there is no need to test for namespace
   914    914     ** collisions.
   915    915     */
   916         -  if( !IN_DECLARE_VTAB ){
          916  +  if( !IN_SPECIAL_PARSE ){
   917    917       char *zDb = db->aDb[iDb].zDbSName;
   918    918       if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
   919    919         goto begin_table_error;
   920    920       }
   921    921       pTable = sqlite3FindTable(db, zName, zDb);
   922    922       if( pTable ){
   923    923         if( !noErr ){
................................................................................
  1068   1068     if( (p = pParse->pNewTable)==0 ) return;
  1069   1069     if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
  1070   1070       sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
  1071   1071       return;
  1072   1072     }
  1073   1073     z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2);
  1074   1074     if( z==0 ) return;
         1075  +  if( IN_RENAME_COLUMN ) sqlite3RenameToken(pParse, (void*)z, pName);
  1075   1076     memcpy(z, pName->z, pName->n);
  1076   1077     z[pName->n] = 0;
  1077   1078     sqlite3Dequote(z);
  1078   1079     for(i=0; i<p->nCol; i++){
  1079   1080       if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){
  1080   1081         sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
  1081   1082         sqlite3DbFree(db, z);
................................................................................
  2757   2758         }
  2758   2759         if( j>=p->nCol ){
  2759   2760           sqlite3ErrorMsg(pParse, 
  2760   2761             "unknown column \"%s\" in foreign key definition", 
  2761   2762             pFromCol->a[i].zName);
  2762   2763           goto fk_end;
  2763   2764         }
         2765  +      if( IN_RENAME_COLUMN ){
         2766  +        sqlite3MoveRenameToken(pParse, &pFKey->aCol[i], &pFromCol->a[i]);
         2767  +      }
  2764   2768       }
  2765   2769     }
  2766   2770     if( pToCol ){
  2767   2771       for(i=0; i<nCol; i++){
  2768   2772         int n = sqlite3Strlen30(pToCol->a[i].zName);
  2769   2773         pFKey->aCol[i].zCol = z;
  2770   2774         memcpy(z, pToCol->a[i].zName, n);
................................................................................
  3095   3099     if( pName ){
  3096   3100       zName = sqlite3NameFromToken(db, pName);
  3097   3101       if( zName==0 ) goto exit_create_index;
  3098   3102       assert( pName->z!=0 );
  3099   3103       if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
  3100   3104         goto exit_create_index;
  3101   3105       }
  3102         -    if( !db->init.busy ){
  3103         -      if( sqlite3FindTable(db, zName, 0)!=0 ){
  3104         -        sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
         3106  +    if( !IN_RENAME_COLUMN ){
         3107  +      if( !db->init.busy ){
         3108  +        if( sqlite3FindTable(db, zName, 0)!=0 ){
         3109  +          sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
         3110  +          goto exit_create_index;
         3111  +        }
         3112  +      }
         3113  +      if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
         3114  +        if( !ifNotExist ){
         3115  +          sqlite3ErrorMsg(pParse, "index %s already exists", zName);
         3116  +        }else{
         3117  +          assert( !db->init.busy );
         3118  +          sqlite3CodeVerifySchema(pParse, iDb);
         3119  +        }
  3105   3120           goto exit_create_index;
  3106   3121         }
  3107   3122       }
  3108         -    if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
  3109         -      if( !ifNotExist ){
  3110         -        sqlite3ErrorMsg(pParse, "index %s already exists", zName);
  3111         -      }else{
  3112         -        assert( !db->init.busy );
  3113         -        sqlite3CodeVerifySchema(pParse, iDb);
  3114         -      }
  3115         -      goto exit_create_index;
  3116         -    }
  3117   3123     }else{
  3118   3124       int n;
  3119   3125       Index *pLoop;
  3120   3126       for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
  3121   3127       zName = sqlite3MPrintf(db, "sqlite_autoindex_%s_%d", pTab->zName, n);
  3122   3128       if( zName==0 ){
  3123   3129         goto exit_create_index;
................................................................................
  3124   3130       }
  3125   3131   
  3126   3132       /* Automatic index names generated from within sqlite3_declare_vtab()
  3127   3133       ** must have names that are distinct from normal automatic index names.
  3128   3134       ** The following statement converts "sqlite3_autoindex..." into
  3129   3135       ** "sqlite3_butoindex..." in order to make the names distinct.
  3130   3136       ** The "vtab_err.test" test demonstrates the need of this statement. */
  3131         -    if( IN_DECLARE_VTAB ) zName[7]++;
         3137  +    if( IN_SPECIAL_PARSE ) zName[7]++;
  3132   3138     }
  3133   3139   
  3134   3140     /* Check for authorization to create an index.
  3135   3141     */
  3136   3142   #ifndef SQLITE_OMIT_AUTHORIZATION
  3137         -  {
         3143  +  if( !IN_RENAME_COLUMN ){
  3138   3144       const char *zDb = pDb->zDbSName;
  3139   3145       if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){
  3140   3146         goto exit_create_index;
  3141   3147       }
  3142   3148       i = SQLITE_CREATE_INDEX;
  3143   3149       if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX;
  3144   3150       if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){
................................................................................
  3217   3223     ** a table column, store that column in aiColumn[].  For general expressions,
  3218   3224     ** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[].
  3219   3225     **
  3220   3226     ** TODO: Issue a warning if two or more columns of the index are identical.
  3221   3227     ** TODO: Issue a warning if the table primary key is used as part of the
  3222   3228     ** index key.
  3223   3229     */
  3224         -  for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
         3230  +  pListItem = pList->a;
         3231  +  if( IN_RENAME_COLUMN ){
         3232  +    pIndex->aColExpr = pList;
         3233  +    pList = 0;
         3234  +  }
         3235  +  for(i=0; i<pIndex->nKeyCol; i++, pListItem++){
  3225   3236       Expr *pCExpr;                  /* The i-th index expression */
  3226   3237       int requestedSortOrder;        /* ASC or DESC on the i-th expression */
  3227   3238       const char *zColl;             /* Collation sequence name */
  3228   3239   
  3229   3240       sqlite3StringToId(pListItem->pExpr);
  3230   3241       sqlite3ResolveSelfReference(pParse, pTab, NC_IdxExpr, pListItem->pExpr, 0);
  3231   3242       if( pParse->nErr ) goto exit_create_index;
................................................................................
  3233   3244       if( pCExpr->op!=TK_COLUMN ){
  3234   3245         if( pTab==pParse->pNewTable ){
  3235   3246           sqlite3ErrorMsg(pParse, "expressions prohibited in PRIMARY KEY and "
  3236   3247                                   "UNIQUE constraints");
  3237   3248           goto exit_create_index;
  3238   3249         }
  3239   3250         if( pIndex->aColExpr==0 ){
  3240         -        ExprList *pCopy = sqlite3ExprListDup(db, pList, 0);
  3241         -        pIndex->aColExpr = pCopy;
  3242         -        if( !db->mallocFailed ){
  3243         -          assert( pCopy!=0 );
  3244         -          pListItem = &pCopy->a[i];
  3245         -        }
         3251  +        pIndex->aColExpr = pList;
         3252  +        pList = 0;
  3246   3253         }
  3247   3254         j = XN_EXPR;
  3248   3255         pIndex->aiColumn[i] = XN_EXPR;
  3249   3256         pIndex->uniqNotNull = 0;
  3250   3257       }else{
  3251   3258         j = pCExpr->iColumn;
  3252   3259         assert( j<=0x7fff );
................................................................................
  3377   3384           }
  3378   3385           if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType;
  3379   3386           goto exit_create_index;
  3380   3387         }
  3381   3388       }
  3382   3389     }
  3383   3390   
  3384         -  /* Link the new Index structure to its table and to the other
  3385         -  ** in-memory database structures. 
  3386         -  */
  3387         -  assert( pParse->nErr==0 );
  3388         -  if( db->init.busy ){
  3389         -    Index *p;
  3390         -    assert( !IN_DECLARE_VTAB );
  3391         -    assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
  3392         -    p = sqlite3HashInsert(&pIndex->pSchema->idxHash, 
  3393         -                          pIndex->zName, pIndex);
  3394         -    if( p ){
  3395         -      assert( p==pIndex );  /* Malloc must have failed */
  3396         -      sqlite3OomFault(db);
  3397         -      goto exit_create_index;
  3398         -    }
  3399         -    db->mDbFlags |= DBFLAG_SchemaChange;
  3400         -    if( pTblName!=0 ){
  3401         -      pIndex->tnum = db->init.newTnum;
  3402         -    }
  3403         -  }
  3404         -
  3405         -  /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
  3406         -  ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
  3407         -  ** emit code to allocate the index rootpage on disk and make an entry for
  3408         -  ** the index in the sqlite_master table and populate the index with
  3409         -  ** content.  But, do not do this if we are simply reading the sqlite_master
  3410         -  ** table to parse the schema, or if this index is the PRIMARY KEY index
  3411         -  ** of a WITHOUT ROWID table.
  3412         -  **
  3413         -  ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY
  3414         -  ** or UNIQUE index in a CREATE TABLE statement.  Since the table
  3415         -  ** has just been created, it contains no data and the index initialization
  3416         -  ** step can be skipped.
  3417         -  */
  3418         -  else if( HasRowid(pTab) || pTblName!=0 ){
  3419         -    Vdbe *v;
  3420         -    char *zStmt;
  3421         -    int iMem = ++pParse->nMem;
  3422         -
  3423         -    v = sqlite3GetVdbe(pParse);
  3424         -    if( v==0 ) goto exit_create_index;
  3425         -
  3426         -    sqlite3BeginWriteOperation(pParse, 1, iDb);
  3427         -
  3428         -    /* Create the rootpage for the index using CreateIndex. But before
  3429         -    ** doing so, code a Noop instruction and store its address in 
  3430         -    ** Index.tnum. This is required in case this index is actually a 
  3431         -    ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In 
  3432         -    ** that case the convertToWithoutRowidTable() routine will replace
  3433         -    ** the Noop with a Goto to jump over the VDBE code generated below. */
  3434         -    pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
  3435         -    sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);
  3436         -
  3437         -    /* Gather the complete text of the CREATE INDEX statement into
  3438         -    ** the zStmt variable
         3391  +  if( !IN_RENAME_COLUMN ){
         3392  +
         3393  +    /* Link the new Index structure to its table and to the other
         3394  +    ** in-memory database structures. 
         3395  +    */
         3396  +    assert( pParse->nErr==0 );
         3397  +    if( db->init.busy ){
         3398  +      Index *p;
         3399  +      assert( !IN_SPECIAL_PARSE );
         3400  +      assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
         3401  +      p = sqlite3HashInsert(&pIndex->pSchema->idxHash, 
         3402  +          pIndex->zName, pIndex);
         3403  +      if( p ){
         3404  +        assert( p==pIndex );  /* Malloc must have failed */
         3405  +        sqlite3OomFault(db);
         3406  +        goto exit_create_index;
         3407  +      }
         3408  +      db->mDbFlags |= DBFLAG_SchemaChange;
         3409  +      if( pTblName!=0 ){
         3410  +        pIndex->tnum = db->init.newTnum;
         3411  +      }
         3412  +    }
         3413  +
         3414  +    /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
         3415  +    ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
         3416  +    ** emit code to allocate the index rootpage on disk and make an entry for
         3417  +    ** the index in the sqlite_master table and populate the index with
         3418  +    ** content.  But, do not do this if we are simply reading the sqlite_master
         3419  +    ** table to parse the schema, or if this index is the PRIMARY KEY index
         3420  +    ** of a WITHOUT ROWID table.
         3421  +    **
         3422  +    ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY
         3423  +    ** or UNIQUE index in a CREATE TABLE statement.  Since the table
         3424  +    ** has just been created, it contains no data and the index initialization
         3425  +    ** step can be skipped.
  3439   3426       */
  3440         -    if( pStart ){
  3441         -      int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
  3442         -      if( pName->z[n-1]==';' ) n--;
  3443         -      /* A named index with an explicit CREATE INDEX statement */
  3444         -      zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
  3445         -        onError==OE_None ? "" : " UNIQUE", n, pName->z);
  3446         -    }else{
  3447         -      /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
  3448         -      /* zStmt = sqlite3MPrintf(""); */
  3449         -      zStmt = 0;
  3450         -    }
  3451         -
  3452         -    /* Add an entry in sqlite_master for this index
  3453         -    */
  3454         -    sqlite3NestedParse(pParse, 
  3455         -        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
  3456         -        db->aDb[iDb].zDbSName, MASTER_NAME,
  3457         -        pIndex->zName,
  3458         -        pTab->zName,
  3459         -        iMem,
  3460         -        zStmt
  3461         -    );
  3462         -    sqlite3DbFree(db, zStmt);
  3463         -
  3464         -    /* Fill the index with data and reparse the schema. Code an OP_Expire
  3465         -    ** to invalidate all pre-compiled statements.
  3466         -    */
  3467         -    if( pTblName ){
  3468         -      sqlite3RefillIndex(pParse, pIndex, iMem);
  3469         -      sqlite3ChangeCookie(pParse, iDb);
  3470         -      sqlite3VdbeAddParseSchemaOp(v, iDb,
  3471         -         sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
  3472         -      sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
  3473         -    }
  3474         -
  3475         -    sqlite3VdbeJumpHere(v, pIndex->tnum);
         3427  +    else if( HasRowid(pTab) || pTblName!=0 ){
         3428  +      Vdbe *v;
         3429  +      char *zStmt;
         3430  +      int iMem = ++pParse->nMem;
         3431  +
         3432  +      v = sqlite3GetVdbe(pParse);
         3433  +      if( v==0 ) goto exit_create_index;
         3434  +
         3435  +      sqlite3BeginWriteOperation(pParse, 1, iDb);
         3436  +
         3437  +      /* Create the rootpage for the index using CreateIndex. But before
         3438  +      ** doing so, code a Noop instruction and store its address in 
         3439  +      ** Index.tnum. This is required in case this index is actually a 
         3440  +      ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In 
         3441  +      ** that case the convertToWithoutRowidTable() routine will replace
         3442  +      ** the Noop with a Goto to jump over the VDBE code generated below. */
         3443  +      pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
         3444  +      sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);
         3445  +
         3446  +      /* Gather the complete text of the CREATE INDEX statement into
         3447  +      ** the zStmt variable
         3448  +      */
         3449  +      if( pStart ){
         3450  +        int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
         3451  +        if( pName->z[n-1]==';' ) n--;
         3452  +        /* A named index with an explicit CREATE INDEX statement */
         3453  +        zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
         3454  +            onError==OE_None ? "" : " UNIQUE", n, pName->z);
         3455  +      }else{
         3456  +        /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
         3457  +        /* zStmt = sqlite3MPrintf(""); */
         3458  +        zStmt = 0;
         3459  +      }
         3460  +
         3461  +      /* Add an entry in sqlite_master for this index
         3462  +      */
         3463  +      sqlite3NestedParse(pParse, 
         3464  +          "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
         3465  +          db->aDb[iDb].zDbSName, MASTER_NAME,
         3466  +          pIndex->zName,
         3467  +          pTab->zName,
         3468  +          iMem,
         3469  +          zStmt
         3470  +          );
         3471  +      sqlite3DbFree(db, zStmt);
         3472  +
         3473  +      /* Fill the index with data and reparse the schema. Code an OP_Expire
         3474  +      ** to invalidate all pre-compiled statements.
         3475  +      */
         3476  +      if( pTblName ){
         3477  +        sqlite3RefillIndex(pParse, pIndex, iMem);
         3478  +        sqlite3ChangeCookie(pParse, iDb);
         3479  +        sqlite3VdbeAddParseSchemaOp(v, iDb,
         3480  +            sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
         3481  +        sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
         3482  +      }
         3483  +
         3484  +      sqlite3VdbeJumpHere(v, pIndex->tnum);
         3485  +    }
  3476   3486     }
  3477   3487   
  3478   3488     /* When adding an index to the list of indices for a table, make
  3479   3489     ** sure all indices labeled OE_Replace come after all those labeled
  3480   3490     ** OE_Ignore.  This is necessary for the correct constraint check
  3481   3491     ** processing (in sqlite3GenerateConstraintChecks()) as part of
  3482   3492     ** UPDATE and INSERT statements.  
................................................................................
  3492   3502           pOther = pOther->pNext;
  3493   3503         }
  3494   3504         pIndex->pNext = pOther->pNext;
  3495   3505         pOther->pNext = pIndex;
  3496   3506       }
  3497   3507       pIndex = 0;
  3498   3508     }
         3509  +  else if( IN_RENAME_COLUMN ){
         3510  +    assert( pParse->pNewIndex==0 );
         3511  +    pParse->pNewIndex = pIndex;
         3512  +    pIndex = 0;
         3513  +  }
  3499   3514   
  3500   3515     /* Clean up before exiting */
  3501   3516   exit_create_index:
  3502         -  if( pIndex ) freeIndex(db, pIndex);
         3517  +  if( pIndex ) sqlite3FreeIndex(db, pIndex);
  3503   3518     sqlite3ExprDelete(db, pPIWhere);
  3504   3519     sqlite3ExprListDelete(db, pList);
  3505   3520     sqlite3SrcListDelete(db, pTblName);
  3506   3521     sqlite3DbFree(db, zName);
  3507   3522   }
  3508   3523   
  3509   3524   /*

Changes to src/parse.y.

   936    936         p->u.zToken = (char*)&p[1];
   937    937         memcpy(p->u.zToken, t.z, t.n);
   938    938         p->u.zToken[t.n] = 0;
   939    939         if( sqlite3Isquote(p->u.zToken[0]) ){
   940    940           if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted;
   941    941           sqlite3Dequote(p->u.zToken);
   942    942         }
          943  +      if( IN_RENAME_COLUMN ) sqlite3RenameToken(pParse, (void*)p, &t);
   943    944   #if SQLITE_MAX_EXPR_DEPTH>0
   944    945         p->nHeight = 1;
   945    946   #endif  
   946    947       }
   947    948       return p;
   948    949     }
   949    950   }
................................................................................
   951    952   expr(A) ::= term(A).
   952    953   expr(A) ::= LP expr(X) RP. {A = X;}
   953    954   expr(A) ::= id(X).          {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/}
   954    955   expr(A) ::= JOIN_KW(X).     {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/}
   955    956   expr(A) ::= nm(X) DOT nm(Y). {
   956    957     Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
   957    958     Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
          959  +  if( IN_RENAME_COLUMN ) sqlite3RenameToken(pParse, (void*)temp2, &Y);
   958    960     A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
   959    961   }
   960    962   expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
   961    963     Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
   962    964     Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
   963    965     Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &Z, 1);
   964    966     Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3);
          967  +  if( IN_RENAME_COLUMN ) sqlite3RenameToken(pParse, (void*)temp3, &Z);
   965    968     A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
   966    969   }
   967    970   term(A) ::= NULL|FLOAT|BLOB(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/}
   968    971   term(A) ::= STRING(X).          {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/}
   969    972   term(A) ::= INTEGER(X). {
   970    973     A = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1);
   971    974   }
................................................................................
  1304   1307       if( (hasCollate || sortOrder!=SQLITE_SO_UNDEFINED)
  1305   1308           && pParse->db->init.busy==0
  1306   1309       ){
  1307   1310         sqlite3ErrorMsg(pParse, "syntax error after column name \"%.*s\"",
  1308   1311                            pIdToken->n, pIdToken->z);
  1309   1312       }
  1310   1313       sqlite3ExprListSetName(pParse, p, pIdToken, 1);
         1314  +    if( IN_RENAME_COLUMN ){
         1315  +      sqlite3RenameToken(pParse, (void*)&(p->a[p->nExpr-1]), pIdToken);
         1316  +    }
  1311   1317       return p;
  1312   1318     }
  1313   1319   } // end %include
  1314   1320   
  1315   1321   eidlist_opt(A) ::= .                         {A = 0;}
  1316   1322   eidlist_opt(A) ::= LP eidlist(X) RP.         {A = X;}
  1317   1323   eidlist(A) ::= eidlist(A) COMMA nm(Y) collate(C) sortorder(Z).  {
................................................................................
  1528   1534     Y.n = (int)(pParse->sLastToken.z-Y.z) + pParse->sLastToken.n;
  1529   1535     sqlite3AlterFinishAddColumn(pParse, &Y);
  1530   1536   }
  1531   1537   add_column_fullname ::= fullname(X). {
  1532   1538     disableLookaside(pParse);
  1533   1539     sqlite3AlterBeginAddColumn(pParse, X);
  1534   1540   }
         1541  +cmd ::= ALTER TABLE fullname(X) RENAME kwcolumn_opt nm(Y) TO nm(Z). {
         1542  +  sqlite3AlterRenameColumn(pParse, X, &Y, &Z);
         1543  +}
         1544  +
  1535   1545   kwcolumn_opt ::= .
  1536   1546   kwcolumn_opt ::= COLUMNKW.
         1547  +
  1537   1548   %endif  SQLITE_OMIT_ALTERTABLE
  1538   1549   
  1539   1550   //////////////////////// CREATE VIRTUAL TABLE ... /////////////////////////////
  1540   1551   %ifndef SQLITE_OMIT_VIRTUALTABLE
  1541   1552   cmd ::= create_vtab.                       {sqlite3VtabFinishParse(pParse,0);}
  1542   1553   cmd ::= create_vtab LP vtabarglist RP(X).  {sqlite3VtabFinishParse(pParse,&X);}
  1543   1554   create_vtab ::= createkw VIRTUAL TABLE ifnotexists(E)

Changes to src/resolve.c.

   664    664           zColumn = pExpr->u.zToken;
   665    665         }else{
   666    666           notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
   667    667           pRight = pExpr->pRight;
   668    668           if( pRight->op==TK_ID ){
   669    669             zDb = 0;
   670    670             zTable = pExpr->pLeft->u.zToken;
   671         -          zColumn = pRight->u.zToken;
   672    671           }else{
   673    672             assert( pRight->op==TK_DOT );
   674    673             zDb = pExpr->pLeft->u.zToken;
   675    674             zTable = pRight->pLeft->u.zToken;
   676         -          zColumn = pRight->pRight->u.zToken;
          675  +          pRight = pRight->pRight;
          676  +        }
          677  +        zColumn = pRight->u.zToken;
          678  +        if( IN_RENAME_COLUMN ){
          679  +          sqlite3MoveRenameToken(pParse, (void*)pExpr, (void*)pRight);
   677    680           }
   678    681         }
   679    682         return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
   680    683       }
   681    684   
   682    685       /* Resolve function names
   683    686       */

Changes to src/sqliteInt.h.

  1083   1083   typedef struct Lookaside Lookaside;
  1084   1084   typedef struct LookasideSlot LookasideSlot;
  1085   1085   typedef struct Module Module;
  1086   1086   typedef struct NameContext NameContext;
  1087   1087   typedef struct Parse Parse;
  1088   1088   typedef struct PreUpdate PreUpdate;
  1089   1089   typedef struct PrintfArguments PrintfArguments;
         1090  +typedef struct RenameToken RenameToken;
  1090   1091   typedef struct RowSet RowSet;
  1091   1092   typedef struct Savepoint Savepoint;
  1092   1093   typedef struct Select Select;
  1093   1094   typedef struct SQLiteThread SQLiteThread;
  1094   1095   typedef struct SelectDest SelectDest;
  1095   1096   typedef struct SrcList SrcList;
  1096   1097   typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
................................................................................
  3083   3084     ** first field in the recursive region.
  3084   3085     ************************************************************************/
  3085   3086   
  3086   3087     Token sLastToken;       /* The last token parsed */
  3087   3088     ynVar nVar;               /* Number of '?' variables seen in the SQL so far */
  3088   3089     u8 iPkSortOrder;          /* ASC or DESC for INTEGER PRIMARY KEY */
  3089   3090     u8 explain;               /* True if the EXPLAIN flag is found on the query */
         3091  +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_ALTERTABLE)
         3092  +  u8 eParseMode;            /* PARSE_MODE_XXX constant */
         3093  +#endif
  3090   3094   #ifndef SQLITE_OMIT_VIRTUALTABLE
  3091         -  u8 declareVtab;           /* True if inside sqlite3_declare_vtab() */
  3092   3095     int nVtabLock;            /* Number of virtual tables to lock */
  3093   3096   #endif
  3094   3097     int nHeight;              /* Expression tree height of current sub-select */
  3095   3098   #ifndef SQLITE_OMIT_EXPLAIN
  3096   3099     int addrExplain;          /* Address of current OP_Explain opcode */
  3097   3100   #endif
  3098   3101     VList *pVList;            /* Mapping between variable names and numbers */
  3099   3102     Vdbe *pReprepare;         /* VM being reprepared (sqlite3Reprepare()) */
  3100   3103     const char *zTail;        /* All SQL text past the last semicolon parsed */
  3101   3104     Table *pNewTable;         /* A table being constructed by CREATE TABLE */
         3105  +  Index *pNewIndex;         /* An index being constructed by CREATE INDEX */
  3102   3106     Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
  3103   3107     const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
  3104   3108   #ifndef SQLITE_OMIT_VIRTUALTABLE
  3105   3109     Token sArg;               /* Complete text of a module argument */
  3106   3110     Table **apVtabLock;       /* Pointer to virtual tables needing locking */
  3107   3111   #endif
  3108   3112     Table *pZombieTab;        /* List of Table objects to delete after code gen */
  3109   3113     TriggerPrg *pTriggerPrg;  /* Linked list of coded triggers */
  3110   3114     With *pWith;              /* Current WITH clause, or NULL */
  3111   3115     With *pWithToFree;        /* Free this WITH object at the end of the parse */
         3116  +#ifndef SQLITE_OMIT_ALTERTABLE
         3117  +  RenameToken *pRename;
         3118  +#endif
  3112   3119   };
         3120  +
         3121  +#define PARSE_MODE_NORMAL        0
         3122  +#define PARSE_MODE_DECLARE_VTAB  1
         3123  +#define PARSE_MODE_RENAME_COLUMN 2
  3113   3124   
  3114   3125   /*
  3115   3126   ** Sizes and pointers of various parts of the Parse object.
  3116   3127   */
  3117   3128   #define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/
  3118   3129   #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken)    /* Recursive part */
  3119   3130   #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
................................................................................
  3121   3132   
  3122   3133   /*
  3123   3134   ** Return true if currently inside an sqlite3_declare_vtab() call.
  3124   3135   */
  3125   3136   #ifdef SQLITE_OMIT_VIRTUALTABLE
  3126   3137     #define IN_DECLARE_VTAB 0
  3127   3138   #else
  3128         -  #define IN_DECLARE_VTAB (pParse->declareVtab)
         3139  +  #define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB)
         3140  +#endif
         3141  +
         3142  +#if defined(SQLITE_OMIT_ALTERTABLE)
         3143  +  #define IN_RENAME_COLUMN 0
         3144  +#else
         3145  +  #define IN_RENAME_COLUMN (pParse->eParseMode==PARSE_MODE_RENAME_COLUMN)
         3146  +#endif
         3147  +
         3148  +#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)
         3149  +  #define IN_SPECIAL_PARSE 0
         3150  +#else
         3151  +  #define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL)
  3129   3152   #endif
  3130   3153   
  3131   3154   /*
  3132   3155   ** An instance of the following structure can be declared on a stack and used
  3133   3156   ** to save the Parse.zAuthContext value so that it can be restored later.
  3134   3157   */
  3135   3158   struct AuthContext {
................................................................................
  3405   3428       int *aiCol;                               /* array of column indexes */
  3406   3429       struct IdxCover *pIdxCover;               /* Check for index coverage */
  3407   3430       struct IdxExprTrans *pIdxTrans;           /* Convert idxed expr to column */
  3408   3431       ExprList *pGroupBy;                       /* GROUP BY clause */
  3409   3432       Select *pSelect;                          /* HAVING to WHERE clause ctx */
  3410   3433       struct WindowRewrite *pRewrite;           /* Window rewrite context */
  3411   3434       struct WhereConst *pConst;                /* WHERE clause constants */
         3435  +    struct RenameCtx *pRename;                /* RENAME COLUMN context */
  3412   3436     } u;
  3413   3437   };
  3414   3438   
  3415   3439   /* Forward declarations */
  3416   3440   int sqlite3WalkExpr(Walker*, Expr*);
  3417   3441   int sqlite3WalkExprList(Walker*, ExprList*);
  3418   3442   int sqlite3WalkSelect(Walker*, Select*);
................................................................................
  3840   3864   
  3841   3865   #if SQLITE_MAX_ATTACHED>30
  3842   3866     int sqlite3DbMaskAllZero(yDbMask);
  3843   3867   #endif
  3844   3868   void sqlite3DropTable(Parse*, SrcList*, int, int);
  3845   3869   void sqlite3CodeDropTable(Parse*, Table*, int, int);
  3846   3870   void sqlite3DeleteTable(sqlite3*, Table*);
         3871  +void sqlite3FreeIndex(sqlite3*, Index*);
  3847   3872   #ifndef SQLITE_OMIT_AUTOINCREMENT
  3848   3873     void sqlite3AutoincrementBegin(Parse *pParse);
  3849   3874     void sqlite3AutoincrementEnd(Parse *pParse);
  3850   3875   #else
  3851   3876   # define sqlite3AutoincrementBegin(X)
  3852   3877   # define sqlite3AutoincrementEnd(X)
  3853   3878   #endif
................................................................................
  4184   4209   #ifdef VDBE_PROFILE
  4185   4210   extern sqlite3_uint64 sqlite3NProfileCnt;
  4186   4211   #endif
  4187   4212   void sqlite3RootPageMoved(sqlite3*, int, int, int);
  4188   4213   void sqlite3Reindex(Parse*, Token*, Token*);
  4189   4214   void sqlite3AlterFunctions(void);
  4190   4215   void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
         4216  +void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
  4191   4217   int sqlite3GetToken(const unsigned char *, int *);
  4192   4218   void sqlite3NestedParse(Parse*, const char*, ...);
  4193   4219   void sqlite3ExpirePreparedStatements(sqlite3*, int);
  4194   4220   int sqlite3CodeSubselect(Parse*, Expr *, int, int);
  4195   4221   void sqlite3SelectPrep(Parse*, Select*, NameContext*);
  4196   4222   void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
  4197   4223   int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
................................................................................
  4199   4225   int sqlite3ResolveExprListNames(NameContext*, ExprList*);
  4200   4226   void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
  4201   4227   void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
  4202   4228   int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
  4203   4229   void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
  4204   4230   void sqlite3AlterFinishAddColumn(Parse *, Token *);
  4205   4231   void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
         4232  +void sqlite3RenameToken(Parse*, void*, Token*);
         4233  +void sqlite3MoveRenameToken(Parse*, void *pTo, void *pFrom);
  4206   4234   CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
  4207   4235   char sqlite3AffinityType(const char*, Column*);
  4208   4236   void sqlite3Analyze(Parse*, Token*, Token*);
  4209   4237   int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
  4210   4238   int sqlite3FindDb(sqlite3*, Token*);
  4211   4239   int sqlite3FindDbName(sqlite3 *, const char *);
  4212   4240   int sqlite3AnalysisLoad(sqlite3*,int iDB);

Changes to src/tokenize.c.

   686    686       pParse->nTableLock = 0;
   687    687     }
   688    688   #endif
   689    689   #ifndef SQLITE_OMIT_VIRTUALTABLE
   690    690     sqlite3_free(pParse->apVtabLock);
   691    691   #endif
   692    692   
   693         -  if( !IN_DECLARE_VTAB ){
          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    700   

Changes to src/vtab.c.

   754    754       sqlite3_mutex_leave(db->mutex);
   755    755       return SQLITE_MISUSE_BKPT;
   756    756     }
   757    757     pTab = pCtx->pTab;
   758    758     assert( IsVirtual(pTab) );
   759    759   
   760    760     memset(&sParse, 0, sizeof(sParse));
   761         -  sParse.declareVtab = 1;
          761  +  sParse.eParseMode = PARSE_MODE_DECLARE_VTAB;
   762    762     sParse.db = db;
   763    763     sParse.nQueryLoop = 1;
   764    764     if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) 
   765    765      && sParse.pNewTable
   766    766      && !db->mallocFailed
   767    767      && !sParse.pNewTable->pSelect
   768    768      && !IsVirtual(sParse.pNewTable)
................................................................................
   795    795       }
   796    796       pCtx->bDeclared = 1;
   797    797     }else{
   798    798       sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
   799    799       sqlite3DbFree(db, zErr);
   800    800       rc = SQLITE_ERROR;
   801    801     }
   802         -  sParse.declareVtab = 0;
          802  +  sParse.eParseMode = PARSE_MODE_NORMAL;
   803    803   
   804    804     if( sParse.pVdbe ){
   805    805       sqlite3VdbeFinalize(sParse.pVdbe);
   806    806     }
   807    807     sqlite3DeleteTable(db, sParse.pNewTable);
   808    808     sqlite3ParserReset(&sParse);
   809    809   

Added test/altercol.test.

            1  +# 2009 February 2
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#*************************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this script is testing that SQLite can handle a subtle 
           13  +# file format change that may be used in the future to implement
           14  +# "ALTER TABLE ... RENAME COLUMN ... TO".
           15  +#
           16  +# $Id: alter4.test,v 1.1 2009/02/02 18:03:22 drh Exp $
           17  +#
           18  +
           19  +set testdir [file dirname $argv0]
           20  +source $testdir/tester.tcl
           21  +set testprefix altercol
           22  +
           23  +# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
           24  +ifcapable !altertable {
           25  +  finish_test
           26  +  return
           27  +}
           28  +
           29  +foreach {tn before after} {
           30  +  1 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB)}
           31  +    {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB)}
           32  +
           33  +  2 {CREATE TABLE t1(a INTEGER, x TEXT, "b" BLOB)}
           34  +    {CREATE TABLE t1(a INTEGER, x TEXT, "d" BLOB)}
           35  +
           36  +  3 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, CHECK(b!=''))}
           37  +    {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, CHECK(d!=''))}
           38  +
           39  +  4 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, CHECK(t1.b!=''))}
           40  +    {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, CHECK(t1.d!=''))}
           41  +
           42  +  5 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, CHECK( coalesce(b,c) ))}
           43  +    {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, CHECK( coalesce(d,c) ))}
           44  +
           45  +  6 {CREATE TABLE t1(a INTEGER, "b"TEXT, c BLOB, CHECK( coalesce(b,c) ))}
           46  +    {CREATE TABLE t1(a INTEGER, "d"TEXT, c BLOB, CHECK( coalesce(d,c) ))}
           47  +
           48  +  7 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, PRIMARY KEY(b, c))}
           49  +    {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, PRIMARY KEY(d, c))}
           50  +
           51  +  8 {CREATE TABLE t1(a INTEGER, b TEXT PRIMARY KEY, c BLOB)}
           52  +    {CREATE TABLE t1(a INTEGER, d TEXT PRIMARY KEY, c BLOB)}
           53  +
           54  +  9 {CREATE TABLE t1(a, b TEXT, c, PRIMARY KEY(a, b), UNIQUE("B"))}
           55  +    {CREATE TABLE t1(a, d TEXT, c, PRIMARY KEY(a, d), UNIQUE("d"))}
           56  +
           57  + 10 {CREATE TABLE t1(a, b, c);   CREATE INDEX t1i ON t1(a, c)}
           58  +    {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(a, c)}}
           59  +
           60  + 11 {CREATE TABLE t1(a, b, c);   CREATE INDEX t1i ON t1(b, c)}
           61  +    {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(d, c)}}
           62  +
           63  + 12 {CREATE TABLE t1(a, b, c);   CREATE INDEX t1i ON t1(b+b+b+b, c) WHERE b>0}
           64  +    {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(d+d+d+d, c) WHERE d>0}}
           65  +
           66  + 13 {CREATE TABLE t1(a, b, c, FOREIGN KEY (b) REFERENCES t2)}
           67  +    {CREATE TABLE t1(a, d, c, FOREIGN KEY (d) REFERENCES t2)}
           68  +
           69  +} {
           70  +  reset_db
           71  +  do_execsql_test 1.$tn.0 $before
           72  +
           73  +  do_execsql_test 1.$tn.1 {
           74  +    INSERT INTO t1 VALUES(1, 2, 3);
           75  +  }
           76  +
           77  +  do_execsql_test 1.$tn.2 {
           78  +    ALTER TABLE t1 RENAME COLUMN b TO d;
           79  +  }
           80  +
           81  +  do_execsql_test 1.$tn.3 {
           82  +    SELECT * FROM t1;
           83  +  } {1 2 3}
           84  +
           85  +  if {[string first INDEX $before]>0} {
           86  +    set res $after
           87  +  } else {
           88  +    set res [list $after]
           89  +  }
           90  +  do_execsql_test 1.$tn.4 {
           91  +    SELECT sql FROM sqlite_master WHERE tbl_name='t1' AND sql!=''
           92  +  } $res
           93  +}
           94  +
           95  +finish_test
           96  +
           97  +