[205] | 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 | */
|
---|
| 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 | }
|
---|