xref: /sqlite-3.40.0/src/test_schema.c (revision 1e32bed3)
1954ce99cSdanielk1977 /*
2954ce99cSdanielk1977 ** 2006 June 10
3954ce99cSdanielk1977 **
4954ce99cSdanielk1977 ** The author disclaims copyright to this source code.  In place of
5954ce99cSdanielk1977 ** a legal notice, here is a blessing:
6954ce99cSdanielk1977 **
7954ce99cSdanielk1977 **    May you do good and not evil.
8954ce99cSdanielk1977 **    May you find forgiveness for yourself and forgive others.
9954ce99cSdanielk1977 **    May you share freely, never taking more than you give.
10954ce99cSdanielk1977 **
11954ce99cSdanielk1977 *************************************************************************
12954ce99cSdanielk1977 ** Code for testing the virtual table interfaces.  This code
13954ce99cSdanielk1977 ** is not included in the SQLite library.  It is used for automated
14954ce99cSdanielk1977 ** testing of the SQLite library.
15954ce99cSdanielk1977 */
16954ce99cSdanielk1977 
17428397c1Sdrh /* The code in this file defines a sqlite3 virtual-table module that
18428397c1Sdrh ** provides a read-only view of the current database schema. There is one
19428397c1Sdrh ** row in the schema table for each column in the database schema.
20954ce99cSdanielk1977 */
21954ce99cSdanielk1977 #define SCHEMA \
22954ce99cSdanielk1977 "CREATE TABLE x("                                                            \
23954ce99cSdanielk1977   "database,"          /* Name of database (i.e. main, temp etc.) */         \
24954ce99cSdanielk1977   "tablename,"         /* Name of table */                                   \
25954ce99cSdanielk1977   "cid,"               /* Column number (from left-to-right, 0 upward) */    \
26954ce99cSdanielk1977   "name,"              /* Column name */                                     \
27954ce99cSdanielk1977   "type,"              /* Specified type (i.e. VARCHAR(32)) */               \
28954ce99cSdanielk1977   "not_null,"          /* Boolean. True if NOT NULL was specified */         \
29954ce99cSdanielk1977   "dflt_value,"        /* Default value for this column */                   \
30954ce99cSdanielk1977   "pk"                 /* True if this column is part of the primary key */  \
31954ce99cSdanielk1977 ")"
32954ce99cSdanielk1977 
33954ce99cSdanielk1977 /* If SQLITE_TEST is defined this code is preprocessed for use as part
34954ce99cSdanielk1977 ** of the sqlite test binary "testfixture". Otherwise it is preprocessed
35954ce99cSdanielk1977 ** to be compiled into an sqlite dynamic extension.
36954ce99cSdanielk1977 */
37954ce99cSdanielk1977 #ifdef SQLITE_TEST
38954ce99cSdanielk1977 #  include "sqliteInt.h"
3952b1dbb5Smistachkin #  if defined(INCLUDE_SQLITE_TCL_H)
4052b1dbb5Smistachkin #    include "sqlite_tcl.h"
4152b1dbb5Smistachkin #  else
42954ce99cSdanielk1977 #    include "tcl.h"
4352b1dbb5Smistachkin #  endif
44954ce99cSdanielk1977 #else
45954ce99cSdanielk1977 #  include "sqlite3ext.h"
46954ce99cSdanielk1977   SQLITE_EXTENSION_INIT1
47954ce99cSdanielk1977 #endif
48954ce99cSdanielk1977 
49954ce99cSdanielk1977 #include <stdlib.h>
50954ce99cSdanielk1977 #include <string.h>
51954ce99cSdanielk1977 #include <assert.h>
52954ce99cSdanielk1977 
53954ce99cSdanielk1977 typedef struct schema_vtab schema_vtab;
54954ce99cSdanielk1977 typedef struct schema_cursor schema_cursor;
55954ce99cSdanielk1977 
56954ce99cSdanielk1977 /* A schema table object */
57954ce99cSdanielk1977 struct schema_vtab {
58954ce99cSdanielk1977   sqlite3_vtab base;
59954ce99cSdanielk1977   sqlite3 *db;
60954ce99cSdanielk1977 };
61954ce99cSdanielk1977 
62954ce99cSdanielk1977 /* A schema table cursor object */
63954ce99cSdanielk1977 struct schema_cursor {
64954ce99cSdanielk1977   sqlite3_vtab_cursor base;
65954ce99cSdanielk1977   sqlite3_stmt *pDbList;
66954ce99cSdanielk1977   sqlite3_stmt *pTableList;
67954ce99cSdanielk1977   sqlite3_stmt *pColumnList;
68954ce99cSdanielk1977   int rowid;
69954ce99cSdanielk1977 };
70954ce99cSdanielk1977 
71954ce99cSdanielk1977 /*
7226e4a8b1Sdrh ** None of this works unless we have virtual tables.
7326e4a8b1Sdrh */
7426e4a8b1Sdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
7526e4a8b1Sdrh 
7626e4a8b1Sdrh /*
77954ce99cSdanielk1977 ** Table destructor for the schema module.
78954ce99cSdanielk1977 */
schemaDestroy(sqlite3_vtab * pVtab)79954ce99cSdanielk1977 static int schemaDestroy(sqlite3_vtab *pVtab){
8017435752Sdrh   sqlite3_free(pVtab);
81954ce99cSdanielk1977   return 0;
82954ce99cSdanielk1977 }
83954ce99cSdanielk1977 
84954ce99cSdanielk1977 /*
85954ce99cSdanielk1977 ** Table constructor for the schema module.
86954ce99cSdanielk1977 */
schemaCreate(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)87954ce99cSdanielk1977 static int schemaCreate(
88954ce99cSdanielk1977   sqlite3 *db,
89954ce99cSdanielk1977   void *pAux,
90e4102960Sdrh   int argc, const char *const*argv,
914ca8aac2Sdrh   sqlite3_vtab **ppVtab,
924ca8aac2Sdrh   char **pzErr
93954ce99cSdanielk1977 ){
94954ce99cSdanielk1977   int rc = SQLITE_NOMEM;
9517435752Sdrh   schema_vtab *pVtab = sqlite3_malloc(sizeof(schema_vtab));
96954ce99cSdanielk1977   if( pVtab ){
97954ce99cSdanielk1977     memset(pVtab, 0, sizeof(schema_vtab));
98954ce99cSdanielk1977     pVtab->db = db;
994b2688abSdanielk1977 #ifndef SQLITE_OMIT_VIRTUALTABLE
100954ce99cSdanielk1977     rc = sqlite3_declare_vtab(db, SCHEMA);
1014b2688abSdanielk1977 #endif
102954ce99cSdanielk1977   }
103954ce99cSdanielk1977   *ppVtab = (sqlite3_vtab *)pVtab;
104954ce99cSdanielk1977   return rc;
105954ce99cSdanielk1977 }
106954ce99cSdanielk1977 
107954ce99cSdanielk1977 /*
108954ce99cSdanielk1977 ** Open a new cursor on the schema table.
109954ce99cSdanielk1977 */
schemaOpen(sqlite3_vtab * pVTab,sqlite3_vtab_cursor ** ppCursor)110954ce99cSdanielk1977 static int schemaOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
111954ce99cSdanielk1977   int rc = SQLITE_NOMEM;
112954ce99cSdanielk1977   schema_cursor *pCur;
11317435752Sdrh   pCur = sqlite3_malloc(sizeof(schema_cursor));
114954ce99cSdanielk1977   if( pCur ){
115954ce99cSdanielk1977     memset(pCur, 0, sizeof(schema_cursor));
116954ce99cSdanielk1977     *ppCursor = (sqlite3_vtab_cursor *)pCur;
117954ce99cSdanielk1977     rc = SQLITE_OK;
118954ce99cSdanielk1977   }
119954ce99cSdanielk1977   return rc;
120954ce99cSdanielk1977 }
121954ce99cSdanielk1977 
122954ce99cSdanielk1977 /*
123954ce99cSdanielk1977 ** Close a schema table cursor.
124954ce99cSdanielk1977 */
schemaClose(sqlite3_vtab_cursor * cur)125954ce99cSdanielk1977 static int schemaClose(sqlite3_vtab_cursor *cur){
126954ce99cSdanielk1977   schema_cursor *pCur = (schema_cursor *)cur;
127954ce99cSdanielk1977   sqlite3_finalize(pCur->pDbList);
128954ce99cSdanielk1977   sqlite3_finalize(pCur->pTableList);
129954ce99cSdanielk1977   sqlite3_finalize(pCur->pColumnList);
13017435752Sdrh   sqlite3_free(pCur);
131954ce99cSdanielk1977   return SQLITE_OK;
132954ce99cSdanielk1977 }
133954ce99cSdanielk1977 
134954ce99cSdanielk1977 /*
135954ce99cSdanielk1977 ** Retrieve a column of data.
136954ce99cSdanielk1977 */
schemaColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int i)137954ce99cSdanielk1977 static int schemaColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
138954ce99cSdanielk1977   schema_cursor *pCur = (schema_cursor *)cur;
139954ce99cSdanielk1977   switch( i ){
140954ce99cSdanielk1977     case 0:
141954ce99cSdanielk1977       sqlite3_result_value(ctx, sqlite3_column_value(pCur->pDbList, 1));
142954ce99cSdanielk1977       break;
143954ce99cSdanielk1977     case 1:
144954ce99cSdanielk1977       sqlite3_result_value(ctx, sqlite3_column_value(pCur->pTableList, 0));
145954ce99cSdanielk1977       break;
146954ce99cSdanielk1977     default:
147954ce99cSdanielk1977       sqlite3_result_value(ctx, sqlite3_column_value(pCur->pColumnList, i-2));
148954ce99cSdanielk1977       break;
149954ce99cSdanielk1977   }
150954ce99cSdanielk1977   return SQLITE_OK;
151954ce99cSdanielk1977 }
152954ce99cSdanielk1977 
153954ce99cSdanielk1977 /*
154954ce99cSdanielk1977 ** Retrieve the current rowid.
155954ce99cSdanielk1977 */
schemaRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)156954ce99cSdanielk1977 static int schemaRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
157954ce99cSdanielk1977   schema_cursor *pCur = (schema_cursor *)cur;
158954ce99cSdanielk1977   *pRowid = pCur->rowid;
159954ce99cSdanielk1977   return SQLITE_OK;
160954ce99cSdanielk1977 }
161954ce99cSdanielk1977 
finalize(sqlite3_stmt ** ppStmt)162954ce99cSdanielk1977 static int finalize(sqlite3_stmt **ppStmt){
163954ce99cSdanielk1977   int rc = sqlite3_finalize(*ppStmt);
164954ce99cSdanielk1977   *ppStmt = 0;
165954ce99cSdanielk1977   return rc;
166954ce99cSdanielk1977 }
167954ce99cSdanielk1977 
schemaEof(sqlite3_vtab_cursor * cur)168a298e90dSdanielk1977 static int schemaEof(sqlite3_vtab_cursor *cur){
169a298e90dSdanielk1977   schema_cursor *pCur = (schema_cursor *)cur;
170a298e90dSdanielk1977   return (pCur->pDbList ? 0 : 1);
171a298e90dSdanielk1977 }
172a298e90dSdanielk1977 
173954ce99cSdanielk1977 /*
174954ce99cSdanielk1977 ** Advance the cursor to the next row.
175954ce99cSdanielk1977 */
schemaNext(sqlite3_vtab_cursor * cur)176954ce99cSdanielk1977 static int schemaNext(sqlite3_vtab_cursor *cur){
1775017dc38Sdanielk1977   int rc = SQLITE_OK;
178954ce99cSdanielk1977   schema_cursor *pCur = (schema_cursor *)cur;
179954ce99cSdanielk1977   schema_vtab *pVtab = (schema_vtab *)(cur->pVtab);
180954ce99cSdanielk1977   char *zSql = 0;
181954ce99cSdanielk1977 
182954ce99cSdanielk1977   while( !pCur->pColumnList || SQLITE_ROW!=sqlite3_step(pCur->pColumnList) ){
183a298e90dSdanielk1977     if( SQLITE_OK!=(rc = finalize(&pCur->pColumnList)) ) goto next_exit;
184954ce99cSdanielk1977 
185954ce99cSdanielk1977     while( !pCur->pTableList || SQLITE_ROW!=sqlite3_step(pCur->pTableList) ){
186a298e90dSdanielk1977       if( SQLITE_OK!=(rc = finalize(&pCur->pTableList)) ) goto next_exit;
187954ce99cSdanielk1977 
188954ce99cSdanielk1977       assert(pCur->pDbList);
189954ce99cSdanielk1977       while( SQLITE_ROW!=sqlite3_step(pCur->pDbList) ){
190a298e90dSdanielk1977         rc = finalize(&pCur->pDbList);
191a298e90dSdanielk1977         goto next_exit;
192954ce99cSdanielk1977       }
193954ce99cSdanielk1977 
194954ce99cSdanielk1977       /* Set zSql to the SQL to pull the list of tables from the
195*1e32bed3Sdrh       ** sqlite_schema (or sqlite_temp_schema) table of the database
19660ec914cSpeter.d.reid       ** identified by the row pointed to by the SQL statement pCur->pDbList
197954ce99cSdanielk1977       ** (iterating through a "PRAGMA database_list;" statement).
198954ce99cSdanielk1977       */
199954ce99cSdanielk1977       if( sqlite3_column_int(pCur->pDbList, 0)==1 ){
200954ce99cSdanielk1977         zSql = sqlite3_mprintf(
201*1e32bed3Sdrh             "SELECT name FROM sqlite_temp_schema WHERE type='table'"
202954ce99cSdanielk1977         );
203954ce99cSdanielk1977       }else{
204954ce99cSdanielk1977         sqlite3_stmt *pDbList = pCur->pDbList;
205954ce99cSdanielk1977         zSql = sqlite3_mprintf(
206*1e32bed3Sdrh             "SELECT name FROM %Q.sqlite_schema WHERE type='table'",
207954ce99cSdanielk1977              sqlite3_column_text(pDbList, 1)
208954ce99cSdanielk1977         );
209954ce99cSdanielk1977       }
210954ce99cSdanielk1977       if( !zSql ){
211954ce99cSdanielk1977         rc = SQLITE_NOMEM;
212a298e90dSdanielk1977         goto next_exit;
213954ce99cSdanielk1977       }
214954ce99cSdanielk1977 
215954ce99cSdanielk1977       rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pTableList, 0);
216954ce99cSdanielk1977       sqlite3_free(zSql);
217a298e90dSdanielk1977       if( rc!=SQLITE_OK ) goto next_exit;
218954ce99cSdanielk1977     }
219954ce99cSdanielk1977 
220954ce99cSdanielk1977     /* Set zSql to the SQL to the table_info pragma for the table currently
221954ce99cSdanielk1977     ** identified by the rows pointed to by statements pCur->pDbList and
222954ce99cSdanielk1977     ** pCur->pTableList.
223954ce99cSdanielk1977     */
224954ce99cSdanielk1977     zSql = sqlite3_mprintf("PRAGMA %Q.table_info(%Q)",
225954ce99cSdanielk1977         sqlite3_column_text(pCur->pDbList, 1),
226954ce99cSdanielk1977         sqlite3_column_text(pCur->pTableList, 0)
227954ce99cSdanielk1977     );
228954ce99cSdanielk1977 
229954ce99cSdanielk1977     if( !zSql ){
230954ce99cSdanielk1977       rc = SQLITE_NOMEM;
231a298e90dSdanielk1977       goto next_exit;
232954ce99cSdanielk1977     }
233954ce99cSdanielk1977     rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pColumnList, 0);
234954ce99cSdanielk1977     sqlite3_free(zSql);
235a298e90dSdanielk1977     if( rc!=SQLITE_OK ) goto next_exit;
236954ce99cSdanielk1977   }
237954ce99cSdanielk1977   pCur->rowid++;
238954ce99cSdanielk1977 
239a298e90dSdanielk1977 next_exit:
240954ce99cSdanielk1977   /* TODO: Handle rc */
241a298e90dSdanielk1977   return rc;
242954ce99cSdanielk1977 }
243954ce99cSdanielk1977 
244954ce99cSdanielk1977 /*
245954ce99cSdanielk1977 ** Reset a schema table cursor.
246954ce99cSdanielk1977 */
schemaFilter(sqlite3_vtab_cursor * pVtabCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)247954ce99cSdanielk1977 static int schemaFilter(
248954ce99cSdanielk1977   sqlite3_vtab_cursor *pVtabCursor,
249954ce99cSdanielk1977   int idxNum, const char *idxStr,
250954ce99cSdanielk1977   int argc, sqlite3_value **argv
251954ce99cSdanielk1977 ){
252954ce99cSdanielk1977   int rc;
253954ce99cSdanielk1977   schema_vtab *pVtab = (schema_vtab *)(pVtabCursor->pVtab);
254954ce99cSdanielk1977   schema_cursor *pCur = (schema_cursor *)pVtabCursor;
255954ce99cSdanielk1977   pCur->rowid = 0;
256954ce99cSdanielk1977   finalize(&pCur->pTableList);
257954ce99cSdanielk1977   finalize(&pCur->pColumnList);
258954ce99cSdanielk1977   finalize(&pCur->pDbList);
259954ce99cSdanielk1977   rc = sqlite3_prepare(pVtab->db,"PRAGMA database_list", -1, &pCur->pDbList, 0);
260954ce99cSdanielk1977   return (rc==SQLITE_OK ? schemaNext(pVtabCursor) : rc);
261954ce99cSdanielk1977 }
262954ce99cSdanielk1977 
263954ce99cSdanielk1977 /*
264954ce99cSdanielk1977 ** Analyse the WHERE condition.
265954ce99cSdanielk1977 */
schemaBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)266954ce99cSdanielk1977 static int schemaBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
267954ce99cSdanielk1977   return SQLITE_OK;
268954ce99cSdanielk1977 }
269954ce99cSdanielk1977 
270954ce99cSdanielk1977 /*
271954ce99cSdanielk1977 ** A virtual table module that merely echos method calls into TCL
272954ce99cSdanielk1977 ** variables.
273954ce99cSdanielk1977 */
274954ce99cSdanielk1977 static sqlite3_module schemaModule = {
275954ce99cSdanielk1977   0,                           /* iVersion */
276954ce99cSdanielk1977   schemaCreate,
277954ce99cSdanielk1977   schemaCreate,
278954ce99cSdanielk1977   schemaBestIndex,
279954ce99cSdanielk1977   schemaDestroy,
280954ce99cSdanielk1977   schemaDestroy,
281954ce99cSdanielk1977   schemaOpen,                  /* xOpen - open a cursor */
282954ce99cSdanielk1977   schemaClose,                 /* xClose - close a cursor */
283954ce99cSdanielk1977   schemaFilter,                /* xFilter - configure scan constraints */
284954ce99cSdanielk1977   schemaNext,                  /* xNext - advance a cursor */
285a298e90dSdanielk1977   schemaEof,                   /* xEof */
286954ce99cSdanielk1977   schemaColumn,                /* xColumn - read data */
287954ce99cSdanielk1977   schemaRowid,                 /* xRowid - read data */
288b7f6f68fSdrh   0,                           /* xUpdate */
289b7f6f68fSdrh   0,                           /* xBegin */
290b7f6f68fSdrh   0,                           /* xSync */
291b7f6f68fSdrh   0,                           /* xCommit */
292b7f6f68fSdrh   0,                           /* xRollback */
293b7f6f68fSdrh   0,                           /* xFindMethod */
294c033b642Sdanielk1977   0,                           /* xRename */
295954ce99cSdanielk1977 };
296954ce99cSdanielk1977 
29726e4a8b1Sdrh #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
298954ce99cSdanielk1977 
299954ce99cSdanielk1977 #ifdef SQLITE_TEST
300954ce99cSdanielk1977 
301954ce99cSdanielk1977 /*
302954ce99cSdanielk1977 ** Decode a pointer to an sqlite3 object.
303954ce99cSdanielk1977 */
30424b58dd7Sdrh extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
305954ce99cSdanielk1977 
306954ce99cSdanielk1977 /*
307954ce99cSdanielk1977 ** Register the schema virtual table module.
308954ce99cSdanielk1977 */
register_schema_module(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])3097617e4a8Smistachkin static int SQLITE_TCLAPI register_schema_module(
310954ce99cSdanielk1977   ClientData clientData, /* Not used */
311954ce99cSdanielk1977   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
312954ce99cSdanielk1977   int objc,              /* Number of arguments */
313954ce99cSdanielk1977   Tcl_Obj *CONST objv[]  /* Command arguments */
314954ce99cSdanielk1977 ){
315954ce99cSdanielk1977   sqlite3 *db;
316954ce99cSdanielk1977   if( objc!=2 ){
317954ce99cSdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "DB");
318954ce99cSdanielk1977     return TCL_ERROR;
319954ce99cSdanielk1977   }
3201f6eec54Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
321954ce99cSdanielk1977 #ifndef SQLITE_OMIT_VIRTUALTABLE
322954ce99cSdanielk1977   sqlite3_create_module(db, "schema", &schemaModule, 0);
323954ce99cSdanielk1977 #endif
324954ce99cSdanielk1977   return TCL_OK;
325954ce99cSdanielk1977 }
326954ce99cSdanielk1977 
327954ce99cSdanielk1977 /*
328954ce99cSdanielk1977 ** Register commands with the TCL interpreter.
329954ce99cSdanielk1977 */
Sqlitetestschema_Init(Tcl_Interp * interp)330954ce99cSdanielk1977 int Sqlitetestschema_Init(Tcl_Interp *interp){
331954ce99cSdanielk1977   static struct {
332954ce99cSdanielk1977      char *zName;
333954ce99cSdanielk1977      Tcl_ObjCmdProc *xProc;
334954ce99cSdanielk1977      void *clientData;
335954ce99cSdanielk1977   } aObjCmd[] = {
336954ce99cSdanielk1977      { "register_schema_module", register_schema_module, 0 },
337954ce99cSdanielk1977   };
338954ce99cSdanielk1977   int i;
339954ce99cSdanielk1977   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
340954ce99cSdanielk1977     Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
341954ce99cSdanielk1977         aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
342954ce99cSdanielk1977   }
343954ce99cSdanielk1977   return TCL_OK;
344954ce99cSdanielk1977 }
345954ce99cSdanielk1977 
346954ce99cSdanielk1977 #else
347954ce99cSdanielk1977 
348954ce99cSdanielk1977 /*
349954ce99cSdanielk1977 ** Extension load function.
350954ce99cSdanielk1977 */
351049d487eSmistachkin #ifdef _WIN32
352049d487eSmistachkin __declspec(dllexport)
353049d487eSmistachkin #endif
sqlite3_schema_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)354049d487eSmistachkin int sqlite3_schema_init(
355954ce99cSdanielk1977   sqlite3 *db,
356954ce99cSdanielk1977   char **pzErrMsg,
357954ce99cSdanielk1977   const sqlite3_api_routines *pApi
358954ce99cSdanielk1977 ){
359954ce99cSdanielk1977   SQLITE_EXTENSION_INIT2(pApi);
3604b2688abSdanielk1977 #ifndef SQLITE_OMIT_VIRTUALTABLE
361954ce99cSdanielk1977   sqlite3_create_module(db, "schema", &schemaModule, 0);
3624b2688abSdanielk1977 #endif
363954ce99cSdanielk1977   return 0;
364954ce99cSdanielk1977 }
365954ce99cSdanielk1977 
366954ce99cSdanielk1977 #endif
367