4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
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.
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.
16 ** The FS virtual table is created as follows:
18 ** CREATE VIRTUAL TABLE tbl USING fs(idx);
20 ** where idx is the name of a table in the db with 2 columns. The virtual
21 ** table also has two columns - file path and file contents.
23 ** The first column of table idx must be an IPK, and the second contains file
24 ** paths. For example:
26 ** CREATE TABLE idx(id INTEGER PRIMARY KEY, path TEXT);
27 ** INSERT INTO idx VALUES(4, '/etc/passwd');
29 ** Adding the row to the idx table automatically creates a row in the
30 ** virtual table with rowid=4, path=/etc/passwd and a text field that
31 ** contains data read from file /etc/passwd on disk.
33 #include "sqliteInt.h"
38 #include <sys/types.h>
49 #ifndef SQLITE_OMIT_VIRTUALTABLE
51 typedef struct fs_vtab fs_vtab
;
52 typedef struct fs_cursor fs_cursor
;
55 ** A fs virtual-table object
60 char *zDb
; /* Name of db containing zTbl */
61 char *zTbl
; /* Name of docid->file map table */
64 /* A fs cursor object */
66 sqlite3_vtab_cursor base
;
74 ** This function is the implementation of both the xConnect and xCreate
75 ** methods of the fs virtual table.
77 ** The argv[] array contains the following:
79 ** argv[0] -> module name ("fs")
80 ** argv[1] -> database name
81 ** argv[2] -> table name
82 ** argv[...] -> other module argument fields.
87 int argc
, const char *const*argv
,
88 sqlite3_vtab
**ppVtab
,
94 const char *zDb
= argv
[1];
97 *pzErr
= sqlite3_mprintf("wrong number of arguments");
102 nByte
= sizeof(fs_vtab
) + (int)strlen(zTbl
) + 1 + (int)strlen(zDb
) + 1;
103 pVtab
= (fs_vtab
*)sqlite3MallocZero( nByte
);
104 if( !pVtab
) return SQLITE_NOMEM
;
106 pVtab
->zTbl
= (char *)&pVtab
[1];
107 pVtab
->zDb
= &pVtab
->zTbl
[strlen(zTbl
)+1];
109 memcpy(pVtab
->zTbl
, zTbl
, strlen(zTbl
));
110 memcpy(pVtab
->zDb
, zDb
, strlen(zDb
));
111 *ppVtab
= &pVtab
->base
;
112 sqlite3_declare_vtab(db
, "CREATE TABLE xyz(path TEXT, data TEXT)");
116 /* Note that for this virtual table, the xCreate and xConnect
117 ** methods are identical. */
119 static int fsDisconnect(sqlite3_vtab
*pVtab
){
123 /* The xDisconnect and xDestroy methods are also the same */
126 ** Open a new fs cursor.
128 static int fsOpen(sqlite3_vtab
*pVTab
, sqlite3_vtab_cursor
**ppCursor
){
130 pCur
= sqlite3MallocZero(sizeof(fs_cursor
));
131 *ppCursor
= &pCur
->base
;
136 ** Close a fs cursor.
138 static int fsClose(sqlite3_vtab_cursor
*cur
){
139 fs_cursor
*pCur
= (fs_cursor
*)cur
;
140 sqlite3_finalize(pCur
->pStmt
);
141 sqlite3_free(pCur
->zBuf
);
146 static int fsNext(sqlite3_vtab_cursor
*cur
){
147 fs_cursor
*pCur
= (fs_cursor
*)cur
;
150 rc
= sqlite3_step(pCur
->pStmt
);
151 if( rc
==SQLITE_ROW
|| rc
==SQLITE_DONE
) rc
= SQLITE_OK
;
157 sqlite3_vtab_cursor
*pVtabCursor
,
158 int idxNum
, const char *idxStr
,
159 int argc
, sqlite3_value
**argv
162 fs_cursor
*pCur
= (fs_cursor
*)pVtabCursor
;
163 fs_vtab
*p
= (fs_vtab
*)(pVtabCursor
->pVtab
);
165 assert( (idxNum
==0 && argc
==0) || (idxNum
==1 && argc
==1) );
167 char *zStmt
= sqlite3_mprintf(
168 "SELECT * FROM %Q.%Q WHERE rowid=?", p
->zDb
, p
->zTbl
);
169 if( !zStmt
) return SQLITE_NOMEM
;
170 rc
= sqlite3_prepare_v2(p
->db
, zStmt
, -1, &pCur
->pStmt
, 0);
173 sqlite3_bind_value(pCur
->pStmt
, 1, argv
[0]);
176 char *zStmt
= sqlite3_mprintf("SELECT * FROM %Q.%Q", p
->zDb
, p
->zTbl
);
177 if( !zStmt
) return SQLITE_NOMEM
;
178 rc
= sqlite3_prepare_v2(p
->db
, zStmt
, -1, &pCur
->pStmt
, 0);
183 rc
= fsNext(pVtabCursor
);
188 static int fsColumn(sqlite3_vtab_cursor
*cur
, sqlite3_context
*ctx
, int i
){
189 fs_cursor
*pCur
= (fs_cursor
*)cur
;
191 assert( i
==0 || i
==1 );
193 sqlite3_result_value(ctx
, sqlite3_column_value(pCur
->pStmt
, 0));
195 const char *zFile
= (const char *)sqlite3_column_text(pCur
->pStmt
, 1);
200 fd
= open(zFile
, O_RDONLY
);
201 if( fd
<0 ) return SQLITE_IOERR
;
204 if( sbuf
.st_size
>=pCur
->nAlloc
){
205 int nNew
= sbuf
.st_size
*2;
207 if( nNew
<1024 ) nNew
= 1024;
209 zNew
= sqlite3Realloc(pCur
->zBuf
, nNew
);
218 n
= (int)read(fd
, pCur
->zBuf
, sbuf
.st_size
);
220 if( n
!=sbuf
.st_size
) return SQLITE_ERROR
;
221 pCur
->nBuf
= sbuf
.st_size
;
222 pCur
->zBuf
[pCur
->nBuf
] = '\0';
224 sqlite3_result_text(ctx
, pCur
->zBuf
, -1, SQLITE_TRANSIENT
);
229 static int fsRowid(sqlite3_vtab_cursor
*cur
, sqlite_int64
*pRowid
){
230 fs_cursor
*pCur
= (fs_cursor
*)cur
;
231 *pRowid
= sqlite3_column_int64(pCur
->pStmt
, 0);
235 static int fsEof(sqlite3_vtab_cursor
*cur
){
236 fs_cursor
*pCur
= (fs_cursor
*)cur
;
237 return (sqlite3_data_count(pCur
->pStmt
)==0);
240 static int fsBestIndex(sqlite3_vtab
*tab
, sqlite3_index_info
*pIdxInfo
){
243 for(ii
=0; ii
<pIdxInfo
->nConstraint
; ii
++){
244 struct sqlite3_index_constraint
const *pCons
= &pIdxInfo
->aConstraint
[ii
];
245 if( pCons
->iColumn
<0 && pCons
->usable
246 && pCons
->op
==SQLITE_INDEX_CONSTRAINT_EQ
){
247 struct sqlite3_index_constraint_usage
*pUsage
;
248 pUsage
= &pIdxInfo
->aConstraintUsage
[ii
];
250 pUsage
->argvIndex
= 1;
251 pIdxInfo
->idxNum
= 1;
252 pIdxInfo
->estimatedCost
= 1.0;
261 ** A virtual table module that provides read-only access to a
262 ** Tcl global variable namespace.
264 static sqlite3_module fsModule
= {
271 fsOpen
, /* xOpen - open a cursor */
272 fsClose
, /* xClose - close a cursor */
273 fsFilter
, /* xFilter - configure scan constraints */
274 fsNext
, /* xNext - advance a cursor */
275 fsEof
, /* xEof - check for end of scan */
276 fsColumn
, /* xColumn - read data */
277 fsRowid
, /* xRowid - read data */
288 ** Decode a pointer to an sqlite3 object.
290 extern int getDbPointer(Tcl_Interp
*interp
, const char *zA
, sqlite3
**ppDb
);
293 ** Register the echo virtual table module.
295 static int register_fs_module(
296 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
297 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
298 int objc
, /* Number of arguments */
299 Tcl_Obj
*CONST objv
[] /* Command arguments */
303 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
306 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
307 #ifndef SQLITE_OMIT_VIRTUALTABLE
308 sqlite3_create_module(db
, "fs", &fsModule
, (void *)interp
);
317 ** Register commands with the TCL interpreter.
319 int Sqlitetestfs_Init(Tcl_Interp
*interp
){
320 #ifndef SQLITE_OMIT_VIRTUALTABLE
323 Tcl_ObjCmdProc
*xProc
;
326 { "register_fs_module", register_fs_module
, 0 },
329 for(i
=0; i
<sizeof(aObjCmd
)/sizeof(aObjCmd
[0]); i
++){
330 Tcl_CreateObjCommand(interp
, aObjCmd
[i
].zName
,
331 aObjCmd
[i
].xProc
, aObjCmd
[i
].clientData
, 0);