/ Check-in [e066b4e1]
Login

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

Overview
Comment:Ensure that ALTER TABLE modifies table and column names embedded in WITH clauses that are part of views and triggers.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | branch-3.26
Files: files | file ages | folders
SHA3-256: e066b4e171b02867b5b3cc0d3a578687f6a5e210248ddc45b5704342d7bb7a0d
User & Date: drh 2018-12-06 13:57:26
Context
2018-12-06
14:11
Fix a potential NULL pointer dereference that can occur in ALTER TABLE following an OOM. Test case in TH3. check-in: 99a0951f user: drh tags: branch-3.26
13:57
Ensure that ALTER TABLE modifies table and column names embedded in WITH clauses that are part of views and triggers. check-in: e066b4e1 user: drh tags: branch-3.26
2018-12-05
13:49
Ensure that ALTER TABLE modifies table and column names embedded in WITH clauses that are part of views and triggers. check-in: f44bc7a8 user: dan tags: trunk
2018-12-01
12:34
Version 3.26.0 check-in: bf8c1b2b user: drh tags: trunk, release, version-3.26.0
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/alter.c.

   775    775         pToken->pNext = pCtx->pList;
   776    776         pCtx->pList = pToken;
   777    777         pCtx->nList++;
   778    778         break;
   779    779       }
   780    780     }
   781    781   }
          782  +
          783  +/*
          784  +** Iterate through the Select objects that are part of WITH clauses attached
          785  +** to select statement pSelect.
          786  +*/
          787  +static void renameWalkWith(Walker *pWalker, Select *pSelect){
          788  +  if( pSelect->pWith ){
          789  +    int i;
          790  +    for(i=0; i<pSelect->pWith->nCte; i++){
          791  +      Select *p = pSelect->pWith->a[i].pSelect;
          792  +      NameContext sNC;
          793  +      memset(&sNC, 0, sizeof(sNC));
          794  +      sNC.pParse = pWalker->pParse;
          795  +      sqlite3SelectPrep(sNC.pParse, p, &sNC);
          796  +      sqlite3WalkSelect(pWalker, p);
          797  +    }
          798  +  }
          799  +}
   782    800   
   783    801   /*
   784    802   ** This is a Walker select callback. It does nothing. It is only required
   785    803   ** because without a dummy callback, sqlite3WalkExpr() and similar do not
   786    804   ** descend into sub-select statements.
   787    805   */
   788    806   static int renameColumnSelectCb(Walker *pWalker, Select *p){
   789         -  UNUSED_PARAMETER(pWalker);
   790         -  UNUSED_PARAMETER(p);
          807  +  renameWalkWith(pWalker, p);
   791    808     return WRC_Continue;
   792    809   }
   793    810   
   794    811   /*
   795    812   ** This is a Walker expression callback.
   796    813   **
   797    814   ** For every TK_COLUMN node in the expression tree, search to see
................................................................................
  1360   1377     SrcList *pSrc = pSelect->pSrc;
  1361   1378     for(i=0; i<pSrc->nSrc; i++){
  1362   1379       struct SrcList_item *pItem = &pSrc->a[i];
  1363   1380       if( pItem->pTab==p->pTab ){
  1364   1381         renameTokenFind(pWalker->pParse, p, pItem->zName);
  1365   1382       }
  1366   1383     }
         1384  +  renameWalkWith(pWalker, pSelect);
  1367   1385   
  1368   1386     return WRC_Continue;
  1369   1387   }
  1370   1388   
  1371   1389   
  1372   1390   /*
  1373   1391   ** This C function implements an SQL user function that is used by SQL code

Changes to test/altertab2.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #*************************************************************************
    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
    15         -set testprefix altertab
           15  +set testprefix altertab2
    16     16   
    17     17   # If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
    18     18   ifcapable !altertable {
    19     19     finish_test
    20     20     return
    21     21   }
    22     22   
................................................................................
    81     81     SELECT sql FROM sqlite_master WHERE name LIKE 'c%';
    82     82   } {
    83     83     {CREATE TABLE c1(x REFERENCES "p3")}
    84     84     {CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES "p3")}
    85     85     {CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p3"(a))}
    86     86   }
    87     87   
           88  +#-------------------------------------------------------------------------
           89  +# Table name in WITH clauses that are part of views or triggers.
           90  +#
           91  +foreach {tn schema} {
           92  +  1 {
           93  +    CREATE TABLE log_entry(col1, y);
           94  +    CREATE INDEX i1 ON log_entry(col1);
           95  +  }
           96  +
           97  +  2 {
           98  +    CREATE TABLE t1(a, b, c);
           99  +    CREATE TABLE t2(x);
          100  +    CREATE TABLE log_entry(col1);
          101  +    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
          102  +      INSERT INTO t2 SELECT col1 FROM log_entry;
          103  +    END;
          104  +  }
          105  +
          106  +  3 {
          107  +    CREATE TABLE t1(a, b, c);
          108  +    CREATE TABLE t2(x);
          109  +    CREATE TABLE log_entry(col1);
          110  +    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
          111  +      INSERT INTO t2
          112  +        WITH xyz(x) AS (SELECT col1 FROM log_entry)
          113  +        SELECT x FROM xyz;
          114  +    END;
          115  +  }
          116  +
          117  +  4 {
          118  +    CREATE TABLE log_entry(col1);
          119  +    CREATE VIEW ttt AS
          120  +        WITH xyz(x) AS (SELECT col1 FROM log_entry)
          121  +        SELECT x FROM xyz;
          122  +  }
          123  +} {
          124  +  reset_db
          125  +  do_execsql_test 3.$tn.1 $schema
          126  +  set expect [db eval "SELECT sql FROM sqlite_master"]
          127  +  set expect [string map {log_entry {"newname"}} $expect]
          128  +
          129  +  do_execsql_test 3.$tn.2 {
          130  +    ALTER TABLE log_entry RENAME TO newname;
          131  +    SELECT sql FROM sqlite_master;
          132  +  } $expect
          133  +
          134  +  reset_db
          135  +  do_execsql_test 3.$tn.3 $schema
          136  +  set expect [db eval "SELECT sql FROM sqlite_master"]
          137  +  set expect [string map {col1 newname} $expect]
          138  +
          139  +  do_execsql_test 3.$tn.4 {
          140  +    ALTER TABLE log_entry RENAME col1 TO newname;
          141  +    SELECT sql FROM sqlite_master;
          142  +  } $expect
          143  +}
    88    144   
    89    145   finish_test