/ Check-in [d468101b]
Login

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

Overview
Comment:Merge latest trunk changes into this branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | rowvalue
Files: files | file ages | folders
SHA1:d468101b421e073e9debd7381bde1d36af31369e
User & Date: dan 2016-08-02 16:24:10
Context
2016-08-02
17:07
Fix a problem with vector range constraints and mixed ASC/DESC indexes. check-in: e2ad30c8 user: dan tags: rowvalue
16:24
Merge latest trunk changes into this branch. check-in: d468101b user: dan tags: rowvalue
16:18
Add missing comments and make some code on this branch clearer. check-in: 6937677c user: dan tags: rowvalue
13:26
Updates to requirements marks. No changes to code. check-in: b23c10ac user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/misc/json1.c.

1219
1220
1221
1222
1223
1224
1225

1226
1227
1228
1229
1230
1231
1232
*/
static void jsonQuoteFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString jx;


  jsonInit(&jx, ctx);
  jsonAppendValue(&jx, argv[0]);
  jsonResult(&jx);
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}








>







1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
*/
static void jsonQuoteFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString jx;
  UNUSED_PARAM(argc);

  jsonInit(&jx, ctx);
  jsonAppendValue(&jx, argv[0]);
  jsonResult(&jx);
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}

Changes to src/loadext.c.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
...
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
...
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
  #define SQLITE_CORE 1  /* Disable the API redefinition in sqlite3ext.h */
#endif
#include "sqlite3ext.h"
#include "sqliteInt.h"
#include <string.h>

#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** This is the function signature used for all extension entry points.
*/
typedef int (*sqlite3_loadext_entry)(
  sqlite3 *db,                       /* Handle to the database. */
  char **pzErrMsg,                   /* Used to set error string on failure. */
  const sqlite3_api_routines *pThunk /* Extension API function pointers. */
);

/*
** Some API routines are omitted when various features are
** excluded from a build of SQLite.  Substitute a NULL pointer
** for any missing APIs.
*/
#ifndef SQLITE_ENABLE_COLUMN_METADATA
# define sqlite3_column_database_name   0
................................................................................


/*
** Register a statically linked extension that is automatically
** loaded by every new database connection.
*/
int sqlite3_auto_extension(
  int (*xInit)(sqlite3 *, char **, const sqlite3_api_routines *)
){
  int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_AUTOINIT
  rc = sqlite3_initialize();
  if( rc ){
    return rc;
  }else
................................................................................
    u32 i;
#if SQLITE_THREADSAFE
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
    wsdAutoextInit;
    sqlite3_mutex_enter(mutex);
    for(i=0; i<wsdAutoext.nExt; i++){
      if( wsdAutoext.aExt[i]==(void*)xInit ) break;
    }
    if( i==wsdAutoext.nExt ){
      u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
      void (**aNew)(void);
      aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte);
      if( aNew==0 ){
        rc = SQLITE_NOMEM_BKPT;
      }else{
        wsdAutoext.aExt = aNew;
        wsdAutoext.aExt[wsdAutoext.nExt] = (void*)xInit;
        wsdAutoext.nExt++;
      }
    }
    sqlite3_mutex_leave(mutex);
    assert( (rc&0xff)==rc );
    return rc;
  }
................................................................................
** is currently on the list.  If xInit is not on the list, then this
** routine is a no-op.
**
** Return 1 if xInit was found on the list and removed.  Return 0 if xInit
** was not on the list.
*/
int sqlite3_cancel_auto_extension(
  int (*xInit)(sqlite3 *, char **, const sqlite3_api_routines *)
){
#if SQLITE_THREADSAFE
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  int i;
  int n = 0;
  wsdAutoextInit;
  sqlite3_mutex_enter(mutex);
  for(i=(int)wsdAutoext.nExt-1; i>=0; i--){
    if( wsdAutoext.aExt[i]==(void*)xInit ){
      wsdAutoext.nExt--;
      wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
      n++;
      break;
    }
  }
  sqlite3_mutex_leave(mutex);







<
<
<
<
<
<
<
<
<







 







|







 







|









|







 







|









|







17
18
19
20
21
22
23









24
25
26
27
28
29
30
...
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
...
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
  #define SQLITE_CORE 1  /* Disable the API redefinition in sqlite3ext.h */
#endif
#include "sqlite3ext.h"
#include "sqliteInt.h"
#include <string.h>

#ifndef SQLITE_OMIT_LOAD_EXTENSION









/*
** Some API routines are omitted when various features are
** excluded from a build of SQLite.  Substitute a NULL pointer
** for any missing APIs.
*/
#ifndef SQLITE_ENABLE_COLUMN_METADATA
# define sqlite3_column_database_name   0
................................................................................


/*
** Register a statically linked extension that is automatically
** loaded by every new database connection.
*/
int sqlite3_auto_extension(
  void (*xInit)(void)
){
  int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_AUTOINIT
  rc = sqlite3_initialize();
  if( rc ){
    return rc;
  }else
................................................................................
    u32 i;
#if SQLITE_THREADSAFE
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
    wsdAutoextInit;
    sqlite3_mutex_enter(mutex);
    for(i=0; i<wsdAutoext.nExt; i++){
      if( wsdAutoext.aExt[i]==xInit ) break;
    }
    if( i==wsdAutoext.nExt ){
      u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
      void (**aNew)(void);
      aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte);
      if( aNew==0 ){
        rc = SQLITE_NOMEM_BKPT;
      }else{
        wsdAutoext.aExt = aNew;
        wsdAutoext.aExt[wsdAutoext.nExt] = xInit;
        wsdAutoext.nExt++;
      }
    }
    sqlite3_mutex_leave(mutex);
    assert( (rc&0xff)==rc );
    return rc;
  }
................................................................................
** is currently on the list.  If xInit is not on the list, then this
** routine is a no-op.
**
** Return 1 if xInit was found on the list and removed.  Return 0 if xInit
** was not on the list.
*/
int sqlite3_cancel_auto_extension(
  void (*xInit)(void)
){
#if SQLITE_THREADSAFE
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  int i;
  int n = 0;
  wsdAutoextInit;
  sqlite3_mutex_enter(mutex);
  for(i=(int)wsdAutoext.nExt-1; i>=0; i--){
    if( wsdAutoext.aExt[i]==xInit ){
      wsdAutoext.nExt--;
      wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
      n++;
      break;
    }
  }
  sqlite3_mutex_leave(mutex);

Changes to src/shell.c.

2546
2547
2548
2549
2550
2551
2552


2553
2554
2555
2556
2557
2558
2559
static int sql_trace_callback(
  unsigned mType,
  void *pArg,
  void *pP,
  void *pX
){
  FILE *f = (FILE*)pArg;


  if( f ){
    const char *z = (const char*)pX;
    int i = (int)strlen(z);
    while( i>0 && z[i-1]==';' ){ i--; }
    utf8_printf(f, "%.*s;\n", i, z);
  }
  return 0;







>
>







2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
static int sql_trace_callback(
  unsigned mType,
  void *pArg,
  void *pP,
  void *pX
){
  FILE *f = (FILE*)pArg;
  UNUSED_PARAMETER(mType);
  UNUSED_PARAMETER(pP);
  if( f ){
    const char *z = (const char*)pX;
    int i = (int)strlen(z);
    while( i>0 && z[i-1]==';' ){ i--; }
    utf8_printf(f, "%.*s;\n", i, z);
  }
  return 0;

Changes to src/sqlite.h.in.

1041
1042
1043
1044
1045
1046
1047










1048
1049
1050
1051
1052
1053
1054
....
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
....
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700

4701
4702
4703
4704
4705
4706
4707
4708
4709
....
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
....
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
....
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
** at the internal representation of an [sqlite3_mutex].  It only
** deals with pointers to the [sqlite3_mutex] object.
**
** Mutexes are created using [sqlite3_mutex_alloc()].
*/
typedef struct sqlite3_mutex sqlite3_mutex;











/*
** CAPI3REF: OS Interface Object
**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system.  The "vfs"
** in the name of the object stands for "virtual file system".  See
** the [VFS | VFS documentation] for further information.
................................................................................
** database connection that invoked the busy handler.  In other words,
** the busy handler is not reentrant.  Any such actions
** result in undefined behavior.
** 
** A busy handler must not close the database connection
** or [prepared statement] that invoked the busy handler.
*/
int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);

/*
** CAPI3REF: Set A Busy Timeout
** METHOD: sqlite3
**
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
** for a specified amount of time when a table is locked.  ^The handler
................................................................................
** calls to sqlite3_get_auxdata(C,N) return P from the most recent
** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
** NULL if the metadata has been discarded.
** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
** SQLite will invoke the destructor function X with parameter P exactly
** once, when the metadata is discarded.
** SQLite is free to discard the metadata at any time, including: <ul>
** <li> when the corresponding function parameter changes, or
** <li> when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
**      SQL statement, or
** <li> when sqlite3_set_auxdata() is invoked again on the same parameter, or

** <li> during the original sqlite3_set_auxdata() call when a memory 
**      allocation error occurs. </ul>)^
**
** Note the last bullet in particular.  The destructor X in 
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
** sqlite3_set_auxdata() interface even returns.  Hence sqlite3_set_auxdata()
** should be called near the end of the function implementation and the
** function implementation should not make any use of P after
** sqlite3_set_auxdata() has been called.
................................................................................
** ^Extension loading is off by default.
** ^Call the sqlite3_enable_load_extension() routine with onoff==1
** to turn extension loading on and call it with onoff==0 to turn
** it back off again.
**
** ^This interface enables or disables both the C-API
** [sqlite3_load_extension()] and the SQL function [load_extension()].
** Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..)
** to enable or disable only the C-API.
**
** <b>Security warning:</b> It is recommended that extension loading
** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
** rather than this interface, so the [load_extension()] SQL function
** remains disabled. This will prevent SQL injections from giving attackers
** access to extension loading capabilities.
*/
................................................................................
** ^This interface causes the xEntryPoint() function to be invoked for
** each new [database connection] that is created.  The idea here is that
** xEntryPoint() is the entry point for a statically linked [SQLite extension]
** that is to be automatically loaded into all new database connections.
**
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects and integer result as if the signature of the
** entry point where as follows:
**
** <blockquote><pre>
** &nbsp;  int xEntryPoint(
** &nbsp;    sqlite3 *db,
** &nbsp;    const char **pzErrMsg,
** &nbsp;    const struct sqlite3_api_routines *pThunk
................................................................................
** ^Calling sqlite3_auto_extension(X) with an entry point X that is already
** on the list of automatic extensions is a harmless no-op. ^No entry point
** will be called more than once for each database connection that is opened.
**
** See also: [sqlite3_reset_auto_extension()]
** and [sqlite3_cancel_auto_extension()]
*/
typedef struct sqlite3_api_routines sqlite3_api_routines;
int sqlite3_auto_extension(
  int (*xEntryPoint)(sqlite3 *, char **, const sqlite3_api_routines *)
);

/*
** CAPI3REF: Cancel Automatic Extension Loading
**
** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
** initialization routine X that was registered using a prior call to
** [sqlite3_auto_extension(X)].  ^The [sqlite3_cancel_auto_extension(X)]
** routine returns 1 if initialization routine X was successfully 
** unregistered and it returns 0 if X was not on the list of initialization
** routines.
*/
int sqlite3_cancel_auto_extension(
  int (*xEntryPoint)(sqlite3 *, char **, const sqlite3_api_routines *)
);

/*
** CAPI3REF: Reset Automatic Extension Loading
**
** ^This interface disables all automatic extensions previously
** registered using [sqlite3_auto_extension()].
*/







>
>
>
>
>
>
>
>
>
>







 







|







 







|
|
|
|
>
|
|







 







|
|







 







|







 







<
|
<
<











|
<
<







1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
....
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
....
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
....
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
....
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
....
5714
5715
5716
5717
5718
5719
5720

5721


5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733


5734
5735
5736
5737
5738
5739
5740
** at the internal representation of an [sqlite3_mutex].  It only
** deals with pointers to the [sqlite3_mutex] object.
**
** Mutexes are created using [sqlite3_mutex_alloc()].
*/
typedef struct sqlite3_mutex sqlite3_mutex;

/*
** CAPI3REF: Loadable Extension Thunk
**
** A pointer to the opaque sqlite3_api_routines structure is passed as
** the third parameter to entry points of [loadable extensions].  This
** structure must be typedefed in order to work around compiler warnings
** on some platforms.
*/
typedef struct sqlite3_api_routines sqlite3_api_routines;

/*
** CAPI3REF: OS Interface Object
**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system.  The "vfs"
** in the name of the object stands for "virtual file system".  See
** the [VFS | VFS documentation] for further information.
................................................................................
** database connection that invoked the busy handler.  In other words,
** the busy handler is not reentrant.  Any such actions
** result in undefined behavior.
** 
** A busy handler must not close the database connection
** or [prepared statement] that invoked the busy handler.
*/
int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);

/*
** CAPI3REF: Set A Busy Timeout
** METHOD: sqlite3
**
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
** for a specified amount of time when a table is locked.  ^The handler
................................................................................
** calls to sqlite3_get_auxdata(C,N) return P from the most recent
** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
** NULL if the metadata has been discarded.
** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
** SQLite will invoke the destructor function X with parameter P exactly
** once, when the metadata is discarded.
** SQLite is free to discard the metadata at any time, including: <ul>
** <li> ^(when the corresponding function parameter changes)^, or
** <li> ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
**      SQL statement)^, or
** <li> ^(when sqlite3_set_auxdata() is invoked again on the same
**       parameter)^, or
** <li> ^(during the original sqlite3_set_auxdata() call when a memory 
**      allocation error occurs.)^ </ul>
**
** Note the last bullet in particular.  The destructor X in 
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
** sqlite3_set_auxdata() interface even returns.  Hence sqlite3_set_auxdata()
** should be called near the end of the function implementation and the
** function implementation should not make any use of P after
** sqlite3_set_auxdata() has been called.
................................................................................
** ^Extension loading is off by default.
** ^Call the sqlite3_enable_load_extension() routine with onoff==1
** to turn extension loading on and call it with onoff==0 to turn
** it back off again.
**
** ^This interface enables or disables both the C-API
** [sqlite3_load_extension()] and the SQL function [load_extension()].
** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..)
** to enable or disable only the C-API.)^
**
** <b>Security warning:</b> It is recommended that extension loading
** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
** rather than this interface, so the [load_extension()] SQL function
** remains disabled. This will prevent SQL injections from giving attackers
** access to extension loading capabilities.
*/
................................................................................
** ^This interface causes the xEntryPoint() function to be invoked for
** each new [database connection] that is created.  The idea here is that
** xEntryPoint() is the entry point for a statically linked [SQLite extension]
** that is to be automatically loaded into all new database connections.
**
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects an integer result as if the signature of the
** entry point where as follows:
**
** <blockquote><pre>
** &nbsp;  int xEntryPoint(
** &nbsp;    sqlite3 *db,
** &nbsp;    const char **pzErrMsg,
** &nbsp;    const struct sqlite3_api_routines *pThunk
................................................................................
** ^Calling sqlite3_auto_extension(X) with an entry point X that is already
** on the list of automatic extensions is a harmless no-op. ^No entry point
** will be called more than once for each database connection that is opened.
**
** See also: [sqlite3_reset_auto_extension()]
** and [sqlite3_cancel_auto_extension()]
*/

int sqlite3_auto_extension(void(*xEntryPoint)(void));



/*
** CAPI3REF: Cancel Automatic Extension Loading
**
** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
** initialization routine X that was registered using a prior call to
** [sqlite3_auto_extension(X)].  ^The [sqlite3_cancel_auto_extension(X)]
** routine returns 1 if initialization routine X was successfully 
** unregistered and it returns 0 if X was not on the list of initialization
** routines.
*/
int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void));



/*
** CAPI3REF: Reset Automatic Extension Loading
**
** ^This interface disables all automatic extensions previously
** registered using [sqlite3_auto_extension()].
*/

Changes to src/sqlite3ext.h.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
** as extensions by SQLite should #include this file instead of 
** sqlite3.h.
*/
#ifndef SQLITE3EXT_H
#define SQLITE3EXT_H
#include "sqlite3.h"

typedef struct sqlite3_api_routines sqlite3_api_routines;

/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING:  In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only.  If you insert new
** interfaces in the middle of this structure, then older different
................................................................................
  int (*stricmp)(const char*,const char*);
  int (*uri_boolean)(const char*,const char*,int);
  sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
  const char *(*uri_parameter)(const char*,const char*);
  char *(*vsnprintf)(int,char*,const char*,va_list);
  int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
  /* Version 3.8.7 and later */
  int (*auto_extension)(int(*)(sqlite3*,char**,const sqlite3_api_routines*));
  int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
                     void(*)(void*));
  int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
                      void(*)(void*),unsigned char);
  int (*cancel_auto_extension)(int(*)(sqlite3*,char**,
                                       const sqlite3_api_routines*));
  int (*load_extension)(sqlite3*,const char*,const char*,char**);
  void *(*malloc64)(sqlite3_uint64);
  sqlite3_uint64 (*msize)(void*);
  void *(*realloc64)(void*,sqlite3_uint64);
  void (*reset_auto_extension)(void);
  void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
                        void(*)(void*));







<
<







 







|




|
<







15
16
17
18
19
20
21


22
23
24
25
26
27
28
...
245
246
247
248
249
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
** as extensions by SQLite should #include this file instead of 
** sqlite3.h.
*/
#ifndef SQLITE3EXT_H
#define SQLITE3EXT_H
#include "sqlite3.h"



/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING:  In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only.  If you insert new
** interfaces in the middle of this structure, then older different
................................................................................
  int (*stricmp)(const char*,const char*);
  int (*uri_boolean)(const char*,const char*,int);
  sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
  const char *(*uri_parameter)(const char*,const char*);
  char *(*vsnprintf)(int,char*,const char*,va_list);
  int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
  /* Version 3.8.7 and later */
  int (*auto_extension)(void(*)(void));
  int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
                     void(*)(void*));
  int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
                      void(*)(void*),unsigned char);
  int (*cancel_auto_extension)(void(*)(void));

  int (*load_extension)(sqlite3*,const char*,const char*,char**);
  void *(*malloc64)(sqlite3_uint64);
  sqlite3_uint64 (*msize)(void*);
  void *(*realloc64)(void*,sqlite3_uint64);
  void (*reset_auto_extension)(void);
  void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
                        void(*)(void*));

Changes to src/status.c.

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
    wsdStat.mxValue[op] = wsdStat.nowValue[op];
  }
  sqlite3_mutex_leave(pMutex);
  (void)pMutex;  /* Prevent warning when SQLITE_THREADSAFE=0 */
  return SQLITE_OK;
}
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
  sqlite3_int64 iCur, iHwtr;
  int rc;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
#endif
  rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
  if( rc==0 ){
    *pCurrent = (int)iCur;







|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
    wsdStat.mxValue[op] = wsdStat.nowValue[op];
  }
  sqlite3_mutex_leave(pMutex);
  (void)pMutex;  /* Prevent warning when SQLITE_THREADSAFE=0 */
  return SQLITE_OK;
}
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
  sqlite3_int64 iCur = 0, iHwtr = 0;
  int rc;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
#endif
  rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
  if( rc==0 ){
    *pCurrent = (int)iCur;

Changes to src/test1.c.

6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
    }
    return TCL_ERROR;
  }
  sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
  return TCL_OK;
}

typedef struct sqlite3_api_routines sqlite3_api_routines;
/*
**     load_static_extension DB NAME ...
**
** Load one or more statically linked extensions.
*/
static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
  void * clientData,







<







6738
6739
6740
6741
6742
6743
6744

6745
6746
6747
6748
6749
6750
6751
    }
    return TCL_ERROR;
  }
  sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
  return TCL_OK;
}


/*
**     load_static_extension DB NAME ...
**
** Load one or more statically linked extensions.
*/
static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
  void * clientData,

Changes to src/test_autoext.c.

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
*/
static int SQLITE_TCLAPI autoExtSqrObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_auto_extension(sqr_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_cancel_auto_extension_sqr
**
................................................................................
*/
static int SQLITE_TCLAPI cancelAutoExtSqrObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_cancel_auto_extension(sqr_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_auto_extension_cube
**
................................................................................
*/
static int SQLITE_TCLAPI autoExtCubeObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_auto_extension(cube_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_cancel_auto_extension_cube
**
................................................................................
*/
static int SQLITE_TCLAPI cancelAutoExtCubeObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_cancel_auto_extension(cube_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_auto_extension_broken
**
................................................................................
*/
static int SQLITE_TCLAPI autoExtBrokenObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_auto_extension(broken_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_cancel_auto_extension_broken
**
................................................................................
*/
static int SQLITE_TCLAPI cancelAutoExtBrokenObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_cancel_auto_extension(broken_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

#endif /* SQLITE_OMIT_LOAD_EXTENSION */









|







 







|







 







|







 







|







 







|







 







|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
*/
static int SQLITE_TCLAPI autoExtSqrObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_auto_extension((void(*)(void))sqr_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_cancel_auto_extension_sqr
**
................................................................................
*/
static int SQLITE_TCLAPI cancelAutoExtSqrObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_cancel_auto_extension((void(*)(void))sqr_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_auto_extension_cube
**
................................................................................
*/
static int SQLITE_TCLAPI autoExtCubeObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_auto_extension((void(*)(void))cube_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_cancel_auto_extension_cube
**
................................................................................
*/
static int SQLITE_TCLAPI cancelAutoExtCubeObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_cancel_auto_extension((void(*)(void))cube_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_auto_extension_broken
**
................................................................................
*/
static int SQLITE_TCLAPI autoExtBrokenObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_auto_extension((void(*)(void))broken_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

/*
** tclcmd:   sqlite3_cancel_auto_extension_broken
**
................................................................................
*/
static int SQLITE_TCLAPI cancelAutoExtBrokenObjCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc = sqlite3_cancel_auto_extension((void(*)(void))broken_init);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return SQLITE_OK;
}

#endif /* SQLITE_OMIT_LOAD_EXTENSION */


Changes to src/test_func.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
...
786
787
788
789
790
791
792

793
794
795
796
797
798
799
...
805
806
807
808
809
810
811
812
813
814
815
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "sqliteInt.h"
#include "vdbeInt.h"


/*
** Allocate nByte bytes of space using sqlite3_malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
** the database handle that malloc() has failed.
*/
static void *testContextMalloc(sqlite3_context *context, int nByte){
  char *z = sqlite3_malloc(nByte);
................................................................................
static int SQLITE_TCLAPI autoinstall_test_funcs(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  extern int Md5_Register(sqlite3 *, char **, const sqlite3_api_routines *);
  int rc = sqlite3_auto_extension(registerTestFunctions);
  if( rc==SQLITE_OK ){
    rc = sqlite3_auto_extension(Md5_Register);
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return TCL_OK;
}

/*
** A bogus step function and finalizer function.
................................................................................
  return TCL_OK;

abuse_err:
  Tcl_AppendResult(interp, "sqlite3_create_function abused test failed", 
                   (char*)0);
  return TCL_ERROR;
}


/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest_func_Init(Tcl_Interp *interp){
  static struct {
     char *zName;
................................................................................
  int i;
  extern int Md5_Register(sqlite3 *, char **, const sqlite3_api_routines *);

  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
  }
  sqlite3_initialize();
  sqlite3_auto_extension(registerTestFunctions);
  sqlite3_auto_extension(Md5_Register);
  return TCL_OK;
}







<







 







|

|







 







>







 







|
|


21
22
23
24
25
26
27

28
29
30
31
32
33
34
...
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
...
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
...
805
806
807
808
809
810
811
812
813
814
815
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "sqliteInt.h"
#include "vdbeInt.h"


/*
** Allocate nByte bytes of space using sqlite3_malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
** the database handle that malloc() has failed.
*/
static void *testContextMalloc(sqlite3_context *context, int nByte){
  char *z = sqlite3_malloc(nByte);
................................................................................
static int SQLITE_TCLAPI autoinstall_test_funcs(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  extern int Md5_Register(sqlite3 *, char **, const sqlite3_api_routines *);
  int rc = sqlite3_auto_extension((void(*)(void))registerTestFunctions);
  if( rc==SQLITE_OK ){
    rc = sqlite3_auto_extension((void(*)(void))Md5_Register);
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return TCL_OK;
}

/*
** A bogus step function and finalizer function.
................................................................................
  return TCL_OK;

abuse_err:
  Tcl_AppendResult(interp, "sqlite3_create_function abused test failed", 
                   (char*)0);
  return TCL_ERROR;
}


/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest_func_Init(Tcl_Interp *interp){
  static struct {
     char *zName;
................................................................................
  int i;
  extern int Md5_Register(sqlite3 *, char **, const sqlite3_api_routines *);

  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
  }
  sqlite3_initialize();
  sqlite3_auto_extension((void(*)(void))registerTestFunctions);
  sqlite3_auto_extension((void(*)(void))Md5_Register);
  return TCL_OK;
}

Changes to src/test_multiplex.c.

1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
  gMultiplex.sIoMethodsV2.iVersion = 2;
  gMultiplex.sIoMethodsV2.xShmMap = multiplexShmMap;
  gMultiplex.sIoMethodsV2.xShmLock = multiplexShmLock;
  gMultiplex.sIoMethodsV2.xShmBarrier = multiplexShmBarrier;
  gMultiplex.sIoMethodsV2.xShmUnmap = multiplexShmUnmap;
  sqlite3_vfs_register(&gMultiplex.sThisVfs, makeDefault);

  sqlite3_auto_extension(multiplexFuncInit);

  return SQLITE_OK;
}

/*
** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown()
**







|







1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
  gMultiplex.sIoMethodsV2.iVersion = 2;
  gMultiplex.sIoMethodsV2.xShmMap = multiplexShmMap;
  gMultiplex.sIoMethodsV2.xShmLock = multiplexShmLock;
  gMultiplex.sIoMethodsV2.xShmBarrier = multiplexShmBarrier;
  gMultiplex.sIoMethodsV2.xShmUnmap = multiplexShmUnmap;
  sqlite3_vfs_register(&gMultiplex.sThisVfs, makeDefault);

  sqlite3_auto_extension((void(*)(void))multiplexFuncInit);

  return SQLITE_OK;
}

/*
** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown()
**

Changes to src/test_thread.c.

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
  Tcl_Obj *CONST objv[]
){
  int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p);

  const char *zFilename;
  sqlite3 *db;
  char zBuf[100];
  extern int Md5_Register(sqlite3 *, char **, const sqlite3_api_routines *);

  UNUSED_PARAMETER(clientData);
  UNUSED_PARAMETER(objc);

  zFilename = Tcl_GetString(objv[2]);
  sqlite3_open(zFilename, &db);
#ifdef SQLITE_HAS_CODEC







|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
  Tcl_Obj *CONST objv[]
){
  int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p);

  const char *zFilename;
  sqlite3 *db;
  char zBuf[100];
  extern int Md5_Register(sqlite3*,char**,const sqlite3_api_routines*);

  UNUSED_PARAMETER(clientData);
  UNUSED_PARAMETER(objc);

  zFilename = Tcl_GetString(objv[2]);
  sqlite3_open(zFilename, &db);
#ifdef SQLITE_HAS_CODEC

Changes to src/vtab.c.

943
944
945
946
947
948
949
950



951
952
953
954
955
956
957
    ** sqlite3.aVTrans[] array. */
    rc = growVTrans(db);
    if( rc==SQLITE_OK ){
      rc = pModule->xBegin(pVTab->pVtab);
      if( rc==SQLITE_OK ){
        int iSvpt = db->nStatement + db->nSavepoint;
        addToVTrans(db, pVTab);
        if( iSvpt ) rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, iSvpt-1);



      }
    }
  }
  return rc;
}

/*







|
>
>
>







943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
    ** sqlite3.aVTrans[] array. */
    rc = growVTrans(db);
    if( rc==SQLITE_OK ){
      rc = pModule->xBegin(pVTab->pVtab);
      if( rc==SQLITE_OK ){
        int iSvpt = db->nStatement + db->nSavepoint;
        addToVTrans(db, pVTab);
        if( iSvpt && pModule->xSavepoint ){
          pVTab->iSavepoint = iSvpt;
          rc = pModule->xSavepoint(pVTab->pVtab, iSvpt-1);
        }
      }
    }
  }
  return rc;
}

/*

Changes to src/where.c.

2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
          ** doing table lookups.  The cost will be 3x the number of
          ** lookups.  Take into account WHERE clause terms that can be
          ** satisfied using just the index, and that do not require a
          ** table lookup. */
          LogEst nLookup = rSize + 16;  /* Base cost:  N*3 */
          int ii;
          int iCur = pSrc->iCursor;
          WhereClause *pWC = &pWInfo->sWC;
          for(ii=0; ii<pWC->nTerm; ii++){
            WhereTerm *pTerm = &pWC->a[ii];
            if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){
              break;
            }
            /* pTerm can be evaluated using just the index.  So reduce
            ** the expected number of table lookups accordingly */
            if( pTerm->truthProb<=0 ){
              nLookup += pTerm->truthProb;







|
|
|







2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
          ** doing table lookups.  The cost will be 3x the number of
          ** lookups.  Take into account WHERE clause terms that can be
          ** satisfied using just the index, and that do not require a
          ** table lookup. */
          LogEst nLookup = rSize + 16;  /* Base cost:  N*3 */
          int ii;
          int iCur = pSrc->iCursor;
          WhereClause *pWC2 = &pWInfo->sWC;
          for(ii=0; ii<pWC2->nTerm; ii++){
            WhereTerm *pTerm = &pWC2->a[ii];
            if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){
              break;
            }
            /* pTerm can be evaluated using just the index.  So reduce
            ** the expected number of table lookups accordingly */
            if( pTerm->truthProb<=0 ){
              nLookup += pTerm->truthProb;

Changes to test/fts3conf.test.

206
207
208
209
210
211
212
213






































214
    ROLLBACK TO abc;
  COMMIT;
}
do_execsql_test 4.2.2 {
  SELECT * FROM t01 WHERE t01 MATCH 'b';
  INSERT INTO t01(t01) VALUES('integrity-check');
} {}







































finish_test








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

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
    ROLLBACK TO abc;
  COMMIT;
}
do_execsql_test 4.2.2 {
  SELECT * FROM t01 WHERE t01 MATCH 'b';
  INSERT INTO t01(t01) VALUES('integrity-check');
} {}

do_execsql_test 4.3.1 {
  CREATE VIRTUAL TABLE t02 USING fts4;
  INSERT INTO t01 VALUES('1 1 1');
  INSERT INTO t02 VALUES('2 2 2');
  BEGIN;
    SAVEPOINT abc;
      INSERT INTO t01 VALUES('a b c');
      INSERT INTO t02 VALUES('a b c');
    ROLLBACK TO abc;
  COMMIT;
}
do_execsql_test 4.3.2 {
  SELECT * FROM t01 WHERE t01 MATCH 'b';
  INSERT INTO t01(t01) VALUES('integrity-check');
} {}

do_execsql_test 4.4.1 {
  CREATE TABLE A(ID INTEGER PRIMARY KEY, AnotherID INTEGER, Notes TEXT);
  CREATE VIRTUAL TABLE AFTS USING FTS4 (Notes);
  CREATE TRIGGER A_DeleteTrigger AFTER DELETE ON A FOR EACH ROW BEGIN 
    DELETE FROM AFTS WHERE rowid=OLD.ID; 
  END;
  CREATE TABLE B(ID INTEGER PRIMARY KEY,Notes TEXT);
  CREATE VIRTUAL TABLE BFTS USING FTS3 (Notes);
  CREATE TRIGGER B_DeleteTrigger AFTER DELETE ON B FOR EACH ROW BEGIN 
    DELETE FROM BFTS WHERE rowid=OLD.ID; 
  END;
}
		
do_execsql_test 4.4.2 {
  BEGIN TRANSACTION;
    DELETE FROM A WHERE AnotherID=1;
    DELETE FROM B WHERE ID=1;
  COMMIT;
}
		


finish_test

Changes to test/loadext.test.

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# test file.
#
if {![file exists $testextension]} {
  set srcdir [file dir $testdir]/src
  set testextsrc $srcdir/test_loadext.c

  set cmdline [concat exec gcc $gcc_shared]
  lappend cmdline -Wall -I$srcdir -I. -g $testextsrc -o $testextension
  
  if {[catch $cmdline msg]} {
    puts "Skipping loadext tests: Test extension not built..."
    puts $msg
    finish_test
    return
  }







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# test file.
#
if {![file exists $testextension]} {
  set srcdir [file dir $testdir]/src
  set testextsrc $srcdir/test_loadext.c

  set cmdline [concat exec gcc $gcc_shared]
  lappend cmdline -Wall -I$srcdir -I. -I.. -g $testextsrc -o $testextension
  
  if {[catch $cmdline msg]} {
    puts "Skipping loadext tests: Test extension not built..."
    puts $msg
    finish_test
    return
  }

Changes to test/releasetest.tcl.

53
54
55
56
57
58
59




60
61
62
63
64
65
66
...
294
295
296
297
298
299
300

301
302
303
304

305
306
307
308
309
310
311
...
721
722
723
724
725
726
727



728
729
730
731
732
733
734
    --disable-amalgamation --disable-shared
    --enable-session
  }
  "Sanitize" {
    CC=clang -fsanitize=undefined
    -DSQLITE_ENABLE_STAT4
    --enable-session




  }
  "Have-Not" {
    # The "Have-Not" configuration sets all possible -UHAVE_feature options
    # in order to verify that the code works even on platforms that lack
    # these support services.
    -DHAVE_FDATASYNC=0
    -DHAVE_GMTIME_R=0
................................................................................
  }
  Darwin-x86_64 {
    "Locking-Style"           "mptest test"
    "Have-Not"                test
    "Apple"                   "threadtest fulltest"
  }
  "Windows NT-intel" {

    "Have-Not"                test
    "Default"                 "mptest fulltestonly"
  }
  "Windows NT-amd64" {

    "Have-Not"                test
    "Default"                 "mptest fulltestonly"
  }

  # The Failure-Detection platform runs various tests that deliberately
  # fail.  This is used as a test of this script to verify that this script
  # correctly identifies failures.
................................................................................
#
proc makeCommand { targets makeOpts cflags opts } {
  set result [list trace_cmd exec]
  if {$::MSVC} {
    set nmakeDir [file nativename $::SRCDIR]
    set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]]
    lappend result nmake /f $nmakeFile TOP=$nmakeDir



  } else {
    lappend result make
  }
  foreach makeOpt $makeOpts {
    lappend result $makeOpt
  }
  lappend result clean







>
>
>
>







 







>




>







 







>
>
>







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
    --disable-amalgamation --disable-shared
    --enable-session
  }
  "Sanitize" {
    CC=clang -fsanitize=undefined
    -DSQLITE_ENABLE_STAT4
    --enable-session
  }
  "Stdcall" {
    -DUSE_STDCALL=1
    -O2
  }
  "Have-Not" {
    # The "Have-Not" configuration sets all possible -UHAVE_feature options
    # in order to verify that the code works even on platforms that lack
    # these support services.
    -DHAVE_FDATASYNC=0
    -DHAVE_GMTIME_R=0
................................................................................
  }
  Darwin-x86_64 {
    "Locking-Style"           "mptest test"
    "Have-Not"                test
    "Apple"                   "threadtest fulltest"
  }
  "Windows NT-intel" {
    "Stdcall"                 test
    "Have-Not"                test
    "Default"                 "mptest fulltestonly"
  }
  "Windows NT-amd64" {
    "Stdcall"                 test
    "Have-Not"                test
    "Default"                 "mptest fulltestonly"
  }

  # The Failure-Detection platform runs various tests that deliberately
  # fail.  This is used as a test of this script to verify that this script
  # correctly identifies failures.
................................................................................
#
proc makeCommand { targets makeOpts cflags opts } {
  set result [list trace_cmd exec]
  if {$::MSVC} {
    set nmakeDir [file nativename $::SRCDIR]
    set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]]
    lappend result nmake /f $nmakeFile TOP=$nmakeDir
    if {[regexp {USE_STDCALL=1} $cflags]} {
      lappend result USE_STDCALL=1
    }
  } else {
    lappend result make
  }
  foreach makeOpt $makeOpts {
    lappend result $makeOpt
  }
  lappend result clean

Added test/time-wordcount.sh.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/sh
#
# This script runs the wordcount program in different ways and generates
# an output useful for performance comparisons.
#

# Select the source text to be analyzed.
#
if test "x$1" = "x";
then echo "Usage: $0 FILENAME [ARGS...]"; exit 1;
fi

# Do test runs
#
rm -f wcdb1.db
./wordcount --tag A: --timer --summary wcdb1.db $* --insert
rm -f wcdb2.db
./wordcount --tag B: --timer --summary wcdb2.db $* --insert --without-rowid
rm -f wcdb1.db
./wordcount --tag C: --timer --summary wcdb1.db $* --replace
rm -f wcdb2.db
./wordcount --tag D: --timer --summary wcdb2.db $* --replace --without-rowid
rm -f wcdb1.db
./wordcount --tag E: --timer --summary wcdb1.db $* --select
rm -f wcdb2.db
./wordcount --tag F: --timer --summary wcdb2.db $* --select --without-rowid
./wordcount --tag G: --timer --summary wcdb1.db $* --query
./wordcount --tag H: --timer --summary wcdb1.db $* --query --without-rowid
./wordcount --tag I: --timer --summary wcdb1.db $* --delete
./wordcount --tag J: --timer --summary wcdb2.db $* --delete --without-rowid

# Clean up temporary files created.
#
rm -f wcdb1.db wcdb2.db

Changes to test/wordcount.c.

26
27
28
29
30
31
32

33
34
35
36
37
38
39
..
78
79
80
81
82
83
84



85
86
87
88
89
90
91
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
216
217
218
219
220
221
222

223
224
225
226
227
228
229
...
262
263
264
265
266
267
268



269
270
271
272
273
274
275
...
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
**     --stats              Show sqlite3_status() results at the end.
**     --pagesize NNN       Use a page size of NNN
**     --cachesize NNN      Use a cache size of NNN
**     --commit NNN         Commit after every NNN operations
**     --nosync             Use PRAGMA synchronous=OFF
**     --journal MMMM       Use PRAGMA journal_mode=MMMM
**     --timer              Time the operation of this program

**
** Modes:
**
** Insert mode means:
**    (1) INSERT OR IGNORE INTO wordcount VALUES($new,1)
**    (2) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new -- if (1) is a noop
**
................................................................................
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include "sqlite3.h"
#define ISALPHA(X) isalpha((unsigned char)(X))




/* Return the current wall-clock time */
static sqlite3_int64 realTime(void){
  static sqlite3_vfs *clockVfs = 0;
  sqlite3_int64 t;
  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
  if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
    clockVfs->xCurrentTimeInt64(clockVfs, &t);
................................................................................
  printf("%s;\n", zSql);
}

/* An sqlite3_exec() callback that prints results on standard output,
** each column separated by a single space. */
static int printResult(void *NotUsed, int nArg, char **azArg, char **azNm){
  int i;
  printf("--");
  for(i=0; i<nArg; i++){
    printf(" %s", azArg[i] ? azArg[i] : "(null)");
  }
  printf("\n");
  return 0;
}

................................................................................
  sqlite3_stmt *pInsert = 0;    /* The INSERT statement */
  sqlite3_stmt *pUpdate = 0;    /* The UPDATE statement */
  sqlite3_stmt *pSelect = 0;    /* The SELECT statement */
  sqlite3_stmt *pDelete = 0;    /* The DELETE statement */
  FILE *in;                     /* The open input file */
  int rc;                       /* Return code from an SQLite interface */
  int iCur, iHiwtr;             /* Statistics values, current and "highwater" */

  sqlite3_int64 sumCnt = 0;     /* Sum in QUERY mode */
  sqlite3_int64 startTime;
  char zInput[2000];            /* A single line of input */

  /* Process command-line arguments */
  for(i=1; i<argc; i++){
    const char *z = argv[i];
................................................................................
        i++;
        pageSize = atoi(argv[i]);
      }else if( strcmp(z,"commit")==0 && i<argc-1 ){
        i++;
        commitInterval = atoi(argv[i]);
      }else if( strcmp(z,"journal")==0 && i<argc-1 ){
        zJMode = argv[++i];



      }else{
        fatal_error("unknown option: %s\n", argv[i]);
      }
    }else if( zDbName==0 ){
      zDbName = argv[i];
    }else if( zFileToRead==0 ){
      zFileToRead = argv[i];
................................................................................
  if( zFileToRead ) fclose(in);
  sqlite3_finalize(pInsert);
  sqlite3_finalize(pUpdate);
  sqlite3_finalize(pSelect);
  sqlite3_finalize(pDelete);

  if( iMode==MODE_QUERY ){
    printf("sum of cnt: %lld\n", sumCnt);
    rc = sqlite3_prepare_v2(db,"SELECT sum(cnt*cnt) FROM wordcount", -1,
                            &pSelect, 0);
    if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
      printf("double-check: %lld\n", sqlite3_column_int64(pSelect, 0));
    }
    sqlite3_finalize(pSelect);
  }


  if( showTimer ){
    sqlite3_int64 elapseTime = realTime() - startTime;
    fprintf(stderr, "%3d.%03d wordcount", (int)(elapseTime/1000),
                                   (int)(elapseTime%1000));
    for(i=1; i<argc; i++) if( i!=showTimer ) fprintf(stderr, " %s", argv[i]);
    fprintf(stderr, "\n");
  }

  if( showSummary ){
    sqlite3_create_function(db, "checksum", -1, SQLITE_UTF8, 0,
                            0, checksumStep, checksumFinalize);
    sqlite3_exec(db, 
      "SELECT 'count(*):  ', count(*) FROM wordcount;\n"
................................................................................
      printResult, 0, 0);
  }

  /* Database connection statistics printed after both prepared statements
  ** have been finalized */
  if( showStats ){
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, 0);
    printf("-- Lookaside Slots Used:        %d (max %d)\n", iCur,iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, 0);
    printf("-- Successful lookasides:       %d\n", iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHiwtr,0);
    printf("-- Lookaside size faults:       %d\n", iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHiwtr,0);
    printf("-- Lookaside OOM faults:        %d\n", iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, 0);
    printf("-- Pager Heap Usage:            %d bytes\n", iCur);
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
    printf("-- Page cache hits:             %d\n", iCur);
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
    printf("-- Page cache misses:           %d\n", iCur); 
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
    printf("-- Page cache writes:           %d\n", iCur); 
    sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, 0);
    printf("-- Schema Heap Usage:           %d bytes\n", iCur); 
    sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, 0);
    printf("-- Statement Heap Usage:        %d bytes\n", iCur); 
  }

  sqlite3_close(db);

  /* Global memory usage statistics printed after the database connection
  ** has closed.  Memory usage should be zero at this point. */
  if( showStats ){
    sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, 0);
    printf("-- Memory Used (bytes):         %d (max %d)\n", iCur,iHiwtr);
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, 0);
    printf("-- Outstanding Allocations:     %d (max %d)\n", iCur,iHiwtr);
    sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, 0);
    printf("-- Pcache Overflow Bytes:       %d (max %d)\n", iCur,iHiwtr);
    sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, 0);
    printf("-- Scratch Overflow Bytes:      %d (max %d)\n", iCur,iHiwtr);
    sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, 0);
    printf("-- Largest Allocation:          %d bytes\n",iHiwtr);
    sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, 0);
    printf("-- Largest Pcache Allocation:   %d bytes\n",iHiwtr);
    sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, 0);
    printf("-- Largest Scratch Allocation:  %d bytes\n", iHiwtr);
  }
  return 0;
}







>







 







>
>
>







 







|







 







>







 







>
>
>







 







|



|







|

|
|







 







|

|

|

|

|

|

|

|

|

|








|

|

|

|

|

|

|



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
**     --stats              Show sqlite3_status() results at the end.
**     --pagesize NNN       Use a page size of NNN
**     --cachesize NNN      Use a cache size of NNN
**     --commit NNN         Commit after every NNN operations
**     --nosync             Use PRAGMA synchronous=OFF
**     --journal MMMM       Use PRAGMA journal_mode=MMMM
**     --timer              Time the operation of this program
**     --tag NAME           Tag all output using NAME.  Use only stdout.
**
** Modes:
**
** Insert mode means:
**    (1) INSERT OR IGNORE INTO wordcount VALUES($new,1)
**    (2) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new -- if (1) is a noop
**
................................................................................
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include "sqlite3.h"
#define ISALPHA(X) isalpha((unsigned char)(X))

/* Output tag */
char *zTag = "--";

/* Return the current wall-clock time */
static sqlite3_int64 realTime(void){
  static sqlite3_vfs *clockVfs = 0;
  sqlite3_int64 t;
  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
  if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
    clockVfs->xCurrentTimeInt64(clockVfs, &t);
................................................................................
  printf("%s;\n", zSql);
}

/* An sqlite3_exec() callback that prints results on standard output,
** each column separated by a single space. */
static int printResult(void *NotUsed, int nArg, char **azArg, char **azNm){
  int i;
  printf("%s", zTag);
  for(i=0; i<nArg; i++){
    printf(" %s", azArg[i] ? azArg[i] : "(null)");
  }
  printf("\n");
  return 0;
}

................................................................................
  sqlite3_stmt *pInsert = 0;    /* The INSERT statement */
  sqlite3_stmt *pUpdate = 0;    /* The UPDATE statement */
  sqlite3_stmt *pSelect = 0;    /* The SELECT statement */
  sqlite3_stmt *pDelete = 0;    /* The DELETE statement */
  FILE *in;                     /* The open input file */
  int rc;                       /* Return code from an SQLite interface */
  int iCur, iHiwtr;             /* Statistics values, current and "highwater" */
  FILE *pTimer = stderr;        /* Output channel for the timer */
  sqlite3_int64 sumCnt = 0;     /* Sum in QUERY mode */
  sqlite3_int64 startTime;
  char zInput[2000];            /* A single line of input */

  /* Process command-line arguments */
  for(i=1; i<argc; i++){
    const char *z = argv[i];
................................................................................
        i++;
        pageSize = atoi(argv[i]);
      }else if( strcmp(z,"commit")==0 && i<argc-1 ){
        i++;
        commitInterval = atoi(argv[i]);
      }else if( strcmp(z,"journal")==0 && i<argc-1 ){
        zJMode = argv[++i];
      }else if( strcmp(z,"tag")==0 && i<argc-1 ){
        zTag = argv[++i];
        pTimer = stdout;
      }else{
        fatal_error("unknown option: %s\n", argv[i]);
      }
    }else if( zDbName==0 ){
      zDbName = argv[i];
    }else if( zFileToRead==0 ){
      zFileToRead = argv[i];
................................................................................
  if( zFileToRead ) fclose(in);
  sqlite3_finalize(pInsert);
  sqlite3_finalize(pUpdate);
  sqlite3_finalize(pSelect);
  sqlite3_finalize(pDelete);

  if( iMode==MODE_QUERY ){
    printf("%s sum of cnt: %lld\n", zTag, sumCnt);
    rc = sqlite3_prepare_v2(db,"SELECT sum(cnt*cnt) FROM wordcount", -1,
                            &pSelect, 0);
    if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
      printf("%s double-check: %lld\n", zTag, sqlite3_column_int64(pSelect, 0));
    }
    sqlite3_finalize(pSelect);
  }


  if( showTimer ){
    sqlite3_int64 elapseTime = realTime() - startTime;
    fprintf(pTimer, "%3d.%03d wordcount", (int)(elapseTime/1000),
                                   (int)(elapseTime%1000));
    for(i=1; i<argc; i++) if( i!=showTimer ) fprintf(pTimer, " %s", argv[i]);
    fprintf(pTimer, "\n");
  }

  if( showSummary ){
    sqlite3_create_function(db, "checksum", -1, SQLITE_UTF8, 0,
                            0, checksumStep, checksumFinalize);
    sqlite3_exec(db, 
      "SELECT 'count(*):  ', count(*) FROM wordcount;\n"
................................................................................
      printResult, 0, 0);
  }

  /* Database connection statistics printed after both prepared statements
  ** have been finalized */
  if( showStats ){
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, 0);
    printf("%s Lookaside Slots Used:        %d (max %d)\n", zTag, iCur,iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, 0);
    printf("%s Successful lookasides:       %d\n", zTag, iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHiwtr,0);
    printf("%s Lookaside size faults:       %d\n", zTag, iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHiwtr,0);
    printf("%s Lookaside OOM faults:        %d\n", zTag, iHiwtr);
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, 0);
    printf("%s Pager Heap Usage:            %d bytes\n", zTag, iCur);
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
    printf("%s Page cache hits:             %d\n", zTag, iCur);
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
    printf("%s Page cache misses:           %d\n", zTag, iCur); 
    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
    printf("%s Page cache writes:           %d\n", zTag, iCur); 
    sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, 0);
    printf("%s Schema Heap Usage:           %d bytes\n", zTag, iCur); 
    sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, 0);
    printf("%s Statement Heap Usage:        %d bytes\n", zTag, iCur); 
  }

  sqlite3_close(db);

  /* Global memory usage statistics printed after the database connection
  ** has closed.  Memory usage should be zero at this point. */
  if( showStats ){
    sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, 0);
    printf("%s Memory Used (bytes):         %d (max %d)\n", zTag,iCur,iHiwtr);
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, 0);
    printf("%s Outstanding Allocations:     %d (max %d)\n",zTag,iCur,iHiwtr);
    sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, 0);
    printf("%s Pcache Overflow Bytes:       %d (max %d)\n",zTag,iCur,iHiwtr);
    sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, 0);
    printf("%s Scratch Overflow Bytes:      %d (max %d)\n",zTag,iCur,iHiwtr);
    sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, 0);
    printf("%s Largest Allocation:          %d bytes\n",zTag,iHiwtr);
    sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, 0);
    printf("%s Largest Pcache Allocation:   %d bytes\n",zTag,iHiwtr);
    sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, 0);
    printf("%s Largest Scratch Allocation:  %d bytes\n",zTag,iHiwtr);
  }
  return 0;
}