Annotation of embedaddon/php/ext/sqlite/libsqlite/src/attach.c, revision 1.1.1.1
1.1 misho 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 195361 2005-09-07 15:11:33Z iliaa $
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, 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: */
136: void 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: */
185: int 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: */
218: int 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: }
242: int 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: }
263: int 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: }
281: int 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: }
294: int 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>