⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vtab.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** 2006 June 10**** The author disclaims copyright to this source code.  In place of** a legal notice, here is a blessing:****    May you do good and not evil.**    May you find forgiveness for yourself and forgive others.**    May you share freely, never taking more than you give.***************************************************************************** This file contains code used to help implement virtual tables.**** $Id: vtab.c,v 1.48 2007/06/26 10:38:55 danielk1977 Exp $*/#ifndef SQLITE_OMIT_VIRTUALTABLE#include "sqliteInt.h"static int createModule(  sqlite3 *db,                    /* Database in which module is registered */  const char *zName,              /* Name assigned to this module */  const sqlite3_module *pModule,  /* The definition of the module */  void *pAux,                     /* Context pointer for xCreate/xConnect */  void (*xDestroy)(void *)        /* Module destructor function */) {  int nName = strlen(zName);  Module *pMod = (Module *)sqliteMallocRaw(sizeof(Module) + nName + 1);  if( pMod ){    char *zCopy = (char *)(&pMod[1]);    memcpy(zCopy, zName, nName+1);    pMod->zName = zCopy;    pMod->pModule = pModule;    pMod->pAux = pAux;    pMod->xDestroy = xDestroy;    pMod = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);    if( pMod && pMod->xDestroy ){      pMod->xDestroy(pMod->pAux);    }    sqliteFree(pMod);    sqlite3ResetInternalSchema(db, 0);  }  return sqlite3ApiExit(db, SQLITE_OK);}/*** External API function used to create a new virtual-table module.*/int sqlite3_create_module(  sqlite3 *db,                    /* Database in which module is registered */  const char *zName,              /* Name assigned to this module */  const sqlite3_module *pModule,  /* The definition of the module */  void *pAux                      /* Context pointer for xCreate/xConnect */){  return createModule(db, zName, pModule, pAux, 0);}/*** External API function used to create a new virtual-table module.*/int sqlite3_create_module_v2(  sqlite3 *db,                    /* Database in which module is registered */  const char *zName,              /* Name assigned to this module */  const sqlite3_module *pModule,  /* The definition of the module */  void *pAux,                     /* Context pointer for xCreate/xConnect */  void (*xDestroy)(void *)        /* Module destructor function */){  return createModule(db, zName, pModule, pAux, xDestroy);}/*** Lock the virtual table so that it cannot be disconnected.** Locks nest.  Every lock should have a corresponding unlock.** If an unlock is omitted, resources leaks will occur.  **** If a disconnect is attempted while a virtual table is locked,** the disconnect is deferred until all locks have been removed.*/void sqlite3VtabLock(sqlite3_vtab *pVtab){  pVtab->nRef++;}/*** Unlock a virtual table.  When the last lock is removed,** disconnect the virtual table.*/void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){  pVtab->nRef--;  assert(db);  assert(!sqlite3SafetyCheck(db));  if( pVtab->nRef==0 ){    if( db->magic==SQLITE_MAGIC_BUSY ){      sqlite3SafetyOff(db);      pVtab->pModule->xDisconnect(pVtab);      sqlite3SafetyOn(db);    } else {      pVtab->pModule->xDisconnect(pVtab);    }  }}/*** Clear any and all virtual-table information from the Table record.** This routine is called, for example, just before deleting the Table** record.*/void sqlite3VtabClear(Table *p){  sqlite3_vtab *pVtab = p->pVtab;  if( pVtab ){    assert( p->pMod && p->pMod->pModule );    sqlite3VtabUnlock(p->pSchema->db, pVtab);    p->pVtab = 0;  }  if( p->azModuleArg ){    int i;    for(i=0; i<p->nModuleArg; i++){      sqliteFree(p->azModuleArg[i]);    }    sqliteFree(p->azModuleArg);  }}/*** Add a new module argument to pTable->azModuleArg[].** The string is not copied - the pointer is stored.  The** string will be freed automatically when the table is** deleted.*/static void addModuleArgument(Table *pTable, char *zArg){  int i = pTable->nModuleArg++;  int nBytes = sizeof(char *)*(1+pTable->nModuleArg);  char **azModuleArg;  azModuleArg = sqliteRealloc(pTable->azModuleArg, nBytes);  if( azModuleArg==0 ){    int j;    for(j=0; j<i; j++){      sqliteFree(pTable->azModuleArg[j]);    }    sqliteFree(zArg);    sqliteFree(pTable->azModuleArg);    pTable->nModuleArg = 0;  }else{    azModuleArg[i] = zArg;    azModuleArg[i+1] = 0;  }  pTable->azModuleArg = azModuleArg;}/*** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE** statement.  The module name has been parsed, but the optional list** of parameters that follow the module name are still pending.*/void sqlite3VtabBeginParse(  Parse *pParse,        /* Parsing context */  Token *pName1,        /* Name of new table, or database name */  Token *pName2,        /* Name of new table or NULL */  Token *pModuleName    /* Name of the module for the virtual table */){  int iDb;              /* The database the table is being created in */  Table *pTable;        /* The new virtual table */#ifndef SQLITE_OMIT_SHARED_CACHE  if( sqlite3ThreadDataReadOnly()->useSharedData ){    sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode");    return;  }#endif  sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);  pTable = pParse->pNewTable;  if( pTable==0 || pParse->nErr ) return;  assert( 0==pTable->pIndex );  iDb = sqlite3SchemaToIndex(pParse->db, pTable->pSchema);  assert( iDb>=0 );  pTable->isVirtual = 1;  pTable->nModuleArg = 0;  addModuleArgument(pTable, sqlite3NameFromToken(pModuleName));  addModuleArgument(pTable, sqlite3StrDup(pParse->db->aDb[iDb].zName));  addModuleArgument(pTable, sqlite3StrDup(pTable->zName));  pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z;#ifndef SQLITE_OMIT_AUTHORIZATION  /* Creating a virtual table invokes the authorization callback twice.  ** The first invocation, to obtain permission to INSERT a row into the  ** sqlite_master table, has already been made by sqlite3StartTable().  ** The second call, to obtain permission to create the table, is made now.  */  if( pTable->azModuleArg ){    sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,             pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);  }#endif}/*** This routine takes the module argument that has been accumulating** in pParse->zArg[] and appends it to the list of arguments on the** virtual table currently under construction in pParse->pTable.*/static void addArgumentToVtab(Parse *pParse){  if( pParse->sArg.z && pParse->pNewTable ){    const char *z = (const char*)pParse->sArg.z;    int n = pParse->sArg.n;    addModuleArgument(pParse->pNewTable, sqliteStrNDup(z, n));  }}/*** The parser calls this routine after the CREATE VIRTUAL TABLE statement** has been completely parsed.*/void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){  Table *pTab;        /* The table being constructed */  sqlite3 *db;        /* The database connection */  char *zModule;      /* The module name of the table: USING modulename */  Module *pMod = 0;  addArgumentToVtab(pParse);  pParse->sArg.z = 0;  /* Lookup the module name. */  pTab = pParse->pNewTable;  if( pTab==0 ) return;  db = pParse->db;  if( pTab->nModuleArg<1 ) return;  zModule = pTab->azModuleArg[0];  pMod = (Module *)sqlite3HashFind(&db->aModule, zModule, strlen(zModule));  pTab->pMod = pMod;    /* If the CREATE VIRTUAL TABLE statement is being entered for the  ** first time (in other words if the virtual table is actually being  ** created now instead of just being read out of sqlite_master) then  ** do additional initialization work and store the statement text  ** in the sqlite_master table.  */  if( !db->init.busy ){    char *zStmt;    char *zWhere;    int iDb;    Vdbe *v;    /* Compute the complete text of the CREATE VIRTUAL TABLE statement */    if( pEnd ){      pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n;    }    zStmt = sqlite3MPrintf("CREATE VIRTUAL TABLE %T", &pParse->sNameToken);    /* A slot for the record has already been allocated in the     ** SQLITE_MASTER table.  We just need to update that slot with all    ** the information we've collected.      **    ** The top of the stack is the rootpage allocated by sqlite3StartTable().    ** This value is always 0 and is ignored, a virtual table does not have a    ** rootpage. The next entry on the stack is the rowid of the record    ** in the sqlite_master table.    */    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);    sqlite3NestedParse(pParse,      "UPDATE %Q.%s "         "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "       "WHERE rowid=#1",      db->aDb[iDb].zName, SCHEMA_TABLE(iDb),      pTab->zName,      pTab->zName,      zStmt    );    sqliteFree(zStmt);    v = sqlite3GetVdbe(pParse);    sqlite3ChangeCookie(db, v, iDb);    sqlite3VdbeAddOp(v, OP_Expire, 0, 0);    zWhere = sqlite3MPrintf("name='%q'", pTab->zName);    sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 1, zWhere, P3_DYNAMIC);    sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1);  }  /* If we are rereading the sqlite_master table create the in-memory  ** record of the table. If the module has already been registered,  ** also call the xConnect method here.  */  else {    Table *pOld;    Schema *pSchema = pTab->pSchema;    const char *zName = pTab->zName;    int nName = strlen(zName) + 1;    pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);    if( pOld ){      assert( pTab==pOld );  /* Malloc must have failed inside HashInsert() */      return;    }    pSchema->db = pParse->db;    pParse->pNewTable = 0;  }}/*** The parser calls this routine when it sees the first token** of an argument to the module name in a CREATE VIRTUAL TABLE statement.*/void sqlite3VtabArgInit(Parse *pParse){  addArgumentToVtab(pParse);  pParse->sArg.z = 0;  pParse->sArg.n = 0;}/*** The parser calls this routine for each token after the first token** in an argument to the module name in a CREATE VIRTUAL TABLE statement.*/void sqlite3VtabArgExtend(Parse *pParse, Token *p){  Token *pArg = &pParse->sArg;  if( pArg->z==0 ){    pArg->z = p->z;    pArg->n = p->n;  }else{    assert(pArg->z < p->z);    pArg->n = (p->z + p->n - pArg->z);  }}/*** Invoke a virtual table constructor (either xCreate or xConnect). The** pointer to the function to invoke is passed as the fourth parameter** to this procedure.*/static int vtabCallConstructor(  sqlite3 *db,   Table *pTab,  Module *pMod,  int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),  char **pzErr){  int rc;  int rc2;  sqlite3_vtab *pVtab;  const char *const*azArg = (const char *const*)pTab->azModuleArg;  int nArg = pTab->nModuleArg;  char *zErr = 0;  char *zModuleName = sqlite3MPrintf("%s", pTab->zName);  if( !zModuleName ){    return SQLITE_NOMEM;  }  assert( !db->pVTab );  assert( xConstruct );  db->pVTab = pTab;  rc = sqlite3SafetyOff(db);  assert( rc==SQLITE_OK );  rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab, &zErr);  rc2 = sqlite3SafetyOn(db);  pVtab = pTab->pVtab;  if( rc==SQLITE_OK && pVtab ){    pVtab->pModule = pMod->pModule;    pVtab->nRef = 1;  }  if( SQLITE_OK!=rc ){    if( zErr==0 ){      *pzErr = sqlite3MPrintf("vtable constructor failed: %s", zModuleName);    }else {      *pzErr = sqlite3MPrintf("%s", zErr);      sqlite3_free(zErr);    }  }else if( db->pVTab ){    const char *zFormat = "vtable constructor did not declare schema: %s";    *pzErr = sqlite3MPrintf(zFormat, pTab->zName);    rc = SQLITE_ERROR;  }   if( rc==SQLITE_OK ){    rc = rc2;  }  db->pVTab = 0;  sqliteFree(zModuleName);  /* If everything went according to plan, loop through the columns  ** of the table to see if any of them contain the token "hidden".  ** If so, set the Column.isHidden flag and remove the token from  ** the type string.  */  if( rc==SQLITE_OK ){    int iCol;    for(iCol=0; iCol<pTab->nCol; iCol++){      char *zType = pTab->aCol[iCol].zType;      int nType;      int i = 0;      if( !zType ) continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -