15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2006 June 10
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code.  In place of
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you do good and not evil.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you share freely, never taking more than you give.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*************************************************************************
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Code for testing the virtual table interfaces.  This code
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is not included in the SQLite library.  It is used for automated
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** testing of the SQLite library.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The code in this file defines a sqlite3 virtual-table module that
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** provides a read-only view of the current database schema. There is one
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** row in the schema table for each column in the database schema.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SCHEMA \
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"CREATE TABLE x("                                                            \
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "database,"          /* Name of database (i.e. main, temp etc.) */         \
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "tablename,"         /* Name of table */                                   \
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "cid,"               /* Column number (from left-to-right, 0 upward) */    \
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "name,"              /* Column name */                                     \
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "type,"              /* Specified type (i.e. VARCHAR(32)) */               \
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "not_null,"          /* Boolean. True if NOT NULL was specified */         \
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "dflt_value,"        /* Default value for this column */                   \
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "pk"                 /* True if this column is part of the primary key */  \
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)")"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* If SQLITE_TEST is defined this code is preprocessed for use as part
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the sqlite test binary "testfixture". Otherwise it is preprocessed
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to be compiled into an sqlite dynamic extension.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #include "sqliteInt.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #include "tcl.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #include "sqlite3ext.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SQLITE_EXTENSION_INIT1
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct schema_vtab schema_vtab;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct schema_cursor schema_cursor;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* A schema table object */
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct schema_vtab {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab base;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* A schema table cursor object */
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct schema_cursor {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab_cursor base;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pDbList;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pTableList;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pColumnList;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rowid;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** None of this works unless we have virtual tables.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_VIRTUALTABLE
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Table destructor for the schema module.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaDestroy(sqlite3_vtab *pVtab){
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pVtab);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Table constructor for the schema module.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaCreate(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pAux,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc, const char *const*argv,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab **ppVtab,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **pzErr
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_NOMEM;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_vtab *pVtab = sqlite3_malloc(sizeof(schema_vtab));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pVtab ){
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pVtab, 0, sizeof(schema_vtab));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pVtab->db = db;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_VIRTUALTABLE
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_declare_vtab(db, SCHEMA);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppVtab = (sqlite3_vtab *)pVtab;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open a new cursor on the schema table.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_NOMEM;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_cursor *pCur;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCur = sqlite3_malloc(sizeof(schema_cursor));
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCur ){
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pCur, 0, sizeof(schema_cursor));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ppCursor = (sqlite3_vtab_cursor *)pCur;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_OK;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a schema table cursor.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaClose(sqlite3_vtab_cursor *cur){
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_cursor *pCur = (schema_cursor *)cur;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_finalize(pCur->pDbList);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_finalize(pCur->pTableList);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_finalize(pCur->pColumnList);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pCur);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Retrieve a column of data.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_cursor *pCur = (schema_cursor *)cur;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( i ){
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_result_value(ctx, sqlite3_column_value(pCur->pDbList, 1));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_result_value(ctx, sqlite3_column_value(pCur->pTableList, 0));
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_result_value(ctx, sqlite3_column_value(pCur->pColumnList, i-2));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Retrieve the current rowid.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_cursor *pCur = (schema_cursor *)cur;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pRowid = pCur->rowid;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int finalize(sqlite3_stmt **ppStmt){
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = sqlite3_finalize(*ppStmt);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppStmt = 0;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaEof(sqlite3_vtab_cursor *cur){
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_cursor *pCur = (schema_cursor *)cur;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (pCur->pDbList ? 0 : 1);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Advance the cursor to the next row.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaNext(sqlite3_vtab_cursor *cur){
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_cursor *pCur = (schema_cursor *)cur;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_vtab *pVtab = (schema_vtab *)(cur->pVtab);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zSql = 0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( !pCur->pColumnList || SQLITE_ROW!=sqlite3_step(pCur->pColumnList) ){
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( SQLITE_OK!=(rc = finalize(&pCur->pColumnList)) ) goto next_exit;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( !pCur->pTableList || SQLITE_ROW!=sqlite3_step(pCur->pTableList) ){
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( SQLITE_OK!=(rc = finalize(&pCur->pTableList)) ) goto next_exit;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(pCur->pDbList);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while( SQLITE_ROW!=sqlite3_step(pCur->pDbList) ){
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = finalize(&pCur->pDbList);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto next_exit;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Set zSql to the SQL to pull the list of tables from the
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** sqlite_master (or sqlite_temp_master) table of the database
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** identfied by the row pointed to by the SQL statement pCur->pDbList
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** (iterating through a "PRAGMA database_list;" statement).
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( sqlite3_column_int(pCur->pDbList, 0)==1 ){
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zSql = sqlite3_mprintf(
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "SELECT name FROM sqlite_temp_master WHERE type='table'"
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        );
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sqlite3_stmt *pDbList = pCur->pDbList;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zSql = sqlite3_mprintf(
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "SELECT name FROM %Q.sqlite_master WHERE type='table'",
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             sqlite3_column_text(pDbList, 1)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        );
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !zSql ){
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_NOMEM;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto next_exit;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pTableList, 0);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(zSql);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ) goto next_exit;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Set zSql to the SQL to the table_info pragma for the table currently
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** identified by the rows pointed to by statements pCur->pDbList and
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** pCur->pTableList.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zSql = sqlite3_mprintf("PRAGMA %Q.table_info(%Q)",
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sqlite3_column_text(pCur->pDbList, 1),
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sqlite3_column_text(pCur->pTableList, 0)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !zSql ){
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_NOMEM;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto next_exit;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pColumnList, 0);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(zSql);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ) goto next_exit;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCur->rowid++;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)next_exit:
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* TODO: Handle rc */
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Reset a schema table cursor.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaFilter(
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab_cursor *pVtabCursor,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int idxNum, const char *idxStr,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc, sqlite3_value **argv
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_vtab *pVtab = (schema_vtab *)(pVtabCursor->pVtab);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schema_cursor *pCur = (schema_cursor *)pVtabCursor;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCur->rowid = 0;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  finalize(&pCur->pTableList);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  finalize(&pCur->pColumnList);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  finalize(&pCur->pDbList);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3_prepare(pVtab->db,"PRAGMA database_list", -1, &pCur->pDbList, 0);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (rc==SQLITE_OK ? schemaNext(pVtabCursor) : rc);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Analyse the WHERE condition.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int schemaBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A virtual table module that merely echos method calls into TCL
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** variables.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_module schemaModule = {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* iVersion */
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaCreate,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaCreate,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaBestIndex,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaDestroy,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaDestroy,
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaOpen,                  /* xOpen - open a cursor */
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaClose,                 /* xClose - close a cursor */
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaFilter,                /* xFilter - configure scan constraints */
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaNext,                  /* xNext - advance a cursor */
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaEof,                   /* xEof */
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaColumn,                /* xColumn - read data */
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  schemaRowid,                 /* xRowid - read data */
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xUpdate */
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xBegin */
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xSync */
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xCommit */
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xRollback */
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xFindMethod */
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xRename */
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Decode a pointer to an sqlite3 object.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register the schema virtual table module.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int register_schema_module(
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientData clientData, /* Not used */
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int objc,              /* Number of arguments */
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *CONST objv[]  /* Command arguments */
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( objc!=2 ){
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_WrongNumArgs(interp, 1, objv, "DB");
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_VIRTUALTABLE
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_create_module(db, "schema", &schemaModule, 0);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register commands with the TCL interpreter.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Sqlitetestschema_Init(Tcl_Interp *interp){
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static struct {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     char *zName;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     Tcl_ObjCmdProc *xProc;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     void *clientData;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } aObjCmd[] = {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "register_schema_module", register_schema_module, 0 },
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Extension load function.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_extension_init(
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **pzErrMsg,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const sqlite3_api_routines *pApi
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SQLITE_EXTENSION_INIT2(pApi);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_VIRTUALTABLE
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_create_module(db, "schema", &schemaModule, 0);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
360