Annotation of embedaddon/php/ext/sqlite/libsqlite/src/attach.c, revision 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>