mirror of
				https://github.com/sqlite/sqlite.git
				synced 2025-11-03 16:53:36 +03:00 
			
		
		
		
	xShadowName method is added to the sqlite3_module object and is used to identify potential shadow tables. The SQLITE_PREPARE_SHADOW argument to sqlite3_prepare_v3() is defined. It is designed to permit writing to shadow tables, but is currently an unused placeholder. FossilOrigin-Name: 31942b3dd3f66eb0d9977bf1cadc2f2d7be7967cce2b55784be0b939dfef1985
		
			
				
	
	
		
			269 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
** 2018-04-19
 | 
						|
**
 | 
						|
** 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 implements a template virtual-table.
 | 
						|
** Developers can make a copy of this file as a baseline for writing
 | 
						|
** new virtual tables and/or table-valued functions.
 | 
						|
**
 | 
						|
** Steps for writing a new virtual table implementation:
 | 
						|
**
 | 
						|
**     (1)  Make a copy of this file.  Perhaps call it "mynewvtab.c"
 | 
						|
**
 | 
						|
**     (2)  Replace this header comment with something appropriate for
 | 
						|
**          the new virtual table
 | 
						|
**
 | 
						|
**     (3)  Change every occurrence of "templatevtab" to some other string
 | 
						|
**          appropriate for the new virtual table.  Ideally, the new string
 | 
						|
**          should be the basename of the source file: "mynewvtab".  Also
 | 
						|
**          globally change "TEMPLATEVTAB" to "MYNEWVTAB".
 | 
						|
**
 | 
						|
**     (4)  Run a test compilation to make sure the unmodified virtual
 | 
						|
**          table works.
 | 
						|
**
 | 
						|
**     (5)  Begin making incremental changes, testing as you go, to evolve
 | 
						|
**          the new virtual table to do what you want it to do.
 | 
						|
**
 | 
						|
** This template is minimal, in the sense that it uses only the required
 | 
						|
** methods on the sqlite3_module object.  As a result, templatevtab is
 | 
						|
** a read-only and eponymous-only table.  Those limitation can be removed
 | 
						|
** by adding new methods.
 | 
						|
**
 | 
						|
** This template implements an eponymous-only virtual table with a rowid and
 | 
						|
** two columns named "a" and "b".  The table as 10 rows with fixed integer
 | 
						|
** values. Usage example:
 | 
						|
**
 | 
						|
**     SELECT rowid, a, b FROM templatevtab;
 | 
						|
*/
 | 
						|
#if !defined(SQLITEINT_H)
 | 
						|
#include "sqlite3ext.h"
 | 
						|
#endif
 | 
						|
SQLITE_EXTENSION_INIT1
 | 
						|
#include <string.h>
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
/* templatevtab_vtab is a subclass of sqlite3_vtab which is
 | 
						|
** underlying representation of the virtual table
 | 
						|
*/
 | 
						|
typedef struct templatevtab_vtab templatevtab_vtab;
 | 
						|
struct templatevtab_vtab {
 | 
						|
  sqlite3_vtab base;  /* Base class - must be first */
 | 
						|
  /* Add new fields here, as necessary */
 | 
						|
};
 | 
						|
 | 
						|
/* templatevtab_cursor is a subclass of sqlite3_vtab_cursor which will
 | 
						|
** serve as the underlying representation of a cursor that scans
 | 
						|
** over rows of the result
 | 
						|
*/
 | 
						|
typedef struct templatevtab_cursor templatevtab_cursor;
 | 
						|
struct templatevtab_cursor {
 | 
						|
  sqlite3_vtab_cursor base;  /* Base class - must be first */
 | 
						|
  /* Insert new fields here.  For this templatevtab we only keep track
 | 
						|
  ** of the rowid */
 | 
						|
  sqlite3_int64 iRowid;      /* The rowid */
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
** The templatevtabConnect() method is invoked to create a new
 | 
						|
** template virtual table.
 | 
						|
**
 | 
						|
** Think of this routine as the constructor for templatevtab_vtab objects.
 | 
						|
**
 | 
						|
** All this routine needs to do is:
 | 
						|
**
 | 
						|
**    (1) Allocate the templatevtab_vtab object and initialize all fields.
 | 
						|
**
 | 
						|
**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
 | 
						|
**        result set of queries against the virtual table will look like.
 | 
						|
*/
 | 
						|
static int templatevtabConnect(
 | 
						|
  sqlite3 *db,
 | 
						|
  void *pAux,
 | 
						|
  int argc, const char *const*argv,
 | 
						|
  sqlite3_vtab **ppVtab,
 | 
						|
  char **pzErr
 | 
						|
){
 | 
						|
  templatevtab_vtab *pNew;
 | 
						|
  int rc;
 | 
						|
 | 
						|
  rc = sqlite3_declare_vtab(db,
 | 
						|
           "CREATE TABLE x(a,b)"
 | 
						|
       );
 | 
						|
  /* For convenience, define symbolic names for the index to each column. */
 | 
						|
#define TEMPLATEVTAB_A  0
 | 
						|
#define TEMPLATEVTAB_B  1
 | 
						|
  if( rc==SQLITE_OK ){
 | 
						|
    pNew = sqlite3_malloc( sizeof(*pNew) );
 | 
						|
    *ppVtab = (sqlite3_vtab*)pNew;
 | 
						|
    if( pNew==0 ) return SQLITE_NOMEM;
 | 
						|
    memset(pNew, 0, sizeof(*pNew));
 | 
						|
  }
 | 
						|
  return rc;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** This method is the destructor for templatevtab_vtab objects.
 | 
						|
*/
 | 
						|
static int templatevtabDisconnect(sqlite3_vtab *pVtab){
 | 
						|
  templatevtab_vtab *p = (templatevtab_vtab*)pVtab;
 | 
						|
  sqlite3_free(p);
 | 
						|
  return SQLITE_OK;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Constructor for a new templatevtab_cursor object.
 | 
						|
*/
 | 
						|
static int templatevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
 | 
						|
  templatevtab_cursor *pCur;
 | 
						|
  pCur = sqlite3_malloc( sizeof(*pCur) );
 | 
						|
  if( pCur==0 ) return SQLITE_NOMEM;
 | 
						|
  memset(pCur, 0, sizeof(*pCur));
 | 
						|
  *ppCursor = &pCur->base;
 | 
						|
  return SQLITE_OK;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Destructor for a templatevtab_cursor.
 | 
						|
*/
 | 
						|
static int templatevtabClose(sqlite3_vtab_cursor *cur){
 | 
						|
  templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
 | 
						|
  sqlite3_free(pCur);
 | 
						|
  return SQLITE_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
** Advance a templatevtab_cursor to its next row of output.
 | 
						|
*/
 | 
						|
static int templatevtabNext(sqlite3_vtab_cursor *cur){
 | 
						|
  templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
 | 
						|
  pCur->iRowid++;
 | 
						|
  return SQLITE_OK;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Return values of columns for the row at which the templatevtab_cursor
 | 
						|
** is currently pointing.
 | 
						|
*/
 | 
						|
static int templatevtabColumn(
 | 
						|
  sqlite3_vtab_cursor *cur,   /* The cursor */
 | 
						|
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
 | 
						|
  int i                       /* Which column to return */
 | 
						|
){
 | 
						|
  templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
 | 
						|
  switch( i ){
 | 
						|
    case TEMPLATEVTAB_A:
 | 
						|
      sqlite3_result_int(ctx, 1000 + pCur->iRowid);
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      assert( i==TEMPLATEVTAB_B );
 | 
						|
      sqlite3_result_int(ctx, 2000 + pCur->iRowid);
 | 
						|
      break;
 | 
						|
  }
 | 
						|
  return SQLITE_OK;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Return the rowid for the current row.  In this implementation, the
 | 
						|
** rowid is the same as the output value.
 | 
						|
*/
 | 
						|
static int templatevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
 | 
						|
  templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
 | 
						|
  *pRowid = pCur->iRowid;
 | 
						|
  return SQLITE_OK;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Return TRUE if the cursor has been moved off of the last
 | 
						|
** row of output.
 | 
						|
*/
 | 
						|
static int templatevtabEof(sqlite3_vtab_cursor *cur){
 | 
						|
  templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
 | 
						|
  return pCur->iRowid>=10;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** This method is called to "rewind" the templatevtab_cursor object back
 | 
						|
** to the first row of output.  This method is always called at least
 | 
						|
** once prior to any call to templatevtabColumn() or templatevtabRowid() or 
 | 
						|
** templatevtabEof().
 | 
						|
*/
 | 
						|
static int templatevtabFilter(
 | 
						|
  sqlite3_vtab_cursor *pVtabCursor, 
 | 
						|
  int idxNum, const char *idxStr,
 | 
						|
  int argc, sqlite3_value **argv
 | 
						|
){
 | 
						|
  templatevtab_cursor *pCur = (templatevtab_cursor *)pVtabCursor;
 | 
						|
  pCur->iRowid = 1;
 | 
						|
  return SQLITE_OK;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** SQLite will invoke this method one or more times while planning a query
 | 
						|
** that uses the virtual table.  This routine needs to create
 | 
						|
** a query plan for each invocation and compute an estimated cost for that
 | 
						|
** plan.
 | 
						|
*/
 | 
						|
static int templatevtabBestIndex(
 | 
						|
  sqlite3_vtab *tab,
 | 
						|
  sqlite3_index_info *pIdxInfo
 | 
						|
){
 | 
						|
  pIdxInfo->estimatedCost = (double)10;
 | 
						|
  pIdxInfo->estimatedRows = 10;
 | 
						|
  return SQLITE_OK;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** This following structure defines all the methods for the 
 | 
						|
** virtual table.
 | 
						|
*/
 | 
						|
static sqlite3_module templatevtabModule = {
 | 
						|
  /* iVersion    */ 0,
 | 
						|
  /* xCreate     */ 0,
 | 
						|
  /* xConnect    */ templatevtabConnect,
 | 
						|
  /* xBestIndex  */ templatevtabBestIndex,
 | 
						|
  /* xDisconnect */ templatevtabDisconnect,
 | 
						|
  /* xDestroy    */ 0,
 | 
						|
  /* xOpen       */ templatevtabOpen,
 | 
						|
  /* xClose      */ templatevtabClose,
 | 
						|
  /* xFilter     */ templatevtabFilter,
 | 
						|
  /* xNext       */ templatevtabNext,
 | 
						|
  /* xEof        */ templatevtabEof,
 | 
						|
  /* xColumn     */ templatevtabColumn,
 | 
						|
  /* xRowid      */ templatevtabRowid,
 | 
						|
  /* xUpdate     */ 0,
 | 
						|
  /* xBegin      */ 0,
 | 
						|
  /* xSync       */ 0,
 | 
						|
  /* xCommit     */ 0,
 | 
						|
  /* xRollback   */ 0,
 | 
						|
  /* xFindMethod */ 0,
 | 
						|
  /* xRename     */ 0,
 | 
						|
  /* xSavepoint  */ 0,
 | 
						|
  /* xRelease    */ 0,
 | 
						|
  /* xRollbackTo */ 0,
 | 
						|
  /* xShadowName */ 0
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
#ifdef _WIN32
 | 
						|
__declspec(dllexport)
 | 
						|
#endif
 | 
						|
int sqlite3_templatevtab_init(
 | 
						|
  sqlite3 *db, 
 | 
						|
  char **pzErrMsg, 
 | 
						|
  const sqlite3_api_routines *pApi
 | 
						|
){
 | 
						|
  int rc = SQLITE_OK;
 | 
						|
  SQLITE_EXTENSION_INIT2(pApi);
 | 
						|
  rc = sqlite3_create_module(db, "templatevtab", &templatevtabModule, 0);
 | 
						|
  return rc;
 | 
						|
}
 |