/ Check-in [e72179f3]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge into trunk the changes that permit :memory: databases to use shared cache.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:e72179f3a43e4df36b7c2955eaacce6c804272c6
User & Date: drh 2012-05-27 22:42:57
Context
2012-05-28
12:22
Omit the fts3 unicode character class routines from the build if fts3/4 is disabled. check-in: c00bb5d4 user: drh tags: trunk
2012-05-27
22:42
Merge into trunk the changes that permit :memory: databases to use shared cache. check-in: e72179f3 user: drh tags: trunk
01:19
Have user interfaces report out the filename of in-memory databases as an empty string, as it always has. This simplifies the changes. Closed-Leaf check-in: 595dfdbf user: drh tags: shared-cache-memdb
2012-05-26
18:42
Merge fts4-unicode branch with trunk. check-in: 25ba1f84 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  1753   1753   #endif
  1754   1754   
  1755   1755   #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
  1756   1756     /*
  1757   1757     ** If this Btree is a candidate for shared cache, try to find an
  1758   1758     ** existing BtShared object that we can share with
  1759   1759     */
  1760         -  if( isMemdb==0 && isTempDb==0 ){
         1760  +  if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
  1761   1761       if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
  1762   1762         int nFullPathname = pVfs->mxPathname+1;
  1763   1763         char *zFullPathname = sqlite3Malloc(nFullPathname);
  1764   1764         MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
  1765   1765         p->sharable = 1;
  1766   1766         if( !zFullPathname ){
  1767   1767           sqlite3_free(p);
  1768   1768           return SQLITE_NOMEM;
  1769   1769         }
  1770         -      rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
  1771         -      if( rc ){
  1772         -        sqlite3_free(zFullPathname);
  1773         -        sqlite3_free(p);
  1774         -        return rc;
         1770  +      if( isMemdb ){
         1771  +        memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1);
         1772  +      }else{
         1773  +        rc = sqlite3OsFullPathname(pVfs, zFilename,
         1774  +                                   nFullPathname, zFullPathname);
         1775  +        if( rc ){
         1776  +          sqlite3_free(zFullPathname);
         1777  +          sqlite3_free(p);
         1778  +          return rc;
         1779  +        }
  1775   1780         }
  1776   1781   #if SQLITE_THREADSAFE
  1777   1782         mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
  1778   1783         sqlite3_mutex_enter(mutexOpen);
  1779   1784         mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
  1780   1785         sqlite3_mutex_enter(mutexShared);
  1781   1786   #endif
  1782   1787         for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
  1783   1788           assert( pBt->nRef>0 );
  1784         -        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
         1789  +        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0))
  1785   1790                    && sqlite3PagerVfs(pBt->pPager)==pVfs ){
  1786   1791             int iDb;
  1787   1792             for(iDb=db->nDb-1; iDb>=0; iDb--){
  1788   1793               Btree *pExisting = db->aDb[iDb].pBt;
  1789   1794               if( pExisting && pExisting->pBt==pBt ){
  1790   1795                 sqlite3_mutex_leave(mutexShared);
  1791   1796                 sqlite3_mutex_leave(mutexOpen);
................................................................................
  8042   8047     *pnErr = sCheck.nErr;
  8043   8048     if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg);
  8044   8049     return sqlite3StrAccumFinish(&sCheck.errMsg);
  8045   8050   }
  8046   8051   #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
  8047   8052   
  8048   8053   /*
  8049         -** Return the full pathname of the underlying database file.
         8054  +** Return the full pathname of the underlying database file.  Return
         8055  +** an empty string if the database is in-memory or a TEMP database.
  8050   8056   **
  8051   8057   ** The pager filename is invariant as long as the pager is
  8052   8058   ** open so it is safe to access without the BtShared mutex.
  8053   8059   */
  8054   8060   const char *sqlite3BtreeGetFilename(Btree *p){
  8055   8061     assert( p->pBt->pPager!=0 );
  8056         -  return sqlite3PagerFilename(p->pBt->pPager);
         8062  +  return sqlite3PagerFilename(p->pBt->pPager, 1);
  8057   8063   }
  8058   8064   
  8059   8065   /*
  8060   8066   ** Return the pathname of the journal file for this database. The return
  8061   8067   ** value of this routine is the same regardless of whether the journal file
  8062   8068   ** has been created or not.
  8063   8069   **

Changes to src/main.c.

  2051   2051   
  2052   2052     }else{
  2053   2053       zFile = sqlite3_malloc(nUri+2);
  2054   2054       if( !zFile ) return SQLITE_NOMEM;
  2055   2055       memcpy(zFile, zUri, nUri);
  2056   2056       zFile[nUri] = '\0';
  2057   2057       zFile[nUri+1] = '\0';
         2058  +    flags &= ~SQLITE_OPEN_URI;
  2058   2059     }
  2059   2060   
  2060   2061     *ppVfs = sqlite3_vfs_find(zVfs);
  2061   2062     if( *ppVfs==0 ){
  2062   2063       *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
  2063   2064       rc = SQLITE_ERROR;
  2064   2065     }

Changes to src/pager.c.

  4356   4356   
  4357   4357     /* Set the output variable to NULL in case an error occurs. */
  4358   4358     *ppPager = 0;
  4359   4359   
  4360   4360   #ifndef SQLITE_OMIT_MEMORYDB
  4361   4361     if( flags & PAGER_MEMORY ){
  4362   4362       memDb = 1;
  4363         -    zFilename = 0;
         4363  +    if( zFilename && zFilename[0] ){
         4364  +      zPathname = sqlite3DbStrDup(0, zFilename);
         4365  +      if( zPathname==0  ) return SQLITE_NOMEM;
         4366  +      nPathname = sqlite3Strlen30(zPathname);
         4367  +      zFilename = 0;
         4368  +    }
  4364   4369     }
  4365   4370   #endif
  4366   4371   
  4367   4372     /* Compute and store the full pathname in an allocated buffer pointed
  4368   4373     ** to by zPathname, length nPathname. Or, if this is a temporary file,
  4369   4374     ** leave both nPathname and zPathname set to 0.
  4370   4375     */
................................................................................
  6292   6297     }
  6293   6298   
  6294   6299     return rc;
  6295   6300   }
  6296   6301   
  6297   6302   /*
  6298   6303   ** Return the full pathname of the database file.
         6304  +**
         6305  +** Except, if the pager is in-memory only, then return an empty string if
         6306  +** nullIfMemDb is true.  This routine is called with nullIfMemDb==1 when
         6307  +** used to report the filename to the user, for compatibility with legacy
         6308  +** behavior.  But when the Btree needs to know the filename for matching to
         6309  +** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
         6310  +** participate in shared-cache.
  6299   6311   */
  6300         -const char *sqlite3PagerFilename(Pager *pPager){
  6301         -  return pPager->zFilename;
         6312  +const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
         6313  +  return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
  6302   6314   }
  6303   6315   
  6304   6316   /*
  6305   6317   ** Return the VFS structure for the pager.
  6306   6318   */
  6307   6319   const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
  6308   6320     return pPager->pVfs;

Changes to src/pager.h.

   147    147     int sqlite3PagerWalFramesize(Pager *pPager);
   148    148   #endif
   149    149   
   150    150   /* Functions used to query pager state and configuration. */
   151    151   u8 sqlite3PagerIsreadonly(Pager*);
   152    152   int sqlite3PagerRefcount(Pager*);
   153    153   int sqlite3PagerMemUsed(Pager*);
   154         -const char *sqlite3PagerFilename(Pager*);
          154  +const char *sqlite3PagerFilename(Pager*, int);
   155    155   const sqlite3_vfs *sqlite3PagerVfs(Pager*);
   156    156   sqlite3_file *sqlite3PagerFile(Pager*);
   157    157   const char *sqlite3PagerJournalname(Pager*);
   158    158   int sqlite3PagerNosync(Pager*);
   159    159   void *sqlite3PagerTempSpace(Pager*);
   160    160   int sqlite3PagerIsMemdb(Pager*);
   161    161   void sqlite3PagerCacheStat(Pager *, int, int, int *);

Changes to src/test_btree.c.

    29     29     Tcl_Obj *CONST objv[]
    30     30   ){
    31     31   #ifndef SQLITE_OMIT_SHARED_CACHE
    32     32     extern BtShared *sqlite3SharedCacheList;
    33     33     BtShared *pBt;
    34     34     Tcl_Obj *pRet = Tcl_NewObj();
    35     35     for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
    36         -    const char *zFile = sqlite3PagerFilename(pBt->pPager);
           36  +    const char *zFile = sqlite3PagerFilename(pBt->pPager, 1);
    37     37       Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1));
    38     38       Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef));
    39     39     }
    40     40     Tcl_SetObjResult(interp, pRet);
    41     41   #endif
    42     42     return TCL_OK;
    43     43   }

Changes to src/vdbe.c.

  5507   5507     pBt = db->aDb[pOp->p1].pBt;
  5508   5508     pPager = sqlite3BtreePager(pBt);
  5509   5509     eOld = sqlite3PagerGetJournalMode(pPager);
  5510   5510     if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
  5511   5511     if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
  5512   5512   
  5513   5513   #ifndef SQLITE_OMIT_WAL
  5514         -  zFilename = sqlite3PagerFilename(pPager);
         5514  +  zFilename = sqlite3PagerFilename(pPager, 1);
  5515   5515   
  5516   5516     /* Do not allow a transition to journal_mode=WAL for a database
  5517   5517     ** in temporary storage or if the VFS does not support shared memory 
  5518   5518     */
  5519   5519     if( eNew==PAGER_JOURNALMODE_WAL
  5520   5520      && (sqlite3Strlen30(zFilename)==0           /* Temp file */
  5521   5521          || !sqlite3PagerWalSupported(pPager))   /* No shared-memory support */

Changes to test/shared.test.

  1052   1052   } {1 2 6 8 9 12 1 2 5 11 12 14 1 2 4}
  1053   1053   do_test shared-$av-15.2 {
  1054   1054     execsql { DROP TABLE t1 } db2
  1055   1055   } {}
  1056   1056   db close
  1057   1057   db2 close
  1058   1058   
  1059         -}
         1059  +# Shared cache on a :memory: database.  This only works for URI filenames.
         1060  +#
         1061  +do_test shared-$av-16.1 {
         1062  +  sqlite3 db1 file::memory: -uri 1
         1063  +  sqlite3 db2 file::memory: -uri 1
         1064  +  db1 eval {
         1065  +    CREATE TABLE t1(x); INSERT INTO t1 VALUES(1),(2),(3);
         1066  +  }
         1067  +  db2 eval {
         1068  +    SELECT x FROM t1 ORDER BY x;
         1069  +  }
         1070  +} {1 2 3}
         1071  +do_test shared-$av-16.2 {
         1072  +  db2 eval {
         1073  +    INSERT INTO t1 VALUES(99);
         1074  +    DELETE FROM t1 WHERE x=2;
         1075  +  }
         1076  +  db1 eval {
         1077  +    SELECT x FROM t1 ORDER BY x;
         1078  +  }
         1079  +} {1 3 99}
         1080  +
         1081  +# Verify that there is no cache sharing ordinary (non-URI) filenames are
         1082  +# used.
         1083  +#
         1084  +do_test shared-$av-16.3 {
         1085  +  db1 close
         1086  +  db2 close
         1087  +  sqlite3 db1 :memory:
         1088  +  sqlite3 db2 :memory:
         1089  +  db1 eval {
         1090  +    CREATE TABLE t1(x); INSERT INTO t1 VALUES(4),(5),(6);
         1091  +  }
         1092  +  catchsql {
         1093  +    SELECT * FROM t1;
         1094  +  } db2
         1095  +} {1 {no such table: t1}}
         1096  +db1 close
         1097  +db2 close
         1098  +
         1099  +}  ;# end of autovacuum on/off loop
  1060   1100   
  1061   1101   sqlite3_enable_shared_cache $::enable_shared_cache
  1062   1102   finish_test