]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix some problems with the feature on this branch. Many problems remain.
authordan <dan@noemail.net>
Thu, 15 Nov 2018 21:20:56 +0000 (21:20 +0000)
committerdan <dan@noemail.net>
Thu, 15 Nov 2018 21:20:56 +0000 (21:20 +0000)
FossilOrigin-Name: 31b6aee755c81d69aeaf3ae197e510d38e5e3bb83ded44c33379bcd0d4c23300

19 files changed:
manifest
manifest.uuid
src/build.c
src/callback.c
src/delete.c
src/fkey.c
src/insert.c
src/pragma.c
src/prepare.c
src/select.c
src/shell.c.in
src/sqliteInt.h
src/trigger.c
src/update.c
src/vdbe.c
src/vdbe.h
src/vdbeInt.h
src/where.c
test/reuse1.test

index ec694b92e2b4d37ff149b7455223a2f2d72ab64d..0dfcf2a90c74266b429062f0ea65821cc4933dca 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\slatest\strunk\schanges\swith\sthis\sbranch.
-D 2018-11-09T18:44:45.344
+C Fix\ssome\sproblems\swith\sthe\sfeature\son\sthis\sbranch.\sMany\sproblems\sremain.
+D 2018-11-15T21:20:56.480
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in edbb6e20bb1decf65f6c64c9e61004a69bdf8afb39cdce5337c916b03dfcd1e3
@@ -448,24 +448,24 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
 F src/btree.c 3ef104ecae8b1b5f0458be1f5fa7c1ecf25fdc322a9d63bb8151f89eb32d381e
 F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
-F src/build.c b48fa5d9eef7fadb84e7f8fd2fe3537cfb5fe56d4da43c3cf8bb61a75f369ef7
-F src/callback.c d102423552dc74edd242c92c5f74c88ac2537e47bb16a2a043929cd394653710
+F src/build.c ce75a5834f17a047fb86b561a1f53dc1ac41d1c8c623f69d74511175a48c1284
+F src/callback.c e5031c28f6e8eb2f290298e262eb1eb5f201ef2ae25db54b396882ae2059e944
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
 F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
 F src/dbpage.c ada9bc6964bb68e4c128df70cb0938faaa214e1a0e1d730ea6b13c5e1fde9a45
 F src/dbstat.c e042b0e7833fdacf2d5ea92c6b536962fea6aeed8b7287ca87ddfa3412bd9564
-F src/delete.c e1ac11c062a4a2ed29a9e9a63f4cbc7f0330291ae276d768b26fb2c5152cc3b4
+F src/delete.c 70817a92a61ba2621c15f0250064d4c451de747eb2a427cf2bc8736fabf21f9f
 F src/expr.c 9aacc0b72348ba90010b672dcbbbe2fa56e1182043bc917a3a147b2bc57a5497
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812
+F src/fkey.c 029a6f10f740b366303a572796f6f21a878ecda9f8cb1614bb4c344d5df6e9aa
 F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
 F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
 F src/hash.c 931ec82d7e070654a8facb42549bbb3a25720171d73ba94c3d3160580d01ef1f
 F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 6b81aae27b196925d8ff78824f4bbd435d6a40cd38dc324685e21735bb402109
+F src/insert.c e0dbee655b327d21670c143a7abf6a0a4b384633c100cfeb1c6ce3dce34f0216
 F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
 F src/loadext.c 448eab53ecdb566a1259ee2d45ebff9c0bc4a2cf393774488775c33e4fbe89bf
 F src/main.c 2bbab4122a28c10ff98e5497a15fdfde1d7a075a659739448a61ef0c09a30d19
@@ -497,19 +497,19 @@ F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179
 F src/pcache.c 4196eb6ed3bbf00b80596c8e0b4f50e57eb7d890c19fb27a7354306abb7f983d
 F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
-F src/pragma.c 0bb05b1788d7af5fdc7f40f5655a79a140dece8fd2523402eb2103925e4739c2
+F src/pragma.c c0fd52b16862060c7e010b1751cab6443a994feda22b59edebea599639cdeebe
 F src/pragma.h fdd03d78a7497f74a3f652909f945328480089189526841ae829ce7313d98d13
-F src/prepare.c d728e4031435277e25769bf27ce90a6c675b9c6aef4b2641b31e9604e23c6340
+F src/prepare.c b64a19ee9b0ba1f3a67c4f5d1be308e9f67f8fb07fe90725982dfa9b616d211f
 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c bc8c79e56439b111e7d9415e44940951f7087e9466c3a9d664558ef0faf31073
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c 61e867a906f140b73baf4ce7a201ad6dcba30820969f5618ee40e9a0d32c6f5f
-F src/shell.c.in 37a6b4c336eab71cc1feef42c3136d7c018a1833797131a35c21767ad00bb1ce
+F src/select.c 08bbb3b8f48a55d900372ba4358fdd0b2a0b5e264fc9aeaedf5a91b3b9546e04
+F src/shell.c.in 9f517c22e3c9a08ab634330789f74454ec9a7e0596c8faed221c6b43ee980b96
 F src/sqlite.h.in 29a3b2eab328c5a345ef6be09ff77dc6dabbfe1a36e05c19204591d084a73d80
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
-F src/sqliteInt.h 925c0379afb30711c1cc171997d21e87f8eee257b0f23791803173dd8ad49385
+F src/sqliteInt.h 47d235a0c1b7a8d210a0a82b27e395c5adba0ddd42fc9f070de18ac17e3023c7
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c b651e68af3cb859e4083c79e0e7177e2aeb35ed23e3892d7bbe5b732d38bf2b9
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -569,15 +569,15 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c 9e781e1ca80eefe7b5d6a9e2cd5c678c847da55fd6f093781fad7950934d4c83
 F src/treeview.c 7b12ac059de54c939b6eb0dbffc9410c29c80d2470cee5cbe07d5ff9ea2d9253
-F src/trigger.c 9ec37388378ba50a433d3a2b7daaca5d712185977c0d3180ab5043c32ed4a8d0
-F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274
+F src/trigger.c 6e970e8d2d4bb805faed88ccbc3f5cc0552822b4c88d655d79197a29925392c1
+F src/update.c 9e05b1eb83dbfa778f76ca8666c403b0a45d449546a27303fce86cbc75fa07d8
 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
 F src/vacuum.c 6da236d4897c0227c0bef7c8f5be718482b65c8fc158fc46ffda2c529df1ba2f
-F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b
-F src/vdbe.h faedef405cf4e0679b46286576cebb307255d1a5c65908f470628255833faec4
-F src/vdbeInt.h 8a52b8db3d20f9755a965d864b8653052c7ef1ccadceb2e057047cd421f6336e
+F src/vdbe.c 103913320325dc5848449a8f9a8470b1b67d74dc47d67ade1c7d6024b50517a5
+F src/vdbe.h fda06d544a79e684797e7d433e5c410e563f8d3897098826e4c23cdb3be4193e
+F src/vdbeInt.h f7ffb42483f9ab5c5594739b0552dc2185bc0a75de3f19e652c6e66543e63659
 F src/vdbeapi.c ecccfce6f614c33a95952efeec969d163e8349eac314ee2b7b163eda921b5eb0
 F src/vdbeaux.c 5e83d8a9e6513d14f17810c70a87d4876bf9f2b55eb78bec8571fe37a37ade1a
 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
@@ -589,7 +589,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
 F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
 F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66
-F src/where.c f5da1079f084c569aa70fd4ada6b7e45b356e19708f1e5307493cc65857ec9e4
+F src/where.c dc648e8b7e98fa8e28a3269991445b361dec13a17c11de13cb20b53228b674f5
 F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
 F src/wherecode.c c45f03aefc2266b990df0fc4d7acc4e27f56f881f4fc0fc355b7cbc4d7189da5
 F src/whereexpr.c 491f0894ad9903750cdecb7894437a0cabdffdd88f574d2b1c9ac85d14fe4b9c
@@ -1205,7 +1205,7 @@ F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
 F test/releasetest.tcl c5b474f9880073fc3b69729ee05d5284653a9ee101af572204917d9dcb1d9015 x
 F test/resetdb.test 684a6ffde5a5141bba79f3101981cc38dcfc3403f61e643b7b3aa68bef0b8408
 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
-F test/reuse1.test 04ae701b4000113fedc472719e4cf4bb1d34d22dcaf8d3e643d41d1256a9590d
+F test/reuse1.test 319bf426a1b86d9cf732cb2fb8a58f6fcbf03028868057a7d11a20f60b3ce8f2
 F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
 F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
 F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
@@ -1777,7 +1777,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 3869b2106b9a639b5e739dc9f9acd2f7a9223d3ce562297b877c5d4d2bf76468 531eca6104e41e4301fa2cf58bb8fec811da31e151a0f766c93aece5521d235b
-R 3fa5f37112ee4c967fdfda26327db2a3
+P ae88f8e1ffc33748e45308c21ba83499228ae05344df81e41dd61e14a1270588
+R 740a0a9e9ba5fc4d27352073aa3c155e
 U dan
-Z 232d13f5aeabfa21c7a449cba90c71ad
+Z 1fe3247f080874c257f8285203414ee8
index cfc614a65da572d9268f4a29a5987bf28cc5e92c..7496447a89e567f235bbba49973d0dc04d58a4f3 100644 (file)
@@ -1 +1 @@
-ae88f8e1ffc33748e45308c21ba83499228ae05344df81e41dd61e14a1270588
\ No newline at end of file
+31b6aee755c81d69aeaf3ae197e510d38e5e3bb83ded44c33379bcd0d4c23300
\ No newline at end of file
index f3be764cca1b5158abd6e92d3784f30bfde85540..084a73d4362543b4745f58d20db5ccba823febba 100644 (file)
@@ -395,8 +395,13 @@ Table *sqlite3LocateTableItem(
   struct SrcList_item *p
 ){
   const char *zDb;
-  assert( p->pSchema==0 || p->zDatabase==0 );
-  if( p->pSchema ){
+  if( pParse->iFixDb && pParse->iFixDb!=2 ){
+    zDb = pParse->db->aDb[pParse->iFixDb-1].zDbSName;
+    assert( p->zDatabase==0 || sqlite3StrICmp(p->zDatabase, zDb)==0 );
+    if( p->zDatabase==0 ){
+      p->zDatabase = sqlite3DbStrDup(pParse->db, zDb);
+    }
+  }else if( p->pSchema ){
     int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
     zDb = pParse->db->aDb[iDb].zDbSName;
   }else{
@@ -3027,7 +3032,6 @@ void sqlite3CreateIndex(
   char *zName = 0;     /* Name of the index */
   int nName;           /* Number of characters in zName */
   int i, j;
-  DbFixer sFix;        /* For assigning database names to pTable */
   int sortOrderMask;   /* 1 to honor DESC in index.  0 to ignore. */
   sqlite3 *db = pParse->db;
   Db *pDb;             /* The specific table containing the indexed database */
@@ -3076,13 +3080,9 @@ void sqlite3CreateIndex(
     }
 #endif
 
-    sqlite3FixInit(&sFix, pParse, iDb, "index", pName);
-    if( sqlite3FixSrcList(&sFix, pTblName) ){
-      /* Because the parser constructs pTblName from a single identifier,
-      ** sqlite3FixSrcList can never fail. */
-      assert(0);
-    }
+    if( iDb!=1 ) pTblName->a[0].zDatabase = db->aDb[iDb].zDbSName;
     pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
+    pTblName->a[0].zDatabase = 0;
     assert( db->mallocFailed==0 || pTab==0 );
     if( pTab==0 ) goto exit_create_index;
     if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){
index e136045fbe9e7919e9221c1b9e08b8acd89dd04a..2ab65eca18c766dd6e00d54e32470c9209f9130e 100644 (file)
@@ -555,11 +555,11 @@ void sqlite3SchemaReuse(sqlite3 *db, int iDb){
   Schema *p;
   assert( pSchema && iDb!=1 );
 
-  sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
+  sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_SCHEMA_REUSE) );
   for(p=sharedSchemaList; p; p=p->pNext){
     if( p->cksum==pSchema->cksum 
-        && p->schema_cookie==pSchema->schema_cookie 
-      ){
+     && p->schema_cookie==pSchema->schema_cookie 
+    ){
       break;
     }
   }
@@ -571,7 +571,7 @@ void sqlite3SchemaReuse(sqlite3 *db, int iDb){
     /* Found a matching schema. Increase its ref count. */
     p->nRef++;
   }
-  sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
+  sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_SCHEMA_REUSE) );
 
   /* If a matching schema was found in the shared schema list, free the
   ** schema object just parsed, and add a pointer to the matching schema
index fa49f6666616544f921bf1c410a8611b3201abd0..c0b94e73a6744f6908554a2bca4a5e02a413f6c4 100644 (file)
@@ -88,6 +88,7 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
 */
 void sqlite3MaterializeView(
   Parse *pParse,       /* Parsing context */
+  int iDb,             /* Database in which view resides */
   Table *pView,        /* View definition */
   Expr *pWhere,        /* Optional WHERE clause to be added */
   ExprList *pOrderBy,  /* Optional ORDER BY clause */
@@ -98,7 +99,6 @@ void sqlite3MaterializeView(
   Select *pSel;
   SrcList *pFrom;
   sqlite3 *db = pParse->db;
-  int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
   pWhere = sqlite3ExprDup(db, pWhere, 0);
   pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
   if( pFrom ){
@@ -312,7 +312,7 @@ void sqlite3DeleteFrom(
   if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){
     goto delete_from_cleanup;
   }
-  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+  iDb = sqlite3SchemaToIndex2(db, pTab->pSchema, pTabList->a[0].zDatabase);
   assert( iDb<db->nDb );
   rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, 
                             db->aDb[iDb].zDbSName);
@@ -350,9 +350,7 @@ void sqlite3DeleteFrom(
   */
 #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
   if( isView ){
-    sqlite3MaterializeView(pParse, pTab, 
-        pWhere, pOrderBy, pLimit, iTabCur
-    );
+    sqlite3MaterializeView(pParse, iDb, pTab, pWhere, pOrderBy, pLimit,iTabCur);
     iDataCur = iIdxCur = iTabCur;
     pOrderBy = 0;
     pLimit = 0;
@@ -516,8 +514,8 @@ void sqlite3DeleteFrom(
         iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
       }
       testcase( IsVirtual(pTab) );
-      sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE,
-                                 iTabCur, aToOpen, &iDataCur, &iIdxCur);
+      sqlite3OpenTableAndIndices(pParse, iDb, pTab, OP_OpenWrite, 
+          OPFLAG_FORDELETE, iTabCur, aToOpen, &iDataCur, &iIdxCur);
       assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
       assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
       if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
@@ -566,7 +564,7 @@ void sqlite3DeleteFrom(
 #endif
     {
       int count = (pParse->nested==0);    /* True to count changes */
-      sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
+      sqlite3GenerateRowDelete(pParse, iDb, pTab, pTrigger, iDataCur, iIdxCur,
           iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]);
     }
   
@@ -665,6 +663,7 @@ delete_from_cleanup:
 */
 void sqlite3GenerateRowDelete(
   Parse *pParse,     /* Parsing context */
+  int iDb,
   Table *pTab,       /* Table containing the row to be deleted */
   Trigger *pTrigger, /* List of triggers to (potentially) fire */
   int iDataCur,      /* Cursor from which column data is extracted */
@@ -707,7 +706,7 @@ void sqlite3GenerateRowDelete(
     /* TODO: Could use temporary registers here. Also could attempt to
     ** avoid copying the contents of the rowid register.  */
     mask = sqlite3TriggerColmask(
-        pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
+        pParse, iDb, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
     );
     mask |= sqlite3FkOldmask(pParse, pTab);
     iOld = pParse->nMem+1;
@@ -726,7 +725,7 @@ void sqlite3GenerateRowDelete(
 
     /* Invoke BEFORE DELETE trigger programs. */
     addrStart = sqlite3VdbeCurrentAddr(v);
-    sqlite3CodeRowTrigger(pParse, pTrigger, 
+    sqlite3CodeRowTrigger(pParse, iDb, pTrigger, 
         TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
     );
 
@@ -782,10 +781,10 @@ void sqlite3GenerateRowDelete(
   /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
   ** handle rows (possibly in other tables) that refer via a foreign key
   ** to the row just deleted. */ 
-  sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0);
+  sqlite3FkActions(pParse, iDb, pTab, 0, iOld, 0, 0);
 
   /* Invoke AFTER DELETE trigger programs. */
-  sqlite3CodeRowTrigger(pParse, pTrigger, 
+  sqlite3CodeRowTrigger(pParse, iDb, pTrigger, 
       TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
   );
 
index 6777d71eafdb91a621c9a295bc842e4c67776365..62cbbd7899fa0d27059fb5a5e02bf436279878bf 100644 (file)
@@ -1359,6 +1359,7 @@ static Trigger *fkActionTrigger(
 */
 void sqlite3FkActions(
   Parse *pParse,                  /* Parse context */
+  int iDb,                        /* Database in which pTab resides */
   Table *pTab,                    /* Table being updated or deleted from */
   ExprList *pChanges,             /* Change-list for UPDATE, NULL for DELETE */
   int regOld,                     /* Address of array containing old row */
@@ -1375,7 +1376,7 @@ void sqlite3FkActions(
       if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){
         Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges);
         if( pAct ){
-          sqlite3CodeRowTriggerDirect(pParse, pAct, pTab, regOld, OE_Abort, 0);
+          sqlite3CodeRowTriggerDirect(pParse, iDb, pAct,pTab,regOld,OE_Abort,0);
         }
       }
     }
index 7a9413901fc32e18fefd13538387b5d5672961fd..5f5ca7afd6ba5b767a4ea0613e46e578ab4c4c05 100644 (file)
@@ -568,7 +568,7 @@ void sqlite3Insert(
   if( pTab==0 ){
     goto insert_cleanup;
   }
-  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+  iDb = sqlite3SchemaToIndex2(db, pTab->pSchema, pTabList->a[0].zDatabase);
   assert( iDb<db->nDb );
   if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0,
                        db->aDb[iDb].zDbSName) ){
@@ -811,7 +811,7 @@ void sqlite3Insert(
   /* If this is not a view, open the table and and all indices */
   if( !isView ){
     int nIdx;
-    nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
+    nIdx = sqlite3OpenTableAndIndices(pParse, iDb, pTab, OP_OpenWrite, 0, -1, 0,
                                       &iDataCur, &iIdxCur);
     aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1));
     if( aRegIdx==0 ){
@@ -927,7 +927,7 @@ void sqlite3Insert(
     }
 
     /* Fire BEFORE or INSTEAD OF triggers */
-    sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, 
+    sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, 
         pTab, regCols-pTab->nCol-1, onError, endOfLoop);
 
     sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
@@ -1067,7 +1067,7 @@ void sqlite3Insert(
 
   if( pTrigger ){
     /* Code AFTER triggers */
-    sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, 
+    sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, 
         pTab, regData-2-pTab->nCol, onError, endOfLoop);
   }
 
@@ -1557,7 +1557,7 @@ void sqlite3GenerateConstraintChecks(
         }
         if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
           sqlite3MultiWrite(pParse);
-          sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
+          sqlite3GenerateRowDelete(pParse, 0, pTab, pTrigger, iDataCur, iIdxCur,
                                    regNewData, 1, 0, OE_Replace, 1, -1);
         }else{
 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
@@ -1806,7 +1806,7 @@ void sqlite3GenerateConstraintChecks(
         if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
           sqlite3MultiWrite(pParse);
         }
-        sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
+        sqlite3GenerateRowDelete(pParse, 0, pTab, pTrigger, iDataCur, iIdxCur,
             regR, nPkField, 0, OE_Replace,
             (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
         seenReplace = 1;
@@ -1967,6 +1967,7 @@ void sqlite3CompleteInsertion(
 */
 int sqlite3OpenTableAndIndices(
   Parse *pParse,   /* Parsing context */
+  int iDb,         /* Database to open pTab in */
   Table *pTab,     /* Table to be opened */
   int op,          /* OP_OpenRead or OP_OpenWrite */
   u8 p5,           /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */
@@ -1976,7 +1977,6 @@ int sqlite3OpenTableAndIndices(
   int *piIdxCur    /* Write the first index cursor number here */
 ){
   int i;
-  int iDb;
   int iDataCur;
   Index *pIdx;
   Vdbe *v;
@@ -1989,7 +1989,6 @@ int sqlite3OpenTableAndIndices(
     ** can detect if they are used by mistake in the caller. */
     return 0;
   }
-  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
   if( iBase<0 ) iBase = pParse->nTab;
index 52d6338ca0495a9e9ba21d40fd1a857d7254ec47..49645093e1c8ea6e7a43921e7da55c6a4161ef5b 100644 (file)
@@ -1552,7 +1552,7 @@ void sqlite3Pragma(
 
         if( pTab->tnum<1 ) continue;  /* Skip VIEWs or VIRTUAL TABLEs */
         pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
-        sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
+        sqlite3OpenTableAndIndices(pParse, i, pTab, OP_OpenRead, 0,
                                    1, 0, &iDataCur, &iIdxCur);
         /* reg[7] counts the number of entries in the table.
         ** reg[8+i] counts the number of entries in the i-th index 
index 305c3b9841c580dedacdae8ca542ed750f06ad5b..57aacf6af3715cdc44129490018435a4bccef7de 100644 (file)
@@ -534,6 +534,17 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
   return i;
 }
 
+int sqlite3SchemaToIndex2(sqlite3 *db, Schema *pSchema, const char *zDb){
+  if( zDb ){
+    int i;
+    for(i=0; i<db->nDb; i++){
+      if( i==1 ) continue;
+      if( sqlite3StrICmp(zDb, db->aDb[i].zDbSName)==0 ) return i;
+    }
+  }
+  return sqlite3SchemaToIndex(db, pSchema);
+}
+
 /*
 ** Free all memory allocations in the pParse object
 */
index c60ff270017733f3f7fa77153a0f0471c4b77ac8..7fec85a43525b77f1c67de337e514e66561a25c7 100644 (file)
@@ -4886,13 +4886,21 @@ static int selectExpander(Walker *pWalker, Select *p){
       }
 #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
       if( IsVirtual(pTab) || pTab->pSelect ){
+        int iSave = pParse->iFixDb;
         i16 nCol;
-        if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
+        pParse->iFixDb = 1 + sqlite3SchemaToIndex2(
+            db, pTab->pSchema, pFrom->zDatabase
+        );
+        if( sqlite3ViewGetColumnNames(pParse, pTab) ){
+          pParse->iFixDb = iSave;
+          return WRC_Abort;
+        }
         assert( pFrom->pSelect==0 );
         pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
         nCol = pTab->nCol;
         pTab->nCol = -1;
         sqlite3WalkSelect(pWalker, pFrom->pSelect);
+        pParse->iFixDb = iSave;
         pTab->nCol = nCol;
       }
 #endif
index 19c32be35096493d43ced2a2e78d8a3210ebbf8b..6df26602ecc468b6b09f5ff3eae42f3dc75bdf04 100644 (file)
@@ -1065,7 +1065,7 @@ struct ShellState {
 #define SHELL_OPEN_ZIPFILE     3      /* Use the zipfile virtual table */
 #define SHELL_OPEN_READONLY    4      /* Open a normal database read-only */
 #define SHELL_OPEN_DESERIALIZE 5      /* Open using sqlite3_deserialize() */
-#define SHELL_OPEN_REUSESCHEMA 5    /* Open for schema reuse */
+#define SHELL_OPEN_REUSESCHEMA 6      /* Open for schema reuse */
 
 /*
 ** These are the allowed shellFlgs values
index 61abb3aa708e9d5adea76eec3ebc5661612ee73a..3bddaf75c47ce53106a9e99bf81170adaf43313c 100644 (file)
@@ -1059,6 +1059,11 @@ struct BusyHandler {
 #define UNUSED_PARAMETER(x) (void)(x)
 #define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
 
+/*
+** The static mutex with which to protect reusable schemas.
+*/
+#define SQLITE_MUTEX_SCHEMA_REUSE SQLITE_MUTEX_STATIC_APP1
+
 /*
 ** Forward references to structures
 */
@@ -3002,6 +3007,7 @@ struct AutoincInfo {
 struct TriggerPrg {
   Trigger *pTrigger;      /* Trigger this program was coded from */
   TriggerPrg *pNext;      /* Next entry in Parse.pTriggerPrg list */
+  int iFixDb;             /* Value of Parse.iFixDb when this was coded */
   SubProgram *pProgram;   /* Program implementing pTrigger/orconf */
   int orconf;             /* Default ON CONFLICT policy */
   u32 aColmask[2];        /* Masks of old.*, new.* columns accessed */
@@ -3139,6 +3145,7 @@ struct Parse {
 #ifndef SQLITE_OMIT_ALTERTABLE
   RenameToken *pRename;     /* Tokens subject to renaming by ALTER TABLE */
 #endif
+  int iFixDb;
 };
 
 #define PARSE_MODE_NORMAL        0
@@ -4024,7 +4031,7 @@ int sqlite3IsRowid(const char*);
 int sqlite3IsRowidN(const char*, int);
 #endif
 void sqlite3GenerateRowDelete(
-    Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
+    Parse*,int,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
 void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
 int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
 void sqlite3ResolvePartIdxLabel(Parse*,int);
@@ -4037,7 +4044,7 @@ void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
 # define sqlite3SetMakeRecordP5(A,B)
 #endif
 void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
-int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
+int sqlite3OpenTableAndIndices(Parse*, int, Table*, int, u8, int,u8*,int*,int*);
 void sqlite3BeginWriteOperation(Parse*, int, int);
 void sqlite3MultiWrite(Parse*);
 void sqlite3MayAbort(Parse*);
@@ -4062,7 +4069,7 @@ int sqlite3SafetyCheckSickOrOk(sqlite3*);
 void sqlite3ChangeCookie(Parse*, int);
 
 #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
-void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
+void sqlite3MaterializeView(Parse*, int, Table*, Expr*, ExprList*,Expr*,int);
 #endif
 
 #ifndef SQLITE_OMIT_TRIGGER
@@ -4073,9 +4080,9 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
   void sqlite3DropTriggerPtr(Parse*, Trigger*);
   Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask);
   Trigger *sqlite3TriggerList(Parse *, Table *);
-  void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *,
-                            int, int, int);
-  void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
+  void sqlite3CodeRowTrigger(Parse*, int, Trigger *, int, ExprList*, int, 
+                             Table *, int, int, int);
+  void sqlite3CodeRowTriggerDirect(Parse*, int, Trigger*, Table*, int, int,int);
   void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
   void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
   TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
@@ -4089,7 +4096,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
                                         const char*,const char*);
   void sqlite3DeleteTrigger(sqlite3*, Trigger*);
   void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
-  u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
+  u32 sqlite3TriggerColmask(Parse*,int,Trigger*,ExprList*,int,int,Table*,int);
 # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
 # define sqlite3IsToplevel(p) ((p)->pToplevel==0)
 #else
@@ -4097,12 +4104,12 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
 # define sqlite3DeleteTrigger(A,B)
 # define sqlite3DropTriggerPtr(A,B)
 # define sqlite3UnlinkAndDeleteTrigger(A,B,C)
-# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I)
-# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
+# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J)
+# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F,G)
 # define sqlite3TriggerList(X, Y) 0
 # define sqlite3ParseToplevel(p) p
 # define sqlite3IsToplevel(p) 1
-# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
+# define sqlite3TriggerColmask(A,B,C,D,E,F,G,H) 0
 #endif
 
 int sqlite3JoinType(Parse*, Token*, Token*, Token*);
@@ -4294,6 +4301,7 @@ void sqlite3SchemaReuse(sqlite3*, int);
 void sqlite3SchemaWritable(Parse*, int);
 Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
 int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
+int sqlite3SchemaToIndex2(sqlite3 *db, Schema *, const char*);
 KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
 void sqlite3KeyInfoUnref(KeyInfo*);
 KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
@@ -4462,12 +4470,12 @@ const char *sqlite3JournalModename(int);
 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
   void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
   void sqlite3FkDropTable(Parse*, SrcList *, Table*);
-  void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
+  void sqlite3FkActions(Parse*, int, Table*, ExprList*, int, int*, int);
   int sqlite3FkRequired(Parse*, Table*, int*, int);
   u32 sqlite3FkOldmask(Parse*, Table*);
   FKey *sqlite3FkReferences(Table *);
 #else
-  #define sqlite3FkActions(a,b,c,d,e,f)
+  #define sqlite3FkActions(a,b,c,d,e,f,g)
   #define sqlite3FkCheck(a,b,c,d,e,f)
   #define sqlite3FkDropTable(a,b,c)
   #define sqlite3FkOldmask(a,b)         0
index 1d5eafbef675975940f2bfc1047a90461988d7c7..4d6c71978e221706dd573f8505fc1263b42ff32c 100644 (file)
@@ -729,20 +729,12 @@ static SrcList *targetSrcList(
   TriggerStep *pStep   /* The trigger containing the target token */
 ){
   sqlite3 *db = pParse->db;
-  int iDb;             /* Index of the database to use */
   SrcList *pSrc;       /* SrcList to be returned */
 
   pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
   if( pSrc ){
     assert( pSrc->nSrc>0 );
     pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
-    iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema);
-    if( iDb==0 || iDb>=2 ){
-      const char *zDb;
-      assert( iDb<db->nDb );
-      zDb = db->aDb[iDb].zDbSName;
-      pSrc->a[pSrc->nSrc-1].zDatabase =  sqlite3DbStrDup(db, zDb);
-    }
   }
   return pSrc;
 }
@@ -904,6 +896,7 @@ static TriggerPrg *codeRowTrigger(
   pPrg->orconf = orconf;
   pPrg->aColmask[0] = 0xffffffff;
   pPrg->aColmask[1] = 0xffffffff;
+  pPrg->iFixDb = pParse->iFixDb;
 
   /* Allocate and populate a new Parse context to use for coding the 
   ** trigger sub-program.  */
@@ -917,11 +910,12 @@ static TriggerPrg *codeRowTrigger(
   pSubParse->zAuthContext = pTrigger->zName;
   pSubParse->eTriggerOp = pTrigger->op;
   pSubParse->nQueryLoop = pParse->nQueryLoop;
+  pSubParse->iFixDb = pParse->iFixDb;
 
   v = sqlite3GetVdbe(pSubParse);
   if( v ){
-    VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", 
-      pTrigger->zName, onErrorText(orconf),
+    VdbeComment((v, "Start: %s.%s (%d) (%s %s%s%s ON %s)", 
+      pTrigger->zName, onErrorText(orconf), pParse->iFixDb-1,
       (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
         (pTrigger->op==TK_UPDATE ? "UPDATE" : ""),
         (pTrigger->op==TK_INSERT ? "INSERT" : ""),
@@ -967,6 +961,7 @@ static TriggerPrg *codeRowTrigger(
     pProgram->nMem = pSubParse->nMem;
     pProgram->nCsr = pSubParse->nTab;
     pProgram->token = (void *)pTrigger;
+    pProgram->itoken = pParse->iFixDb;
     pPrg->aColmask[0] = pSubParse->oldmask;
     pPrg->aColmask[1] = pSubParse->newmask;
     sqlite3VdbeDelete(v);
@@ -988,12 +983,15 @@ static TriggerPrg *codeRowTrigger(
 */
 static TriggerPrg *getRowTrigger(
   Parse *pParse,       /* Current parse context */
+  int iDb,             /* Database containing pTab */
   Trigger *pTrigger,   /* Trigger to code */
   Table *pTab,         /* The table trigger pTrigger is attached to */
   int orconf           /* ON CONFLICT algorithm. */
 ){
   Parse *pRoot = sqlite3ParseToplevel(pParse);
   TriggerPrg *pPrg;
+  int iFixDb = pParse->iFixDb;
+  pParse->iFixDb = (pTrigger->pSchema==pRoot->db->aDb[1].pSchema)?0:(iDb+1);
 
   assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
 
@@ -1001,16 +999,19 @@ static TriggerPrg *getRowTrigger(
   ** process of being coded). If this is the case, then an entry with
   ** a matching TriggerPrg.pTrigger field will be present somewhere
   ** in the Parse.pTriggerPrg list. Search for such an entry.  */
-  for(pPrg=pRoot->pTriggerPrg; 
-      pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); 
-      pPrg=pPrg->pNext
-  );
+  for(pPrg=pRoot->pTriggerPrg; pPrg; pPrg=pPrg->pNext){
+    if( pPrg->pTrigger==pTrigger 
+     && pPrg->orconf==orconf 
+     && pParse->iFixDb==pPrg->iFixDb
+    ) break;
+  }
 
   /* If an existing TriggerPrg could not be located, create a new one. */
   if( !pPrg ){
     pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf);
   }
 
+  pParse->iFixDb = iFixDb;
   return pPrg;
 }
 
@@ -1022,6 +1023,7 @@ static TriggerPrg *getRowTrigger(
 */
 void sqlite3CodeRowTriggerDirect(
   Parse *pParse,       /* Parse context */
+  int iDb,             /* Database containing pTrigger */
   Trigger *p,          /* Trigger to code */
   Table *pTab,         /* The table to code triggers from */
   int reg,             /* Reg array containing OLD.* and NEW.* values */
@@ -1030,7 +1032,8 @@ void sqlite3CodeRowTriggerDirect(
 ){
   Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */
   TriggerPrg *pPrg;
-  pPrg = getRowTrigger(pParse, p, pTab, orconf);
+
+  pPrg = getRowTrigger(pParse, iDb, p, pTab, orconf);
   assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
 
   /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program 
@@ -1040,8 +1043,9 @@ void sqlite3CodeRowTriggerDirect(
 
     sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem,
                       (const char *)pPrg->pProgram, P4_SUBPROGRAM);
-    VdbeComment(
-        (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf)));
+    VdbeComment((v, "Call: %s.%s (%d)", 
+          (p->zName?p->zName:"fkey"), onErrorText(orconf), iDb
+    ));
 
     /* Set the P5 operand of the OP_Program instruction to non-zero if
     ** recursive invocation of this trigger program is disallowed. Recursive
@@ -1094,6 +1098,7 @@ void sqlite3CodeRowTriggerDirect(
 */
 void sqlite3CodeRowTrigger(
   Parse *pParse,       /* Parse context */
+  int iDb,
   Trigger *pTrigger,   /* List of triggers on table pTab */
   int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
   ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
@@ -1124,7 +1129,7 @@ void sqlite3CodeRowTrigger(
      && p->tr_tm==tr_tm 
      && checkColumnOverlap(p->pColumns, pChanges)
     ){
-      sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
+      sqlite3CodeRowTriggerDirect(pParse, iDb, p, pTab, reg, orconf,ignoreJump);
     }
   }
 }
@@ -1156,6 +1161,7 @@ void sqlite3CodeRowTrigger(
 */
 u32 sqlite3TriggerColmask(
   Parse *pParse,       /* Parse context */
+  int iDb,
   Trigger *pTrigger,   /* List of triggers on table pTab */
   ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
   int isNew,           /* 1 for new.* ref mask, 0 for old.* ref mask */
@@ -1173,7 +1179,7 @@ u32 sqlite3TriggerColmask(
      && checkColumnOverlap(p->pColumns,pChanges)
     ){
       TriggerPrg *pPrg;
-      pPrg = getRowTrigger(pParse, p, pTab, orconf);
+      pPrg = getRowTrigger(pParse, iDb, p, pTab, orconf);
       if( pPrg ){
         mask |= pPrg->aColmask[isNew];
       }
index 70f4f676da1d223a20f15126534e3d250df8d670..c482e734b1ad3da8484496adba4d8561b20488cf 100644 (file)
@@ -211,7 +211,7 @@ void sqlite3Update(
   */
   pTab = sqlite3SrcListLookup(pParse, pTabList);
   if( pTab==0 ) goto update_cleanup;
-  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+  iDb = sqlite3SchemaToIndex2(db, pTab->pSchema, pTabList->a[0].zDatabase);
 
   /* Figure out if we have any triggers and if the table being
   ** updated is a view.
@@ -416,7 +416,7 @@ void sqlite3Update(
   */
 #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
   if( isView ){
-    sqlite3MaterializeView(pParse, pTab, 
+    sqlite3MaterializeView(pParse, iDb, pTab, 
         pWhere, pOrderBy, pLimit, iDataCur
     );
     pOrderBy = 0;
@@ -563,7 +563,7 @@ void sqlite3Update(
       if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){
         addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
       }
-      sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur,
+      sqlite3OpenTableAndIndices(pParse, iDb, pTab, OP_OpenWrite, 0, iBaseCur,
                                  aToOpen, 0, 0);
       if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
     }
@@ -610,7 +610,7 @@ void sqlite3Update(
   ** information is needed */
   if( chngPk || hasFK || pTrigger ){
     u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
-    oldmask |= sqlite3TriggerColmask(pParse, 
+    oldmask |= sqlite3TriggerColmask(pParse, iDb,
         pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
     );
     for(i=0; i<pTab->nCol; i++){
@@ -643,7 +643,7 @@ void sqlite3Update(
   ** be used eliminates some redundant opcodes.
   */
   newmask = sqlite3TriggerColmask(
-      pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
+      pParse, iDb, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
   );
   for(i=0; i<pTab->nCol; i++){
     if( i==pTab->iPKey ){
@@ -672,7 +672,7 @@ void sqlite3Update(
   */
   if( tmask&TRIGGER_BEFORE ){
     sqlite3TableAffinity(v, pTab, regNew);
-    sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
+    sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_UPDATE, pChanges, 
         TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue);
 
     /* The row-trigger may have deleted the row being updated. In this
@@ -776,7 +776,7 @@ void sqlite3Update(
     ** handle rows (possibly in other tables) that refer via a foreign key
     ** to the row just updated. */ 
     if( hasFK ){
-      sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey);
+      sqlite3FkActions(pParse, iDb, pTab, pChanges, regOldRowid, aXRef,chngKey);
     }
   }
 
@@ -786,7 +786,7 @@ void sqlite3Update(
     sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
   }
 
-  sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
+  sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_UPDATE, pChanges, 
       TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue);
 
   /* Repeat the above with the next record to be updated, until
index 14f3e1bd3cc3cc282938493b7eb2835eacdf5c83..df5f6c0cebeb243218971ef3fc66e8ba706e9155 100644 (file)
@@ -6038,6 +6038,7 @@ case OP_Program: {        /* jump */
   VdbeFrame *pFrame;      /* New vdbe frame to execute in */
   SubProgram *pProgram;   /* Sub-program to execute */
   void *t;                /* Token identifying trigger */
+  int i;                  /* Second part of token identifying trigger */
 
   pProgram = pOp->p4.pProgram;
   pRt = &aMem[pOp->p3];
@@ -6056,7 +6057,10 @@ case OP_Program: {        /* jump */
   ** variable.  */
   if( pOp->p5 ){
     t = pProgram->token;
-    for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent);
+    i = pProgram->itoken;
+    for(pFrame=p->pFrame; 
+        pFrame && (pFrame->token!=t || pFrame->itoken!=i); 
+        pFrame=pFrame->pParent);
     if( pFrame ) break;
   }
 
@@ -6104,6 +6108,7 @@ case OP_Program: {        /* jump */
     pFrame->aOp = p->aOp;
     pFrame->nOp = p->nOp;
     pFrame->token = pProgram->token;
+    pFrame->itoken = pProgram->itoken;
 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
     pFrame->anExec = p->anExec;
 #endif
index b6b3204790ba97df326c388270796a812570b062..4b686f01f18057116efef4776bd7b188d8b19433 100644 (file)
@@ -90,6 +90,7 @@ struct SubProgram {
   int nCsr;                     /* Number of cursors required */
   u8 *aOnce;                    /* Array of OP_Once flags */
   void *token;                  /* id that may be used to recursive triggers */
+  int itoken;                   /* Second part of id to identify rec. trig. */
   SubProgram *pNext;            /* Next sub-program already visited */
 };
 
index 1cb7219611010f992f1313330ea593d894aa7ea8..bdb5e4084fc182ea76d11bf489c5a29d67805a27 100644 (file)
@@ -167,6 +167,7 @@ struct VdbeFrame {
   VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
   u8 *aOnce;              /* Bitmask used by OP_Once */
   void *token;            /* Copy of SubProgram.token */
+  int itoken;             /* Copy of SubProgram.itoken */
   i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
   AuxData *pAuxData;      /* Linked list of auxdata allocations */
 #if SQLITE_DEBUG
index f4d4138c8fa7305aa2c7bd4fa4f865acb78fa82a..d2d581901b4050ca20abdbcbaf82eda5608c1d45 100644 (file)
@@ -4942,7 +4942,7 @@ WhereInfo *sqlite3WhereBegin(
 
     pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
-    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+    iDb = sqlite3SchemaToIndex2(db, pTab->pSchema, pTabItem->zDatabase);
     pLoop = pLevel->pWLoop;
     if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
       /* Do nothing */
index b21779b9947cbb4d3a6232a564b6ddbea77ffa88..50f609d7b872e29ffedb949c4adb145718918912 100644 (file)
@@ -91,4 +91,112 @@ foreach {tn sql} {
   do_catchsql_test 1.5.$tn $sql {1 {attempt to modify read-only schema}}
 }
 
+#-------------------------------------------------------------------------
+#
+reset_db
+forcedelete test.db2
+ifcapable fts5 {
+  do_execsql_test 2.0 {
+    CREATE VIRTUAL TABLE ft USING fts5(a);
+    INSERT INTO ft VALUES('one'), ('two'), ('three');
+    ATTACH 'test.db2' AS aux;
+    CREATE VIRTUAL TABLE aux.ft USING fts5(a);
+    INSERT INTO aux.ft VALUES('aux1'), ('aux2'), ('aux3');
+  }
+
+  db close
+  sqlite3 db  test.db -reuse-schema 1
+
+  do_execsql_test 2.1 {
+    ATTACH 'test.db2' AS aux;
+    SELECT * FROM main.ft;
+  } {one two three}
+
+  do_execsql_test 2.2 {
+    SELECT * FROM aux.ft;
+  } {aux1 aux2 aux3}
+
+  do_execsql_test 2.2 {
+    SELECT * FROM aux.ft_content;
+  } {1 aux1 2 aux2 3 aux3}
+}
+
+reset_db
+forcedelete test.db2
+do_execsql_test 3.0 {
+  CREATE TABLE t1(a PRIMARY KEY, b, c);
+  CREATE VIEW v1 AS SELECT * FROM t1;
+  CREATE TRIGGER v1_ins INSTEAD OF INSERT ON v1 BEGIN
+    INSERT INTO t1 VALUES(new.a, new.b, new.c);
+  END;
+  CREATE TRIGGER v1_del INSTEAD OF DELETE ON v1 BEGIN
+    DELETE FROM t1 WHERE a=old.a;
+  END;
+  CREATE TRIGGER v1_up INSTEAD OF UPDATE ON v1 BEGIN
+    UPDATE t1 SET a=new.a, b=new.b, c=new.c WHERE a=old.a;
+  END;
+}
+forcecopy test.db test.db2
+
+do_test 3.1 {
+  sqlite3 db2 test.db2
+  execsql { INSERT INTO t1 VALUES(1, 2, 3) } db
+  execsql { INSERT INTO t1 VALUES(4, 5, 6) } db2
+  db2 close
+  execsql { ATTACH 'test.db2' AS aux; }
+} {}
+
+do_execsql_test 3.2 {
+  SELECT * FROM main.v1;
+} {1 2 3}
+
+do_execsql_test 3.3 {
+  SELECT * FROM aux.v1;
+} {4 5 6}
+
+db close
+sqlite3 db test.db -reuse-schema 1
+
+do_execsql_test 3.4 { ATTACH 'test.db2' AS aux } {}
+do_execsql_test 3.5 { SELECT * FROM main.v1 } {1 2 3}
+do_execsql_test 3.6 { SELECT * FROM aux.v1  } {4 5 6}
+
+do_execsql_test 3.7.1 { INSERT INTO aux.t1 VALUES(8, 9, 10); }
+do_execsql_test 3.7.2 { SELECT * FROM main.v1 } {1 2 3}
+do_execsql_test 3.7.3 { SELECT * FROM aux.v1  } {4 5 6 8 9 10}
+
+do_execsql_test 3.8.1 { DELETE FROM aux.t1 WHERE b=5 }
+do_execsql_test 3.8.2 { SELECT * FROM main.v1 } {1 2 3}
+do_execsql_test 3.8.3 { SELECT * FROM aux.v1  } {8 9 10}
+
+do_execsql_test 3.9.1 { UPDATE aux.t1 SET b='abc' }
+do_execsql_test 3.9.2 { SELECT * FROM main.v1 } {1 2 3}
+do_execsql_test 3.9.3 { SELECT * FROM aux.v1  } {8 abc 10}
+
+do_execsql_test 3.10.1 { INSERT INTO aux.v1 VALUES(11, 12, 13) }
+do_execsql_test 3.10.2 { SELECT * FROM main.v1 } {1 2 3}
+do_execsql_test 3.10.3 { SELECT * FROM aux.v1  } {8 abc 10 11 12 13}
+
+do_execsql_test 3.11.1 { DELETE FROM aux.v1 WHERE b='abc' }
+do_execsql_test 3.11.2 { SELECT * FROM main.v1 } {1 2 3}
+do_execsql_test 3.11.3 { SELECT * FROM aux.v1  } {11 12 13}
+
+do_execsql_test 3.12.1 { UPDATE aux.v1 SET b='def' }
+do_execsql_test 3.12.2 { SELECT * FROM main.v1 } {1 2 3}
+do_execsql_test 3.12.3 { SELECT * FROM aux.v1  } {11 def 13}
+
+do_execsql_test 3.13.1 {
+  CREATE TEMP TRIGGER xyz AFTER INSERT ON aux.t1 BEGIN
+    INSERT INTO v1 VALUES(new.a, new.b, new.c);
+  END;
+}
+do_execsql_test 3.13.2 {
+  INSERT INTO aux.v1 VALUES('x', 'y', 'z');
+}
+do_execsql_test 3.13.3 {
+  SELECT * FROM v1;
+} {1 2 3 x y z}
+
+
 finish_test
+