/ Check-in [e066b4e1]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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 Unified Diffs Ignore Whitespace Patch

Changes to src/alter.c.

775
776
777
778
779
780
781


















782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
....
1360
1361
1362
1363
1364
1365
1366

1367
1368
1369
1370
1371
1372
1373
      pToken->pNext = pCtx->pList;
      pCtx->pList = pToken;
      pCtx->nList++;
      break;
    }
  }
}



















/*
** This is a Walker select callback. It does nothing. It is only required
** because without a dummy callback, sqlite3WalkExpr() and similar do not
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
  UNUSED_PARAMETER(pWalker);
  UNUSED_PARAMETER(p);
  return WRC_Continue;
}

/*
** This is a Walker expression callback.
**
** For every TK_COLUMN node in the expression tree, search to see
................................................................................
  SrcList *pSrc = pSelect->pSrc;
  for(i=0; i<pSrc->nSrc; i++){
    struct SrcList_item *pItem = &pSrc->a[i];
    if( pItem->pTab==p->pTab ){
      renameTokenFind(pWalker->pParse, p, pItem->zName);
    }
  }


  return WRC_Continue;
}


/*
** This C function implements an SQL user function that is used by SQL code







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|
<







 







>







775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
....
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
      pToken->pNext = pCtx->pList;
      pCtx->pList = pToken;
      pCtx->nList++;
      break;
    }
  }
}

/*
** Iterate through the Select objects that are part of WITH clauses attached
** to select statement pSelect.
*/
static void renameWalkWith(Walker *pWalker, Select *pSelect){
  if( pSelect->pWith ){
    int i;
    for(i=0; i<pSelect->pWith->nCte; i++){
      Select *p = pSelect->pWith->a[i].pSelect;
      NameContext sNC;
      memset(&sNC, 0, sizeof(sNC));
      sNC.pParse = pWalker->pParse;
      sqlite3SelectPrep(sNC.pParse, p, &sNC);
      sqlite3WalkSelect(pWalker, p);
    }
  }
}

/*
** This is a Walker select callback. It does nothing. It is only required
** because without a dummy callback, sqlite3WalkExpr() and similar do not
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
  renameWalkWith(pWalker, p);

  return WRC_Continue;
}

/*
** This is a Walker expression callback.
**
** For every TK_COLUMN node in the expression tree, search to see
................................................................................
  SrcList *pSrc = pSelect->pSrc;
  for(i=0; i<pSrc->nSrc; i++){
    struct SrcList_item *pItem = &pSrc->a[i];
    if( pItem->pTab==p->pTab ){
      renameTokenFind(pWalker->pParse, p, pItem->zName);
    }
  }
  renameWalkWith(pWalker, pSelect);

  return WRC_Continue;
}


/*
** This C function implements an SQL user function that is used by SQL code

Changes to test/altertab2.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
81
82
83
84
85
86
87


88






















































89
#    May you share freely, never taking more than you give.
#
#*************************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix altertab

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

................................................................................
  SELECT sql FROM sqlite_master WHERE name LIKE 'c%';
} {
  {CREATE TABLE c1(x REFERENCES "p3")}
  {CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES "p3")}
  {CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p3"(a))}
}


























































finish_test







|







 







>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#    May you share freely, never taking more than you give.
#
#*************************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix altertab2

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

................................................................................
  SELECT sql FROM sqlite_master WHERE name LIKE 'c%';
} {
  {CREATE TABLE c1(x REFERENCES "p3")}
  {CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES "p3")}
  {CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p3"(a))}
}

#-------------------------------------------------------------------------
# Table name in WITH clauses that are part of views or triggers.
#
foreach {tn schema} {
  1 {
    CREATE TABLE log_entry(col1, y);
    CREATE INDEX i1 ON log_entry(col1);
  }

  2 {
    CREATE TABLE t1(a, b, c);
    CREATE TABLE t2(x);
    CREATE TABLE log_entry(col1);
    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
      INSERT INTO t2 SELECT col1 FROM log_entry;
    END;
  }

  3 {
    CREATE TABLE t1(a, b, c);
    CREATE TABLE t2(x);
    CREATE TABLE log_entry(col1);
    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
      INSERT INTO t2
        WITH xyz(x) AS (SELECT col1 FROM log_entry)
        SELECT x FROM xyz;
    END;
  }

  4 {
    CREATE TABLE log_entry(col1);
    CREATE VIEW ttt AS
        WITH xyz(x) AS (SELECT col1 FROM log_entry)
        SELECT x FROM xyz;
  }
} {
  reset_db
  do_execsql_test 3.$tn.1 $schema
  set expect [db eval "SELECT sql FROM sqlite_master"]
  set expect [string map {log_entry {"newname"}} $expect]

  do_execsql_test 3.$tn.2 {
    ALTER TABLE log_entry RENAME TO newname;
    SELECT sql FROM sqlite_master;
  } $expect

  reset_db
  do_execsql_test 3.$tn.3 $schema
  set expect [db eval "SELECT sql FROM sqlite_master"]
  set expect [string map {col1 newname} $expect]

  do_execsql_test 3.$tn.4 {
    ALTER TABLE log_entry RENAME col1 TO newname;
    SELECT sql FROM sqlite_master;
  } $expect
}

finish_test