| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) |
| #if !defined(SQLITEINT_H) |
| #include "sqlite3ext.h" |
| #endif |
| SQLITE_EXTENSION_INIT1 |
| #include <assert.h> |
| #include <string.h> |
|
|
| #ifndef SQLITE_OMIT_VIRTUALTABLE |
|
|
|
|
| #define STMT_NUM_INTEGER_COLUMN 10 |
| typedef struct StmtRow StmtRow; |
| struct StmtRow { |
| sqlite3_int64 iRowid; |
| char *zSql; |
| int aCol[STMT_NUM_INTEGER_COLUMN+1]; |
| StmtRow *pNext; |
| }; |
|
|
| |
| |
| |
| typedef struct stmt_vtab stmt_vtab; |
| struct stmt_vtab { |
| sqlite3_vtab base; |
| sqlite3 *db; |
| }; |
|
|
| |
| |
| |
| |
| typedef struct stmt_cursor stmt_cursor; |
| struct stmt_cursor { |
| sqlite3_vtab_cursor base; |
| sqlite3 *db; |
| StmtRow *pRow; |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static int stmtConnect( |
| sqlite3 *db, |
| void *pAux, |
| int argc, const char *const*argv, |
| sqlite3_vtab **ppVtab, |
| char **pzErr |
| ){ |
| stmt_vtab *pNew; |
| int rc; |
|
|
| |
| #define STMT_COLUMN_SQL 0 |
| #define STMT_COLUMN_NCOL 1 |
| #define STMT_COLUMN_RO 2 |
| #define STMT_COLUMN_BUSY 3 |
| #define STMT_COLUMN_NSCAN 4 |
| #define STMT_COLUMN_NSORT 5 |
| #define STMT_COLUMN_NAIDX 6 |
| #define STMT_COLUMN_NSTEP 7 |
| #define STMT_COLUMN_REPREP 8 |
| #define STMT_COLUMN_RUN 9 |
| #define STMT_COLUMN_MEM 10 |
|
|
|
|
| (void)pAux; |
| (void)argc; |
| (void)argv; |
| (void)pzErr; |
| rc = sqlite3_declare_vtab(db, |
| "CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep," |
| "reprep,run,mem)"); |
| if( rc==SQLITE_OK ){ |
| pNew = sqlite3_malloc64( sizeof(*pNew) ); |
| *ppVtab = (sqlite3_vtab*)pNew; |
| if( pNew==0 ) return SQLITE_NOMEM; |
| memset(pNew, 0, sizeof(*pNew)); |
| pNew->db = db; |
| } |
| return rc; |
| } |
|
|
| |
| |
| |
| static int stmtDisconnect(sqlite3_vtab *pVtab){ |
| sqlite3_free(pVtab); |
| return SQLITE_OK; |
| } |
|
|
| |
| |
| |
| static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ |
| stmt_cursor *pCur; |
| pCur = sqlite3_malloc64( sizeof(*pCur) ); |
| if( pCur==0 ) return SQLITE_NOMEM; |
| memset(pCur, 0, sizeof(*pCur)); |
| pCur->db = ((stmt_vtab*)p)->db; |
| *ppCursor = &pCur->base; |
| return SQLITE_OK; |
| } |
|
|
| static void stmtCsrReset(stmt_cursor *pCur){ |
| StmtRow *pRow = 0; |
| StmtRow *pNext = 0; |
| for(pRow=pCur->pRow; pRow; pRow=pNext){ |
| pNext = pRow->pNext; |
| sqlite3_free(pRow); |
| } |
| pCur->pRow = 0; |
| } |
|
|
| |
| |
| |
| static int stmtClose(sqlite3_vtab_cursor *cur){ |
| stmtCsrReset((stmt_cursor*)cur); |
| sqlite3_free(cur); |
| return SQLITE_OK; |
| } |
|
|
|
|
| |
| |
| |
| static int stmtNext(sqlite3_vtab_cursor *cur){ |
| stmt_cursor *pCur = (stmt_cursor*)cur; |
| StmtRow *pNext = pCur->pRow->pNext; |
| sqlite3_free(pCur->pRow); |
| pCur->pRow = pNext; |
| return SQLITE_OK; |
| } |
|
|
| |
| |
| |
| |
| static int stmtColumn( |
| sqlite3_vtab_cursor *cur, |
| sqlite3_context *ctx, |
| int i |
| ){ |
| stmt_cursor *pCur = (stmt_cursor*)cur; |
| StmtRow *pRow = pCur->pRow; |
| if( i==STMT_COLUMN_SQL ){ |
| sqlite3_result_text(ctx, pRow->zSql, -1, SQLITE_TRANSIENT); |
| }else{ |
| sqlite3_result_int(ctx, pRow->aCol[i]); |
| } |
| return SQLITE_OK; |
| } |
|
|
| |
| |
| |
| |
| static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ |
| stmt_cursor *pCur = (stmt_cursor*)cur; |
| *pRowid = pCur->pRow->iRowid; |
| return SQLITE_OK; |
| } |
|
|
| |
| |
| |
| |
| static int stmtEof(sqlite3_vtab_cursor *cur){ |
| stmt_cursor *pCur = (stmt_cursor*)cur; |
| return pCur->pRow==0; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| static int stmtFilter( |
| sqlite3_vtab_cursor *pVtabCursor, |
| int idxNum, const char *idxStr, |
| int argc, sqlite3_value **argv |
| ){ |
| stmt_cursor *pCur = (stmt_cursor *)pVtabCursor; |
| sqlite3_stmt *p = 0; |
| sqlite3_int64 iRowid = 1; |
| StmtRow **ppRow = 0; |
|
|
| (void)idxNum; |
| (void)idxStr; |
| (void)argc; |
| (void)argv; |
| stmtCsrReset(pCur); |
| ppRow = &pCur->pRow; |
| for(p=sqlite3_next_stmt(pCur->db, 0); p; p=sqlite3_next_stmt(pCur->db, p)){ |
| const char *zSql = sqlite3_sql(p); |
| sqlite3_int64 nSql = zSql ? strlen(zSql)+1 : 0; |
| StmtRow *pNew = (StmtRow*)sqlite3_malloc64(sizeof(StmtRow) + nSql); |
|
|
| if( pNew==0 ) return SQLITE_NOMEM; |
| memset(pNew, 0, sizeof(StmtRow)); |
| if( zSql ){ |
| pNew->zSql = (char*)&pNew[1]; |
| memcpy(pNew->zSql, zSql, nSql); |
| } |
| pNew->aCol[STMT_COLUMN_NCOL] = sqlite3_column_count(p); |
| pNew->aCol[STMT_COLUMN_RO] = sqlite3_stmt_readonly(p); |
| pNew->aCol[STMT_COLUMN_BUSY] = sqlite3_stmt_busy(p); |
| pNew->aCol[STMT_COLUMN_NSCAN] = sqlite3_stmt_status( |
| p, SQLITE_STMTSTATUS_FULLSCAN_STEP, 0 |
| ); |
| pNew->aCol[STMT_COLUMN_NSORT] = sqlite3_stmt_status( |
| p, SQLITE_STMTSTATUS_SORT, 0 |
| ); |
| pNew->aCol[STMT_COLUMN_NAIDX] = sqlite3_stmt_status( |
| p, SQLITE_STMTSTATUS_AUTOINDEX, 0 |
| ); |
| pNew->aCol[STMT_COLUMN_NSTEP] = sqlite3_stmt_status( |
| p, SQLITE_STMTSTATUS_VM_STEP, 0 |
| ); |
| pNew->aCol[STMT_COLUMN_REPREP] = sqlite3_stmt_status( |
| p, SQLITE_STMTSTATUS_REPREPARE, 0 |
| ); |
| pNew->aCol[STMT_COLUMN_RUN] = sqlite3_stmt_status( |
| p, SQLITE_STMTSTATUS_RUN, 0 |
| ); |
| pNew->aCol[STMT_COLUMN_MEM] = sqlite3_stmt_status( |
| p, SQLITE_STMTSTATUS_MEMUSED, 0 |
| ); |
| pNew->iRowid = iRowid++; |
| *ppRow = pNew; |
| ppRow = &pNew->pNext; |
| } |
|
|
| return SQLITE_OK; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| static int stmtBestIndex( |
| sqlite3_vtab *tab, |
| sqlite3_index_info *pIdxInfo |
| ){ |
| (void)tab; |
| pIdxInfo->estimatedCost = (double)500; |
| pIdxInfo->estimatedRows = 500; |
| return SQLITE_OK; |
| } |
|
|
| |
| |
| |
| |
| static sqlite3_module stmtModule = { |
| 0, |
| 0, |
| stmtConnect, |
| stmtBestIndex, |
| stmtDisconnect, |
| 0, |
| stmtOpen, |
| stmtClose, |
| stmtFilter, |
| stmtNext, |
| stmtEof, |
| stmtColumn, |
| stmtRowid, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0 |
| }; |
|
|
| #endif |
|
|
| int sqlite3StmtVtabInit(sqlite3 *db){ |
| int rc = SQLITE_OK; |
| #ifndef SQLITE_OMIT_VIRTUALTABLE |
| rc = sqlite3_create_module(db, "sqlite_stmt", &stmtModule, 0); |
| #endif |
| return rc; |
| } |
|
|
| #ifndef SQLITE_CORE |
| #ifdef _WIN32 |
| __declspec(dllexport) |
| #endif |
| int sqlite3_stmt_init( |
| sqlite3 *db, |
| char **pzErrMsg, |
| const sqlite3_api_routines *pApi |
| ){ |
| int rc = SQLITE_OK; |
| SQLITE_EXTENSION_INIT2(pApi); |
| #ifndef SQLITE_OMIT_VIRTUALTABLE |
| rc = sqlite3StmtVtabInit(db); |
| #endif |
| return rc; |
| } |
| #endif |
| #endif |
|
|