modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/stmt.c (about)

     1  /*
     2  ** 2017-05-31
     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  **
    13  ** This file demonstrates an eponymous virtual table that returns information
    14  ** about all prepared statements for the database connection.
    15  **
    16  ** Usage example:
    17  **
    18  **     .load ./stmt
    19  **     .mode line
    20  **     .header on
    21  **     SELECT * FROM stmt;
    22  */
    23  #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB)
    24  #if !defined(SQLITEINT_H)
    25  #include "sqlite3ext.h"
    26  #endif
    27  SQLITE_EXTENSION_INIT1
    28  #include <assert.h>
    29  #include <string.h>
    30  
    31  #ifndef SQLITE_OMIT_VIRTUALTABLE
    32  
    33  /* stmt_vtab is a subclass of sqlite3_vtab which will
    34  ** serve as the underlying representation of a stmt virtual table
    35  */
    36  typedef struct stmt_vtab stmt_vtab;
    37  struct stmt_vtab {
    38    sqlite3_vtab base;  /* Base class - must be first */
    39    sqlite3 *db;        /* Database connection for this stmt vtab */
    40  };
    41  
    42  /* stmt_cursor is a subclass of sqlite3_vtab_cursor which will
    43  ** serve as the underlying representation of a cursor that scans
    44  ** over rows of the result
    45  */
    46  typedef struct stmt_cursor stmt_cursor;
    47  struct stmt_cursor {
    48    sqlite3_vtab_cursor base;  /* Base class - must be first */
    49    sqlite3 *db;               /* Database connection for this cursor */
    50    sqlite3_stmt *pStmt;       /* Statement cursor is currently pointing at */
    51    sqlite3_int64 iRowid;      /* The rowid */
    52  };
    53  
    54  /*
    55  ** The stmtConnect() method is invoked to create a new
    56  ** stmt_vtab that describes the stmt virtual table.
    57  **
    58  ** Think of this routine as the constructor for stmt_vtab objects.
    59  **
    60  ** All this routine needs to do is:
    61  **
    62  **    (1) Allocate the stmt_vtab object and initialize all fields.
    63  **
    64  **    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
    65  **        result set of queries against stmt will look like.
    66  */
    67  static int stmtConnect(
    68    sqlite3 *db,
    69    void *pAux,
    70    int argc, const char *const*argv,
    71    sqlite3_vtab **ppVtab,
    72    char **pzErr
    73  ){
    74    stmt_vtab *pNew;
    75    int rc;
    76  
    77  /* Column numbers */
    78  #define STMT_COLUMN_SQL     0   /* SQL for the statement */
    79  #define STMT_COLUMN_NCOL    1   /* Number of result columns */
    80  #define STMT_COLUMN_RO      2   /* True if read-only */
    81  #define STMT_COLUMN_BUSY    3   /* True if currently busy */
    82  #define STMT_COLUMN_NSCAN   4   /* SQLITE_STMTSTATUS_FULLSCAN_STEP */
    83  #define STMT_COLUMN_NSORT   5   /* SQLITE_STMTSTATUS_SORT */
    84  #define STMT_COLUMN_NAIDX   6   /* SQLITE_STMTSTATUS_AUTOINDEX */
    85  #define STMT_COLUMN_NSTEP   7   /* SQLITE_STMTSTATUS_VM_STEP */
    86  #define STMT_COLUMN_REPREP  8   /* SQLITE_STMTSTATUS_REPREPARE */
    87  #define STMT_COLUMN_RUN     9   /* SQLITE_STMTSTATUS_RUN */
    88  #define STMT_COLUMN_MEM    10   /* SQLITE_STMTSTATUS_MEMUSED */
    89  
    90  
    91    rc = sqlite3_declare_vtab(db,
    92       "CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep,"
    93                      "reprep,run,mem)");
    94    if( rc==SQLITE_OK ){
    95      pNew = sqlite3_malloc( sizeof(*pNew) );
    96      *ppVtab = (sqlite3_vtab*)pNew;
    97      if( pNew==0 ) return SQLITE_NOMEM;
    98      memset(pNew, 0, sizeof(*pNew));
    99      pNew->db = db;
   100    }
   101    return rc;
   102  }
   103  
   104  /*
   105  ** This method is the destructor for stmt_cursor objects.
   106  */
   107  static int stmtDisconnect(sqlite3_vtab *pVtab){
   108    sqlite3_free(pVtab);
   109    return SQLITE_OK;
   110  }
   111  
   112  /*
   113  ** Constructor for a new stmt_cursor object.
   114  */
   115  static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
   116    stmt_cursor *pCur;
   117    pCur = sqlite3_malloc( sizeof(*pCur) );
   118    if( pCur==0 ) return SQLITE_NOMEM;
   119    memset(pCur, 0, sizeof(*pCur));
   120    pCur->db = ((stmt_vtab*)p)->db;
   121    *ppCursor = &pCur->base;
   122    return SQLITE_OK;
   123  }
   124  
   125  /*
   126  ** Destructor for a stmt_cursor.
   127  */
   128  static int stmtClose(sqlite3_vtab_cursor *cur){
   129    sqlite3_free(cur);
   130    return SQLITE_OK;
   131  }
   132  
   133  
   134  /*
   135  ** Advance a stmt_cursor to its next row of output.
   136  */
   137  static int stmtNext(sqlite3_vtab_cursor *cur){
   138    stmt_cursor *pCur = (stmt_cursor*)cur;
   139    pCur->iRowid++;
   140    pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt);
   141    return SQLITE_OK;
   142  }
   143  
   144  /*
   145  ** Return values of columns for the row at which the stmt_cursor
   146  ** is currently pointing.
   147  */
   148  static int stmtColumn(
   149    sqlite3_vtab_cursor *cur,   /* The cursor */
   150    sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
   151    int i                       /* Which column to return */
   152  ){
   153    stmt_cursor *pCur = (stmt_cursor*)cur;
   154    switch( i ){
   155      case STMT_COLUMN_SQL: {
   156        sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
   157        break;
   158      }
   159      case STMT_COLUMN_NCOL: {
   160        sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt));
   161        break;
   162      }
   163      case STMT_COLUMN_RO: {
   164        sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt));
   165        break;
   166      }
   167      case STMT_COLUMN_BUSY: {
   168        sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
   169        break;
   170      }
   171      case STMT_COLUMN_MEM: {
   172        i = SQLITE_STMTSTATUS_MEMUSED + 
   173              STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
   174        /* Fall thru */
   175      }
   176      case STMT_COLUMN_NSCAN:
   177      case STMT_COLUMN_NSORT:
   178      case STMT_COLUMN_NAIDX:
   179      case STMT_COLUMN_NSTEP:
   180      case STMT_COLUMN_REPREP:
   181      case STMT_COLUMN_RUN: {
   182        sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt,
   183                        i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0));
   184        break;
   185      }
   186    }
   187    return SQLITE_OK;
   188  }
   189  
   190  /*
   191  ** Return the rowid for the current row.  In this implementation, the
   192  ** rowid is the same as the output value.
   193  */
   194  static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
   195    stmt_cursor *pCur = (stmt_cursor*)cur;
   196    *pRowid = pCur->iRowid;
   197    return SQLITE_OK;
   198  }
   199  
   200  /*
   201  ** Return TRUE if the cursor has been moved off of the last
   202  ** row of output.
   203  */
   204  static int stmtEof(sqlite3_vtab_cursor *cur){
   205    stmt_cursor *pCur = (stmt_cursor*)cur;
   206    return pCur->pStmt==0;
   207  }
   208  
   209  /*
   210  ** This method is called to "rewind" the stmt_cursor object back
   211  ** to the first row of output.  This method is always called at least
   212  ** once prior to any call to stmtColumn() or stmtRowid() or 
   213  ** stmtEof().
   214  */
   215  static int stmtFilter(
   216    sqlite3_vtab_cursor *pVtabCursor, 
   217    int idxNum, const char *idxStr,
   218    int argc, sqlite3_value **argv
   219  ){
   220    stmt_cursor *pCur = (stmt_cursor *)pVtabCursor;
   221    pCur->pStmt = 0;
   222    pCur->iRowid = 0;
   223    return stmtNext(pVtabCursor);
   224  }
   225  
   226  /*
   227  ** SQLite will invoke this method one or more times while planning a query
   228  ** that uses the stmt virtual table.  This routine needs to create
   229  ** a query plan for each invocation and compute an estimated cost for that
   230  ** plan.
   231  */
   232  static int stmtBestIndex(
   233    sqlite3_vtab *tab,
   234    sqlite3_index_info *pIdxInfo
   235  ){
   236    pIdxInfo->estimatedCost = (double)500;
   237    pIdxInfo->estimatedRows = 500;
   238    return SQLITE_OK;
   239  }
   240  
   241  /*
   242  ** This following structure defines all the methods for the 
   243  ** stmt virtual table.
   244  */
   245  static sqlite3_module stmtModule = {
   246    0,                         /* iVersion */
   247    0,                         /* xCreate */
   248    stmtConnect,               /* xConnect */
   249    stmtBestIndex,             /* xBestIndex */
   250    stmtDisconnect,            /* xDisconnect */
   251    0,                         /* xDestroy */
   252    stmtOpen,                  /* xOpen - open a cursor */
   253    stmtClose,                 /* xClose - close a cursor */
   254    stmtFilter,                /* xFilter - configure scan constraints */
   255    stmtNext,                  /* xNext - advance a cursor */
   256    stmtEof,                   /* xEof - check for end of scan */
   257    stmtColumn,                /* xColumn - read data */
   258    stmtRowid,                 /* xRowid - read data */
   259    0,                         /* xUpdate */
   260    0,                         /* xBegin */
   261    0,                         /* xSync */
   262    0,                         /* xCommit */
   263    0,                         /* xRollback */
   264    0,                         /* xFindMethod */
   265    0,                         /* xRename */
   266    0,                         /* xSavepoint */
   267    0,                         /* xRelease */
   268    0,                         /* xRollbackTo */
   269  };
   270  
   271  #endif /* SQLITE_OMIT_VIRTUALTABLE */
   272  
   273  int sqlite3StmtVtabInit(sqlite3 *db){
   274    int rc = SQLITE_OK;
   275  #ifndef SQLITE_OMIT_VIRTUALTABLE
   276    rc = sqlite3_create_module(db, "sqlite_stmt", &stmtModule, 0);
   277  #endif
   278    return rc;
   279  }
   280  
   281  #ifndef SQLITE_CORE
   282  #ifdef _WIN32
   283  __declspec(dllexport)
   284  #endif
   285  int sqlite3_stmt_init(
   286    sqlite3 *db, 
   287    char **pzErrMsg, 
   288    const sqlite3_api_routines *pApi
   289  ){
   290    int rc = SQLITE_OK;
   291    SQLITE_EXTENSION_INIT2(pApi);
   292  #ifndef SQLITE_OMIT_VIRTUALTABLE
   293    rc = sqlite3StmtVtabInit(db);
   294  #endif
   295    return rc;
   296  }
   297  #endif /* SQLITE_CORE */
   298  #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */