]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix problems that could occur if a table with the same name as the table being update...
authordan <dan@noemail.net>
Wed, 15 Jul 2020 18:30:01 +0000 (18:30 +0000)
committerdan <dan@noemail.net>
Wed, 15 Jul 2020 18:30:01 +0000 (18:30 +0000)
FossilOrigin-Name: 13224cbd75990615088f3e30ccba05d31b3099fae4300c9ab8f7663bc5f0eb6f

manifest
manifest.uuid
src/resolve.c
src/update.c
test/upfrom3.test

index 872b6d5db8ab47adcb200d68db852cd842bb676f..e34967af0ce79ad504bcaf348dfed6e6b59dea87 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,15 +1,15 @@
 B 5ee3c27e20d12a126fb773b428bb864102b949a5b26a8d5c523753dcedf4be10
-C Fix\sa\sproblem\sin\sSQLITE_ENABLE_HIDDEN_COLUMN\sbuilds\soccuring\swhen\san\sUPDATE...FROM\sfired\san\sINSTEAD\sOF\strigger.
-D 2020-07-15T15:32:59.655
+C Fix\sproblems\sthat\scould\soccur\sif\sa\stable\swith\sthe\ssame\sname\sas\sthe\stable\sbeing\supdated\sappeared\sin\sthe\sFROM\sclause\sof\san\sUPDATE\sstatement.
+D 2020-07-15T18:30:01.625
 F src/alter.c c63fb72ae0ca39175996fcf7008d44022a7ea99e03c0af3e1d968505ceff7120
 F src/attach.c 0b11e00c166b622c84ec176773b1d691c61ad07d247809e3e1635d4e99e71d30
 F src/btree.c b8b0e80c8bbe4e1fb35ae559e9e9aa009799c20cf12f159ebb503b05be1fab9b
 F src/parse.y ecb9abdd79ec86c8dca7cb126bbdcf322c0e282f87a6d0d734ea5f2c57ced516
-F src/resolve.c 04f4710d3ab0070073b60b5b963158dadfbd049db55d10742d9fbd3f28a3f4b8
+F src/resolve.c 2dd6821aac2cd27de9fcf6aa6d1f8c41b4b5841c9bc58bf1c9109008009a3a2e
 F src/select.c a48570f614f777d02dd7f419789944225432a9231b2dbca863411ac19e5fb683
 F src/sqliteInt.h e2684c4ba7ee9c0a0529ae2eb847cc5bf923e4104a9d0944bf3d9d151856b6ab
 F src/trigger.c 6ff9c64a06e6354df8eba08ae18bc809e79931175d39dda32bf1101adee238e5
-F src/update.c d9b7f86c8d694f5131152b4c216ba257844a8bf63ec4bfe71dbe511cad8a7600
+F src/update.c d254339ce702ca08e4761efcc3b841895f09e6a144f4d2b65f4da9e872f9825d
 F src/where.c 35cb38d45294118e484fd3a8011aaee8ebe96b28855a6913575a7fe3722d7af5
 F test/altertab3.test d0d51e652aaa11e37de1f1215181d88334fefcb185f3b9bd91e06e98260c4694
 F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7
@@ -18,8 +18,8 @@ F test/fuzzdata8.db 281cbc8166a8bc5843f4a913e803ba76e27905eb02fb9d5cfd581c2429f2
 F test/triggerupfrom.test d25961fa70a99b6736193da7b49a36d8c1d28d56188f0be6406d4366315cd6e4
 F test/upfrom1.tcl df984cb88010af1555812af55e9db44c4df50677395b45d1f30b69b1b6c07b73
 F test/upfrom1.test 2ba1ed45b4a2161fc79f234b9ce4300b0d3deba545e3f23b938fb3ebdbf8758d
-F test/upfrom3.test 2619374c4806913414cc39514630d85bb12489a5f09a5ebdf6fad0fb4df242e2
-P 53b8b507a10364f5d580655d89c950a5f14c2a8114625fd8749d77f289413b22
-R 50049e7505da24bcfa1309cf7e88265f
+F test/upfrom3.test 3890e1fc372aaf70ca88ec2650f4574b169368a5a63770245a45a28f1524b1b9
+P 5176cb7a6a4e8cfa1973aaae46fcd7d39baedb70ae20bfacc82d62ca39fb0aa3
+R 5994321bbabb2542296f6db00df19961
 U dan
-Z 6a5f095ea5bbd01f6db55318ec51bead
+Z 41a21fcf4a769b492a5346939daeca22
index b024410586a8a38aa3fc47d96e4fcd2e077cb852..d68e77393bdc5625ddb9382e93ba4bf89e4f3dc9 100644 (file)
@@ -1 +1 @@
-5176cb7a6a4e8cfa1973aaae46fcd7d39baedb70ae20bfacc82d62ca39fb0aa3
\ No newline at end of file
+13224cbd75990615088f3e30ccba05d31b3099fae4300c9ab8f7663bc5f0eb6f
\ No newline at end of file
index 8e06344c7a381e36cb02e97088a92acf420e3a5d..3fa3cf97bd5ef5dcaf8d4148f021c91ea5f19eaa 100644 (file)
@@ -766,11 +766,10 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
       struct SrcList_item *pItem;
       assert( pSrcList && pSrcList->nSrc>=1 );
       pItem = pSrcList->a;
-      assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
       pExpr->op = TK_COLUMN;
       pExpr->y.pTab = pItem->pTab;
       pExpr->iTable = pItem->iCursor;
-      pExpr->iColumn = -1;
+      pExpr->iColumn--;
       pExpr->affExpr = SQLITE_AFF_INTEGER;
       break;
     }
index c321edce8edc30c9790257b17055a205cf67cdf8..9cc0e4f64f85987cc6a606127f7e8b0793e1ccaa 100644 (file)
@@ -131,14 +131,36 @@ static int indexWhereClauseMightChange(
 }
 
 /*
-** This function generates VM code to run the query:
+** Allocate and return a pointer to an expression of type TK_ROW with
+** Expr.iColumn set to value (iCol+1). The resolver will modify the
+** expression to be a TK_COLUMN reading column iCol of the first
+** table in the source-list (pSrc->a[0]).
+*/
+static Expr *exprRowColumn(Parse *pParse, int iCol){
+  Expr *pRet = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+  if( pRet ) pRet->iColumn = iCol+1;
+  return pRet;
+}
+
+/*
+** Assuming both the pLimit and pOrderBy parameters are NULL, this function
+** generates VM code to run the query:
 **
-**   SELECT <other-columns>, pChanges FROM pTabList WHERE pWhere
+**   SELECT <other-columns>, pChanges FROM pTabList WHERE pWhere 
 **
 ** and write the results to the ephemeral table already opened as cursor 
 ** iEph. None of pChanges, pTabList or pWhere are modified or consumed by 
 ** this function, they must be deleted by the caller.
 **
+** Or, if pLimit and pOrderBy are not NULL, and pTab is not a view:
+**
+**   SELECT <other-columns>, pChanges FROM pTabList 
+**   WHERE pWhere
+**   GROUP BY <other-columns> 
+**   ORDER BY pOrderBy LIMIT pLimit
+**
+** If pTab is a view, the GROUP BY clause is omitted.
+**
 ** Exactly how results are written to table iEph, and exactly what
 ** the <other-columns> in the query above are is determined by the type
 ** of table pTabList->a[0].pTab.
@@ -158,7 +180,7 @@ static int indexWhereClauseMightChange(
 ** rowid value in <other-columns> is used as the integer key, and the 
 ** remaining fields make up the table record. 
 */
-static void updatePopulateEphTable(
+static void updateFromSelect(
   Parse *pParse,                  /* Parse context */
   int iEph,                       /* Cursor for open eph. table */
   Index *pPk,                     /* PK if table 0 is WITHOUT ROWID */
@@ -172,7 +194,7 @@ static void updatePopulateEphTable(
   SelectDest dest;
   Select *pSelect = 0;
   ExprList *pList = 0;
-  ExprList *pGroupBy = 0;
+  ExprList *pGrp = 0;
   sqlite3 *db = pParse->db;
   Table *pTab = pTabList->a[0].pTab;
   SrcList *pSrc;
@@ -199,34 +221,23 @@ static void updatePopulateEphTable(
   }
   if( pPk ){
     for(i=0; i<pPk->nKeyCol; i++){
-      Expr *pNew = sqlite3PExpr(pParse, TK_DOT,
-          sqlite3Expr(db, TK_ID, pTab->zName),
-          sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName)
-      );
+      Expr *pNew = exprRowColumn(pParse, pPk->aiColumn[i]);
       if( pLimit ){
-        pGroupBy = sqlite3ExprListAppend(pParse, pGroupBy, 
-            sqlite3ExprDup(db, pNew, 0)
-        );
+        pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0));
       }
       pList = sqlite3ExprListAppend(pParse, pList, pNew);
     }
     eDest = SRT_Upfrom;
   }else if( pTab->pSelect ){
-    pList = sqlite3ExprListAppend(pParse, pList, 
-        sqlite3PExpr(pParse, TK_DOT,
-          sqlite3Expr(db, TK_ID, pTab->zName),
-          sqlite3PExpr(pParse, TK_ASTERISK, 0, 0)
-    ));
+    for(i=0; i<pTab->nCol; i++){
+      pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
+    }
     eDest = SRT_Table;
   }else{
     eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
-    pList = sqlite3ExprListAppend(pParse, pList, 
-        sqlite3PExpr(pParse, TK_ROW, 0, 0)
-    );
+    pList = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
     if( pLimit ){
-      pGroupBy = sqlite3ExprListAppend(pParse, pGroupBy, 
-          sqlite3PExpr(pParse, TK_ROW, 0, 0)
-      );
+      pGrp = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
     }
   }
   assert( pChanges || db->mallocFailed );
@@ -238,7 +249,7 @@ static void updatePopulateEphTable(
     }
   }
   pSelect = sqlite3SelectNew(pParse, pList, 
-      pSrc, pWhere2, pGroupBy, 0, pOrderBy2, SF_IncludeHidden, pLimit2
+      pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_IncludeHidden, pLimit2
   );
   sqlite3SelectDestInit(&dest, eDest, iEph);
   dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
@@ -652,7 +663,7 @@ void sqlite3Update(
         }
       }
       if( nChangeFrom ){
-        updatePopulateEphTable(
+        updateFromSelect(
             pParse, iEph, pPk, pChanges, pTabList, pWhere, pOrderBy, pLimit
         );
 #ifndef SQLITE_OMIT_SUBQUERY
@@ -1169,31 +1180,26 @@ static void updateVirtualTable(
   regArg = pParse->nMem + 1;
   pParse->nMem += nArg;
   if( pSrc->nSrc>1 ){
-    ExprList *pList = 0;
+    Expr *pRow;
+    ExprList *pList;
     if( pRowid ){
-      pList = sqlite3ExprListAppend(pParse, pList, sqlite3ExprDup(db,pRowid,0));
+      pRow = sqlite3ExprDup(db, pRowid, 0);
     }else{
-      pList = sqlite3ExprListAppend(pParse, pList, 
-          sqlite3PExpr(pParse, TK_DOT,
-            sqlite3Expr(db, TK_ID, pTab->zName),
-            sqlite3Expr(db, TK_ID, "_rowid_")
-      ));
+      pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
     }
+    pList = sqlite3ExprListAppend(pParse, 0, pRow);
+
     for(i=0; i<pTab->nCol; i++){
       if( aXRef[i]>=0 ){
         pList = sqlite3ExprListAppend(pParse, pList,
           sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0)
         );
       }else{
-        pList = sqlite3ExprListAppend(pParse, pList, 
-            sqlite3PExpr(pParse, TK_DOT,
-              sqlite3Expr(db, TK_ID, pTab->zName),
-              sqlite3Expr(db, TK_ID, pTab->aCol[i].zName)
-        ));
+        pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
       }
     }
 
-    updatePopulateEphTable(pParse, ephemTab, 0, pList, pSrc, pWhere, 0, 0);
+    updateFromSelect(pParse, ephemTab, 0, pList, pSrc, pWhere, 0, 0);
     sqlite3ExprListDelete(db, pList);
     eOnePass = ONEPASS_OFF;
   }else{
index cd1e8c68521c5e93b32d7ddb1968ffbd6e3dce9f..d191cfe3feda954ef2b351d6a26e42619070c973 100644 (file)
@@ -22,6 +22,9 @@ set testprefix upfrom3
 #   2.*: Test UPDATE ... FROM statements that modify PK fields of WITHOUT
 #        ROWID tables.
 #
+#   3.*: Test that UPDATE ... FROM statements are not confused if there
+#        are multiple tables of the same name in attached databases.
+#
 
 foreach {tn wo} {
   1 ""
@@ -171,5 +174,40 @@ do_execsql_test 2.1.4 {
   3 60 60
 }
 
+#-------------------------------------------------------------------------
+foreach {tn wo} {
+  1 ""
+  2 "WITHOUT ROWID"
+} {
+  reset_db
+  forcedelete test.db2
+  eval [string map [list %WO% $wo %TN% $tn] {
+    do_execsql_test 3.$tn.1 {
+      CREATE TABLE g1(a, b, c, PRIMARY KEY(a, b)) %WO%;
+      INSERT INTO g1 VALUES(1, 1, 1);
+
+      ATTACH 'test.db2' AS aux;
+      CREATE TABLE aux.g1(a, b, c, PRIMARY KEY(a, b)) %WO%;
+      INSERT INTO aux.g1 VALUES(10, 1, 10);
+      INSERT INTO aux.g1 VALUES(20, 2, 20);
+      INSERT INTO aux.g1 VALUES(30, 3, 30);
+    }
+
+    do_execsql_test 3.$tn.2 {
+      UPDATE aux.g1 SET c=101 FROM main.g1;
+    }
+    do_execsql_test 3.$tn.3 {
+      SELECT * FROM aux.g1;
+    } {10 1 101  20 2 101  30 3 101}
+
+    do_execsql_test 3.$tn.4 {
+      UPDATE g1 SET c=101 FROM g1;
+    }
+    do_execsql_test 3.$tn.5 {
+      SELECT * FROM g1;
+    } {1 1 101}
+  }]
+}
+
 finish_test