1c11d4f93Sdrh /* 2c11d4f93Sdrh ** 2003 April 6 3c11d4f93Sdrh ** 4c11d4f93Sdrh ** The author disclaims copyright to this source code. In place of 5c11d4f93Sdrh ** a legal notice, here is a blessing: 6c11d4f93Sdrh ** 7c11d4f93Sdrh ** May you do good and not evil. 8c11d4f93Sdrh ** May you find forgiveness for yourself and forgive others. 9c11d4f93Sdrh ** May you share freely, never taking more than you give. 10c11d4f93Sdrh ** 11c11d4f93Sdrh ************************************************************************* 12c11d4f93Sdrh ** This file contains code used to implement the ATTACH and DETACH commands. 13c11d4f93Sdrh ** 14*96fb0dd5Sdanielk1977 ** $Id: attach.c,v 1.21 2004/06/30 09:49:23 danielk1977 Exp $ 15c11d4f93Sdrh */ 16c11d4f93Sdrh #include "sqliteInt.h" 17c11d4f93Sdrh 18c11d4f93Sdrh /* 19c11d4f93Sdrh ** This routine is called by the parser to process an ATTACH statement: 20c11d4f93Sdrh ** 21c11d4f93Sdrh ** ATTACH DATABASE filename AS dbname 22c11d4f93Sdrh ** 23c11d4f93Sdrh ** The pFilename and pDbname arguments are the tokens that define the 24c11d4f93Sdrh ** filename and dbname in the ATTACH statement. 25c11d4f93Sdrh */ 264adee20fSdanielk1977 void sqlite3Attach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){ 27c11d4f93Sdrh Db *aNew; 28c11d4f93Sdrh int rc, i; 29c11d4f93Sdrh char *zFile, *zName; 30c11d4f93Sdrh sqlite *db; 310bca3530Sdrh Vdbe *v; 32c11d4f93Sdrh 334adee20fSdanielk1977 v = sqlite3GetVdbe(pParse); 34*96fb0dd5Sdanielk1977 if( !v ) return; 354adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Halt, 0, 0); 36c11d4f93Sdrh if( pParse->explain ) return; 37c11d4f93Sdrh db = pParse->db; 38c11d4f93Sdrh if( db->nDb>=MAX_ATTACHED+2 ){ 394adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "too many attached databases - max %d", 40c11d4f93Sdrh MAX_ATTACHED); 41c11d4f93Sdrh pParse->rc = SQLITE_ERROR; 42c11d4f93Sdrh return; 43c11d4f93Sdrh } 4481e293b4Sdrh 4592f9a1bbSdanielk1977 if( !db->autoCommit ){ 4692f9a1bbSdanielk1977 sqlite3ErrorMsg(pParse, "cannot ATTACH database within transaction"); 4792f9a1bbSdanielk1977 pParse->rc = SQLITE_ERROR; 4892f9a1bbSdanielk1977 return; 4992f9a1bbSdanielk1977 } 5092f9a1bbSdanielk1977 51a99db3b6Sdrh zFile = sqlite3NameFromToken(pFilename);; 5281e293b4Sdrh if( zFile==0 ) return; 5381e293b4Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION 544adee20fSdanielk1977 if( sqlite3AuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){ 5581e293b4Sdrh sqliteFree(zFile); 5681e293b4Sdrh return; 5781e293b4Sdrh } 5881e293b4Sdrh #endif /* SQLITE_OMIT_AUTHORIZATION */ 5981e293b4Sdrh 60a99db3b6Sdrh zName = sqlite3NameFromToken(pDbname); 6181e293b4Sdrh if( zName==0 ) return; 6281e293b4Sdrh for(i=0; i<db->nDb; i++){ 63124b27e6Sdrh char *z = db->aDb[i].zName; 64124b27e6Sdrh if( z && sqlite3StrICmp(z, zName)==0 ){ 654adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "database %z is already in use", zName); 6681e293b4Sdrh pParse->rc = SQLITE_ERROR; 6781e293b4Sdrh sqliteFree(zFile); 6881e293b4Sdrh return; 6981e293b4Sdrh } 7081e293b4Sdrh } 7181e293b4Sdrh 72c11d4f93Sdrh if( db->aDb==db->aDbStatic ){ 73c11d4f93Sdrh aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); 74c11d4f93Sdrh if( aNew==0 ) return; 75c11d4f93Sdrh memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); 76c11d4f93Sdrh }else{ 77c11d4f93Sdrh aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); 78c11d4f93Sdrh if( aNew==0 ) return; 79c11d4f93Sdrh } 80c11d4f93Sdrh db->aDb = aNew; 81c11d4f93Sdrh aNew = &db->aDb[db->nDb++]; 82c11d4f93Sdrh memset(aNew, 0, sizeof(*aNew)); 834adee20fSdanielk1977 sqlite3HashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0); 844adee20fSdanielk1977 sqlite3HashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); 854adee20fSdanielk1977 sqlite3HashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); 864adee20fSdanielk1977 sqlite3HashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); 87c11d4f93Sdrh aNew->zName = zName; 8891cf71b0Sdanielk1977 aNew->safety_level = 3; 894adee20fSdanielk1977 rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); 90c11d4f93Sdrh if( rc ){ 914adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "unable to open database: %s", zFile); 92c11d4f93Sdrh } 934d189ca4Sdrh #if SQLITE_HAS_CODEC 944d189ca4Sdrh { 954d189ca4Sdrh extern int sqliteCodecAttach(sqlite*, int, void*, int); 964d189ca4Sdrh char *zKey = 0; 974d189ca4Sdrh int nKey; 984d189ca4Sdrh if( pKey && pKey->z && pKey->n ){ 994adee20fSdanielk1977 sqlite3SetNString(&zKey, pKey->z, pKey->n, 0); 1004adee20fSdanielk1977 sqlite3Dequote(zKey); 1014d189ca4Sdrh nKey = strlen(zKey); 1024d189ca4Sdrh }else{ 1034d189ca4Sdrh zKey = 0; 1044d189ca4Sdrh nKey = 0; 1054d189ca4Sdrh } 1064d189ca4Sdrh sqliteCodecAttach(db, db->nDb-1, zKey, nKey); 1074d189ca4Sdrh } 1084d189ca4Sdrh #endif 109c11d4f93Sdrh sqliteFree(zFile); 110c11d4f93Sdrh db->flags &= ~SQLITE_Initialized; 111c11d4f93Sdrh if( pParse->nErr ) return; 112447623d9Sdrh if( rc==SQLITE_OK ){ 1138a41449eSdanielk1977 rc = sqlite3ReadSchema(pParse); 114447623d9Sdrh } 115c11d4f93Sdrh if( rc ){ 116447623d9Sdrh int i = db->nDb - 1; 117447623d9Sdrh assert( i>=2 ); 118447623d9Sdrh if( db->aDb[i].pBt ){ 1194adee20fSdanielk1977 sqlite3BtreeClose(db->aDb[i].pBt); 120447623d9Sdrh db->aDb[i].pBt = 0; 121447623d9Sdrh } 1224adee20fSdanielk1977 sqlite3ResetInternalSchema(db, 0); 1238a41449eSdanielk1977 if( 0==pParse->nErr ){ 124c11d4f93Sdrh pParse->nErr++; 125c11d4f93Sdrh pParse->rc = SQLITE_ERROR; 126c11d4f93Sdrh } 127c11d4f93Sdrh } 1288a41449eSdanielk1977 } 129c11d4f93Sdrh 130c11d4f93Sdrh /* 131c11d4f93Sdrh ** This routine is called by the parser to process a DETACH statement: 132c11d4f93Sdrh ** 133c11d4f93Sdrh ** DETACH DATABASE dbname 134c11d4f93Sdrh ** 135c11d4f93Sdrh ** The pDbname argument is the name of the database in the DETACH statement. 136c11d4f93Sdrh */ 1374adee20fSdanielk1977 void sqlite3Detach(Parse *pParse, Token *pDbname){ 138c11d4f93Sdrh int i; 139c11d4f93Sdrh sqlite *db; 1400bca3530Sdrh Vdbe *v; 141e0d4b060Sdanielk1977 Db *pDb = 0; 142c11d4f93Sdrh 1434adee20fSdanielk1977 v = sqlite3GetVdbe(pParse); 144*96fb0dd5Sdanielk1977 if( !v ) return; 1454adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Halt, 0, 0); 146c11d4f93Sdrh if( pParse->explain ) return; 147c11d4f93Sdrh db = pParse->db; 148c11d4f93Sdrh for(i=0; i<db->nDb; i++){ 149124b27e6Sdrh pDb = &db->aDb[i]; 150124b27e6Sdrh if( pDb->pBt==0 || pDb->zName==0 ) continue; 151124b27e6Sdrh if( strlen(pDb->zName)!=pDbname->n ) continue; 152124b27e6Sdrh if( sqlite3StrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break; 153c11d4f93Sdrh } 154c11d4f93Sdrh if( i>=db->nDb ){ 1554adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "no such database: %T", pDbname); 156c11d4f93Sdrh return; 157c11d4f93Sdrh } 158c11d4f93Sdrh if( i<2 ){ 1594adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "cannot detach database %T", pDbname); 160c11d4f93Sdrh return; 161c11d4f93Sdrh } 16292f9a1bbSdanielk1977 if( !db->autoCommit ){ 16392f9a1bbSdanielk1977 sqlite3ErrorMsg(pParse, "cannot DETACH database within transaction"); 16492f9a1bbSdanielk1977 pParse->rc = SQLITE_ERROR; 16592f9a1bbSdanielk1977 return; 16692f9a1bbSdanielk1977 } 16781e293b4Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION 1684adee20fSdanielk1977 if( sqlite3AuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){ 16981e293b4Sdrh return; 17081e293b4Sdrh } 17181e293b4Sdrh #endif /* SQLITE_OMIT_AUTHORIZATION */ 172124b27e6Sdrh sqlite3BtreeClose(pDb->pBt); 173124b27e6Sdrh pDb->pBt = 0; 174124b27e6Sdrh sqliteFree(pDb->zName); 1754adee20fSdanielk1977 sqlite3ResetInternalSchema(db, i); 176c11d4f93Sdrh db->nDb--; 177c11d4f93Sdrh if( i<db->nDb ){ 178c11d4f93Sdrh db->aDb[i] = db->aDb[db->nDb]; 179c11d4f93Sdrh memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0])); 1804adee20fSdanielk1977 sqlite3ResetInternalSchema(db, i); 181c11d4f93Sdrh } 182c11d4f93Sdrh } 183f26e09c8Sdrh 184f26e09c8Sdrh /* 185f26e09c8Sdrh ** Initialize a DbFixer structure. This routine must be called prior 186f26e09c8Sdrh ** to passing the structure to one of the sqliteFixAAAA() routines below. 187f26e09c8Sdrh ** 188f26e09c8Sdrh ** The return value indicates whether or not fixation is required. TRUE 189f26e09c8Sdrh ** means we do need to fix the database references, FALSE means we do not. 190f26e09c8Sdrh */ 1914adee20fSdanielk1977 int sqlite3FixInit( 192f26e09c8Sdrh DbFixer *pFix, /* The fixer to be initialized */ 193f26e09c8Sdrh Parse *pParse, /* Error messages will be written here */ 194f26e09c8Sdrh int iDb, /* This is the database that must must be used */ 195f26e09c8Sdrh const char *zType, /* "view", "trigger", or "index" */ 196f26e09c8Sdrh const Token *pName /* Name of the view, trigger, or index */ 197f26e09c8Sdrh ){ 198f26e09c8Sdrh sqlite *db; 199f26e09c8Sdrh 200f26e09c8Sdrh if( iDb<0 || iDb==1 ) return 0; 201f26e09c8Sdrh db = pParse->db; 202f26e09c8Sdrh assert( db->nDb>iDb ); 2034312db55Sdrh pFix->pParse = pParse; 204f26e09c8Sdrh pFix->zDb = db->aDb[iDb].zName; 205f26e09c8Sdrh pFix->zType = zType; 206f26e09c8Sdrh pFix->pName = pName; 207f26e09c8Sdrh return 1; 208f26e09c8Sdrh } 209f26e09c8Sdrh 210f26e09c8Sdrh /* 211f26e09c8Sdrh ** The following set of routines walk through the parse tree and assign 212f26e09c8Sdrh ** a specific database to all table references where the database name 213f26e09c8Sdrh ** was left unspecified in the original SQL statement. The pFix structure 2144adee20fSdanielk1977 ** must have been initialized by a prior call to sqlite3FixInit(). 215f26e09c8Sdrh ** 216f26e09c8Sdrh ** These routines are used to make sure that an index, trigger, or 217f26e09c8Sdrh ** view in one database does not refer to objects in a different database. 218f26e09c8Sdrh ** (Exception: indices, triggers, and views in the TEMP database are 219f26e09c8Sdrh ** allowed to refer to anything.) If a reference is explicitly made 220f26e09c8Sdrh ** to an object in a different database, an error message is added to 221f26e09c8Sdrh ** pParse->zErrMsg and these routines return non-zero. If everything 222f26e09c8Sdrh ** checks out, these routines return 0. 223f26e09c8Sdrh */ 2244adee20fSdanielk1977 int sqlite3FixSrcList( 225f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 226f26e09c8Sdrh SrcList *pList /* The Source list to check and modify */ 227f26e09c8Sdrh ){ 228f26e09c8Sdrh int i; 229f26e09c8Sdrh const char *zDb; 230f26e09c8Sdrh 231f26e09c8Sdrh if( pList==0 ) return 0; 232f26e09c8Sdrh zDb = pFix->zDb; 233f26e09c8Sdrh for(i=0; i<pList->nSrc; i++){ 234f26e09c8Sdrh if( pList->a[i].zDatabase==0 ){ 235f26e09c8Sdrh pList->a[i].zDatabase = sqliteStrDup(zDb); 2364adee20fSdanielk1977 }else if( sqlite3StrICmp(pList->a[i].zDatabase,zDb)!=0 ){ 2374adee20fSdanielk1977 sqlite3ErrorMsg(pFix->pParse, 2384312db55Sdrh "%s %z cannot reference objects in database %s", 2394312db55Sdrh pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n), 2404312db55Sdrh pList->a[i].zDatabase); 241f26e09c8Sdrh return 1; 242f26e09c8Sdrh } 2434adee20fSdanielk1977 if( sqlite3FixSelect(pFix, pList->a[i].pSelect) ) return 1; 2444adee20fSdanielk1977 if( sqlite3FixExpr(pFix, pList->a[i].pOn) ) return 1; 245f26e09c8Sdrh } 246f26e09c8Sdrh return 0; 247f26e09c8Sdrh } 2484adee20fSdanielk1977 int sqlite3FixSelect( 249f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 250f26e09c8Sdrh Select *pSelect /* The SELECT statement to be fixed to one database */ 251f26e09c8Sdrh ){ 252f26e09c8Sdrh while( pSelect ){ 2534adee20fSdanielk1977 if( sqlite3FixExprList(pFix, pSelect->pEList) ){ 254f26e09c8Sdrh return 1; 255f26e09c8Sdrh } 2564adee20fSdanielk1977 if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ 257f26e09c8Sdrh return 1; 258f26e09c8Sdrh } 2594adee20fSdanielk1977 if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ 260f26e09c8Sdrh return 1; 261f26e09c8Sdrh } 2624adee20fSdanielk1977 if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ 263f26e09c8Sdrh return 1; 264f26e09c8Sdrh } 265f26e09c8Sdrh pSelect = pSelect->pPrior; 266f26e09c8Sdrh } 267f26e09c8Sdrh return 0; 268f26e09c8Sdrh } 2694adee20fSdanielk1977 int sqlite3FixExpr( 270f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 271f26e09c8Sdrh Expr *pExpr /* The expression to be fixed to one database */ 272f26e09c8Sdrh ){ 273f26e09c8Sdrh while( pExpr ){ 2744adee20fSdanielk1977 if( sqlite3FixSelect(pFix, pExpr->pSelect) ){ 275f26e09c8Sdrh return 1; 276f26e09c8Sdrh } 2774adee20fSdanielk1977 if( sqlite3FixExprList(pFix, pExpr->pList) ){ 278f26e09c8Sdrh return 1; 279f26e09c8Sdrh } 2804adee20fSdanielk1977 if( sqlite3FixExpr(pFix, pExpr->pRight) ){ 281f26e09c8Sdrh return 1; 282f26e09c8Sdrh } 283f26e09c8Sdrh pExpr = pExpr->pLeft; 284f26e09c8Sdrh } 285f26e09c8Sdrh return 0; 286f26e09c8Sdrh } 2874adee20fSdanielk1977 int sqlite3FixExprList( 288f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 289f26e09c8Sdrh ExprList *pList /* The expression to be fixed to one database */ 290f26e09c8Sdrh ){ 291f26e09c8Sdrh int i; 292f26e09c8Sdrh if( pList==0 ) return 0; 293f26e09c8Sdrh for(i=0; i<pList->nExpr; i++){ 2944adee20fSdanielk1977 if( sqlite3FixExpr(pFix, pList->a[i].pExpr) ){ 295f26e09c8Sdrh return 1; 296f26e09c8Sdrh } 297f26e09c8Sdrh } 298f26e09c8Sdrh return 0; 299f26e09c8Sdrh } 3004adee20fSdanielk1977 int sqlite3FixTriggerStep( 301f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 302f26e09c8Sdrh TriggerStep *pStep /* The trigger step be fixed to one database */ 303f26e09c8Sdrh ){ 304f26e09c8Sdrh while( pStep ){ 3054adee20fSdanielk1977 if( sqlite3FixSelect(pFix, pStep->pSelect) ){ 306f26e09c8Sdrh return 1; 307f26e09c8Sdrh } 3084adee20fSdanielk1977 if( sqlite3FixExpr(pFix, pStep->pWhere) ){ 309f26e09c8Sdrh return 1; 310f26e09c8Sdrh } 3114adee20fSdanielk1977 if( sqlite3FixExprList(pFix, pStep->pExprList) ){ 312f26e09c8Sdrh return 1; 313f26e09c8Sdrh } 314f26e09c8Sdrh pStep = pStep->pNext; 315f26e09c8Sdrh } 316f26e09c8Sdrh return 0; 317f26e09c8Sdrh } 318