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

📄 test8.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 3 页
字号:
/*** 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.***************************************************************************** Code for testing the virtual table interfaces.  This code** is not included in the SQLite library.  It is used for automated** testing of the SQLite library.**** $Id: test8.c,v 1.48 2007/07/20 00:35:59 drh Exp $*/#include "sqliteInt.h"#include "tcl.h"#include "os.h"#include <stdlib.h>#include <string.h>#ifndef SQLITE_OMIT_VIRTUALTABLEtypedef struct echo_vtab echo_vtab;typedef struct echo_cursor echo_cursor;/*** The test module defined in this file uses four global Tcl variables to** commicate with test-scripts:****     $::echo_module**     $::echo_module_sync_fail**     $::echo_module_begin_fail**     $::echo_module_cost**** The variable ::echo_module is a list. Each time one of the following** methods is called, one or more elements are appended to the list.** This is used for automated testing of virtual table modules.**** The ::echo_module_sync_fail variable is set by test scripts and read** by code in this file. If it is set to the name of a real table in the** the database, then all xSync operations on echo virtual tables that** use the named table as a backing store will fail.*//* ** An echo virtual-table object.**** echo.vtab.aIndex is an array of booleans. The nth entry is true if ** the nth column of the real table is the left-most column of an index** (implicit or otherwise). In other words, if SQLite can optimize** a query like "SELECT * FROM real_table WHERE col = ?".**** Member variable aCol[] contains copies of the column names of the real** table.*/struct echo_vtab {  sqlite3_vtab base;  Tcl_Interp *interp;     /* Tcl interpreter containing debug variables */  sqlite3 *db;            /* Database connection */  int isPattern;  char *zThis;            /* Name of the echo table */  char *zTableName;       /* Name of the real table */  char *zLogName;         /* Name of the log table */  int nCol;               /* Number of columns in the real table */  int *aIndex;            /* Array of size nCol. True if column has an index */  char **aCol;            /* Array of size nCol. Column names */};/* An echo cursor object */struct echo_cursor {  sqlite3_vtab_cursor base;  sqlite3_stmt *pStmt;};/*** Convert an SQL-style quoted string into a normal string by removing** the quote characters.  The conversion is done in-place.  If the** input does not begin with a quote character, then this routine** is a no-op.**** Examples:****     "abc"   becomes   abc**     'xyz'   becomes   xyz**     [pqr]   becomes   pqr**     `mno`   becomes   mno*/static void dequoteString(char *z){  int quote;  int i, j;  if( z==0 ) return;  quote = z[0];  switch( quote ){    case '\'':  break;    case '"':   break;    case '`':   break;                /* For MySQL compatibility */    case '[':   quote = ']';  break;  /* For MS SqlServer compatibility */    default:    return;  }  for(i=1, j=0; z[i]; i++){    if( z[i]==quote ){      if( z[i+1]==quote ){        z[j++] = quote;        i++;      }else{        z[j++] = 0;        break;      }    }else{      z[j++] = z[i];    }  }}/*** Retrieve the column names for the table named zTab via database** connection db. SQLITE_OK is returned on success, or an sqlite error** code otherwise.**** If successful, the number of columns is written to *pnCol. *paCol is** set to point at sqliteMalloc()'d space containing the array of** nCol column names. The caller is responsible for calling sqliteFree** on *paCol.*/static int getColumnNames(  sqlite3 *db,   const char *zTab,  char ***paCol,   int *pnCol){  char **aCol = 0;  char *zSql;  sqlite3_stmt *pStmt = 0;  int rc = SQLITE_OK;  int nCol = 0;  /* Prepare the statement "SELECT * FROM <tbl>". The column names  ** of the result set of the compiled SELECT will be the same as  ** the column names of table <tbl>.  */  zSql = sqlite3MPrintf("SELECT * FROM %Q", zTab);  if( !zSql ){    rc = SQLITE_NOMEM;    goto out;  }  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);  sqliteFree(zSql);  if( rc==SQLITE_OK ){    int ii;    int nBytes;    char *zSpace;    nCol = sqlite3_column_count(pStmt);    /* Figure out how much space to allocate for the array of column names     ** (including space for the strings themselves). Then allocate it.    */    nBytes = sizeof(char *) * nCol;    for(ii=0; ii<nCol; ii++){      nBytes += (strlen(sqlite3_column_name(pStmt, ii)) + 1);    }    aCol = (char **)sqliteMalloc(nBytes);    if( !aCol ){      rc = SQLITE_NOMEM;      goto out;    }    /* Copy the column names into the allocated space and set up the    ** pointers in the aCol[] array.    */    zSpace = (char *)(&aCol[nCol]);    for(ii=0; ii<nCol; ii++){      aCol[ii] = zSpace;      zSpace += sprintf(zSpace, "%s", sqlite3_column_name(pStmt, ii));      zSpace++;    }    assert( (zSpace-nBytes)==(char *)aCol );  }  *paCol = aCol;  *pnCol = nCol;out:  sqlite3_finalize(pStmt);  return rc;}/*** Parameter zTab is the name of a table in database db with nCol ** columns. This function allocates an array of integers nCol in ** size and populates it according to any implicit or explicit ** indices on table zTab.**** If successful, SQLITE_OK is returned and *paIndex set to point ** at the allocated array. Otherwise, an error code is returned.**** See comments associated with the member variable aIndex above ** "struct echo_vtab" for details of the contents of the array.*/static int getIndexArray(  sqlite3 *db,             /* Database connection */  const char *zTab,        /* Name of table in database db */  int nCol,  int **paIndex){  sqlite3_stmt *pStmt = 0;  int *aIndex = 0;  int rc;  char *zSql;  /* Allocate space for the index array */  aIndex = (int *)sqliteMalloc(sizeof(int) * nCol);  if( !aIndex ){    rc = SQLITE_NOMEM;    goto get_index_array_out;  }  /* Compile an sqlite pragma to loop through all indices on table zTab */  zSql = sqlite3MPrintf("PRAGMA index_list(%s)", zTab);  if( !zSql ){    rc = SQLITE_NOMEM;    goto get_index_array_out;  }  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);  sqliteFree(zSql);  /* For each index, figure out the left-most column and set the   ** corresponding entry in aIndex[] to 1.  */  while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){    const char *zIdx = (const char *)sqlite3_column_text(pStmt, 1);    sqlite3_stmt *pStmt2 = 0;    zSql = sqlite3MPrintf("PRAGMA index_info(%s)", zIdx);    if( !zSql ){      rc = SQLITE_NOMEM;      goto get_index_array_out;    }    rc = sqlite3_prepare(db, zSql, -1, &pStmt2, 0);    sqliteFree(zSql);    if( pStmt2 && sqlite3_step(pStmt2)==SQLITE_ROW ){      int cid = sqlite3_column_int(pStmt2, 1);      assert( cid>=0 && cid<nCol );      aIndex[cid] = 1;    }    if( pStmt2 ){      rc = sqlite3_finalize(pStmt2);    }    if( rc!=SQLITE_OK ){      goto get_index_array_out;    }  }get_index_array_out:  if( pStmt ){    int rc2 = sqlite3_finalize(pStmt);    if( rc==SQLITE_OK ){      rc = rc2;    }  }  if( rc!=SQLITE_OK ){    sqliteFree(aIndex);    aIndex = 0;  }  *paIndex = aIndex;  return rc;}/*** Global Tcl variable $echo_module is a list. This routine appends** the string element zArg to that list in interpreter interp.*/static void appendToEchoModule(Tcl_Interp *interp, const char *zArg){  int flags = (TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);  Tcl_SetVar(interp, "echo_module", (zArg?zArg:""), flags);}/*** This function is called from within the echo-modules xCreate and** xConnect methods. The argc and argv arguments are copies of those ** passed to the calling method. This function is responsible for** calling sqlite3_declare_vtab() to declare the schema of the virtual** table being created or connected.**** If the constructor was passed just one argument, i.e.:****   CREATE TABLE t1 AS echo(t2);**** Then t2 is assumed to be the name of a *real* database table. The** schema of the virtual table is declared by passing a copy of the ** CREATE TABLE statement for the real table to sqlite3_declare_vtab().** Hence, the virtual table should have exactly the same column names and ** types as the real table.*/static int echoDeclareVtab(  echo_vtab *pVtab,   sqlite3 *db ){  int rc = SQLITE_OK;  if( pVtab->zTableName ){    sqlite3_stmt *pStmt = 0;    sqlite3_prepare(db,         "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",        -1, &pStmt, 0);    sqlite3_bind_text(pStmt, 1, pVtab->zTableName, -1, 0);    if( sqlite3_step(pStmt)==SQLITE_ROW ){      int rc2;      const char *zCreateTable = (const char *)sqlite3_column_text(pStmt, 0);      rc = sqlite3_declare_vtab(db, zCreateTable);      rc2 = sqlite3_finalize(pStmt);      if( rc==SQLITE_OK ){        rc = rc2;      }    } else {      rc = sqlite3_finalize(pStmt);      if( rc==SQLITE_OK ){         rc = SQLITE_ERROR;      }    }    if( rc==SQLITE_OK ){      rc = getColumnNames(db, pVtab->zTableName, &pVtab->aCol, &pVtab->nCol);    }    if( rc==SQLITE_OK ){      rc = getIndexArray(db, pVtab->zTableName, pVtab->nCol, &pVtab->aIndex);    }  }  return rc;}/*** This function frees all runtime structures associated with the virtual** table pVtab.*/static int echoDestructor(sqlite3_vtab *pVtab){  echo_vtab *p = (echo_vtab*)pVtab;  sqliteFree(p->aIndex);  sqliteFree(p->aCol);  sqliteFree(p->zThis);  sqliteFree(p->zTableName);  sqliteFree(p->zLogName);  sqliteFree(p);  return 0;}/*** This function is called to do the work of the xConnect() method -** to allocate the required in-memory structures for a newly connected** virtual table.*/static int echoConstructor(  sqlite3 *db,  void *pAux,  int argc, const char *const*argv,  sqlite3_vtab **ppVtab,  char **pzErr){  int i;  echo_vtab *pVtab;  /* Allocate the sqlite3_vtab/echo_vtab structure itself */  pVtab = sqliteMalloc( sizeof(*pVtab) );  if( !pVtab ){    return SQLITE_NOMEM;  }  pVtab->interp = (Tcl_Interp *)pAux;  pVtab->db = db;  /* Allocate echo_vtab.zThis */  pVtab->zThis = sqlite3MPrintf("%s", argv[2]);  if( !pVtab->zThis ){    echoDestructor((sqlite3_vtab *)pVtab);    return SQLITE_NOMEM;  }  /* Allocate echo_vtab.zTableName */  if( argc>3 ){    pVtab->zTableName = sqlite3MPrintf("%s", argv[3]);    dequoteString(pVtab->zTableName);    if( pVtab->zTableName && pVtab->zTableName[0]=='*' ){

⌨️ 快捷键说明

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