Fix bugs caused by assuming that shared-schemas are initialized. (CVS 2917)

FossilOrigin-Name: 3970eb875d1830d35b3a70a7583a8ab6b238cad6
diff --git a/src/attach.c b/src/attach.c
index eca7eb7..f1f1bbb 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the ATTACH and DETACH commands.
 **
-** $Id: attach.c,v 1.44 2006/01/10 07:14:23 danielk1977 Exp $
+** $Id: attach.c,v 1.45 2006/01/11 14:09:31 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -171,7 +171,6 @@
   ** we found it.
   */
   if( rc==SQLITE_OK ){
-    db->flags &= ~SQLITE_Initialized;
     sqlite3SafetyOn(db);
     rc = sqlite3Init(db, &zErrDyn);
     sqlite3SafetyOff(db);
diff --git a/src/btree.c b/src/btree.c
index daa4527..b1bd141 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.289 2006/01/10 13:58:48 drh Exp $
+** $Id: btree.c,v 1.290 2006/01/11 14:09:31 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
@@ -1579,6 +1579,7 @@
       return SQLITE_NOMEM;
     }
     for(pBt=pTsd->pBtree; pBt; pBt=pBt->pNext){
+      assert( pBt->nRef>0 );
       if( 0==strcmp(zFullPathname, sqlite3pager_filename(pBt->pPager)) ){
         p->pBt = pBt;
         *ppBtree = p;
@@ -6498,3 +6499,27 @@
 #endif
   return rc;
 }
+
+#if defined(SQLITE_TEST) && !defined(NO_TCL)
+#include <tcl.h>
+int sqlite3_shared_cache_report(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  ThreadData *pTd = sqlite3ThreadData();
+  if( pTd->useSharedData ){
+    BtShared *pBt;
+    Tcl_Obj *pRet = Tcl_NewObj();
+    for(pBt=pTd->pBtree; pBt; pBt=pBt->pNext){
+      const char *zFile = sqlite3pager_filename(pBt->pPager);
+      Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1));
+      Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef));
+    }
+    Tcl_SetObjResult(interp, pRet);
+  }
+  return TCL_OK;
+}
+#endif
+
diff --git a/src/build.c b/src/build.c
index e7c1742..65ce2e5 100644
--- a/src/build.c
+++ b/src/build.c
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.375 2006/01/10 17:58:23 danielk1977 Exp $
+** $Id: build.c,v 1.376 2006/01/11 14:09:32 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -255,7 +255,6 @@
   Table *p = 0;
   int i;
   assert( zName!=0 );
-  assert( (db->flags & SQLITE_Initialized) || db->init.busy );
   for(i=OMIT_TEMPDB; i<db->nDb; i++){
     int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
     if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
@@ -311,7 +310,6 @@
 Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
   Index *p = 0;
   int i;
-  assert( (db->flags & SQLITE_Initialized) || db->init.busy );
   for(i=OMIT_TEMPDB; i<db->nDb; i++){
     int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
     Schema *pSchema = db->aDb[j].pSchema;
@@ -393,7 +391,6 @@
   int i, j;
 
   assert( iDb>=0 && iDb<db->nDb );
-  db->flags &= ~SQLITE_Initialized;
   for(i=iDb; i<db->nDb; i++){
     Db *pDb = &db->aDb[i];
     if( pDb->pSchema ){
diff --git a/src/pragma.c b/src/pragma.c
index b9f510c..54fb19f 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.112 2006/01/10 17:58:23 danielk1977 Exp $
+** $Id: pragma.c,v 1.113 2006/01/11 14:09:32 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -808,7 +808,10 @@
       ** will be overwritten when the schema is next loaded. If it does not
       ** already exists, it will be created to use the new encoding value.
       */
-      if( !(pParse->db->flags&SQLITE_Initialized) ){
+      if( 
+        !(DbHasProperty(db, 0, DB_SchemaLoaded)) || 
+        DbHasProperty(db, 0, DB_Empty) 
+      ){
         for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
           if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
             ENC(pParse->db) = pEnc->enc;
diff --git a/src/prepare.c b/src/prepare.c
index c59d7fc..fcd0d19 100644
--- a/src/prepare.c
+++ b/src/prepare.c
@@ -13,7 +13,7 @@
 ** interface, and routines that contribute to loading the database schema
 ** from disk.
 **
-** $Id: prepare.c,v 1.18 2006/01/10 17:58:23 danielk1977 Exp $
+** $Id: prepare.c,v 1.19 2006/01/11 14:09:32 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -154,27 +154,7 @@
 #endif
 
   assert( iDb>=0 && iDb<db->nDb );
-
   assert( db->aDb[iDb].pSchema );
-#if 0
-  if( 0==db->aDb[iDb].pSchema ){
-    Schema *pS = sqlite3SchemaGet(db->aDb[iDb].pBt);
-    db->aDb[iDb].pSchema = pS;
-    if( !pS ){
-      return SQLITE_NOMEM;
-    }else if( pS->file_format!=0 ){
-      /* This means that the shared-schema associated with the the btree
-      ** is already open and populated.
-      */
-      if( pS->enc!=ENC(db) ){
-        sqlite3SetString(pzErrMsg, "attached databases must use the same"
-            " text encoding as main database", (char*)0);
-        return SQLITE_ERROR;
-      }
-      return SQLITE_OK;
-    }
-  }
-#endif
 
   /* zMasterSchema and zInitScript are set to point at the master schema
   ** and initialisation script appropriate for the database being
@@ -212,7 +192,9 @@
   */
   pDb = &db->aDb[iDb];
   if( pDb->pBt==0 ){
-    if( !OMIT_TEMPDB && iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded);
+    if( !OMIT_TEMPDB && iDb==1 ){
+      DbSetProperty(db, 1, DB_SchemaLoaded);
+    }
     return SQLITE_OK;
   }
   rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain);
@@ -272,6 +254,8 @@
         return SQLITE_ERROR;
       }
     }
+  }else{
+    DbSetProperty(db, iDb, DB_Empty);
   }
   pDb->pSchema->enc = ENC(db);
 
@@ -343,9 +327,9 @@
 */
 int sqlite3Init(sqlite3 *db, char **pzErrMsg){
   int i, rc;
+  int called_initone = 0;
   
   if( db->init.busy ) return SQLITE_OK;
-  assert( (db->flags & SQLITE_Initialized)==0 );
   rc = SQLITE_OK;
   db->init.busy = 1;
   for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
@@ -354,6 +338,7 @@
     if( rc ){
       sqlite3ResetInternalSchema(db, i);
     }
+    called_initone = 1;
   }
 
   /* Once all the other databases have been initialised, load the schema
@@ -366,19 +351,16 @@
     if( rc ){
       sqlite3ResetInternalSchema(db, 1);
     }
+    called_initone = 1;
   }
 #endif
 
   db->init.busy = 0;
-  if( rc==SQLITE_OK ){
-    db->flags |= SQLITE_Initialized;
+  if( rc==SQLITE_OK && called_initone ){
     sqlite3CommitInternalChanges(db);
   }
 
-  if( rc!=SQLITE_OK ){
-    db->flags &= ~SQLITE_Initialized;
-  }
-  return rc;
+  return rc; 
 }
 
 /*
@@ -389,11 +371,8 @@
   int rc = SQLITE_OK;
   sqlite3 *db = pParse->db;
   if( !db->init.busy ){
-    if( (db->flags & SQLITE_Initialized)==0 ){
-      rc = sqlite3Init(db, &pParse->zErrMsg);
-    }
+    rc = sqlite3Init(db, &pParse->zErrMsg);
   }
-  assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized) || db->init.busy );
   if( rc!=SQLITE_OK ){
     pParse->rc = rc;
     pParse->nErr++;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 5dc84f2..1710f92 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.460 2006/01/10 17:58:23 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.461 2006/01/11 14:09:32 danielk1977 Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -423,6 +423,7 @@
 */
 #define DB_SchemaLoaded    0x0001  /* The schema has been loaded */
 #define DB_UnresetViews    0x0002  /* Some views have defined column names */
+#define DB_Empty           0x0004  /* The file is empty (length 0 bytes) */
 
 #define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
 
@@ -522,7 +523,6 @@
 ** transaction is active on that particular database file.
 */
 #define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
-#define SQLITE_Initialized    0x00000002  /* True after initialization */
 #define SQLITE_Interrupt      0x00000004  /* Cancel current operation */
 #define SQLITE_InTrans        0x00000008  /* True if in a transaction */
 #define SQLITE_InternChanges  0x00000010  /* Uncommitted Hash table changes */
diff --git a/src/test1.c b/src/test1.c
index 6e54789..d98640b 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.186 2006/01/09 16:12:05 danielk1977 Exp $
+** $Id: test1.c,v 1.187 2006/01/11 14:09:32 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -3523,5 +3523,9 @@
       (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
 #endif /* OS_UNIX */
   set_options(interp);
+
+  int sqlite3_shared_cache_report(void *, Tcl_Interp *, int, Tcl_Obj *CONST[]);
+  Tcl_CreateObjCommand(interp, "sqlite_shared_cache_report", 
+      sqlite3_shared_cache_report, 0, 0);
   return TCL_OK;
 }