Annotation of embedaddon/sqlite3/src/test_schema.c, revision 1.1.1.1

1.1       misho       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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>