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