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

📄 test8.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    pIdxInfo->estimatedCost = cost;  } else if( useIdx ){    /* Approximation of log2(nRow). */    for( ii=0; ii<(sizeof(int)*8); ii++ ){      if( nRow & (1<<ii) ){        pIdxInfo->estimatedCost = (double)ii;      }    }  } else {    pIdxInfo->estimatedCost = (double)nRow;  }  return rc;}/*** The xUpdate method for echo module virtual tables.** **    apData[0]  apData[1]  apData[2..]****    INTEGER                              DELETE            ****    INTEGER    NULL       (nCol args)    UPDATE (do not set rowid)**    INTEGER    INTEGER    (nCol args)    UPDATE (with SET rowid = <arg1>)****    NULL       NULL       (nCol args)    INSERT INTO (automatic rowid value)**    NULL       INTEGER    (nCol args)    INSERT (incl. rowid value)***/int echoUpdate(  sqlite3_vtab *tab,   int nData,   sqlite3_value **apData,   sqlite_int64 *pRowid){  echo_vtab *pVtab = (echo_vtab *)tab;  sqlite3 *db = pVtab->db;  int rc = SQLITE_OK;  sqlite3_stmt *pStmt;  char *z = 0;               /* SQL statement to execute */  int bindArgZero = 0;       /* True to bind apData[0] to sql var no. nData */  int bindArgOne = 0;        /* True to bind apData[1] to sql var no. 1 */  int i;                     /* Counter variable used by for loops */  assert( nData==pVtab->nCol+2 || nData==1 );  /* Ticket #3083 - make sure we always start a transaction prior to  ** making any changes to a virtual table */  assert( pVtab->inTransaction );  if( simulateVtabError(pVtab, "xUpdate") ){    return SQLITE_ERROR;  }  /* If apData[0] is an integer and nData>1 then do an UPDATE */  if( nData>1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){    char *zSep = " SET";    z = sqlite3_mprintf("UPDATE %Q", pVtab->zTableName);    if( !z ){      rc = SQLITE_NOMEM;    }    bindArgOne = (apData[1] && sqlite3_value_type(apData[1])==SQLITE_INTEGER);    bindArgZero = 1;    if( bindArgOne ){       string_concat(&z, " SET rowid=?1 ", 0, &rc);       zSep = ",";    }    for(i=2; i<nData; i++){      if( apData[i]==0 ) continue;      string_concat(&z, sqlite3_mprintf(          "%s %Q=?%d", zSep, pVtab->aCol[i-2], i), 1, &rc);      zSep = ",";    }    string_concat(&z, sqlite3_mprintf(" WHERE rowid=?%d", nData), 1, &rc);  }  /* If apData[0] is an integer and nData==1 then do a DELETE */  else if( nData==1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){    z = sqlite3_mprintf("DELETE FROM %Q WHERE rowid = ?1", pVtab->zTableName);    if( !z ){      rc = SQLITE_NOMEM;    }    bindArgZero = 1;  }  /* If the first argument is NULL and there are more than two args, INSERT */  else if( nData>2 && sqlite3_value_type(apData[0])==SQLITE_NULL ){    int ii;    char *zInsert = 0;    char *zValues = 0;      zInsert = sqlite3_mprintf("INSERT INTO %Q (", pVtab->zTableName);    if( !zInsert ){      rc = SQLITE_NOMEM;    }    if( sqlite3_value_type(apData[1])==SQLITE_INTEGER ){      bindArgOne = 1;      zValues = sqlite3_mprintf("?");      string_concat(&zInsert, "rowid", 0, &rc);    }    assert((pVtab->nCol+2)==nData);    for(ii=2; ii<nData; ii++){      string_concat(&zInsert,           sqlite3_mprintf("%s%Q", zValues?", ":"", pVtab->aCol[ii-2]), 1, &rc);      string_concat(&zValues,           sqlite3_mprintf("%s?%d", zValues?", ":"", ii), 1, &rc);    }    string_concat(&z, zInsert, 1, &rc);    string_concat(&z, ") VALUES(", 0, &rc);    string_concat(&z, zValues, 1, &rc);    string_concat(&z, ")", 0, &rc);  }  /* Anything else is an error */  else{    assert(0);    return SQLITE_ERROR;  }  if( rc==SQLITE_OK ){    rc = sqlite3_prepare(db, z, -1, &pStmt, 0);  }  assert( rc!=SQLITE_OK || pStmt );  sqlite3_free(z);  if( rc==SQLITE_OK ) {    if( bindArgZero ){      sqlite3_bind_value(pStmt, nData, apData[0]);    }    if( bindArgOne ){      sqlite3_bind_value(pStmt, 1, apData[1]);    }    for(i=2; i<nData && rc==SQLITE_OK; i++){      if( apData[i] ) rc = sqlite3_bind_value(pStmt, i, apData[i]);    }    if( rc==SQLITE_OK ){      sqlite3_step(pStmt);      rc = sqlite3_finalize(pStmt);    }else{      sqlite3_finalize(pStmt);    }  }  if( pRowid && rc==SQLITE_OK ){    *pRowid = sqlite3_last_insert_rowid(db);  }  if( rc!=SQLITE_OK ){    tab->zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", sqlite3_errmsg(db));  }  return rc;}/*** xBegin, xSync, xCommit and xRollback callbacks for echo module** virtual tables. Do nothing other than add the name of the callback** to the $::echo_module Tcl variable.*/static int echoTransactionCall(sqlite3_vtab *tab, const char *zCall){  char *z;  echo_vtab *pVtab = (echo_vtab *)tab;  z = sqlite3_mprintf("echo(%s)", pVtab->zTableName);  if( z==0 ) return SQLITE_NOMEM;  appendToEchoModule(pVtab->interp, zCall);  appendToEchoModule(pVtab->interp, z);  sqlite3_free(z);  return SQLITE_OK;}static int echoBegin(sqlite3_vtab *tab){  int rc;  echo_vtab *pVtab = (echo_vtab *)tab;  Tcl_Interp *interp = pVtab->interp;  const char *zVal;   /* Ticket #3083 - do not start a transaction if we are already in  ** a transaction */  assert( !pVtab->inTransaction );  if( simulateVtabError(pVtab, "xBegin") ){    return SQLITE_ERROR;  }  rc = echoTransactionCall(tab, "xBegin");  if( rc==SQLITE_OK ){    /* Check if the $::echo_module_begin_fail variable is defined. If it is,    ** and it is set to the name of the real table underlying this virtual    ** echo module table, then cause this xSync operation to fail.    */    zVal = Tcl_GetVar(interp, "echo_module_begin_fail", TCL_GLOBAL_ONLY);    if( zVal && 0==strcmp(zVal, pVtab->zTableName) ){      rc = SQLITE_ERROR;    }  }  if( rc==SQLITE_OK ){    pVtab->inTransaction = 1;  }  return rc;}static int echoSync(sqlite3_vtab *tab){  int rc;  echo_vtab *pVtab = (echo_vtab *)tab;  Tcl_Interp *interp = pVtab->interp;  const char *zVal;   /* Ticket #3083 - Only call xSync if we have previously started a  ** transaction */  assert( pVtab->inTransaction );  if( simulateVtabError(pVtab, "xSync") ){    return SQLITE_ERROR;  }  rc = echoTransactionCall(tab, "xSync");  if( rc==SQLITE_OK ){    /* Check if the $::echo_module_sync_fail variable is defined. If it is,    ** and it is set to the name of the real table underlying this virtual    ** echo module table, then cause this xSync operation to fail.    */    zVal = Tcl_GetVar(interp, "echo_module_sync_fail", TCL_GLOBAL_ONLY);    if( zVal && 0==strcmp(zVal, pVtab->zTableName) ){      rc = -1;    }  }  return rc;}static int echoCommit(sqlite3_vtab *tab){  echo_vtab *pVtab = (echo_vtab*)tab;  int rc;  /* Ticket #3083 - Only call xCommit if we have previously started  ** a transaction */  assert( pVtab->inTransaction );  if( simulateVtabError(pVtab, "xCommit") ){    return SQLITE_ERROR;  }  sqlite3BeginBenignMalloc();  rc = echoTransactionCall(tab, "xCommit");  sqlite3EndBenignMalloc();  pVtab->inTransaction = 0;  return rc;}static int echoRollback(sqlite3_vtab *tab){  int rc;  echo_vtab *pVtab = (echo_vtab*)tab;  /* Ticket #3083 - Only call xRollback if we have previously started  ** a transaction */  assert( pVtab->inTransaction );  rc = echoTransactionCall(tab, "xRollback");  pVtab->inTransaction = 0;  return rc;}/*** Implementation of "GLOB" function on the echo module.  Pass** all arguments to the ::echo_glob_overload procedure of TCL** and return the result of that procedure as a string.*/static void overloadedGlobFunction(  sqlite3_context *pContext,  int nArg,  sqlite3_value **apArg){  Tcl_Interp *interp = sqlite3_user_data(pContext);  Tcl_DString str;  int i;  int rc;  Tcl_DStringInit(&str);  Tcl_DStringAppendElement(&str, "::echo_glob_overload");  for(i=0; i<nArg; i++){    Tcl_DStringAppendElement(&str, (char*)sqlite3_value_text(apArg[i]));  }  rc = Tcl_Eval(interp, Tcl_DStringValue(&str));  Tcl_DStringFree(&str);  if( rc ){    sqlite3_result_error(pContext, Tcl_GetStringResult(interp), -1);  }else{    sqlite3_result_text(pContext, Tcl_GetStringResult(interp),                        -1, SQLITE_TRANSIENT);  }  Tcl_ResetResult(interp);}/*** This is the xFindFunction implementation for the echo module.** SQLite calls this routine when the first argument of a function** is a column of an echo virtual table.  This routine can optionally** override the implementation of that function.  It will choose to** do so if the function is named "glob", and a TCL command named** ::echo_glob_overload exists.*/static int echoFindFunction(  sqlite3_vtab *vtab,  int nArg,  const char *zFuncName,  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),  void **ppArg){  echo_vtab *pVtab = (echo_vtab *)vtab;  Tcl_Interp *interp = pVtab->interp;  Tcl_CmdInfo info;  if( strcmp(zFuncName,"glob")!=0 ){    return 0;  }  if( Tcl_GetCommandInfo(interp, "::echo_glob_overload", &info)==0 ){    return 0;  }  *pxFunc = overloadedGlobFunction;  *ppArg = interp;  return 1;}static int echoRename(sqlite3_vtab *vtab, const char *zNewName){  int rc = SQLITE_OK;  echo_vtab *p = (echo_vtab *)vtab;  if( simulateVtabError(p, "xRename") ){    return SQLITE_ERROR;  }  if( p->isPattern ){    int nThis = strlen(p->zThis);    char *zSql = sqlite3MPrintf(0, "ALTER TABLE %s RENAME TO %s%s",         p->zTableName, zNewName, &p->zTableName[nThis]    );    rc = sqlite3_exec(p->db, zSql, 0, 0, 0);    sqlite3_free(zSql);  }  return rc;}/*** A virtual table module that merely "echos" the contents of another** table (like an SQL VIEW).*/static sqlite3_module echoModule = {  0,                         /* iVersion */  echoCreate,  echoConnect,  echoBestIndex,  echoDisconnect,   echoDestroy,  echoOpen,                  /* xOpen - open a cursor */  echoClose,                 /* xClose - close a cursor */  echoFilter,                /* xFilter - configure scan constraints */  echoNext,                  /* xNext - advance a cursor */  echoEof,                   /* xEof */  echoColumn,                /* xColumn - read data */  echoRowid,                 /* xRowid - read data */  echoUpdate,                /* xUpdate - write data */  echoBegin,                 /* xBegin - begin transaction */  echoSync,                  /* xSync - sync transaction */  echoCommit,                /* xCommit - commit transaction */  echoRollback,              /* xRollback - rollback transaction */  echoFindFunction,          /* xFindFunction - function overloading */  echoRename,                /* xRename - rename the table */};/*** Decode a pointer to an sqlite3 object.*/extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);static void moduleDestroy(void *p){  sqlite3_free(p);}/*** Register the echo virtual table module.*/static int register_echo_module(  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */  int objc,              /* Number of arguments */  Tcl_Obj *CONST objv[]  /* Command arguments */){  sqlite3 *db;  EchoModule *pMod;  if( objc!=2 ){    Tcl_WrongNumArgs(interp, 1, objv, "DB");    return TCL_ERROR;  }  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;  pMod = sqlite3_malloc(sizeof(EchoModule));  pMod->interp = interp;  sqlite3_create_module_v2(db, "echo", &echoModule, (void*)pMod, moduleDestroy);  return TCL_OK;}/*** Tcl interface to sqlite3_declare_vtab, invoked as follows from Tcl:**** sqlite3_declare_vtab DB SQL*/static int declare_vtab(  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */  int objc,              /* Number of arguments */  Tcl_Obj *CONST objv[]  /* Command arguments */){  sqlite3 *db;  int rc;  if( objc!=3 ){    Tcl_WrongNumArgs(interp, 1, objv, "DB SQL");    return TCL_ERROR;  }  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;  rc = sqlite3_declare_vtab(db, Tcl_GetString(objv[2]));  if( rc!=SQLITE_OK ){    Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);    return TCL_ERROR;  }  return TCL_OK;}#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE *//*** Register commands with the TCL interpreter.*/int Sqlitetest8_Init(Tcl_Interp *interp){#ifndef SQLITE_OMIT_VIRTUALTABLE  static struct {     char *zName;     Tcl_ObjCmdProc *xProc;     void *clientData;  } aObjCmd[] = {     { "register_echo_module",   register_echo_module, 0 },     { "sqlite3_declare_vtab",   declare_vtab, 0 },  };  int i;  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){    Tcl_CreateObjCommand(interp, aObjCmd[i].zName,         aObjCmd[i].xProc, aObjCmd[i].clientData, 0);  }#endif  return TCL_OK;}

⌨️ 快捷键说明

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