1 /* 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 */ 16 17 /* The code in this file defines a sqlite3 virtual-table module that 18 ** provides a read-only view of the current database schema. There is one 19 ** row in the schema table for each column in the database schema. 20 */ 21 #define SCHEMA \ 22 "CREATE TABLE x(" \ 23 "database," /* Name of database (i.e. main, temp etc.) */ \ 24 "tablename," /* Name of table */ \ 25 "cid," /* Column number (from left-to-right, 0 upward) */ \ 26 "name," /* Column name */ \ 27 "type," /* Specified type (i.e. VARCHAR(32)) */ \ 28 "not_null," /* Boolean. True if NOT NULL was specified */ \ 29 "dflt_value," /* Default value for this column */ \ 30 "pk" /* True if this column is part of the primary key */ \ 31 ")" 32 33 /* If SQLITE_TEST is defined this code is preprocessed for use as part 34 ** of the sqlite test binary "testfixture". Otherwise it is preprocessed 35 ** to be compiled into an sqlite dynamic extension. 36 */ 37 #ifdef SQLITE_TEST 38 #include "sqliteInt.h" 39 #include "tcl.h" 40 #else 41 #include "sqlite3ext.h" 42 SQLITE_EXTENSION_INIT1 43 #endif 44 45 #include <stdlib.h> 46 #include <string.h> 47 #include <assert.h> 48 49 typedef struct schema_vtab schema_vtab; 50 typedef struct schema_cursor schema_cursor; 51 52 /* A schema table object */ 53 struct schema_vtab { 54 sqlite3_vtab base; 55 sqlite3 *db; 56 }; 57 58 /* A schema table cursor object */ 59 struct schema_cursor { 60 sqlite3_vtab_cursor base; 61 sqlite3_stmt *pDbList; 62 sqlite3_stmt *pTableList; 63 sqlite3_stmt *pColumnList; 64 int rowid; 65 }; 66 67 /* 68 ** None of this works unless we have virtual tables. 69 */ 70 #ifndef SQLITE_OMIT_VIRTUALTABLE 71 72 /* 73 ** Table destructor for the schema module. 74 */ 75 static int schemaDestroy(sqlite3_vtab *pVtab){ 76 sqlite3_free(pVtab); 77 return 0; 78 } 79 80 /* 81 ** Table constructor for the schema module. 82 */ 83 static int schemaCreate( 84 sqlite3 *db, 85 void *pAux, 86 int argc, const char *const*argv, 87 sqlite3_vtab **ppVtab, 88 char **pzErr 89 ){ 90 int rc = SQLITE_NOMEM; 91 schema_vtab *pVtab = sqlite3_malloc(sizeof(schema_vtab)); 92 if( pVtab ){ 93 memset(pVtab, 0, sizeof(schema_vtab)); 94 pVtab->db = db; 95 #ifndef SQLITE_OMIT_VIRTUALTABLE 96 rc = sqlite3_declare_vtab(db, SCHEMA); 97 #endif 98 } 99 *ppVtab = (sqlite3_vtab *)pVtab; 100 return rc; 101 } 102 103 /* 104 ** Open a new cursor on the schema table. 105 */ 106 static int schemaOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ 107 int rc = SQLITE_NOMEM; 108 schema_cursor *pCur; 109 pCur = sqlite3_malloc(sizeof(schema_cursor)); 110 if( pCur ){ 111 memset(pCur, 0, sizeof(schema_cursor)); 112 *ppCursor = (sqlite3_vtab_cursor *)pCur; 113 rc = SQLITE_OK; 114 } 115 return rc; 116 } 117 118 /* 119 ** Close a schema table cursor. 120 */ 121 static int schemaClose(sqlite3_vtab_cursor *cur){ 122 schema_cursor *pCur = (schema_cursor *)cur; 123 sqlite3_finalize(pCur->pDbList); 124 sqlite3_finalize(pCur->pTableList); 125 sqlite3_finalize(pCur->pColumnList); 126 sqlite3_free(pCur); 127 return SQLITE_OK; 128 } 129 130 /* 131 ** Retrieve a column of data. 132 */ 133 static int schemaColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ 134 schema_cursor *pCur = (schema_cursor *)cur; 135 switch( i ){ 136 case 0: 137 sqlite3_result_value(ctx, sqlite3_column_value(pCur->pDbList, 1)); 138 break; 139 case 1: 140 sqlite3_result_value(ctx, sqlite3_column_value(pCur->pTableList, 0)); 141 break; 142 default: 143 sqlite3_result_value(ctx, sqlite3_column_value(pCur->pColumnList, i-2)); 144 break; 145 } 146 return SQLITE_OK; 147 } 148 149 /* 150 ** Retrieve the current rowid. 151 */ 152 static int schemaRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ 153 schema_cursor *pCur = (schema_cursor *)cur; 154 *pRowid = pCur->rowid; 155 return SQLITE_OK; 156 } 157 158 static int finalize(sqlite3_stmt **ppStmt){ 159 int rc = sqlite3_finalize(*ppStmt); 160 *ppStmt = 0; 161 return rc; 162 } 163 164 static int schemaEof(sqlite3_vtab_cursor *cur){ 165 schema_cursor *pCur = (schema_cursor *)cur; 166 return (pCur->pDbList ? 0 : 1); 167 } 168 169 /* 170 ** Advance the cursor to the next row. 171 */ 172 static int schemaNext(sqlite3_vtab_cursor *cur){ 173 int rc = SQLITE_OK; 174 schema_cursor *pCur = (schema_cursor *)cur; 175 schema_vtab *pVtab = (schema_vtab *)(cur->pVtab); 176 char *zSql = 0; 177 178 while( !pCur->pColumnList || SQLITE_ROW!=sqlite3_step(pCur->pColumnList) ){ 179 if( SQLITE_OK!=(rc = finalize(&pCur->pColumnList)) ) goto next_exit; 180 181 while( !pCur->pTableList || SQLITE_ROW!=sqlite3_step(pCur->pTableList) ){ 182 if( SQLITE_OK!=(rc = finalize(&pCur->pTableList)) ) goto next_exit; 183 184 assert(pCur->pDbList); 185 while( SQLITE_ROW!=sqlite3_step(pCur->pDbList) ){ 186 rc = finalize(&pCur->pDbList); 187 goto next_exit; 188 } 189 190 /* Set zSql to the SQL to pull the list of tables from the 191 ** sqlite_master (or sqlite_temp_master) table of the database 192 ** identfied by the row pointed to by the SQL statement pCur->pDbList 193 ** (iterating through a "PRAGMA database_list;" statement). 194 */ 195 if( sqlite3_column_int(pCur->pDbList, 0)==1 ){ 196 zSql = sqlite3_mprintf( 197 "SELECT name FROM sqlite_temp_master WHERE type='table'" 198 ); 199 }else{ 200 sqlite3_stmt *pDbList = pCur->pDbList; 201 zSql = sqlite3_mprintf( 202 "SELECT name FROM %Q.sqlite_master WHERE type='table'", 203 sqlite3_column_text(pDbList, 1) 204 ); 205 } 206 if( !zSql ){ 207 rc = SQLITE_NOMEM; 208 goto next_exit; 209 } 210 211 rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pTableList, 0); 212 sqlite3_free(zSql); 213 if( rc!=SQLITE_OK ) goto next_exit; 214 } 215 216 /* Set zSql to the SQL to the table_info pragma for the table currently 217 ** identified by the rows pointed to by statements pCur->pDbList and 218 ** pCur->pTableList. 219 */ 220 zSql = sqlite3_mprintf("PRAGMA %Q.table_info(%Q)", 221 sqlite3_column_text(pCur->pDbList, 1), 222 sqlite3_column_text(pCur->pTableList, 0) 223 ); 224 225 if( !zSql ){ 226 rc = SQLITE_NOMEM; 227 goto next_exit; 228 } 229 rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pColumnList, 0); 230 sqlite3_free(zSql); 231 if( rc!=SQLITE_OK ) goto next_exit; 232 } 233 pCur->rowid++; 234 235 next_exit: 236 /* TODO: Handle rc */ 237 return rc; 238 } 239 240 /* 241 ** Reset a schema table cursor. 242 */ 243 static int schemaFilter( 244 sqlite3_vtab_cursor *pVtabCursor, 245 int idxNum, const char *idxStr, 246 int argc, sqlite3_value **argv 247 ){ 248 int rc; 249 schema_vtab *pVtab = (schema_vtab *)(pVtabCursor->pVtab); 250 schema_cursor *pCur = (schema_cursor *)pVtabCursor; 251 pCur->rowid = 0; 252 finalize(&pCur->pTableList); 253 finalize(&pCur->pColumnList); 254 finalize(&pCur->pDbList); 255 rc = sqlite3_prepare(pVtab->db,"PRAGMA database_list", -1, &pCur->pDbList, 0); 256 return (rc==SQLITE_OK ? schemaNext(pVtabCursor) : rc); 257 } 258 259 /* 260 ** Analyse the WHERE condition. 261 */ 262 static int schemaBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ 263 return SQLITE_OK; 264 } 265 266 /* 267 ** A virtual table module that merely echos method calls into TCL 268 ** variables. 269 */ 270 static sqlite3_module schemaModule = { 271 0, /* iVersion */ 272 schemaCreate, 273 schemaCreate, 274 schemaBestIndex, 275 schemaDestroy, 276 schemaDestroy, 277 schemaOpen, /* xOpen - open a cursor */ 278 schemaClose, /* xClose - close a cursor */ 279 schemaFilter, /* xFilter - configure scan constraints */ 280 schemaNext, /* xNext - advance a cursor */ 281 schemaEof, /* xEof */ 282 schemaColumn, /* xColumn - read data */ 283 schemaRowid, /* xRowid - read data */ 284 0, /* xUpdate */ 285 0, /* xBegin */ 286 0, /* xSync */ 287 0, /* xCommit */ 288 0, /* xRollback */ 289 0, /* xFindMethod */ 290 0, /* xRename */ 291 }; 292 293 #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ 294 295 #ifdef SQLITE_TEST 296 297 /* 298 ** Decode a pointer to an sqlite3 object. 299 */ 300 extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); 301 302 /* 303 ** Register the schema virtual table module. 304 */ 305 static int register_schema_module( 306 ClientData clientData, /* Not used */ 307 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 308 int objc, /* Number of arguments */ 309 Tcl_Obj *CONST objv[] /* Command arguments */ 310 ){ 311 sqlite3 *db; 312 if( objc!=2 ){ 313 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 314 return TCL_ERROR; 315 } 316 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 317 #ifndef SQLITE_OMIT_VIRTUALTABLE 318 sqlite3_create_module(db, "schema", &schemaModule, 0); 319 #endif 320 return TCL_OK; 321 } 322 323 /* 324 ** Register commands with the TCL interpreter. 325 */ 326 int Sqlitetestschema_Init(Tcl_Interp *interp){ 327 static struct { 328 char *zName; 329 Tcl_ObjCmdProc *xProc; 330 void *clientData; 331 } aObjCmd[] = { 332 { "register_schema_module", register_schema_module, 0 }, 333 }; 334 int i; 335 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 336 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 337 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); 338 } 339 return TCL_OK; 340 } 341 342 #else 343 344 /* 345 ** Extension load function. 346 */ 347 int sqlite3_extension_init( 348 sqlite3 *db, 349 char **pzErrMsg, 350 const sqlite3_api_routines *pApi 351 ){ 352 SQLITE_EXTENSION_INIT2(pApi); 353 #ifndef SQLITE_OMIT_VIRTUALTABLE 354 sqlite3_create_module(db, "schema", &schemaModule, 0); 355 #endif 356 return 0; 357 } 358 359 #endif 360