1 /* 2 ** 2003 April 6 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** This file contains code used to implement the ATTACH and DETACH commands. 13 ** 14 ** $Id: attach.c,v 1.7 2003/06/14 12:04:08 drh Exp $ 15 */ 16 #include "sqliteInt.h" 17 18 /* 19 ** This routine is called by the parser to process an ATTACH statement: 20 ** 21 ** ATTACH DATABASE filename AS dbname 22 ** 23 ** The pFilename and pDbname arguments are the tokens that define the 24 ** filename and dbname in the ATTACH statement. 25 */ 26 void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){ 27 Db *aNew; 28 int rc, i; 29 char *zFile, *zName; 30 sqlite *db; 31 32 if( pParse->explain ) return; 33 db = pParse->db; 34 if( db->file_format<4 ){ 35 sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an " 36 "older format master database", 0); 37 pParse->rc = SQLITE_ERROR; 38 return; 39 } 40 if( db->nDb>=MAX_ATTACHED+2 ){ 41 sqliteErrorMsg(pParse, "too many attached databases - max %d", 42 MAX_ATTACHED); 43 pParse->rc = SQLITE_ERROR; 44 return; 45 } 46 47 zFile = 0; 48 sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0); 49 if( zFile==0 ) return; 50 sqliteDequote(zFile); 51 #ifndef SQLITE_OMIT_AUTHORIZATION 52 if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){ 53 sqliteFree(zFile); 54 return; 55 } 56 #endif /* SQLITE_OMIT_AUTHORIZATION */ 57 58 zName = 0; 59 sqliteSetNString(&zName, pDbname->z, pDbname->n, 0); 60 if( zName==0 ) return; 61 sqliteDequote(zName); 62 for(i=0; i<db->nDb; i++){ 63 if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){ 64 sqliteErrorMsg(pParse, "database %z is already in use", zName); 65 pParse->rc = SQLITE_ERROR; 66 sqliteFree(zFile); 67 return; 68 } 69 } 70 71 if( db->aDb==db->aDbStatic ){ 72 aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); 73 if( aNew==0 ) return; 74 memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); 75 }else{ 76 aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); 77 if( aNew==0 ) return; 78 } 79 db->aDb = aNew; 80 aNew = &db->aDb[db->nDb++]; 81 memset(aNew, 0, sizeof(*aNew)); 82 sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0); 83 sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); 84 sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); 85 sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); 86 aNew->zName = zName; 87 rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); 88 if( rc ){ 89 sqliteErrorMsg(pParse, "unable to open database: %s", zFile); 90 } 91 sqliteFree(zFile); 92 db->flags &= ~SQLITE_Initialized; 93 if( pParse->nErr ) return; 94 rc = sqliteInit(pParse->db, &pParse->zErrMsg); 95 if( rc ){ 96 sqliteResetInternalSchema(db, 0); 97 pParse->nErr++; 98 pParse->rc = SQLITE_ERROR; 99 } 100 } 101 102 /* 103 ** This routine is called by the parser to process a DETACH statement: 104 ** 105 ** DETACH DATABASE dbname 106 ** 107 ** The pDbname argument is the name of the database in the DETACH statement. 108 */ 109 void sqliteDetach(Parse *pParse, Token *pDbname){ 110 int i; 111 sqlite *db; 112 113 if( pParse->explain ) return; 114 db = pParse->db; 115 for(i=0; i<db->nDb; i++){ 116 if( db->aDb[i].pBt==0 || db->aDb[i].zName==0 ) continue; 117 if( strlen(db->aDb[i].zName)!=pDbname->n ) continue; 118 if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break; 119 } 120 if( i>=db->nDb ){ 121 sqliteErrorMsg(pParse, "no such database: %T", pDbname); 122 return; 123 } 124 if( i<2 ){ 125 sqliteErrorMsg(pParse, "cannot detach database %T", pDbname); 126 return; 127 } 128 #ifndef SQLITE_OMIT_AUTHORIZATION 129 if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){ 130 return; 131 } 132 #endif /* SQLITE_OMIT_AUTHORIZATION */ 133 sqliteBtreeClose(db->aDb[i].pBt); 134 db->aDb[i].pBt = 0; 135 sqliteFree(db->aDb[i].zName); 136 sqliteResetInternalSchema(db, i); 137 db->nDb--; 138 if( i<db->nDb ){ 139 db->aDb[i] = db->aDb[db->nDb]; 140 memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0])); 141 sqliteResetInternalSchema(db, i); 142 } 143 } 144 145 /* 146 ** Initialize a DbFixer structure. This routine must be called prior 147 ** to passing the structure to one of the sqliteFixAAAA() routines below. 148 ** 149 ** The return value indicates whether or not fixation is required. TRUE 150 ** means we do need to fix the database references, FALSE means we do not. 151 */ 152 int sqliteFixInit( 153 DbFixer *pFix, /* The fixer to be initialized */ 154 Parse *pParse, /* Error messages will be written here */ 155 int iDb, /* This is the database that must must be used */ 156 const char *zType, /* "view", "trigger", or "index" */ 157 const Token *pName /* Name of the view, trigger, or index */ 158 ){ 159 sqlite *db; 160 161 if( iDb<0 || iDb==1 ) return 0; 162 db = pParse->db; 163 assert( db->nDb>iDb ); 164 pFix->pParse = pParse; 165 pFix->zDb = db->aDb[iDb].zName; 166 pFix->zType = zType; 167 pFix->pName = pName; 168 return 1; 169 } 170 171 /* 172 ** The following set of routines walk through the parse tree and assign 173 ** a specific database to all table references where the database name 174 ** was left unspecified in the original SQL statement. The pFix structure 175 ** must have been initialized by a prior call to sqliteFixInit(). 176 ** 177 ** These routines are used to make sure that an index, trigger, or 178 ** view in one database does not refer to objects in a different database. 179 ** (Exception: indices, triggers, and views in the TEMP database are 180 ** allowed to refer to anything.) If a reference is explicitly made 181 ** to an object in a different database, an error message is added to 182 ** pParse->zErrMsg and these routines return non-zero. If everything 183 ** checks out, these routines return 0. 184 */ 185 int sqliteFixSrcList( 186 DbFixer *pFix, /* Context of the fixation */ 187 SrcList *pList /* The Source list to check and modify */ 188 ){ 189 int i; 190 const char *zDb; 191 192 if( pList==0 ) return 0; 193 zDb = pFix->zDb; 194 for(i=0; i<pList->nSrc; i++){ 195 if( pList->a[i].zDatabase==0 ){ 196 pList->a[i].zDatabase = sqliteStrDup(zDb); 197 }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){ 198 sqliteErrorMsg(pFix->pParse, 199 "%s %z cannot reference objects in database %s", 200 pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n), 201 pList->a[i].zDatabase); 202 return 1; 203 } 204 if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1; 205 if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1; 206 } 207 return 0; 208 } 209 int sqliteFixSelect( 210 DbFixer *pFix, /* Context of the fixation */ 211 Select *pSelect /* The SELECT statement to be fixed to one database */ 212 ){ 213 while( pSelect ){ 214 if( sqliteFixExprList(pFix, pSelect->pEList) ){ 215 return 1; 216 } 217 if( sqliteFixSrcList(pFix, pSelect->pSrc) ){ 218 return 1; 219 } 220 if( sqliteFixExpr(pFix, pSelect->pWhere) ){ 221 return 1; 222 } 223 if( sqliteFixExpr(pFix, pSelect->pHaving) ){ 224 return 1; 225 } 226 pSelect = pSelect->pPrior; 227 } 228 return 0; 229 } 230 int sqliteFixExpr( 231 DbFixer *pFix, /* Context of the fixation */ 232 Expr *pExpr /* The expression to be fixed to one database */ 233 ){ 234 while( pExpr ){ 235 if( sqliteFixSelect(pFix, pExpr->pSelect) ){ 236 return 1; 237 } 238 if( sqliteFixExprList(pFix, pExpr->pList) ){ 239 return 1; 240 } 241 if( sqliteFixExpr(pFix, pExpr->pRight) ){ 242 return 1; 243 } 244 pExpr = pExpr->pLeft; 245 } 246 return 0; 247 } 248 int sqliteFixExprList( 249 DbFixer *pFix, /* Context of the fixation */ 250 ExprList *pList /* The expression to be fixed to one database */ 251 ){ 252 int i; 253 if( pList==0 ) return 0; 254 for(i=0; i<pList->nExpr; i++){ 255 if( sqliteFixExpr(pFix, pList->a[i].pExpr) ){ 256 return 1; 257 } 258 } 259 return 0; 260 } 261 int sqliteFixTriggerStep( 262 DbFixer *pFix, /* Context of the fixation */ 263 TriggerStep *pStep /* The trigger step be fixed to one database */ 264 ){ 265 while( pStep ){ 266 if( sqliteFixSelect(pFix, pStep->pSelect) ){ 267 return 1; 268 } 269 if( sqliteFixExpr(pFix, pStep->pWhere) ){ 270 return 1; 271 } 272 if( sqliteFixExprList(pFix, pStep->pExprList) ){ 273 return 1; 274 } 275 pStep = pStep->pNext; 276 } 277 return 0; 278 } 279