Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -146,11 +146,11 @@ ** set for each database that is used. Generate code to start a ** transaction on each used database and to verify the schema cookie ** on each used database. */ if( pParse->cookieGoto>0 ){ - u32 mask; + tAttachMask mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDbnDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); @@ -3442,16 +3442,16 @@ if( v==0 ) return; /* This only happens if there was a prior error */ pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; } if( iDb>=0 ){ sqlite3 *db = pToplevel->db; - int mask; + tAttachMask mask; assert( iDbnDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDbcookieMask & mask)==0 ){ pToplevel->cookieMask |= mask; pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; if( !OMIT_TEMPDB && iDb==1 ){ sqlite3OpenTempDatabase(pToplevel); @@ -3474,11 +3474,11 @@ ** necessary to undo a write and the checkpoint should not be set. */ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); sqlite3CodeVerifySchema(pParse, iDb); - pToplevel->writeMask |= 1<writeMask |= ((tAttachMask)1)<isMultiWrite |= setStatement; } /* ** Indicate that the statement currently under construction might write Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -1721,12 +1721,12 @@ # error SQLITE_MAX_VDBE_OP must be at least 40 #endif #if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000 # error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000 #endif -#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>30 -# error SQLITE_MAX_ATTACHED must be between 0 and 30 +#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>62 +# error SQLITE_MAX_ATTACHED must be between 0 and 62 #endif #if SQLITE_MAX_LIKE_PATTERN_LENGTH<1 # error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1 #endif #if SQLITE_MAX_COLUMN>32767 Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2123,10 +2123,17 @@ SubProgram *pProgram; /* Program implementing pTrigger/orconf */ u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */ TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ }; +/* Datatype for the bitmask of all attached databases */ +#if SQLITE_MAX_ATTACHED>30 + typedef sqlite3_uint64 tAttachMask; +#else + typedef unsigned int tAttachMask; +#endif + /* ** An SQL parser context. A copy of this structure is passed through ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. ** @@ -2171,12 +2178,12 @@ u8 tempReg; /* iReg is a temp register that needs to be freed */ int iLevel; /* Nesting level */ int iReg; /* Reg with value of this column. 0 means none. */ int lru; /* Least recently used entry has the smallest value */ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ - u32 writeMask; /* Start a write transaction on these databases */ - u32 cookieMask; /* Bitmask of schema verified databases */ + tAttachMask writeMask; /* Start a write transaction on these databases */ + tAttachMask cookieMask; /* Bitmask of schema verified databases */ u8 isMultiWrite; /* True if statement may affect/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ #ifndef SQLITE_OMIT_SHARED_CACHE Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -300,11 +300,11 @@ u8 inVtabMethod; /* See comments above */ u8 usesStmtJournal; /* True if uses a statement journal */ u8 readOnly; /* True for read-only statements */ u8 isPrepareV2; /* True if prepared with prepare_v2() */ int nChange; /* Number of db changes made since last reset */ - int btreeMask; /* Bitmask of db->aDb[] entries referenced */ + tAttachMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ int aCounter[3]; /* Counters used by sqlite3_stmt_status() */ BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */ #ifndef SQLITE_OMIT_TRACE i64 startTime; /* Time when query started - used for profiling */ Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -948,12 +948,12 @@ ** will be used so that it can acquire mutexes on them all in sorted ** order (via sqlite3VdbeMutexArrayEnter(). Mutexes are acquired ** in order (and released in reverse order) to avoid deadlocks. */ void sqlite3VdbeUsesBtree(Vdbe *p, int i){ - int mask; - assert( i>=0 && idb->nDb && i=0 && idb->nDb && ibtreeMask)*8 ); mask = ((u32)1)<btreeMask & mask)==0 ){ p->btreeMask |= mask; sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt); Index: test/attach.test ================================================================== --- test/attach.test +++ test/attach.test @@ -150,18 +150,20 @@ catchsql { ATTACH 'test.db' as db10; ATTACH 'test.db' as db11; } } {0 {}} -do_test attach-1.19 { - catchsql { - ATTACH 'test.db' as db12; - } -} {1 {too many attached databases - max 10}} -do_test attach-1.19.1 { - db errorcode -} {1} +if {$SQLITE_MAX_ATTACHED==10} { + do_test attach-1.19 { + catchsql { + ATTACH 'test.db' as db12; + } + } {1 {too many attached databases - max 10}} + do_test attach-1.19.1 { + db errorcode + } {1} +} do_test attach-1.20.1 { execsql { DETACH db5; } } {} @@ -177,18 +179,20 @@ do_test attach-1.21 { catchsql { ATTACH 'test.db' as db12; } } {0 {}} -do_test attach-1.22 { - catchsql { - ATTACH 'test.db' as db13; - } -} {1 {too many attached databases - max 10}} -do_test attach-1.22.1 { - db errorcode -} {1} +if {$SQLITE_MAX_ATTACHED==10} { + do_test attach-1.22 { + catchsql { + ATTACH 'test.db' as db13; + } + } {1 {too many attached databases - max 10}} + do_test attach-1.22.1 { + db errorcode + } {1} +} do_test attach-1.23 { catchsql { DETACH "db14"; } } {1 {no such database: db14}}