xref: /sqlite-3.40.0/src/attach.c (revision 96fb0dd5)
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