aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2020-03-23 15:49:22 +0000
committerdrh <drh@noemail.net>2020-03-23 15:49:22 +0000
commit691b5c54b80c4861906d8791623a09af6db2d966 (patch)
tree88c65cc0f49207df96db32f9b174ec12fa0b0048 /src
parent74a07986cee851014e2bd154e0376768cd4d07b5 (diff)
downloadsqlite-691b5c54b80c4861906d8791623a09af6db2d966.tar.gz
sqlite-691b5c54b80c4861906d8791623a09af6db2d966.zip
Infrastructure for the bytecode() table-valued function. The function itself
is not yet implemented. FossilOrigin-Name: 2795f0d633577e0de66b389d9e8e44c55e85975bdc62f1a0b8f93959d19b22bf
Diffstat (limited to 'src')
-rw-r--r--src/ctime.c3
-rw-r--r--src/main.c6
-rw-r--r--src/vdbe.h3
-rw-r--r--src/vdbevtab.c223
4 files changed, 235 insertions, 0 deletions
diff --git a/src/ctime.c b/src/ctime.c
index 7a2ace931..b104b35db 100644
--- a/src/ctime.c
+++ b/src/ctime.c
@@ -193,6 +193,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
"ENABLE_BATCH_ATOMIC_WRITE",
#endif
+#if SQLITE_ENABLE_BYTECODE_VTAB
+ "ENABLE_BYTECODE_VTAB",
+#endif
#if SQLITE_ENABLE_CEROD
"ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
#endif
diff --git a/src/main.c b/src/main.c
index 98e030fad..24cbe8bdb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -3346,6 +3346,12 @@ static int openDatabase(
}
#endif
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
+ if( !db->mallocFailed && rc==SQLITE_OK){
+ rc = sqlite3VdbeBytecodeVtabInit(db);
+ }
+#endif
+
#ifdef SQLITE_ENABLE_INTERNAL_FUNCTIONS
/* Testing use only!!! The -DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1 compile-time
** option gives access to internal functions by default.
diff --git a/src/vdbe.h b/src/vdbe.h
index 482331eff..38b43eb71 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -290,6 +290,9 @@ void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
int sqlite3VdbeHasSubProgram(Vdbe*);
int sqlite3NotPureFunc(sqlite3_context*);
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
+int sqlite3VdbeBytecodeVtabInit(sqlite3*);
+#endif
/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
** each VDBE opcode.
diff --git a/src/vdbevtab.c b/src/vdbevtab.c
new file mode 100644
index 000000000..b2994cb25
--- /dev/null
+++ b/src/vdbevtab.c
@@ -0,0 +1,223 @@
+/*
+** 2020-03-23
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements virtual-tables for examining the bytecode content
+** of a prepared statement.
+*/
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
+#include "sqliteInt.h"
+#include "vdbeInt.h"
+
+/* An instance of the bytecode() table-valued function.
+*/
+typedef struct bytecodevtab_vtab bytecodevtab_vtab;
+struct bytecodevtab_vtab {
+ sqlite3_vtab base; /* Base class - must be first */
+ sqlite3_stmt *pStmt; /* The statement whose bytecode is to be displayed */
+};
+
+/* A cursor for scanning through the bytecode
+*/
+typedef struct bytecodevtab_cursor bytecodevtab_cursor;
+struct bytecodevtab_cursor {
+ sqlite3_vtab_cursor base; /* Base class - must be first */
+ sqlite3_int64 iRowid; /* The rowid */
+};
+
+/*
+** Create a new bytecode() table-valued function.
+*/
+static int bytecodevtabConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ bytecodevtab_vtab *pNew;
+ int rc;
+
+ rc = sqlite3_declare_vtab(db,
+ "CREATE TABLE x("
+ "addr INT,"
+ "opcode TEXT,"
+ "p1 INT,"
+ "p2 INT,"
+ "p3 INT,"
+ "p4 TEXT,"
+ "p5 INT,"
+ "comment TEXT,"
+ "subprog TEXT,"
+ "stmt HIDDEN"
+ ");"
+ );
+ if( rc==SQLITE_OK ){
+ pNew = sqlite3_malloc( sizeof(*pNew) );
+ *ppVtab = (sqlite3_vtab*)pNew;
+ if( pNew==0 ) return SQLITE_NOMEM;
+ memset(pNew, 0, sizeof(*pNew));
+ }
+ return rc;
+}
+
+/*
+** This method is the destructor for bytecodevtab_vtab objects.
+*/
+static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){
+ bytecodevtab_vtab *p = (bytecodevtab_vtab*)pVtab;
+ sqlite3_free(p);
+ return SQLITE_OK;
+}
+
+/*
+** Constructor for a new bytecodevtab_cursor object.
+*/
+static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+ bytecodevtab_cursor *pCur;
+ pCur = sqlite3_malloc( sizeof(*pCur) );
+ if( pCur==0 ) return SQLITE_NOMEM;
+ memset(pCur, 0, sizeof(*pCur));
+ *ppCursor = &pCur->base;
+ return SQLITE_OK;
+}
+
+/*
+** Destructor for a bytecodevtab_cursor.
+*/
+static int bytecodevtabClose(sqlite3_vtab_cursor *cur){
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
+ sqlite3_free(pCur);
+ return SQLITE_OK;
+}
+
+
+/*
+** Advance a bytecodevtab_cursor to its next row of output.
+*/
+static int bytecodevtabNext(sqlite3_vtab_cursor *cur){
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
+ pCur->iRowid++;
+ return SQLITE_OK;
+}
+
+/*
+** Return values of columns for the row at which the bytecodevtab_cursor
+** is currently pointing.
+*/
+static int bytecodevtabColumn(
+ sqlite3_vtab_cursor *cur, /* The cursor */
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
+ int i /* Which column to return */
+){
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
+#if 0
+ switch( i ){
+ case TEMPLATEVTAB_A:
+ sqlite3_result_int(ctx, 1000 + pCur->iRowid);
+ break;
+ default:
+ assert( i==TEMPLATEVTAB_B );
+ sqlite3_result_int(ctx, 2000 + pCur->iRowid);
+ break;
+ }
+#endif
+ return SQLITE_OK;
+}
+
+/*
+** Return the rowid for the current row. In this implementation, the
+** rowid is the same as the output value.
+*/
+static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
+ *pRowid = pCur->iRowid;
+ return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the cursor has been moved off of the last
+** row of output.
+*/
+static int bytecodevtabEof(sqlite3_vtab_cursor *cur){
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
+ return pCur->iRowid>=10;
+}
+
+/*
+** This method is called to "rewind" the bytecodevtab_cursor object back
+** to the first row of output. This method is always called at least
+** once prior to any call to bytecodevtabColumn() or bytecodevtabRowid() or
+** bytecodevtabEof().
+*/
+static int bytecodevtabFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor;
+ pCur->iRowid = 1;
+ return SQLITE_OK;
+}
+
+/*
+** SQLite will invoke this method one or more times while planning a query
+** that uses the virtual table. This routine needs to create
+** a query plan for each invocation and compute an estimated cost for that
+** plan.
+*/
+static int bytecodevtabBestIndex(
+ sqlite3_vtab *tab,
+ sqlite3_index_info *pIdxInfo
+){
+ pIdxInfo->estimatedCost = (double)10;
+ pIdxInfo->estimatedRows = 10;
+ return SQLITE_OK;
+}
+
+/*
+** This following structure defines all the methods for the
+** virtual table.
+*/
+static sqlite3_module bytecodevtabModule = {
+ /* iVersion */ 0,
+ /* xCreate */ 0,
+ /* xConnect */ bytecodevtabConnect,
+ /* xBestIndex */ bytecodevtabBestIndex,
+ /* xDisconnect */ bytecodevtabDisconnect,
+ /* xDestroy */ 0,
+ /* xOpen */ bytecodevtabOpen,
+ /* xClose */ bytecodevtabClose,
+ /* xFilter */ bytecodevtabFilter,
+ /* xNext */ bytecodevtabNext,
+ /* xEof */ bytecodevtabEof,
+ /* xColumn */ bytecodevtabColumn,
+ /* xRowid */ bytecodevtabRowid,
+ /* xUpdate */ 0,
+ /* xBegin */ 0,
+ /* xSync */ 0,
+ /* xCommit */ 0,
+ /* xRollback */ 0,
+ /* xFindMethod */ 0,
+ /* xRename */ 0,
+ /* xSavepoint */ 0,
+ /* xRelease */ 0,
+ /* xRollbackTo */ 0,
+ /* xShadowName */ 0
+};
+
+
+int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){
+ int rc;
+ rc = sqlite3_create_module(db, "bytecodevtab", &bytecodevtabModule, 0);
+ return rc;
+}
+#endif /* SQLITE_ENABLE_BYTECODE_VTAB */