blob: c55f5ccaa13b264ba50c352e0799a8c7b23fccb5 [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**
danielk1977fe3fcbe22006-06-12 12:08:45 +000016** $Id: test8.c,v 1.4 2006/06/12 12:08:45 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*/
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);
66 sqlite3_declare_vtab(db, zCreateTable);
67 } else {
68 rc = SQLITE_ERROR;
69 }
70 sqlite3_finalize(pStmt);
71 }
72
73 return rc;
74}
75
drhb9bb7c12006-06-11 23:41:55 +000076/* Methods for the echo module */
77static int echoCreate(
78 sqlite3 *db,
79 const sqlite3_module *pModule,
80 int argc, char **argv,
81 sqlite3_vtab **ppVtab
82){
83 int i;
drhb9bb7c12006-06-11 23:41:55 +000084 *ppVtab = pModule->pAux;
85
danielk197778efaba2006-06-12 06:09:17 +000086 appendToEchoModule(pModule, "xCreate");
drhb9bb7c12006-06-11 23:41:55 +000087 for(i=0; i<argc; i++){
danielk197778efaba2006-06-12 06:09:17 +000088 appendToEchoModule(pModule, argv[i]);
drhb9bb7c12006-06-11 23:41:55 +000089 }
danielk197778efaba2006-06-12 06:09:17 +000090
danielk19777e6ebfb2006-06-12 11:24:37 +000091 echoDeclareVtab(db, argc, argv);
drhb9bb7c12006-06-11 23:41:55 +000092 return 0;
93}
94static int echoConnect(
95 sqlite3 *db,
96 const sqlite3_module *pModule,
97 int argc, char **argv,
98 sqlite3_vtab **ppVtab
99){
100 int i;
101 Tcl_Interp *interp = pModule->pAux;
102 *ppVtab = pModule->pAux;
103
104 Tcl_SetVar(interp, "echo_module", "xConnect", TCL_GLOBAL_ONLY);
105 for(i=0; i<argc; i++){
106 Tcl_SetVar(interp, "echo_module", argv[i],
107 TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
108 }
danielk19777e6ebfb2006-06-12 11:24:37 +0000109
110 echoDeclareVtab(db, argc, argv);
drhb9bb7c12006-06-11 23:41:55 +0000111 return 0;
112}
113static int echoDisconnect(sqlite3_vtab *pVtab){
danielk1977fe3fcbe22006-06-12 12:08:45 +0000114 appendToEchoTable(pVtab, "xDisconnect");
drhb9bb7c12006-06-11 23:41:55 +0000115 return 0;
116}
117static int echoDestroy(sqlite3_vtab *pVtab){
118 Tcl_Interp *interp = (Tcl_Interp*)pVtab;
119 Tcl_SetVar(interp, "echo_module", "xDestroy",
120 TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
121 return 0;
122}
123
124/*
125** A virtual table module that merely echos method calls into TCL
126** variables.
127*/
128static sqlite3_module echoModule = {
danielk197778efaba2006-06-12 06:09:17 +0000129 0, /* iVersion */
130 "echo", /* zName */
131 0, /* pAux */
drhb9bb7c12006-06-11 23:41:55 +0000132 echoCreate,
133 echoConnect,
danielk197778efaba2006-06-12 06:09:17 +0000134 0, /* xBestIndex */
drhb9bb7c12006-06-11 23:41:55 +0000135 echoDisconnect,
136 echoDestroy,
137};
138
139/*
140** Decode a pointer to an sqlite3 object.
141*/
142static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
143 *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
144 return TCL_OK;
145}
146
147
148/*
149** Register the echo virtual table module.
150*/
151static int register_echo_module(
152 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
153 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
154 int objc, /* Number of arguments */
155 Tcl_Obj *CONST objv[] /* Command arguments */
156){
157 sqlite3 *db;
158 if( objc!=2 ){
159 Tcl_WrongNumArgs(interp, 1, objv, "DB");
160 return TCL_ERROR;
161 }
162 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
163 echoModule.pAux = interp;
164#ifndef SQLITE_OMIT_VIRTUALTABLE
165 sqlite3_create_module(db, "echo", &echoModule);
166#endif
167 return TCL_OK;
168}
169
170
171/*
172** Register commands with the TCL interpreter.
173*/
174int Sqlitetest8_Init(Tcl_Interp *interp){
175 static struct {
176 char *zName;
177 Tcl_ObjCmdProc *xProc;
178 void *clientData;
179 } aObjCmd[] = {
180 { "register_echo_module", register_echo_module, 0 },
181 };
182 int i;
183 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
184 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
185 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
186 }
187 return TCL_OK;
188}