SQLite

Check-in [1bc4e93407]
Login

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

Overview
Comment:Change the name of the STMT virtual table to SQLITE_STMT. Also remove the first column of that virtual table, which was a pointer leak.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 1bc4e93407b7894b0271fbde3720930dcaadda6070e871d9719c4e8dc65b915f
User & Date: drh 2017-07-14 15:14:21.567
Context
2017-07-14
15:18
Fix a typo in the header comment to the remember extension. No code changes. (check-in: 604b9664f4 user: drh tags: trunk)
15:14
Change the name of the STMT virtual table to SQLITE_STMT. Also remove the first column of that virtual table, which was a pointer leak. (check-in: 1bc4e93407 user: drh tags: trunk)
13:24
Minor updates to requirements marks and documention. No changes to code. (check-in: 8f6dd5e290 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/misc/stmt.c.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE

/*
** The following macros are used to cast pointers to integers.
** The way you do this varies from one compiler
** to the next, so we have developed the following set of #if statements
** to generate appropriate macros for a wide range of compilers.
*/
#if defined(__PTRDIFF_TYPE__)  /* This case should work for GCC */
# define SQLITE_PTR_TO_INT64(X)  ((sqlite3_int64)(__PTRDIFF_TYPE__)(X))
#elif !defined(__GNUC__)       /* Works for compilers other than LLVM */
# define SQLITE_PTR_TO_INT64(X)  ((sqlite3_int64)(((char*)X)-(char*)0))
#elif defined(HAVE_STDINT_H)   /* Use this case if we have ANSI headers */
# define SQLITE_PTR_TO_INT64(X)  ((sqlite3_int64)(intptr_t)(X))
#else                          /* Generates a warning - but it always works */
# define SQLITE_PTR_TO_INT64(X)  ((sqlite3_int64)(X))
#endif


/* stmt_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a stmt virtual table
*/
typedef struct stmt_vtab stmt_vtab;
struct stmt_vtab {
  sqlite3_vtab base;  /* Base class - must be first */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







25
26
27
28
29
30
31

















32
33
34
35
36
37
38
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE


















/* stmt_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a stmt virtual table
*/
typedef struct stmt_vtab stmt_vtab;
struct stmt_vtab {
  sqlite3_vtab base;  /* Base class - must be first */
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  stmt_vtab *pNew;
  int rc;

/* Column numbers */
#define STMT_COLUMN_PTR     0   /* Numeric value of the statement pointer */
#define STMT_COLUMN_SQL     1   /* SQL for the statement */
#define STMT_COLUMN_NCOL    2   /* Number of result columns */
#define STMT_COLUMN_RO      3   /* True if read-only */
#define STMT_COLUMN_BUSY    4   /* True if currently busy */
#define STMT_COLUMN_NSCAN   5   /* SQLITE_STMTSTATUS_FULLSCAN_STEP */
#define STMT_COLUMN_NSORT   6   /* SQLITE_STMTSTATUS_SORT */
#define STMT_COLUMN_NAIDX   7   /* SQLITE_STMTSTATUS_AUTOINDEX */
#define STMT_COLUMN_NSTEP   8   /* SQLITE_STMTSTATUS_VM_STEP */
#define STMT_COLUMN_REPREP  9   /* SQLITE_STMTSTATUS_REPREPARE */
#define STMT_COLUMN_RUN    10   /* SQLITE_STMTSTATUS_RUN */
#define STMT_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;







<
|
|
|
|
|
|
|
|
|
|
|



|







71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  stmt_vtab *pNew;
  int rc;

/* Column numbers */

#define STMT_COLUMN_SQL     0   /* SQL for the statement */
#define STMT_COLUMN_NCOL    1   /* Number of result columns */
#define STMT_COLUMN_RO      2   /* True if read-only */
#define STMT_COLUMN_BUSY    3   /* True if currently busy */
#define STMT_COLUMN_NSCAN   4   /* SQLITE_STMTSTATUS_FULLSCAN_STEP */
#define STMT_COLUMN_NSORT   5   /* SQLITE_STMTSTATUS_SORT */
#define STMT_COLUMN_NAIDX   6   /* SQLITE_STMTSTATUS_AUTOINDEX */
#define STMT_COLUMN_NSTEP   7   /* SQLITE_STMTSTATUS_VM_STEP */
#define STMT_COLUMN_REPREP  8   /* SQLITE_STMTSTATUS_REPREPARE */
#define STMT_COLUMN_RUN     9   /* SQLITE_STMTSTATUS_RUN */
#define STMT_COLUMN_MEM    10   /* SQLITE_STMTSTATUS_MEMUSED */


  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_malloc( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    pNew->db = db;
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
static int stmtColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  stmt_cursor *pCur = (stmt_cursor*)cur;
  switch( i ){
    case STMT_COLUMN_PTR: {
      sqlite3_result_int64(ctx, SQLITE_PTR_TO_INT64(pCur->pStmt));
      break;
    }
    case STMT_COLUMN_SQL: {
      sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
      break;
    }
    case STMT_COLUMN_NCOL: {
      sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt));
      break;







<
<
<
<







148
149
150
151
152
153
154




155
156
157
158
159
160
161
static int stmtColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  stmt_cursor *pCur = (stmt_cursor*)cur;
  switch( i ){




    case STMT_COLUMN_SQL: {
      sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
      break;
    }
    case STMT_COLUMN_NCOL: {
      sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt));
      break;
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
};

#endif /* SQLITE_OMIT_VIRTUALTABLE */

int sqlite3StmtVtabInit(sqlite3 *db){
  int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  rc = sqlite3_create_module(db, "stmt", &stmtModule, 0);
#endif
  return rc;
}

#ifndef SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)







|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
};

#endif /* SQLITE_OMIT_VIRTUALTABLE */

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)
Changes to test/stmtvtab1.test.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
set x giraffe
set y mango
set z alabama
do_execsql_test stmtvtab1-100 {
  CREATE TABLE t1(a,b,c);
  INSERT INTO t1 VALUES($a,$b,$c);
  CREATE INDEX t1a ON t1(a);
  SELECT run, sql FROM stmt ORDER BY 1;
} {1 {SELECT run, sql FROM stmt ORDER BY 1;} 1 {CREATE INDEX t1a ON t1(a);} 1 {INSERT INTO t1 VALUES($a,$b,$c);} 1 {CREATE TABLE t1(a,b,c);}}
set x neon
set y event
set z future
do_execsql_test stmtvtab1-110 {
  INSERT INTO t1 VALUES($a,$b,$c);
  SELECT reprep,run,SQL FROM stmt WHERE sql LIKE '%INSERT%' AND NOT busy;
} {1 2 {INSERT INTO t1 VALUES($a,$b,$c);}}
set x network
set y fit
set z metal
do_execsql_test stmtvtab1-120 {
  INSERT INTO t1 VALUES($a,$b,$c);
  SELECT reprep,run,SQL FROM stmt WHERE sql LIKE '%INSERT%' AND NOT busy;
} {1 3 {INSERT INTO t1 VALUES($a,$b,$c);}}
set x history
set y detail
set z grace
do_execsql_test stmtvtab1-130 {
  CREATE INDEX t1b ON t1(b);
  INSERT INTO t1 VALUES($a,$b,$c);
  SELECT reprep,run,SQL FROM stmt WHERE sql LIKE '%INSERT%' AND NOT busy;
} {2 4 {INSERT INTO t1 VALUES($a,$b,$c);}}

# All statements are still in cache
#
do_execsql_test stmtvtab1-140 {
  SELECT count(*) FROM stmt WHERE NOT busy;
} {6}

# None of the prepared statements should use more than a couple thousand
# bytes of memory
#
#db eval {SELECT mem, sql FROM stmt} {puts [format {%5d %s} $mem $sql]}
do_execsql_test stmtvtab1-150 {
  SELECT count(*) FROM stmt WHERE mem>5000;
} {0}

# Flushing the cache clears all of the prepared statements.
#
db cache flush
do_execsql_test stmtvtab1-160 {
  SELECT * FROM stmt WHERE NOT busy;
} {}







|
|





|






|







|





|





|

|






|

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
set x giraffe
set y mango
set z alabama
do_execsql_test stmtvtab1-100 {
  CREATE TABLE t1(a,b,c);
  INSERT INTO t1 VALUES($a,$b,$c);
  CREATE INDEX t1a ON t1(a);
  SELECT run, sql FROM sqlite_stmt ORDER BY 1;
} {1 {SELECT run, sql FROM sqlite_stmt ORDER BY 1;} 1 {CREATE INDEX t1a ON t1(a);} 1 {INSERT INTO t1 VALUES($a,$b,$c);} 1 {CREATE TABLE t1(a,b,c);}}
set x neon
set y event
set z future
do_execsql_test stmtvtab1-110 {
  INSERT INTO t1 VALUES($a,$b,$c);
  SELECT reprep,run,SQL FROM sqlite_stmt WHERE sql LIKE '%INSERT%' AND NOT busy;
} {1 2 {INSERT INTO t1 VALUES($a,$b,$c);}}
set x network
set y fit
set z metal
do_execsql_test stmtvtab1-120 {
  INSERT INTO t1 VALUES($a,$b,$c);
  SELECT reprep,run,SQL FROM sqlite_stmt WHERE sql LIKE '%INSERT%' AND NOT busy;
} {1 3 {INSERT INTO t1 VALUES($a,$b,$c);}}
set x history
set y detail
set z grace
do_execsql_test stmtvtab1-130 {
  CREATE INDEX t1b ON t1(b);
  INSERT INTO t1 VALUES($a,$b,$c);
  SELECT reprep,run,SQL FROM sqlite_stmt WHERE sql LIKE '%INSERT%' AND NOT busy;
} {2 4 {INSERT INTO t1 VALUES($a,$b,$c);}}

# All statements are still in cache
#
do_execsql_test stmtvtab1-140 {
  SELECT count(*) FROM sqlite_stmt WHERE NOT busy;
} {6}

# None of the prepared statements should use more than a couple thousand
# bytes of memory
#
#db eval {SELECT mem, sql FROM sqlite_stmt} {puts [format {%5d %s} $mem $sql]}
do_execsql_test stmtvtab1-150 {
  SELECT count(*) FROM sqlite_stmt WHERE mem>5000;
} {0}

# Flushing the cache clears all of the prepared statements.
#
db cache flush
do_execsql_test stmtvtab1-160 {
  SELECT * FROM sqlite_stmt WHERE NOT busy;
} {}