-C Add\scolumn_value,\sdeclare_vtab\sand\screate_module\sto\sthe\sfunction\stable\sused\sby\sdynamic\sextensions.\s(CVS\s3256)
-D 2006-06-15T15:38:42
-F Makefile.in 200f6dc376ecfd9b01e5359c4e0c10c02f649b34
+C Add\stest_schema.c,\scontaining\sa\smodule\sfor\sviewing\sthe\sdatabase\sschema\svia\sa\svirtual\stable.\s(CVS\s3257)
+D 2006-06-15T15:59:19
+F Makefile.in f839b470345d3cb4b0644068474623fe2464b5d3
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F VERSION 301ed2b2c08f5cca242ea56e50a9ed0264a3eb76
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
-F main.mk 3fe86a381432abf3ba96d0276ea85618bcf9e5a1
+F main.mk 5dbef60b29006c0bc3fd9ce78c846f38750302e2
F mkdll.sh 919df5efde876194e3102c6ebc60657d38949909
F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
F mkopcodeh.awk cde995d269aa06c94adbf6455bea0acedb913fa5
F src/sqlite3ext.h fc8647211af0caa9d8e49ab31624b357c1332380
F src/sqliteInt.h 5eb64f1dd9a8b237d147962bc57637d87e044ff4
F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e
-F src/tclsqlite.c 4ad22f354b6e4e137889000e9f585a0590ca39c5
+F src/tclsqlite.c c03bf44bd9f629d4c8d6545788c647b2e846b523
F src/test1.c 40f20775903bc76d3be3e7c026dddcbc221c1cb0
F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b
F src/test3.c 86e99724ee898b119ed575ef9f98618afe7e5e5d
F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
+F src/test_schema.c 533a9ed125a4676a22a20d9e87e6379989d901e9
F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c
F src/test_tclvar.c c52f67fbe06d32804af2ba9a2d7aadfc15f5910c
F src/tokenize.c 6ebcafa6622839968dda4418a7b6945f277a128f
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P fe3e70a7275d68acb6fb8ea5d62bed3e9d8d2766
-R 47a8b2f6537c22850ce9af0f2e0f04a2
+P 25c475087892fea83bce9d140b46651793b85a86
+R fb8cae10b8c9b6f899ced712e7826fd2
U danielk1977
-Z ec60b2bf5c12236743a6bbfcf541f438
+Z 593d3f2a16cc3c6c0ea1ba4705d0de74
--- /dev/null
+/*
+** 2006 June 10
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Code for testing the virtual table interfaces. This code
+** is not included in the SQLite library. It is used for automated
+** testing of the SQLite library.
+**
+** $Id: test_schema.c,v 1.1 2006/06/15 15:59:20 danielk1977 Exp $
+*/
+
+/* The code in this file defines a sqlite3 module that provides
+** a read-only view of the current database schema. There is one
+** row in the schema table for each column in the database.
+*/
+#define SCHEMA \
+"CREATE TABLE x(" \
+ "database," /* Name of database (i.e. main, temp etc.) */ \
+ "tablename," /* Name of table */ \
+ "cid," /* Column number (from left-to-right, 0 upward) */ \
+ "name," /* Column name */ \
+ "type," /* Specified type (i.e. VARCHAR(32)) */ \
+ "not_null," /* Boolean. True if NOT NULL was specified */ \
+ "dflt_value," /* Default value for this column */ \
+ "pk" /* True if this column is part of the primary key */ \
+")"
+
+/* If SQLITE_TEST is defined this code is preprocessed for use as part
+** of the sqlite test binary "testfixture". Otherwise it is preprocessed
+** to be compiled into an sqlite dynamic extension.
+*/
+#ifdef SQLITE_TEST
+ #include "sqliteInt.h"
+ #include "tcl.h"
+ #define MALLOC(x) sqliteRawMalloc(x)
+ #define FREE(x) sqliteFree(x)
+#else
+ #include "sqlite3ext.h"
+ SQLITE_EXTENSION_INIT1
+ #define MALLOC(x) malloc(x)
+ #define FREE(x) free(x)
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+typedef struct schema_vtab schema_vtab;
+typedef struct schema_cursor schema_cursor;
+
+/* A schema table object */
+struct schema_vtab {
+ sqlite3_vtab base;
+ sqlite3 *db;
+};
+
+/* A schema table cursor object */
+struct schema_cursor {
+ sqlite3_vtab_cursor base;
+ sqlite3_stmt *pDbList;
+ sqlite3_stmt *pTableList;
+ sqlite3_stmt *pColumnList;
+ int rowid;
+};
+
+/*
+** Table destructor for the schema module.
+*/
+static int schemaDestroy(sqlite3_vtab *pVtab){
+ FREE(pVtab);
+ return 0;
+}
+
+/*
+** Table constructor for the schema module.
+*/
+static int schemaCreate(
+ sqlite3 *db,
+ void *pAux,
+ int argc, char **argv,
+ sqlite3_vtab **ppVtab
+){
+ int rc = SQLITE_NOMEM;
+ schema_vtab *pVtab = MALLOC(sizeof(schema_vtab));
+ if( pVtab ){
+ memset(pVtab, 0, sizeof(schema_vtab));
+ pVtab->db = db;
+ rc = sqlite3_declare_vtab(db, SCHEMA);
+ }
+ *ppVtab = (sqlite3_vtab *)pVtab;
+ return rc;
+}
+
+/*
+** Open a new cursor on the schema table.
+*/
+static int schemaOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
+ int rc = SQLITE_NOMEM;
+ schema_cursor *pCur;
+ pCur = MALLOC(sizeof(schema_cursor));
+ if( pCur ){
+ memset(pCur, 0, sizeof(schema_cursor));
+ *ppCursor = (sqlite3_vtab_cursor *)pCur;
+ rc = SQLITE_OK;
+ }
+ return rc;
+}
+
+/*
+** Close a schema table cursor.
+*/
+static int schemaClose(sqlite3_vtab_cursor *cur){
+ schema_cursor *pCur = (schema_cursor *)cur;
+ sqlite3_finalize(pCur->pDbList);
+ sqlite3_finalize(pCur->pTableList);
+ sqlite3_finalize(pCur->pColumnList);
+ FREE(pCur);
+ return SQLITE_OK;
+}
+
+/*
+** Retrieve a column of data.
+*/
+static int schemaColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
+ schema_cursor *pCur = (schema_cursor *)cur;
+ switch( i ){
+ case 0:
+ sqlite3_result_value(ctx, sqlite3_column_value(pCur->pDbList, 1));
+ break;
+ case 1:
+ sqlite3_result_value(ctx, sqlite3_column_value(pCur->pTableList, 0));
+ break;
+ default:
+ sqlite3_result_value(ctx, sqlite3_column_value(pCur->pColumnList, i-2));
+ break;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Retrieve the current rowid.
+*/
+static int schemaRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+ schema_cursor *pCur = (schema_cursor *)cur;
+ *pRowid = pCur->rowid;
+ return SQLITE_OK;
+}
+
+static int finalize(sqlite3_stmt **ppStmt){
+ int rc = sqlite3_finalize(*ppStmt);
+ *ppStmt = 0;
+ return rc;
+}
+
+/*
+** Advance the cursor to the next row.
+*/
+static int schemaNext(sqlite3_vtab_cursor *cur){
+ int rc;
+ schema_cursor *pCur = (schema_cursor *)cur;
+ schema_vtab *pVtab = (schema_vtab *)(cur->pVtab);
+ char *zSql = 0;
+
+ while( !pCur->pColumnList || SQLITE_ROW!=sqlite3_step(pCur->pColumnList) ){
+ if( SQLITE_OK!=(rc = finalize(&pCur->pColumnList)) ) goto fail;
+
+ while( !pCur->pTableList || SQLITE_ROW!=sqlite3_step(pCur->pTableList) ){
+ if( SQLITE_OK!=(rc = finalize(&pCur->pTableList)) ) goto fail;
+
+ assert(pCur->pDbList);
+ while( SQLITE_ROW!=sqlite3_step(pCur->pDbList) ){
+ if( SQLITE_OK!=(rc = finalize(&pCur->pDbList)) ) goto fail;
+ return 0;
+ }
+
+ /* Set zSql to the SQL to pull the list of tables from the
+ ** sqlite_master (or sqlite_temp_master) table of the database
+ ** identfied by the row pointed to by the SQL statement pCur->pDbList
+ ** (iterating through a "PRAGMA database_list;" statement).
+ */
+ if( sqlite3_column_int(pCur->pDbList, 0)==1 ){
+ zSql = sqlite3_mprintf(
+ "SELECT name FROM sqlite_temp_master WHERE type='table'"
+ );
+ }else{
+ sqlite3_stmt *pDbList = pCur->pDbList;
+ zSql = sqlite3_mprintf(
+ "SELECT name FROM %Q.sqlite_master WHERE type='table'",
+ sqlite3_column_text(pDbList, 1)
+ );
+ }
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ goto fail;
+ }
+
+ rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pTableList, 0);
+ sqlite3_free(zSql);
+ if( rc!=SQLITE_OK ) goto fail;
+ }
+
+ /* Set zSql to the SQL to the table_info pragma for the table currently
+ ** identified by the rows pointed to by statements pCur->pDbList and
+ ** pCur->pTableList.
+ */
+ zSql = sqlite3_mprintf("PRAGMA %Q.table_info(%Q)",
+ sqlite3_column_text(pCur->pDbList, 1),
+ sqlite3_column_text(pCur->pTableList, 0)
+ );
+
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ goto fail;
+ }
+ rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pColumnList, 0);
+ sqlite3_free(zSql);
+ if( rc!=SQLITE_OK ) goto fail;
+ }
+ pCur->rowid++;
+
+fail:
+ /* TODO: Handle rc */
+ return 1;
+}
+
+/*
+** Reset a schema table cursor.
+*/
+static int schemaFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ int rc;
+ schema_vtab *pVtab = (schema_vtab *)(pVtabCursor->pVtab);
+ schema_cursor *pCur = (schema_cursor *)pVtabCursor;
+ pCur->rowid = 0;
+ finalize(&pCur->pTableList);
+ finalize(&pCur->pColumnList);
+ finalize(&pCur->pDbList);
+ rc = sqlite3_prepare(pVtab->db,"PRAGMA database_list", -1, &pCur->pDbList, 0);
+ return (rc==SQLITE_OK ? schemaNext(pVtabCursor) : rc);
+}
+
+/*
+** Analyse the WHERE condition.
+*/
+static int schemaBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+ return SQLITE_OK;
+}
+
+/*
+** A virtual table module that merely echos method calls into TCL
+** variables.
+*/
+static sqlite3_module schemaModule = {
+ 0, /* iVersion */
+ "schema", /* zName */
+ schemaCreate,
+ schemaCreate,
+ schemaBestIndex,
+ schemaDestroy,
+ schemaDestroy,
+ schemaOpen, /* xOpen - open a cursor */
+ schemaClose, /* xClose - close a cursor */
+ schemaFilter, /* xFilter - configure scan constraints */
+ schemaNext, /* xNext - advance a cursor */
+ schemaColumn, /* xColumn - read data */
+ schemaRowid, /* xRowid - read data */
+};
+
+
+#ifdef SQLITE_TEST
+
+/*
+** Decode a pointer to an sqlite3 object.
+*/
+static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
+ *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
+ return TCL_OK;
+}
+
+/*
+** Register the schema virtual table module.
+*/
+static int register_schema_module(
+ ClientData clientData, /* Not used */
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[] /* Command arguments */
+){
+ sqlite3 *db;
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB");
+ return TCL_ERROR;
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlite3_create_module(db, "schema", &schemaModule, 0);
+#endif
+ return TCL_OK;
+}
+
+/*
+** Register commands with the TCL interpreter.
+*/
+int Sqlitetestschema_Init(Tcl_Interp *interp){
+ static struct {
+ char *zName;
+ Tcl_ObjCmdProc *xProc;
+ void *clientData;
+ } aObjCmd[] = {
+ { "register_schema_module", register_schema_module, 0 },
+ };
+ int i;
+ for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
+ Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
+ aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
+ }
+ return TCL_OK;
+}
+
+#else
+
+/*
+** Extension load function.
+*/
+int schema_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ SQLITE_EXTENSION_INIT2(pApi);
+ sqlite3_create_module(db, "schema", &schemaModule, 0);
+ return 0;
+}
+
+#endif