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*0bca3530Sdrh ** $Id: attach.c,v 1.9 2004/01/20 11:54:03 drh 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 */ 26c11d4f93Sdrh void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){ 27c11d4f93Sdrh Db *aNew; 28c11d4f93Sdrh int rc, i; 29c11d4f93Sdrh char *zFile, *zName; 30c11d4f93Sdrh sqlite *db; 31*0bca3530Sdrh Vdbe *v; 32c11d4f93Sdrh 33*0bca3530Sdrh v = sqliteGetVdbe(pParse); 34*0bca3530Sdrh sqliteVdbeAddOp(v, OP_Halt, 0, 0); 35c11d4f93Sdrh if( pParse->explain ) return; 36c11d4f93Sdrh db = pParse->db; 37c11d4f93Sdrh if( db->file_format<4 ){ 38c11d4f93Sdrh sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an " 39c11d4f93Sdrh "older format master database", 0); 40c11d4f93Sdrh pParse->rc = SQLITE_ERROR; 41c11d4f93Sdrh return; 42c11d4f93Sdrh } 43c11d4f93Sdrh if( db->nDb>=MAX_ATTACHED+2 ){ 44c11d4f93Sdrh sqliteErrorMsg(pParse, "too many attached databases - max %d", 45c11d4f93Sdrh MAX_ATTACHED); 46c11d4f93Sdrh pParse->rc = SQLITE_ERROR; 47c11d4f93Sdrh return; 48c11d4f93Sdrh } 4981e293b4Sdrh 5081e293b4Sdrh zFile = 0; 5181e293b4Sdrh sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0); 5281e293b4Sdrh if( zFile==0 ) return; 5381e293b4Sdrh sqliteDequote(zFile); 5481e293b4Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION 5581e293b4Sdrh if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){ 5681e293b4Sdrh sqliteFree(zFile); 5781e293b4Sdrh return; 5881e293b4Sdrh } 5981e293b4Sdrh #endif /* SQLITE_OMIT_AUTHORIZATION */ 6081e293b4Sdrh 6181e293b4Sdrh zName = 0; 6281e293b4Sdrh sqliteSetNString(&zName, pDbname->z, pDbname->n, 0); 6381e293b4Sdrh if( zName==0 ) return; 6481e293b4Sdrh sqliteDequote(zName); 6581e293b4Sdrh for(i=0; i<db->nDb; i++){ 6681e293b4Sdrh if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){ 6781e293b4Sdrh sqliteErrorMsg(pParse, "database %z is already in use", zName); 6881e293b4Sdrh pParse->rc = SQLITE_ERROR; 6981e293b4Sdrh sqliteFree(zFile); 7081e293b4Sdrh return; 7181e293b4Sdrh } 7281e293b4Sdrh } 7381e293b4Sdrh 74c11d4f93Sdrh if( db->aDb==db->aDbStatic ){ 75c11d4f93Sdrh aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); 76c11d4f93Sdrh if( aNew==0 ) return; 77c11d4f93Sdrh memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); 78c11d4f93Sdrh }else{ 79c11d4f93Sdrh aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); 80c11d4f93Sdrh if( aNew==0 ) return; 81c11d4f93Sdrh } 82c11d4f93Sdrh db->aDb = aNew; 83c11d4f93Sdrh aNew = &db->aDb[db->nDb++]; 84c11d4f93Sdrh memset(aNew, 0, sizeof(*aNew)); 85c11d4f93Sdrh sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0); 86c11d4f93Sdrh sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); 87c11d4f93Sdrh sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); 88c11d4f93Sdrh sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); 89c11d4f93Sdrh aNew->zName = zName; 90b0208ccaSpaul rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); 91c11d4f93Sdrh if( rc ){ 92c11d4f93Sdrh sqliteErrorMsg(pParse, "unable to open database: %s", zFile); 93c11d4f93Sdrh } 94c11d4f93Sdrh sqliteFree(zFile); 95c11d4f93Sdrh db->flags &= ~SQLITE_Initialized; 96c11d4f93Sdrh if( pParse->nErr ) return; 97447623d9Sdrh if( rc==SQLITE_OK ){ 98c11d4f93Sdrh rc = sqliteInit(pParse->db, &pParse->zErrMsg); 99447623d9Sdrh } 100c11d4f93Sdrh if( rc ){ 101447623d9Sdrh int i = db->nDb - 1; 102447623d9Sdrh assert( i>=2 ); 103447623d9Sdrh if( db->aDb[i].pBt ){ 104447623d9Sdrh sqliteBtreeClose(db->aDb[i].pBt); 105447623d9Sdrh db->aDb[i].pBt = 0; 106447623d9Sdrh } 107c11d4f93Sdrh sqliteResetInternalSchema(db, 0); 108c11d4f93Sdrh pParse->nErr++; 109c11d4f93Sdrh pParse->rc = SQLITE_ERROR; 110c11d4f93Sdrh } 111c11d4f93Sdrh } 112c11d4f93Sdrh 113c11d4f93Sdrh /* 114c11d4f93Sdrh ** This routine is called by the parser to process a DETACH statement: 115c11d4f93Sdrh ** 116c11d4f93Sdrh ** DETACH DATABASE dbname 117c11d4f93Sdrh ** 118c11d4f93Sdrh ** The pDbname argument is the name of the database in the DETACH statement. 119c11d4f93Sdrh */ 120c11d4f93Sdrh void sqliteDetach(Parse *pParse, Token *pDbname){ 121c11d4f93Sdrh int i; 122c11d4f93Sdrh sqlite *db; 123*0bca3530Sdrh Vdbe *v; 124c11d4f93Sdrh 125*0bca3530Sdrh v = sqliteGetVdbe(pParse); 126*0bca3530Sdrh sqliteVdbeAddOp(v, OP_Halt, 0, 0); 127c11d4f93Sdrh if( pParse->explain ) return; 128c11d4f93Sdrh db = pParse->db; 129c11d4f93Sdrh for(i=0; i<db->nDb; i++){ 130c11d4f93Sdrh if( db->aDb[i].pBt==0 || db->aDb[i].zName==0 ) continue; 131c11d4f93Sdrh if( strlen(db->aDb[i].zName)!=pDbname->n ) continue; 132c11d4f93Sdrh if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break; 133c11d4f93Sdrh } 134c11d4f93Sdrh if( i>=db->nDb ){ 135c11d4f93Sdrh sqliteErrorMsg(pParse, "no such database: %T", pDbname); 136c11d4f93Sdrh return; 137c11d4f93Sdrh } 138c11d4f93Sdrh if( i<2 ){ 139c11d4f93Sdrh sqliteErrorMsg(pParse, "cannot detach database %T", pDbname); 140c11d4f93Sdrh return; 141c11d4f93Sdrh } 14281e293b4Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION 14381e293b4Sdrh if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){ 14481e293b4Sdrh return; 14581e293b4Sdrh } 14681e293b4Sdrh #endif /* SQLITE_OMIT_AUTHORIZATION */ 147c11d4f93Sdrh sqliteBtreeClose(db->aDb[i].pBt); 148c11d4f93Sdrh db->aDb[i].pBt = 0; 14970ce3f0cSdrh sqliteFree(db->aDb[i].zName); 150c11d4f93Sdrh sqliteResetInternalSchema(db, i); 151c11d4f93Sdrh db->nDb--; 152c11d4f93Sdrh if( i<db->nDb ){ 153c11d4f93Sdrh db->aDb[i] = db->aDb[db->nDb]; 154c11d4f93Sdrh memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0])); 155c11d4f93Sdrh sqliteResetInternalSchema(db, i); 156c11d4f93Sdrh } 157c11d4f93Sdrh } 158f26e09c8Sdrh 159f26e09c8Sdrh /* 160f26e09c8Sdrh ** Initialize a DbFixer structure. This routine must be called prior 161f26e09c8Sdrh ** to passing the structure to one of the sqliteFixAAAA() routines below. 162f26e09c8Sdrh ** 163f26e09c8Sdrh ** The return value indicates whether or not fixation is required. TRUE 164f26e09c8Sdrh ** means we do need to fix the database references, FALSE means we do not. 165f26e09c8Sdrh */ 166f26e09c8Sdrh int sqliteFixInit( 167f26e09c8Sdrh DbFixer *pFix, /* The fixer to be initialized */ 168f26e09c8Sdrh Parse *pParse, /* Error messages will be written here */ 169f26e09c8Sdrh int iDb, /* This is the database that must must be used */ 170f26e09c8Sdrh const char *zType, /* "view", "trigger", or "index" */ 171f26e09c8Sdrh const Token *pName /* Name of the view, trigger, or index */ 172f26e09c8Sdrh ){ 173f26e09c8Sdrh sqlite *db; 174f26e09c8Sdrh 175f26e09c8Sdrh if( iDb<0 || iDb==1 ) return 0; 176f26e09c8Sdrh db = pParse->db; 177f26e09c8Sdrh assert( db->nDb>iDb ); 1784312db55Sdrh pFix->pParse = pParse; 179f26e09c8Sdrh pFix->zDb = db->aDb[iDb].zName; 180f26e09c8Sdrh pFix->zType = zType; 181f26e09c8Sdrh pFix->pName = pName; 182f26e09c8Sdrh return 1; 183f26e09c8Sdrh } 184f26e09c8Sdrh 185f26e09c8Sdrh /* 186f26e09c8Sdrh ** The following set of routines walk through the parse tree and assign 187f26e09c8Sdrh ** a specific database to all table references where the database name 188f26e09c8Sdrh ** was left unspecified in the original SQL statement. The pFix structure 189f26e09c8Sdrh ** must have been initialized by a prior call to sqliteFixInit(). 190f26e09c8Sdrh ** 191f26e09c8Sdrh ** These routines are used to make sure that an index, trigger, or 192f26e09c8Sdrh ** view in one database does not refer to objects in a different database. 193f26e09c8Sdrh ** (Exception: indices, triggers, and views in the TEMP database are 194f26e09c8Sdrh ** allowed to refer to anything.) If a reference is explicitly made 195f26e09c8Sdrh ** to an object in a different database, an error message is added to 196f26e09c8Sdrh ** pParse->zErrMsg and these routines return non-zero. If everything 197f26e09c8Sdrh ** checks out, these routines return 0. 198f26e09c8Sdrh */ 199f26e09c8Sdrh int sqliteFixSrcList( 200f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 201f26e09c8Sdrh SrcList *pList /* The Source list to check and modify */ 202f26e09c8Sdrh ){ 203f26e09c8Sdrh int i; 204f26e09c8Sdrh const char *zDb; 205f26e09c8Sdrh 206f26e09c8Sdrh if( pList==0 ) return 0; 207f26e09c8Sdrh zDb = pFix->zDb; 208f26e09c8Sdrh for(i=0; i<pList->nSrc; i++){ 209f26e09c8Sdrh if( pList->a[i].zDatabase==0 ){ 210f26e09c8Sdrh pList->a[i].zDatabase = sqliteStrDup(zDb); 211f26e09c8Sdrh }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){ 212f26e09c8Sdrh sqliteErrorMsg(pFix->pParse, 2134312db55Sdrh "%s %z cannot reference objects in database %s", 2144312db55Sdrh pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n), 2154312db55Sdrh pList->a[i].zDatabase); 216f26e09c8Sdrh return 1; 217f26e09c8Sdrh } 218f26e09c8Sdrh if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1; 219f26e09c8Sdrh if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1; 220f26e09c8Sdrh } 221f26e09c8Sdrh return 0; 222f26e09c8Sdrh } 223f26e09c8Sdrh int sqliteFixSelect( 224f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 225f26e09c8Sdrh Select *pSelect /* The SELECT statement to be fixed to one database */ 226f26e09c8Sdrh ){ 227f26e09c8Sdrh while( pSelect ){ 228f26e09c8Sdrh if( sqliteFixExprList(pFix, pSelect->pEList) ){ 229f26e09c8Sdrh return 1; 230f26e09c8Sdrh } 231f26e09c8Sdrh if( sqliteFixSrcList(pFix, pSelect->pSrc) ){ 232f26e09c8Sdrh return 1; 233f26e09c8Sdrh } 234f26e09c8Sdrh if( sqliteFixExpr(pFix, pSelect->pWhere) ){ 235f26e09c8Sdrh return 1; 236f26e09c8Sdrh } 237f26e09c8Sdrh if( sqliteFixExpr(pFix, pSelect->pHaving) ){ 238f26e09c8Sdrh return 1; 239f26e09c8Sdrh } 240f26e09c8Sdrh pSelect = pSelect->pPrior; 241f26e09c8Sdrh } 242f26e09c8Sdrh return 0; 243f26e09c8Sdrh } 244f26e09c8Sdrh int sqliteFixExpr( 245f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 246f26e09c8Sdrh Expr *pExpr /* The expression to be fixed to one database */ 247f26e09c8Sdrh ){ 248f26e09c8Sdrh while( pExpr ){ 249f26e09c8Sdrh if( sqliteFixSelect(pFix, pExpr->pSelect) ){ 250f26e09c8Sdrh return 1; 251f26e09c8Sdrh } 252f26e09c8Sdrh if( sqliteFixExprList(pFix, pExpr->pList) ){ 253f26e09c8Sdrh return 1; 254f26e09c8Sdrh } 255f26e09c8Sdrh if( sqliteFixExpr(pFix, pExpr->pRight) ){ 256f26e09c8Sdrh return 1; 257f26e09c8Sdrh } 258f26e09c8Sdrh pExpr = pExpr->pLeft; 259f26e09c8Sdrh } 260f26e09c8Sdrh return 0; 261f26e09c8Sdrh } 262f26e09c8Sdrh int sqliteFixExprList( 263f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 264f26e09c8Sdrh ExprList *pList /* The expression to be fixed to one database */ 265f26e09c8Sdrh ){ 266f26e09c8Sdrh int i; 267f26e09c8Sdrh if( pList==0 ) return 0; 268f26e09c8Sdrh for(i=0; i<pList->nExpr; i++){ 269f26e09c8Sdrh if( sqliteFixExpr(pFix, pList->a[i].pExpr) ){ 270f26e09c8Sdrh return 1; 271f26e09c8Sdrh } 272f26e09c8Sdrh } 273f26e09c8Sdrh return 0; 274f26e09c8Sdrh } 275f26e09c8Sdrh int sqliteFixTriggerStep( 276f26e09c8Sdrh DbFixer *pFix, /* Context of the fixation */ 277f26e09c8Sdrh TriggerStep *pStep /* The trigger step be fixed to one database */ 278f26e09c8Sdrh ){ 279f26e09c8Sdrh while( pStep ){ 280f26e09c8Sdrh if( sqliteFixSelect(pFix, pStep->pSelect) ){ 281f26e09c8Sdrh return 1; 282f26e09c8Sdrh } 283f26e09c8Sdrh if( sqliteFixExpr(pFix, pStep->pWhere) ){ 284f26e09c8Sdrh return 1; 285f26e09c8Sdrh } 286f26e09c8Sdrh if( sqliteFixExprList(pFix, pStep->pExprList) ){ 287f26e09c8Sdrh return 1; 288f26e09c8Sdrh } 289f26e09c8Sdrh pStep = pStep->pNext; 290f26e09c8Sdrh } 291f26e09c8Sdrh return 0; 292f26e09c8Sdrh } 293