blob: d7d7515bd026a51d813ccbe49114483a89d38074 [file] [log] [blame]
drhb9bb7c12006-06-11 23:41:55 +00001/*
2** 2006 June 10
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11*************************************************************************
12** This file contains code used to help implement virtual tables.
13**
14** $Id: vtab.c,v 1.1 2006/06/11 23:41:56 drh Exp $
15*/
16#ifndef SQLITE_OMIT_VIRTUALTABLE
17#include "sqliteInt.h"
18
19/*
20** External API function used to create a new virtual-table module.
21*/
22int sqlite3_create_module(
23 sqlite3 *db, /* Database in which module is registered */
24 const char *zName, /* Name assigned to this module */
25 const sqlite3_module *pModule /* The definition of the module */
26){
27 sqlite3HashInsert(&db->aModule, zName, strlen(zName), (void*)pModule);
28 sqlite3ResetInternalSchema(db, 0);
29 return SQLITE_OK;
30}
31
32
33/*
34** Clear any and all virtual-table information from the Table record.
35** This routine is called, for example, just before deleting the Table
36** record.
37*/
38void sqlite3VtabClear(Table *p){
39 if( p->pVtab ){
40 assert( p->pModule!=0 );
41 p->pModule->xDisconnect(p->pVtab);
42 }
43 if( p->azModuleArg ){
44 int i;
45 for(i=0; i<p->nModuleArg; i++){
46 sqliteFree(p->azModuleArg[i]);
47 }
48 sqliteFree(p->azModuleArg);
49 }
50}
51
52/*
53** Add a new module argument to pTable->azModuleArg[].
54** The string is not copied - the pointer is stored. The
55** string will be freed automatically when the table is
56** deleted.
57*/
58static void addModuleArgument(Table *pTable, char *zArg){
59 int i = pTable->nModuleArg++;
60 pTable->azModuleArg = sqliteRealloc(pTable->azModuleArg,
61 sizeof(char*)*(pTable->nModuleArg+1));
62 if( pTable->azModuleArg==0 ){
63 pTable->nModuleArg = 0;
64 sqliteFree(zArg);
65 }else{
66 pTable->azModuleArg[i] = zArg;
67 pTable->azModuleArg[i+1] = 0;
68 }
69}
70
71/*
72** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
73** statement. The module name has been parsed, but the optional list
74** of parameters that follow the module name are still pending.
75*/
76void sqlite3VtabBeginParse(
77 Parse *pParse, /* Parsing context */
78 Token *pName1, /* Name of new table, or database name */
79 Token *pName2, /* Name of new table or NULL */
80 Token *pModuleName /* Name of the module for the virtual table */
81){
82 Table *pTable; /* The new virtual table */
83
84 sqlite3StartTable(pParse, pName1, pName2, 0, 0, 0);
85 pTable = pParse->pNewTable;
86 if( pTable==0 ) return;
87 pTable->isVirtual = 1;
88 pTable->nModuleArg = 0;
89 addModuleArgument(pTable, sqlite3NameFromToken(pModuleName));
90 pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z;
91}
92
93/*
94** This routine takes the module argument that has been accumulating
95** in pParse->zArg[] and appends it to the list of arguments on the
96** virtual table currently under construction in pParse->pTable.
97*/
98static void addArgumentToVtab(Parse *pParse){
99 if( pParse->nArgUsed && pParse->pNewTable ){
100 addModuleArgument(pParse->pNewTable, sqliteStrDup(pParse->zArg));
101 }
102 pParse->nArgUsed = 0;
103}
104
105/*
106** The parser calls this routine after the CREATE VIRTUAL TABLE statement
107** has been completely parsed.
108*/
109void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
110 Table *pTab; /* The table being constructed */
111 sqlite3 *db; /* The database connection */
112 char *zModule; /* The module name of the table: USING modulename */
113
114 addArgumentToVtab(pParse);
115 sqliteFree(pParse->zArg);
116 pParse->zArg = 0;
117 pParse->nArgAlloc = 0;
118
119 /* Lookup the module name. */
120 pTab = pParse->pNewTable;
121 if( pTab==0 ) return;
122 db = pParse->db;
123 if( pTab->nModuleArg<1 ) return;
124 pParse->pNewTable = 0;
125 zModule = pTab->azModuleArg[0];
126 pTab->pModule = (sqlite3_module*)sqlite3HashFind(&db->aModule,
127 zModule, strlen(zModule));
128
129 /* If the CREATE VIRTUAL TABLE statement is being entered for the
130 ** first time (in other words if the virtual table is actually being
131 ** created now instead of just being read out of sqlite_master) then
132 ** do additional initialization work and store the statement text
133 ** in the sqlite_master table.
134 */
135 if( !db->init.busy ){
136 char *zStmt;
137 int iDb;
138 Vdbe *v;
139 if( pTab->pModule==0 ){
140 sqlite3ErrorMsg(pParse, "unknown module: %s", zModule);
141 }
142
143 /* Compute the complete text of the CREATE VIRTUAL TABLE statement */
144 if( pEnd ){
145 pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n;
146 }
147 zStmt = sqlite3MPrintf("CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
148
149 /* A slot for the record has already been allocated in the
150 ** SQLITE_MASTER table. We just need to update that slot with all
151 ** the information we've collected. The rowid for the preallocated
152 ** slot is the top the stack.
153 */
154 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
155 sqlite3NestedParse(pParse,
156 "UPDATE %Q.%s "
157 "SET type='table', name=%Q, tbl_name=%Q, rootpage=NULL, sql=%Q "
158 "WHERE rowid=#0",
159 db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
160 pTab->zName,
161 pTab->zName,
162 zStmt
163 );
164 sqliteFree(zStmt);
165 v = sqlite3GetVdbe(pParse);
166 sqlite3VdbeOp3(v, OP_VCreate, 0, 0, pTab->zName, P3_DYNAMIC);
167 sqlite3ChangeCookie(db, v, iDb);
168 }
169
170 /* If we are rereading the sqlite_master table and we happen to
171 ** currently know the module for the new table, create an
172 ** sqlite3_vtab instance.
173 */
174 else if( pTab->pModule ){
175 sqlite3_module *pMod = pTab->pModule;
176 assert( pMod->xConnect );
177 pMod->xConnect(db, pMod, pTab->nModuleArg, pTab->azModuleArg, &pTab->pVtab);
178 }
179}
180
181/*
182** The parser calls this routine when it sees the first token
183** of an argument to the module name in a CREATE VIRTUAL TABLE statement.
184*/
185void sqlite3VtabArgInit(Parse *pParse){
186 addArgumentToVtab(pParse);
187 pParse->nArgUsed = 0;
188}
189
190/*
191** The parser calls this routine for each token after the first token
192** in an argument to the module name in a CREATE VIRTUAL TABLE statement.
193*/
194void sqlite3VtabArgExtend(Parse *pParse, Token *p){
195 if( pParse->nArgUsed + p->n + 2 >= pParse->nArgAlloc ){
196 pParse->nArgAlloc = pParse->nArgAlloc*2 + p->n + 200;
197 pParse->zArg = sqliteRealloc(pParse->zArg, pParse->nArgAlloc);
198 if( pParse->zArg==0 ){
199 pParse->nArgAlloc = 0;
200 return;
201 }
202 }
203 if( pParse->nArgUsed ){
204 pParse->zArg[pParse->nArgUsed++] = ' ';
205 }
206 memcpy(&pParse->zArg[pParse->nArgUsed], p->z, p->n);
207 pParse->nArgUsed += p->n;
208 pParse->zArg[pParse->nArgUsed] = 0;
209}
210
211#endif /* SQLITE_OMIT_VIRTUALTABLE */