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

📄 vtab.c

📁 sqlite的最新源码 This ZIP archive contains preprocessed C code for the SQLite library as individual sour
💻 C
📖 第 1 页 / 共 2 页
字号:
        for(j=i; (j+nDel)<=nType; j++){          zType[j] = zType[j+nDel];        }        if( zType[i]=='\0' && i>0 ){          assert(zType[i-1]==' ');          zType[i-1] = '\0';        }        pTab->aCol[iCol].isHidden = 1;      }    }  }  return rc;}/*** This function is invoked by the parser to call the xConnect() method** of the virtual table pTab. If an error occurs, an error code is returned ** and an error left in pParse.**** This call is a no-op if table pTab is not a virtual table.*/int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){  Module *pMod;  int rc = SQLITE_OK;  if( !pTab || (pTab->tabFlags & TF_Virtual)==0 || pTab->pVtab ){    return SQLITE_OK;  }  pMod = pTab->pMod;  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);    }    sqlite3DbFree(db, 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 = sqlite3DbRealloc(db, (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 sqlite3DbFree(db, ) 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->tabFlags & TF_Virtual)!=0 && !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(db, "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;  char *zErr = 0;  sqlite3_mutex_enter(db->mutex);  pTab = db->pVTab;  if( !pTab ){    sqlite3Error(db, SQLITE_MISUSE, 0);    sqlite3_mutex_leave(db->mutex);    return SQLITE_MISUSE;  }  assert((pTab->tabFlags & TF_Virtual)!=0 && 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->tabFlags & TF_Virtual)==0  ){    pTab->aCol = sParse.pNewTable->aCol;    pTab->nCol = sParse.pNewTable->nCol;    sParse.pNewTable->nCol = 0;    sParse.pNewTable->aCol = 0;    db->pVTab = 0;  } else {    sqlite3Error(db, SQLITE_ERROR, zErr);    sqlite3DbFree(db, zErr);    rc = SQLITE_ERROR;  }  sParse.declareVtab = 0;  sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);  sqlite3DeleteTable(sParse.pNewTable);  sParse.pNewTable = 0;  assert( (rc&0xff)==rc );  rc = sqlite3ApiExit(db, rc);  sqlite3_mutex_leave(db->mutex);  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);    }    (void)sqlite3SafetyOn(db);    if( rc==SQLITE_OK ){      int i;      for(i=0; i<db->nVTrans; i++){        if( db->aVTrans[i]==pTab->pVtab ){          db->aVTrans[i] = db->aVTrans[--db->nVTrans];          break;        }      }      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;  if( db->aVTrans ){    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(db, pVtab);    }    sqlite3DbFree(db, db->aVTrans);    db->nVTrans = 0;    db->aVTrans = 0;  }}/*** 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.**** Set *pzErrmsg to point to a buffer that should be released using ** sqlite3DbFree() containing an error message, if one is available.*/int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){  int i;  int rc = SQLITE_OK;  int rcsafety;  sqlite3_vtab **aVTrans = db->aVTrans;  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);      sqlite3DbFree(db, *pzErrmsg);      *pzErrmsg = pVtab->zErrMsg;      pVtab->zErrMsg = 0;    }  }  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, offsetof(sqlite3_module,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, offsetof(sqlite3_module,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( sqlite3VtabInSync(db) ){    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 ){      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(  sqlite3 *db,    /* Database connection for reporting malloc problems */  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 = 0;  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->tabFlags & TF_Virtual)==0 ) 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 xFindFunction method on the virtual table implementation  ** to see if the implementation wants to overload this function   */  zLowerName = sqlite3DbStrDup(db, pDef->zName);  if( zLowerName ){    for(z=(unsigned char*)zLowerName; *z; z++){      *z = sqlite3UpperToLower[*z];    }    rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);    sqlite3DbFree(db, zLowerName);    if( pVtab->zErrMsg ){      sqlite3Error(db, rc, "%s", pVtab->zErrMsg);      sqlite3DbFree(db, pVtab->zErrMsg);      pVtab->zErrMsg = 0;    }  }  if( rc==0 ){    return pDef;  }  /* Create a new ephemeral function definition for the overloaded  ** function */  pNew = sqlite3DbMallocZero(db, sizeof(*pNew) + strlen(pDef->zName) );  if( pNew==0 ){    return pDef;  }  *pNew = *pDef;  pNew->zName = (char *)&pNew[1];  memcpy(pNew->zName, pDef->zName, strlen(pDef->zName)+1);  pNew->xFunc = xFunc;  pNew->pUserData = pArg;  pNew->flags |= SQLITE_FUNC_EPHEM;  return pNew;}/*** Make sure virtual table pTab is contained in the pParse->apVirtualLock[]** array so that an OP_VBegin will get generated for it.  Add pTab to the** array if it is missing.  If pTab is already in the array, this routine** is a no-op.*/void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){  int i, n;  assert( IsVirtual(pTab) );  for(i=0; i<pParse->nVtabLock; i++){    if( pTab==pParse->apVtabLock[i] ) return;  }  n = (pParse->nVtabLock+1)*sizeof(pParse->apVtabLock[0]);  pParse->apVtabLock = sqlite3_realloc(pParse->apVtabLock, n);  if( pParse->apVtabLock ){    pParse->apVtabLock[pParse->nVtabLock++] = pTab;  }else{    pParse->db->mallocFailed = 1;  }}#endif /* SQLITE_OMIT_VIRTUALTABLE */

⌨️ 快捷键说明

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