]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Backport the [/timeline?r=shared-cache-fix | shared-cache-fix] branch.
authordrh <drh@noemail.net>
Fri, 26 Oct 2012 13:34:05 +0000 (13:34 +0000)
committerdrh <drh@noemail.net>
Fri, 26 Oct 2012 13:34:05 +0000 (13:34 +0000)
FossilOrigin-Name: 325364a984e9a5c0825810bf50f57e026ff3b8dd

13 files changed:
manifest
manifest.uuid
src/alter.c
src/attach.c
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/select.c
src/sqliteInt.h
src/vtab.c
test/shared9.test [new file with mode: 0644]
test/trigger1.test

index e3e9227f54fea91cac799cae5cfa2849fa1ca96c..772b7d45e307bea266a5ff001a852aa228495689 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sQNX-specific\sperformance\stweaks\sto\sthe\sunix\sVFS.\s(Cherry-pick\smerge\sof\n[b02849e7bde458].)\nPut\sauxiliary\slibraries\safter\slibsqlite3.a\sin\sthe\stestfixture\starget\sof\nthe\s"main.mk"\smakefile.\s\s(Cherry-pick\smerge\sof\s[8fc8548f52ab8fcfb5].)
-D 2012-10-26T13:25:32.533
+C Backport\sthe\s[/timeline?r=shared-cache-fix\s|\sshared-cache-fix]\sbranch.
+D 2012-10-26T13:34:05.437
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in abd5c10d21d1395f140d9e50ea999df8fa4d6376
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -116,9 +116,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
 F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
 F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
-F src/alter.c 149cc80d9257971b0bff34e58fb2263e01998289
+F src/alter.c c3d9d0d6735064c4ba83a67dbf0d42f9bf5a1d6f
 F src/analyze.c 7553068d21e32a57fc33ab6b2393fc8c1ba41410
-F src/attach.c 577bf5675b0c50495fc28549f2fcbdb1bac71143
+F src/attach.c 34c15ecd686e58f08e5bb1389e28a0b65c2c83db
 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
 F src/backup.c 5b31b24d6814b11de763debf342c8cd0a15a4910
 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1
@@ -126,13 +126,13 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
 F src/btree.c 97edf88abd2b66f31886ba977d2b3b2a21d81d4c
 F src/btree.h 4aee02e879211bfcfd3f551769578d2e940ab6c2
 F src/btreeInt.h 4e5c2bd0f9b36b2a815a6d84f771a61a65830621
-F src/build.c a3b700afd475e6387da59be6f2e86161e80d6d87
+F src/build.c 0aef4fa83fbf334d0929f5e5ad1bb4beecfd00fb
 F src/callback.c 0cb4228cdcd827dcc5def98fb099edcc9142dbcd
 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c 500d019da966631ad957c37705642be87524463b
 F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
-F src/delete.c 335f36750dc6ac88d580aa36a6487459be9889de
-F src/expr.c 217840a107dcc1e5dbb57cea311daad04bedbb9a
+F src/delete.c c374ab8dd20ef475d9a4d26ef3799e71db7379a9
+F src/expr.c 763fce595793e1f47fe9c80fceed2354eb089d13
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c 9c77d842dc9961d92a06a65abb80c64ef1750296
 F src/func.c 18dfedfb857e100b05755a1b12e88b389f957879
@@ -140,7 +140,7 @@ F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b
 F src/hash.c a4031441741932da9e7a65bee2b36b5d0e81c073
 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c b090d0a9fb9ff2dbdeaf66aedccf98cd13b1af60
+F src/insert.c ece0dfd2e1cee4cc35e343c79a52eab9f52cef48
 F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
 F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
 F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
@@ -176,12 +176,12 @@ F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
 F src/resolve.c 9e28280ec98035f31900fdd1db01f86f68ca6c32
 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
-F src/select.c f843c872a97baa1594c2cc3d4c003409a7bd03af
+F src/select.c b2c911d0bfad8a22732f9de08cbcc2148f7d8d6d
 F src/shell.c 87953c5d9c73d9494db97d1607e2e2280418f261
 F src/sqlite.h.in c447d35212736c4c77d86bc2d00f6cf4d4c12131
 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
-F src/sqliteInt.h 053e03a532beb909ead2df0721db67cdb4c48ae8
+F src/sqliteInt.h 462f9552011af3648628cfcdef1be7df823cdb52
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -247,7 +247,7 @@ F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
 F src/vdbemem.c cb55e84b8e2c15704968ee05f0fae25883299b74
 F src/vdbesort.c 0dc1b274dcb4d4c8e71b0b2b15261f286caba39b
 F src/vdbetrace.c 8bd5da325fc90f28464335e4cc4ad1407fe30835
-F src/vtab.c d2c54fd22aa83eb34fc6f7cd9b097f2fc2b1e9de
+F src/vtab.c bf61d2b47fbe544cf128f176d950a95ab9fa7990
 F src/wal.c 5acb3e7bbd31f10ba39acad9ce6b399055337a9d
 F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
 F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b
@@ -699,6 +699,7 @@ F test/shared4.test 72d90821e8d2fc918a08f16d32880868d8ee8e9d
 F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
 F test/shared7.test 960760bc8d03e1419e70dea69cf41db62853616e
 F test/shared8.test b27befbefbe7f4517f1d6b7ff8f64a41ec74165d
+F test/shared9.test 3a5b09583e3ba3139a4bd66958061306b4331c7e
 F test/shared_err.test 91e26ec4f3fbe07951967955585137e2f18993de
 F test/sharedlock.test ffa0a3c4ac192145b310f1254f8afca4d553eabf
 F test/shell1.test 9895ee3013742a02e5afd8d77793729967ffd195
@@ -881,7 +882,7 @@ F test/trace2.test c1dc104a8d11a347c870cfea6235e3fc6f6cb06d
 F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
 F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22
 F test/trans3.test 373ac5183cc56be69f48ae44090e7f672939f732
-F test/trigger1.test de42feb7cd442787d38185ae74f5a1d7afa400cb
+F test/trigger1.test 70acedb76532117bbcc873f8601cdc6905f1f455
 F test/trigger2.test 834187beafd1db383af0c659cfa49b0576832816
 F test/trigger3.test d2c60d8be271c355d61727411e753181e877230a
 F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
@@ -1014,7 +1015,7 @@ F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix bc91332e37e980c20575e087b368922f93673f1b
-P 521024d4a799f36618e8adb1d032d76806db28bc
-R 8488838a2bba50b76a7185282c39e09d
+P cbfd1b120ada30ee98403af8d95cfbd590353365
+R cec8d9ad420249b78e42ff233036b95b
 U drh
-Z 0b8c2e8e933f44d93bc453110c788c68
+Z f05ff88a3dfee3e1a7e5cb1a864f2163
index 80578f6042194cfc5b25901feea6277cc0ce3a08..b5826c41ad31a4736578cd2a5b5335dc7350b983 100644 (file)
@@ -1 +1 @@
-cbfd1b120ada30ee98403af8d95cfbd590353365
\ No newline at end of file
+325364a984e9a5c0825810bf50f57e026ff3b8dd
\ No newline at end of file
index 7f56ce7e0bcf9bf05121c9bf214d37ee767e3b7f..a1cef7b82e67de19f587d6b28d93962f848973c5 100644 (file)
@@ -414,7 +414,7 @@ void sqlite3AlterRenameTable(
   assert( pSrc->nSrc==1 );
   assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
 
-  pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
   if( !pTab ) goto exit_rename_table;
   iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
   zDb = db->aDb[iDb].zName;
@@ -757,7 +757,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
   assert( pParse->pNewTable==0 );
   assert( sqlite3BtreeHoldsAllMutexes(db) );
   if( db->mallocFailed ) goto exit_begin_add_column;
-  pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
   if( !pTab ) goto exit_begin_add_column;
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
index e295c30111bb7d438d23af183aeec068cfddc6c5..3e045aa366e8d40c8cd7905788966974f0f6f34c 100644 (file)
@@ -434,6 +434,7 @@ int sqlite3FixInit(
   assert( db->nDb>iDb );
   pFix->pParse = pParse;
   pFix->zDb = db->aDb[iDb].zName;
+  pFix->pSchema = db->aDb[iDb].pSchema;
   pFix->zType = zType;
   pFix->pName = pName;
   return 1;
@@ -464,14 +465,15 @@ int sqlite3FixSrcList(
   if( NEVER(pList==0) ) return 0;
   zDb = pFix->zDb;
   for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
-    if( pItem->zDatabase==0 ){
-      pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb);
-    }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
+    if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
       sqlite3ErrorMsg(pFix->pParse,
          "%s %T cannot reference objects in database %s",
          pFix->zType, pFix->pName, pItem->zDatabase);
       return 1;
     }
+    sqlite3_free(pItem->zDatabase);
+    pItem->zDatabase = 0;
+    pItem->pSchema = pFix->pSchema;
 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
     if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
     if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
index 25e474031fb6218237a908687807e579549e9ce7..d07542fe67602c03cde57d26ef02bcdaf398942e 100644 (file)
@@ -319,6 +319,31 @@ Table *sqlite3LocateTable(
   return p;
 }
 
+/*
+** Locate the table identified by *p.
+**
+** This is a wrapper around sqlite3LocateTable(). The difference between
+** sqlite3LocateTable() and this function is that this function restricts
+** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
+** non-NULL if it is part of a view or trigger program definition. See
+** sqlite3FixSrcList() for details.
+*/
+Table *sqlite3LocateTableItem(
+  Parse *pParse, 
+  int isView, 
+  struct SrcList_item *p
+){
+  const char *zDb;
+  assert( p->pSchema==0 || p->zDatabase==0 );
+  if( p->pSchema ){
+    int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+    zDb = pParse->db->aDb[iDb].zName;
+  }else{
+    zDb = p->zDatabase;
+  }
+  return sqlite3LocateTable(pParse, isView, p->zName, zDb);
+}
+
 /*
 ** Locate the in-memory structure that describes 
 ** a particular index given the name of that index
@@ -2114,8 +2139,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
   assert( pParse->nErr==0 );
   assert( pName->nSrc==1 );
   if( noErr ) db->suppressErr++;
-  pTab = sqlite3LocateTable(pParse, isView, 
-                            pName->a[0].zName, pName->a[0].zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
   if( noErr ) db->suppressErr--;
 
   if( pTab==0 ){
@@ -2555,8 +2579,7 @@ Index *sqlite3CreateIndex(
       ** sqlite3FixSrcList can never fail. */
       assert(0);
     }
-    pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName, 
-        pTblName->a[0].zDatabase);
+    pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
     if( !pTab || db->mallocFailed ) goto exit_create_index;
     assert( db->aDb[iDb].pSchema==pTab->pSchema );
   }else{
index 44e5995a6975eeb6140a2f214d1c38d0c5af97fd..3772198b54b55d72791b8a1e70a7bf89b1f579b8 100644 (file)
@@ -32,7 +32,7 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
   struct SrcList_item *pItem = pSrc->a;
   Table *pTab;
   assert( pItem && pSrc->nSrc==1 );
-  pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
+  pTab = sqlite3LocateTableItem(pParse, 0, pItem);
   sqlite3DeleteTable(pParse->db, pItem->pTab);
   pItem->pTab = pTab;
   if( pTab ){
index 89172f94bf570f8e28df3cf439c9acb841e1310a..47f79bd2af2a4e1ad17544dbbf5f2d78b7d30827 100644 (file)
@@ -930,6 +930,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
     struct SrcList_item *pNewItem = &pNew->a[i];
     struct SrcList_item *pOldItem = &p->a[i];
     Table *pTab;
+    pNewItem->pSchema = pOldItem->pSchema;
     pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
     pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
     pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
index a24e8f9481aa2e7630d05e4c06a118ab287aaf2f..d0ea159616b2cd6e9a836274159539c0b89254d9 100644 (file)
@@ -1222,7 +1222,9 @@ void sqlite3GenerateConstraintChecks(
     onError = overrideError!=OE_Default ? overrideError : OE_Abort;
     for(i=0; i<pCheck->nExpr; i++){
       int allOk = sqlite3VdbeMakeLabel(v);
-      sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL);
+      Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0);
+      if( pDup==0 ) break;
+      sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL);
       if( onError==OE_Ignore ){
         sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
       }else{
@@ -1236,6 +1238,7 @@ void sqlite3GenerateConstraintChecks(
         sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
       }
       sqlite3VdbeResolveLabel(v, allOk);
+      sqlite3ExprDelete(db, pDup);
     }
   }
 #endif /* !defined(SQLITE_OMIT_CHECK) */
@@ -1691,7 +1694,7 @@ static int xferOptimization(
   ** we have to check the semantics.
   */
   pItem = pSelect->pSrc->a;
-  pSrc = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
+  pSrc = sqlite3LocateTableItem(pParse, 0, pItem);
   if( pSrc==0 ){
     return 0;   /* FROM clause does not contain a real table */
   }
index 6ec9da39a19c42c9dcb2be7e2a3a1bb6b0176797..1badde362bc9c080d0daee5410205229255b295a 100644 (file)
@@ -3268,8 +3268,7 @@ static int selectExpander(Walker *pWalker, Select *p){
     }else{
       /* An ordinary table or view name in the FROM clause */
       assert( pFrom->pTab==0 );
-      pFrom->pTab = pTab = 
-        sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
+      pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
       if( pTab==0 ) return WRC_Abort;
       pTab->nRef++;
 #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
index 09163bf69c9399648ce62ecce064ca0e7f85519f..599c4cb7bb20c047ac918e66e5dd407bed346b25 100644 (file)
@@ -1855,6 +1855,7 @@ struct SrcList {
   i16 nSrc;        /* Number of tables or subqueries in the FROM clause */
   i16 nAlloc;      /* Number of entries allocated in a[] below */
   struct SrcList_item {
+    Schema *pSchema;  /* Schema to which this item is fixed */
     char *zDatabase;  /* Name of database holding this table */
     char *zName;      /* Name of the table */
     char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
@@ -2420,6 +2421,7 @@ struct TriggerStep {
 typedef struct DbFixer DbFixer;
 struct DbFixer {
   Parse *pParse;      /* The parsing context.  Error messages written here */
+  Schema *pSchema;    /* Fix items to this schema */
   const char *zDb;    /* Make sure all objects are contained in this database */
   const char *zType;  /* Type of the container - used for error messages */
   const Token *pName; /* Name of the container - used for error messages */
@@ -2830,6 +2832,7 @@ void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
 void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
 Table *sqlite3FindTable(sqlite3*,const char*, const char*);
 Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
+Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
 Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
 void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
 void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
index 50d576fc3894863bbb15794683b1006cd596e488..6219f8b0ba7f4df2d510de995c3dd85d3277714f 100644 (file)
@@ -263,6 +263,7 @@ void sqlite3VtabClear(sqlite3 *db, Table *p){
   if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
   if( p->azModuleArg ){
     int i;
+    assert( p->nModuleArg<2 || p->azModuleArg[1]==0 );
     for(i=0; i<p->nModuleArg; i++){
       sqlite3DbFree(db, p->azModuleArg[i]);
     }
@@ -324,7 +325,7 @@ void sqlite3VtabBeginParse(
   pTable->tabFlags |= TF_Virtual;
   pTable->nModuleArg = 0;
   addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
-  addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
+  addModuleArgument(db, pTable, 0);
   addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
   pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z);
 
@@ -481,6 +482,7 @@ static int vtabCallConstructor(
   int nArg = pTab->nModuleArg;
   char *zErr = 0;
   char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
+  int iDb;
 
   if( !zModuleName ){
     return SQLITE_NOMEM;
@@ -494,6 +496,10 @@ static int vtabCallConstructor(
   pVTable->db = db;
   pVTable->pMod = pMod;
 
+  assert( pTab->azModuleArg[1]==0 );
+  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+  pTab->azModuleArg[1] = db->aDb[iDb].zName;
+
   /* Invoke the virtual table constructor */
   assert( &db->pVtabCtx );
   assert( xConstruct );
@@ -504,6 +510,7 @@ static int vtabCallConstructor(
   rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
   db->pVtabCtx = pPriorCtx;
   if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
+  pTab->azModuleArg[1] = 0;
 
   if( SQLITE_OK!=rc ){
     if( zErr==0 ){
diff --git a/test/shared9.test b/test/shared9.test
new file mode 100644 (file)
index 0000000..bb0dfee
--- /dev/null
@@ -0,0 +1,140 @@
+# 2012 October 5
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# The tests in this file are intended to show if two connections attach
+# to the same shared cache using different database names, views and
+# virtual tables may still be accessed.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix shared9
+
+ifcapable !view||!trigger {
+  finish_test
+  return
+}
+
+db close
+set enable_shared_cache [sqlite3_enable_shared_cache 1]
+
+sqlite3 db1 test.db
+sqlite3 db2 test.db
+forcedelete test.db2
+
+do_test 1.1 {
+  db1 eval {
+    ATTACH 'test.db2' AS 'fred';
+    CREATE TABLE fred.t1(a, b, c);
+    CREATE VIEW fred.v1 AS SELECT * FROM t1;
+
+    CREATE TABLE fred.t2(a, b);
+    CREATE TABLE fred.t3(a, b);
+    CREATE TRIGGER fred.trig AFTER INSERT ON t2 BEGIN
+      DELETE FROM t3;
+      INSERT INTO t3 SELECT * FROM t2;
+    END;
+    INSERT INTO t2 VALUES(1, 2);
+    SELECT * FROM t3;
+  }
+} {1 2}
+
+do_test 1.2 { db2 eval "ATTACH 'test.db2' AS 'jones'" } {}
+do_test 1.3 { db2 eval "SELECT * FROM v1"             } {}
+do_test 1.4 { db2 eval "INSERT INTO t2 VALUES(3, 4)"  } {}
+
+ifcapable fts3 {
+  do_test 1.5 {
+    db1 eval {
+      CREATE VIRTUAL TABLE fred.t4 USING fts4;
+      INSERT INTO t4 VALUES('hello world');
+    }
+  } {}
+
+  do_test 1.6 {
+    db2 eval {
+      INSERT INTO t4 VALUES('shared cache');
+      SELECT * FROM t4 WHERE t4 MATCH 'hello';
+    }
+  } {{hello world}}
+
+  do_test 1.7 {
+    db1 eval {
+      SELECT * FROM t4 WHERE t4 MATCH 'c*';
+    }
+  } {{shared cache}}
+}
+
+db1 close
+db2 close
+
+#-------------------------------------------------------------------------
+# The following tests attempt to find a similar problem with collation 
+# sequence names - pointers to database handle specific allocations leaking 
+# into schema objects and being used after the original handle has been
+# closed.
+#
+forcedelete test.db test.db2
+sqlite3 db1 test.db
+sqlite3 db2 test.db
+foreach x {collate1 collate2 collate3} {
+  proc $x {a b} { string compare $a $b }
+  db1 collate $x $x
+  db2 collate $x $x
+}
+do_test 2.1 {
+  db1 eval {
+    CREATE TABLE t1(a, b, c COLLATE collate1);
+    CREATE INDEX i1 ON t1(a COLLATE collate2, c, b);
+  }
+} {}
+do_test 2.2 {
+  db1 close
+  db2 eval "INSERT INTO t1 VALUES('abc', 'def', 'ghi')"
+} {}
+db2 close
+
+#-------------------------------------------------------------------------
+# At one point, the following would cause a collation sequence belonging
+# to connection [db1] to be invoked by a call to [db2 eval]. Which is a
+# problem if [db1] has already been closed.
+#
+forcedelete test.db test.db2
+sqlite3 db1 test.db
+sqlite3 db2 test.db
+
+proc mycollate_db1 {a b} {set ::invoked_mycollate_db1 1 ; string compare $a $b}
+proc mycollate_db2 {a b} {string compare $a $b}
+
+db1 collate mycollate mycollate_db1
+db2 collate mycollate mycollate_db2
+
+do_test 2.3 {
+  set ::invoked_mycollate_db1 0
+  db1 eval {
+    CREATE TABLE t1(a COLLATE mycollate, CHECK (a IN ('one', 'two', 'three')));
+    INSERT INTO t1 VALUES('one');
+  }
+  db1 close
+  set ::invoked_mycollate_db1
+} {1}
+do_test 2.4 {
+  set ::invoked_mycollate_db1 0
+  db2 eval {
+    INSERT INTO t1 VALUES('two');
+  }
+  db2 close
+  set ::invoked_mycollate_db1
+} {0}
+
+sqlite3_enable_shared_cache $::enable_shared_cache
+finish_test
+
index 9d917bdb3897f1b1d327eafacfc407d60f9ff73d..38806db3b5fc0974619458619d3ff957d4d3ff26 100644 (file)
@@ -210,7 +210,7 @@ do_test trigger1-1.12 {
       delete from t1 WHERE a=old.a+2;
     end;
   }
-} {1 {cannot create INSTEAD OF trigger on table: main.t1}}
+} {1 {cannot create INSTEAD OF trigger on table: t1}}
 
 ifcapable view {
 # Ensure that we cannot create BEFORE triggers on views
@@ -221,7 +221,7 @@ do_test trigger1-1.13 {
       delete from t1 WHERE a=old.a+2;
     end;
   }
-} {1 {cannot create BEFORE trigger on view: main.v1}}
+} {1 {cannot create BEFORE trigger on view: v1}}
 # Ensure that we cannot create AFTER triggers on views
 do_test trigger1-1.14 {
   catchsql {
@@ -231,7 +231,7 @@ do_test trigger1-1.14 {
       delete from t1 WHERE a=old.a+2;
     end;
   }
-} {1 {cannot create AFTER trigger on view: main.v1}}
+} {1 {cannot create AFTER trigger on view: v1}}
 } ;# ifcapable view
 
 # Check for memory leaks in the trigger parser