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>