/ Check-in [71947337]
Login

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

Overview
Comment:By default, make all "ALTER TABLE RENAME" statements executed within a virtual table xRename() method exhibit the legacy behaviour.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | legacy-alter-table
Files: files | file ages | folders
SHA3-256:71947337e98b90debb13b390119bc2a6b39dd41535151b836071ee327a31e45d
User & Date: dan 2018-09-20 17:21:21
Context
2018-09-20
20:15
Add the "PRAGMA legacy_alter_table=ON" command to enable the pre-3.25.0 behavior of ALTER TABLE that does not modify the bodies of triggers or views or the WHERE clause of a partial index. Enable the legacy behavior by default when running the xRename method of virtual tables. check-in: 7edd26ed user: drh tags: trunk
17:21
By default, make all "ALTER TABLE RENAME" statements executed within a virtual table xRename() method exhibit the legacy behaviour. Closed-Leaf check-in: 71947337 user: dan tags: legacy-alter-table
08:28
Add a PRAGMA that restores the legacy ALTER TABLE RENAME TO behaviour. check-in: 5acad2e9 user: dan tags: legacy-alter-table
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/alter.c.

   165    165     ** table.
   166    166     */
   167    167     v = sqlite3GetVdbe(pParse);
   168    168     if( v==0 ){
   169    169       goto exit_rename_table;
   170    170     }
   171    171   
   172         -  /* If this is a virtual table, invoke the xRename() function if
   173         -  ** one is defined. The xRename() callback will modify the names
   174         -  ** of any resources used by the v-table implementation (including other
   175         -  ** SQLite tables) that are identified by the name of the virtual table.
   176         -  */
   177         -#ifndef SQLITE_OMIT_VIRTUALTABLE
   178         -  if( pVTab ){
   179         -    int i = ++pParse->nMem;
   180         -    sqlite3VdbeLoadString(v, i, zName);
   181         -    sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
   182         -    sqlite3MayAbort(pParse);
   183         -  }
   184         -#endif
   185         -
   186    172     /* figure out how many UTF-8 characters are in zName */
   187    173     zTabName = pTab->zName;
   188    174     nTabName = sqlite3Utf8CharLen(zTabName, -1);
   189    175   
   190    176     /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in
   191    177     ** the schema to use the new table name.  */
   192    178     sqlite3NestedParse(pParse, 
................................................................................
   235    221               "tbl_name = "
   236    222                 "CASE WHEN tbl_name=%Q COLLATE nocase AND "
   237    223                 "          sqlite_rename_test(%Q, sql, type, name, 1) "
   238    224                 "THEN %Q ELSE tbl_name END "
   239    225               "WHERE type IN ('view', 'trigger')"
   240    226           , zDb, zTabName, zName, zTabName, zDb, zName);
   241    227     }
          228  +
          229  +  /* If this is a virtual table, invoke the xRename() function if
          230  +  ** one is defined. The xRename() callback will modify the names
          231  +  ** of any resources used by the v-table implementation (including other
          232  +  ** SQLite tables) that are identified by the name of the virtual table.
          233  +  */
          234  +#ifndef SQLITE_OMIT_VIRTUALTABLE
          235  +  if( pVTab ){
          236  +    int i = ++pParse->nMem;
          237  +    sqlite3VdbeLoadString(v, i, zName);
          238  +    sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
          239  +    sqlite3MayAbort(pParse);
          240  +  }
          241  +#endif
   242    242   
   243    243     renameReloadSchema(pParse, iDb);
   244    244     renameTestSchema(pParse, zDb, iDb==1);
   245    245   
   246    246   exit_rename_table:
   247    247     sqlite3SrcListDelete(db, pSrc);
   248    248     sqlite3DbFree(db, zName);

Changes to src/vdbe.c.

  7055   7055   ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
  7056   7056   ** This opcode invokes the corresponding xRename method. The value
  7057   7057   ** in register P1 is passed as the zName argument to the xRename method.
  7058   7058   */
  7059   7059   case OP_VRename: {
  7060   7060     sqlite3_vtab *pVtab;
  7061   7061     Mem *pName;
  7062         -
         7062  +  int isLegacy;
         7063  +  
         7064  +  isLegacy = (db->flags & SQLITE_LegacyAlter);
         7065  +  db->flags |= SQLITE_LegacyAlter;
  7063   7066     pVtab = pOp->p4.pVtab->pVtab;
  7064   7067     pName = &aMem[pOp->p1];
  7065   7068     assert( pVtab->pModule->xRename );
  7066   7069     assert( memIsValid(pName) );
  7067   7070     assert( p->readOnly==0 );
  7068   7071     REGISTER_TRACE(pOp->p1, pName);
  7069   7072     assert( pName->flags & MEM_Str );
  7070   7073     testcase( pName->enc==SQLITE_UTF8 );
  7071   7074     testcase( pName->enc==SQLITE_UTF16BE );
  7072   7075     testcase( pName->enc==SQLITE_UTF16LE );
  7073   7076     rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
  7074   7077     if( rc ) goto abort_due_to_error;
  7075   7078     rc = pVtab->pModule->xRename(pVtab, pName->z);
         7079  +  if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter;
  7076   7080     sqlite3VtabImportErrmsg(p, pVtab);
  7077   7081     p->expired = 0;
  7078   7082     if( rc ) goto abort_due_to_error;
  7079   7083     break;
  7080   7084   }
  7081   7085   #endif
  7082   7086   

Changes to test/altermalloc2.test.

    68     68   } -body {
    69     69     execsql {
    70     70       ALTER TABLE t1 RENAME abcd TO dcba
    71     71     }
    72     72   } -test {
    73     73     faultsim_test_result {0 {}}
    74     74   }
           75  +
           76  +reset_db
           77  +do_execsql_test 4.0 {
           78  +  CREATE TABLE rr(a, b);
           79  +  CREATE VIEW vv AS SELECT * FROM rr;
           80  +
           81  +  CREATE TRIGGER vv1 INSTEAD OF INSERT ON vv BEGIN
           82  +    SELECT 1, 2, 3;
           83  +  END;
           84  +  CREATE TRIGGER tr1 AFTER INSERT ON rr BEGIN
           85  +    INSERT INTO vv VALUES(new.a, new.b);
           86  +  END;
           87  +} {}
           88  +
           89  +faultsim_save_and_close
           90  +do_faultsim_test 4 -faults oom-* -prep {
           91  +  faultsim_restore_and_reopen
           92  +  execsql { SELECT * FROM sqlite_master }
           93  +} -body {
           94  +  execsql {
           95  +    ALTER TABLE rr RENAME a TO c;
           96  +  }
           97  +} -test {
           98  +  faultsim_test_result {0 {}} 
           99  +}
          100  +
    75    101   finish_test

Added test/altertab2.test.

            1  +# 2018 September 30
            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  +#
           12  +
           13  +set testdir [file dirname $argv0]
           14  +source $testdir/tester.tcl
           15  +set testprefix altertab
           16  +
           17  +# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
           18  +ifcapable !altertable {
           19  +  finish_test
           20  +  return
           21  +}
           22  +
           23  +ifcapable fts5 {
           24  +  do_execsql_test 1.0 {
           25  +    CREATE TABLE rr(a, b);
           26  +    CREATE VIRTUAL TABLE ff USING fts5(a, b);
           27  +    CREATE TRIGGER tr1 AFTER INSERT ON rr BEGIN
           28  +      INSERT INTO ff VALUES(new.a, new.b);
           29  +    END;
           30  +    INSERT INTO rr VALUES('hello', 'world');
           31  +    SELECT * FROM ff;
           32  +  } {hello world}
           33  +
           34  +  do_execsql_test 1.1 {
           35  +    ALTER TABLE ff RENAME TO ffff;
           36  +  }
           37  +
           38  +  do_execsql_test 1.2 {
           39  +    INSERT INTO rr VALUES('in', 'tcl');
           40  +    SELECT * FROM ffff;
           41  +  } {hello world in tcl}
           42  +}
           43  +
           44  +
           45  +finish_test
           46  +