source: trunk/src/3rdparty/sqlite/attach.c@ 205

Last change on this file since 205 was 205, checked in by rudi, 14 years ago

Added SQLite 2.8.17 sources. This allows to build at least one of the sql drivers / plugins.

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