/ Check-in [b0b0c8f8]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the SQLITE_STMTSTATUS_REPREPARE and SQLITE_STMTSTATUS_RUN options to sqlite3_stmt_status(). Use this for two new columns in the stmts virtual table.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | stmts-vtab
Files: files | file ages | folders
SHA3-256: b0b0c8f8d548ef78584ab714ab120b01c1b83fc0d8ae2fd7626b970bab9fca58
User & Date: drh 2017-06-29 12:49:18
Context
2017-06-29
13:13
Add the "stmts" virtual table to the amalgamation, activated when compiled using -DSQLITE_ENABLE_STMTSVTAB. Add the SQLITE_STMTSTATUS_REPREPARE and SQLITE_STMTSTATUS_RUN statistics outputs from sqlite3_stmt_status() and add corresponding columns to the stmts virtual table. Change the numeric value of SQLITE_STMTSTATUS_MEMUSED to get it out of the way of counter values. check-in: 88976ae3 user: drh tags: trunk
12:49
Add the SQLITE_STMTSTATUS_REPREPARE and SQLITE_STMTSTATUS_RUN options to sqlite3_stmt_status(). Use this for two new columns in the stmts virtual table. Closed-Leaf check-in: b0b0c8f8 user: drh tags: stmts-vtab
2017-06-28
15:47
Build the "stmts" virtual table into the amalgamation. It is active only when compiled using SQLITE_ENABLE_STMTSVTAB. That option is supplied to the command-line shell. check-in: 0ff057d8 user: drh tags: stmts-vtab
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to ext/misc/stmts.c.

97
98
99
100
101
102
103


104
105
106
107
108

109
110
111
112
113
114
115
...
182
183
184
185
186
187
188





189
190
191
192
193
194

195
196
197
198
199
200
201
#define STMTS_COLUMN_NCOL  2    /* Number of result columns */
#define STMTS_COLUMN_RO    3    /* True if read-only */
#define STMTS_COLUMN_BUSY  4    /* True if currently busy */
#define STMTS_COLUMN_NSCAN 5    /* SQLITE_STMTSTATUS_FULLSCAN_STEP */
#define STMTS_COLUMN_NSORT 6    /* SQLITE_STMTSTATUS_SORT */
#define STMTS_COLUMN_NAIDX 7    /* SQLITE_STMTSTATUS_AUTOINDEX */
#define STMTS_COLUMN_NSTEP 8    /* SQLITE_STMTSTATUS_VM_STEP */


#define STMTS_COLUMN_MEM   9    /* SQLITE_STMTSTATUS_MEMUSED */


  rc = sqlite3_declare_vtab(db,
     "CREATE TABLE x(ptr,sql,ncol,ro,busy,nscan,nsort,naidx,nstep,mem)");

  if( rc==SQLITE_OK ){
    pNew = sqlite3_malloc( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    pNew->db = db;
  }
................................................................................
    case STMTS_COLUMN_RO: {
      sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt));
      break;
    }
    case STMTS_COLUMN_BUSY: {
      sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
      break;





    }
    case STMTS_COLUMN_NSCAN:
    case STMTS_COLUMN_NSORT:
    case STMTS_COLUMN_NAIDX:
    case STMTS_COLUMN_NSTEP:
    case STMTS_COLUMN_MEM: {

      sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt,
                      i-STMTS_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0));
      break;
    }
  }
  return SQLITE_OK;
}







>
>
|



|
>







 







>
>
>
>
>





|
>







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#define STMTS_COLUMN_NCOL    2   /* Number of result columns */
#define STMTS_COLUMN_RO      3   /* True if read-only */
#define STMTS_COLUMN_BUSY    4   /* True if currently busy */
#define STMTS_COLUMN_NSCAN   5   /* SQLITE_STMTSTATUS_FULLSCAN_STEP */
#define STMTS_COLUMN_NSORT   6   /* SQLITE_STMTSTATUS_SORT */
#define STMTS_COLUMN_NAIDX   7   /* SQLITE_STMTSTATUS_AUTOINDEX */
#define STMTS_COLUMN_NSTEP   8   /* SQLITE_STMTSTATUS_VM_STEP */
#define STMTS_COLUMN_REPREP  9   /* SQLITE_STMTSTATUS_REPREPARE */
#define STMTS_COLUMN_RUN    10   /* SQLITE_STMTSTATUS_RUN */
#define STMTS_COLUMN_MEM    11   /* SQLITE_STMTSTATUS_MEMUSED */


  rc = sqlite3_declare_vtab(db,
     "CREATE TABLE x(ptr,sql,ncol,ro,busy,nscan,nsort,naidx,nstep,"
                    "reprep,run,mem)");
  if( rc==SQLITE_OK ){
    pNew = sqlite3_malloc( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    pNew->db = db;
  }
................................................................................
    case STMTS_COLUMN_RO: {
      sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt));
      break;
    }
    case STMTS_COLUMN_BUSY: {
      sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
      break;
    }
    case STMTS_COLUMN_MEM: {
      i = SQLITE_STMTSTATUS_MEMUSED + 
            STMTS_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
      /* Fall thru */
    }
    case STMTS_COLUMN_NSCAN:
    case STMTS_COLUMN_NSORT:
    case STMTS_COLUMN_NAIDX:
    case STMTS_COLUMN_NSTEP:
    case STMTS_COLUMN_REPREP:
    case STMTS_COLUMN_RUN: {
      sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt,
                      i-STMTS_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0));
      break;
    }
  }
  return SQLITE_OK;
}

Changes to src/sqlite.h.in.

7143
7144
7145
7146
7147
7148
7149












7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162


7163
7164
7165
7166
7167
7168
7169
7170
** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
** <dd>^This is the number of virtual machine operations executed
** by the prepared statement if that number is less than or equal
** to 2147483647.  The number of virtual machine operations can be 
** used as a proxy for the total work done by the prepared statement.
** If the number of virtual machine operations exceeds 2147483647
** then the value returned by this statement status code is undefined.












**
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
** <dd>^This is the approximate number of bytes of heap memory
** used to store the prepared statement.  ^This value is not actually
** a counter, and so the resetFlg parameter to sqlite3_stmt_status()
** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED.
** </dd>
** </dl>
*/
#define SQLITE_STMTSTATUS_FULLSCAN_STEP     1
#define SQLITE_STMTSTATUS_SORT              2
#define SQLITE_STMTSTATUS_AUTOINDEX         3
#define SQLITE_STMTSTATUS_VM_STEP           4


#define SQLITE_STMTSTATUS_MEMUSED           5

/*
** CAPI3REF: Custom Page Cache Object
**
** The sqlite3_pcache type is opaque.  It is implemented by
** the pluggable module.  The SQLite core has no knowledge of
** its size or internal structure and never deals with the







>
>
>
>
>
>
>
>
>
>
>
>













>
>
|







7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
** <dd>^This is the number of virtual machine operations executed
** by the prepared statement if that number is less than or equal
** to 2147483647.  The number of virtual machine operations can be 
** used as a proxy for the total work done by the prepared statement.
** If the number of virtual machine operations exceeds 2147483647
** then the value returned by this statement status code is undefined.
**
** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt>
** <dd>^This is the number of times that the prepare statement has been
** automatically regenerated due to schema changes or change to 
** [bound parameters] that might affect the query plan.
**
** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt>
** <dd>^This is the number of times that the prepared statement has
** been run.  A single "run" for the purposes of this counter is one
** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()].
** The counter is incremented on the first [sqlite3_step()] call of each
** cycle.
**
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
** <dd>^This is the approximate number of bytes of heap memory
** used to store the prepared statement.  ^This value is not actually
** a counter, and so the resetFlg parameter to sqlite3_stmt_status()
** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED.
** </dd>
** </dl>
*/
#define SQLITE_STMTSTATUS_FULLSCAN_STEP     1
#define SQLITE_STMTSTATUS_SORT              2
#define SQLITE_STMTSTATUS_AUTOINDEX         3
#define SQLITE_STMTSTATUS_VM_STEP           4
#define SQLITE_STMTSTATUS_REPREPARE         5
#define SQLITE_STMTSTATUS_RUN               6
#define SQLITE_STMTSTATUS_MEMUSED           99

/*
** CAPI3REF: Custom Page Cache Object
**
** The sqlite3_pcache type is opaque.  It is implemented by
** the pluggable module.  The SQLite core has no knowledge of
** its size or internal structure and never deals with the

Changes to src/test1.c.

2135
2136
2137
2138
2139
2140
2141



2142
2143
2144
2145
2146
2147
2148
    const char *zName;
    int op;
  } aOp[] = {
    { "SQLITE_STMTSTATUS_FULLSCAN_STEP",   SQLITE_STMTSTATUS_FULLSCAN_STEP   },
    { "SQLITE_STMTSTATUS_SORT",            SQLITE_STMTSTATUS_SORT            },
    { "SQLITE_STMTSTATUS_AUTOINDEX",       SQLITE_STMTSTATUS_AUTOINDEX       },
    { "SQLITE_STMTSTATUS_VM_STEP",         SQLITE_STMTSTATUS_VM_STEP         },



  };
  if( objc!=4 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
    return TCL_ERROR;
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  zOpName = Tcl_GetString(objv[2]);







>
>
>







2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
    const char *zName;
    int op;
  } aOp[] = {
    { "SQLITE_STMTSTATUS_FULLSCAN_STEP",   SQLITE_STMTSTATUS_FULLSCAN_STEP   },
    { "SQLITE_STMTSTATUS_SORT",            SQLITE_STMTSTATUS_SORT            },
    { "SQLITE_STMTSTATUS_AUTOINDEX",       SQLITE_STMTSTATUS_AUTOINDEX       },
    { "SQLITE_STMTSTATUS_VM_STEP",         SQLITE_STMTSTATUS_VM_STEP         },
    { "SQLITE_STMTSTATUS_REPREPARE",       SQLITE_STMTSTATUS_REPREPARE       },
    { "SQLITE_STMTSTATUS_RUN",             SQLITE_STMTSTATUS_RUN             },
    { "SQLITE_STMTSTATUS_MEMUSED",         SQLITE_STMTSTATUS_MEMUSED         },
  };
  if( objc!=4 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
    return TCL_ERROR;
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  zOpName = Tcl_GetString(objv[2]);

Changes to src/vdbe.c.

7075
7076
7077
7078
7079
7080
7081

7082
7083
7084
7085
7086
7087
7088
  if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){
    for(i=1; i<p->nOp; i++){
      if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0;
    }
    pOp->p1 = 0;
  }
  pOp->p1++;

  goto jump_to_p2;
}

#ifdef SQLITE_ENABLE_CURSOR_HINTS
/* Opcode: CursorHint P1 * * P4 *
**
** Provide a hint to cursor P1 that it only needs to return rows that







>







7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
  if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){
    for(i=1; i<p->nOp; i++){
      if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0;
    }
    pOp->p1 = 0;
  }
  pOp->p1++;
  p->aCounter[SQLITE_STMTSTATUS_RUN]++;
  goto jump_to_p2;
}

#ifdef SQLITE_ENABLE_CURSOR_HINTS
/* Opcode: CursorHint P1 * * P4 *
**
** Provide a hint to cursor P1 that it only needs to return rows that

Changes to src/vdbeInt.h.

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  bft runOnlyOnce:1;      /* Automatically expire on reset */
  bft usesStmtJournal:1;  /* True if uses a statement journal */
  bft readOnly:1;         /* True for statements that do not write */
  bft bIsReader:1;        /* True for statements that read */
  bft isPrepareV2:1;      /* True if prepared with prepare_v2() */
  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
  yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
  u32 aCounter[5];        /* Counters used by sqlite3_stmt_status() */
  char *zSql;             /* Text of the SQL statement that generated this */
  void *pFree;            /* Free this when deleting the vdbe */
  VdbeFrame *pFrame;      /* Parent frame */
  VdbeFrame *pDelFrame;   /* List of frame objects to free on VM reset */
  int nFrame;             /* Number of frames in pFrame list */
  u32 expmask;            /* Binding to these vars invalidates VM */
  SubProgram *pProgram;   /* Linked list of all sub-programs used by VM */







|







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  bft runOnlyOnce:1;      /* Automatically expire on reset */
  bft usesStmtJournal:1;  /* True if uses a statement journal */
  bft readOnly:1;         /* True for statements that do not write */
  bft bIsReader:1;        /* True for statements that read */
  bft isPrepareV2:1;      /* True if prepared with prepare_v2() */
  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
  yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
  u32 aCounter[7];        /* Counters used by sqlite3_stmt_status() */
  char *zSql;             /* Text of the SQL statement that generated this */
  void *pFree;            /* Free this when deleting the vdbe */
  VdbeFrame *pFrame;      /* Parent frame */
  VdbeFrame *pDelFrame;   /* List of frame objects to free on VM reset */
  int nFrame;             /* Number of frames in pFrame list */
  u32 expmask;            /* Binding to these vars invalidates VM */
  SubProgram *pProgram;   /* Linked list of all sub-programs used by VM */

Changes to src/vdbeaux.c.

83
84
85
86
87
88
89



90
91
92
93
94
95
96
  pA->pPrev = pB->pPrev;
  pB->pPrev = pTmp;
  zTmp = pA->zSql;
  pA->zSql = pB->zSql;
  pB->zSql = zTmp;
  pB->isPrepareV2 = pA->isPrepareV2;
  pB->expmask = pA->expmask;



}

/*
** Resize the Vdbe.aOp array so that it is at least nOp elements larger 
** than its current size. nOp is guaranteed to be less than or equal
** to 1024/sizeof(Op).
**







>
>
>







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  pA->pPrev = pB->pPrev;
  pB->pPrev = pTmp;
  zTmp = pA->zSql;
  pA->zSql = pB->zSql;
  pB->zSql = zTmp;
  pB->isPrepareV2 = pA->isPrepareV2;
  pB->expmask = pA->expmask;
  memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter));
  pB->aCounter[SQLITE_STMTSTATUS_REPREPARE]++;

}

/*
** Resize the Vdbe.aOp array so that it is at least nOp elements larger 
** than its current size. nOp is guaranteed to be less than or equal
** to 1024/sizeof(Op).
**