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

📄 vtab.c

📁 sqlite 3.3.8 支持加密的版本
💻 C
📖 第 1 页 / 共 2 页
字号:

  pMod = pTab->pMod;
  zModule = pTab->azModuleArg[0];
  if( !pMod ){
    const char *zModule = pTab->azModuleArg[0];
    sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
    rc = SQLITE_ERROR;
  } else {
    char *zErr = 0;
    sqlite3 *db = pParse->db;
    rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
    if( rc!=SQLITE_OK ){
      sqlite3ErrorMsg(pParse, "%s", zErr);
    }
    sqliteFree(zErr);
  }

  return rc;
}

/*
** Add the virtual table pVtab to the array sqlite3.aVTrans[].
*/
static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){
  const int ARRAY_INCR = 5;

  /* Grow the sqlite3.aVTrans array if required */
  if( (db->nVTrans%ARRAY_INCR)==0 ){
    sqlite3_vtab **aVTrans;
    int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR);
    aVTrans = sqliteRealloc((void *)db->aVTrans, nBytes);
    if( !aVTrans ){
      return SQLITE_NOMEM;
    }
    memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR);
    db->aVTrans = aVTrans;
  }

  /* Add pVtab to the end of sqlite3.aVTrans */
  db->aVTrans[db->nVTrans++] = pVtab;
  sqlite3VtabLock(pVtab);
  return SQLITE_OK;
}

/*
** This function is invoked by the vdbe to call the xCreate method
** of the virtual table named zTab in database iDb. 
**
** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
** In this case the caller must call sqliteFree() on *pzErr.
*/
int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
  int rc = SQLITE_OK;
  Table *pTab;
  Module *pMod;
  const char *zModule;

  pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
  assert(pTab && pTab->isVirtual && !pTab->pVtab);
  pMod = pTab->pMod;
  zModule = pTab->azModuleArg[0];

  /* If the module has been registered and includes a Create method, 
  ** invoke it now. If the module has not been registered, return an 
  ** error. Otherwise, do nothing.
  */
  if( !pMod ){
    *pzErr = sqlite3MPrintf("no such module: %s", zModule);
    rc = SQLITE_ERROR;
  }else{
    rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
  }

  if( rc==SQLITE_OK && pTab->pVtab ){
      rc = addToVTrans(db, pTab->pVtab);
  }

  return rc;
}

/*
** This function is used to set the schema of a virtual table.  It is only
** valid to call this function from within the xCreate() or xConnect() of a
** virtual table module.
*/
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
  Parse sParse;

  int rc = SQLITE_OK;
  Table *pTab = db->pVTab;
  char *zErr = 0;

  if( !pTab ){
    sqlite3Error(db, SQLITE_MISUSE, 0);
    return SQLITE_MISUSE;
  }
  assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);

  memset(&sParse, 0, sizeof(Parse));
  sParse.declareVtab = 1;
  sParse.db = db;

  if( 
      SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) && 
      sParse.pNewTable && 
      !sParse.pNewTable->pSelect && 
      !sParse.pNewTable->isVirtual 
  ){
    pTab->aCol = sParse.pNewTable->aCol;
    pTab->nCol = sParse.pNewTable->nCol;
    sParse.pNewTable->nCol = 0;
    sParse.pNewTable->aCol = 0;
  } else {
    sqlite3Error(db, SQLITE_ERROR, zErr);
    sqliteFree(zErr);
    rc = SQLITE_ERROR;
  }
  sParse.declareVtab = 0;

  sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
  sqlite3DeleteTable(0, sParse.pNewTable);
  sParse.pNewTable = 0;
  db->pVTab = 0;

  assert( (rc&0xff)==rc );
  return rc;
}

/*
** This function is invoked by the vdbe to call the xDestroy method
** of the virtual table named zTab in database iDb. This occurs
** when a DROP TABLE is mentioned.
**
** This call is a no-op if zTab is not a virtual table.
*/
int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab)
{
  int rc = SQLITE_OK;
  Table *pTab;

  pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
  assert(pTab);
  if( pTab->pVtab ){
    int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy;
    rc = sqlite3SafetyOff(db);
    assert( rc==SQLITE_OK );
    if( xDestroy ){
      rc = xDestroy(pTab->pVtab);
    }
    sqlite3SafetyOn(db);
    if( rc==SQLITE_OK ){
      pTab->pVtab = 0;
    }
  }

  return rc;
}

/*
** This function invokes either the xRollback or xCommit method
** of each of the virtual tables in the sqlite3.aVTrans array. The method
** called is identified by the second argument, "offset", which is
** the offset of the method to call in the sqlite3_module structure.
**
** The array is cleared after invoking the callbacks. 
*/
static void callFinaliser(sqlite3 *db, int offset){
  int i;
  for(i=0; i<db->nVTrans && db->aVTrans[i]; i++){
    sqlite3_vtab *pVtab = db->aVTrans[i];
    int (*x)(sqlite3_vtab *);
    x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
    if( x ) x(pVtab);
    sqlite3VtabUnlock(pVtab);
  }
  sqliteFree(db->aVTrans);
  db->nVTrans = 0;
  db->aVTrans = 0;
}

/*
** If argument rc2 is not SQLITE_OK, then return it and do nothing. 
** Otherwise, invoke the xSync method of all virtual tables in the 
** sqlite3.aVTrans array. Return the error code for the first error 
** that occurs, or SQLITE_OK if all xSync operations are successful.
*/
int sqlite3VtabSync(sqlite3 *db, int rc2){
  int i;
  int rc = SQLITE_OK;
  int rcsafety;
  sqlite3_vtab **aVTrans = db->aVTrans;
  if( rc2!=SQLITE_OK ) return rc2;

  rc = sqlite3SafetyOff(db);
  db->aVTrans = 0;
  for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){
    sqlite3_vtab *pVtab = aVTrans[i];
    int (*x)(sqlite3_vtab *);
    x = pVtab->pModule->xSync;
    if( x ){
      rc = x(pVtab);
    }
  }
  db->aVTrans = aVTrans;
  rcsafety = sqlite3SafetyOn(db);

  if( rc==SQLITE_OK ){
    rc = rcsafety;
  }
  return rc;
}

/*
** Invoke the xRollback method of all virtual tables in the 
** sqlite3.aVTrans array. Then clear the array itself.
*/
int sqlite3VtabRollback(sqlite3 *db){
  callFinaliser(db, (int)(&((sqlite3_module *)0)->xRollback));
  return SQLITE_OK;
}

/*
** Invoke the xCommit method of all virtual tables in the 
** sqlite3.aVTrans array. Then clear the array itself.
*/
int sqlite3VtabCommit(sqlite3 *db){
  callFinaliser(db, (int)(&((sqlite3_module *)0)->xCommit));
  return SQLITE_OK;
}

/*
** If the virtual table pVtab supports the transaction interface
** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is
** not currently open, invoke the xBegin method now.
**
** If the xBegin call is successful, place the sqlite3_vtab pointer
** in the sqlite3.aVTrans array.
*/
int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){
  int rc = SQLITE_OK;
  const sqlite3_module *pModule;

  /* Special case: If db->aVTrans is NULL and db->nVTrans is greater
  ** than zero, then this function is being called from within a
  ** virtual module xSync() callback. It is illegal to write to 
  ** virtual module tables in this case, so return SQLITE_LOCKED.
  */
  if( 0==db->aVTrans && db->nVTrans>0 ){
    return SQLITE_LOCKED;
  }
  if( !pVtab ){
    return SQLITE_OK;
  } 
  pModule = pVtab->pModule;

  if( pModule->xBegin ){
    int i;


    /* If pVtab is already in the aVTrans array, return early */
    for(i=0; (i<db->nVTrans) && 0!=db->aVTrans[i]; i++){
      if( db->aVTrans[i]==pVtab ){
        return SQLITE_OK;
      }
    }

    /* Invoke the xBegin method */
    rc = pModule->xBegin(pVtab);
    if( rc!=SQLITE_OK ){
      return rc;
    }

    rc = addToVTrans(db, pVtab);
  }
  return rc;
}

/*
** The first parameter (pDef) is a function implementation.  The
** second parameter (pExpr) is the first argument to this function.
** If pExpr is a column in a virtual table, then let the virtual
** table implementation have an opportunity to overload the function.
**
** This routine is used to allow virtual table implementations to
** overload MATCH, LIKE, GLOB, and REGEXP operators.
**
** Return either the pDef argument (indicating no change) or a 
** new FuncDef structure that is marked as ephemeral using the
** SQLITE_FUNC_EPHEM flag.
*/
FuncDef *sqlite3VtabOverloadFunction(
  FuncDef *pDef,  /* Function to possibly overload */
  int nArg,       /* Number of arguments to the function */
  Expr *pExpr     /* First argument to the function */
){
  Table *pTab;
  sqlite3_vtab *pVtab;
  sqlite3_module *pMod;
  void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
  void *pArg;
  FuncDef *pNew;
  int rc;
  char *zLowerName;
  unsigned char *z;


  /* Check to see the left operand is a column in a virtual table */
  if( pExpr==0 ) return pDef;
  if( pExpr->op!=TK_COLUMN ) return pDef;
  pTab = pExpr->pTab;
  if( pTab==0 ) return pDef;
  if( !pTab->isVirtual ) return pDef;
  pVtab = pTab->pVtab;
  assert( pVtab!=0 );
  assert( pVtab->pModule!=0 );
  pMod = (sqlite3_module *)pVtab->pModule;
  if( pMod->xFindFunction==0 ) return pDef;
 
  /* Call the xFuncFunction method on the virtual table implementation
  ** to see if the implementation wants to overload this function 
  */
  zLowerName = sqlite3StrDup(pDef->zName);
  for(z=(unsigned char*)zLowerName; *z; z++){
    *z = sqlite3UpperToLower[*z];
  }
  rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
  sqliteFree(zLowerName);
  if( rc==0 ){
    return pDef;
  }

  /* Create a new ephemeral function definition for the overloaded
  ** function */
  pNew = sqliteMalloc( sizeof(*pNew) + strlen(pDef->zName) );
  if( pNew==0 ){
    return pDef;
  }
  *pNew = *pDef;
  strcpy(pNew->zName, pDef->zName);
  pNew->xFunc = xFunc;
  pNew->pUserData = pArg;
  pNew->flags |= SQLITE_FUNC_EPHEM;
  return pNew;
}

#endif /* SQLITE_OMIT_VIRTUALTABLE */

⌨️ 快捷键说明

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