*** 1,4 **** ! ***Proposed Virtual Table Mechanism For SQLite*** A virtual table is an object that is registered with an open SQLite database connection. From the perspective --- 1,4 ---- ! ***Virtual Tables In SQLite*** A virtual table is an object that is registered with an open SQLite database connection. From the perspective *************** *** 11,227 **** The virtual table mechanism allows an application to publish interfaces that are accessible from SQL statements as if they were tables. ! SQL statements can in general do anything to a virtual table that they ! can do to a real table, though particular virtual table implementations ! might restrict what actions are allowed on a case by case basis. A virtual table might represent an in-memory data structures. Or it might represent a view of data on disk that is not in the SQLite format. Or the application might compute the content of the virtual table on demand. ! Two data structures are used by the virtual table ! implementation: ! typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; ! typedef struct sqlite3_vtab sqlite3_vtab; ! The sqlite3_vtab_cursor structure is an opaque type that ! represents a pointer into a virtual table. The ! sqlite3_vtab structure is the method table for the virtual ! table object. A read-only instance of this structure defines ! the format of the virtual table and the callback methods that ! are invoked when SQL is executed against the virtual table. ! The sqlite3_vtab structure looks like this: ! struct sqlite3_vtab { ! /* The first group of fields define the format of the virtual table ! */ ! int nCol; /* Number of columns in the virtual table */ ! const char **azColName; /* Name of each column */ ! const char **azDeclType; /* Declared data type for each column */ ! int intPrimKey; /* The INTEGER PRIMARY KEY column. -1 for none */ ! int nIdx; /* Number of indices */ ! const struct _vtab_idx { /* For each index */ ! int nCol; /* Number of columns in this index */ ! const struct _vtab_idx_col { /* For each column in this index */ ! int iCol; /* The column in table that is indexed */ ! const char *zColl; /* Name of the collating sequence */ ! } *aCol; ! } *aIdx; ! ! /* The rest of this structure define callbacks for various operations ! ** against the virtual table ! */ ! int (*xConnect)(void *pArg); ! int (*xOpenCursor)(void *pArg, sqlite3_vtab_cursor**, int idx); ! int (*xInsert)(sqlite3_vtab_cursor*, sqlite3_int64 rowid, int nCol, ! sqlite3_value **apCol); ! sqlite3_int64 (*xNewRowid)(sqlite3_vtab_cursor*); ! int (*xDelete)(sqlite3_vtab_cursor*); ! int (*xSeek)(sqlite3_vtab_cursor*, int, sqlite3_value**, int*); ! int (*xFirst)(sqlite3_vtab_cursor*); ! int (*xLast)(sqlite3_vtab_cursor*); ! int (*xNext)(sqlite3_vtab_cursor*); ! int (*xPrevious)(sqlite3_vtab_cursor*); ! int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); ! int (*xCloseCursor)(sqlite3_vtab_cursor*); ! int (*xBegin)(void *pArg); ! int (*xSync)(void *pArg); ! int (*xCommit)(void *pArg); ! int (*xRollback)(void *pArg); ! int (*xIsInTrans)(void *pArg); ! void (*xDisconnect)(void *pArg); ! }; ! A virtual table implementation must define and initialize an ! instance of the sqlite_vtab structure and pass a pointer to ! that structure into the sqlite3_create_virtual_table API in ! order to register the virtual table object with an SQLite ! database connection. The details of how a sqlite3_vtab ! object must be initialized are documented separately. ! ! The sqlite3_create_virtual_table API used to create a new ! virtual table is as follows: ! ! int sqlite3_create_virtual_table( ! sqlite3 *db, ! const char *zTableName, ! const sqlite3_vtab *pVTab, ! void *pArg ! ); ! The zTableName paramater is the name of the table to be created. ! The pVTab parameter defines the characteristics of the table. ! The pArg parameter can have additional information needed by ! the virtual table instance. The pArg parameter is passed ! unaltered into many of the callback methods defined in the sqlite3_vtab structure. ! ----- ! _The latest thoughts on virtual tables as of 2006-06-02:_ ! ! A virtual table is created using SQL as follows: ! CREATE TABLE vtabname USING c_module(arg-list); ! For example, suppose we want to create a virtual table that ! will do full-text search on the content of email messages: ! ! CREATE TABLE emailfts USING fulltextsearch1; ! ! The "fulltextsearch1" identifier is associated with a C-language ! module that is registered separately, in a manner similar to ! the way collating sequences and user-defined functions are ! registered. The argument-list to the module is optional. No ! arguments are shown in the example above, though in practice we ! would probably add arguments to specify various options to the ! full text search engine, such as what tokenizer and stemmer ! algorithms to use and whether or not token positional information ! should be stored in order to help with phrase queries. ! ! In the fulltextsearch1 module, the columns of the virtual ! table are fixed. One can image a more sophisticated implementation ! in which the columns are specified by arguments: ! ! CREATE TABLE emailfts USING fts2( ! docid INTEGER PRIMARY KEY, ! subj TEXT INDEXED, ! body TEXT INDEXED ! ); ! The comma-separate arguments to the C-language module in a ! virtual table create statement can be any arbitrary sequence ! of tokens. The arguments are passed into the module as a ! array of strings, one string for each argument. The module ! is responsible for parsing the arguments. In the example ! above, we would expect the module to create a virtual table ! containing three columns named docid, subj, and body. We ! further expect the virtual table to cause docid to be the ! rowid and that subj and body are both columns that participate ! in the full-text index. In this example, the internal parser ! in fts2 would interpret its arguments very much like a standard ! SQL table declaration. ! ! But arguments do not have to be interpreted this way. The ! arguments could be used to specify optional parameters. ! Consider the following example: ! ! CREATE TABLE emailfts3 USING fts3( ! stemmer = porter, ! retain content = off, ! fast phrase searching = off ); ! Here we have a example of a full-text search ! engine that has fixed column names, but is configured to ! select a different stemmer, to store only the index and not the ! original text of the documents being indexed, and to use a slower ! but more disk-space efficient algorithm for doing phrase searching. ! ! All of the examples above are hypothetical. They are intended to ! show the flexibility of the virtual table mechanism. An actual ! full-text search virtual table might work differently from the ! examples above. The examples are intended to illustrate the ! power and flexibility of virtual tables, not to serve as a ! design spec for full-text search. ! ! The CREATE TABLE statements for virtual tables ! are stored in the SQLITE_MASTER table and are reread when a ! new connection is created or after a schema change. The ! implementation modules (the "fulltextsearch1") need not be ! registered at the time the virtual table is created. ! But the virtual table cannot be used until after the ! module has been registered. ! ! A full-text index would require additional real tables and/or ! indices to store auxiliary information needed to help speed ! the full-text search. These additional tables and indices ! would be created automatically, if they do not already exist, ! when the CREATE TABLE statement is first executed, or when ! the fulltextsearch1 module is first registered - whichever ! comes second. Triggers would also be created to cause ! changes to the email table to make corresponding changes to ! the real tables and indices that back the virtual table. ! A new C-language API will be developed that allows the ! module to mark these triggers as protected so that they ! cannot be accidently dropped. These triggers would also ! provent other processes from modifying the email table unless ! they had the fulltestsearch1 module registered. ! ! To better support full-text search, a new binary operator called ! "MATCH" will be provided. The default operation of MATCH is to ! call a function named "match" with parameters which are the left ! and right operands of the MATCH operator. Virtual tables can ! specify alternative processing for the MATCH operator, however. ! The optimizer will detect this and allow virtual tables to perform ! the MATCH operation for themselves. Thus, full-text query ! statements can be of the form: ! ! SELECT * FROM emailfts WHERE body MATCH 'search string' ! ORDER BY date DESC LIMIT 10; ! ! A default implementation of the MATCH procedure will do full ! text search without using indices. This will be slow for ! large data sets, but will provide consistent results even ! in the absence of a full-text index. ! ! ---- ! ! ! Potential uses: ! ! *: Access to SQLite's internal symbol table information. ! ! *: Access to variables in the host scripting language. ! ! *: A full-text search interface ! ! *: Spatial Indexes ! ! *: Enabling SQL manipulation of data in statistics packages like R ! *: Constructing a federated group of SQLite engines on a cluster for large scale data mining. ! *: Make a completely different backing store for SQLite tables: memory mapped files, other databases, etc. --- 11,214 ---- The virtual table mechanism allows an application to publish interfaces that are accessible from SQL statements as if they were tables. ! SQL statements can in general do almost anything to a virtual table that they ! can do to a real table. There are some exceptions, though. ! ! *: You cannot create a trigger on a virtual table ! *: You cannot create additional indices on a virtual table. ! (Virtual tables can have indices but that must be built into ! the virtual table implementation. They cannot be added separately ! using CREATE INDEX statements.) ! *: You cannot run ALTER TABLE commands against a virtual table. ! ! Particular virtual table implementations might impose additional ! constraints. For example, some virtual implementations might ! provide read-only tables. Or some virtual table implementations ! might allow INSERT or DELETE but not UPDATE. A virtual table might represent an in-memory data structures. Or it might represent a view of data on disk that is not in the SQLite format. Or the application might compute the content of the virtual table on demand. ! Here are some postulated uses for virtual tables: ! *: Access to SQLite's internal symbol table information. ! *: Access to variables in the host scripting language. ! *: A full-text search interface ! *: Spatial Indexes ! *: Enabling SQL manipulation of data in statistics packages like R ! *: Constructing a federated group of SQLite engines on a cluster ! for large scale data mining. ! *: Make a completely different backing store for SQLite tables: ! memory mapped files, other databases, etc. ! ! *Usage* ! ! Create a virtual table using a CREATE VIRTUAL TABLE statement. ! This statement creates a table with a particular name and associates ! the table with a "module". ! ! CREATE TABLE tablename USING modulename; ! ! You can also provide comma-separated arguments to the module ! following the module name: ! ! CREATE TABLE tablename USING modulename(arg1, arg2, ...); ! ! The format of the arguments to the module is very general. ! Each argument can consist of keywords, string literals, ! identifiers, numbers, and punctuation. ! The arguments are passed as written (as text) into a ! constructor for the for the virtual table when the ! virtual table is created and the constructor is responsible ! for parsing and interpreting the arguments. The argument ! syntax is sufficiently general that a virtual table ! implementation can, if it wants to, interpret its arguments ! as column definitions in an ordinary CREATE TABLE statement. ! Or the implementation could impose some other interpretation ! on the arguments. The SQLite core does not care. ! ! Once a virtual table has been created, it can be used like ! any other table with the exceptions noted above and imposed ! by specific virtual table implementations. A virtual table ! is destroyed using the ordinary DROP TABLE syntax. ! *Implementation* ! Several new data structures are used by the virtual table ! implementation: + typedef struct sqlite3_vtab sqlite3_vtab; + typedef struct sqlite3_index_info sqlite3_index_info; + typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; + typedef struct sqlite3_module sqlite3_module; ! The sqlite3_module structure defines a module object ! used to implement a virtual table. Think of a module ! as a class from which you can construct multiple virtual ! tables having similar properties. For example, one might ! have a module that provides read-only access to ! comma-separated-value (CSV) files on disk. That one ! module can then be used to create several virtual tables ! where each virtual table refers to a different CSV file. ! ! The module structure contains ! methods that are invoked by SQLite to perform various ! actions on the virtual table such as creating new instances ! of a virtual table or destroying old ones, reading and writing ! data, searching for and deleting, updating, or inserting ! rows. The module structure is explained in more detail ! below. ! Each virtual table instance is represented by an sqlite3_vtab structure. + The sqlite3_vtab structure looks like this: ! struct sqlite3_vtab { ! const sqlite3_module *pModule; ! }; ! Virtual table implementation will normally ! subclass this structure to add additional fields ! that are private to that implementation. ! ! The sqlite3_vtab_cursor structure ! represents a pointer into a virtual table. ! This is what an sqlite3_vtab_cursor looks like: ! struct sqlite3_vtab_cursor { ! sqlite3_vtab *pVtab; ! }; ! Once again, useful implementation will likely subclass ! this structure to add additional fields that are ! private to the implementation. ! ! The sqlite3_index_info structure is used to pass ! information into out of the xBestIndex method of ! the module that implements a virtual table. For ! additional information on this structure, see the ! VirtualTableBestIndexMethod documentation. ! ! Before a CREATE VIRTUAL TABLE statement can be run, ! the module specified in that statement must be ! registered with the database connection. This ! is accomplished using this routine: ! ! int sqlite3_create_module( ! sqlite3 *db, /* SQLite connection to register module with */ ! const char *zName, /* Name of the module */ ! const sqlite3_module *, /* Methods for the module */ ! void * /* Client data for xCreate/xConnect */ ); ! The sqlite3_create_module() command associates a module ! name with an sqlite3_module structure and a separate ! client data that is specific to each module. The ! module structure looks like this: ! ! struct sqlite3_module { ! int iVersion; ! const char *zName; ! int (*xCreate)(sqlite3*, void *pAux, ! int argc, char **argv, ! sqlite3_vtab **ppVTab); ! int (*xConnect)(sqlite3*, void *pAux, ! int argc, char **argv, ! sqlite3_vtab **ppVTab); ! int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); ! int (*xDisconnect)(sqlite3_vtab *pVTab); ! int (*xDestroy)(sqlite3_vtab *pVTab); ! int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); ! int (*xClose)(sqlite3_vtab_cursor*); ! int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, ! int argc, sqlite3_value **argv); ! int (*xNext)(sqlite3_vtab_cursor*); ! int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); ! int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid); ! int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite_int64 *); ! int (*xBegin)(sqlite3_vtab *pVTab); ! int (*xSync)(sqlite3_vtab *pVTab); ! int (*xCommit)(sqlite3_vtab *pVTab); ! int (*xRollback)(sqlite3_vtab *pVTab); ! }; ! The module structure defines all of the methods for each ! virtual table object. The module structure also contains ! the iVersion field which defines the particular edition of ! the module table structure. Currently, iVersion is always ! 1, but in future releases of SQLite the module structure ! definition might be extended with additional methods and in ! that case the iVersion value will be increased. ! ! The module structure also contains the zName field which ! is the name of the module used for error messages. ! ! The rest of the module structure consists of methods used ! to implement various features of the virtual table. ! Details on what each of these methods do are provided ! on the VirtualTableMethods page. ! ! *Creating New Virtual Tables* ! ! Follow these steps to create your own virtual table: ! ! 1: Write all necessary methods. ! 2: Create an instance of the sqlite3_module structure ! containing pointers to all the methods from step 1. ! 3: Register your sqlite3_module structure using the ! sqlite3_create_module() API. ! 4: Run a CREATE VIRTUAL TABLE command that specifies ! your module in the USING clause. ! ! The only really hard part is step 1. You might want to ! start with an existing virtual table implementation and ! modify it to suit your needs. There are several virtual ! table methods implemented in the SQLite source tree ! (for testing purposes). ! You might can use one of those as a guide. Locate ! these test virtual methods by searching for "sqlite3_create_method". ! You might also want to implement your new virtual table ! as a {link: wiki?p=LoadableExtensions loadable extension}.