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 - vtab.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 294
Code covered: 12.2 % Executed lines: 36
Legend: not executed executed

       1                 : /*
       2                 : ** 2006 June 10
       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 help implement virtual tables.
      13                 : **
      14                 : ** $Id: vtab.c 235759 2007-05-16 21:04:46Z iliaa $
      15                 : */
      16                 : #ifndef SQLITE_OMIT_VIRTUALTABLE
      17                 : #include "sqliteInt.h"
      18                 : 
      19                 : /*
      20                 : ** External API function used to create a new virtual-table module.
      21                 : */
      22                 : int sqlite3_create_module(
      23                 :   sqlite3 *db,                    /* Database in which module is registered */
      24                 :   const char *zName,              /* Name assigned to this module */
      25                 :   const sqlite3_module *pModule,  /* The definition of the module */
      26                 :   void *pAux                      /* Context pointer for xCreate/xConnect */
      27               0 : ){
      28               0 :   int nName = strlen(zName);
      29               0 :   Module *pMod = (Module *)sqliteMallocRaw(sizeof(Module) + nName + 1);
      30               0 :   if( pMod ){
      31               0 :     char *zCopy = (char *)(&pMod[1]);
      32               0 :     strcpy(zCopy, zName);
      33               0 :     pMod->zName = zCopy;
      34               0 :     pMod->pModule = pModule;
      35               0 :     pMod->pAux = pAux;
      36               0 :     pMod = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
      37               0 :     sqliteFree(pMod);
      38               0 :     sqlite3ResetInternalSchema(db, 0);
      39                 :   }
      40               0 :   return sqlite3ApiExit(db, SQLITE_OK);
      41                 : }
      42                 : 
      43                 : /*
      44                 : ** Lock the virtual table so that it cannot be disconnected.
      45                 : ** Locks nest.  Every lock should have a corresponding unlock.
      46                 : ** If an unlock is omitted, resources leaks will occur.  
      47                 : **
      48                 : ** If a disconnect is attempted while a virtual table is locked,
      49                 : ** the disconnect is deferred until all locks have been removed.
      50                 : */
      51               0 : void sqlite3VtabLock(sqlite3_vtab *pVtab){
      52               0 :   pVtab->nRef++;
      53               0 : }
      54                 : 
      55                 : /*
      56                 : ** Unlock a virtual table.  When the last lock is removed,
      57                 : ** disconnect the virtual table.
      58                 : */
      59               0 : void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){
      60               0 :   pVtab->nRef--;
      61                 :   assert(db);
      62                 :   assert(!sqlite3SafetyCheck(db));
      63               0 :   if( pVtab->nRef==0 ){
      64               0 :     if( db->magic==SQLITE_MAGIC_BUSY ){
      65               0 :       sqlite3SafetyOff(db);
      66               0 :       pVtab->pModule->xDisconnect(pVtab);
      67               0 :       sqlite3SafetyOn(db);
      68                 :     } else {
      69               0 :       pVtab->pModule->xDisconnect(pVtab);
      70                 :     }
      71                 :   }
      72               0 : }
      73                 : 
      74                 : /*
      75                 : ** Clear any and all virtual-table information from the Table record.
      76                 : ** This routine is called, for example, just before deleting the Table
      77                 : ** record.
      78                 : */
      79             327 : void sqlite3VtabClear(Table *p){
      80             327 :   sqlite3_vtab *pVtab = p->pVtab;
      81             327 :   if( pVtab ){
      82                 :     assert( p->pMod && p->pMod->pModule );
      83               0 :     sqlite3VtabUnlock(p->pSchema->db, pVtab);
      84               0 :     p->pVtab = 0;
      85                 :   }
      86             327 :   if( p->azModuleArg ){
      87                 :     int i;
      88               0 :     for(i=0; i<p->nModuleArg; i++){
      89               0 :       sqliteFree(p->azModuleArg[i]);
      90                 :     }
      91               0 :     sqliteFree(p->azModuleArg);
      92                 :   }
      93             327 : }
      94                 : 
      95                 : /*
      96                 : ** Add a new module argument to pTable->azModuleArg[].
      97                 : ** The string is not copied - the pointer is stored.  The
      98                 : ** string will be freed automatically when the table is
      99                 : ** deleted.
     100                 : */
     101               0 : static void addModuleArgument(Table *pTable, char *zArg){
     102               0 :   int i = pTable->nModuleArg++;
     103               0 :   int nBytes = sizeof(char *)*(1+pTable->nModuleArg);
     104                 :   char **azModuleArg;
     105               0 :   azModuleArg = sqliteRealloc(pTable->azModuleArg, nBytes);
     106               0 :   if( azModuleArg==0 ){
     107                 :     int j;
     108               0 :     for(j=0; j<i; j++){
     109               0 :       sqliteFree(pTable->azModuleArg[j]);
     110                 :     }
     111               0 :     sqliteFree(zArg);
     112               0 :     sqliteFree(pTable->azModuleArg);
     113               0 :     pTable->nModuleArg = 0;
     114                 :   }else{
     115               0 :     azModuleArg[i] = zArg;
     116               0 :     azModuleArg[i+1] = 0;
     117                 :   }
     118               0 :   pTable->azModuleArg = azModuleArg;
     119               0 : }
     120                 : 
     121                 : /*
     122                 : ** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
     123                 : ** statement.  The module name has been parsed, but the optional list
     124                 : ** of parameters that follow the module name are still pending.
     125                 : */
     126                 : void sqlite3VtabBeginParse(
     127                 :   Parse *pParse,        /* Parsing context */
     128                 :   Token *pName1,        /* Name of new table, or database name */
     129                 :   Token *pName2,        /* Name of new table or NULL */
     130                 :   Token *pModuleName    /* Name of the module for the virtual table */
     131               0 : ){
     132                 :   int iDb;              /* The database the table is being created in */
     133                 :   Table *pTable;        /* The new virtual table */
     134                 : 
     135                 : #ifndef SQLITE_OMIT_SHARED_CACHE
     136               0 :   if( sqlite3ThreadDataReadOnly()->useSharedData ){
     137               0 :     sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode");
     138               0 :     return;
     139                 :   }
     140                 : #endif
     141                 : 
     142               0 :   sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
     143               0 :   pTable = pParse->pNewTable;
     144               0 :   if( pTable==0 || pParse->nErr ) return;
     145                 :   assert( 0==pTable->pIndex );
     146                 : 
     147               0 :   iDb = sqlite3SchemaToIndex(pParse->db, pTable->pSchema);
     148                 :   assert( iDb>=0 );
     149                 : 
     150               0 :   pTable->isVirtual = 1;
     151               0 :   pTable->nModuleArg = 0;
     152               0 :   addModuleArgument(pTable, sqlite3NameFromToken(pModuleName));
     153               0 :   addModuleArgument(pTable, sqlite3StrDup(pParse->db->aDb[iDb].zName));
     154               0 :   addModuleArgument(pTable, sqlite3StrDup(pTable->zName));
     155               0 :   pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z;
     156                 : 
     157                 : #ifndef SQLITE_OMIT_AUTHORIZATION
     158                 :   /* Creating a virtual table invokes the authorization callback twice.
     159                 :   ** The first invocation, to obtain permission to INSERT a row into the
     160                 :   ** sqlite_master table, has already been made by sqlite3StartTable().
     161                 :   ** The second call, to obtain permission to create the table, is made now.
     162                 :   */
     163               0 :   if( pTable->azModuleArg ){
     164               0 :     sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, 
     165                 :             pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);
     166                 :   }
     167                 : #endif
     168                 : }
     169                 : 
     170                 : /*
     171                 : ** This routine takes the module argument that has been accumulating
     172                 : ** in pParse->zArg[] and appends it to the list of arguments on the
     173                 : ** virtual table currently under construction in pParse->pTable.
     174                 : */
     175               0 : static void addArgumentToVtab(Parse *pParse){
     176               0 :   if( pParse->sArg.z && pParse->pNewTable ){
     177               0 :     const char *z = (const char*)pParse->sArg.z;
     178               0 :     int n = pParse->sArg.n;
     179               0 :     addModuleArgument(pParse->pNewTable, sqliteStrNDup(z, n));
     180                 :   }
     181               0 : }
     182                 : 
     183                 : /*
     184                 : ** The parser calls this routine after the CREATE VIRTUAL TABLE statement
     185                 : ** has been completely parsed.
     186                 : */
     187               0 : void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
     188                 :   Table *pTab;        /* The table being constructed */
     189                 :   sqlite3 *db;        /* The database connection */
     190                 :   char *zModule;      /* The module name of the table: USING modulename */
     191               0 :   Module *pMod = 0;
     192                 : 
     193               0 :   addArgumentToVtab(pParse);
     194               0 :   pParse->sArg.z = 0;
     195                 : 
     196                 :   /* Lookup the module name. */
     197               0 :   pTab = pParse->pNewTable;
     198               0 :   if( pTab==0 ) return;
     199               0 :   db = pParse->db;
     200               0 :   if( pTab->nModuleArg<1 ) return;
     201               0 :   zModule = pTab->azModuleArg[0];
     202               0 :   pMod = (Module *)sqlite3HashFind(&db->aModule, zModule, strlen(zModule));
     203               0 :   pTab->pMod = pMod;
     204                 :   
     205                 :   /* If the CREATE VIRTUAL TABLE statement is being entered for the
     206                 :   ** first time (in other words if the virtual table is actually being
     207                 :   ** created now instead of just being read out of sqlite_master) then
     208                 :   ** do additional initialization work and store the statement text
     209                 :   ** in the sqlite_master table.
     210                 :   */
     211               0 :   if( !db->init.busy ){
     212                 :     char *zStmt;
     213                 :     char *zWhere;
     214                 :     int iDb;
     215                 :     Vdbe *v;
     216                 : 
     217                 :     /* Compute the complete text of the CREATE VIRTUAL TABLE statement */
     218               0 :     if( pEnd ){
     219               0 :       pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n;
     220                 :     }
     221               0 :     zStmt = sqlite3MPrintf("CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
     222                 : 
     223                 :     /* A slot for the record has already been allocated in the 
     224                 :     ** SQLITE_MASTER table.  We just need to update that slot with all
     225                 :     ** the information we've collected.  
     226                 :     **
     227                 :     ** The top of the stack is the rootpage allocated by sqlite3StartTable().
     228                 :     ** This value is always 0 and is ignored, a virtual table does not have a
     229                 :     ** rootpage. The next entry on the stack is the rowid of the record
     230                 :     ** in the sqlite_master table.
     231                 :     */
     232               0 :     iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
     233               0 :     sqlite3NestedParse(pParse,
     234                 :       "UPDATE %Q.%s "
     235                 :          "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
     236                 :        "WHERE rowid=#1",
     237                 :       db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
     238                 :       pTab->zName,
     239                 :       pTab->zName,
     240                 :       zStmt
     241                 :     );
     242               0 :     sqliteFree(zStmt);
     243               0 :     v = sqlite3GetVdbe(pParse);
     244               0 :     sqlite3ChangeCookie(db, v, iDb);
     245                 : 
     246               0 :     sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
     247               0 :     zWhere = sqlite3MPrintf("name='%q'", pTab->zName);
     248               0 :     sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 1, zWhere, P3_DYNAMIC);
     249               0 :     sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1);
     250                 :   }
     251                 : 
     252                 :   /* If we are rereading the sqlite_master table create the in-memory
     253                 :   ** record of the table. If the module has already been registered,
     254                 :   ** also call the xConnect method here.
     255                 :   */
     256                 :   else {
     257                 :     Table *pOld;
     258               0 :     Schema *pSchema = pTab->pSchema;
     259               0 :     const char *zName = pTab->zName;
     260               0 :     int nName = strlen(zName) + 1;
     261               0 :     pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
     262               0 :     if( pOld ){
     263                 :       assert( pTab==pOld );  /* Malloc must have failed inside HashInsert() */
     264               0 :       return;
     265                 :     }
     266               0 :     pSchema->db = pParse->db;
     267               0 :     pParse->pNewTable = 0;
     268                 :   }
     269                 : }
     270                 : 
     271                 : /*
     272                 : ** The parser calls this routine when it sees the first token
     273                 : ** of an argument to the module name in a CREATE VIRTUAL TABLE statement.
     274                 : */
     275               0 : void sqlite3VtabArgInit(Parse *pParse){
     276               0 :   addArgumentToVtab(pParse);
     277               0 :   pParse->sArg.z = 0;
     278               0 :   pParse->sArg.n = 0;
     279               0 : }
     280                 : 
     281                 : /*
     282                 : ** The parser calls this routine for each token after the first token
     283                 : ** in an argument to the module name in a CREATE VIRTUAL TABLE statement.
     284                 : */
     285               0 : void sqlite3VtabArgExtend(Parse *pParse, Token *p){
     286               0 :   Token *pArg = &pParse->sArg;
     287               0 :   if( pArg->z==0 ){
     288               0 :     pArg->z = p->z;
     289               0 :     pArg->n = p->n;
     290                 :   }else{
     291                 :     assert(pArg->z < p->z);
     292               0 :     pArg->n = (p->z + p->n - pArg->z);
     293                 :   }
     294               0 : }
     295                 : 
     296                 : /*
     297                 : ** Invoke a virtual table constructor (either xCreate or xConnect). The
     298                 : ** pointer to the function to invoke is passed as the fourth parameter
     299                 : ** to this procedure.
     300                 : */
     301                 : static int vtabCallConstructor(
     302                 :   sqlite3 *db, 
     303                 :   Table *pTab,
     304                 :   Module *pMod,
     305                 :   int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
     306                 :   char **pzErr
     307               0 : ){
     308                 :   int rc;
     309                 :   int rc2;
     310                 :   sqlite3_vtab *pVtab;
     311               0 :   const char *const*azArg = (const char *const*)pTab->azModuleArg;
     312               0 :   int nArg = pTab->nModuleArg;
     313               0 :   char *zErr = 0;
     314               0 :   char *zModuleName = sqlite3MPrintf("%s", pTab->zName);
     315                 : 
     316               0 :   if( !zModuleName ){
     317               0 :     return SQLITE_NOMEM;
     318                 :   }
     319                 : 
     320                 :   assert( !db->pVTab );
     321                 :   assert( xConstruct );
     322                 : 
     323               0 :   db->pVTab = pTab;
     324               0 :   rc = sqlite3SafetyOff(db);
     325                 :   assert( rc==SQLITE_OK );
     326               0 :   rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab, &zErr);
     327               0 :   rc2 = sqlite3SafetyOn(db);
     328               0 :   pVtab = pTab->pVtab;
     329               0 :   if( rc==SQLITE_OK && pVtab ){
     330               0 :     pVtab->pModule = pMod->pModule;
     331               0 :     pVtab->nRef = 1;
     332                 :   }
     333                 : 
     334               0 :   if( SQLITE_OK!=rc ){
     335               0 :     if( zErr==0 ){
     336               0 :       *pzErr = sqlite3MPrintf("vtable constructor failed: %s", zModuleName);
     337                 :     }else {
     338               0 :       *pzErr = sqlite3MPrintf("%s", zErr);
     339               0 :       sqlite3_free(zErr);
     340                 :     }
     341               0 :   }else if( db->pVTab ){
     342               0 :     const char *zFormat = "vtable constructor did not declare schema: %s";
     343               0 :     *pzErr = sqlite3MPrintf(zFormat, pTab->zName);
     344               0 :     rc = SQLITE_ERROR;
     345                 :   } 
     346               0 :   if( rc==SQLITE_OK ){
     347               0 :     rc = rc2;
     348                 :   }
     349               0 :   db->pVTab = 0;
     350               0 :   sqliteFree(zModuleName);
     351               0 :   return rc;
     352                 : }
     353                 : 
     354                 : /*
     355                 : ** This function is invoked by the parser to call the xConnect() method
     356                 : ** of the virtual table pTab. If an error occurs, an error code is returned 
     357                 : ** and an error left in pParse.
     358                 : **
     359                 : ** This call is a no-op if table pTab is not a virtual table.
     360                 : */
     361             228 : int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
     362                 :   Module *pMod;
     363             228 :   int rc = SQLITE_OK;
     364                 : 
     365             228 :   if( !pTab || !pTab->isVirtual || pTab->pVtab ){
     366             228 :     return SQLITE_OK;
     367                 :   }
     368                 : 
     369               0 :   pMod = pTab->pMod;
     370               0 :   if( !pMod ){
     371               0 :     const char *zModule = pTab->azModuleArg[0];
     372               0 :     sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
     373               0 :     rc = SQLITE_ERROR;
     374                 :   } else {
     375               0 :     char *zErr = 0;
     376               0 :     sqlite3 *db = pParse->db;
     377               0 :     rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
     378               0 :     if( rc!=SQLITE_OK ){
     379               0 :       sqlite3ErrorMsg(pParse, "%s", zErr);
     380                 :     }
     381               0 :     sqliteFree(zErr);
     382                 :   }
     383                 : 
     384               0 :   return rc;
     385                 : }
     386                 : 
     387                 : /*
     388                 : ** Add the virtual table pVtab to the array sqlite3.aVTrans[].
     389                 : */
     390               0 : static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){
     391               0 :   const int ARRAY_INCR = 5;
     392                 : 
     393                 :   /* Grow the sqlite3.aVTrans array if required */
     394               0 :   if( (db->nVTrans%ARRAY_INCR)==0 ){
     395                 :     sqlite3_vtab **aVTrans;
     396               0 :     int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR);
     397               0 :     aVTrans = sqliteRealloc((void *)db->aVTrans, nBytes);
     398               0 :     if( !aVTrans ){
     399               0 :       return SQLITE_NOMEM;
     400                 :     }
     401               0 :     memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR);
     402               0 :     db->aVTrans = aVTrans;
     403                 :   }
     404                 : 
     405                 :   /* Add pVtab to the end of sqlite3.aVTrans */
     406               0 :   db->aVTrans[db->nVTrans++] = pVtab;
     407               0 :   sqlite3VtabLock(pVtab);
     408               0 :   return SQLITE_OK;
     409                 : }
     410                 : 
     411                 : /*
     412                 : ** This function is invoked by the vdbe to call the xCreate method
     413                 : ** of the virtual table named zTab in database iDb. 
     414                 : **
     415                 : ** If an error occurs, *pzErr is set to point an an English language
     416                 : ** description of the error and an SQLITE_XXX error code is returned.
     417                 : ** In this case the caller must call sqliteFree() on *pzErr.
     418                 : */
     419               0 : int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
     420               0 :   int rc = SQLITE_OK;
     421                 :   Table *pTab;
     422                 :   Module *pMod;
     423                 :   const char *zModule;
     424                 : 
     425               0 :   pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
     426                 :   assert(pTab && pTab->isVirtual && !pTab->pVtab);
     427               0 :   pMod = pTab->pMod;
     428               0 :   zModule = pTab->azModuleArg[0];
     429                 : 
     430                 :   /* If the module has been registered and includes a Create method, 
     431                 :   ** invoke it now. If the module has not been registered, return an 
     432                 :   ** error. Otherwise, do nothing.
     433                 :   */
     434               0 :   if( !pMod ){
     435               0 :     *pzErr = sqlite3MPrintf("no such module: %s", zModule);
     436               0 :     rc = SQLITE_ERROR;
     437                 :   }else{
     438               0 :     rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
     439                 :   }
     440                 : 
     441               0 :   if( rc==SQLITE_OK && pTab->pVtab ){
     442               0 :       rc = addToVTrans(db, pTab->pVtab);
     443                 :   }
     444                 : 
     445               0 :   return rc;
     446                 : }
     447                 : 
     448                 : /*
     449                 : ** This function is used to set the schema of a virtual table.  It is only
     450                 : ** valid to call this function from within the xCreate() or xConnect() of a
     451                 : ** virtual table module.
     452                 : */
     453               0 : int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
     454                 :   Parse sParse;
     455                 : 
     456               0 :   int rc = SQLITE_OK;
     457               0 :   Table *pTab = db->pVTab;
     458               0 :   char *zErr = 0;
     459                 : 
     460               0 :   if( !pTab ){
     461               0 :     sqlite3Error(db, SQLITE_MISUSE, 0);
     462               0 :     return SQLITE_MISUSE;
     463                 :   }
     464                 :   assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
     465                 : 
     466               0 :   memset(&sParse, 0, sizeof(Parse));
     467               0 :   sParse.declareVtab = 1;
     468               0 :   sParse.db = db;
     469                 : 
     470               0 :   if( 
     471                 :       SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) && 
     472                 :       sParse.pNewTable && 
     473                 :       !sParse.pNewTable->pSelect && 
     474                 :       !sParse.pNewTable->isVirtual 
     475                 :   ){
     476               0 :     pTab->aCol = sParse.pNewTable->aCol;
     477               0 :     pTab->nCol = sParse.pNewTable->nCol;
     478               0 :     sParse.pNewTable->nCol = 0;
     479               0 :     sParse.pNewTable->aCol = 0;
     480               0 :     db->pVTab = 0;
     481                 :   } else {
     482               0 :     sqlite3Error(db, SQLITE_ERROR, zErr);
     483               0 :     sqliteFree(zErr);
     484               0 :     rc = SQLITE_ERROR;
     485                 :   }
     486               0 :   sParse.declareVtab = 0;
     487                 : 
     488               0 :   sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
     489               0 :   sqlite3DeleteTable(sParse.pNewTable);
     490               0 :   sParse.pNewTable = 0;
     491                 : 
     492                 :   assert( (rc&0xff)==rc );
     493               0 :   return sqlite3ApiExit(db, rc);
     494                 : }
     495                 : 
     496                 : /*
     497                 : ** This function is invoked by the vdbe to call the xDestroy method
     498                 : ** of the virtual table named zTab in database iDb. This occurs
     499                 : ** when a DROP TABLE is mentioned.
     500                 : **
     501                 : ** This call is a no-op if zTab is not a virtual table.
     502                 : */
     503                 : int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab)
     504               0 : {
     505               0 :   int rc = SQLITE_OK;
     506                 :   Table *pTab;
     507                 : 
     508               0 :   pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
     509                 :   assert(pTab);
     510               0 :   if( pTab->pVtab ){
     511               0 :     int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy;
     512               0 :     rc = sqlite3SafetyOff(db);
     513                 :     assert( rc==SQLITE_OK );
     514               0 :     if( xDestroy ){
     515               0 :       rc = xDestroy(pTab->pVtab);
     516                 :     }
     517               0 :     sqlite3SafetyOn(db);
     518               0 :     if( rc==SQLITE_OK ){
     519               0 :       pTab->pVtab = 0;
     520                 :     }
     521                 :   }
     522                 : 
     523               0 :   return rc;
     524                 : }
     525                 : 
     526                 : /*
     527                 : ** This function invokes either the xRollback or xCommit method
     528                 : ** of each of the virtual tables in the sqlite3.aVTrans array. The method
     529                 : ** called is identified by the second argument, "offset", which is
     530                 : ** the offset of the method to call in the sqlite3_module structure.
     531                 : **
     532                 : ** The array is cleared after invoking the callbacks. 
     533                 : */
     534             694 : static void callFinaliser(sqlite3 *db, int offset){
     535                 :   int i;
     536             694 :   if( db->aVTrans ){
     537               0 :     for(i=0; i<db->nVTrans && db->aVTrans[i]; i++){
     538               0 :       sqlite3_vtab *pVtab = db->aVTrans[i];
     539                 :       int (*x)(sqlite3_vtab *);
     540               0 :       x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
     541               0 :       if( x ) x(pVtab);
     542               0 :       sqlite3VtabUnlock(db, pVtab);
     543                 :     }
     544               0 :     sqliteFree(db->aVTrans);
     545               0 :     db->nVTrans = 0;
     546               0 :     db->aVTrans = 0;
     547                 :   }
     548             694 : }
     549                 : 
     550                 : /*
     551                 : ** If argument rc2 is not SQLITE_OK, then return it and do nothing. 
     552                 : ** Otherwise, invoke the xSync method of all virtual tables in the 
     553                 : ** sqlite3.aVTrans array. Return the error code for the first error 
     554                 : ** that occurs, or SQLITE_OK if all xSync operations are successful.
     555                 : */
     556             562 : int sqlite3VtabSync(sqlite3 *db, int rc2){
     557                 :   int i;
     558             562 :   int rc = SQLITE_OK;
     559                 :   int rcsafety;
     560             562 :   sqlite3_vtab **aVTrans = db->aVTrans;
     561             562 :   if( rc2!=SQLITE_OK ) return rc2;
     562                 : 
     563             562 :   rc = sqlite3SafetyOff(db);
     564             562 :   db->aVTrans = 0;
     565             562 :   for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){
     566               0 :     sqlite3_vtab *pVtab = aVTrans[i];
     567                 :     int (*x)(sqlite3_vtab *);
     568               0 :     x = pVtab->pModule->xSync;
     569               0 :     if( x ){
     570               0 :       rc = x(pVtab);
     571                 :     }
     572                 :   }
     573             562 :   db->aVTrans = aVTrans;
     574             562 :   rcsafety = sqlite3SafetyOn(db);
     575                 : 
     576             562 :   if( rc==SQLITE_OK ){
     577             562 :     rc = rcsafety;
     578                 :   }
     579             562 :   return rc;
     580                 : }
     581                 : 
     582                 : /*
     583                 : ** Invoke the xRollback method of all virtual tables in the 
     584                 : ** sqlite3.aVTrans array. Then clear the array itself.
     585                 : */
     586             132 : int sqlite3VtabRollback(sqlite3 *db){
     587             132 :   callFinaliser(db, (int)(&((sqlite3_module *)0)->xRollback));
     588             132 :   return SQLITE_OK;
     589                 : }
     590                 : 
     591                 : /*
     592                 : ** Invoke the xCommit method of all virtual tables in the 
     593                 : ** sqlite3.aVTrans array. Then clear the array itself.
     594                 : */
     595             562 : int sqlite3VtabCommit(sqlite3 *db){
     596             562 :   callFinaliser(db, (int)(&((sqlite3_module *)0)->xCommit));
     597             562 :   return SQLITE_OK;
     598                 : }
     599                 : 
     600                 : /*
     601                 : ** If the virtual table pVtab supports the transaction interface
     602                 : ** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is
     603                 : ** not currently open, invoke the xBegin method now.
     604                 : **
     605                 : ** If the xBegin call is successful, place the sqlite3_vtab pointer
     606                 : ** in the sqlite3.aVTrans array.
     607                 : */
     608               0 : int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){
     609               0 :   int rc = SQLITE_OK;
     610                 :   const sqlite3_module *pModule;
     611                 : 
     612                 :   /* Special case: If db->aVTrans is NULL and db->nVTrans is greater
     613                 :   ** than zero, then this function is being called from within a
     614                 :   ** virtual module xSync() callback. It is illegal to write to 
     615                 :   ** virtual module tables in this case, so return SQLITE_LOCKED.
     616                 :   */
     617               0 :   if( 0==db->aVTrans && db->nVTrans>0 ){
     618               0 :     return SQLITE_LOCKED;
     619                 :   }
     620               0 :   if( !pVtab ){
     621               0 :     return SQLITE_OK;
     622                 :   } 
     623               0 :   pModule = pVtab->pModule;
     624                 : 
     625               0 :   if( pModule->xBegin ){
     626                 :     int i;
     627                 : 
     628                 : 
     629                 :     /* If pVtab is already in the aVTrans array, return early */
     630               0 :     for(i=0; (i<db->nVTrans) && 0!=db->aVTrans[i]; i++){
     631               0 :       if( db->aVTrans[i]==pVtab ){
     632               0 :         return SQLITE_OK;
     633                 :       }
     634                 :     }
     635                 : 
     636                 :     /* Invoke the xBegin method */
     637               0 :     rc = pModule->xBegin(pVtab);
     638               0 :     if( rc!=SQLITE_OK ){
     639               0 :       return rc;
     640                 :     }
     641                 : 
     642               0 :     rc = addToVTrans(db, pVtab);
     643                 :   }
     644               0 :   return rc;
     645                 : }
     646                 : 
     647                 : /*
     648                 : ** The first parameter (pDef) is a function implementation.  The
     649                 : ** second parameter (pExpr) is the first argument to this function.
     650                 : ** If pExpr is a column in a virtual table, then let the virtual
     651                 : ** table implementation have an opportunity to overload the function.
     652                 : **
     653                 : ** This routine is used to allow virtual table implementations to
     654                 : ** overload MATCH, LIKE, GLOB, and REGEXP operators.
     655                 : **
     656                 : ** Return either the pDef argument (indicating no change) or a 
     657                 : ** new FuncDef structure that is marked as ephemeral using the
     658                 : ** SQLITE_FUNC_EPHEM flag.
     659                 : */
     660                 : FuncDef *sqlite3VtabOverloadFunction(
     661                 :   FuncDef *pDef,  /* Function to possibly overload */
     662                 :   int nArg,       /* Number of arguments to the function */
     663                 :   Expr *pExpr     /* First argument to the function */
     664               1 : ){
     665                 :   Table *pTab;
     666                 :   sqlite3_vtab *pVtab;
     667                 :   sqlite3_module *pMod;
     668                 :   void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
     669                 :   void *pArg;
     670                 :   FuncDef *pNew;
     671                 :   int rc;
     672                 :   char *zLowerName;
     673                 :   unsigned char *z;
     674                 : 
     675                 : 
     676                 :   /* Check to see the left operand is a column in a virtual table */
     677               1 :   if( pExpr==0 ) return pDef;
     678               1 :   if( pExpr->op!=TK_COLUMN ) return pDef;
     679               1 :   pTab = pExpr->pTab;
     680               1 :   if( pTab==0 ) return pDef;
     681               1 :   if( !pTab->isVirtual ) return pDef;
     682               0 :   pVtab = pTab->pVtab;
     683                 :   assert( pVtab!=0 );
     684                 :   assert( pVtab->pModule!=0 );
     685               0 :   pMod = (sqlite3_module *)pVtab->pModule;
     686               0 :   if( pMod->xFindFunction==0 ) return pDef;
     687                 :  
     688                 :   /* Call the xFuncFunction method on the virtual table implementation
     689                 :   ** to see if the implementation wants to overload this function 
     690                 :   */
     691               0 :   zLowerName = sqlite3StrDup(pDef->zName);
     692               0 :   for(z=(unsigned char*)zLowerName; *z; z++){
     693               0 :     *z = sqlite3UpperToLower[*z];
     694                 :   }
     695               0 :   rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
     696               0 :   sqliteFree(zLowerName);
     697               0 :   if( rc==0 ){
     698               0 :     return pDef;
     699                 :   }
     700                 : 
     701                 :   /* Create a new ephemeral function definition for the overloaded
     702                 :   ** function */
     703               0 :   pNew = sqliteMalloc( sizeof(*pNew) + strlen(pDef->zName) );
     704               0 :   if( pNew==0 ){
     705               0 :     return pDef;
     706                 :   }
     707               0 :   *pNew = *pDef;
     708               0 :   strcpy(pNew->zName, pDef->zName);
     709               0 :   pNew->xFunc = xFunc;
     710               0 :   pNew->pUserData = pArg;
     711               0 :   pNew->flags |= SQLITE_FUNC_EPHEM;
     712               0 :   return pNew;
     713                 : }
     714                 : 
     715                 : #endif /* SQLITE_OMIT_VIRTUALTABLE */

Generated by: LTP GCOV extension version 1.5

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

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