SQLite4
Check-in [c8d956ad1a]
Not logged in

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

Overview
Comment:Change the names of some API functions to make their purposes clearer: "get_auxdata" -> "auxdata_fetch", "set_auxdata" -> "auxdata_store", "get_autocommit" -> "db_transaction_status", and "sql" -> "stmt_sql".
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c8d956ad1a336c83d25eb71b81fd9a87c247dd13
User & Date: dan 2013-06-06 17:18:17
Context
2013-06-07
00:49
Coverting an approximate sqlite4_num to int64 is flagged as lossy. check-in: b667dab56b user: peterreid tags: trunk
2013-06-06
17:18
Change the names of some API functions to make their purposes clearer: "get_auxdata" -> "auxdata_fetch", "set_auxdata" -> "auxdata_store", "get_autocommit" -> "db_transaction_status", and "sql" -> "stmt_sql". check-in: c8d956ad1a user: dan tags: trunk
16:43
Add documentation for sqlite4_kvstore_methods.xGetMethod. Use the lsm pragmas in various tests instead of the file-controls. check-in: c39156d2b8 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/fts5func.c.

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

  int bm25mask = SQLITE4_PTR_TO_INT(sqlite4_context_appdata(pCtx));
  bExplain = (bm25mask & BM25_EXPLAIN);

  if( bm25mask & BM25_FCOLUMNS ) sqlite4_mi_column_count(pCtx, &nField);
  if( bm25mask & BM25_FSTREAMS ) sqlite4_mi_stream_count(pCtx, &nField);

  p = sqlite4_get_auxdata(pCtx, 0);
  if( p==0 ){
    int nPhrase;                  /* Number of phrases in query expression */
    int nByte;                    /* Number of bytes of data to allocate */

    sqlite4_mi_phrase_count(pCtx, &nPhrase);
    nByte = sizeof(Fts5RankCtx) + (nPhrase+nField) * sizeof(double);
    p = (Fts5RankCtx *)sqlite4DbMallocZero(db, nByte);
    sqlite4_set_auxdata(pCtx, 0, (void *)p, fts5RankFreeCtx, 0);
    p = sqlite4_get_auxdata(pCtx, 0);

    if( !p ){
      rc = SQLITE4_NOMEM;
    }else{
      int N;                      /* Total number of docs in collection */
      int ni;                     /* Number of docs with phrase i */








|







|
|







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

  int bm25mask = SQLITE4_PTR_TO_INT(sqlite4_context_appdata(pCtx));
  bExplain = (bm25mask & BM25_EXPLAIN);

  if( bm25mask & BM25_FCOLUMNS ) sqlite4_mi_column_count(pCtx, &nField);
  if( bm25mask & BM25_FSTREAMS ) sqlite4_mi_stream_count(pCtx, &nField);

  p = sqlite4_auxdata_fetch(pCtx, 0);
  if( p==0 ){
    int nPhrase;                  /* Number of phrases in query expression */
    int nByte;                    /* Number of bytes of data to allocate */

    sqlite4_mi_phrase_count(pCtx, &nPhrase);
    nByte = sizeof(Fts5RankCtx) + (nPhrase+nField) * sizeof(double);
    p = (Fts5RankCtx *)sqlite4DbMallocZero(db, nByte);
    sqlite4_auxdata_store(pCtx, 0, (void *)p, fts5RankFreeCtx, 0);
    p = sqlite4_auxdata_fetch(pCtx, 0);

    if( !p ){
      rc = SQLITE4_NOMEM;
    }else{
      int N;                      /* Total number of docs in collection */
      int ni;                     /* Number of docs with phrase i */

Changes to src/main.c.

1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
  db->pCollNeededArg = pCollNeededArg;
  sqlite4_mutex_leave(db->mutex);
  return SQLITE4_OK;
}
#endif /* SQLITE4_OMIT_UTF16 */

/*
** Test to see whether or not the database connection is in autocommit
** mode.  Return TRUE if it is and FALSE if not.  Autocommit mode is on
** by default.  Autocommit is disabled by a BEGIN statement and reenabled
** by the next COMMIT or ROLLBACK.
*/
int sqlite4_get_autocommit(sqlite4 *db){
  return (db->pSavepoint==0);
}

/*
** The following routines are subtitutes for constants SQLITE4_CORRUPT,
** SQLITE4_MISUSE, SQLITE4_CANTOPEN, SQLITE4_IOERR and possibly other error
** constants.  They server two purposes:
**







|
|
|
|

|
|







1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
  db->pCollNeededArg = pCollNeededArg;
  sqlite4_mutex_leave(db->mutex);
  return SQLITE4_OK;
}
#endif /* SQLITE4_OMIT_UTF16 */

/*
** Test to see whether or not the database connection is currently within
** an explicitly started transaction (BEGIN/COMMIT block). Return non-zero 
** if it is and FALSE otherwise. Explicit transactions are opened by a 
** BEGIN statement and concluded by the next COMMIT or ROLLBACK.
*/
int sqlite4_db_transaction_status(sqlite4 *db){
  return (db->pSavepoint!=0);
}

/*
** The following routines are subtitutes for constants SQLITE4_CORRUPT,
** SQLITE4_MISUSE, SQLITE4_CANTOPEN, SQLITE4_IOERR and possibly other error
** constants.  They server two purposes:
**

Changes to src/prepare.c.

623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
int sqlite4Reprepare(Vdbe *p){
  int rc;
  sqlite4_stmt *pNew;
  const char *zSql;
  sqlite4 *db;

  assert( sqlite4_mutex_held(sqlite4VdbeDb(p)->mutex) );
  zSql = sqlite4_sql((sqlite4_stmt *)p);
  db = sqlite4VdbeDb(p);
  assert( sqlite4_mutex_held(db->mutex) );
  rc = sqlite4LockAndPrepare(db, zSql, -1, p, &pNew, 0);
  if( rc ){
    if( rc==SQLITE4_NOMEM ){
      db->mallocFailed = 1;
    }







|







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
int sqlite4Reprepare(Vdbe *p){
  int rc;
  sqlite4_stmt *pNew;
  const char *zSql;
  sqlite4 *db;

  assert( sqlite4_mutex_held(sqlite4VdbeDb(p)->mutex) );
  zSql = sqlite4_stmt_sql((sqlite4_stmt *)p);
  db = sqlite4VdbeDb(p);
  assert( sqlite4_mutex_held(db->mutex) );
  rc = sqlite4LockAndPrepare(db, zSql, -1, p, &pNew, 0);
  if( rc ){
    if( rc==SQLITE4_NOMEM ){
      db->mallocFailed = 1;
    }

Changes to src/shell.c.

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100

    rc = sqlite4_prepare(db, zSql, -1, &pStmt, &nUsed);
    if( rc!=SQLITE4_OK ) return rc;
    zSql += nUsed;
    if( pStmt==0 ) continue;      /* A comment or whitespace */

    if( pArg->echoOn ){
      const char *zStmtSql = sqlite4_sql(pStmt);
      fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
    }

    /* Output TESTCTRL_EXPLAIN text of requested */
    if( pArg->mode==MODE_Explain ){
      const char *zExplain = 0;
      sqlite4_test_control(SQLITE4_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);







|







1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100

    rc = sqlite4_prepare(db, zSql, -1, &pStmt, &nUsed);
    if( rc!=SQLITE4_OK ) return rc;
    zSql += nUsed;
    if( pStmt==0 ) continue;      /* A comment or whitespace */

    if( pArg->echoOn ){
      const char *zStmtSql = sqlite4_stmt_sql(pStmt);
      fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
    }

    /* Output TESTCTRL_EXPLAIN text of requested */
    if( pArg->mode==MODE_Explain ){
      const char *zExplain = 0;
      sqlite4_test_control(SQLITE4_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);

Changes to src/sqlite.h.in.

1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
....
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
....
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
....
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
....
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
/*
** CAPIREF: Retrieving Statement SQL
**
** ^This interface can be used to retrieve a saved copy of the original
** SQL text used to create a [prepared statement] if that statement was
** compiled using either [sqlite4_prepare()] or [sqlite4_prepare16_v2()].
*/
const char *sqlite4_sql(sqlite4_stmt *pStmt);

/*
** CAPIREF: Determine If An SQL Statement Writes The Database
**
** ^The sqlite4_stmt_readonly(X) interface returns true (non-zero) if
** and only if the [prepared statement] X makes no direct changes to
** the content of the database file.
................................................................................
**
** The context in which an SQL function executes is stored in an
** sqlite4_context object.  ^A pointer to an sqlite4_context object
** is always first parameter to [application-defined SQL functions].
** The application-defined SQL function implementation will pass this
** pointer through into calls to [sqlite4_result_int | sqlite4_result()],
** [sqlite4_aggregate_context()], [sqlite4_context_appdata()],
** [sqlite4_context_db_handle()], [sqlite4_get_auxdata()],
** and/or [sqlite4_set_auxdata()].
*/
typedef struct sqlite4_context sqlite4_context;

/*
** CAPIREF: Binding Values To Prepared Statements
** KEYWORDS: {host parameter} {host parameters} {host parameter name}
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
................................................................................
** be used, for example, to add a regular-expression matching scalar
** function. The compiled version of the regular expression is stored as
** metadata associated with the SQL value passed as the regular expression
** pattern.  The compiled regular expression can be reused on multiple
** invocations of the same function so that the original pattern string
** does not need to be recompiled on each invocation.
**
** ^The sqlite4_get_auxdata() interface returns a pointer to the metadata
** associated by the sqlite4_set_auxdata() function with the Nth argument
** value to the application-defined function. ^If no metadata has been ever
** been set for the Nth argument of the function, or if the corresponding
** function parameter has changed since the meta-data was set,
** then sqlite4_get_auxdata() returns a NULL pointer.
**
** ^The sqlite4_set_auxdata() interface saves the metadata
** pointed to by its 3rd parameter as the metadata for the N-th
** argument of the application-defined function.  Subsequent
** calls to sqlite4_get_auxdata() might return this data, if it has
** not been destroyed.
** ^If it is not NULL, SQLite will invoke the destructor
** function given by the 4th parameter to sqlite4_set_auxdata() on
** the metadata when the corresponding function parameter changes
** or when the SQL statement completes, whichever comes first.
**
** SQLite is free to call the destructor and drop metadata on any
** parameter of any function at any time.  ^The only guarantee is that
** the destructor will be called before the metadata is dropped.
**
................................................................................
** ^(In practice, metadata is preserved between function calls for
** expressions that are constant at compile time. This includes literal
** values and [parameters].)^
**
** These routines must be called from the same thread in which
** the SQL function is running.
*/
void *sqlite4_get_auxdata(sqlite4_context*, int N);
void sqlite4_set_auxdata(sqlite4_context*, int N, void*,
                         void (*)(void*,void*),void*);


/*
** CAPIREF: Constants Defining Special Destructor Behavior
**
** These are special values for the destructor that is passed in as the
................................................................................
*/
int sqlite4_sleep(int);

/*
** CAPIREF: Test For Auto-Commit Mode
** KEYWORDS: {autocommit mode}
**
** ^The sqlite4_get_autocommit() interface returns non-zero or
** zero if the given database connection is or is not in autocommit mode,
** respectively.  ^Autocommit mode is on by default.
** ^Autocommit mode is disabled by a [BEGIN] statement.
** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK].
**
** If certain kinds of errors occur on a statement within a multi-statement
** transaction (errors including [SQLITE4_FULL], [SQLITE4_IOERR],
** [SQLITE4_NOMEM], [SQLITE4_BUSY], and [SQLITE4_INTERRUPT]) then the
** transaction might be rolled back automatically.  The only way to
** find out whether SQLite automatically rolled back the transaction after
** an error is to use this function.
**
** If another thread changes the autocommit status of the database
** connection while this routine is running, then the return value
** is undefined.
*/
int sqlite4_get_autocommit(sqlite4*);

/*
** CAPIREF: Find The Database Handle Of A Prepared Statement
**
** ^The sqlite4_db_handle interface returns the [database connection] handle
** to which a [prepared statement] belongs.  ^The [database connection]
** returned by sqlite4_db_handle is the same [database connection]







|







 







|
|







 







|
|



|

|


|


|







 







|
|







 







|
|
|
|
|

|






|
|
|

|







1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
....
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
....
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
....
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
....
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
/*
** CAPIREF: Retrieving Statement SQL
**
** ^This interface can be used to retrieve a saved copy of the original
** SQL text used to create a [prepared statement] if that statement was
** compiled using either [sqlite4_prepare()] or [sqlite4_prepare16_v2()].
*/
const char *sqlite4_stmt_sql(sqlite4_stmt *pStmt);

/*
** CAPIREF: Determine If An SQL Statement Writes The Database
**
** ^The sqlite4_stmt_readonly(X) interface returns true (non-zero) if
** and only if the [prepared statement] X makes no direct changes to
** the content of the database file.
................................................................................
**
** The context in which an SQL function executes is stored in an
** sqlite4_context object.  ^A pointer to an sqlite4_context object
** is always first parameter to [application-defined SQL functions].
** The application-defined SQL function implementation will pass this
** pointer through into calls to [sqlite4_result_int | sqlite4_result()],
** [sqlite4_aggregate_context()], [sqlite4_context_appdata()],
** [sqlite4_context_db_handle()], [sqlite4_auxdata_fetch()],
** and/or [sqlite4_auxdata_store()].
*/
typedef struct sqlite4_context sqlite4_context;

/*
** CAPIREF: Binding Values To Prepared Statements
** KEYWORDS: {host parameter} {host parameters} {host parameter name}
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
................................................................................
** be used, for example, to add a regular-expression matching scalar
** function. The compiled version of the regular expression is stored as
** metadata associated with the SQL value passed as the regular expression
** pattern.  The compiled regular expression can be reused on multiple
** invocations of the same function so that the original pattern string
** does not need to be recompiled on each invocation.
**
** ^The sqlite4_auxdata_fetch() interface returns a pointer to the metadata
** associated by the sqlite4_auxdata_store() function with the Nth argument
** value to the application-defined function. ^If no metadata has been ever
** been set for the Nth argument of the function, or if the corresponding
** function parameter has changed since the meta-data was set,
** then sqlite4_auxdata_fetch() returns a NULL pointer.
**
** ^The sqlite4_auxdata_store() interface saves the metadata
** pointed to by its 3rd parameter as the metadata for the N-th
** argument of the application-defined function.  Subsequent
** calls to sqlite4_auxdata_fetch() might return this data, if it has
** not been destroyed.
** ^If it is not NULL, SQLite will invoke the destructor
** function given by the 4th parameter to sqlite4_auxdata_store() on
** the metadata when the corresponding function parameter changes
** or when the SQL statement completes, whichever comes first.
**
** SQLite is free to call the destructor and drop metadata on any
** parameter of any function at any time.  ^The only guarantee is that
** the destructor will be called before the metadata is dropped.
**
................................................................................
** ^(In practice, metadata is preserved between function calls for
** expressions that are constant at compile time. This includes literal
** values and [parameters].)^
**
** These routines must be called from the same thread in which
** the SQL function is running.
*/
void *sqlite4_auxdata_fetch(sqlite4_context*, int N);
void sqlite4_auxdata_store(sqlite4_context*, int N, void*,
                         void (*)(void*,void*),void*);


/*
** CAPIREF: Constants Defining Special Destructor Behavior
**
** These are special values for the destructor that is passed in as the
................................................................................
*/
int sqlite4_sleep(int);

/*
** CAPIREF: Test For Auto-Commit Mode
** KEYWORDS: {autocommit mode}
**
** ^The sqlite4_db_transaction_status() interface returns non-zero if
** the database connection passed as the only argument is currently within
** an explicitly started transaction. An explicit transaction is opened
** using a [BEGIN] command, and usually concluded using a [COMMIT] or
** [ROLLBACK].
**
** If certain kinds of errors occur on a statement within an explicit
** transaction (errors including [SQLITE4_FULL], [SQLITE4_IOERR],
** [SQLITE4_NOMEM], [SQLITE4_BUSY], and [SQLITE4_INTERRUPT]) then the
** transaction might be rolled back automatically.  The only way to
** find out whether SQLite automatically rolled back the transaction after
** an error is to use this function.
**
** If another thread opens or closes a transaction on this database 
** connection while this routine is running, then the return value is 
** undefined.
*/
int sqlite4_db_transaction_status(sqlite4*);

/*
** CAPIREF: Find The Database Handle Of A Prepared Statement
**
** ^The sqlite4_db_handle interface returns the [database connection] handle
** to which a [prepared statement] belongs.  ^The [database connection]
** returned by sqlite4_db_handle is the same [database connection]

Changes to src/tclsqlite.c.

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
...
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
}

/*
** Free a single SqlPreparedStmt object.
*/
static void dbFreeStmt(SqlPreparedStmt *pStmt){
#ifdef SQLITE4_TEST
  if( sqlite4_sql(pStmt->pStmt)==0 ){
    Tcl_Free((char *)pStmt->zSql);
  }
#endif
  sqlite4_finalize(pStmt->pStmt);
  Tcl_Free((char *)pStmt);
}

................................................................................
    nVar = sqlite4_bind_parameter_count(pStmt);
    nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *);
    pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte);
    memset(pPreStmt, 0, nByte);

    pPreStmt->pStmt = pStmt;
    pPreStmt->nSql = nUsed;
    pPreStmt->zSql = sqlite4_sql(pStmt);
    pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1];
#ifdef SQLITE4_TEST
    if( pPreStmt->zSql==0 ){
      char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1);
      memcpy(zCopy, zSql, pPreStmt->nSql);
      zCopy[pPreStmt->nSql] = '\0';
      pPreStmt->zSql = zCopy;







|







 







|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
...
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
}

/*
** Free a single SqlPreparedStmt object.
*/
static void dbFreeStmt(SqlPreparedStmt *pStmt){
#ifdef SQLITE4_TEST
  if( sqlite4_stmt_sql(pStmt->pStmt)==0 ){
    Tcl_Free((char *)pStmt->zSql);
  }
#endif
  sqlite4_finalize(pStmt->pStmt);
  Tcl_Free((char *)pStmt);
}

................................................................................
    nVar = sqlite4_bind_parameter_count(pStmt);
    nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *);
    pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte);
    memset(pPreStmt, 0, nByte);

    pPreStmt->pStmt = pStmt;
    pPreStmt->nSql = nUsed;
    pPreStmt->zSql = sqlite4_stmt_sql(pStmt);
    pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1];
#ifdef SQLITE4_TEST
    if( pPreStmt->zSql==0 ){
      char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1);
      memcpy(zCopy, zSql, pPreStmt->nSql);
      zCopy[pPreStmt->nSql] = '\0';
      pPreStmt->zSql = zCopy;

Changes to src/vdbe.c.

1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
** successors.  The result of the function is stored in register P3.
** Register P3 must not be one of the function inputs.
**
** P1 is a 32-bit bitmask indicating whether or not each argument to the 
** function was determined to be constant at compile time. If the first
** argument was constant then bit 0 of P1 is set. This is used to determine
** whether meta data associated with a user function argument using the
** sqlite4_set_auxdata() API may be safely retained until the next
** invocation of this opcode.
**
** See also: AggStep and AggFinal
*/
case OP_Function: {
  int i;
  Mem *pArg;







|







1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
** successors.  The result of the function is stored in register P3.
** Register P3 must not be one of the function inputs.
**
** P1 is a 32-bit bitmask indicating whether or not each argument to the 
** function was determined to be constant at compile time. If the first
** argument was constant then bit 0 of P1 is set. This is used to determine
** whether meta data associated with a user function argument using the
** sqlite4_auxdata_store() API may be safely retained until the next
** invocation of this opcode.
**
** See also: AggStep and AggFinal
*/
case OP_Function: {
  int i;
  Mem *pArg;

Changes to src/vdbeInt.h.

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#ifdef SQLITE4_DEBUG
#define memIsValid(M)  ((M)->flags & MEM_Invalid)==0
#endif


/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
** additional information about auxiliary information bound to arguments
** of the function.  This is used to implement the sqlite4_get_auxdata()
** and sqlite4_set_auxdata() APIs.  The "auxdata" is some auxiliary data
** that can be associated with a constant argument to a function.  This
** allows functions such as "regexp" to compile their constant regular
** expression argument once and reused the compiled code for multiple
** invocations.
*/
struct VdbeFunc {
  FuncDef *pFunc;               /* The definition of the function */







|
|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#ifdef SQLITE4_DEBUG
#define memIsValid(M)  ((M)->flags & MEM_Invalid)==0
#endif


/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
** additional information about auxiliary information bound to arguments
** of the function.  This is used to implement the sqlite4_auxdata_fetch()
** and sqlite4_auxdata_store() APIs.  The "auxdata" is some auxiliary data
** that can be associated with a constant argument to a function.  This
** allows functions such as "regexp" to compile their constant regular
** expression argument once and reused the compiled code for multiple
** invocations.
*/
struct VdbeFunc {
  FuncDef *pFunc;               /* The definition of the function */

Changes to src/vdbeapi.c.

566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
  return (void*)pMem->z;
}

/*
** Return the auxilary data pointer, if any, for the iArg'th argument to
** the user-function defined by pCtx.
*/
void *sqlite4_get_auxdata(sqlite4_context *pCtx, int iArg){
  VdbeFunc *pVdbeFunc;

  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  pVdbeFunc = pCtx->pVdbeFunc;
  if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
    return 0;
  }
................................................................................
}

/*
** Set the auxilary data pointer and delete function, for the iArg'th
** argument to the user-function defined by pCtx. Any previous value is
** deleted by calling the delete function specified when it was set.
*/
void sqlite4_set_auxdata(
  sqlite4_context *pCtx, 
  int iArg, 
  void *pAux, 
  void (*xDelete)(void*,void*),
  void *pDeleteArg
){
  struct AuxData *pAuxData;







|







 







|







566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
  return (void*)pMem->z;
}

/*
** Return the auxilary data pointer, if any, for the iArg'th argument to
** the user-function defined by pCtx.
*/
void *sqlite4_auxdata_fetch(sqlite4_context *pCtx, int iArg){
  VdbeFunc *pVdbeFunc;

  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  pVdbeFunc = pCtx->pVdbeFunc;
  if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
    return 0;
  }
................................................................................
}

/*
** Set the auxilary data pointer and delete function, for the iArg'th
** argument to the user-function defined by pCtx. Any previous value is
** deleted by calling the delete function specified when it was set.
*/
void sqlite4_auxdata_store(
  sqlite4_context *pCtx, 
  int iArg, 
  void *pAux, 
  void (*xDelete)(void*,void*),
  void *pDeleteArg
){
  struct AuxData *pAuxData;

Changes to src/vdbeaux.c.

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  assert( p->zSql==0 );
  p->zSql = sqlite4DbStrNDup(p->db, z, n);
}

/*
** Return the SQL associated with a prepared statement
*/
const char *sqlite4_sql(sqlite4_stmt *pStmt){
  Vdbe *p = (Vdbe *)pStmt;
  return p ? p->zSql : 0;
}

/*
** Swap all content between two VDBE structures.
*/







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  assert( p->zSql==0 );
  p->zSql = sqlite4DbStrNDup(p->db, z, n);
}

/*
** Return the SQL associated with a prepared statement
*/
const char *sqlite4_stmt_sql(sqlite4_stmt *pStmt){
  Vdbe *p = (Vdbe *)pStmt;
  return p ? p->zSql : 0;
}

/*
** Swap all content between two VDBE structures.
*/

Changes to test/savepoint.test.

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
...
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
sqlite4 db test.db
do_test savepoint-1.4.1 {
  execsql {
    SAVEPOINT sp1;
    SAVEPOINT sp2;
    RELEASE sp1;
  }
  sqlite4_get_autocommit db
} {1}
do_test savepoint-1.4.2 {
  execsql {
    SAVEPOINT sp1;
    SAVEPOINT sp2;
    RELEASE sp2;
  }
  sqlite4_get_autocommit db
} {0}
do_test savepoint-1.4.3 {
  execsql { RELEASE sp1 }
  sqlite4_get_autocommit db
} {1}
do_test savepoint-1.4.4 {
  execsql {
    SAVEPOINT sp1;
    SAVEPOINT sp2;
    ROLLBACK TO sp1;
  }
  sqlite4_get_autocommit db
} {0}
do_test savepoint-1.4.5 {
  execsql { RELEASE SAVEPOINT sp1 }
  sqlite4_get_autocommit db
} {1}
do_test savepoint-1.4.6 {
  execsql {
    SAVEPOINT sp1;
    SAVEPOINT sp2;
    SAVEPOINT sp3;
    ROLLBACK TO SAVEPOINT sp3;
    ROLLBACK TRANSACTION TO sp2;
    ROLLBACK TRANSACTION TO SAVEPOINT sp1;
  }
  sqlite4_get_autocommit db
} {0}
do_test savepoint-1.4.7 {
  execsql { RELEASE SAVEPOINT SP1 }
  sqlite4_get_autocommit db
} {1}
do_test savepoint-1.5 {
  execsql {
    SAVEPOINT sp1;
    ROLLBACK TO sp1;
  }
} {}
do_test savepoint-1.6 {
................................................................................
      SAVEPOINT sp1;
        INSERT INTO t4 VALUES(3, 'three');
        SAVEPOINT sp2;
          INSERT OR ROLLBACK INTO t4 VALUES(1, 'one');
  }
} {1 {PRIMARY KEY must be unique}}
do_test savepoint-12.3 {
  sqlite4_get_autocommit db
} {1}
do_test savepoint-12.4 {
  execsql { SAVEPOINT one }
} {}
wal_check_journal_mode savepoint-12.5

#-------------------------------------------------------------------------
# The following tests - savepoint-13.* - test the interaction of 







|
|






|
|


|
|






|
|


|
|









|
|


|
|







 







|
|







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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
...
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
sqlite4 db test.db
do_test savepoint-1.4.1 {
  execsql {
    SAVEPOINT sp1;
    SAVEPOINT sp2;
    RELEASE sp1;
  }
  sqlite4_db_transaction_status db
} {0}
do_test savepoint-1.4.2 {
  execsql {
    SAVEPOINT sp1;
    SAVEPOINT sp2;
    RELEASE sp2;
  }
  sqlite4_db_transaction_status db
} {1}
do_test savepoint-1.4.3 {
  execsql { RELEASE sp1 }
  sqlite4_db_transaction_status db
} {0}
do_test savepoint-1.4.4 {
  execsql {
    SAVEPOINT sp1;
    SAVEPOINT sp2;
    ROLLBACK TO sp1;
  }
  sqlite4_db_transaction_status db
} {1}
do_test savepoint-1.4.5 {
  execsql { RELEASE SAVEPOINT sp1 }
  sqlite4_db_transaction_status db
} {0}
do_test savepoint-1.4.6 {
  execsql {
    SAVEPOINT sp1;
    SAVEPOINT sp2;
    SAVEPOINT sp3;
    ROLLBACK TO SAVEPOINT sp3;
    ROLLBACK TRANSACTION TO sp2;
    ROLLBACK TRANSACTION TO SAVEPOINT sp1;
  }
  sqlite4_db_transaction_status db
} {1}
do_test savepoint-1.4.7 {
  execsql { RELEASE SAVEPOINT SP1 }
  sqlite4_db_transaction_status db
} {0}
do_test savepoint-1.5 {
  execsql {
    SAVEPOINT sp1;
    ROLLBACK TO sp1;
  }
} {}
do_test savepoint-1.6 {
................................................................................
      SAVEPOINT sp1;
        INSERT INTO t4 VALUES(3, 'three');
        SAVEPOINT sp2;
          INSERT OR ROLLBACK INTO t4 VALUES(1, 'one');
  }
} {1 {PRIMARY KEY must be unique}}
do_test savepoint-12.3 {
  sqlite4_db_transaction_status db
} {0}
do_test savepoint-12.4 {
  execsql { SAVEPOINT one }
} {}
wal_check_journal_mode savepoint-12.5

#-------------------------------------------------------------------------
# The following tests - savepoint-13.* - test the interaction of 

Changes to test/test_func.c.

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
  z = sqlite4_errmsg16(db);
  sqlite4EndBenignMalloc();
  sqlite4_result_text16(ctx, z, -1, SQLITE4_TRANSIENT, 0);
#endif
}

/*
** Routines for testing the sqlite4_get_auxdata() and sqlite4_set_auxdata()
** interface.
**
** The test_auxdata() SQL function attempts to register each of its arguments
** as auxiliary data.  If there are no prior registrations of aux data for
** that argument (meaning the argument is not a constant or this is its first
** call) then the result for that argument is 0.  If there is a prior
** registration, the result for that argument is 1.  The overall result
................................................................................
  char *zRet = testContextMalloc(pCtx, nArg*2);
  if( !zRet ) return;
  memset(zRet, 0, nArg*2);
  for(i=0; i<nArg; i++){
    char const *z = sqlite4_value_text(argv[i], 0);
    if( z ){
      int n;
      char *zAux = sqlite4_get_auxdata(pCtx, i);
      if( zAux ){
        zRet[i*2] = '1';
        assert( strcmp(zAux,z)==0 );
      }else {
        zRet[i*2] = '0';
      }
      n = strlen(z) + 1;
      zAux = testContextMalloc(pCtx, n);
      if( zAux ){
        memcpy(zAux, z, n);
        sqlite4_set_auxdata(pCtx, i, zAux,
                            free_test_auxdata, sqlite4_context_env(pCtx));
      }
      zRet[i*2+1] = ' ';
    }
  }
  sqlite4_result_text(pCtx, zRet, 2*nArg-1,
                      free_test_auxdata, sqlite4_context_env(pCtx));
................................................................................
*/
static void counterFunc(
  sqlite4_context *pCtx,   /* Function context */
  int nArg,                /* Number of function arguments */
  sqlite4_value **argv     /* Values for all function arguments */
){
  struct counterObject *pCounter;
  pCounter = (struct counterObject*)sqlite4_get_auxdata(pCtx, 0);
  if( pCounter==0 ){
    pCounter = sqlite4_malloc(sqlite4_context_env(pCtx), sizeof(*pCounter) );
    if( pCounter==0 ){
      sqlite4_result_error_nomem(pCtx);
      return;
    }
    pCounter->cnt = sqlite4_value_int(argv[0]);
    pCounter->pEnv = sqlite4_context_env(pCtx);
    sqlite4_set_auxdata(pCtx, 0, pCounter, counterFree, 0);
  }else{
    pCounter->cnt++;
  }
  sqlite4_result_int(pCtx, pCounter->cnt);
}









|







 







|










|







 







|








|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
  z = sqlite4_errmsg16(db);
  sqlite4EndBenignMalloc();
  sqlite4_result_text16(ctx, z, -1, SQLITE4_TRANSIENT, 0);
#endif
}

/*
** Routines for testing the sqlite4_auxdata_fetch() and sqlite4_auxdata_store()
** interface.
**
** The test_auxdata() SQL function attempts to register each of its arguments
** as auxiliary data.  If there are no prior registrations of aux data for
** that argument (meaning the argument is not a constant or this is its first
** call) then the result for that argument is 0.  If there is a prior
** registration, the result for that argument is 1.  The overall result
................................................................................
  char *zRet = testContextMalloc(pCtx, nArg*2);
  if( !zRet ) return;
  memset(zRet, 0, nArg*2);
  for(i=0; i<nArg; i++){
    char const *z = sqlite4_value_text(argv[i], 0);
    if( z ){
      int n;
      char *zAux = sqlite4_auxdata_fetch(pCtx, i);
      if( zAux ){
        zRet[i*2] = '1';
        assert( strcmp(zAux,z)==0 );
      }else {
        zRet[i*2] = '0';
      }
      n = strlen(z) + 1;
      zAux = testContextMalloc(pCtx, n);
      if( zAux ){
        memcpy(zAux, z, n);
        sqlite4_auxdata_store(pCtx, i, zAux,
                            free_test_auxdata, sqlite4_context_env(pCtx));
      }
      zRet[i*2+1] = ' ';
    }
  }
  sqlite4_result_text(pCtx, zRet, 2*nArg-1,
                      free_test_auxdata, sqlite4_context_env(pCtx));
................................................................................
*/
static void counterFunc(
  sqlite4_context *pCtx,   /* Function context */
  int nArg,                /* Number of function arguments */
  sqlite4_value **argv     /* Values for all function arguments */
){
  struct counterObject *pCounter;
  pCounter = (struct counterObject*)sqlite4_auxdata_fetch(pCtx, 0);
  if( pCounter==0 ){
    pCounter = sqlite4_malloc(sqlite4_context_env(pCtx), sizeof(*pCounter) );
    if( pCounter==0 ){
      sqlite4_result_error_nomem(pCtx);
      return;
    }
    pCounter->cnt = sqlite4_value_int(argv[0]);
    pCounter->pEnv = sqlite4_context_env(pCtx);
    sqlite4_auxdata_store(pCtx, 0, pCounter, counterFree, 0);
  }else{
    pCounter->cnt++;
  }
  sqlite4_result_int(pCtx, pCounter->cnt);
}


Changes to test/test_main.c.

3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
....
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
....
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
....
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
....
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
  rc = sqlite4_step(pStmt);

  /* if( rc!=SQLITE4_DONE && rc!=SQLITE4_ROW ) return TCL_ERROR; */
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  return TCL_OK;
}

static int test_sql(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite4_stmt *pStmt;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT");
    return TCL_ERROR;
  }

  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  Tcl_SetResult(interp, (char *)sqlite4_sql(pStmt), TCL_VOLATILE);
  return TCL_OK;
}

/*
** Usage: sqlite4_column_count STMT 
**
** Return the number of columns returned by the sql statement STMT.
................................................................................
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  rc = sqlite4_create_collation(db, argv[2], SQLITE4_UTF8, 0, 0, 0, 0);
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  return TCL_OK;
}

/*
** Usage: sqlite4_get_autocommit DB
**
** Return true if the database DB is currently in auto-commit mode.
** Return false if not.
*/
static int get_autocommit(
  void * clientData,
  Tcl_Interp *interp,
  int argc,
  char **argv
){
  char zBuf[30];
  sqlite4 *db;
  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
        " DB", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  sprintf(zBuf, "%d", sqlite4_get_autocommit(db));
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}

/*
** Usage:  tcl_variable_type VARIABLENAME
**
................................................................................
*/
int printExplainQueryPlan(sqlite4_stmt *pStmt){
  const char *zSql;               /* Input SQL */
  char *zExplain;                 /* SQL with EXPLAIN QUERY PLAN prepended */
  sqlite4_stmt *pExplain;         /* Compiled EXPLAIN QUERY PLAN command */
  int rc;                         /* Return code from sqlite4_prepare() */

  zSql = sqlite4_sql(pStmt);
  if( zSql==0 ) return SQLITE4_ERROR;

  zExplain = sqlite4_mprintf(0, "EXPLAIN QUERY PLAN %s", zSql);
  if( zExplain==0 ) return SQLITE4_NOMEM;

  rc = sqlite4_prepare(sqlite4_db_handle(pStmt), zExplain, -1, &pExplain, 0);
  sqlite4_free(0, zExplain);
................................................................................
     { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
     { "sqlite4_key",                   (Tcl_CmdProc*)test_key              },
     { "sqlite4_rekey",                 (Tcl_CmdProc*)test_rekey            },
     { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },
     { "sqlite4_interrupt",             (Tcl_CmdProc*)test_interrupt        },
     { "sqlite_delete_function",        (Tcl_CmdProc*)delete_function       },
     { "sqlite_delete_collation",       (Tcl_CmdProc*)delete_collation      },
     { "sqlite4_get_autocommit",        (Tcl_CmdProc*)get_autocommit        },
     { "sqlite4_stack_used",            (Tcl_CmdProc*)test_stack_used       },
     { "printf",                        (Tcl_CmdProc*)test_printf           },
     { "sqlite4IoTrace",                (Tcl_CmdProc*)test_io_trace         },
  };
  static struct {
     char *zName;
     Tcl_ObjCmdProc *xProc;
................................................................................
     { "sqlite4_prepare",               test_prepare       ,0 },
     { "sqlite4_prepare_tkt3134",       test_prepare_tkt3134, 0},
     { "sqlite4_finalize",              test_finalize      ,0 },
     { "sqlite4_stmt_status",           test_stmt_status   ,0 },
     { "sqlite4_reset",                 test_reset         ,0 },
     { "sqlite4_changes",               test_changes       ,0 },
     { "sqlite4_step",                  test_step          ,0 },
     { "sqlite4_sql",                   test_sql           ,0 },
     { "sqlite4_next_stmt",             test_next_stmt     ,0 },
     { "sqlite4_stmt_readonly",         test_stmt_readonly ,0 },
     { "sqlite4_stmt_busy",             test_stmt_busy     ,0 },
     { "uses_stmt_journal",             uses_stmt_journal ,0 },

     { "sqlite4_db_release_memory",     test_db_release_memory,  0},








|













|







 







|

|


|













|







 







|







 







|







 







|







3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
....
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
....
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
....
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
....
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
  rc = sqlite4_step(pStmt);

  /* if( rc!=SQLITE4_DONE && rc!=SQLITE4_ROW ) return TCL_ERROR; */
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  return TCL_OK;
}

static int test_stmt_sql(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite4_stmt *pStmt;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT");
    return TCL_ERROR;
  }

  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  Tcl_SetResult(interp, (char *)sqlite4_stmt_sql(pStmt), TCL_VOLATILE);
  return TCL_OK;
}

/*
** Usage: sqlite4_column_count STMT 
**
** Return the number of columns returned by the sql statement STMT.
................................................................................
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  rc = sqlite4_create_collation(db, argv[2], SQLITE4_UTF8, 0, 0, 0, 0);
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  return TCL_OK;
}

/*
** Usage: sqlite4_db_transaction_status DB
**
** Return true if the database DB currently has an open transaction.
** Return false if not.
*/
static int db_transaction_status(
  void * clientData,
  Tcl_Interp *interp,
  int argc,
  char **argv
){
  char zBuf[30];
  sqlite4 *db;
  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
        " DB", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  sprintf(zBuf, "%d", sqlite4_db_transaction_status(db));
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}

/*
** Usage:  tcl_variable_type VARIABLENAME
**
................................................................................
*/
int printExplainQueryPlan(sqlite4_stmt *pStmt){
  const char *zSql;               /* Input SQL */
  char *zExplain;                 /* SQL with EXPLAIN QUERY PLAN prepended */
  sqlite4_stmt *pExplain;         /* Compiled EXPLAIN QUERY PLAN command */
  int rc;                         /* Return code from sqlite4_prepare() */

  zSql = sqlite4_stmt_sql(pStmt);
  if( zSql==0 ) return SQLITE4_ERROR;

  zExplain = sqlite4_mprintf(0, "EXPLAIN QUERY PLAN %s", zSql);
  if( zExplain==0 ) return SQLITE4_NOMEM;

  rc = sqlite4_prepare(sqlite4_db_handle(pStmt), zExplain, -1, &pExplain, 0);
  sqlite4_free(0, zExplain);
................................................................................
     { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
     { "sqlite4_key",                   (Tcl_CmdProc*)test_key              },
     { "sqlite4_rekey",                 (Tcl_CmdProc*)test_rekey            },
     { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },
     { "sqlite4_interrupt",             (Tcl_CmdProc*)test_interrupt        },
     { "sqlite_delete_function",        (Tcl_CmdProc*)delete_function       },
     { "sqlite_delete_collation",       (Tcl_CmdProc*)delete_collation      },
     { "sqlite4_db_transaction_status", (Tcl_CmdProc*)db_transaction_status },
     { "sqlite4_stack_used",            (Tcl_CmdProc*)test_stack_used       },
     { "printf",                        (Tcl_CmdProc*)test_printf           },
     { "sqlite4IoTrace",                (Tcl_CmdProc*)test_io_trace         },
  };
  static struct {
     char *zName;
     Tcl_ObjCmdProc *xProc;
................................................................................
     { "sqlite4_prepare",               test_prepare       ,0 },
     { "sqlite4_prepare_tkt3134",       test_prepare_tkt3134, 0},
     { "sqlite4_finalize",              test_finalize      ,0 },
     { "sqlite4_stmt_status",           test_stmt_status   ,0 },
     { "sqlite4_reset",                 test_reset         ,0 },
     { "sqlite4_changes",               test_changes       ,0 },
     { "sqlite4_step",                  test_step          ,0 },
     { "sqlite4_stmt_sql",              test_stmt_sql      ,0 },
     { "sqlite4_next_stmt",             test_next_stmt     ,0 },
     { "sqlite4_stmt_readonly",         test_stmt_readonly ,0 },
     { "sqlite4_stmt_busy",             test_stmt_busy     ,0 },
     { "uses_stmt_journal",             uses_stmt_journal ,0 },

     { "sqlite4_db_release_memory",     test_db_release_memory,  0},