/ Check-in [1bc4e934]
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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:1bc4e93407b7894b0271fbde3720930dcaadda6070e871d9719c4e8dc65b915f
User & Date: drh 2017-07-14 15:14:21
Context
2017-07-14
15:18
Fix a typo in the header comment to the remember extension. No code changes. check-in: 604b9664 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: 1bc4e934 user: drh tags: trunk
13:24
Minor updates to requirements marks and documention. No changes to code. check-in: 8f6dd5e2 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs 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
..
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
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
#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 */
................................................................................
  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;
................................................................................
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;
................................................................................
};

#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)







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







 







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



|







 







<
<
<
<







 







|







25
26
27
28
29
30
31

















32
33
34
35
36
37
38
..
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
...
148
149
150
151
152
153
154




155
156
157
158
159
160
161
...
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#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 */
................................................................................
  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;
................................................................................
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;
................................................................................
};

#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;
} {}