Back to index

php5  5.3.10
attach.c
Go to the documentation of this file.
00001 /*
00002 ** 2003 April 6
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** This file contains code used to implement the ATTACH and DETACH commands.
00013 **
00014 ** $Id: attach.c 195361 2005-09-07 15:11:33Z iliaa $
00015 */
00016 #include "sqliteInt.h"
00017 
00018 /*
00019 ** This routine is called by the parser to process an ATTACH statement:
00020 **
00021 **     ATTACH DATABASE filename AS dbname
00022 **
00023 ** The pFilename and pDbname arguments are the tokens that define the
00024 ** filename and dbname in the ATTACH statement.
00025 */
00026 void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){
00027   Db *aNew;
00028   int rc, i;
00029   char *zFile, *zName;
00030   sqlite *db;
00031   Vdbe *v;
00032 
00033   v = sqliteGetVdbe(pParse);
00034   sqliteVdbeAddOp(v, OP_Halt, 0, 0);
00035   if( pParse->explain ) return;
00036   db = pParse->db;
00037   if( db->file_format<4 ){
00038     sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an "
00039        "older format master database", 0);
00040     pParse->rc = SQLITE_ERROR;
00041     return;
00042   }
00043   if( db->nDb>=MAX_ATTACHED+2 ){
00044     sqliteErrorMsg(pParse, "too many attached databases - max %d", 
00045        MAX_ATTACHED);
00046     pParse->rc = SQLITE_ERROR;
00047     return;
00048   }
00049 
00050   zFile = 0;
00051   sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
00052   if( zFile==0 ) return;
00053   sqliteDequote(zFile);
00054 #ifndef SQLITE_OMIT_AUTHORIZATION
00055   if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){
00056     sqliteFree(zFile);
00057     return;
00058   }
00059 #endif /* SQLITE_OMIT_AUTHORIZATION */
00060 
00061   zName = 0;
00062   sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
00063   if( zName==0 ) return;
00064   sqliteDequote(zName);
00065   for(i=0; i<db->nDb; i++){
00066     if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
00067       sqliteErrorMsg(pParse, "database %z is already in use", zName);
00068       pParse->rc = SQLITE_ERROR;
00069       sqliteFree(zFile);
00070       return;
00071     }
00072   }
00073 
00074   if( db->aDb==db->aDbStatic ){
00075     aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
00076     if( aNew==0 ) return;
00077     memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
00078   }else{
00079     aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
00080     if( aNew==0 ) return;
00081   }
00082   db->aDb = aNew;
00083   aNew = &db->aDb[db->nDb++];
00084   memset(aNew, 0, sizeof(*aNew));
00085   sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
00086   sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
00087   sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
00088   sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
00089   aNew->zName = zName;
00090   rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
00091   if( rc ){
00092     sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
00093   }
00094 #if SQLITE_HAS_CODEC
00095   {
00096     extern int sqliteCodecAttach(sqlite*, int, void*, int);
00097     char *zKey = 0;
00098     int nKey;
00099     if( pKey && pKey->z && pKey->n ){
00100       sqliteSetNString(&zKey, pKey->z, pKey->n, 0);
00101       sqliteDequote(zKey);
00102       nKey = strlen(zKey);
00103     }else{
00104       zKey = 0;
00105       nKey = 0;
00106     }
00107     sqliteCodecAttach(db, db->nDb-1, zKey, nKey);
00108   }
00109 #endif
00110   sqliteFree(zFile);
00111   db->flags &= ~SQLITE_Initialized;
00112   if( pParse->nErr ) return;
00113   if( rc==SQLITE_OK ){
00114     rc = sqliteInit(pParse->db, &pParse->zErrMsg);
00115   }
00116   if( rc ){
00117     int i = db->nDb - 1;
00118     assert( i>=2 );
00119     if( db->aDb[i].pBt ){
00120       sqliteBtreeClose(db->aDb[i].pBt);
00121       db->aDb[i].pBt = 0;
00122     }
00123     sqliteResetInternalSchema(db, 0);
00124     pParse->nErr++;
00125     pParse->rc = SQLITE_ERROR;
00126   }
00127 }
00128 
00129 /*
00130 ** This routine is called by the parser to process a DETACH statement:
00131 **
00132 **    DETACH DATABASE dbname
00133 **
00134 ** The pDbname argument is the name of the database in the DETACH statement.
00135 */
00136 void sqliteDetach(Parse *pParse, Token *pDbname){
00137   int i;
00138   sqlite *db;
00139   Vdbe *v;
00140   Db *pDb;
00141 
00142   v = sqliteGetVdbe(pParse);
00143   sqliteVdbeAddOp(v, OP_Halt, 0, 0);
00144   if( pParse->explain ) return;
00145   db = pParse->db;
00146   for(i=0; i<db->nDb; i++){
00147     pDb = &db->aDb[i];
00148     if( pDb->pBt==0 || pDb->zName==0 ) continue;
00149     if( strlen(pDb->zName)!=pDbname->n ) continue;
00150     if( sqliteStrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break;
00151   }
00152   if( i>=db->nDb ){
00153     sqliteErrorMsg(pParse, "no such database: %T", pDbname);
00154     return;
00155   }
00156   if( i<2 ){
00157     sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
00158     return;
00159   }
00160 #ifndef SQLITE_OMIT_AUTHORIZATION
00161   if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){
00162     return;
00163   }
00164 #endif /* SQLITE_OMIT_AUTHORIZATION */
00165   sqliteBtreeClose(pDb->pBt);
00166   pDb->pBt = 0;
00167   sqliteFree(pDb->zName);
00168   sqliteResetInternalSchema(db, i);
00169   if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
00170   db->nDb--;
00171   if( i<db->nDb ){
00172     db->aDb[i] = db->aDb[db->nDb];
00173     memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
00174     sqliteResetInternalSchema(db, i);
00175   }
00176 }
00177 
00178 /*
00179 ** Initialize a DbFixer structure.  This routine must be called prior
00180 ** to passing the structure to one of the sqliteFixAAAA() routines below.
00181 **
00182 ** The return value indicates whether or not fixation is required.  TRUE
00183 ** means we do need to fix the database references, FALSE means we do not.
00184 */
00185 int sqliteFixInit(
00186   DbFixer *pFix,      /* The fixer to be initialized */
00187   Parse *pParse,      /* Error messages will be written here */
00188   int iDb,            /* This is the database that must must be used */
00189   const char *zType,  /* "view", "trigger", or "index" */
00190   const Token *pName  /* Name of the view, trigger, or index */
00191 ){
00192   sqlite *db;
00193 
00194   if( iDb<0 || iDb==1 ) return 0;
00195   db = pParse->db;
00196   assert( db->nDb>iDb );
00197   pFix->pParse = pParse;
00198   pFix->zDb = db->aDb[iDb].zName;
00199   pFix->zType = zType;
00200   pFix->pName = pName;
00201   return 1;
00202 }
00203 
00204 /*
00205 ** The following set of routines walk through the parse tree and assign
00206 ** a specific database to all table references where the database name
00207 ** was left unspecified in the original SQL statement.  The pFix structure
00208 ** must have been initialized by a prior call to sqliteFixInit().
00209 **
00210 ** These routines are used to make sure that an index, trigger, or
00211 ** view in one database does not refer to objects in a different database.
00212 ** (Exception: indices, triggers, and views in the TEMP database are
00213 ** allowed to refer to anything.)  If a reference is explicitly made
00214 ** to an object in a different database, an error message is added to
00215 ** pParse->zErrMsg and these routines return non-zero.  If everything
00216 ** checks out, these routines return 0.
00217 */
00218 int sqliteFixSrcList(
00219   DbFixer *pFix,       /* Context of the fixation */
00220   SrcList *pList       /* The Source list to check and modify */
00221 ){
00222   int i;
00223   const char *zDb;
00224 
00225   if( pList==0 ) return 0;
00226   zDb = pFix->zDb;
00227   for(i=0; i<pList->nSrc; i++){
00228     if( pList->a[i].zDatabase==0 ){
00229       pList->a[i].zDatabase = sqliteStrDup(zDb);
00230     }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){
00231       sqliteErrorMsg(pFix->pParse,
00232          "%s %z cannot reference objects in database %s",
00233          pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n),
00234          pList->a[i].zDatabase);
00235       return 1;
00236     }
00237     if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1;
00238     if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1;
00239   }
00240   return 0;
00241 }
00242 int sqliteFixSelect(
00243   DbFixer *pFix,       /* Context of the fixation */
00244   Select *pSelect      /* The SELECT statement to be fixed to one database */
00245 ){
00246   while( pSelect ){
00247     if( sqliteFixExprList(pFix, pSelect->pEList) ){
00248       return 1;
00249     }
00250     if( sqliteFixSrcList(pFix, pSelect->pSrc) ){
00251       return 1;
00252     }
00253     if( sqliteFixExpr(pFix, pSelect->pWhere) ){
00254       return 1;
00255     }
00256     if( sqliteFixExpr(pFix, pSelect->pHaving) ){
00257       return 1;
00258     }
00259     pSelect = pSelect->pPrior;
00260   }
00261   return 0;
00262 }
00263 int sqliteFixExpr(
00264   DbFixer *pFix,     /* Context of the fixation */
00265   Expr *pExpr        /* The expression to be fixed to one database */
00266 ){
00267   while( pExpr ){
00268     if( sqliteFixSelect(pFix, pExpr->pSelect) ){
00269       return 1;
00270     }
00271     if( sqliteFixExprList(pFix, pExpr->pList) ){
00272       return 1;
00273     }
00274     if( sqliteFixExpr(pFix, pExpr->pRight) ){
00275       return 1;
00276     }
00277     pExpr = pExpr->pLeft;
00278   }
00279   return 0;
00280 }
00281 int sqliteFixExprList(
00282   DbFixer *pFix,     /* Context of the fixation */
00283   ExprList *pList    /* The expression to be fixed to one database */
00284 ){
00285   int i;
00286   if( pList==0 ) return 0;
00287   for(i=0; i<pList->nExpr; i++){
00288     if( sqliteFixExpr(pFix, pList->a[i].pExpr) ){
00289       return 1;
00290     }
00291   }
00292   return 0;
00293 }
00294 int sqliteFixTriggerStep(
00295   DbFixer *pFix,     /* Context of the fixation */
00296   TriggerStep *pStep /* The trigger step be fixed to one database */
00297 ){
00298   while( pStep ){
00299     if( sqliteFixSelect(pFix, pStep->pSelect) ){
00300       return 1;
00301     }
00302     if( sqliteFixExpr(pFix, pStep->pWhere) ){
00303       return 1;
00304     }
00305     if( sqliteFixExprList(pFix, pStep->pExprList) ){
00306       return 1;
00307     }
00308     pStep = pStep->pNext;
00309   }
00310   return 0;
00311 }