xref: /sqlite-3.40.0/src/attach.c (revision 9bb575fd)
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*9bb575fdSdrh ** $Id: attach.c,v 1.28 2004/09/06 17:24:12 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 */
2625d6543dSdrh void sqlite3Attach(
2725d6543dSdrh   Parse *pParse,       /* The parser context */
2825d6543dSdrh   Token *pFilename,    /* Name of database file */
2925d6543dSdrh   Token *pDbname,      /* Name of the database to use internally */
3025d6543dSdrh   int keyType,         /* 0: no key.  1: TEXT,  2: BLOB */
31873cdcb2Sdrh   Token *pKey          /* Text of the key for keytype 1 and 2 */
3225d6543dSdrh ){
33c11d4f93Sdrh   Db *aNew;
34c11d4f93Sdrh   int rc, i;
35c11d4f93Sdrh   char *zFile, *zName;
36*9bb575fdSdrh   sqlite3 *db;
370bca3530Sdrh   Vdbe *v;
38c11d4f93Sdrh 
394adee20fSdanielk1977   v = sqlite3GetVdbe(pParse);
4096fb0dd5Sdanielk1977   if( !v ) return;
414adee20fSdanielk1977   sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
42c11d4f93Sdrh   if( pParse->explain ) return;
43c11d4f93Sdrh   db = pParse->db;
44c11d4f93Sdrh   if( db->nDb>=MAX_ATTACHED+2 ){
454adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "too many attached databases - max %d",
46c11d4f93Sdrh        MAX_ATTACHED);
47c11d4f93Sdrh     pParse->rc = SQLITE_ERROR;
48c11d4f93Sdrh     return;
49c11d4f93Sdrh   }
5081e293b4Sdrh 
5192f9a1bbSdanielk1977   if( !db->autoCommit ){
5292f9a1bbSdanielk1977     sqlite3ErrorMsg(pParse, "cannot ATTACH database within transaction");
5392f9a1bbSdanielk1977     pParse->rc = SQLITE_ERROR;
5492f9a1bbSdanielk1977     return;
5592f9a1bbSdanielk1977   }
5692f9a1bbSdanielk1977 
57a99db3b6Sdrh   zFile = sqlite3NameFromToken(pFilename);;
5881e293b4Sdrh   if( zFile==0 ) return;
5981e293b4Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION
604adee20fSdanielk1977   if( sqlite3AuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){
6181e293b4Sdrh     sqliteFree(zFile);
6281e293b4Sdrh     return;
6381e293b4Sdrh   }
6481e293b4Sdrh #endif /* SQLITE_OMIT_AUTHORIZATION */
6581e293b4Sdrh 
66a99db3b6Sdrh   zName = sqlite3NameFromToken(pDbname);
6781e293b4Sdrh   if( zName==0 ) return;
6881e293b4Sdrh   for(i=0; i<db->nDb; i++){
69124b27e6Sdrh     char *z = db->aDb[i].zName;
70124b27e6Sdrh     if( z && sqlite3StrICmp(z, zName)==0 ){
714adee20fSdanielk1977       sqlite3ErrorMsg(pParse, "database %z is already in use", zName);
7281e293b4Sdrh       pParse->rc = SQLITE_ERROR;
7381e293b4Sdrh       sqliteFree(zFile);
7481e293b4Sdrh       return;
7581e293b4Sdrh     }
7681e293b4Sdrh   }
7781e293b4Sdrh 
78c11d4f93Sdrh   if( db->aDb==db->aDbStatic ){
79c11d4f93Sdrh     aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
80c11d4f93Sdrh     if( aNew==0 ) return;
81c11d4f93Sdrh     memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
82c11d4f93Sdrh   }else{
83c11d4f93Sdrh     aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
84c11d4f93Sdrh     if( aNew==0 ) return;
85c11d4f93Sdrh   }
86c11d4f93Sdrh   db->aDb = aNew;
87c11d4f93Sdrh   aNew = &db->aDb[db->nDb++];
88c11d4f93Sdrh   memset(aNew, 0, sizeof(*aNew));
894adee20fSdanielk1977   sqlite3HashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
904adee20fSdanielk1977   sqlite3HashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
914adee20fSdanielk1977   sqlite3HashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
924adee20fSdanielk1977   sqlite3HashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
93c11d4f93Sdrh   aNew->zName = zName;
9491cf71b0Sdanielk1977   aNew->safety_level = 3;
954adee20fSdanielk1977   rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
96c11d4f93Sdrh   if( rc ){
974adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "unable to open database: %s", zFile);
98c11d4f93Sdrh   }
994d189ca4Sdrh #if SQLITE_HAS_CODEC
10025d6543dSdrh   {
10125d6543dSdrh     extern int sqlite3CodecAttach(sqlite3*, int, void*, int);
10225d6543dSdrh     char *zKey;
1034d189ca4Sdrh     int nKey;
10425d6543dSdrh     if( keyType==0 ){
10525d6543dSdrh       /* No key specified.  Use the key from the main database */
10625d6543dSdrh       extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
10725d6543dSdrh       sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
10825d6543dSdrh     }else if( keyType==1 ){
10925d6543dSdrh       /* Key specified as text */
11090f5ecb3Sdrh       zKey = sqlite3NameFromToken(pKey);
1114d189ca4Sdrh       nKey = strlen(zKey);
11225d6543dSdrh     }else{
11325d6543dSdrh       /* Key specified as a BLOB */
11425d6543dSdrh       char *zTemp;
11525d6543dSdrh       assert( keyType==2 );
11625d6543dSdrh       pKey->z++;
11725d6543dSdrh       pKey->n--;
11825d6543dSdrh       zTemp = sqlite3NameFromToken(pKey);
11925d6543dSdrh       zKey = sqlite3HexToBlob(zTemp);
12025d6543dSdrh       sqliteFree(zTemp);
12125d6543dSdrh     }
12225d6543dSdrh     sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
12325d6543dSdrh     if( keyType ){
12425d6543dSdrh       sqliteFree(zKey);
12525d6543dSdrh     }
1264d189ca4Sdrh   }
1274d189ca4Sdrh #endif
128c11d4f93Sdrh   sqliteFree(zFile);
129c11d4f93Sdrh   db->flags &= ~SQLITE_Initialized;
130755b6ba9Sdrh   if( pParse->nErr==0 && rc==SQLITE_OK ){
1318a41449eSdanielk1977     rc = sqlite3ReadSchema(pParse);
132447623d9Sdrh   }
133c11d4f93Sdrh   if( rc ){
134447623d9Sdrh     int i = db->nDb - 1;
135447623d9Sdrh     assert( i>=2 );
136447623d9Sdrh     if( db->aDb[i].pBt ){
1374adee20fSdanielk1977       sqlite3BtreeClose(db->aDb[i].pBt);
138447623d9Sdrh       db->aDb[i].pBt = 0;
139447623d9Sdrh     }
1404adee20fSdanielk1977     sqlite3ResetInternalSchema(db, 0);
1418a41449eSdanielk1977     if( 0==pParse->nErr ){
142c11d4f93Sdrh       pParse->nErr++;
143c11d4f93Sdrh       pParse->rc = SQLITE_ERROR;
144c11d4f93Sdrh     }
145c11d4f93Sdrh   }
1468a41449eSdanielk1977 }
147c11d4f93Sdrh 
148c11d4f93Sdrh /*
149c11d4f93Sdrh ** This routine is called by the parser to process a DETACH statement:
150c11d4f93Sdrh **
151c11d4f93Sdrh **    DETACH DATABASE dbname
152c11d4f93Sdrh **
153c11d4f93Sdrh ** The pDbname argument is the name of the database in the DETACH statement.
154c11d4f93Sdrh */
1554adee20fSdanielk1977 void sqlite3Detach(Parse *pParse, Token *pDbname){
156c11d4f93Sdrh   int i;
157*9bb575fdSdrh   sqlite3 *db;
1580bca3530Sdrh   Vdbe *v;
159e0d4b060Sdanielk1977   Db *pDb = 0;
160c11d4f93Sdrh 
1614adee20fSdanielk1977   v = sqlite3GetVdbe(pParse);
16296fb0dd5Sdanielk1977   if( !v ) return;
1634adee20fSdanielk1977   sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
164c11d4f93Sdrh   if( pParse->explain ) return;
165c11d4f93Sdrh   db = pParse->db;
166c11d4f93Sdrh   for(i=0; i<db->nDb; i++){
167124b27e6Sdrh     pDb = &db->aDb[i];
168124b27e6Sdrh     if( pDb->pBt==0 || pDb->zName==0 ) continue;
169124b27e6Sdrh     if( strlen(pDb->zName)!=pDbname->n ) continue;
170124b27e6Sdrh     if( sqlite3StrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break;
171c11d4f93Sdrh   }
172c11d4f93Sdrh   if( i>=db->nDb ){
1734adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "no such database: %T", pDbname);
174c11d4f93Sdrh     return;
175c11d4f93Sdrh   }
176c11d4f93Sdrh   if( i<2 ){
1774adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "cannot detach database %T", pDbname);
178c11d4f93Sdrh     return;
179c11d4f93Sdrh   }
18092f9a1bbSdanielk1977   if( !db->autoCommit ){
18192f9a1bbSdanielk1977     sqlite3ErrorMsg(pParse, "cannot DETACH database within transaction");
18292f9a1bbSdanielk1977     pParse->rc = SQLITE_ERROR;
18392f9a1bbSdanielk1977     return;
18492f9a1bbSdanielk1977   }
18581e293b4Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION
1864adee20fSdanielk1977   if( sqlite3AuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){
18781e293b4Sdrh     return;
18881e293b4Sdrh   }
18981e293b4Sdrh #endif /* SQLITE_OMIT_AUTHORIZATION */
190124b27e6Sdrh   sqlite3BtreeClose(pDb->pBt);
191124b27e6Sdrh   pDb->pBt = 0;
192db2d9a0bSdrh   sqlite3ResetInternalSchema(db, 0);
193c11d4f93Sdrh }
194f26e09c8Sdrh 
195f26e09c8Sdrh /*
196f26e09c8Sdrh ** Initialize a DbFixer structure.  This routine must be called prior
197f26e09c8Sdrh ** to passing the structure to one of the sqliteFixAAAA() routines below.
198f26e09c8Sdrh **
199f26e09c8Sdrh ** The return value indicates whether or not fixation is required.  TRUE
200f26e09c8Sdrh ** means we do need to fix the database references, FALSE means we do not.
201f26e09c8Sdrh */
2024adee20fSdanielk1977 int sqlite3FixInit(
203f26e09c8Sdrh   DbFixer *pFix,      /* The fixer to be initialized */
204f26e09c8Sdrh   Parse *pParse,      /* Error messages will be written here */
205873cdcb2Sdrh   int iDb,            /* This is the database that must be used */
206f26e09c8Sdrh   const char *zType,  /* "view", "trigger", or "index" */
207f26e09c8Sdrh   const Token *pName  /* Name of the view, trigger, or index */
208f26e09c8Sdrh ){
209*9bb575fdSdrh   sqlite3 *db;
210f26e09c8Sdrh 
211f26e09c8Sdrh   if( iDb<0 || iDb==1 ) return 0;
212f26e09c8Sdrh   db = pParse->db;
213f26e09c8Sdrh   assert( db->nDb>iDb );
2144312db55Sdrh   pFix->pParse = pParse;
215f26e09c8Sdrh   pFix->zDb = db->aDb[iDb].zName;
216f26e09c8Sdrh   pFix->zType = zType;
217f26e09c8Sdrh   pFix->pName = pName;
218f26e09c8Sdrh   return 1;
219f26e09c8Sdrh }
220f26e09c8Sdrh 
221f26e09c8Sdrh /*
222f26e09c8Sdrh ** The following set of routines walk through the parse tree and assign
223f26e09c8Sdrh ** a specific database to all table references where the database name
224f26e09c8Sdrh ** was left unspecified in the original SQL statement.  The pFix structure
2254adee20fSdanielk1977 ** must have been initialized by a prior call to sqlite3FixInit().
226f26e09c8Sdrh **
227f26e09c8Sdrh ** These routines are used to make sure that an index, trigger, or
228f26e09c8Sdrh ** view in one database does not refer to objects in a different database.
229f26e09c8Sdrh ** (Exception: indices, triggers, and views in the TEMP database are
230f26e09c8Sdrh ** allowed to refer to anything.)  If a reference is explicitly made
231f26e09c8Sdrh ** to an object in a different database, an error message is added to
232f26e09c8Sdrh ** pParse->zErrMsg and these routines return non-zero.  If everything
233f26e09c8Sdrh ** checks out, these routines return 0.
234f26e09c8Sdrh */
2354adee20fSdanielk1977 int sqlite3FixSrcList(
236f26e09c8Sdrh   DbFixer *pFix,       /* Context of the fixation */
237f26e09c8Sdrh   SrcList *pList       /* The Source list to check and modify */
238f26e09c8Sdrh ){
239f26e09c8Sdrh   int i;
240f26e09c8Sdrh   const char *zDb;
241873cdcb2Sdrh   struct SrcList_item *pItem;
242f26e09c8Sdrh 
243f26e09c8Sdrh   if( pList==0 ) return 0;
244f26e09c8Sdrh   zDb = pFix->zDb;
245873cdcb2Sdrh   for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
246873cdcb2Sdrh     if( pItem->zDatabase==0 ){
247873cdcb2Sdrh       pItem->zDatabase = sqliteStrDup(zDb);
248873cdcb2Sdrh     }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
2494adee20fSdanielk1977       sqlite3ErrorMsg(pFix->pParse,
250873cdcb2Sdrh          "%s %T cannot reference objects in database %s",
251873cdcb2Sdrh          pFix->zType, pFix->pName, pItem->zDatabase);
252f26e09c8Sdrh       return 1;
253f26e09c8Sdrh     }
254873cdcb2Sdrh     if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
255873cdcb2Sdrh     if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
256f26e09c8Sdrh   }
257f26e09c8Sdrh   return 0;
258f26e09c8Sdrh }
2594adee20fSdanielk1977 int sqlite3FixSelect(
260f26e09c8Sdrh   DbFixer *pFix,       /* Context of the fixation */
261f26e09c8Sdrh   Select *pSelect      /* The SELECT statement to be fixed to one database */
262f26e09c8Sdrh ){
263f26e09c8Sdrh   while( pSelect ){
2644adee20fSdanielk1977     if( sqlite3FixExprList(pFix, pSelect->pEList) ){
265f26e09c8Sdrh       return 1;
266f26e09c8Sdrh     }
2674adee20fSdanielk1977     if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
268f26e09c8Sdrh       return 1;
269f26e09c8Sdrh     }
2704adee20fSdanielk1977     if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
271f26e09c8Sdrh       return 1;
272f26e09c8Sdrh     }
2734adee20fSdanielk1977     if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
274f26e09c8Sdrh       return 1;
275f26e09c8Sdrh     }
276f26e09c8Sdrh     pSelect = pSelect->pPrior;
277f26e09c8Sdrh   }
278f26e09c8Sdrh   return 0;
279f26e09c8Sdrh }
2804adee20fSdanielk1977 int sqlite3FixExpr(
281f26e09c8Sdrh   DbFixer *pFix,     /* Context of the fixation */
282f26e09c8Sdrh   Expr *pExpr        /* The expression to be fixed to one database */
283f26e09c8Sdrh ){
284f26e09c8Sdrh   while( pExpr ){
2854adee20fSdanielk1977     if( sqlite3FixSelect(pFix, pExpr->pSelect) ){
286f26e09c8Sdrh       return 1;
287f26e09c8Sdrh     }
2884adee20fSdanielk1977     if( sqlite3FixExprList(pFix, pExpr->pList) ){
289f26e09c8Sdrh       return 1;
290f26e09c8Sdrh     }
2914adee20fSdanielk1977     if( sqlite3FixExpr(pFix, pExpr->pRight) ){
292f26e09c8Sdrh       return 1;
293f26e09c8Sdrh     }
294f26e09c8Sdrh     pExpr = pExpr->pLeft;
295f26e09c8Sdrh   }
296f26e09c8Sdrh   return 0;
297f26e09c8Sdrh }
2984adee20fSdanielk1977 int sqlite3FixExprList(
299f26e09c8Sdrh   DbFixer *pFix,     /* Context of the fixation */
300f26e09c8Sdrh   ExprList *pList    /* The expression to be fixed to one database */
301f26e09c8Sdrh ){
302f26e09c8Sdrh   int i;
303873cdcb2Sdrh   struct ExprList_item *pItem;
304f26e09c8Sdrh   if( pList==0 ) return 0;
305873cdcb2Sdrh   for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
306873cdcb2Sdrh     if( sqlite3FixExpr(pFix, pItem->pExpr) ){
307f26e09c8Sdrh       return 1;
308f26e09c8Sdrh     }
309f26e09c8Sdrh   }
310f26e09c8Sdrh   return 0;
311f26e09c8Sdrh }
3124adee20fSdanielk1977 int sqlite3FixTriggerStep(
313f26e09c8Sdrh   DbFixer *pFix,     /* Context of the fixation */
314f26e09c8Sdrh   TriggerStep *pStep /* The trigger step be fixed to one database */
315f26e09c8Sdrh ){
316f26e09c8Sdrh   while( pStep ){
3174adee20fSdanielk1977     if( sqlite3FixSelect(pFix, pStep->pSelect) ){
318f26e09c8Sdrh       return 1;
319f26e09c8Sdrh     }
3204adee20fSdanielk1977     if( sqlite3FixExpr(pFix, pStep->pWhere) ){
321f26e09c8Sdrh       return 1;
322f26e09c8Sdrh     }
3234adee20fSdanielk1977     if( sqlite3FixExprList(pFix, pStep->pExprList) ){
324f26e09c8Sdrh       return 1;
325f26e09c8Sdrh     }
326f26e09c8Sdrh     pStep = pStep->pNext;
327f26e09c8Sdrh   }
328f26e09c8Sdrh   return 0;
329f26e09c8Sdrh }
330