blob: 5f8112d0928e1449710071ff2f1a7b95ad916d49 [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** Code for testing the virtual table interfaces. This code
13** is not included in the SQLite library. It is used for automated
14** testing of the SQLite library.
15**
danielk19777dabaa12006-06-13 04:11:43 +000016** $Id: test8.c,v 1.7 2006/06/13 04:11:44 danielk1977 Exp $
drhb9bb7c12006-06-11 23:41:55 +000017*/
18#include "sqliteInt.h"
19#include "tcl.h"
20#include "os.h"
21#include <stdlib.h>
22#include <string.h>
23
danielk197778efaba2006-06-12 06:09:17 +000024/*
25** Global Tcl variable $echo_module is a list. This routine appends
26** the string element zArg to that list in interpreter interp.
27*/
drha967e882006-06-13 01:04:52 +000028static void appendToEchoModule(Tcl_Interp *interp, const char *zArg){
danielk197778efaba2006-06-12 06:09:17 +000029 int flags = (TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
drha967e882006-06-13 01:04:52 +000030 Tcl_SetVar(interp, "echo_module", zArg, flags);
danielk197778efaba2006-06-12 06:09:17 +000031}
32
danielk19777e6ebfb2006-06-12 11:24:37 +000033/*
34** This function is called from within the echo-modules xCreate and
35** xConnect methods. The argc and argv arguments are copies of those
36** passed to the calling method. This function is responsible for
37** calling sqlite3_declare_vtab() to declare the schema of the virtual
38** table being created or connected.
39**
40** If the constructor was passed just one argument, i.e.:
41**
42** CREATE TABLE t1 AS echo(t2);
43**
44** Then t2 is assumed to be the name of a *real* database table. The
45** schema of the virtual table is declared by passing a copy of the
46** CREATE TABLE statement for the real table to sqlite3_declare_vtab().
47** Hence, the virtual table should have exactly the same column names and
48** types as the real table.
49*/
50static int echoDeclareVtab(sqlite3 *db, int argc, char **argv){
51 int rc = SQLITE_OK;
52
53 if( argc==2 ){
54 sqlite3_stmt *pStmt = 0;
55 sqlite3_prepare(db,
56 "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",
57 -1, &pStmt, 0);
58 sqlite3_bind_text(pStmt, 1, argv[1], -1, 0);
59 if( sqlite3_step(pStmt)==SQLITE_ROW ){
60 const char *zCreateTable = sqlite3_column_text(pStmt, 0);
drha75803d2006-06-12 12:50:23 +000061#ifndef SQLITE_OMIT_VIRTUALTABLE
danielk19777e6ebfb2006-06-12 11:24:37 +000062 sqlite3_declare_vtab(db, zCreateTable);
drha75803d2006-06-12 12:50:23 +000063#endif
danielk19777e6ebfb2006-06-12 11:24:37 +000064 } else {
65 rc = SQLITE_ERROR;
66 }
67 sqlite3_finalize(pStmt);
68 }
69
70 return rc;
71}
72
drha967e882006-06-13 01:04:52 +000073/* An echo vtab object */
74typedef struct echo_vtab echo_vtab;
75struct echo_vtab {
76 sqlite3_vtab base;
77 Tcl_Interp *interp;
78};
79
drhb9bb7c12006-06-11 23:41:55 +000080/* Methods for the echo module */
81static int echoCreate(
82 sqlite3 *db,
83 const sqlite3_module *pModule,
84 int argc, char **argv,
85 sqlite3_vtab **ppVtab
86){
87 int i;
drha967e882006-06-13 01:04:52 +000088 echo_vtab *pVtab;
drhb9bb7c12006-06-11 23:41:55 +000089
drha967e882006-06-13 01:04:52 +000090 pVtab = sqliteMalloc( sizeof(*pVtab) );
91 *ppVtab = &pVtab->base;
92 pVtab->base.pModule = pModule;
93 pVtab->interp = pModule->pAux;
94 appendToEchoModule(pVtab->interp, "xCreate");
drhb9bb7c12006-06-11 23:41:55 +000095 for(i=0; i<argc; i++){
drha967e882006-06-13 01:04:52 +000096 appendToEchoModule(pVtab->interp, argv[i]);
drhb9bb7c12006-06-11 23:41:55 +000097 }
danielk197778efaba2006-06-12 06:09:17 +000098
danielk19777e6ebfb2006-06-12 11:24:37 +000099 echoDeclareVtab(db, argc, argv);
drhb9bb7c12006-06-11 23:41:55 +0000100 return 0;
101}
102static int echoConnect(
103 sqlite3 *db,
104 const sqlite3_module *pModule,
105 int argc, char **argv,
106 sqlite3_vtab **ppVtab
107){
108 int i;
109 Tcl_Interp *interp = pModule->pAux;
drha967e882006-06-13 01:04:52 +0000110 echo_vtab *pVtab;
drhb9bb7c12006-06-11 23:41:55 +0000111
drha967e882006-06-13 01:04:52 +0000112 pVtab = sqliteMalloc( sizeof(*pVtab) );
113 *ppVtab = &pVtab->base;
114 pVtab->base.pModule = pModule;
115 pVtab->interp = pModule->pAux;
danielk19777dabaa12006-06-13 04:11:43 +0000116 appendToEchoModule(pVtab->interp, "xConnect");
drhb9bb7c12006-06-11 23:41:55 +0000117 for(i=0; i<argc; i++){
danielk19777dabaa12006-06-13 04:11:43 +0000118 appendToEchoModule(pVtab->interp, argv[i]);
drhb9bb7c12006-06-11 23:41:55 +0000119 }
danielk19777e6ebfb2006-06-12 11:24:37 +0000120
121 echoDeclareVtab(db, argc, argv);
drhb9bb7c12006-06-11 23:41:55 +0000122 return 0;
123}
124static int echoDisconnect(sqlite3_vtab *pVtab){
drha967e882006-06-13 01:04:52 +0000125 echo_vtab *p = (echo_vtab*)pVtab;
danielk19777dabaa12006-06-13 04:11:43 +0000126 appendToEchoModule(p->interp, "xDisconnect");
drha967e882006-06-13 01:04:52 +0000127 sqliteFree(pVtab);
drhb9bb7c12006-06-11 23:41:55 +0000128 return 0;
129}
130static int echoDestroy(sqlite3_vtab *pVtab){
drha967e882006-06-13 01:04:52 +0000131 echo_vtab *p = (echo_vtab*)pVtab;
danielk19777dabaa12006-06-13 04:11:43 +0000132 appendToEchoModule(p->interp, "xDestroy");
133 sqliteFree(pVtab);
drhb9bb7c12006-06-11 23:41:55 +0000134 return 0;
135}
136
137/*
drha967e882006-06-13 01:04:52 +0000138** The xBestIndex method for the echo module always returns
139** an index of 123.
140*/
141static int echoBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
142 pIdxInfo->idxNum = 123;
143 return SQLITE_OK;
144}
145
146/*
drhb9bb7c12006-06-11 23:41:55 +0000147** A virtual table module that merely echos method calls into TCL
148** variables.
149*/
150static sqlite3_module echoModule = {
danielk197778efaba2006-06-12 06:09:17 +0000151 0, /* iVersion */
152 "echo", /* zName */
153 0, /* pAux */
drhb9bb7c12006-06-11 23:41:55 +0000154 echoCreate,
155 echoConnect,
drha967e882006-06-13 01:04:52 +0000156 echoBestIndex,
drhb9bb7c12006-06-11 23:41:55 +0000157 echoDisconnect,
158 echoDestroy,
159};
160
161/*
162** Decode a pointer to an sqlite3 object.
163*/
164static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
165 *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
166 return TCL_OK;
167}
168
169
170/*
171** Register the echo virtual table module.
172*/
173static int register_echo_module(
174 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
175 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
176 int objc, /* Number of arguments */
177 Tcl_Obj *CONST objv[] /* Command arguments */
178){
179 sqlite3 *db;
180 if( objc!=2 ){
181 Tcl_WrongNumArgs(interp, 1, objv, "DB");
182 return TCL_ERROR;
183 }
184 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
185 echoModule.pAux = interp;
186#ifndef SQLITE_OMIT_VIRTUALTABLE
187 sqlite3_create_module(db, "echo", &echoModule);
188#endif
189 return TCL_OK;
190}
191
192
193/*
194** Register commands with the TCL interpreter.
195*/
196int Sqlitetest8_Init(Tcl_Interp *interp){
197 static struct {
198 char *zName;
199 Tcl_ObjCmdProc *xProc;
200 void *clientData;
201 } aObjCmd[] = {
202 { "register_echo_module", register_echo_module, 0 },
203 };
204 int i;
205 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
206 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
207 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
208 }
209 return TCL_OK;
210}