PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - pdo_sqlite/sqlite/src - attach.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 197
Code covered: 2.0 % Executed lines: 4
Legend: not executed executed

       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$
      15                 : */
      16                 : #include "sqliteInt.h"
      17                 : 
      18                 : #ifndef SQLITE_OMIT_ATTACH
      19                 : /*
      20                 : ** Resolve an expression that was part of an ATTACH or DETACH statement. This
      21                 : ** is slightly different from resolving a normal SQL expression, because simple
      22                 : ** identifiers are treated as strings, not possible column names or aliases.
      23                 : **
      24                 : ** i.e. if the parser sees:
      25                 : **
      26                 : **     ATTACH DATABASE abc AS def
      27                 : **
      28                 : ** it treats the two expressions as literal strings 'abc' and 'def' instead of
      29                 : ** looking for columns of the same name.
      30                 : **
      31                 : ** This only applies to the root node of pExpr, so the statement:
      32                 : **
      33                 : **     ATTACH DATABASE abc||def AS 'db2'
      34                 : **
      35                 : ** will fail because neither abc or def can be resolved.
      36                 : */
      37                 : static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
      38               0 : {
      39               0 :   int rc = SQLITE_OK;
      40               0 :   if( pExpr ){
      41               0 :     if( pExpr->op!=TK_ID ){
      42               0 :       rc = sqlite3ExprResolveNames(pName, pExpr);
      43                 :     }else{
      44               0 :       pExpr->op = TK_STRING;
      45                 :     }
      46                 :   }
      47               0 :   return rc;
      48                 : }
      49                 : 
      50                 : /*
      51                 : ** An SQL user-function registered to do the work of an ATTACH statement. The
      52                 : ** three arguments to the function come directly from an attach statement:
      53                 : **
      54                 : **     ATTACH DATABASE x AS y KEY z
      55                 : **
      56                 : **     SELECT sqlite_attach(x, y, z)
      57                 : **
      58                 : ** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
      59                 : ** third argument.
      60                 : */
      61                 : static void attachFunc(
      62                 :   sqlite3_context *context,
      63                 :   int argc,
      64                 :   sqlite3_value **argv
      65               0 : ){
      66                 :   int i;
      67               0 :   int rc = 0;
      68               0 :   sqlite3 *db = sqlite3_user_data(context);
      69                 :   const char *zName;
      70                 :   const char *zFile;
      71                 :   Db *aNew;
      72                 :   char zErr[128];
      73               0 :   char *zErrDyn = 0;
      74                 : 
      75               0 :   zFile = (const char *)sqlite3_value_text(argv[0]);
      76               0 :   zName = (const char *)sqlite3_value_text(argv[1]);
      77               0 :   if( zFile==0 ) zFile = "";
      78               0 :   if( zName==0 ) zName = "";
      79                 : 
      80                 :   /* Check for the following errors:
      81                 :   **
      82                 :   **     * Too many attached databases,
      83                 :   **     * Transaction currently open
      84                 :   **     * Specified database name already being used.
      85                 :   */
      86               0 :   if( db->nDb>=MAX_ATTACHED+2 ){
      87               0 :     sqlite3_snprintf(
      88                 :       sizeof(zErr), zErr, "too many attached databases - max %d", MAX_ATTACHED
      89                 :     );
      90               0 :     goto attach_error;
      91                 :   }
      92               0 :   if( !db->autoCommit ){
      93               0 :     strcpy(zErr, "cannot ATTACH database within transaction");
      94               0 :     goto attach_error;
      95                 :   }
      96               0 :   for(i=0; i<db->nDb; i++){
      97               0 :     char *z = db->aDb[i].zName;
      98               0 :     if( z && zName && sqlite3StrICmp(z, zName)==0 ){
      99               0 :       sqlite3_snprintf(sizeof(zErr), zErr, "database %s is already in use", zName);
     100               0 :       goto attach_error;
     101                 :     }
     102                 :   }
     103                 : 
     104                 :   /* Allocate the new entry in the db->aDb[] array and initialise the schema
     105                 :   ** hash tables.
     106                 :   */
     107               0 :   if( db->aDb==db->aDbStatic ){
     108               0 :     aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
     109               0 :     if( aNew==0 ){
     110               0 :       return;
     111                 :     }
     112               0 :     memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
     113                 :   }else{
     114               0 :     aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
     115               0 :     if( aNew==0 ){
     116               0 :       return;
     117                 :     } 
     118                 :   }
     119               0 :   db->aDb = aNew;
     120               0 :   aNew = &db->aDb[db->nDb++];
     121               0 :   memset(aNew, 0, sizeof(*aNew));
     122                 : 
     123                 :   /* Open the database file. If the btree is successfully opened, use
     124                 :   ** it to obtain the database schema. At this point the schema may
     125                 :   ** or may not be initialised.
     126                 :   */
     127               0 :   rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
     128               0 :   if( rc==SQLITE_OK ){
     129               0 :     aNew->pSchema = sqlite3SchemaGet(aNew->pBt);
     130               0 :     if( !aNew->pSchema ){
     131               0 :       rc = SQLITE_NOMEM;
     132               0 :     }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
     133               0 :       strcpy(zErr, 
     134                 :         "attached databases must use the same text encoding as main database");
     135               0 :       goto attach_error;
     136                 :     }
     137               0 :     sqlite3PagerLockingMode(sqlite3BtreePager(aNew->pBt), db->dfltLockMode);
     138                 :   }
     139               0 :   aNew->zName = sqliteStrDup(zName);
     140               0 :   aNew->safety_level = 3;
     141                 : 
     142                 : #if SQLITE_HAS_CODEC
     143                 :   {
     144                 :     extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
     145                 :     extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
     146                 :     int nKey;
     147                 :     char *zKey;
     148                 :     int t = sqlite3_value_type(argv[2]);
     149                 :     switch( t ){
     150                 :       case SQLITE_INTEGER:
     151                 :       case SQLITE_FLOAT:
     152                 :         zErrDyn = sqliteStrDup("Invalid key value");
     153                 :         rc = SQLITE_ERROR;
     154                 :         break;
     155                 :         
     156                 :       case SQLITE_TEXT:
     157                 :       case SQLITE_BLOB:
     158                 :         nKey = sqlite3_value_bytes(argv[2]);
     159                 :         zKey = (char *)sqlite3_value_blob(argv[2]);
     160                 :         sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
     161                 :         break;
     162                 : 
     163                 :       case SQLITE_NULL:
     164                 :         /* No key specified.  Use the key from the main database */
     165                 :         sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
     166                 :         sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
     167                 :         break;
     168                 :     }
     169                 :   }
     170                 : #endif
     171                 : 
     172                 :   /* If the file was opened successfully, read the schema for the new database.
     173                 :   ** If this fails, or if opening the file failed, then close the file and 
     174                 :   ** remove the entry from the db->aDb[] array. i.e. put everything back the way
     175                 :   ** we found it.
     176                 :   */
     177               0 :   if( rc==SQLITE_OK ){
     178               0 :     sqlite3SafetyOn(db);
     179               0 :     rc = sqlite3Init(db, &zErrDyn);
     180               0 :     sqlite3SafetyOff(db);
     181                 :   }
     182               0 :   if( rc ){
     183               0 :     int iDb = db->nDb - 1;
     184                 :     assert( iDb>=2 );
     185               0 :     if( db->aDb[iDb].pBt ){
     186               0 :       sqlite3BtreeClose(db->aDb[iDb].pBt);
     187               0 :       db->aDb[iDb].pBt = 0;
     188               0 :       db->aDb[iDb].pSchema = 0;
     189                 :     }
     190               0 :     sqlite3ResetInternalSchema(db, 0);
     191               0 :     db->nDb = iDb;
     192               0 :     if( rc==SQLITE_NOMEM ){
     193               0 :       sqlite3FailedMalloc();
     194               0 :       sqlite3_snprintf(sizeof(zErr),zErr, "out of memory");
     195                 :     }else{
     196               0 :       sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);
     197                 :     }
     198               0 :     goto attach_error;
     199                 :   }
     200                 :   
     201               0 :   return;
     202                 : 
     203               0 : attach_error:
     204                 :   /* Return an error if we get here */
     205               0 :   if( zErrDyn ){
     206               0 :     sqlite3_result_error(context, zErrDyn, -1);
     207               0 :     sqliteFree(zErrDyn);
     208                 :   }else{
     209               0 :     zErr[sizeof(zErr)-1] = 0;
     210               0 :     sqlite3_result_error(context, zErr, -1);
     211                 :   }
     212                 : }
     213                 : 
     214                 : /*
     215                 : ** An SQL user-function registered to do the work of an DETACH statement. The
     216                 : ** three arguments to the function come directly from a detach statement:
     217                 : **
     218                 : **     DETACH DATABASE x
     219                 : **
     220                 : **     SELECT sqlite_detach(x)
     221                 : */
     222                 : static void detachFunc(
     223                 :   sqlite3_context *context,
     224                 :   int argc,
     225                 :   sqlite3_value **argv
     226               0 : ){
     227               0 :   const char *zName = (const char *)sqlite3_value_text(argv[0]);
     228               0 :   sqlite3 *db = sqlite3_user_data(context);
     229                 :   int i;
     230               0 :   Db *pDb = 0;
     231                 :   char zErr[128];
     232                 : 
     233               0 :   if( zName==0 ) zName = "";
     234               0 :   for(i=0; i<db->nDb; i++){
     235               0 :     pDb = &db->aDb[i];
     236               0 :     if( pDb->pBt==0 ) continue;
     237               0 :     if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
     238                 :   }
     239                 : 
     240               0 :   if( i>=db->nDb ){
     241               0 :     sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
     242               0 :     goto detach_error;
     243                 :   }
     244               0 :   if( i<2 ){
     245               0 :     sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
     246               0 :     goto detach_error;
     247                 :   }
     248               0 :   if( !db->autoCommit ){
     249               0 :     strcpy(zErr, "cannot DETACH database within transaction");
     250               0 :     goto detach_error;
     251                 :   }
     252               0 :   if( sqlite3BtreeIsInReadTrans(pDb->pBt) ){
     253               0 :     sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
     254               0 :     goto detach_error;
     255                 :   }
     256                 : 
     257               0 :   sqlite3BtreeClose(pDb->pBt);
     258               0 :   pDb->pBt = 0;
     259               0 :   pDb->pSchema = 0;
     260               0 :   sqlite3ResetInternalSchema(db, 0);
     261               0 :   return;
     262                 : 
     263               0 : detach_error:
     264               0 :   sqlite3_result_error(context, zErr, -1);
     265                 : }
     266                 : 
     267                 : /*
     268                 : ** This procedure generates VDBE code for a single invocation of either the
     269                 : ** sqlite_detach() or sqlite_attach() SQL user functions.
     270                 : */
     271                 : static void codeAttach(
     272                 :   Parse *pParse,       /* The parser context */
     273                 :   int type,            /* Either SQLITE_ATTACH or SQLITE_DETACH */
     274                 :   const char *zFunc,   /* Either "sqlite_attach" or "sqlite_detach */
     275                 :   int nFunc,           /* Number of args to pass to zFunc */
     276                 :   Expr *pAuthArg,      /* Expression to pass to authorization callback */
     277                 :   Expr *pFilename,     /* Name of database file */
     278                 :   Expr *pDbname,       /* Name of the database to use internally */
     279                 :   Expr *pKey           /* Database key for encryption extension */
     280               0 : ){
     281                 :   int rc;
     282                 :   NameContext sName;
     283                 :   Vdbe *v;
     284                 :   FuncDef *pFunc;
     285               0 :   sqlite3* db = pParse->db;
     286                 : 
     287                 : #ifndef SQLITE_OMIT_AUTHORIZATION
     288                 :   assert( sqlite3MallocFailed() || pAuthArg );
     289               0 :   if( pAuthArg ){
     290               0 :     char *zAuthArg = sqlite3NameFromToken(&pAuthArg->span);
     291               0 :     if( !zAuthArg ){
     292               0 :       goto attach_end;
     293                 :     }
     294               0 :     rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
     295               0 :     sqliteFree(zAuthArg);
     296               0 :     if(rc!=SQLITE_OK ){
     297               0 :       goto attach_end;
     298                 :     }
     299                 :   }
     300                 : #endif /* SQLITE_OMIT_AUTHORIZATION */
     301                 : 
     302               0 :   memset(&sName, 0, sizeof(NameContext));
     303               0 :   sName.pParse = pParse;
     304                 : 
     305               0 :   if( 
     306                 :       SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
     307                 :       SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
     308                 :       SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
     309                 :   ){
     310               0 :     pParse->nErr++;
     311               0 :     goto attach_end;
     312                 :   }
     313                 : 
     314               0 :   v = sqlite3GetVdbe(pParse);
     315               0 :   sqlite3ExprCode(pParse, pFilename);
     316               0 :   sqlite3ExprCode(pParse, pDbname);
     317               0 :   sqlite3ExprCode(pParse, pKey);
     318                 : 
     319                 :   assert( v || sqlite3MallocFailed() );
     320               0 :   if( v ){
     321               0 :     sqlite3VdbeAddOp(v, OP_Function, 0, nFunc);
     322               0 :     pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
     323               0 :     sqlite3VdbeChangeP3(v, -1, (char *)pFunc, P3_FUNCDEF);
     324                 : 
     325                 :     /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
     326                 :     ** statement only). For DETACH, set it to false (expire all existing
     327                 :     ** statements).
     328                 :     */
     329               0 :     sqlite3VdbeAddOp(v, OP_Expire, (type==SQLITE_ATTACH), 0);
     330                 :   }
     331                 :   
     332               0 : attach_end:
     333               0 :   sqlite3ExprDelete(pFilename);
     334               0 :   sqlite3ExprDelete(pDbname);
     335               0 :   sqlite3ExprDelete(pKey);
     336               0 : }
     337                 : 
     338                 : /*
     339                 : ** Called by the parser to compile a DETACH statement.
     340                 : **
     341                 : **     DETACH pDbname
     342                 : */
     343               0 : void sqlite3Detach(Parse *pParse, Expr *pDbname){
     344               0 :   codeAttach(pParse, SQLITE_DETACH, "sqlite_detach", 1, pDbname, 0, 0, pDbname);
     345               0 : }
     346                 : 
     347                 : /*
     348                 : ** Called by the parser to compile an ATTACH statement.
     349                 : **
     350                 : **     ATTACH p AS pDbname KEY pKey
     351                 : */
     352               0 : void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
     353               0 :   codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey);
     354               0 : }
     355                 : #endif /* SQLITE_OMIT_ATTACH */
     356                 : 
     357                 : /*
     358                 : ** Register the functions sqlite_attach and sqlite_detach.
     359                 : */
     360             130 : void sqlite3AttachFunctions(sqlite3 *db){
     361                 : #ifndef SQLITE_OMIT_ATTACH
     362                 :   static const int enc = SQLITE_UTF8;
     363             130 :   sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0);
     364             130 :   sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0);
     365                 : #endif
     366             130 : }
     367                 : 
     368                 : /*
     369                 : ** Initialize a DbFixer structure.  This routine must be called prior
     370                 : ** to passing the structure to one of the sqliteFixAAAA() routines below.
     371                 : **
     372                 : ** The return value indicates whether or not fixation is required.  TRUE
     373                 : ** means we do need to fix the database references, FALSE means we do not.
     374                 : */
     375                 : int sqlite3FixInit(
     376                 :   DbFixer *pFix,      /* The fixer to be initialized */
     377                 :   Parse *pParse,      /* Error messages will be written here */
     378                 :   int iDb,            /* This is the database that must be used */
     379                 :   const char *zType,  /* "view", "trigger", or "index" */
     380                 :   const Token *pName  /* Name of the view, trigger, or index */
     381               0 : ){
     382                 :   sqlite3 *db;
     383                 : 
     384               0 :   if( iDb<0 || iDb==1 ) return 0;
     385               0 :   db = pParse->db;
     386                 :   assert( db->nDb>iDb );
     387               0 :   pFix->pParse = pParse;
     388               0 :   pFix->zDb = db->aDb[iDb].zName;
     389               0 :   pFix->zType = zType;
     390               0 :   pFix->pName = pName;
     391               0 :   return 1;
     392                 : }
     393                 : 
     394                 : /*
     395                 : ** The following set of routines walk through the parse tree and assign
     396                 : ** a specific database to all table references where the database name
     397                 : ** was left unspecified in the original SQL statement.  The pFix structure
     398                 : ** must have been initialized by a prior call to sqlite3FixInit().
     399                 : **
     400                 : ** These routines are used to make sure that an index, trigger, or
     401                 : ** view in one database does not refer to objects in a different database.
     402                 : ** (Exception: indices, triggers, and views in the TEMP database are
     403                 : ** allowed to refer to anything.)  If a reference is explicitly made
     404                 : ** to an object in a different database, an error message is added to
     405                 : ** pParse->zErrMsg and these routines return non-zero.  If everything
     406                 : ** checks out, these routines return 0.
     407                 : */
     408                 : int sqlite3FixSrcList(
     409                 :   DbFixer *pFix,       /* Context of the fixation */
     410                 :   SrcList *pList       /* The Source list to check and modify */
     411               0 : ){
     412                 :   int i;
     413                 :   const char *zDb;
     414                 :   struct SrcList_item *pItem;
     415                 : 
     416               0 :   if( pList==0 ) return 0;
     417               0 :   zDb = pFix->zDb;
     418               0 :   for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
     419               0 :     if( pItem->zDatabase==0 ){
     420               0 :       pItem->zDatabase = sqliteStrDup(zDb);
     421               0 :     }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
     422               0 :       sqlite3ErrorMsg(pFix->pParse,
     423                 :          "%s %T cannot reference objects in database %s",
     424                 :          pFix->zType, pFix->pName, pItem->zDatabase);
     425               0 :       return 1;
     426                 :     }
     427                 : #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
     428               0 :     if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
     429               0 :     if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
     430                 : #endif
     431                 :   }
     432               0 :   return 0;
     433                 : }
     434                 : #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
     435                 : int sqlite3FixSelect(
     436                 :   DbFixer *pFix,       /* Context of the fixation */
     437                 :   Select *pSelect      /* The SELECT statement to be fixed to one database */
     438               0 : ){
     439               0 :   while( pSelect ){
     440               0 :     if( sqlite3FixExprList(pFix, pSelect->pEList) ){
     441               0 :       return 1;
     442                 :     }
     443               0 :     if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
     444               0 :       return 1;
     445                 :     }
     446               0 :     if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
     447               0 :       return 1;
     448                 :     }
     449               0 :     if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
     450               0 :       return 1;
     451                 :     }
     452               0 :     pSelect = pSelect->pPrior;
     453                 :   }
     454               0 :   return 0;
     455                 : }
     456                 : int sqlite3FixExpr(
     457                 :   DbFixer *pFix,     /* Context of the fixation */
     458                 :   Expr *pExpr        /* The expression to be fixed to one database */
     459               0 : ){
     460               0 :   while( pExpr ){
     461               0 :     if( sqlite3FixSelect(pFix, pExpr->pSelect) ){
     462               0 :       return 1;
     463                 :     }
     464               0 :     if( sqlite3FixExprList(pFix, pExpr->pList) ){
     465               0 :       return 1;
     466                 :     }
     467               0 :     if( sqlite3FixExpr(pFix, pExpr->pRight) ){
     468               0 :       return 1;
     469                 :     }
     470               0 :     pExpr = pExpr->pLeft;
     471                 :   }
     472               0 :   return 0;
     473                 : }
     474                 : int sqlite3FixExprList(
     475                 :   DbFixer *pFix,     /* Context of the fixation */
     476                 :   ExprList *pList    /* The expression to be fixed to one database */
     477               0 : ){
     478                 :   int i;
     479                 :   struct ExprList_item *pItem;
     480               0 :   if( pList==0 ) return 0;
     481               0 :   for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
     482               0 :     if( sqlite3FixExpr(pFix, pItem->pExpr) ){
     483               0 :       return 1;
     484                 :     }
     485                 :   }
     486               0 :   return 0;
     487                 : }
     488                 : #endif
     489                 : 
     490                 : #ifndef SQLITE_OMIT_TRIGGER
     491                 : int sqlite3FixTriggerStep(
     492                 :   DbFixer *pFix,     /* Context of the fixation */
     493                 :   TriggerStep *pStep /* The trigger step be fixed to one database */
     494               0 : ){
     495               0 :   while( pStep ){
     496               0 :     if( sqlite3FixSelect(pFix, pStep->pSelect) ){
     497               0 :       return 1;
     498                 :     }
     499               0 :     if( sqlite3FixExpr(pFix, pStep->pWhere) ){
     500               0 :       return 1;
     501                 :     }
     502               0 :     if( sqlite3FixExprList(pFix, pStep->pExprList) ){
     503               0 :       return 1;
     504                 :     }
     505               0 :     pStep = pStep->pNext;
     506                 :   }
     507               0 :   return 0;
     508                 : }
     509                 : #endif

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:15 +0000 (5 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.