blob: a444bf1b8bb5c715300f1e30ef6dcd7dc19c9972 [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**
drha75803d2006-06-12 12:50:23 +000016** $Id: test8.c,v 1.5 2006/06/12 12:50:23 drh 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*/
28static void appendToEchoModule(const sqlite3_module *pModule, const char *zArg){
29 int flags = (TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
30 Tcl_SetVar((Tcl_Interp *)(pModule->pAux), "echo_module", zArg, flags);
31}
32
danielk1977fe3fcbe22006-06-12 12:08:45 +000033static void appendToEchoTable(const sqlite3_vtab *pTab, const char *zArg){
34 int flags = (TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
35 Tcl_SetVar((Tcl_Interp *)(pTab), "echo_module", zArg, flags);
36}
37
danielk19777e6ebfb2006-06-12 11:24:37 +000038/*
39** This function is called from within the echo-modules xCreate and
40** xConnect methods. The argc and argv arguments are copies of those
41** passed to the calling method. This function is responsible for
42** calling sqlite3_declare_vtab() to declare the schema of the virtual
43** table being created or connected.
44**
45** If the constructor was passed just one argument, i.e.:
46**
47** CREATE TABLE t1 AS echo(t2);
48**
49** Then t2 is assumed to be the name of a *real* database table. The
50** schema of the virtual table is declared by passing a copy of the
51** CREATE TABLE statement for the real table to sqlite3_declare_vtab().
52** Hence, the virtual table should have exactly the same column names and
53** types as the real table.
54*/
55static int echoDeclareVtab(sqlite3 *db, int argc, char **argv){
56 int rc = SQLITE_OK;
57
58 if( argc==2 ){
59 sqlite3_stmt *pStmt = 0;
60 sqlite3_prepare(db,
61 "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",
62 -1, &pStmt, 0);
63 sqlite3_bind_text(pStmt, 1, argv[1], -1, 0);
64 if( sqlite3_step(pStmt)==SQLITE_ROW ){
65 const char *zCreateTable = sqlite3_column_text(pStmt, 0);
drha75803d2006-06-12 12:50:23 +000066#ifndef SQLITE_OMIT_VIRTUALTABLE
danielk19777e6ebfb2006-06-12 11:24:37 +000067 sqlite3_declare_vtab(db, zCreateTable);
drha75803d2006-06-12 12:50:23 +000068#endif
danielk19777e6ebfb2006-06-12 11:24:37 +000069 } else {
70 rc = SQLITE_ERROR;
71 }
72 sqlite3_finalize(pStmt);
73 }
74
75 return rc;
76}
77
drhb9bb7c12006-06-11 23:41:55 +000078/* Methods for the echo module */
79static int echoCreate(
80 sqlite3 *db,
81 const sqlite3_module *pModule,
82 int argc, char **argv,
83 sqlite3_vtab **ppVtab
84){
85 int i;
drhb9bb7c12006-06-11 23:41:55 +000086 *ppVtab = pModule->pAux;
87
danielk197778efaba2006-06-12 06:09:17 +000088 appendToEchoModule(pModule, "xCreate");
drhb9bb7c12006-06-11 23:41:55 +000089 for(i=0; i<argc; i++){
danielk197778efaba2006-06-12 06:09:17 +000090 appendToEchoModule(pModule, argv[i]);
drhb9bb7c12006-06-11 23:41:55 +000091 }
danielk197778efaba2006-06-12 06:09:17 +000092
danielk19777e6ebfb2006-06-12 11:24:37 +000093 echoDeclareVtab(db, argc, argv);
drhb9bb7c12006-06-11 23:41:55 +000094 return 0;
95}
96static int echoConnect(
97 sqlite3 *db,
98 const sqlite3_module *pModule,
99 int argc, char **argv,
100 sqlite3_vtab **ppVtab
101){
102 int i;
103 Tcl_Interp *interp = pModule->pAux;
104 *ppVtab = pModule->pAux;
105
106 Tcl_SetVar(interp, "echo_module", "xConnect", TCL_GLOBAL_ONLY);
107 for(i=0; i<argc; i++){
108 Tcl_SetVar(interp, "echo_module", argv[i],
109 TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
110 }
danielk19777e6ebfb2006-06-12 11:24:37 +0000111
112 echoDeclareVtab(db, argc, argv);
drhb9bb7c12006-06-11 23:41:55 +0000113 return 0;
114}
115static int echoDisconnect(sqlite3_vtab *pVtab){
danielk1977fe3fcbe22006-06-12 12:08:45 +0000116 appendToEchoTable(pVtab, "xDisconnect");
drhb9bb7c12006-06-11 23:41:55 +0000117 return 0;
118}
119static int echoDestroy(sqlite3_vtab *pVtab){
120 Tcl_Interp *interp = (Tcl_Interp*)pVtab;
121 Tcl_SetVar(interp, "echo_module", "xDestroy",
122 TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
123 return 0;
124}
125
126/*
127** A virtual table module that merely echos method calls into TCL
128** variables.
129*/
130static sqlite3_module echoModule = {
danielk197778efaba2006-06-12 06:09:17 +0000131 0, /* iVersion */
132 "echo", /* zName */
133 0, /* pAux */
drhb9bb7c12006-06-11 23:41:55 +0000134 echoCreate,
135 echoConnect,
danielk197778efaba2006-06-12 06:09:17 +0000136 0, /* xBestIndex */
drhb9bb7c12006-06-11 23:41:55 +0000137 echoDisconnect,
138 echoDestroy,
139};
140
141/*
142** Decode a pointer to an sqlite3 object.
143*/
144static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
145 *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
146 return TCL_OK;
147}
148
149
150/*
151** Register the echo virtual table module.
152*/
153static int register_echo_module(
154 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
155 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
156 int objc, /* Number of arguments */
157 Tcl_Obj *CONST objv[] /* Command arguments */
158){
159 sqlite3 *db;
160 if( objc!=2 ){
161 Tcl_WrongNumArgs(interp, 1, objv, "DB");
162 return TCL_ERROR;
163 }
164 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
165 echoModule.pAux = interp;
166#ifndef SQLITE_OMIT_VIRTUALTABLE
167 sqlite3_create_module(db, "echo", &echoModule);
168#endif
169 return TCL_OK;
170}
171
172
173/*
174** Register commands with the TCL interpreter.
175*/
176int Sqlitetest8_Init(Tcl_Interp *interp){
177 static struct {
178 char *zName;
179 Tcl_ObjCmdProc *xProc;
180 void *clientData;
181 } aObjCmd[] = {
182 { "register_echo_module", register_echo_module, 0 },
183 };
184 int i;
185 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
186 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
187 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
188 }
189 return TCL_OK;
190}