SQLite

Check-in [f4497b0136]
Login

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

Overview
Comment:Reload the entire schema after renaming a column in order to ensure that the schema for any tables for which parent key definitions were changed are reloaded.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | alter-table-rename-column
Files: files | file ages | folders
SHA3-256: f4497b0136e9fcb1121a834c86f84eeaf8f1e7d3157d409484e086bcef3487f1
User & Date: dan 2018-08-11 13:40:20.594
Context
2018-08-11
17:34
Fix a bug causing all ALTER TABLE RENAME COLUMN commands to fail if ANALYZE had been run on the database. Also prevent the user from renaming the columns of system tables. (check-in: ca644a2877 user: dan tags: alter-table-rename-column)
13:40
Reload the entire schema after renaming a column in order to ensure that the schema for any tables for which parent key definitions were changed are reloaded. (check-in: f4497b0136 user: dan tags: alter-table-rename-column)
2018-08-10
20:19
Ensure the schema cookie is changed when a column is renamed. (check-in: 2dec9ea4ab user: dan tags: alter-table-rename-column)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/alter.c.
827
828
829
830
831
832
833
834


835
836

837
838
839
840
841
842
843
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "sql = sqlite_rename_column(sql, %d, %Q, %Q, %Q) "
      "WHERE type = 'table' OR (type='index' AND tbl_name = %Q AND sql!='')",
      zDb, MASTER_NAME, iCol, zNew, pTab->zName, zOld, pTab->zName
  );

  /* Drop and reload the internal table schema. */


  sqlite3ChangeCookie(pParse, iSchema);
  reloadTableSchema(pParse, pTab, pTab->zName);


 exit_rename_column:
  sqlite3SrcListDelete(db, pSrc);
  sqlite3DbFree(db, zOld);
  sqlite3DbFree(db, zNew);
  return;
}







|
>
>
|
|
>







827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "sql = sqlite_rename_column(sql, %d, %Q, %Q, %Q) "
      "WHERE type = 'table' OR (type='index' AND tbl_name = %Q AND sql!='')",
      zDb, MASTER_NAME, iCol, zNew, pTab->zName, zOld, pTab->zName
  );

  /* Drop and reload the database schema. */
  if( db->mallocFailed==0 ){
    assert( pParse->pVdbe );
    sqlite3ChangeCookie(pParse, iSchema);
    sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iSchema, 0);
  }

 exit_rename_column:
  sqlite3SrcListDelete(db, pSrc);
  sqlite3DbFree(db, zOld);
  sqlite3DbFree(db, zNew);
  return;
}
Changes to src/prepare.c.
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
  int rc;
  int i;
#ifndef SQLITE_OMIT_DEPRECATED
  int size;
#endif
  Db *pDb;
  char const *azArg[4];







|







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
  int rc;
  int i;
#ifndef SQLITE_OMIT_DEPRECATED
  int size;
#endif
  Db *pDb;
  char const *azArg[4];
Changes to src/sqliteInt.h.
3795
3796
3797
3798
3799
3800
3801

3802
3803
3804
3805
3806
3807
3808
void sqlite3ExprListSetSortOrder(ExprList*,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
u32 sqlite3ExprListFlags(const ExprList*);
int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**);

void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
#ifndef SQLITE_OMIT_VIRTUALTABLE
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
#endif
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);







>







3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
void sqlite3ExprListSetSortOrder(ExprList*,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
u32 sqlite3ExprListFlags(const ExprList*);
int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**);
int sqlite3InitOne(sqlite3*, int, char**);
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
#ifndef SQLITE_OMIT_VIRTUALTABLE
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
#endif
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);
Changes to src/vdbe.c.
5742
5743
5744
5745
5746
5747
5748








5749
5750
5751
5752
5753
5754
5755
    assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
  }
#endif

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );








  /* Used to be a conditional */ {
    zMaster = MASTER_NAME;
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",







>
>
>
>
>
>
>
>







5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
    assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
  }
#endif

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );

#ifndef SQLITE_OMIT_ALTERTABLE
  if( pOp->p4.z==0 ){
    sqlite3SchemaClear(db->aDb[iDb].pSchema);
    rc = sqlite3InitOne(db, iDb, &p->zErrMsg);
    db->mDbFlags |= DBFLAG_SchemaChange;
  }else
#endif
  /* Used to be a conditional */ {
    zMaster = MASTER_NAME;
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
Changes to test/altercol.test.
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  ALTER TABLE p1 RENAME d TO "silly name";
  SELECT sql FROM sqlite_master WHERE name IN ('c1', 'p1');
} {
  {CREATE TABLE c1(a, b, FOREIGN KEY (a, b) REFERENCES p1(c, "silly name"))}
  {CREATE TABLE p1(c, "silly name", PRIMARY KEY(c, "silly name"))}
}

# do_execsql_test 4.2 { INSERT INTO c1 VALUES(1, 2); }

do_execsql_test 4.3 {
  CREATE TABLE c2(a, b, FOREIGN KEY (a, b) REFERENCES p1);
}

do_execsql_test 4.4 {
  ALTER TABLE p1 RENAME "silly name" TO reasonable;







|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  ALTER TABLE p1 RENAME d TO "silly name";
  SELECT sql FROM sqlite_master WHERE name IN ('c1', 'p1');
} {
  {CREATE TABLE c1(a, b, FOREIGN KEY (a, b) REFERENCES p1(c, "silly name"))}
  {CREATE TABLE p1(c, "silly name", PRIMARY KEY(c, "silly name"))}
}

do_execsql_test 4.2 { INSERT INTO c1 VALUES(1, 2); }

do_execsql_test 4.3 {
  CREATE TABLE c2(a, b, FOREIGN KEY (a, b) REFERENCES p1);
}

do_execsql_test 4.4 {
  ALTER TABLE p1 RENAME "silly name" TO reasonable;