Annotation of embedaddon/sqlite3/src/test_schema.c, revision 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>