]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When a column is renamed, update any references to it in REFERENCES clauses
authordan <dan@noemail.net>
Fri, 10 Aug 2018 19:19:33 +0000 (19:19 +0000)
committerdan <dan@noemail.net>
Fri, 10 Aug 2018 19:19:33 +0000 (19:19 +0000)
that belong to other tables.

FossilOrigin-Name: 191079bd4f774528a1e39b71b4a4ce7859dee0edf0ce72e4b6968ae889dc35c8

manifest
manifest.uuid
src/alter.c
src/build.c
test/altercol.test

index c272a2160dbd790a89546228cdaf6ed44db16a70..36033333218ae790cdf9454a2b9d18b0d3b761d8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\slatest\strunk\schanges\swith\sthis\sbranch.
-D 2018-08-10T15:27:55.230
+C When\sa\scolumn\sis\srenamed,\supdate\sany\sreferences\sto\sit\sin\sREFERENCES\sclauses\nthat\sbelong\sto\sother\stables.
+D 2018-08-10T19:19:33.246
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6
@@ -432,7 +432,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
 F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c 94baeaee1206dfed286b2a69c5e771519c9cf12253bfc3895ffa2198ce437bf0
+F src/alter.c f5c2b068f977b19608b66bf9a4ba02fd9b3e81b6995943b974ee62449f6e02fb
 F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
 F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a
 F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114
@@ -442,7 +442,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
 F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173
 F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
-F src/build.c e7c0350573891114749588a6679f5de69ca94af4648f3393f4f25ebfed983806
+F src/build.c a8e71a3cf77ddf953a85d9d2d4c7fbc0a0f70ef4e4515915ad6ff1cdff9c9808
 F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387
@@ -599,7 +599,7 @@ F test/alter.test b820ab9dcf85f8e3a65bc8326accb2f0c7be64ef
 F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
 F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3
 F test/alter4.test b6d7b86860111864f6cddb54af313f5862dda23b
-F test/altercol.test d5a228930e4600adfce9c91cc4e730fc6872f435856b20aad965143bfdf1bffa
+F test/altercol.test 93847fb3692e4039c99353c59cc8445b46699e708db14df04a3f37fe114408d3
 F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
 F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
 F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df
@@ -1755,7 +1755,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P d48f7bbdf4a1686c25e634a8dec6ead88bf2866fee94ed8e5058f830363424a8 4195a3f8b5d2c2ec63771890c5aa7b5e2de60b9fa2273652730239b8577ae418
-R b24a2e05d71f86ed70ef242ae03982aa
+P c355a8370782aa70f155ee956fa0faec7f45d7c483c442b169b63c5f0a988fd3
+R 9b5309f7995cf06a3165d0a23c637e3a
 U dan
-Z 031a736f5c3b4bef78d9b69d733a942c
+Z e0fd0e786033013f88a3bbb95087baa7
index 533a3fb5f2807597a18e8de6e9849544cd7aff92..dfbb592209c421ca45989d0a70e007a26fde11b5 100644 (file)
@@ -1 +1 @@
-c355a8370782aa70f155ee956fa0faec7f45d7c483c442b169b63c5f0a988fd3
\ No newline at end of file
+191079bd4f774528a1e39b71b4a4ce7859dee0edf0ce72e4b6968ae889dc35c8
\ No newline at end of file
index c4dc00bd27576a46837206d9ee61f65b41a589cb..6e0de05e89bb680b20d6107e0bcd85e7ef8ce0af 100644 (file)
@@ -825,9 +825,9 @@ void sqlite3AlterRenameColumn(
 
   sqlite3NestedParse(pParse, 
       "UPDATE \"%w\".%s SET "
-      "sql = sqlite_rename_column(sql, %d, %Q) "
-      "WHERE type IN ('table', 'index') AND tbl_name = %Q AND sql!=''",
-      zDb, MASTER_NAME, iCol, zNew, pTab->zName
+      "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. */
@@ -923,6 +923,9 @@ static RenameToken *renameColumnTokenNext(struct RenameCtx *pCtx){
   return pBest;
 }
 
+/*
+** sqlite_rename_table(SQL, iCol, zNew, zTable, zOld)
+*/
 static void renameColumnFunc(
   sqlite3_context *context,
   int NotUsed,
@@ -934,6 +937,11 @@ static void renameColumnFunc(
   int nSql = sqlite3_value_bytes(argv[0]);
   const char *zNew = sqlite3_value_text(argv[2]);
   int nNew = sqlite3_value_bytes(argv[2]);
+  const char *zTable = sqlite3_value_text(argv[3]);
+  int nTable = sqlite3_value_bytes(argv[3]);
+  const char *zOld = sqlite3_value_text(argv[4]);
+  int nOld = sqlite3_value_bytes(argv[4]);
+
   int rc;
   char *zErr = 0;
   Parse sParse;
@@ -1004,26 +1012,38 @@ static void renameColumnFunc(
   sWalker.u.pRename = &sCtx;
 
   if( sParse.pNewTable ){
+    int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
     FKey *pFKey;
-    sCtx.pList = renameTokenFind(
-        &sParse, (void*)sParse.pNewTable->aCol[sCtx.iCol].zName
-    );
-    sCtx.nList = 1;
-    sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
-    for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
-      sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
+    if( bFKOnly==0 ){
+      sCtx.pList = renameTokenFind(
+          &sParse, (void*)sParse.pNewTable->aCol[sCtx.iCol].zName
+      );
+      sCtx.nList = 1;
+      sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
+      for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
+        sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
+      }
     }
 
     for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
       for(i=0; i<pFKey->nCol; i++){
-        if( pFKey->aCol[i].iFrom==sCtx.iCol ){
-          RenameToken *pTok = renameTokenFind(&sParse, (void*)&pFKey->aCol[i]);
+        RenameToken *pTok = 0;
+        if( bFKOnly==0 && pFKey->aCol[i].iFrom==sCtx.iCol ){
+          pTok = renameTokenFind(&sParse, (void*)&pFKey->aCol[i]);
           if( pTok ){
             pTok->pNext = sCtx.pList;
             sCtx.pList = pTok;
             sCtx.nList++;
           }
         }
+        if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
+         && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld)
+        ){
+          pTok = renameTokenFind(&sParse, (void*)pFKey->aCol[i].zCol);
+          pTok->pNext = sCtx.pList;
+          sCtx.pList = pTok;
+          sCtx.nList++;
+        }
       }
     }
   }else{
@@ -1081,7 +1101,7 @@ static void renameColumnFunc(
 void sqlite3AlterFunctions(void){
   static FuncDef aAlterTableFuncs[] = {
     FUNCTION(sqlite_rename_table,   2, 0, 0, renameTableFunc),
-    FUNCTION(sqlite_rename_column,   3, 0, 0, renameColumnFunc),
+    FUNCTION(sqlite_rename_column,   5, 0, 0, renameColumnFunc),
 #ifndef SQLITE_OMIT_TRIGGER
     FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
 #endif
index 963c97465bee1f92dcce9d7db0c54fa5e9f767d1..f7a91025bb5ed6dcedc14d4bd70e35468d14ab5e 100644 (file)
@@ -2771,6 +2771,9 @@ void sqlite3CreateForeignKey(
     for(i=0; i<nCol; i++){
       int n = sqlite3Strlen30(pToCol->a[i].zName);
       pFKey->aCol[i].zCol = z;
+      if( IN_RENAME_COLUMN ){
+        sqlite3MoveRenameToken(pParse, z, pToCol->a[i].zName);
+      }
       memcpy(z, pToCol->a[i].zName, n);
       z[n] = 0;
       z += n+1;
index f05fb8dce7fec70ac30a693ef01047aea547316a..d9e4d2a90f710956433253f2462e8a7fb3e4d32c 100644 (file)
@@ -93,6 +93,7 @@ foreach {tn before after} {
 }
 
 #-------------------------------------------------------------------------
+#
 do_execsql_test 2.0 {
   CREATE TABLE t3(a, b, c, d, e, f, g, h, i, j, k, l, m, FOREIGN KEY (b, c, d, e, f, g, h, i, j, k, l, m) REFERENCES t4);
 }
@@ -102,6 +103,61 @@ do_execsql_test 2.1 {
   SELECT sql FROM sqlite_master WHERE name='t3';
 } {{CREATE TABLE t3(a, biglongname, c, d, e, f, g, h, i, j, k, l, m, FOREIGN KEY (biglongname, c, d, e, f, g, h, i, j, k, l, m) REFERENCES t4)}}
 
-finish_test
 
+#-------------------------------------------------------------------------
+#
+do_execsql_test 3.0 {
+  CREATE TABLE t4(x, y, z);
+  CREATE TRIGGER ttt AFTER INSERT ON t4 WHEN new.y<0 BEGIN
+    SELECT 1, 2, 3, 4;
+  END;
+  INSERT INTO t4 VALUES(3, 2, 1);
+}
+
+do_execsql_test 3.1 {
+  ALTER TABLE t4 RENAME y TO abc;
+  SELECT sql FROM sqlite_master WHERE name='t4';
+} {{CREATE TABLE t4(x, abc, z)}}
+
+db close
+sqlite3 db test.db
+
+do_execsql_test 3.2 {
+  SELECT * FROM t4;
+} {3 2 1}
+
+# do_execsql_test 3.3 { INSERT INTO t4 VALUES(6, 5, 4); } {}
+
+#-------------------------------------------------------------------------
+#
+do_execsql_test 4.0 {
+  CREATE TABLE c1(a, b, FOREIGN KEY (a, b) REFERENCES p1(c, d));
+  CREATE TABLE p1(c, d, PRIMARY KEY(c, d));
+  PRAGMA foreign_keys = 1;
+  INSERT INTO p1 VALUES(1, 2);
+  INSERT INTO p1 VALUES(3, 4);
+}
+
+do_execsql_test 4.1 {
+  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 {
+  CREATE TABLE c2(a, b, FOREIGN KEY (a, b) REFERENCES p1);
+}
+
+do_execsql_test 4.1 {
+  ALTER TABLE p1 RENAME "silly name" TO reasonable;
+  SELECT sql FROM sqlite_master WHERE name IN ('c1', 'c2', 'p1');
+} {
+  {CREATE TABLE c1(a, b, FOREIGN KEY (a, b) REFERENCES p1(c, "reasonable"))}
+  {CREATE TABLE p1(c, "reasonable", PRIMARY KEY(c, "reasonable"))}
+  {CREATE TABLE c2(a, b, FOREIGN KEY (a, b) REFERENCES p1)}
+}
+
+finish_test