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